From ddc06b35565d9f2888e8d946ee7ae292bc902afd Mon Sep 17 00:00:00 2001
From: "Dr. Stephen Henson" <steve@openssl.org>
Date: Fri, 23 Jan 2015 02:45:13 +0000
Subject: [PATCH] Extended master secret extension support.

Add and retrieve extended master secret extension, setting the flag
SSL_SESS_FLAG_EXTMS appropriately.

Note: this just sets the flag and doesn't include the changes to
master secret generation.
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
---
 ssl/ssl_txt.c |  4 ++++
 ssl/t1_lib.c  | 14 ++++++++++++++
 ssl/t1_trce.c |  3 ++-
 ssl/tls1.h    |  6 ++++++
 4 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c
index 76a7cce78..e5774d2c1 100644
--- a/ssl/ssl_txt.c
+++ b/ssl/ssl_txt.c
@@ -244,6 +244,10 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
                    X509_verify_cert_error_string(x->verify_result)) <= 0)
         goto err;
 
+    if (BIO_printf(bp, "    Extended master secret: %s\n",
+                   x->flags & SSL_SESS_FLAG_EXTMS ? "yes" : "no") <= 0)
+        goto err;
+
     return (1);
  err:
     return (0);
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 9be7347b5..22f704791 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1445,6 +1445,8 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
     s2n(TLSEXT_TYPE_encrypt_then_mac, ret);
     s2n(0, ret);
 # endif
+    s2n(TLSEXT_TYPE_extended_master_secret, ret);
+    s2n(0, ret);
 
     /*
      * Add padding to workaround bugs in F5 terminators. See
@@ -1682,6 +1684,10 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
         }
     }
 # endif
+    if (!s->hit && s->session->flags & SSL_SESS_FLAG_EXTMS) {
+        s2n(TLSEXT_TYPE_extended_master_secret, ret);
+        s2n(0, ret);
+    }
 
     if (s->s3->alpn_selected) {
         const unsigned char *selected = s->s3->alpn_selected;
@@ -2300,6 +2306,10 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
         else if (type == TLSEXT_TYPE_encrypt_then_mac)
             s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
 # endif
+        else if (type == TLSEXT_TYPE_extended_master_secret) {
+            if (!s->hit)
+                s->session->flags |= SSL_SESS_FLAG_EXTMS;
+        }
         /*
          * If this ClientHello extension was unhandled and this is a
          * nonresumed connection, check whether the extension is a custom
@@ -2594,6 +2604,10 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p,
                 s->s3->flags |= TLS1_FLAGS_ENCRYPT_THEN_MAC;
         }
 # endif
+        else if (type == TLSEXT_TYPE_extended_master_secret) {
+            if (!s->hit)
+                s->session->flags |= SSL_SESS_FLAG_EXTMS;
+        }
         /*
          * If this extension type was not otherwise handled, but matches a
          * custom_cli_ext_record, then send it to the c callback
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index 26160ed09..4161750b4 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -363,7 +363,8 @@ static ssl_trace_tbl ssl_exts_tbl[] = {
     {TLSEXT_TYPE_session_ticket, "session_ticket"},
     {TLSEXT_TYPE_renegotiate, "renegotiate"},
     {TLSEXT_TYPE_next_proto_neg, "next_proto_neg"},
-    {TLSEXT_TYPE_padding, "padding"}
+    {TLSEXT_TYPE_padding, "padding"},
+    {TLSEXT_TYPE_extended_master_secret, "extended_master_secret"}
 };
 
 static ssl_trace_tbl ssl_curve_tbl[] = {
diff --git a/ssl/tls1.h b/ssl/tls1.h
index 1f756a451..b33c917e3 100644
--- a/ssl/tls1.h
+++ b/ssl/tls1.h
@@ -250,6 +250,12 @@ extern "C" {
  * http://www.ietf.org/id/draft-ietf-tls-encrypt-then-mac-02.txt
  */
 # define TLSEXT_TYPE_encrypt_then_mac    22
+/*
+ * Extended master secret extension.
+ * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
+ * https://tools.ietf.org/id/draft-ietf-tls-session-hash-03.txt
+ */
+# define TLSEXT_TYPE_extended_master_secret      23
 
 /* ExtensionType value from RFC4507 */
 # define TLSEXT_TYPE_session_ticket              35