[openssl-users] Authentication over ECDHE

Christian c.wehrmeyer at freshlions.de
Fri Dec 28 10:22:23 UTC 2018


Thank you for the suggestions thus far. I've been working on a simple 
SSL client/server system in the last couple days. Unfortunately the SSL 
documentation is a right mess, so I don't know what is allowed and what 
is not, which leads to some problems that I don't know exactly how to 
tackle on.

First of all, I opted out for the cipher "ECDHE-PSK-AES128-CBC-SHA256". 
As Matt suggested, using PSKs does reduce a lot of complexity in this 
scenario - if I've been understanding him correctly, this cipher should 
give us forward secrecy while still relying on a pre-shared key, which 
also authenticates both sides to each other. When I run my server, and 
then run my client, it receives the data the server sends without any 
problems.

However, things start to get messy once the keys mismatch, as would in 
any attacker scenario. The client initiates the handshake, but on the 
server side SSL_accept() returns -1, the client receives no data (as 
should). Then I start the client *again*. On the server side 
SSL_accept() returns -1 again, but this time the client blocks in 
SSL_read() (I haven't not implemented timeout handling yet, as this 
still all runs on my testing environments). It's almost as if 
SSL_shutdown on the server side does not notify the client that the 
connection is to be closed.

For the BIO object on the server side I'm using a permanent BIO object 
which I just call BIO_set_fd() upon to set the socket I receive from 
accept(). The call chain looks like this:

===================
First connection, client closes connection as excepted.
===================
BIO_set_fd with 4|1         #Socket 4, BIO_CLOSE
SSL_set_accept_state
SSL_accept
SSL_accept returned with -1
SSL_shutdown
SSL_clear
===================
Second connection, client suddenly blocks, has to be interrupted
with CTRL + C.
===================
BIO_set_fd with 5|1         #Socket 5, BIO_CLOSE
SSL_set_accept_state
SSL_accept
SSL_accept returned with -1
SSL_shutdown
SSL_clear
===================
Third connection, client blocks again, has to be interrupted again.
===================
BIO_set_fd with 4|1
SSL_set_accept_state
SSL_accept
SSL_accept returned with -1
SSL_shutdown
SSL_clear

What am I doing wrong on the server side? I assume it's the server; the 
client process ends right after the connection attempt, and it's the 
server that keeps running. And once I reset the server the first 
connection closes properly again. Am I supposed to use a new BIO object 
for each incoming connection? If so, that's pretty dumb. You usually 
want to have your accept() loop to be free of as much code as possible, 
and setting up everything in advance during server startup. The current 
server code for setting up the SSL object and using it looks like this:

 > if(NULL == (bio = BIO_new_socket(0,BIO_NOCLOSE))) /*Socket doesn't 
really matter, we're gonna reset this soon enough.*/
 > {
 >         goto LABEL_END_NO_BIO;
 > }
 >
 > if(NULL == (ssl = SSL_new(ssl_ctx)))
 > {
 >         BIO_free(bio);
 >         goto LABEL_END_NO_SSL;
 > }
 >
 > SSL_clear(ssl);
 > SSL_set_bio(ssl,bio,bio);
 >
 > tmp = 1;
 > setsockopt
 > (
 >         socket_server,
 >         SOL_SOCKET,
 >         SO_REUSEADDR,
 >         &tmp,
 >         sizeof(tmp)
 > );
 >
 > if(-1 == bind
 > (
 >         socket_server,
 >         (struct sockaddr*)&sin_server,
 >         sizeof(sin_server)
 > ))
 > {
 >         fprintf(stderr,"Can't bind socket.\n");
 >         goto LABEL_END;
 > }
 >
 > if(-1 == listen(socket_server,1))
 >         goto LABEL_END;
 >
 > while(0 <= (socket_client = accept
 > (
 >         socket_server,
 >         (struct sockaddr*)&sin_client,
 >         &sin_client_length
 > )))
 > {
 >         fprintf(stderr,"BIO_set_fd with 
%u|%u\n",socket_client,BIO_CLOSE);
 >         BIO_set_fd(bio,socket_client,BIO_CLOSE);
 >         fprintf(stderr,"SSL_set_accept_state\n");
 >         SSL_set_accept_state(ssl);
 >         fprintf(stderr,"SSL_accept\n");
 >         tmp = SSL_accept(ssl);
 >         if(tmp != 1)
 >         {
 >                 fprintf(stderr,"SSL_accept returned with %i\n",tmp);
 >                 goto LABEL_NEXT_CLIENT;
 >         }
 >
 >         fprintf(stderr,"SSL_write\n");
 >         SSL_write(ssl,"That is my string",sizeof("That is my string") 
- 1);
 >
 > LABEL_NEXT_CLIENT:
 >         fprintf(stderr,"SSL_shutdown\n");
 >         SSL_shutdown(ssl);
 >         fprintf(stderr,"SSL_clear\n");
 >         SSL_clear(ssl);
 > }
 >
 > /*Rest of cleanup, doesn't matter, this is hopefully never reached.*/

Thank you for your continued help.


More information about the openssl-users mailing list