Add extms support to master key generation.
authorDr. Stephen Henson <steve@openssl.org>
Fri, 23 Jan 2015 02:49:16 +0000 (02:49 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 3 Feb 2015 14:50:07 +0000 (14:50 +0000)
Update master secret calculation to support extended master secret.
TLS 1.2 client authentication adds a complication because we need to
cache the handshake messages. This is simpllified however because
the point at which the handshake hashes are calculated for extended
master secret is identical to that required for TLS 1.2 client
authentication (immediately after client key exchange which is also
immediately before certificate verify).
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
ssl/d1_srvr.c
ssl/s3_clnt.c
ssl/s3_srvr.c
ssl/t1_enc.c
ssl/tls1.h

index 1ccdc35e4db01a3273a5ddef5b5c754716297b9d..55d37e78b05775c35b12e3077e353c6acd9a3ada 100644 (file)
@@ -655,17 +655,19 @@ int dtls1_accept(SSL *s)
                 s->init_num = 0;
                 if (!s->session->peer)
                     break;
                 s->init_num = 0;
                 if (!s->session->peer)
                     break;
-                /*
-                 * For sigalgs freeze the handshake buffer at this point and
-                 * digest cached records.
-                 */
                 if (!s->s3->handshake_buffer) {
                     SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR);
                     return -1;
                 }
                 if (!s->s3->handshake_buffer) {
                     SSLerr(SSL_F_DTLS1_ACCEPT, ERR_R_INTERNAL_ERROR);
                     return -1;
                 }
-                s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
-                if (!ssl3_digest_cached_records(s))
-                    return -1;
+                /*
+                 * For sigalgs freeze the handshake buffer. If we support
+                 * extms we've done this already.
+                 */
+                if (!(s->s3->flags & SSL_SESS_FLAG_EXTMS)) {
+                    s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
+                    if (!ssl3_digest_cached_records(s))
+                        return -1;
+                }
             } else {
                 s->state = SSL3_ST_SR_CERT_VRFY_A;
                 s->init_num = 0;
             } else {
                 s->state = SSL3_ST_SR_CERT_VRFY_A;
                 s->init_num = 0;
index a90c9f9a6e482f9012e7c6801605673d85302860..5e2b543e6b8d703ab7ffce91ef90928b01a97b01 100644 (file)
@@ -3150,7 +3150,15 @@ int ssl3_send_client_verify(SSL *s)
             }
             s2n(u, p);
             n = u + 4;
             }
             s2n(u, p);
             n = u + 4;
-            if (!ssl3_digest_cached_records(s))
+            /*
+             * For extended master secret we've already digested cached
+             * records.
+             */
+            if (s->session->flags & SSL_SESS_FLAG_EXTMS) {
+                BIO_free(s->s3->handshake_buffer);
+                s->s3->handshake_buffer = NULL;
+                s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE;
+            } else if (!ssl3_digest_cached_records(s))
                 goto err;
         } else
 #ifndef OPENSSL_NO_RSA
                 goto err;
         } else
 #ifndef OPENSSL_NO_RSA
index e92965879871a06e1ff0e80d6c490f72aec8c7d2..f31b76a96ab9f1e4c19c7b208782af94cbc013e7 100644 (file)
@@ -620,17 +620,19 @@ int ssl3_accept(SSL *s)
                 s->init_num = 0;
                 if (!s->session->peer)
                     break;
                 s->init_num = 0;
                 if (!s->session->peer)
                     break;
-                /*
-                 * For sigalgs freeze the handshake buffer at this point and
-                 * digest cached records.
-                 */
                 if (!s->s3->handshake_buffer) {
                     SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
                     return -1;
                 }
                 if (!s->s3->handshake_buffer) {
                     SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
                     return -1;
                 }
-                s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
-                if (!ssl3_digest_cached_records(s))
-                    return -1;
+                /*
+                 * For sigalgs freeze the handshake buffer. If we support
+                 * extms we've done this already.
+                 */
+                if (!(s->s3->flags & SSL_SESS_FLAG_EXTMS)) {
+                    s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
+                    if (!ssl3_digest_cached_records(s))
+                        return -1;
+                }
             } else {
                 int offset = 0;
                 int dgst_num;
             } else {
                 int offset = 0;
                 int dgst_num;
index 666864e85c72c3c8049e6b140cb70b10174b3b8b..ff6273f1503196e664b7a1dc0c31317214cb7435 100644 (file)
@@ -1070,13 +1070,41 @@ int tls1_generate_master_secret(SSL *s, unsigned char *out, unsigned char *p,
             len);
 #endif                          /* KSSL_DEBUG */
 
             len);
 #endif                          /* KSSL_DEBUG */
 
-
-    tls1_PRF(ssl_get_algorithm2(s),
-             TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE,
-             s->s3->client_random, SSL3_RANDOM_SIZE,
-             co, col,
-             s->s3->server_random, SSL3_RANDOM_SIZE,
-             so, sol, p, len, s->session->master_key, buff, sizeof buff);
+    if (s->session->flags & SSL_SESS_FLAG_EXTMS) {
+        unsigned char hash[EVP_MAX_MD_SIZE * 2];
+        int hashlen;
+        /* If we don't have any digests cache records */
+        if (s->s3->handshake_buffer) {
+            /*
+             * keep record buffer: this wont affect client auth because we're
+             * freezing the buffer at the same point (after client key
+             * exchange and before certificate verify)
+             */
+            s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
+            ssl3_digest_cached_records(s);
+        }
+        hashlen = ssl_handshake_hash(s, hash, sizeof(hash));
+#ifdef SSL_DEBUG
+        fprintf(stderr, "Handshake hashes:\n");
+        BIO_dump_fp(stderr, (char *)hash, hashlen);
+#endif
+        tls1_PRF(ssl_get_algorithm2(s),
+                 TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+                 TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE,
+                 hash, hashlen,
+                 co, col,
+                 NULL, 0,
+                 so, sol, p, len, s->session->master_key, buff, sizeof buff);
+        OPENSSL_cleanse(hash, hashlen);
+    } else {
+        tls1_PRF(ssl_get_algorithm2(s),
+                 TLS_MD_MASTER_SECRET_CONST,
+                 TLS_MD_MASTER_SECRET_CONST_SIZE,
+                 s->s3->client_random, SSL3_RANDOM_SIZE,
+                 co, col,
+                 s->s3->server_random, SSL3_RANDOM_SIZE,
+                 so, sol, p, len, s->session->master_key, buff, sizeof buff);
+    }
 #ifdef SSL_DEBUG
     fprintf(stderr, "Premaster Secret:\n");
     BIO_dump_fp(stderr, (char *)p, len);
 #ifdef SSL_DEBUG
     fprintf(stderr, "Premaster Secret:\n");
     BIO_dump_fp(stderr, (char *)p, len);
@@ -1175,6 +1203,9 @@ int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
     if (memcmp(val, TLS_MD_MASTER_SECRET_CONST,
                TLS_MD_MASTER_SECRET_CONST_SIZE) == 0)
         goto err1;
     if (memcmp(val, TLS_MD_MASTER_SECRET_CONST,
                TLS_MD_MASTER_SECRET_CONST_SIZE) == 0)
         goto err1;
+    if (memcmp(val, TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+               TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE) == 0)
+        goto err1;
     if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
                TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0)
         goto err1;
     if (memcmp(val, TLS_MD_KEY_EXPANSION_CONST,
                TLS_MD_KEY_EXPANSION_CONST_SIZE) == 0)
         goto err1;
index b33c917e33d2d11e0d50e33021532a6712a69cb0..af03f13938ad12e09cd3c891f443a981a8432fb7 100644 (file)
@@ -782,7 +782,7 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 
 # define TLS1_FINISH_MAC_LENGTH          12
 
 
 # define TLS1_FINISH_MAC_LENGTH          12
 
-# define TLS_MD_MAX_CONST_SIZE                   20
+# define TLS_MD_MAX_CONST_SIZE                   22
 # define TLS_MD_CLIENT_FINISH_CONST              "client finished"
 # define TLS_MD_CLIENT_FINISH_CONST_SIZE         15
 # define TLS_MD_SERVER_FINISH_CONST              "server finished"
 # define TLS_MD_CLIENT_FINISH_CONST              "client finished"
 # define TLS_MD_CLIENT_FINISH_CONST_SIZE         15
 # define TLS_MD_SERVER_FINISH_CONST              "server finished"
@@ -797,6 +797,8 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 # define TLS_MD_IV_BLOCK_CONST_SIZE              8
 # define TLS_MD_MASTER_SECRET_CONST              "master secret"
 # define TLS_MD_MASTER_SECRET_CONST_SIZE         13
 # define TLS_MD_IV_BLOCK_CONST_SIZE              8
 # define TLS_MD_MASTER_SECRET_CONST              "master secret"
 # define TLS_MD_MASTER_SECRET_CONST_SIZE         13
+# define TLS_MD_EXTENDED_MASTER_SECRET_CONST     "extended master secret"
+# define TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE        22
 
 # ifdef CHARSET_EBCDIC
 #  undef TLS_MD_CLIENT_FINISH_CONST
 
 # ifdef CHARSET_EBCDIC
 #  undef TLS_MD_CLIENT_FINISH_CONST
@@ -846,6 +848,11 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
  * master secret
  */
 #  define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"
  * master secret
  */
 #  define TLS_MD_MASTER_SECRET_CONST    "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"
+#  undef TLS_MD_EXTENDED_MASTER_SECRET_CONST
+/*
+ * extended master secret
+ */
+#  define TLS_MD_EXTENDED_MASTER_SECRET_CONST    "\x65\x78\x74\x65\x63\x64\x65\x64\x20\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"
 # endif
 
 /* TLS Session Ticket extension struct */
 # endif
 
 /* TLS Session Ticket extension struct */