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!
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).
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.
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.
“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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With