0
votes

generated key

openssl ecparam -param_enc named_curve -name secp521r1 -genkey -outform PEM -out key.pem

generated cert

openssl req -x509 -new -key key.pem -keyform PEM -out ca.pem -outform PEM -days 3650

when i use

openssl s_server -accept 5000 -key key.pem -cert ca.pem -tls1_2 -www

i can connect fine using

openssl s_client -host 10.8.0.26 -port 5000

Client tells me it uses

Protocol : TLSv1.2 Cipher : ECDHE-ECDSA-AES256-GCM-SHA384

exactly what i want

when i compile and use the following c code to start the server

compiled with

g++ Main2.cpp -ldl -lcrypto -lssl -o Main)

#include <iostream>
#include <string>
#include <errno.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <resolv.h>

#include "openssl/ssl.h"
#include "openssl/err.h"

using namespace std;

void Servlet(SSL* ssl) /* Serve the connection -- threadable */
{   char buf[1024];
    char reply[1024];
    int sd, bytes, err;
    const char* HTMLecho="<html><body><pre>%s</pre></body></html>\n\n";

	err = SSL_accept(ssl);

    if ( err <= 0 ) {    /* do SSL-protocol accept */
        printf("%d\n",err);
		ERR_print_errors_fp(stderr);
	}
    else
    {
        bytes = SSL_read(ssl, buf, sizeof(buf)); /* get request */
        if ( bytes > 0 )
        {
            buf[bytes] = 0;
            printf("Client msg: \"%s\"\n", buf);
            sprintf(reply, HTMLecho, buf);   /* construct reply */
            SSL_write(ssl, reply, strlen(reply)); /* send reply */
        }
        else
            ERR_print_errors_fp(stderr);
    }
    sd = SSL_get_fd(ssl);       /* get socket connection */
    SSL_free(ssl);         /* release SSL state */
    close(sd);          /* close connection */
}


int OpenListener(int port)
{   int sd;
    struct sockaddr_in addr;
	

    sd = socket(PF_INET, SOCK_STREAM, 0);
    bzero(&addr, sizeof(addr));

	inet_aton("10.8.0.26", &addr.sin_addr);

    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    //addr.sin_addr.s_addr = INADDR_ANY;
    
	if ( bind(sd, (struct sockaddr*)&addr, sizeof(addr)) != 0 )
    {
        perror("can't bind port");
        abort();
    }
    if ( listen(sd, 10) != 0 )
    {
        perror("Can't configure listening port");
        abort();
    }
    return sd;
}

int main(int argc, const char* argv[]) {

	//SSL_library_init();
	SSL_load_error_strings();
    OpenSSL_add_ssl_algorithms(); 

	cout << SSLeay_version(SSLEAY_VERSION) << endl;

	SSL_CTX *ctx;
	const SSL_METHOD *method;

	method = TLSv1_2_server_method();
	//method = SSLv23_server_method();

	ctx = SSL_CTX_new(method);   /* create new context from method */
    if ( ctx == NULL )
    {
        ERR_print_errors_fp(stderr);
        abort();
    }
	        
	if (SSL_CTX_set_ecdh_auto(ctx, 1) != 1)
		ERR_print_errors_fp(stderr);

	//if (SSL_CTX_set_cipher_list(ctx, "ECDH-ECDSA-AES256-GCM-SHA384") != 1)
		// ERR_print_errors_fp(stderr);

	if (SSL_CTX_load_verify_locations(ctx, "ca.pem", "key.pem") != 1)
        ERR_print_errors_fp(stderr);

	if (SSL_CTX_set_default_verify_paths(ctx) != 1)
        ERR_print_errors_fp(stderr);

	if (SSL_CTX_use_certificate_file(ctx, "ca.pem", SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }

	if (SSL_CTX_use_PrivateKey_file(ctx, "key.pem", SSL_FILETYPE_PEM) <= 0)
    {
        ERR_print_errors_fp(stderr);
        abort();
    }

	if (!SSL_CTX_check_private_key(ctx))
    {
        fprintf(stderr, "Private key does not match the public certificate\n");
        abort();
    }



	int server;

	server = OpenListener(5000);

	struct sockaddr_in addr;
        socklen_t len = sizeof(addr);
        SSL *ssl;

        int client = accept(server, (struct sockaddr*)&addr, &len);  /* accept connection as usual */
        printf("Connection: %s:%d\n",inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
        ssl = SSL_new(ctx);              /* get new SSL state with context */
		if (ssl == NULL) {
		
			ERR_print_errors_fp(stderr);
			return 0;
		
		}

		  SSL_set_fd(ssl, client);      /* set connection socket to SSL state */
        Servlet(ssl);         /* service connection */
  
    close(server);          /* close server socket */
    SSL_CTX_free(ctx);         /* release context */

    return 0;

}

when i now connect using openssl s_client just like above it uses

Protocol : TLSv1.2 Cipher : ECDH-ECDSA-AES256-GCM-SHA384

not ECDHE ! Why ?

When i use chrome/firefox to connect either to the openssl s_server or my server code i get:

140675163166384:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1396:

Why no connection at all ?

1
I am using OpenSSL 1.0.2a 19 Mar 2015 i check this by printing it at the beginning of the code using cout << SSLeay_version(SSLEAY_VERSION) << endl;CutiePie666
Possible duplicate of Server with ECDHE key and cert not working.jww

1 Answers

1
votes

when i now connect using openssl s_client just like above it uses Protocol : TLSv1.2 Cipher : ECDH-ECDSA-AES256-GCM-SHA384

not ECDHE ! Why ?

ECDH and ECDHE are two different Diffie-Hellman's. ECDH uses a fixed server key. ECDHE is ephemeral, and it uses a temporary key. You should be using ECDHE.

For ECDHE, you did not set the ECDHE callback with SSL_CTX_set_tmp_ecdh_callback.

See Server with ECDHE key and cert not working for details.


Related, here are the EC based DH ciphers:

openssl ciphers -v 'ALL:!aNULL' | grep ECDH
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA384
ECDHE-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA384
ECDHE-RSA-AES256-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(256)  Mac=SHA1
ECDHE-ECDSA-AES256-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(256)  Mac=SHA1
ECDH-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
ECDH-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(256) Mac=AEAD
ECDH-RSA-AES256-SHA384  TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AES(256)  Mac=SHA384
ECDH-ECDSA-AES256-SHA384 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AES(256)  Mac=SHA384
ECDH-RSA-AES256-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(256)  Mac=SHA1
ECDH-ECDSA-AES256-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(256)  Mac=SHA1
ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(128) Mac=AEAD
ECDHE-RSA-AES128-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AES(128)  Mac=SHA256
ECDHE-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AES(128)  Mac=SHA256
ECDHE-RSA-AES128-SHA    SSLv3 Kx=ECDH     Au=RSA  Enc=AES(128)  Mac=SHA1
ECDHE-ECDSA-AES128-SHA  SSLv3 Kx=ECDH     Au=ECDSA Enc=AES(128)  Mac=SHA1
ECDH-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
ECDH-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AESGCM(128) Mac=AEAD
ECDH-RSA-AES128-SHA256  TLSv1.2 Kx=ECDH/RSA Au=ECDH Enc=AES(128)  Mac=SHA256
ECDH-ECDSA-AES128-SHA256 TLSv1.2 Kx=ECDH/ECDSA Au=ECDH Enc=AES(128)  Mac=SHA256
ECDH-RSA-AES128-SHA     SSLv3 Kx=ECDH/RSA Au=ECDH Enc=AES(128)  Mac=SHA1
ECDH-ECDSA-AES128-SHA   SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=AES(128)  Mac=SHA1
ECDHE-RSA-RC4-SHA       SSLv3 Kx=ECDH     Au=RSA  Enc=RC4(128)  Mac=SHA1
ECDHE-ECDSA-RC4-SHA     SSLv3 Kx=ECDH     Au=ECDSA Enc=RC4(128)  Mac=SHA1
ECDH-RSA-RC4-SHA        SSLv3 Kx=ECDH/RSA Au=ECDH Enc=RC4(128)  Mac=SHA1
ECDH-ECDSA-RC4-SHA      SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=RC4(128)  Mac=SHA1
ECDHE-RSA-DES-CBC3-SHA  SSLv3 Kx=ECDH     Au=RSA  Enc=3DES(168) Mac=SHA1
ECDHE-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH     Au=ECDSA Enc=3DES(168) Mac=SHA1
ECDH-RSA-DES-CBC3-SHA   SSLv3 Kx=ECDH/RSA Au=ECDH Enc=3DES(168) Mac=SHA1
ECDH-ECDSA-DES-CBC3-SHA SSLv3 Kx=ECDH/ECDSA Au=ECDH Enc=3DES(168) Mac=SHA1

When i use chrome/firefox to connect either to the openssl s_server or my server code i get: 140675163166384:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1396

Why no connection at all ?

You used P-521. It should be supported, but it may be cause trouble. For maximum interoperability, use P-256: ... -param_enc named_curve -name secp256k1.


The elliptic curve gear is available in TLS 1.0 and above. From RFC 4492, Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS):

This document describes additions to TLS to support ECC, applicable both to TLS Version 1.0 [2] and to TLS Version 1.1 [3]...

You should change this:

method = TLSv1_2_server_method();

To:

method = SSLv23_method();
ctx = SSL_CTX_new(method);
...

const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);

That gets you "TLS 1.0 and above", and it removes compression, which leaks information. You should also consider other server side options, like SSL_OP_SAFARI_ECDHE_ECDSA_BUG.

TLS 1.2 in the only protocol version that provides the Authenticated Encryption, like AES/GCM. But you usually handle that detail in the cipher suite list string.


For completeness, you should also use the following cipher list string with SSL_CTX_set_cipher_list:

HIGH:!aNULL:!kRSA:!RC4:!MD5

Also see Obsolete cryptography warning from Browser for details.


Eventually, you are probably going to run into more browser troubles. Browsers have moved against self signed server certificates. To solve that, see How do you sign Certificate Signing Request with your Certification Authority?.

After fixing the self signed certificate, your server certificate will likely have troubles due to the server name in the Common Name (CN). Server names must be listed in the Subject Alternate Name (SAN). To fix that, see How to create a self-signed certificate with openssl?.