Fix stateless session resumption so it can coexist with SNI
authorDr. Stephen Henson <steve@openssl.org>
Fri, 30 Oct 2009 13:28:07 +0000 (13:28 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 30 Oct 2009 13:28:07 +0000 (13:28 +0000)
CHANGES
ssl/s3_srvr.c
ssl/ssl_asn1.c
ssl/t1_lib.c

diff --git a/CHANGES b/CHANGES
index 5016827..8002886 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,14 @@
 
  Changes between 0.9.8k and 0.9.8l  [xx XXX xxxx]
 
+  *) Fixes to stateless session resumption handling. Use initial_ctx when
+     issuing and attempting to decrypt tickets in case it has changed during
+     servername handling. Use a non-zero length session ID when attempting
+     stateless session resumption: this makes it possible to determine if
+     a resumption has occurred immediately after receiving server hello 
+     (several places in OpenSSL subtly assume this) instead of later in
+     the handshake.
+     [Steve Henson]
 
   *) The functions ENGINE_ctrl(), OPENSSL_isservice(),
      CMS_get1_RecipientRequest() and RAND_bytes() can return <=0 on error
index e3d8c78..c698513 100644 (file)
@@ -2716,6 +2716,7 @@ int ssl3_send_newsession_ticket(SSL *s)
                unsigned int hlen;
                EVP_CIPHER_CTX ctx;
                HMAC_CTX hctx;
+               SSL_CTX *tctx = s->initial_ctx;
                unsigned char iv[EVP_MAX_IV_LENGTH];
                unsigned char key_name[16];
 
@@ -2754,9 +2755,9 @@ int ssl3_send_newsession_ticket(SSL *s)
                 * it does all the work otherwise use generated values
                 * from parent ctx.
                 */
-               if (s->ctx->tlsext_ticket_key_cb)
+               if (tctx->tlsext_ticket_key_cb)
                        {
-                       if (s->ctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
+                       if (tctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
                                                         &hctx, 1) < 0)
                                {
                                OPENSSL_free(senc);
@@ -2767,10 +2768,10 @@ int ssl3_send_newsession_ticket(SSL *s)
                        {
                        RAND_pseudo_bytes(iv, 16);
                        EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
-                                       s->ctx->tlsext_tick_aes_key, iv);
-                       HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
+                                       tctx->tlsext_tick_aes_key, iv);
+                       HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
                                        tlsext_tick_md(), NULL);
-                       memcpy(key_name, s->ctx->tlsext_tick_key_name, 16);
+                       memcpy(key_name, tctx->tlsext_tick_key_name, 16);
                        }
                l2n(s->session->tlsext_tick_lifetime_hint, p);
                /* Skip ticket length for now */
index 48b111c..333cee8 100644 (file)
@@ -501,19 +501,26 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
                ret->tlsext_ticklen = os.length;
                os.data = NULL;
                os.length = 0;
-#if 0
                /* There are two ways to detect a resumed ticket sesion.
                 * One is to set a random session ID and then the server
                 * must return a match in ServerHello. This allows the normal
-                * client session ID matching to work.
+                * client session ID matching to work and we know much 
+                * earlier that the ticket has been accepted.
+                * 
+                * The other way is to set zero length session ID when the
+                * ticket is presented and rely on the handshake to determine
+                * session resumption.
                 */ 
                if (ret->session_id_length == 0)
                        {
-                       ret->session_id_length=SSL3_MAX_SSL_SESSION_ID_LENGTH;
-                       RAND_pseudo_bytes(ret->session_id,
-                                               ret->session_id_length);
-                       }
+                       EVP_Digest(ret->tlsext_tick, ret->tlsext_ticklen, 
+                                  ret->session_id, &ret->session_id_length,
+#ifndef OPENSSL_NO_SHA256
+                                       EVP_sha256(), NULL);
+#else
+                                       EVP_sha1(), NULL);
 #endif
+                       }
                }
        else
                ret->tlsext_tick=NULL;
index 2fc5176..c9a81f2 100644 (file)
@@ -811,16 +811,17 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
        unsigned char tick_hmac[EVP_MAX_MD_SIZE];
        HMAC_CTX hctx;
        EVP_CIPHER_CTX ctx;
+       SSL_CTX *tctx = s->initial_ctx;
        /* Need at least keyname + iv + some encrypted data */
        if (eticklen < 48)
                goto tickerr;
        /* Initialize session ticket encryption and HMAC contexts */
        HMAC_CTX_init(&hctx);
        EVP_CIPHER_CTX_init(&ctx);
-       if (s->ctx->tlsext_ticket_key_cb)
+       if (tctx->tlsext_ticket_key_cb)
                {
                unsigned char *nctick = (unsigned char *)etick;
-               int rv = s->ctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
+               int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
                                                        &ctx, &hctx, 0);
                if (rv < 0)
                        return -1;
@@ -832,12 +833,12 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
        else
                {
                /* Check key name matches */
-               if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16))
+               if (memcmp(etick, tctx->tlsext_tick_key_name, 16))
                        goto tickerr;
-               HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
+               HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
                                        tlsext_tick_md(), NULL);
                EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
-                               s->ctx->tlsext_tick_aes_key, etick + 16);
+                               tctx->tlsext_tick_aes_key, etick + 16);
                }
        /* Attempt to process session ticket, first conduct sanity and
         * integrity checks on ticket.