Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"no shared cipher" at ssl_accept, why?

Have googled a lot, not found any answer to the following problem: Created server code and client code, but get

error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher

at the server when doing SSL_connect.

The code below is narrowed down to the sequence of the SSL / socket related function calls only. Error handling code has been applied where applicable to make sure calls before SSL_accept / SSL_connect does not return any failure codes. I have also left out initialization methods.

I do not know if it matters, but I run both server and client on localhost.

There might be obvious errors, but I am quite new with OpenSSL.

Client code (inparams: hostname, certificate_chain_file, ca_certificate_file):

SSL_library_init();             // <<< To clarify my initialization
OpenSSL_add_all_algorithms();   // <<< To clarify my initialization
SSL_load_error_strings();       // <<< To clarify my initialization
ERR_load_crypto_strings();      // <<< To clarify my initialization (2)
OpenSSL_add_all_ciphers();      // <<< To clarify my initialization (2)
SSL_METHOD const * method = SSLv23_method();  // <<< Updated method
SSL_CTX * ctx = SSL_CTX_new(method);
SSL_CTX_use_certificate_chain_file(ctx, certificate_chain_file));
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;    // <<< Added
SSL_CTX_set_options(ctx, flags);   // <<< Added
SSL_CTX_load_verify_locations(ctx, ca_certificate_file, NULL));
struct hostent * host = gethostbyname(hostname);
int client_sd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(6789);
server.sin_addr.s_addr = *(long *) (host->h_addr);
connect(client_sd, (struct sockaddr *) &server, sizeof(server));
SSL * ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_sd);
const char * const preferred_ciphers = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
SSL_set_cipher_list(ssl, preferred_ciphers);   // <<< Added
SSL_set_tlsext_host_name(ssl, hostname);       // <<< Added
mydata_t mydata;
mydata_index_client = SSL_get_ex_new_index(0, (void *) "mydata index", NULL, NULL, NULL);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback_client);
SSL_CTX_set_verify_depth(ctx, 1);
mydata.verify_depth = 0;
SSL_set_ex_data(ssl, mydata_index_client, &mydata);
int connection_result = SSL_connect(ssl);
if (connection_result < 0)
{
  // Comes in here and ERR_get_error indicates
  // error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
}
else if (connection_result == 0)
{
}
else if (connection_result == 1)
{
}
else
{
}

Server code (inparams: certificate_chain_file, ca_certificate_file):

SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
SSL_METHOD const * method = SSLv23_method();
SSL_CTX * ctx = SSL_CTX_new(method);
SSL_CTX_use_certificate_chain_file(ctx, certificate_chain_file);  //Contains only root CA
SSL_CTX_set_default_passwd_cb_userdata(ctx, (void *) private_key_file_password);
SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
SSL_CTX_load_verify_locations(ctx, ca_certificate_file, NULL);
struct sockaddr_in addr;
int server_sd = create_socket(addr, 6789);
bind(server_sd, (struct sockaddr *) &addr, sizeof(addr));
listen(server_sd, max_nr_of_simultaneous_connections);
sockaddr_in client;
client.sin_family = AF_INET;
socklen_t c_len = sizeof(client);
int client_sd = accept(server_sd, (sockaddr *) &client, &c_len);
char remote_addr[INET_ADDRSTRLEN];
inet_ntop(client.sin_family, &(client.sin_addr), remote_addr, INET_ADDRSTRLEN);
SSL * ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_sd);
const char * const preferred_ciphers = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
SSL_set_cipher_list(ssl, preferred_ciphers);   // <<< Added
STACK_OF(X509_NAME) * cert_names = SSL_load_client_CA_file(certificate_chain_file);
if (cert_names != NULL)
{
    SSL_CTX_set_client_CA_list(ctx, cert_names);
}
mydata_t mydata;
mydata_index_server = SSL_get_ex_new_index(0, (void *) "mydata index", NULL, NULL, NULL);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback_server);
SSL_CTX_set_verify_depth(ctx, 1);
mydata.verify_depth = 1;
SSL_set_ex_data(ssl, mydata_index_server, &mydata);
int accept_result = SSL_accept(ssl);
if (accept_result == 0)
{
}
else if (accept_result < 0)
{
  // Comes in here and ERR_get_error indicates
  // error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher
}

EDITED: jww, I have tried the things you suggested below. However, without any progress; I still get the same error output. This is how I have created my certificates:

openssl-ca.cnf

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ ca ]
default_ca  = CA_default        # The default ca section

####################################################################
[ CA_default ]
default_days     = 1000          # how long to certify for
default_crl_days = 30            # how long before next CRL
default_md       = sha256        # use public key default MD
preserve         = no            # keep passed DN ordering

x509_extensions  = ca_extensions     # The extensions to add to the cert

email_in_dn      = no            # Don't concat the email in the DN
copy_extensions  = copy          # Required to copy SANs from CSR to cert

base_dir        = .
certificate     = $base_dir/certs/ca_fromweb.cert.pem  # The CA certifcate
private_key     = $base_dir/private/ca.key.pem   # The CA private key
new_certs_dir   = $base_dir     # Location for new certs after signing
database        = $base_dir/index2.txt   # Database index file
serial          = $base_dir/serial2.txt  # The current serial number

unique_subject  = no            # Set to 'no' to allow creation of
                                # several certificates with same subject.

####################################################################
[ req ]
default_bits        = 4096
default_keyfile     = ./private/ca.key.pem
distinguished_name  = ca_distinguished_name
x509_extensions     = ca_extensions
string_mask         = utf8only

####################################################################
[ ca_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default = SE

stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = Östergötland

localityName            = Locality Name (eg, city)
localityName_default    = 

organizationName          = Organization Name (eg, company)
organizationName_default  = 

organizationalUnitName          = Organizational Unit (eg, division)
organizationalUnitName_default  = 

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default  = 

emailAddress            = Email Address
emailAddress_default    = 

####################################################################
[ ca_extensions ]
subjectKeyIdentifier    = hash
authorityKeyIdentifier  = keyid:always, issuer
basicConstraints        = critical, CA:true
keyUsage                = keyCertSign, cRLSign

####################################################################
[ signing_policy ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

####################################################################
[ signing_req ]
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer

basicConstraints       = CA:FALSE
keyUsage               = digitalSignature, keyEncipherment

openssl-server.cnf

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ req ]
default_bits        = 2048
default_keyfile     = ./intermediate/private/my.example.com.key.pem
distinguished_name  = server_distinguished_name
req_extensions      = server_req_extensions
string_mask         = utf8only

####################################################################
[ server_distinguished_name ]
countryName             = Country Name (2 letter code)
countryName_default     = SE

stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = Östergötland

localityName            = Locality Name (eg, city)
localityName_default    = Linköping

organizationName            = Organization Name (eg, company)
organizationName_default    = 

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default  = 

emailAddress            = Email Address
emailAddress_default    = 

####################################################################
[ server_req_extensions ]
subjectKeyIdentifier    = hash
basicConstraints        = CA:FALSE
keyUsage                = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment               = "OpenSSL Generated Certificate"

####################################################################
[ alternate_names ]
DNS.1       = my.example.com

Commands

 touch index.txt
 echo 1000 > serial
 openssl genrsa -aes256 -out ca.key.pem 4096
 chmod 400 private/ca.key.pem
 openssl req -config openssl-ca.cnf -key ca.key.pem -new -x509 -days 7300 -sha256 -extensions ca_extensions -out ca.cert.pem
 chmod 444 ca.cert.pem

 openssl genrsa -aes256 -out server.key.pem 4096
 openssl req -config openssl-server.cnf -new -sha256 -key server.key.pem -out my.example.com.csr.pem
 openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out my.example.com.cert.pem -infiles my.example.com.csr.pem
 chmod 444 my.example.com.cert.pem
 cat ca.cert.pem > ca_chain.cert.pem

EDIT 2: Also tried with

 ERR_load_crypto_strings();      // <<< To clarify my initialization (2)
 OpenSSL_add_all_ciphers();      // <<< To clarify my initialization (2)

See top. Same result.

"Unfortunately, all the initialization function return a useless values (for example, always 1) or are void functions. There is no way to determine if a failure occurred. " - (https://wiki.openssl.org/index.php/Library_Initialization) that sucks!

like image 733
Joachim Avatar asked Nov 06 '16 20:11

Joachim


People also ask

How does SSL ciphers work?

An SSL cipher, or an SSL cipher suite, is a set of algorithms or a set of instructions/steps that helps to establish a secure connection between two entities — usually the client (a user's browser) and the web server they're connecting to (your website).

How does server choose cipher suite?

The server chooses the cipher to use based on the preference order and what the client supports. This is illustrated in the image below. The language represents the cipher suite. The order/preference specifies the encryption strength.

What cipher is used in SSL?

To facilitate this authentication process, cipher suites employ an authentication algorithm such as RSA, DSA and ECDSA. To ensure the secure transfer of data, cipher suites come with a bulk data encryption algorithm. AES, 3DES and CAMELLA are some of the most common algorithms in this category.


1 Answers

“no shared cipher” at ssl_accept, why?

There could be several reasons for it. Below are some suggestions depending on the problem you are having. I suspect one or more is the answer to your problems.


Client:

SSL_METHOD const * method = SSLv3_client_method();

And:

Server:

SSL_METHOD const * method = SSLv23_method();

You should start by setting "TLS 1.0 and above". You would do that on the client and server with the following. Its from the OpenSSL wiki and SLL/TLS Client example.

const SSL_METHOD* method = SSLv23_method();
if(method == NULL) handleFailure();

ctx = SSL_CTX_new(method);
if(ctx == NULL) handleFailure();

...

/* Cannot fail ??? */
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);

Your client should also use Server Name Indication (SNI). The client utilizes it with SSL_set_tlsext_host_name. SNI is a TLS extension, and its part of the reason you want "TLS 1.0 and above".

Both the client and the server want to use a cipher suite list like "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4". Set them with either SSL_CTX_set_cipher_list or SSL_set_cipher_list. It avoids the “Your connection to website is encrypted with obsolete cryptography” warnings from the browser.

If you are using Elliptic Curve based certificates, then you need to use a named curve. Also see boost asio with ECDSA certificate issue on Stack Overflow and Elliptic Curve Cryptography | Named Curves on the OpenSSL wiki.

Be sure you initialize the OpenSSL library. If the library is not initialized properly, then there will be no ciphers available, and it can result in "no shared ciphers". Also see Openssl SSL_CTX_new(SSLv3_method()) returns NULL on Stack Overflow and Library Initialization on the OpenSSL wiki.

If you are creating your own certificate, then be sure you put hostnames in the in the Subject Alternate Name (SAN). Hostnames always go in the SAN. If its present in the CN, then it must be present in the SAN too (you have to list it twice in this case). For more rules and reasons, see How do you sign Certificate Signing Request with your Certification Authority and How to create a self-signed certificate with openssl?

like image 113
jww Avatar answered Jan 04 '23 04:01

jww