Update from stable branch.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 30 Apr 2008 16:14:02 +0000 (16:14 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 30 Apr 2008 16:14:02 +0000 (16:14 +0000)
CHANGES
ssl/s3_lib.c
ssl/s3_srvr.c
ssl/ssl.h
ssl/t1_lib.c
ssl/tls1.h

diff --git a/CHANGES b/CHANGES
index ff51f47..cf5c17c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
      [NTT]
 
  Changes between 0.9.8g and 0.9.8h  [xx XXX xxxx]
+  
+  *) Add TLS session ticket callback. This allows an application to set
+     TLS ticket cipher and HMAC keys rather than relying on hardcoded fixed
+     values. This is useful for key rollover for example where several key
+     sets may exist with different names.
+     [Steve Henson]
 
   *) Reverse ENGINE-internal logic for caching default ENGINE handles.
      This was broken until now in 0.9.8 releases, such that the only way
index 00bc1b3..6844a43 100644 (file)
@@ -2770,6 +2770,13 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
                ctx->tlsext_status_cb=(int (*)(SSL *,void *))fp;
                break;
 
+       case SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB:
+               ctx->tlsext_ticket_key_cb=(int (*)(SSL *,unsigned char  *,
+                                               unsigned char *,
+                                               EVP_CIPHER_CTX *,
+                                               HMAC_CTX *, int))fp;
+               break;
+
 #endif
        default:
                return(0);
index dee1f73..8a4faa6 100644 (file)
@@ -2853,6 +2853,8 @@ int ssl3_send_newsession_ticket(SSL *s)
                unsigned int hlen;
                EVP_CIPHER_CTX ctx;
                HMAC_CTX hctx;
+               unsigned char iv[EVP_MAX_IV_LENGTH];
+               unsigned char key_name[16];
 
                /* get session encoding length */
                slen = i2d_SSL_SESSION(s->session, NULL);
@@ -2883,29 +2885,47 @@ int ssl3_send_newsession_ticket(SSL *s)
                *(p++)=SSL3_MT_NEWSESSION_TICKET;
                /* Skip message length for now */
                p += 3;
+               EVP_CIPHER_CTX_init(&ctx);
+               HMAC_CTX_init(&hctx);
+               /* Initialize HMAC and cipher contexts. If callback present
+                * it does all the work otherwise use generated values
+                * from parent ctx.
+                */
+               if (s->ctx->tlsext_ticket_key_cb)
+                       {
+                       if (s->ctx->tlsext_ticket_key_cb(s, key_name, iv, &ctx,
+                                                        &hctx, 1) < 0)
+                               {
+                               OPENSSL_free(senc);
+                               return -1;
+                               }
+                       }
+               else
+                       {
+                       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,
+                                       tlsext_tick_md(), NULL);
+                       memcpy(key_name, s->ctx->tlsext_tick_key_name, 16);
+                       }
                l2n(s->session->tlsext_tick_lifetime_hint, p);
                /* Skip ticket length for now */
                p += 2;
                /* Output key name */
                macstart = p;
-               memcpy(p, s->ctx->tlsext_tick_key_name, 16);
+               memcpy(p, key_name, 16);
                p += 16;
-               /* Generate and output IV */
-               RAND_pseudo_bytes(p, 16);
-               EVP_CIPHER_CTX_init(&ctx);
+               /* output IV */
+               memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
+               p += EVP_CIPHER_CTX_iv_length(&ctx);
                /* Encrypt session data */
-               EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
-                                       s->ctx->tlsext_tick_aes_key, p);
-               p += 16;
                EVP_EncryptUpdate(&ctx, p, &len, senc, slen);
                p += len;
                EVP_EncryptFinal(&ctx, p, &len);
                p += len;
                EVP_CIPHER_CTX_cleanup(&ctx);
 
-               HMAC_CTX_init(&hctx);
-               HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
-                               tlsext_tick_md(), NULL);
                HMAC_Update(&hctx, macstart, p - macstart);
                HMAC_Final(&hctx, p, &hlen);
                HMAC_CTX_cleanup(&hctx);
index 77a6d6a..53236ee 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
 #include <openssl/buffer.h>
 #endif
 #include <openssl/pem.h>
+#include <openssl/hmac.h>
 
 #include <openssl/kssl.h>
 #include <openssl/safestack.h>
@@ -807,6 +808,11 @@ struct ssl_ctx_st
        unsigned char tlsext_tick_key_name[16];
        unsigned char tlsext_tick_hmac_key[16];
        unsigned char tlsext_tick_aes_key[16];
+       /* Callback to support customisation of ticket key setting */
+       int (*tlsext_ticket_key_cb)(SSL *ssl,
+                                       unsigned char *name, unsigned char *iv,
+                                       EVP_CIPHER_CTX *ectx,
+                                       HMAC_CTX *hctx, int enc);
 
        /* certificate status request info */
        /* Callback for status request */
@@ -1351,6 +1357,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS     69
 #define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP       70
 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP       71
+
+#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB      72
 #endif
 
 #define SSL_session_reused(ssl) \
index 39629c2..f3c5a16 100644 (file)
@@ -1442,39 +1442,53 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
        SSL_SESSION *sess;
        unsigned char *sdec;
        const unsigned char *p;
-       int slen, mlen;
+       int slen, mlen, renew_ticket = 0;
        unsigned char tick_hmac[EVP_MAX_MD_SIZE];
        HMAC_CTX hctx;
        EVP_CIPHER_CTX 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)
+               {
+               unsigned char *nctick = (unsigned char *)etick;
+               int rv = s->ctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
+                                                       &ctx, &hctx, 0);
+               if (rv < 0)
+                       return -1;
+               if (rv == 0)
+                       goto tickerr;
+               if (rv == 2)
+                       renew_ticket = 1;
+               }
+       else
+               {
+               /* Check key name matches */
+               if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16))
+                       goto tickerr;
+               HMAC_Init_ex(&hctx, s->ctx->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);
+               }
        /* Attempt to process session ticket, first conduct sanity and
         * integrity checks on ticket.
         */
-       mlen = EVP_MD_size(tlsext_tick_md());
+       mlen = HMAC_size(&hctx);
        eticklen -= mlen;
-       /* Need at least keyname + iv + some encrypted data */
-       if (eticklen < 48)
-               goto tickerr;
-       /* Check key name matches */
-       if (memcmp(etick, s->ctx->tlsext_tick_key_name, 16))
-               goto tickerr;
        /* Check HMAC of encrypted ticket */
-       HMAC_CTX_init(&hctx);
-       HMAC_Init_ex(&hctx, s->ctx->tlsext_tick_hmac_key, 16,
-                               tlsext_tick_md(), NULL);
        HMAC_Update(&hctx, etick, eticklen);
        HMAC_Final(&hctx, tick_hmac, NULL);
        HMAC_CTX_cleanup(&hctx);
        if (memcmp(tick_hmac, etick + eticklen, mlen))
                goto tickerr;
-       /* Set p to start of IV */
-       p = etick + 16;
-       EVP_CIPHER_CTX_init(&ctx);
        /* Attempt to decrypt session data */
-       EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
-                                       s->ctx->tlsext_tick_aes_key, p);
        /* Move p after IV to start of encrypted ticket, update length */
-       p += 16;
-       eticklen -= 32;
+       p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
+       eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx);
        sdec = OPENSSL_malloc(eticklen);
        if (!sdec)
                {
@@ -1501,7 +1515,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
                        memcpy(sess->session_id, sess_id, sesslen);
                sess->session_id_length = sesslen;
                *psess = sess;
-               s->tlsext_ticket_expected = 0;
+               s->tlsext_ticket_expected = renew_ticket;
                return 1;
                }
        /* If session decrypt failure indicate a cache miss and set state to
index d831eec..22399b9 100644 (file)
@@ -279,6 +279,9 @@ SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB, (void (*)(voi
 #define SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg) \
 SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG, 0, arg)
 
+#define SSL_CTX_set_tlsext_ticket_key_cb(ssl, cb) \
+SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
+
 #endif
 
 /* PSK ciphersuites from 4279 */