Hi,

I recently tried to refactor the TLS related code of my server
application and wanted to use a SSL-BIO instead of performing all
SSL-read/-write-operations by hand. As cipher suite I use
ADH-AES256-SHA, because no authentication of the peers is needed and a
man-in-the-middle-attack is highly unlikely in my setup. My problem is
know that with the new code the handshake fails most of the time (but
works on like every 10th retry). For establishing a new TLS-connection
my code looked like this:

   SSL *ssl_handle = NULL;
   bool retry_accept = true;
   bool ssl_want_read = false;
   bool ssl_want_write = false;
   bool can_read = false;
   bool can_write = false;
   int ssl_return = 0;   
   tls_handle_t *tls_handle = NULL;

   if (!global_ssl_context) {
       print_SSL_error("TLS accept: SSL context not initialized. SSL
accept failed.");
       return TLS_EINIT;
   }

   if (!h->sfd) {
       print_SSL_error("TLS accept: Bad socket file descriptor.");
       return TLS_EINVAL;
   }

   if (!(socket_bio = BIO_new_socket((int) h->sfd, BIO_NOCLOSE))) {
       print_SSL_error("TLS accept: Failed to create socket-BIO object.");
       return TLS_EGENER;
   }

   ssl_handle = SSL_new(global_ssl_context);
   SSL_set_bio(ssl_handle, socket_bio, socket_bio);

   tls_handle = calloc(1, sizeof(tls_handle_t));
   tls_handle->con_handle = ssl_handle;

   do {
       if (ssl_want_read) {
           rttTmsTLSSelect(tls_handle, &can_read, NULL, true);
           ssl_want_read = false;
       }
       else if (ssl_want_write) {
           rttTmsTLSSelect(tls_handle, NULL, &can_write, true);
           ssl_want_write = false;
       }

       ssl_return = SSL_accept(tls_handle->con_handle);
       switch (SSL_get_error(tls_handle->con_handle, ssl_return)) {
       case SSL_ERROR_WANT_READ:
           ssl_want_read = true;
           break;
       case SSL_ERROR_WANT_WRITE:
           ssl_want_write = true;
           break;
       default:
           retry_accept = false;
       }
   } while (ssl_return <= 0 && retry_accept);

This worked reliably. My new code looks like this:

   BIO *socket_bio = NULL;
   BIO *ssl_bio = NULL;
   BIO *buffer_bio = NULL;
   tls_handle_t *tls_handle = NULL;

   if (!global_ssl_context) {
       print_SSL_error("TLS accept: SSL context not initialized. SSL
accept failed.");
       return TLS_EINIT;
   }

   if (!h->sfd) {
       print_SSL_error("TLS accept: Bad socket file descriptor.");
       return TLS_EINVAL;
   }

   if (!(socket_bio = BIO_new_socket((int) h->sfd, BIO_NOCLOSE))) {
       print_SSL_error("TLS accept: Failed to create socket-BIO object.");
       return TLS_EGENER;
   }
   /*

   if (!(ssl_bio = BIO_new_ssl(global_ssl_context, 0))) {
       print_SSL_error("TLS_accept: Failed to create SSL-BIO object");
       BIO_free_all(socket_bio);
       return TLS_EGENER;
   }

   // Append the socket-BIO to the SSL-BIO
   ssl_bio = BIO_push(ssl_bio, socket_bio);

   if (!(buffer_bio = BIO_new(BIO_f_buffer()))) {
       print_SSL_error("TLS_accept: Failed to create buffer-BIO object");
       BIO_free_all(ssl_bio);
       return TLS_EGENER;
   }

   // Prepend the buffer-BIO to the SSL-BIO
   ssl_bio = BIO_push(buffer_bio, ssl_bio);

   if (BIO_do_handshake(ssl_bio) <= 0) {
       print_SSL_error("TLS accept: Handshake failed");
       return TLS_EGENER;
   }

   tls_handle = calloc(1, sizeof(tls_handle_t));
   tls_handle->ssl_bio = ssl_bio;
   BIO_get_ssl(tls_handle->ssl_bio, &(tls_handle->con_handle));

My global SSL-context object is initialized like

   if (!(tls_context = SSL_CTX_new(TLSv1_method()))) {
       print_SSL_error("TLS error while creating context object.");
       return TLS_EINIT;
   }

   SSL_CTX_set_mode(tls_context, SSL_MODE_AUTO_RETRY);

   if (!SSL_CTX_set_cipher_list(tls_context, "ADH-AES256-SHA")) {
       print_SSL_error("TLS error while setting cipher list");
       return TLS_EGENER;
   }

   global_use_ssl = true;
   global_ssl_context = tls_context;

The s_client test-application delivers the following output:

> openssl s_client -cipher "ADH-AES256-SHA" -connect localhost:9111
-state -msg -tls1
CONNECTED(00000003)
SSL_connect:before/connect initialization
>>> TLS 1.0 Handshake [length 0036], ClientHello
   01 00 00 32 03 01 4d 91 11 d5 4b 61 48 50 5b 27
   b8 a2 3b d0 ea d9 53 3d 28 78 70 d7 fa 28 0e 96
   d7 3a 5c eb 99 dc 00 00 04 00 3a 00 ff 02 01 00
   00 04 00 23 00 00
SSL_connect:SSLv3 write client hello A
<<< TLS 1.0 Handshake [length 0035], ServerHello
   02 00 00 31 03 01 4d 91 11 d5 5e 5f c9 5c 08 05
   27 44 8c 47 3d 44 36 fe cc a7 12 de e9 c2 e5 c3
   31 91 61 bc 07 9a 00 00 3a 01 00 09 ff 01 00 01
   00 00 23 00 00
SSL_connect:SSLv3 read server hello A
<<< TLS 1.0 Handshake [length 002b], ServerKeyExchange
   0c 00 00 27 00 10 f3 0a 17 a4 aa 28 63 71 4d 57
   2b 0e 66 c3 99 23 00 01 05 00 10 46 e1 f7 72 24
   39 22 11 1c f1 48 7c 04 f0 70 7d
SSL_connect:SSLv3 read server key exchange A
<<< TLS 1.0 Handshake [length 0004], ServerHelloDone
   0e 00 00 00
SSL_connect:SSLv3 read server done A
>>> TLS 1.0 Handshake [length 0016], ClientKeyExchange
   10 00 00 12 00 10 b2 e7 1c e0 8c f9 49 67 2a eb
   1a f2 ce de e0 9c
SSL_connect:SSLv3 write client key exchange A
>>> TLS 1.0 ChangeCipherSpec [length 0001]
   01
SSL_connect:SSLv3 write change cipher spec A
>>> TLS 1.0 Handshake [length 0010], Finished
   14 00 00 0c d2 53 c4 44 4a 1d 11 9c ee d4 f1 6a
SSL_connect:SSLv3 write finished A
SSL_connect:SSLv3 flush data
SSL_connect:failed in SSLv3 read server session ticket A
3074487944:error:1409E0E5:SSL routines:SSL3_WRITE_BYTES:ssl handshake
failure:s3_pkt.c:590:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 115 bytes and written 86 bytes
---
New, TLSv1/SSLv3, Cipher is ADH-AES256-SHA
Secure Renegotiation IS supported
Compression: zlib compression
Expansion: NONE
SSL-Session:
   Protocol  : TLSv1
   Cipher    : ADH-AES256-SHA
   Session-ID:
   Session-ID-ctx:
   Master-Key:
A56F57324F1757E4FA5368610DA95D302BFFF94BE392850E8895D477D3C5E63C7AA947F6C613F599C4DDAC7390512A88
   Key-Arg   : None
   PSK identity: None
   PSK identity hint: None
   Compression: 1 (zlib compression)
   Start Time: 1301352917
   Timeout   : 7200 (sec)
   Verify return code: 0 (ok)

One observation that I made is that with a correct handshake the number
of sent/received data is

SSL handshake has read 349 bytes and written 145 bytes

whereas in the above output the transmitted data is much less.

Does anyone have a suggestion how to fix the code using the SSL-BIO
approach? Any hints would be appreciated.

Regards,
Martin
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to