[openssl-commits] [openssl] master update

Matt Caswell matt at openssl.org
Sun Dec 27 22:07:23 UTC 2015


The branch master has been updated
       via  b1931d432f4b53ceb2e2eacec09c2e32e043830b (commit)
       via  43c34894d703e3e5c2fc03bad3a78a1cf10d8ba5 (commit)
       via  80e339fd09ca32680e0c0cbcfa40d73212ea276d (commit)
       via  bb1aaab42880489729aeafea27d3569cce60c20b (commit)
       via  ef96e4a28fa98cdf44246baab9ec8cdb69914fd9 (commit)
      from  b22d71131aa01d371029908e3c2bce332fd77e70 (commit)


- Log -----------------------------------------------------------------
commit b1931d432f4b53ceb2e2eacec09c2e32e043830b
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Dec 10 10:44:30 2015 +0000

    Simplify calling of the OCSP callback
    
    Move all calls of the OCSP callback into one place, rather than repeating it
    in two different places.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>

commit 43c34894d703e3e5c2fc03bad3a78a1cf10d8ba5
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Nov 30 16:04:51 2015 +0000

    Add some documentation for the OCSP callback functions
    
    Describe the usage of the OCSP callback functions on both the client and
    the server side.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>

commit 80e339fd09ca32680e0c0cbcfa40d73212ea276d
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Nov 30 13:29:41 2015 +0000

    Ensure we don't call the OCSP callback if resuming a session
    
    It makes no sense to call the OCSP status callback if we are resuming a
    session because no certificates will be sent.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>

commit bb1aaab42880489729aeafea27d3569cce60c20b
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 5 14:31:11 2015 +0000

    Fix error when server does not send CertificateStatus message
    
    If a server sends the status_request extension then it may choose
    to send the CertificateStatus message. However this is optional.
    We were treating it as mandatory and the connection was failing.
    
    Thanks to BoringSSL for reporting this issue.
    
    RT#4120
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>

commit ef96e4a28fa98cdf44246baab9ec8cdb69914fd9
Author: Matt Caswell <matt at openssl.org>
Date:   Thu Nov 5 14:08:54 2015 +0000

    Add test for missing CertificateStatus message
    
    If the client sends a status_request extension in the ClientHello
    and the server responds with a status_request extension in the
    ServerHello then normally the server will also later send a
    CertificateStatus message. However this message is *optional* even
    if the extensions were sent. This adds a test to ensure that if
    the extensions are sent then we can still omit the message.
    
    Reviewed-by: Viktor Dukhovni <viktor at openssl.org>

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

Summary of changes:
 doc/ssl/SSL_CTX_set_tlsext_status_cb.pod           | 73 ++++++++++++++++++++++
 ssl/statem/statem_clnt.c                           | 50 ++++++++-------
 ssl/t1_lib.c                                       | 27 ++------
 ...test_sslskewith0p.t => 70-test_sslcertstatus.t} | 33 +++++-----
 util/TLSProxy/ClientHello.pm                       |  1 +
 5 files changed, 123 insertions(+), 61 deletions(-)
 create mode 100644 doc/ssl/SSL_CTX_set_tlsext_status_cb.pod
 copy test/recipes/{70-test_sslskewith0p.t => 70-test_sslcertstatus.t} (80%)

diff --git a/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod b/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod
new file mode 100644
index 0000000..b8147ba
--- /dev/null
+++ b/doc/ssl/SSL_CTX_set_tlsext_status_cb.pod
@@ -0,0 +1,73 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set_tlsext_status_cb, SSL_CTX_set_tlsext_status_arg,
+SSL_set_tlsext_status_type, SSL_get_tlsext_status_ocsp_resp,
+SSL_set_tlsext_status_ocsp_resp - OCSP Certificate Status Request functions
+
+=head1 SYNOPSIS
+
+ #include <openssl/tls1.h>
+
+ long SSL_CTX_set_tlsext_status_cb(SSL_CTX *ctx,
+                                   int (*callback)(SSL *, void *));
+ long SSL_CTX_set_tlsext_status_arg(SSL_CTX *ctx, void *arg);
+
+ long SSL_set_tlsext_status_type(SSL *s, int type);
+
+ long SSL_get_tlsext_status_ocsp_resp(ssl, unsigned char **resp);
+ long SSL_set_tlsext_status_ocsp_resp(ssl, unsigned char *resp, int len);
+
+=head1 DESCRIPTION
+
+A client application may request that a server send back an OCSP status response
+(also known as OCSP stapling). To do so the client should call the
+SSL_set_tlsext_status_type() function prior to the start of the handshake.
+Currently the only supported type is B<TLSEXT_STATUSTYPE_ocsp>. This value
+should be passed in the B<type> argument. The client should additionally provide
+a callback function to decide what to do with the returned OCSP response by
+calling SSL_CTX_set_tlsext_status_cb(). The callback function should determine
+whether the returned OCSP response is acceptable or not. The callback will be
+passed as an argument the value previously set via a call to
+SSL_CTX_set_tlsext_status_arg(). Note that the callback will not be called in
+the event of a handshake where session resumption occurs (because there are no
+Certificates exchanged in such a handshake).
+
+The response returned by the server can be obtained via a call to
+SSL_get_tlsext_status_ocsp_resp(). The value B<*resp> will be updated to point
+to the OCSP response data and the return value will be the length of that data.
+Typically a callback would obtain an OCSP_RESPONSE object from this data via a
+call to the d2i_OCSP_RESPONSE() function. If the server has not provided any
+response data then B<*resp> will be NULL and the return value from
+SSL_get_tlsext_status_ocsp_resp() will be -1.
+
+A server application must also call the SSL_CTX_set_tlsext_status_cb() function
+if it wants to be able to provide clients with OCSP Certificate Status
+responses. Typically the server callback would obtain the server certificate
+that is being sent back to the client via a call to SSL_get_certificate();
+obtain the OCSP response to be sent back; and then set that response data by
+calling SSL_set_tlsext_status_ocsp_resp(). A pointer to the response data should
+be provided in the B<resp> argument, and the length of that data should be in
+the B<len> argument.
+
+=head1 RETURN VALUES
+
+The callback when used on the client side should return a negative value on
+error; 0 if the response is not acceptable (in which case the handshake will
+fail) or a positive value if it is acceptable.
+
+The callback when used on the server side should return with either
+SSL_TLSEXT_ERR_OK (meaning that the OCSP response that has been set should be
+returned), SSL_TLSEXT_ERR_NOACK (meaning that an OCSP response should not be
+returned) or SSL_TLSEXT_ERR_ALERT_FATAL (meaning that a fatal error has
+occurred).
+
+SSL_CTX_set_tlsext_status_cb(), SSL_CTX_set_tlsext_status_arg(),
+SSL_set_tlsext_status_type() and SSL_set_tlsext_status_ocsp_resp() return 0 on
+error or 1 on success.
+
+SSL_get_tlsext_status_ocsp_resp() returns the length of the OCSP response data
+or -1 if there is no OCSP response data.
+
+=cut
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 46cb4b0..b14e6ed 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -303,12 +303,13 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
         break;
 
     case TLS_ST_CR_CERT:
-        if (s->tlsext_status_expected) {
-            if (mt == SSL3_MT_CERTIFICATE_STATUS) {
-                st->hand_state = TLS_ST_CR_CERT_STATUS;
-                return 1;
-            }
-            return 0;
+        /*
+         * The CertificateStatus message is optional even if
+         * |tlsext_status_expected| is set
+         */
+        if (s->tlsext_status_expected && mt == SSL3_MT_CERTIFICATE_STATUS) {
+            st->hand_state = TLS_ST_CR_CERT_STATUS;
+            return 1;
         }
         /* Fall through */
 
@@ -2155,7 +2156,6 @@ MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
         SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
         goto f_err;
     }
-    OPENSSL_free(s->tlsext_ocsp_resp);
     s->tlsext_ocsp_resp = OPENSSL_malloc(resplen);
     if (s->tlsext_ocsp_resp == NULL) {
         al = SSL_AD_INTERNAL_ERROR;
@@ -2168,20 +2168,6 @@ MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
         goto f_err;
     }
     s->tlsext_ocsp_resplen = resplen;
-    if (s->ctx->tlsext_status_cb) {
-        int ret;
-        ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
-        if (ret == 0) {
-            al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, SSL_R_INVALID_STATUS_RESPONSE);
-            goto f_err;
-        }
-        if (ret < 0) {
-            al = SSL_AD_INTERNAL_ERROR;
-            SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, ERR_R_MALLOC_FAILURE);
-            goto f_err;
-        }
-    }
     return MSG_PROCESS_CONTINUE_READING;
  f_err:
     ssl3_send_alert(s, SSL3_AL_FATAL, al);
@@ -2220,6 +2206,28 @@ MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
         return MSG_PROCESS_ERROR;
     }
 
+    /*
+     * Call the ocsp status callback if needed. The |tlsext_ocsp_resp| and
+     * |tlsext_ocsp_resplen| values will be set if we actually received a status
+     * message, or NULL and -1 otherwise
+     */
+    if (s->tlsext_status_type != -1 && s->ctx->tlsext_status_cb != NULL) {
+        int ret;
+        ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+        if (ret == 0) {
+            ssl3_send_alert(s, SSL3_AL_FATAL,
+                            SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
+            SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE,
+                   SSL_R_INVALID_STATUS_RESPONSE);
+            return MSG_PROCESS_ERROR;
+        }
+        if (ret < 0) {
+            ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+            SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, ERR_R_MALLOC_FAILURE);
+            return MSG_PROCESS_ERROR;
+        }
+    }
+
 #ifndef OPENSSL_NO_SCTP
     /* Only applies to renegotiation */
     if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index d9cfe27..73ad604 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -2848,29 +2848,12 @@ int ssl_check_serverhello_tlsext(SSL *s)
                                                        initial_ctx->tlsext_servername_arg);
 
     /*
-     * If we've requested certificate status and we wont get one tell the
-     * callback
+     * Ensure we get sensible values passed to tlsext_status_cb in the event
+     * that we don't receive a status message
      */
-    if ((s->tlsext_status_type != -1) && !(s->tlsext_status_expected)
-        && s->ctx && s->ctx->tlsext_status_cb) {
-        int r;
-        /*
-         * Set resp to NULL, resplen to -1 so callback knows there is no
-         * response.
-         */
-        OPENSSL_free(s->tlsext_ocsp_resp);
-        s->tlsext_ocsp_resp = NULL;
-        s->tlsext_ocsp_resplen = -1;
-        r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
-        if (r == 0) {
-            al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
-            ret = SSL_TLSEXT_ERR_ALERT_FATAL;
-        }
-        if (r < 0) {
-            al = SSL_AD_INTERNAL_ERROR;
-            ret = SSL_TLSEXT_ERR_ALERT_FATAL;
-        }
-    }
+    OPENSSL_free(s->tlsext_ocsp_resp);
+    s->tlsext_ocsp_resp = NULL;
+    s->tlsext_ocsp_resplen = -1;
 
     switch (ret) {
     case SSL_TLSEXT_ERR_ALERT_FATAL:
diff --git a/test/recipes/70-test_sslskewith0p.t b/test/recipes/70-test_sslcertstatus.t
similarity index 80%
copy from test/recipes/70-test_sslskewith0p.t
copy to test/recipes/70-test_sslcertstatus.t
index b3c5dc1..32e2680 100755
--- a/test/recipes/70-test_sslskewith0p.t
+++ b/test/recipes/70-test_sslcertstatus.t
@@ -54,50 +54,47 @@
 
 use strict;
 use OpenSSL::Test qw/:DEFAULT cmdstr top_file top_dir/;
-use OpenSSL::Test::Utils;
 use TLSProxy::Proxy;
 
-my $test_name = "test_sslskewith0p";
+my $test_name = "test_sslcertstatus";
 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 "";
-
-plan skip_all => "dh is not supported by this OpenSSL build"
-    if disabled("dh");
+        grep { /^SHARED_LIBS=/ }
+        do { local @ARGV = ( top_file("Makefile") ); <> })[0] ne "";
 
 $ENV{OPENSSL_ENGINES} = top_dir("engines");
 $ENV{OPENSSL_ia32cap} = '~0x200000200000000';
 my $proxy = TLSProxy::Proxy->new(
-    \&ske_0_p_filter,
+    \&certstatus_filter,
     cmdstr(app(["openssl"])),
     top_file("apps", "server.pem")
 );
 
 plan tests => 1;
 
-#We must use an anon DHE cipher for this test
-$proxy->cipherc('ADH-AES128-SHA:@SECLEVEL=0');
-$proxy->ciphers('ADH-AES128-SHA:@SECLEVEL=0');
-
+#Test 1: Sending a status_request extension in both ClientHello and ServerHello
+#but then omitting the CertificateStatus message is valid
+$proxy->clientflags("-status");
 $proxy->start();
-ok(TLSProxy::Message->fail, "ServerKeyExchange with 0 p");
+ok(TLSProxy::Message->success, "Missing CertificateStatus message");
 
-sub ske_0_p_filter
+sub certstatus_filter
 {
     my $proxy = shift;
 
-    # We're only interested in the SKE - always in flight 1
+    # We're only interested in the initial ServerHello
     if ($proxy->flight != 1) {
         return;
     }
 
     foreach my $message (@{$proxy->message_list}) {
-        if ($message->mt == TLSProxy::Message::MT_SERVER_KEY_EXCHANGE) {
-            #Set p to a value of 0
-            $message->p(pack('C', 0));
+        if ($message->mt == TLSProxy::Message::MT_SERVER_HELLO) {
+            #Add the status_request to the ServerHello even though we are not
+            #going to send a CertificateStatus message
+            $message->set_extension(TLSProxy::ClientHello::EXT_STATUS_REQUEST,
+                                    "");
 
             $message->repack();
         }
diff --git a/util/TLSProxy/ClientHello.pm b/util/TLSProxy/ClientHello.pm
index c6f3c3f..7266112 100644
--- a/util/TLSProxy/ClientHello.pm
+++ b/util/TLSProxy/ClientHello.pm
@@ -58,6 +58,7 @@ package TLSProxy::ClientHello;
 use parent 'TLSProxy::Message';
 
 use constant {
+    EXT_STATUS_REQUEST => 5,
     EXT_ENCRYPT_THEN_MAC => 22,
     EXT_EXTENDED_MASTER_SECRET => 23,
     EXT_SESSION_TICKET => 35


More information about the openssl-commits mailing list