Add processing of the key_share received in the ServerHello
authorMatt Caswell <matt@openssl.org>
Tue, 1 Nov 2016 14:09:19 +0000 (14:09 +0000)
committerMatt Caswell <matt@openssl.org>
Wed, 16 Nov 2016 10:09:46 +0000 (10:09 +0000)
Reviewed-by: Rich Salz <rsalz@openssl.org>
include/openssl/ssl.h
ssl/ssl_err.c
ssl/t1_lib.c

index dab0c4ee38f44139a99f94a31144f1df53772e71..fdef8c54e3d2d5d778c6fdd471b2dc14810a99de 100644 (file)
@@ -2313,6 +2313,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_R_BAD_ECPOINT                                306
 # define SSL_R_BAD_HANDSHAKE_LENGTH                       332
 # define SSL_R_BAD_HELLO_REQUEST                          105
+# define SSL_R_BAD_KEY_SHARE                              108
 # define SSL_R_BAD_LENGTH                                 271
 # define SSL_R_BAD_PACKET_LENGTH                          115
 # define SSL_R_BAD_PROTOCOL_VERSION_NUMBER                116
index 7523f1c76f4746fcb95e714293c31074d476cd2b..fcd4375c24fd7ccf358e04f3ad2a6fdee8195363 100644 (file)
@@ -342,6 +342,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
     {ERR_REASON(SSL_R_BAD_ECPOINT), "bad ecpoint"},
     {ERR_REASON(SSL_R_BAD_HANDSHAKE_LENGTH), "bad handshake length"},
     {ERR_REASON(SSL_R_BAD_HELLO_REQUEST), "bad hello request"},
+    {ERR_REASON(SSL_R_BAD_KEY_SHARE), "bad key share"},
     {ERR_REASON(SSL_R_BAD_LENGTH), "bad length"},
     {ERR_REASON(SSL_R_BAD_PACKET_LENGTH), "bad packet length"},
     {ERR_REASON(SSL_R_BAD_PROTOCOL_VERSION_NUMBER),
index 11c8399a2830cae0a796079b7268d90fefad3f55..f87b7ef1ea1ce60523f3ce9f2b8759c359dcc0e3 100644 (file)
@@ -2637,12 +2637,64 @@ static int ssl_scan_serverhello_tlsext(SSL *s, PACKET *pkt, int *al)
             s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
             if (!s->hit)
                 s->session->flags |= SSL_SESS_FLAG_EXTMS;
-        }
+        } else if (type == TLSEXT_TYPE_key_share
+                && s->version == TLS1_3_VERSION) {
+            unsigned int group_id;
+            PACKET encoded_pt;
+            EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL;
+
+            /* Sanity check */
+            if (ckey == NULL) {
+                *al = SSL_AD_INTERNAL_ERROR;
+                SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
+                return 0;
+            }
+
+            if (!PACKET_get_net_2(&spkt, &group_id)) {
+                *al = SSL_AD_HANDSHAKE_FAILURE;
+                SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT,
+                       SSL_R_LENGTH_MISMATCH);
+                return 0;
+            }
+
+            if (group_id != s->s3->group_id) {
+                /*
+                 * This isn't for the group that we sent in the original
+                 * key_share!
+                 */
+                *al = SSL_AD_HANDSHAKE_FAILURE;
+                SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT,
+                       SSL_R_BAD_KEY_SHARE);
+                return 0;
+            }
+
+            /* TODO(TLS1.3): Create skey from ckey */
+            skey = ssl_generate_pkey(ckey);
+
+            if (!PACKET_as_length_prefixed_2(&spkt, &encoded_pt)) {
+                *al = SSL_AD_DECODE_ERROR;
+                SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT,
+                       SSL_R_LENGTH_MISMATCH);
+                return 0;
+            }
+
+            if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt),
+                                                PACKET_remaining(&encoded_pt))) {
+                *al = SSL_AD_DECODE_ERROR;
+                SSLerr(SSL_F_SSL_SCAN_SERVERHELLO_TLSEXT, SSL_R_BAD_ECPOINT);
+                return 0;
+            }
+
+            /*
+             * TODO(TLS1.3): Throw it all away for now, later we will use the
+             * two keys.
+             */
+            EVP_PKEY_free(skey);
         /*
          * If this extension type was not otherwise handled, but matches a
          * custom_cli_ext_record, then send it to the c callback
          */
-        else if (custom_ext_parse(s, 0, type, data, size, al) <= 0)
+        else if (custom_ext_parse(s, 0, type, data, size, al) <= 0)
             return 0;
     }