Fix OCSP Status Request extension unbounded memory growth
authorMatt Caswell <matt@openssl.org>
Fri, 9 Sep 2016 09:08:45 +0000 (10:08 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 22 Sep 2016 08:28:07 +0000 (09:28 +0100)
A malicious client can send an excessively large OCSP Status Request
extension. If that client continually requests renegotiation,
sending a large OCSP Status Request extension each time, then there will
be unbounded memory growth on the server. This will eventually lead to a
Denial Of Service attack through memory exhaustion. Servers with a
default configuration are vulnerable even if they do not support OCSP.
Builds using the "no-ocsp" build time option are not affected.

I have also checked other extensions to see if they suffer from a similar
problem but I could not find any other issues.

CVE-2016-6304

Issue reported by Shi Lei.

Reviewed-by: Rich Salz <rsalz@openssl.org>
ssl/t1_lib.c

index b8f8fd22fe91dccabbea092bac0d66baa7500172..8c0a20f9631120584e7817e8c61f6c5bfdcdf928 100644 (file)
@@ -2030,6 +2030,22 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
                     (&extension, &responder_id_list))
                     return 0;
 
                     (&extension, &responder_id_list))
                     return 0;
 
+                /*
+                 * We remove any OCSP_RESPIDs from a previous handshake
+                 * to prevent unbounded memory growth - CVE-2016-6304
+                 */
+                sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids,
+                                        OCSP_RESPID_free);
+                if (PACKET_remaining(&responder_id_list) > 0) {
+                    s->tlsext_ocsp_ids = sk_OCSP_RESPID_new_null();
+                    if (s->tlsext_ocsp_ids == NULL) {
+                        *al = SSL_AD_INTERNAL_ERROR;
+                        return 0;
+                    }
+                } else {
+                    s->tlsext_ocsp_ids = NULL;
+                }
+
                 while (PACKET_remaining(&responder_id_list) > 0) {
                     OCSP_RESPID *id;
                     PACKET responder_id;
                 while (PACKET_remaining(&responder_id_list) > 0) {
                     OCSP_RESPID *id;
                     PACKET responder_id;
@@ -2041,13 +2057,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
                         return 0;
                     }
 
                         return 0;
                     }
 
-                    if (s->tlsext_ocsp_ids == NULL
-                        && (s->tlsext_ocsp_ids =
-                            sk_OCSP_RESPID_new_null()) == NULL) {
-                        *al = SSL_AD_INTERNAL_ERROR;
-                        return 0;
-                    }
-
                     id_data = PACKET_data(&responder_id);
                     id = d2i_OCSP_RESPID(NULL, &id_data,
                                          PACKET_remaining(&responder_id));
                     id_data = PACKET_data(&responder_id);
                     id = d2i_OCSP_RESPID(NULL, &id_data,
                                          PACKET_remaining(&responder_id));