diff options
Diffstat (limited to 'ssl/t1_lib.c')
| -rw-r--r-- | ssl/t1_lib.c | 106 | 
1 files changed, 66 insertions, 40 deletions
| diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c index dd5bd0050d89f..7831046b92613 100644 --- a/ssl/t1_lib.c +++ b/ssl/t1_lib.c @@ -1429,7 +1429,7 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,      }   skip_ext: -    if (SSL_USE_SIGALGS(s)) { +    if (SSL_CLIENT_USE_SIGALGS(s)) {          size_t salglen;          const unsigned char *salg;          salglen = tls12_get_psigalgs(s, &salg); @@ -1867,11 +1867,11 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,          0x02, 0x03,             /* SHA-1/ECDSA */      }; -    if (data >= (limit - 2)) +    if (limit - data <= 2)          return;      data += 2; -    if (data > (limit - 4)) +    if (limit - data < 4)          return;      n2s(data, type);      n2s(data, size); @@ -1879,7 +1879,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,      if (type != TLSEXT_TYPE_server_name)          return; -    if (data + size > limit) +    if (limit - data < size)          return;      data += size; @@ -1887,7 +1887,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,          const size_t len1 = sizeof(kSafariExtensionsBlock);          const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock); -        if (data + len1 + len2 != limit) +        if (limit - data != (int)(len1 + len2))              return;          if (memcmp(data, kSafariExtensionsBlock, len1) != 0)              return; @@ -1896,7 +1896,7 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,      } else {          const size_t len = sizeof(kSafariExtensionsBlock); -        if (data + len != limit) +        if (limit - data != (int)(len))              return;          if (memcmp(data, kSafariExtensionsBlock, len) != 0)              return; @@ -2053,19 +2053,19 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,      if (data == limit)          goto ri_check; -    if (data > (limit - 2)) +    if (limit - data < 2)          goto err;      n2s(data, len); -    if (data + len != limit) +    if (limit - data != len)          goto err; -    while (data <= (limit - 4)) { +    while (limit - data >= 4) {          n2s(data, type);          n2s(data, size); -        if (data + size > (limit)) +        if (limit - data < size)              goto err;  # if 0          fprintf(stderr, "Received extension type %d size %d\n", type, size); @@ -2316,6 +2316,23 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,                  size -= 2;                  if (dsize > size)                      goto err; + +                /* +                 * 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 (dsize > 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 (dsize > 0) {                      OCSP_RESPID *id;                      int idsize; @@ -2335,13 +2352,6 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,                          OCSP_RESPID_free(id);                          goto err;                      } -                    if (!s->tlsext_ocsp_ids -                        && !(s->tlsext_ocsp_ids = -                             sk_OCSP_RESPID_new_null())) { -                        OCSP_RESPID_free(id); -                        *al = SSL_AD_INTERNAL_ERROR; -                        return 0; -                    }                      if (!sk_OCSP_RESPID_push(s->tlsext_ocsp_ids, id)) {                          OCSP_RESPID_free(id);                          *al = SSL_AD_INTERNAL_ERROR; @@ -2472,18 +2482,18 @@ static int ssl_scan_clienthello_custom_tlsext(SSL *s,      if (s->hit || s->cert->srv_ext.meths_count == 0)          return 1; -    if (data >= limit - 2) +    if (limit - data <= 2)          return 1;      n2s(data, len); -    if (data > limit - len) +    if (limit - data < len)          return 1; -    while (data <= limit - 4) { +    while (limit - data >= 4) {          n2s(data, type);          n2s(data, size); -        if (data + size > limit) +        if (limit - data < size)              return 1;          if (custom_ext_parse(s, 1 /* server */ , type, data, size, al) <= 0)              return 0; @@ -2569,20 +2579,20 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p,                               SSL_TLSEXT_HB_DONT_SEND_REQUESTS);  # endif -    if (data >= (d + n - 2)) +    if ((d + n) - data <= 2)          goto ri_check;      n2s(data, length); -    if (data + length != d + n) { +    if ((d + n) - data != length) {          *al = SSL_AD_DECODE_ERROR;          return 0;      } -    while (data <= (d + n - 4)) { +    while ((d + n) - data >= 4) {          n2s(data, type);          n2s(data, size); -        if (data + size > (d + n)) +        if ((d + n) - data < size)              goto ri_check;          if (s->tlsext_debug_cb) @@ -2712,6 +2722,11 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p,                  *al = TLS1_AD_INTERNAL_ERROR;                  return 0;              } +            /* +             * Could be non-NULL if server has sent multiple NPN extensions in +             * a single Serverhello +             */ +            OPENSSL_free(s->next_proto_negotiated);              s->next_proto_negotiated = OPENSSL_malloc(selected_len);              if (!s->next_proto_negotiated) {                  *al = TLS1_AD_INTERNAL_ERROR; @@ -3307,29 +3322,33 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,      /* Skip past DTLS cookie */      if (SSL_IS_DTLS(s)) {          i = *(p++); -        p += i; -        if (p >= limit) + +        if (limit - p <= i)              return -1; + +        p += i;      }      /* Skip past cipher list */      n2s(p, i); -    p += i; -    if (p >= limit) +    if (limit - p <= i)          return -1; +    p += i; +      /* Skip past compression algorithm list */      i = *(p++); -    p += i; -    if (p > limit) +    if (limit - p < i)          return -1; +    p += i; +      /* Now at start of extensions */ -    if ((p + 2) >= limit) +    if (limit - p <= 2)          return 0;      n2s(p, i); -    while ((p + 4) <= limit) { +    while (limit - p >= 4) {          unsigned short type, size;          n2s(p, type);          n2s(p, size); -        if (p + size > limit) +        if (limit - p < size)              return 0;          if (type == TLSEXT_TYPE_session_ticket) {              int r; @@ -3397,9 +3416,7 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,      HMAC_CTX hctx;      EVP_CIPHER_CTX ctx;      SSL_CTX *tctx = s->initial_ctx; -    /* Need at least keyname + iv + some encrypted data */ -    if (eticklen < 48) -        return 2; +      /* Initialize session ticket encryption and HMAC contexts */      HMAC_CTX_init(&hctx);      EVP_CIPHER_CTX_init(&ctx); @@ -3433,6 +3450,13 @@ static int tls_decrypt_ticket(SSL *s, const unsigned char *etick,      if (mlen < 0) {          goto err;      } +    /* Sanity check ticket length: must exceed keyname + IV + HMAC */ +    if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) { +        HMAC_CTX_cleanup(&hctx); +        EVP_CIPHER_CTX_cleanup(&ctx); +        return 2; +    } +      eticklen -= mlen;      /* Check HMAC of encrypted ticket */      if (HMAC_Update(&hctx, etick, eticklen) <= 0 @@ -3902,7 +3926,7 @@ int tls1_process_heartbeat(SSL *s)          memcpy(bp, pl, payload);          bp += payload;          /* Random padding */ -        if (RAND_pseudo_bytes(bp, padding) < 0) { +        if (RAND_bytes(bp, padding) <= 0) {              OPENSSL_free(buffer);              return -1;          } @@ -3980,6 +4004,8 @@ int tls1_heartbeat(SSL *s)       *  - Padding       */      buf = OPENSSL_malloc(1 + 2 + payload + padding); +    if (buf == NULL) +        return -1;      p = buf;      /* Message Type */      *p++ = TLS1_HB_REQUEST; @@ -3988,13 +4014,13 @@ int tls1_heartbeat(SSL *s)      /* Sequence number */      s2n(s->tlsext_hb_seq, p);      /* 16 random bytes */ -    if (RAND_pseudo_bytes(p, 16) < 0) { +    if (RAND_bytes(p, 16) <= 0) {          SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);          goto err;      }      p += 16;      /* Random padding */ -    if (RAND_pseudo_bytes(p, padding) < 0) { +    if (RAND_bytes(p, padding) <= 0) {          SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);          goto err;      } | 
