[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Wed May 3 13:49:54 UTC 2017


The branch master has been updated
       via  6d9d8019bbc02e73ee1fdb5f6ffe3dd6ffcaa9d8 (commit)
       via  f233a9d181b5cd150322e2e10348a4c1d96fc1f3 (commit)
       via  fb29c0f0704a488b9e282caf7643cde0119223b8 (commit)
       via  2698bbfec60bf048bc7362307658143b5ad657d5 (commit)
       via  c3a48c7b1d19fe884f727713b341d6ffb1530942 (commit)
       via  b878afae4ba4a1470a26fcdbaa57d9f76159f8df (commit)
       via  7f533d6fa1e1497e3c43630952528521b2627f53 (commit)
       via  84c34ba8762463057d372e22ad98a045dbd9a51f (commit)
      from  f0ef20bf386b5c37ba5a4ce5c1de9a819bbeffb2 (commit)


- Log -----------------------------------------------------------------
commit 6d9d8019bbc02e73ee1fdb5f6ffe3dd6ffcaa9d8
Author: Matt Caswell <matt at openssl.org>
Date:   Wed May 3 14:41:43 2017 +0100

    Update serverinfo documentation based on feedback received
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3298)

commit f233a9d181b5cd150322e2e10348a4c1d96fc1f3
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Apr 25 12:42:17 2017 +0100

    Clarify serverinfo usage with Certificate messages
    
    Ensure that serverinfo only gets added for the first Certificate in a list.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3298)

commit fb29c0f0704a488b9e282caf7643cde0119223b8
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Apr 18 17:53:54 2017 +0100

    Document the new SSL_CTX_use_serverinfo_ex() function
    
    Also document other releated changes to the serverinfo capability.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3298)

commit 2698bbfec60bf048bc7362307658143b5ad657d5
Author: Matt Caswell <matt at openssl.org>
Date:   Tue Apr 18 17:53:29 2017 +0100

    Add an SSL_ prefix to SERVERINFOV2 and SERVERINFOV1
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3298)

commit c3a48c7b1d19fe884f727713b341d6ffb1530942
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Apr 13 16:55:45 2017 +0100

    Add a test for CT in TLSv1.3
    
    This also tests the SERVERINFO2 file format.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3298)

commit b878afae4ba4a1470a26fcdbaa57d9f76159f8df
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 10 16:19:16 2017 +0100

    Add a SERVERINFOV2 format test file
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3298)

commit 7f533d6fa1e1497e3c43630952528521b2627f53
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 10 16:18:26 2017 +0100

    Only send custom extensions where we have received one in the ClientHello
    
    We already did this for ServerHello and EncryptedExtensions. We should be
    doing it for Certificate and HelloRetryRequest as well.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3298)

commit 84c34ba8762463057d372e22ad98a045dbd9a51f
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Apr 10 16:13:20 2017 +0100

    Extend the SERVERINFO file format to include an extensions context
    
    This enables us to know what messages the extensions are relevant for in
    TLSv1.3. The new file format is not compatible with the previous one so
    we call it SERVERINFOV2.
    
    Reviewed-by: Rich Salz <rsalz at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/3298)

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

Summary of changes:
 doc/man3/SSL_CTX_use_serverinfo.pod  |  51 ++++++--
 include/openssl/ssl.h                |   9 ++
 ssl/ssl_err.c                        |   1 +
 ssl/ssl_rsa.c                        | 246 ++++++++++++++++++++++-------------
 ssl/statem/extensions_cust.c         |   9 +-
 test/recipes/70-test_tls13messages.t |  44 ++++---
 test/serverinfo2.pem                 |   8 ++
 util/libssl.num                      |   1 +
 8 files changed, 244 insertions(+), 125 deletions(-)
 create mode 100644 test/serverinfo2.pem

diff --git a/doc/man3/SSL_CTX_use_serverinfo.pod b/doc/man3/SSL_CTX_use_serverinfo.pod
index bd496ff..d35a196 100644
--- a/doc/man3/SSL_CTX_use_serverinfo.pod
+++ b/doc/man3/SSL_CTX_use_serverinfo.pod
@@ -2,12 +2,19 @@
 
 =head1 NAME
 
-SSL_CTX_use_serverinfo, SSL_CTX_use_serverinfo_file - use serverinfo extension
+SSL_CTX_use_serverinfo_ex,
+SSL_CTX_use_serverinfo,
+SSL_CTX_use_serverinfo_file
+- use serverinfo extension
 
 =head1 SYNOPSIS
 
  #include <openssl/ssl.h>
 
+ int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
+                               const unsigned char *serverinfo,
+                               size_t serverinfo_length);
+
  int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
                             size_t serverinfo_length);
 
@@ -15,20 +22,40 @@ SSL_CTX_use_serverinfo, SSL_CTX_use_serverinfo_file - use serverinfo extension
 
 =head1 DESCRIPTION
 
-These functions load "serverinfo" TLS ServerHello Extensions into the SSL_CTX.
-A "serverinfo" extension is returned in response to an empty ClientHello
+These functions load "serverinfo" TLS extensions into the SSL_CTX. A
+"serverinfo" extension is returned in response to an empty ClientHello
 Extension.
 
-SSL_CTX_use_serverinfo() loads one or more serverinfo extensions from
-a byte array into B<ctx>.  The extensions must be concatenated into a
-sequence of bytes.  Each extension must consist of a 2-byte Extension Type,
-a 2-byte length, and then length bytes of extension_data.
+SSL_CTX_use_serverinfo_ex() loads one or more serverinfo extensions from
+a byte array into B<ctx>. The B<version> parameter specifies the format of the
+byte array provided in B<*serverinfo> which is of length B<serverinfo_length>.
+
+If B<version> is B<SSL_SERVERINFOV2> then the extensions in the array must
+consist of a 4-byte context, a 2-byte Extension Type, a 2-byte length, and then
+length bytes of extension_data. The context and type values have the same
+meaning as for L<SSL_CTX_add_custom_ext(3)>. If serverinfo is being loaded for
+extensions to be added to a Certificate message, then the extension will only
+be added for the first certificate in the message (which is always the
+end-entity certificate).
+
+If B<version> is B<SSL_SERVERINFOV1> then the extensions in the array must
+consist of a 2-byte Extension Type, a 2-byte length, and then length bytes of
+extension_data. The type value has the same meaning as for
+L<SSL_CTX_add_custom_ext(3)>. The following default context value will be used
+in this case:
+
+ SSL_EXT_TLS1_2_AND_BELOW_ONLY | SSL_EXT_CLIENT_HELLO
+ | SSL_EXT_TLS1_2_SERVER_HELLO | SSL_EXT_IGNORE_ON_RESUMPTION
+
+SSL_CTX_use_serverinfo() does the same thing as SSL_CTX_use_serverinfo_ex()
+except that there is no B<version> parameter so a default version of
+SSL_SERVERINFOV1 is used instead.
 
 SSL_CTX_use_serverinfo_file() loads one or more serverinfo extensions from
 B<file> into B<ctx>.  The extensions must be in PEM format.  Each extension
-must consist of a 2-byte Extension Type, a 2-byte length, and then length
-bytes of extension_data.  Each PEM extension name must begin with the phrase
-"BEGIN SERVERINFO FOR ".
+must be in a format as described above for SSL_CTX_use_serverinfo_ex().  Each
+PEM extension name must begin with the phrase "BEGIN SERVERINFOV2 FOR " for
+SSL_SERVERINFOV2 data or "BEGIN SERVERINFO FOR " for SSL_SERVERINFOV1 data.
 
 If more than one certificate (RSA/DSA) is installed using
 SSL_CTX_use_certificate(), the serverinfo extension will be loaded into the
@@ -36,7 +63,7 @@ last certificate installed.  If e.g. the last item was a RSA certificate, the
 loaded serverinfo extension data will be loaded for that certificate.  To
 use the serverinfo extension for multiple certificates,
 SSL_CTX_use_serverinfo() needs to be called multiple times, once B<after>
-each time a certificate is loaded.
+each time a certificate is loaded via a call to SSL_CTX_use_certificate().
 
 =head1 RETURN VALUES
 
@@ -46,7 +73,7 @@ the reason.
 
 =head1 COPYRIGHT
 
-Copyright 2013-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2013-2017 The OpenSSL Project Authors. All Rights Reserved.
 
 Licensed under the OpenSSL license (the "License").  You may not use
 this file except in compliance with the License.  You can obtain a copy
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index b1da6c5..764ecea 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1451,9 +1451,17 @@ __owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d,
 __owur int SSL_use_certificate(SSL *ssl, X509 *x);
 __owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
 
+
+/* serverinfo file format versions */
+# define SSL_SERVERINFOV1   1
+# define SSL_SERVERINFOV2   2
+
 /* Set serverinfo data for the current active cert. */
 __owur int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
                            size_t serverinfo_length);
+__owur int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
+                                     const unsigned char *serverinfo,
+                                     size_t serverinfo_length);
 __owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file);
 
 #ifndef OPENSSL_NO_RSA
@@ -2328,6 +2336,7 @@ int ERR_load_SSL_strings(void);
 # define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_ASN1             178
 # define SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE             179
 # define SSL_F_SSL_CTX_USE_SERVERINFO                     336
+# define SSL_F_SSL_CTX_USE_SERVERINFO_EX                  543
 # define SSL_F_SSL_CTX_USE_SERVERINFO_FILE                337
 # define SSL_F_SSL_DANE_DUP                               403
 # define SSL_F_SSL_DANE_ENABLE                            395
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 296ce0d..a845dae 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -174,6 +174,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
     {ERR_FUNC(SSL_F_SSL_CTX_USE_RSAPRIVATEKEY_FILE),
      "SSL_CTX_use_RSAPrivateKey_file"},
     {ERR_FUNC(SSL_F_SSL_CTX_USE_SERVERINFO), "SSL_CTX_use_serverinfo"},
+    {ERR_FUNC(SSL_F_SSL_CTX_USE_SERVERINFO_EX), "SSL_CTX_use_serverinfo_ex"},
     {ERR_FUNC(SSL_F_SSL_CTX_USE_SERVERINFO_FILE),
      "SSL_CTX_use_serverinfo_file"},
     {ERR_FUNC(SSL_F_SSL_DANE_DUP), "ssl_dane_dup"},
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index 87be646..f0a058e 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -9,6 +9,7 @@
 
 #include <stdio.h>
 #include "ssl_locl.h"
+#include "packet_locl.h"
 #include <openssl/bio.h>
 #include <openssl/objects.h>
 #include <openssl/evp.h>
@@ -693,50 +694,43 @@ static int serverinfo_find_extension(const unsigned char *serverinfo,
                                      const unsigned char **extension_data,
                                      size_t *extension_length)
 {
+    PACKET pkt, data;
+
     *extension_data = NULL;
     *extension_length = 0;
     if (serverinfo == NULL || serverinfo_length == 0)
         return -1;
+
+    if (!PACKET_buf_init(&pkt, serverinfo, serverinfo_length))
+        return -1;
+
     for (;;) {
         unsigned int type = 0;
-        size_t len = 0;
+        unsigned long context = 0;
 
         /* end of serverinfo */
-        if (serverinfo_length == 0)
+        if (PACKET_remaining(&pkt) == 0)
             return 0;           /* Extension not found */
 
-        /* read 2-byte type field */
-        if (serverinfo_length < 2)
-            return -1;          /* Error */
-        type = (serverinfo[0] << 8) + serverinfo[1];
-        serverinfo += 2;
-        serverinfo_length -= 2;
-
-        /* read 2-byte len field */
-        if (serverinfo_length < 2)
-            return -1;          /* Error */
-        len = (serverinfo[0] << 8) + serverinfo[1];
-        serverinfo += 2;
-        serverinfo_length -= 2;
-
-        if (len > serverinfo_length)
-            return -1;          /* Error */
+        if (!PACKET_get_net_4(&pkt, &context)
+                || !PACKET_get_net_2(&pkt, &type)
+                || !PACKET_get_length_prefixed_2(&pkt, &data))
+            return -1;
 
         if (type == extension_type) {
-            *extension_data = serverinfo;
-            *extension_length = len;
+            *extension_data = PACKET_data(&data);
+            *extension_length = PACKET_remaining(&data);;
             return 1;           /* Success */
         }
-
-        serverinfo += len;
-        serverinfo_length -= len;
     }
     /* Unreachable */
 }
 
-static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type,
-                                   const unsigned char *in,
-                                   size_t inlen, int *al, void *arg)
+static int serverinfoex_srv_parse_cb(SSL *s, unsigned int ext_type,
+                                     unsigned int context,
+                                     const unsigned char *in,
+                                     size_t inlen, X509 *x, size_t chainidx,
+                                     int *al, void *arg)
 {
 
     if (inlen != 0) {
@@ -747,13 +741,27 @@ static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type,
     return 1;
 }
 
-static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type,
-                                 const unsigned char **out, size_t *outlen,
-                                 int *al, void *arg)
+static int serverinfo_srv_parse_cb(SSL *s, unsigned int ext_type,
+                                   const unsigned char *in,
+                                   size_t inlen, int *al, void *arg)
+{
+    return serverinfoex_srv_parse_cb(s, ext_type, 0, in, inlen, NULL, 0, al,
+                                     arg);
+}
+
+static int serverinfoex_srv_add_cb(SSL *s, unsigned int ext_type,
+                                   unsigned int context,
+                                   const unsigned char **out,
+                                   size_t *outlen, X509 *x, size_t chainidx,
+                                   int *al, void *arg)
 {
     const unsigned char *serverinfo = NULL;
     size_t serverinfo_length = 0;
 
+    /* We only support extensions for the first Certificate */
+    if ((context & SSL_EXT_TLS1_3_CERTIFICATE) != 0 && chainidx > 0)
+        return 0;
+
     /* Is there serverinfo data for the chosen server cert? */
     if ((ssl_get_server_cert_serverinfo(s, &serverinfo,
                                         &serverinfo_length)) != 0) {
@@ -772,81 +780,90 @@ static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type,
                                  * extension */
 }
 
+static int serverinfo_srv_add_cb(SSL *s, unsigned int ext_type,
+                                 const unsigned char **out, size_t *outlen,
+                                 int *al, void *arg)
+{
+    return serverinfoex_srv_add_cb(s, ext_type, 0, out, outlen, NULL, 0, al,
+                                   arg);
+}
+
 /*
  * With a NULL context, this function just checks that the serverinfo data
  * parses correctly.  With a non-NULL context, it registers callbacks for
  * the included extensions.
  */
-static int serverinfo_process_buffer(const unsigned char *serverinfo,
+static int serverinfo_process_buffer(unsigned int version,
+                                     const unsigned char *serverinfo,
                                      size_t serverinfo_length, SSL_CTX *ctx)
 {
+    PACKET pkt;
+
     if (serverinfo == NULL || serverinfo_length == 0)
         return 0;
-    for (;;) {
-        unsigned int ext_type = 0;
-        size_t len = 0;
 
-        /* end of serverinfo */
-        if (serverinfo_length == 0)
-            return 1;
-
-        /* read 2-byte type field */
-        if (serverinfo_length < 2)
-            return 0;
-        /* FIXME: check for types we understand explicitly? */
-
-        /* Register callbacks for extensions */
-        ext_type = (serverinfo[0] << 8) + serverinfo[1];
-        if (ctx != NULL
-                && custom_ext_find(&ctx->cert->custext, ENDPOINT_SERVER,
-                                   ext_type, NULL)
-                   == NULL
-                && !SSL_CTX_add_server_custom_ext(ctx, ext_type,
-                                                  serverinfo_srv_add_cb,
-                                                  NULL, NULL,
-                                                  serverinfo_srv_parse_cb,
-                                                  NULL))
-            return 0;
+    if (version != SSL_SERVERINFOV1 && version != SSL_SERVERINFOV2)
+        return 0;
 
-        serverinfo += 2;
-        serverinfo_length -= 2;
+    if (!PACKET_buf_init(&pkt, serverinfo, serverinfo_length))
+        return 0;
 
-        /* read 2-byte len field */
-        if (serverinfo_length < 2)
-            return 0;
-        len = (serverinfo[0] << 8) + serverinfo[1];
-        serverinfo += 2;
-        serverinfo_length -= 2;
+    while (PACKET_remaining(&pkt)) {
+        unsigned long context = 0;
+        unsigned int ext_type = 0;
+        PACKET data;
 
-        if (len > serverinfo_length)
+        if (!PACKET_get_net_4(&pkt, &context)
+                || !PACKET_get_net_2(&pkt, &ext_type)
+                || !PACKET_get_length_prefixed_2(&pkt, &data))
             return 0;
 
-        serverinfo += len;
-        serverinfo_length -= len;
+        if (ctx == NULL)
+            continue;
+
+        if (version == SSL_SERVERINFOV1) {
+            if (!SSL_CTX_add_server_custom_ext(ctx, ext_type,
+                                               serverinfo_srv_add_cb,
+                                               NULL, NULL,
+                                               serverinfo_srv_parse_cb,
+                                               NULL))
+                return 0;
+        } else {
+            if (!SSL_CTX_add_custom_ext(ctx, ext_type, context,
+                                        serverinfoex_srv_add_cb,
+                                        NULL, NULL,
+                                        serverinfoex_srv_parse_cb,
+                                        NULL))
+                return 0;
+        }
     }
+
+    return 1;
 }
 
-int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
-                           size_t serverinfo_length)
+int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
+                              const unsigned char *serverinfo,
+                              size_t serverinfo_length)
 {
     unsigned char *new_serverinfo;
 
     if (ctx == NULL || serverinfo == NULL || serverinfo_length == 0) {
-        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_PASSED_NULL_PARAMETER);
+        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
-    if (!serverinfo_process_buffer(serverinfo, serverinfo_length, NULL)) {
-        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, SSL_R_INVALID_SERVERINFO_DATA);
+    if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length,
+                                   NULL)) {
+        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, SSL_R_INVALID_SERVERINFO_DATA);
         return 0;
     }
     if (ctx->cert->key == NULL) {
-        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_INTERNAL_ERROR);
+        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_INTERNAL_ERROR);
         return 0;
     }
     new_serverinfo = OPENSSL_realloc(ctx->cert->key->serverinfo,
                                      serverinfo_length);
     if (new_serverinfo == NULL) {
-        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, ERR_R_MALLOC_FAILURE);
+        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, ERR_R_MALLOC_FAILURE);
         return 0;
     }
     ctx->cert->key->serverinfo = new_serverinfo;
@@ -857,13 +874,21 @@ int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
      * Now that the serverinfo is validated and stored, go ahead and
      * register callbacks.
      */
-    if (!serverinfo_process_buffer(serverinfo, serverinfo_length, ctx)) {
-        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO, SSL_R_INVALID_SERVERINFO_DATA);
+    if (!serverinfo_process_buffer(version, serverinfo, serverinfo_length,
+                                   ctx)) {
+        SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_EX, SSL_R_INVALID_SERVERINFO_DATA);
         return 0;
     }
     return 1;
 }
 
+int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
+                           size_t serverinfo_length)
+{
+    return SSL_CTX_use_serverinfo_ex(ctx, SSL_SERVERINFOV1, serverinfo,
+                                     serverinfo_length);
+}
+
 int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
 {
     unsigned char *serverinfo = NULL;
@@ -873,10 +898,12 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
     long extension_length = 0;
     char *name = NULL;
     char *header = NULL;
-    char namePrefix[] = "SERVERINFO FOR ";
+    char namePrefix1[] = "SERVERINFO FOR ";
+    char namePrefix2[] = "SERVERINFOV2 FOR ";
     int ret = 0;
     BIO *bin = NULL;
-    size_t num_extensions = 0;
+    size_t num_extensions = 0, contextoff = 0;
+    unsigned int version;
 
     if (ctx == NULL || file == NULL) {
         SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_PASSED_NULL_PARAMETER);
@@ -907,32 +934,72 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
                 break;
         }
         /* Check that PEM name starts with "BEGIN SERVERINFO FOR " */
-        if (strlen(name) < strlen(namePrefix)) {
+        if (strlen(name) < strlen(namePrefix1)) {
             SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_PEM_NAME_TOO_SHORT);
             goto end;
         }
-        if (strncmp(name, namePrefix, strlen(namePrefix)) != 0) {
-            SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,
-                   SSL_R_PEM_NAME_BAD_PREFIX);
-            goto end;
+        if (strncmp(name, namePrefix1, strlen(namePrefix1)) == 0) {
+            version = SSL_SERVERINFOV1;
+        } else {
+            if (strlen(name) < strlen(namePrefix2)) {
+                SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,
+                       SSL_R_PEM_NAME_TOO_SHORT);
+                goto end;
+            }
+            if (strncmp(name, namePrefix2, strlen(namePrefix2)) != 0) {
+                SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE,
+                       SSL_R_PEM_NAME_BAD_PREFIX);
+                goto end;
+            }
+            version = SSL_SERVERINFOV2;
         }
         /*
          * Check that the decoded PEM data is plausible (valid length field)
          */
-        if (extension_length < 4
-            || (extension[2] << 8) + extension[3] != extension_length - 4) {
-            SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA);
-            goto end;
+        if (version == SSL_SERVERINFOV1) {
+            /* 4 byte header: 2 bytes type, 2 bytes len */
+            if (extension_length < 4
+                    || (extension[2] << 8) + extension[3]
+                       != extension_length - 4) {
+                SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA);
+                goto end;
+            }
+            /*
+             * File does not have a context value so we must take account of
+             * this later.
+             */
+            contextoff = 4;
+        } else {
+            /* 8 byte header: 4 bytes context, 2 bytes type, 2 bytes len */
+            if (extension_length < 8
+                    || (extension[6] << 8) + extension[7]
+                       != extension_length - 8) {
+                SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, SSL_R_BAD_DATA);
+                goto end;
+            }
         }
         /* Append the decoded extension to the serverinfo buffer */
-        tmp = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length);
+        tmp = OPENSSL_realloc(serverinfo, serverinfo_length + extension_length
+                                          + contextoff);
         if (tmp == NULL) {
             SSLerr(SSL_F_SSL_CTX_USE_SERVERINFO_FILE, ERR_R_MALLOC_FAILURE);
             goto end;
         }
         serverinfo = tmp;
-        memcpy(serverinfo + serverinfo_length, extension, extension_length);
-        serverinfo_length += extension_length;
+        if (contextoff > 0) {
+            unsigned int synthcontext = SSL_EXT_CLIENT_HELLO
+                                        | SSL_EXT_TLS1_2_SERVER_HELLO;
+            unsigned char *sinfo = serverinfo + serverinfo_length;
+
+            /* We know this only uses the last 2 bytes */
+            sinfo[0] = 0;
+            sinfo[1] = 0;
+            sinfo[2] = (synthcontext >> 8) & 0xff;
+            sinfo[3] = synthcontext & 0xff;
+        }
+        memcpy(serverinfo + serverinfo_length + contextoff,
+               extension, extension_length);
+        serverinfo_length += extension_length + contextoff;
 
         OPENSSL_free(name);
         name = NULL;
@@ -942,7 +1009,8 @@ int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file)
         extension = NULL;
     }
 
-    ret = SSL_CTX_use_serverinfo(ctx, serverinfo, serverinfo_length);
+    ret = SSL_CTX_use_serverinfo_ex(ctx, version, serverinfo,
+                                    serverinfo_length);
  end:
     /* SSL_CTX_use_serverinfo makes a local copy of the serverinfo. */
     OPENSSL_free(name);
diff --git a/ssl/statem/extensions_cust.c b/ssl/statem/extensions_cust.c
index 6de59e2..2a21ec4 100644
--- a/ssl/statem/extensions_cust.c
+++ b/ssl/statem/extensions_cust.c
@@ -181,11 +181,10 @@ int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
 
         if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
                         | SSL_EXT_TLS1_3_SERVER_HELLO
-                        | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) {
-            /*
-             * For ServerHello/EncryptedExtensions only send extensions present
-             * in ClientHello.
-             */
+                        | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
+                        | SSL_EXT_TLS1_3_CERTIFICATE
+                        | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
+            /* Only send extensions present in ClientHello. */
             if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
                 continue;
         }
diff --git a/test/recipes/70-test_tls13messages.t b/test/recipes/70-test_tls13messages.t
index c4e20b7..c9603de 100644
--- a/test/recipes/70-test_tls13messages.t
+++ b/test/recipes/70-test_tls13messages.t
@@ -126,6 +126,8 @@ $ENV{CTLOG_FILE} = srctop_file("test", "ct", "log_list.conf");
 
     [TLSProxy::Message::MT_CERTIFICATE, TLSProxy::Message::EXT_STATUS_REQUEST,
         checkhandshake::STATUS_REQUEST_SRV_EXTENSION],
+    [TLSProxy::Message::MT_CERTIFICATE, TLSProxy::Message::EXT_SCT,
+        checkhandshake::SCT_SRV_EXTENSION],
 
     [0,0,0]
 );
@@ -257,25 +259,29 @@ checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
                | checkhandshake::ALPN_SRV_EXTENSION,
                "ALPN handshake test");
 
-#Test 13: SCT handshake (client request only)
-#TODO(TLS1.3): This only checks that the client side extension appears. The
-#SCT extension is unusual in that we have no built-in server side implementation
-#The server side implementation can nomrally be added using the custom
-#extensions framework (e.g. by using the "-serverinfo" s_server option). However
-#currently we only support <= TLS1.2 for custom extensions because the existing
-#framework and API has no knowledge of the TLS1.3 messages
-$proxy->clear();
-#Note: -ct also sends status_request
-$proxy->clientflags("-ct");
-$proxy->serverflags("-status_file "
-                    .srctop_file("test", "recipes", "ocsp-response.der"));
-$proxy->start();
-checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
-               checkhandshake::DEFAULT_EXTENSIONS
-               | checkhandshake::SCT_CLI_EXTENSION
-               | checkhandshake::STATUS_REQUEST_CLI_EXTENSION
-               | checkhandshake::STATUS_REQUEST_SRV_EXTENSION,
-               "SCT handshake test");
+SKIP: {
+    skip "No CT, EC or OCSP support in this OpenSSL build", 1
+        if disabled("ct") || disabled("ec") || disabled("ocsp");
+
+    #Test 13: SCT handshake (client request only)
+    $proxy->clear();
+    #Note: -ct also sends status_request
+    $proxy->clientflags("-ct");
+    $proxy->serverflags("-status_file "
+                        .srctop_file("test", "recipes", "ocsp-response.der")
+                        ." -serverinfo ".srctop_file("test", "serverinfo2.pem"));
+    $proxy->start();
+    checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
+                   checkhandshake::DEFAULT_EXTENSIONS
+                   | checkhandshake::SCT_CLI_EXTENSION
+                   | checkhandshake::SCT_SRV_EXTENSION
+                   | checkhandshake::STATUS_REQUEST_CLI_EXTENSION
+                   | checkhandshake::STATUS_REQUEST_SRV_EXTENSION,
+                   "SCT handshake test");
+}
+
+
+
 
 #Test 14: HRR Handshake
 $proxy->clear();
diff --git a/test/serverinfo2.pem b/test/serverinfo2.pem
new file mode 100644
index 0000000..792d5c0
--- /dev/null
+++ b/test/serverinfo2.pem
@@ -0,0 +1,8 @@
+-----BEGIN SERVERINFOV2 FOR CT-----
+AAARgAASAPIA8AB2AO5Lvbd1zmC64UJpH6vhnmajD35fsHLYgwDEe4l6qP3LAAAB
+Wxp+yVkAAAQDAEcwRQIhAMhZ7Se2olZ35Mqze2NlDsW35ttyIrRuHyi6F0KlzsSp
+AiBDT8YLjNCUByVrD9jhoRbUy+t38fx9WbOWgRVxZ5xk2wB2AN3rHSt6DU+mIIuB
+rYFocH4ujp0B1VyIjT0RxM227L7MAAABWxp+x80AAAQDAEcwRQIgEz/5SC+JA5Ko
+0ivxGYf5XBCqjfcIrp2BpCVxyYA2ys0CIQC1kcCeihwwbiVFTjR8UecLaCd1l1ix
+nopZ9ljhG018+g==
+-----END SERVERINFOV2 FOR CT-----
diff --git a/util/libssl.num b/util/libssl.num
index a17ebbc..b4acb5d 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -449,3 +449,4 @@ SSL_get_record_padding_callback_arg     449	1_1_1	EXIST::FUNCTION:
 SSL_set_block_padding                   450	1_1_1	EXIST::FUNCTION:
 SSL_set_record_padding_callback_arg     451	1_1_1	EXIST::FUNCTION:
 SSL_CTX_set_record_padding_callback_arg 452	1_1_1	EXIST::FUNCTION:
+SSL_CTX_use_serverinfo_ex               453	1_1_1	EXIST::FUNCTION:


More information about the openssl-commits mailing list