[openssl-commits] [openssl] master update

Dr. Stephen Henson steve at openssl.org
Tue Dec 8 16:35:57 UTC 2015


The branch master has been updated
       via  42a8b3f90aef8eb2e9d5c7f9c7cb7f8ae1a3ace2 (commit)
       via  b3fce9c91eeee661be6a89803778e18ac76d05a4 (commit)
       via  040c8783509b85a707d25dd3086cc1984b7fef60 (commit)
       via  41609361433d34f609ca841eb1bbaaf0feba1946 (commit)
       via  e7f0d9210c4a421e6306cd9a0c486c3e96be4d25 (commit)
      from  686cf15e9dfd3263ec05019f4b2b52253cdcf38e (commit)


- Log -----------------------------------------------------------------
commit 42a8b3f90aef8eb2e9d5c7f9c7cb7f8ae1a3ace2
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Mon Dec 7 16:09:13 2015 +0000

    Extended master secret test script.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit b3fce9c91eeee661be6a89803778e18ac76d05a4
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sun Dec 6 17:49:14 2015 +0000

    Add extms extension
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 040c8783509b85a707d25dd3086cc1984b7fef60
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Tue Dec 8 02:07:43 2015 +0000

    TLSProxy update
    
    Add function to delete extensions and fix ClientHello repacking.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 41609361433d34f609ca841eb1bbaaf0feba1946
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Sat Dec 5 18:58:49 2015 +0000

    update errors
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit e7f0d9210c4a421e6306cd9a0c486c3e96be4d25
Author: Dr. Stephen Henson <steve at openssl.org>
Date:   Fri Dec 4 19:48:15 2015 +0000

    Extended master secret fixes and checks.
    
    Add new flag TLS1_FLAGS_RECEIVED_EXTMS which is set when the peer sends
    the extended master secret extension.
    
    Server now sends extms if and only if the client sent extms.
    
    Check consistency of extms extension when resuming sessions following (where
    practical) RFC7627.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 include/openssl/ssl.h           |   1 +
 include/openssl/ssl3.h          |   2 +
 ssl/ssl_err.c                   |   1 +
 ssl/ssl_locl.h                  |   5 +-
 ssl/ssl_sess.c                  |  22 +++-
 ssl/t1_lib.c                    |  68 +++++++---
 test/recipes/70-test_tlsextms.t | 273 ++++++++++++++++++++++++++++++++++++++++
 util/TLSProxy/ClientHello.pm    |  22 +++-
 util/TLSProxy/ServerHello.pm    |   5 +
 9 files changed, 373 insertions(+), 26 deletions(-)
 create mode 100644 test/recipes/70-test_tlsextms.t

diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 1fb5948..bc58b0b 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -2247,6 +2247,7 @@ void ERR_load_SSL_strings(void);
 # define SSL_R_ILLEGAL_SUITEB_DIGEST                      380
 # define SSL_R_INAPPROPRIATE_FALLBACK                     373
 # define SSL_R_INCONSISTENT_COMPRESSION                   340
+# define SSL_R_INCONSISTENT_EXTMS                         104
 # define SSL_R_INVALID_COMMAND                            280
 # define SSL_R_INVALID_COMPRESSION_ALGORITHM              341
 # define SSL_R_INVALID_NULL_CMD_NAME                      385
diff --git a/include/openssl/ssl3.h b/include/openssl/ssl3.h
index ef93c08..2a2974c 100644
--- a/include/openssl/ssl3.h
+++ b/include/openssl/ssl3.h
@@ -369,6 +369,8 @@ extern "C" {
 /* Set if we encrypt then mac instead of usual mac then encrypt */
 # define TLS1_FLAGS_ENCRYPT_THEN_MAC             0x0100
 
+/* Set if extended master secret extension received from peer */
+# define TLS1_FLAGS_RECEIVED_EXTMS               0x0200
 
 # define SSL3_MT_HELLO_REQUEST                   0
 # define SSL3_MT_CLIENT_HELLO                    1
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index b594028..0623104 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -533,6 +533,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
     {ERR_REASON(SSL_R_ILLEGAL_SUITEB_DIGEST), "illegal Suite B digest"},
     {ERR_REASON(SSL_R_INAPPROPRIATE_FALLBACK), "inappropriate fallback"},
     {ERR_REASON(SSL_R_INCONSISTENT_COMPRESSION), "inconsistent compression"},
+    {ERR_REASON(SSL_R_INCONSISTENT_EXTMS), "inconsistent extms"},
     {ERR_REASON(SSL_R_INVALID_COMMAND), "invalid command"},
     {ERR_REASON(SSL_R_INVALID_COMPRESSION_ALGORITHM),
      "invalid compression algorithm"},
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 34091d3..1e1b265 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -2021,8 +2021,9 @@ __owur int tls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length)
 __owur int dtls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length);
 #  endif
 
-__owur int tls1_process_ticket(SSL *s, const PACKET *ext,
-                               const PACKET *session_id, SSL_SESSION **ret);
+__owur int tls_check_serverhello_tlsext_early(SSL *s, const PACKET *ext,
+                                              const PACKET *session_id,
+                                              SSL_SESSION **ret);
 
 __owur int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
                          const EVP_MD *md);
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 5265b15..aff615e 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -497,6 +497,10 @@ int ssl_get_new_session(SSL *s, int session)
     ss->ssl_version = s->version;
     ss->verify_result = X509_V_OK;
 
+    /* If client supports extended master secret set it in session */
+    if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)
+        ss->flags |= SSL_SESS_FLAG_EXTMS;
+
     return (1);
 }
 
@@ -533,8 +537,8 @@ int ssl_get_prev_session(SSL *s, const PACKET *ext, const PACKET *session_id)
     if (len == 0)
         try_session_cache = 0;
 
-    /* sets s->tlsext_ticket_expected */
-    r = tls1_process_ticket(s, ext, session_id, &ret);
+    /* sets s->tlsext_ticket_expected and extended master secret flag */
+    r = tls_check_serverhello_tlsext_early(s, ext, session_id, &ret);
     switch (r) {
     case -1:                   /* Error during processing */
         fatal = 1;
@@ -670,6 +674,20 @@ int ssl_get_prev_session(SSL *s, const PACKET *ext, const PACKET *session_id)
         goto err;
     }
 
+    /* Check extended master secret extension consistency */
+    if (ret->flags & SSL_SESS_FLAG_EXTMS) {
+        /* If old session includes extms, but new does not: abort handshake */
+        if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS)) {
+            SSLerr(SSL_F_SSL_GET_PREV_SESSION, SSL_R_INCONSISTENT_EXTMS);
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+            fatal = 1;
+            goto err;
+        }
+    } else if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
+        /* If new session includes extms, but old does not: do not resume */
+        goto err;
+    }
+
     s->session_ctx->stats.sess_hit++;
 
     SSL_SESSION_free(s->session);
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index a6f2502..83015e8 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1699,7 +1699,7 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
         }
     }
 #endif
-    if (!s->hit && s->session->flags & SSL_SESS_FLAG_EXTMS) {
+    if (s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) {
         s2n(TLSEXT_TYPE_extended_master_secret, ret);
         s2n(0, ret);
     }
@@ -2269,10 +2269,11 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
         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;
-        }
+        /*
+         * Note: extended master secret extension handled in
+         * tls_check_serverhello_tlsext_early()
+         */
+
         /*
          * If this ClientHello extension was unhandled and this is a
          * nonresumed connection, check whether the extension is a custom
@@ -2366,6 +2367,8 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
     s->s3->flags &= ~TLS1_FLAGS_ENCRYPT_THEN_MAC;
 #endif
 
+    s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
+
     if (!PACKET_get_net_2(pkt, &length))
         goto ri_check;
 
@@ -2554,6 +2557,7 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
         }
 #endif
         else if (type == TLSEXT_TYPE_extended_master_secret) {
+            s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
             if (!s->hit)
                 s->session->flags |= SSL_SESS_FLAG_EXTMS;
         }
@@ -2603,6 +2607,19 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
         return 0;
     }
 
+    if (s->hit) {
+        /*
+         * Check extended master secret extension is consistent with
+         * original session.
+         */
+        if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
+            !(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
+            *al = SSL_AD_HANDSHAKE_FAILURE;
+            SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, SSL_R_INCONSISTENT_EXTMS);
+            return 0;
+            }
+    }
+
     return 1;
 }
 
@@ -2892,8 +2909,11 @@ int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt)
 
 /*-
  * Since the server cache lookup is done early on in the processing of the
- * ClientHello, and other operations depend on the result, we need to handle
- * any TLS session ticket extension at the same time.
+ * ClientHello and other operations depend on the result some extensions
+ * need to be handled at the same time.
+ *
+ * Two extensions are currently handled, session ticket and extended master
+ * secret.
  *
  *   session_id: ClientHello session ID.
  *   ext: ClientHello extensions (including length prefix)
@@ -2920,23 +2940,29 @@ int ssl_parse_serverhello_tlsext(SSL *s, PACKET *pkt)
  *   a session ticket or we couldn't use the one it gave us, or if
  *   s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket.
  *   Otherwise, s->tlsext_ticket_expected is set to 0.
+ *
+ *   For extended master secret flag is set if the extension is present.
+ *
  */
-int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
-                        SSL_SESSION **ret)
+int tls_check_serverhello_tlsext_early(SSL *s, const PACKET *ext,
+                                       const PACKET *session_id,
+                                       SSL_SESSION **ret)
 {
     unsigned int i;
     PACKET local_ext = *ext;
     int retv = -1;
 
+    int have_ticket = 0;
+    int use_ticket = tls_use_ticket(s);
+
     *ret = NULL;
     s->tlsext_ticket_expected = 0;
+    s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
 
     /*
      * If tickets disabled behave as if no ticket present to permit stateful
      * resumption.
      */
-    if (!tls_use_ticket(s))
-        return 0;
     if ((s->version <= SSL3_VERSION))
         return 0;
 
@@ -2957,10 +2983,17 @@ int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
             retv = 0;
             goto end;
         }
-        if (type == TLSEXT_TYPE_session_ticket) {
+        if (type == TLSEXT_TYPE_session_ticket && use_ticket) {
             int r;
             unsigned char *etick;
 
+            /* Duplicate extension */
+            if (have_ticket != 0) {
+                retv = -1;
+                goto end;
+            }
+            have_ticket = 1;
+
             if (size == 0) {
                 /*
                  * The client will accept a ticket but doesn't currently have
@@ -2968,7 +3001,7 @@ int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
                  */
                 s->tlsext_ticket_expected = 1;
                 retv = 1;
-                goto end;
+                continue;
             }
             if (s->tls_session_secret_cb) {
                 /*
@@ -2978,7 +3011,7 @@ int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
                  * calculate the master secret later.
                  */
                 retv = 2;
-                goto end;
+                continue;
             }
             if (!PACKET_get_bytes(&local_ext, &etick, size)) {
                 /* Shouldn't ever happen */
@@ -3003,15 +3036,18 @@ int tls1_process_ticket(SSL *s, const PACKET *ext, const PACKET *session_id,
                 retv = -1;
                 break;
             }
-            goto end;
+            continue;
         } else {
+            if (type == TLSEXT_TYPE_extended_master_secret)
+                s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
             if (!PACKET_forward(&local_ext, size)) {
                 retv = -1;
                 goto end;
             }
         }
     }
-    retv = 0;
+    if (have_ticket == 0)
+        retv = 0;
 end:
     return retv;
 }
diff --git a/test/recipes/70-test_tlsextms.t b/test/recipes/70-test_tlsextms.t
new file mode 100644
index 0000000..cdda7f8
--- /dev/null
+++ b/test/recipes/70-test_tlsextms.t
@@ -0,0 +1,273 @@
+#!/usr/bin/perl
+# Written by Stephen Henson for the OpenSSL project.
+# ====================================================================
+# Copyright (c) 1998-2015 The OpenSSL Project.  All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#
+# 3. All advertising materials mentioning features or use of this
+#    software must display the following acknowledgment:
+#    "This product includes software developed by the OpenSSL Project
+#    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+#
+# 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+#    endorse or promote products derived from this software without
+#    prior written permission. For written permission, please contact
+#    openssl-core at openssl.org.
+#
+# 5. Products derived from this software may not be called "OpenSSL"
+#    nor may "OpenSSL" appear in their names without prior written
+#    permission of the OpenSSL Project.
+#
+# 6. Redistributions of any form whatsoever must retain the following
+#    acknowledgment:
+#    "This product includes software developed by the OpenSSL Project
+#    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+#
+# THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+# EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+# OF THE POSSIBILITY OF SUCH DAMAGE.
+# ====================================================================
+#
+# This product includes cryptographic software written by Eric Young
+# (eay at cryptsoft.com).  This product includes software written by Tim
+# Hudson (tjh at cryptsoft.com).
+
+use strict;
+use OpenSSL::Test qw/:DEFAULT cmdstr top_file top_dir/;
+use TLSProxy::Proxy;
+use File::Temp qw(tempfile);
+
+my $test_name = "test_tlsextms";
+setup($test_name);
+
+plan skip_all => "$test_name can only be performed with OpenSSL configured shared"
+    unless (map { s/\R//; s/^SHARED_LIBS=\s*//; $_ }
+        grep { /^SHARED_LIBS=/ }
+        do { local @ARGV = ( top_file("Makefile") ); <> })[0] ne "";
+
+$ENV{OPENSSL_ENGINES} = top_dir("engines");
+$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
+
+sub checkmessages($$$$$);
+sub setrmextms($$);
+sub clearall();
+
+my $crmextms = 0;
+my $srmextms = 0;
+my $cextms = 0;
+my $sextms = 0;
+my $fullhand = 0;
+
+my $proxy = TLSProxy::Proxy->new(
+    \&extms_filter,
+    cmdstr(app(["openssl"])),
+    top_file("apps", "server.pem"),
+    1
+);
+
+plan tests => 9;
+
+#Test 1: By default server and client should send extended master secret
+# extension.
+#Expected result: ClientHello extension seen; ServerHello extension seen
+#                 Full handshake
+
+setrmextms(0, 0);
+$proxy->start();
+checkmessages(1, "Default extended master secret test", 1, 1, 1);
+
+#Test 2: If client omits extended master secret extension, server should too.
+#Expected result: ClientHello extension not seen; ServerHello extension not seen
+#                 Full handshake
+
+clearall();
+setrmextms(1, 0);
+$proxy->start();
+checkmessages(2, "No client extension extended master secret test", 0, 0, 1);
+
+# Test 3: same as 1 but with session tickets disabled.
+# Expected result: same as test 1.
+
+clearall();
+$proxy->clientflags("-no_ticket");
+setrmextms(0, 0);
+$proxy->start();
+checkmessages(3, "No ticket extended master secret test", 1, 1, 1);
+
+# Test 4: same as 2 but with session tickets disabled.
+# Expected result: same as test 2.
+
+clearall();
+$proxy->clientflags("-no_ticket");
+setrmextms(1, 0);
+$proxy->start();
+checkmessages(2, "No ticket, no client extension extended master secret test", 0, 0, 1);
+
+#Test 5: Session resumption extended master secret test
+#
+#Expected result: ClientHello extension seen; ServerHello extension seen
+#                 Abbreviated handshake
+
+clearall();
+setrmextms(0, 0);
+(my $fh, my $session) = tempfile();
+$proxy->serverconnects(2);
+$proxy->clientflags("-sess_out ".$session);
+$proxy->start();
+$proxy->clear();
+$proxy->clientflags("-sess_in ".$session);
+$proxy->clientstart();
+checkmessages(5, "Session resumption extended master secret test", 1, 1, 0);
+
+#Test 6: Session resumption extended master secret test orginial session
+# omits extension. Server must not resume session.
+#Expected result: ClientHello extension seen; ServerHello extension seen
+#                 Full handshake
+
+clearall();
+setrmextms(1, 0);
+($fh, $session) = tempfile();
+$proxy->serverconnects(2);
+$proxy->clientflags("-sess_out ".$session);
+$proxy->start();
+$proxy->clear();
+$proxy->clientflags("-sess_in ".$session);
+setrmextms(0, 0);
+$proxy->clientstart();
+checkmessages(6, "Session resumption extended master secret test", 1, 1, 1);
+
+#Test 7: Session resumption extended master secret test resumed session
+# omits client extension. Server must abort connection.
+#Expected result: aborted connection.
+
+clearall();
+setrmextms(0, 0);
+($fh, $session) = tempfile();
+$proxy->serverconnects(2);
+$proxy->clientflags("-sess_out ".$session);
+$proxy->start();
+$proxy->clear();
+$proxy->clientflags("-sess_in ".$session);
+setrmextms(1, 0);
+$proxy->clientstart();
+ok(TLSProxy::Message->fail(), "Client inconsistent session resupmption");
+
+#Test 8: Session resumption extended master secret test resumed session
+# omits server extension. Client must abort connection.
+#Expected result: aborted connection.
+
+clearall();
+setrmextms(0, 0);
+($fh, $session) = tempfile();
+$proxy->serverconnects(2);
+$proxy->clientflags("-sess_out ".$session);
+$proxy->start();
+$proxy->clear();
+$proxy->clientflags("-sess_in ".$session);
+setrmextms(0, 1);
+$proxy->clientstart();
+ok(TLSProxy::Message->fail(), "Server inconsistent session resumption 1");
+
+#Test 9: Session resumption extended master secret test initial session
+# omits server extension. Client must abort connection.
+#Expected result: aborted connection.
+
+clearall();
+setrmextms(0, 1);
+($fh, $session) = tempfile();
+$proxy->serverconnects(2);
+$proxy->clientflags("-sess_out ".$session);
+$proxy->start();
+$proxy->clear();
+$proxy->clientflags("-sess_in ".$session);
+setrmextms(0, 0);
+$proxy->clientstart();
+ok(TLSProxy::Message->fail(), "Server inconsistent session resumption 2");
+
+sub extms_filter
+{
+    my $proxy = shift;
+
+    foreach my $message (@{$proxy->message_list}) {
+        if ($crmextms && $message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
+            $message->delete_extension(TLSProxy::ClientHello::EXT_EXTENDED_MASTER_SECRET);
+            $message->repack();
+        }
+        if ($srmextms && $message->mt == TLSProxy::Message::MT_SERVER_HELLO) {
+            $message->delete_extension(TLSProxy::ClientHello::EXT_EXTENDED_MASTER_SECRET);
+            $message->repack();
+        }
+    }
+}
+
+sub checkmessages($$$$$)
+{
+    my ($testno, $testname, $testcextms, $testsextms, $testhand) = @_;
+
+    subtest $testname => sub {
+
+    foreach my $message (@{$proxy->message_list}) {
+        if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO
+            || $message->mt == TLSProxy::Message::MT_SERVER_HELLO) {
+        #Get the extensions data
+        my %extensions = %{$message->extension_data};
+        if (defined
+            $extensions{TLSProxy::ClientHello::EXT_EXTENDED_MASTER_SECRET}) {
+            if ($message->mt == TLSProxy::Message::MT_CLIENT_HELLO) {
+                $cextms = 1;
+            } else {
+                $sextms = 1;
+            }
+        }
+        } elsif ($message->mt == TLSProxy::Message::MT_CLIENT_KEY_EXCHANGE) {
+            #Must be doing a full handshake
+            $fullhand = 1;
+        }
+    }
+
+    plan tests => 4;
+
+    ok(TLSProxy::Message->success, "Handshake");
+
+    ok($testcextms == $cextms,
+       "ClientHello extension extended master secret check");
+    ok($testsextms == $sextms,
+       "ServerHello extension extended master secret check");
+    ok($testhand == $fullhand,
+       "Extended master secret full handshake check");
+
+    }
+}
+
+sub setrmextms($$)
+{
+    ($crmextms, $srmextms) = @_;
+}
+
+sub clearall()
+{
+    $cextms = 0;
+    $sextms = 0;
+    $fullhand = 0;
+    $proxy->clear();
+}
diff --git a/util/TLSProxy/ClientHello.pm b/util/TLSProxy/ClientHello.pm
index 0b7dbbc..c6f3c3f 100644
--- a/util/TLSProxy/ClientHello.pm
+++ b/util/TLSProxy/ClientHello.pm
@@ -59,6 +59,7 @@ use parent 'TLSProxy::Message';
 
 use constant {
     EXT_ENCRYPT_THEN_MAC => 22,
+    EXT_EXTENDED_MASTER_SECRET => 23,
     EXT_SESSION_TICKET => 35
 };
 
@@ -70,7 +71,7 @@ sub new
         $records,
         $startoffset,
         $message_frag_lens) = @_;
-    
+
     my $self = $class->SUPER::new(
         $server,
         1,
@@ -118,7 +119,7 @@ sub parse
     #For now we just deal with this as a block of data. In the future we will
     #want to parse this
     my $extension_data = substr($self->data, $ptr);
-    
+
     if (length($extension_data) != $extensions_len) {
         die "Invalid extension length\n";
     }
@@ -169,6 +170,7 @@ sub set_message_contents
 {
     my $self = shift;
     my $data;
+    my $extensions = "";
 
     $data = pack('n', $self->client_version);
     $data .= $self->random;
@@ -178,14 +180,17 @@ sub set_message_contents
     $data .= pack("n*", @{$self->ciphersuites});
     $data .= pack('C', $self->comp_meth_len);
     $data .= pack("C*", @{$self->comp_meths});
-    $data .= pack('n', $self->extensions_len);
+
     foreach my $key (keys %{$self->extension_data}) {
         my $extdata = ${$self->extension_data}{$key};
-        $data .= pack("n", $key);
-        $data .= pack("n", length($extdata));
-        $data .= $extdata;
+        $extensions .= pack("n", $key);
+        $extensions .= pack("n", length($extdata));
+        $extensions .= $extdata;
     }
 
+    $data .= pack('n', length($extensions));
+    $data .= $extensions;
+
     $self->data($data);
 }
 
@@ -270,4 +275,9 @@ sub extension_data
     }
     return $self->{extension_data};
 }
+sub delete_extension
+{
+    my ($self, $ext_type) = @_;
+    delete $self->{extension_data}{$ext_type};
+}
 1;
diff --git a/util/TLSProxy/ServerHello.pm b/util/TLSProxy/ServerHello.pm
index 56b8a34..487538a 100644
--- a/util/TLSProxy/ServerHello.pm
+++ b/util/TLSProxy/ServerHello.pm
@@ -230,4 +230,9 @@ sub set_extension
     my ($self, $ext_type, $ext_data) = @_;
     $self->{extension_data}{$ext_type} = $ext_data;
 }
+sub delete_extension
+{
+    my ($self, $ext_type) = @_;
+    delete $self->{extension_data}{$ext_type};
+}
 1;


More information about the openssl-commits mailing list