Module Name: src Committed By: drochner Date: Thu Jan 5 17:32:02 UTC 2012
Modified Files: src/crypto/external/bsd/openssl/dist/crypto/x509v3: v3_addr.c src/crypto/external/bsd/openssl/dist/engines/ccgost: gost2001_keyx.c gost94_keyx.c src/crypto/external/bsd/openssl/dist/ssl: d1_pkt.c s3_enc.c s3_srvr.c ssl.h ssl3.h ssl_err.c Log Message: pull in some patches from upstream CVS, following secadv_20120104.txt: -rev.21964 for DTLS Plaintext Recovery Attack (CVE-2011-4108) -rev.21961 for Uninitialized SSL 3.0 Padding (CVE-2011-4576) -rev.21456+21954 for Malformed RFC 3779 Data Can Cause Assertion Failures (CVE-2011-4577) (rev.21456 is not mentioned in the advisory, but there is code overlap) -rev.21958 for SGC Restart DoS Attack (CVE-2011-4619) -rev.21956 for Invalid GOST parameters DoS Attack (CVE-2012-0027) To generate a diff of this commit: cvs rdiff -u -r1.1.1.2 -r1.2 \ src/crypto/external/bsd/openssl/dist/crypto/x509v3/v3_addr.c cvs rdiff -u -r1.1.1.1 -r1.2 \ src/crypto/external/bsd/openssl/dist/engines/ccgost/gost2001_keyx.c \ src/crypto/external/bsd/openssl/dist/engines/ccgost/gost94_keyx.c cvs rdiff -u -r1.1.1.4 -r1.2 \ src/crypto/external/bsd/openssl/dist/ssl/d1_pkt.c \ src/crypto/external/bsd/openssl/dist/ssl/ssl.h \ src/crypto/external/bsd/openssl/dist/ssl/ssl_err.c cvs rdiff -u -r1.3 -r1.4 src/crypto/external/bsd/openssl/dist/ssl/s3_enc.c cvs rdiff -u -r1.8 -r1.9 src/crypto/external/bsd/openssl/dist/ssl/s3_srvr.c cvs rdiff -u -r1.1.1.3 -r1.2 src/crypto/external/bsd/openssl/dist/ssl/ssl3.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/crypto/external/bsd/openssl/dist/crypto/x509v3/v3_addr.c diff -u src/crypto/external/bsd/openssl/dist/crypto/x509v3/v3_addr.c:1.1.1.2 src/crypto/external/bsd/openssl/dist/crypto/x509v3/v3_addr.c:1.2 --- src/crypto/external/bsd/openssl/dist/crypto/x509v3/v3_addr.c:1.1.1.2 Sun Jun 5 15:00:02 2011 +++ src/crypto/external/bsd/openssl/dist/crypto/x509v3/v3_addr.c Thu Jan 5 17:32:02 2012 @@ -142,12 +142,13 @@ unsigned int v3_addr_get_afi(const IPAdd * Expand the bitstring form of an address into a raw byte array. * At the moment this is coded for simplicity, not speed. */ -static void addr_expand(unsigned char *addr, +static int addr_expand(unsigned char *addr, const ASN1_BIT_STRING *bs, const int length, const unsigned char fill) { - OPENSSL_assert(bs->length >= 0 && bs->length <= length); + if (bs->length < 0 || bs->length > length) + return 0; if (bs->length > 0) { memcpy(addr, bs->data, bs->length); if ((bs->flags & 7) != 0) { @@ -159,6 +160,7 @@ static void addr_expand(unsigned char *a } } memset(addr + bs->length, fill, length - bs->length); + return 1; } /* @@ -181,15 +183,13 @@ static int i2r_address(BIO *out, return 0; switch (afi) { case IANA_AFI_IPV4: - if (bs->length > 4) + if (!addr_expand(addr, bs, 4, fill)) return 0; - addr_expand(addr, bs, 4, fill); BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); break; case IANA_AFI_IPV6: - if (bs->length > 16) + if (!addr_expand(addr, bs, 16, fill)) return 0; - addr_expand(addr, bs, 16, fill); for (n = 16; n > 1 && addr[n-1] == 0x00 && addr[n-2] == 0x00; n -= 2) ; for (i = 0; i < n; i += 2) @@ -315,6 +315,12 @@ static int i2r_IPAddrBlocks(const X509V3 /* * Sort comparison function for a sequence of IPAddressOrRange * elements. + * + * There's no sane answer we can give if addr_expand() fails, and an + * assertion failure on externally supplied data is seriously uncool, + * so we just arbitrarily declare that if given invalid inputs this + * function returns -1. If this messes up your preferred sort order + * for garbage input, tough noogies. */ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, const IPAddressOrRange *b, @@ -326,22 +332,26 @@ static int IPAddressOrRange_cmp(const IP switch (a->type) { case IPAddressOrRange_addressPrefix: - addr_expand(addr_a, a->u.addressPrefix, length, 0x00); + if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) + return -1; prefixlen_a = addr_prefixlen(a->u.addressPrefix); break; case IPAddressOrRange_addressRange: - addr_expand(addr_a, a->u.addressRange->min, length, 0x00); + if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) + return -1; prefixlen_a = length * 8; break; } switch (b->type) { case IPAddressOrRange_addressPrefix: - addr_expand(addr_b, b->u.addressPrefix, length, 0x00); + if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) + return -1; prefixlen_b = addr_prefixlen(b->u.addressPrefix); break; case IPAddressOrRange_addressRange: - addr_expand(addr_b, b->u.addressRange->min, length, 0x00); + if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) + return -1; prefixlen_b = length * 8; break; } @@ -383,6 +393,7 @@ static int range_should_be_prefix(const unsigned char mask; int i, j; + OPENSSL_assert(memcmp(min, max, length) <= 0); for (i = 0; i < length && min[i] == max[i]; i++) ; for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) @@ -656,22 +667,22 @@ int v3_addr_add_range(IPAddrBlocks *addr /* * Extract min and max values from an IPAddressOrRange. */ -static void extract_min_max(IPAddressOrRange *aor, +static int extract_min_max(IPAddressOrRange *aor, unsigned char *min, unsigned char *max, int length) { - OPENSSL_assert(aor != NULL && min != NULL && max != NULL); + if (aor == NULL || min == NULL || max == NULL) + return 0; switch (aor->type) { case IPAddressOrRange_addressPrefix: - addr_expand(min, aor->u.addressPrefix, length, 0x00); - addr_expand(max, aor->u.addressPrefix, length, 0xFF); - return; + return (addr_expand(min, aor->u.addressPrefix, length, 0x00) && + addr_expand(max, aor->u.addressPrefix, length, 0xFF)); case IPAddressOrRange_addressRange: - addr_expand(min, aor->u.addressRange->min, length, 0x00); - addr_expand(max, aor->u.addressRange->max, length, 0xFF); - return; + return (addr_expand(min, aor->u.addressRange->min, length, 0x00) && + addr_expand(max, aor->u.addressRange->max, length, 0xFF)); } + return 0; } /* @@ -687,9 +698,10 @@ int v3_addr_get_range(IPAddressOrRange * if (aor == NULL || min == NULL || max == NULL || afi_length == 0 || length < afi_length || (aor->type != IPAddressOrRange_addressPrefix && - aor->type != IPAddressOrRange_addressRange)) + aor->type != IPAddressOrRange_addressRange) || + !extract_min_max(aor, min, max, afi_length)) return 0; - extract_min_max(aor, min, max, afi_length); + return afi_length; } @@ -771,8 +783,9 @@ int v3_addr_is_canonical(IPAddrBlocks *a IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); - extract_min_max(a, a_min, a_max, length); - extract_min_max(b, b_min, b_max, length); + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; /* * Punt misordered list, overlapping start, or inverted range. @@ -800,14 +813,17 @@ int v3_addr_is_canonical(IPAddrBlocks *a } /* - * Check final range to see if it should be a prefix. + * Check range to see if it's inverted or should be a + * prefix. */ j = sk_IPAddressOrRange_num(aors) - 1; { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); - if (a->type == IPAddressOrRange_addressRange) { - extract_min_max(a, a_min, a_max, length); - if (range_should_be_prefix(a_min, a_max, length) >= 0) + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + if (!extract_min_max(a, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0 || + range_should_be_prefix(a_min, a_max, length) >= 0) return 0; } } @@ -841,8 +857,16 @@ static int IPAddressOrRanges_canonize(IP unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; - extract_min_max(a, a_min, a_max, length); - extract_min_max(b, b_min, b_max, length); + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; + + /* + * Punt inverted ranges. + */ + if (memcmp(a_min, a_max, length) > 0 || + memcmp(b_min, b_max, length) > 0) + return 0; /* * Punt overlaps. @@ -869,6 +893,20 @@ static int IPAddressOrRanges_canonize(IP } } + /* + * Check for inverted final range. + */ + j = sk_IPAddressOrRange_num(aors) - 1; + { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + extract_min_max(a, a_min, a_max, length); + if (memcmp(a_min, a_max, length) > 0) + return 0; + } + } + return 1; } @@ -1017,6 +1055,11 @@ static void *v2i_IPAddrBlocks(const stru X509V3_conf_err(val); goto err; } + if (memcmp(min, max, length_from_afi(afi)) > 0) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } if (!v3_addr_add_range(addr, afi, safi, min, max)) { X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); goto err; @@ -1102,13 +1145,15 @@ static int addr_contains(IPAddressOrRang p = 0; for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { - extract_min_max(sk_IPAddressOrRange_value(child, c), - c_min, c_max, length); + if (!extract_min_max(sk_IPAddressOrRange_value(child, c), + c_min, c_max, length)) + return -1; for (;; p++) { if (p >= sk_IPAddressOrRange_num(parent)) return 0; - extract_min_max(sk_IPAddressOrRange_value(parent, p), - p_min, p_max, length); + if (!extract_min_max(sk_IPAddressOrRange_value(parent, p), + p_min, p_max, length)) + return 0; if (memcmp(p_max, c_max, length) < 0) continue; if (memcmp(p_min, c_min, length) > 0) Index: src/crypto/external/bsd/openssl/dist/engines/ccgost/gost2001_keyx.c diff -u src/crypto/external/bsd/openssl/dist/engines/ccgost/gost2001_keyx.c:1.1.1.1 src/crypto/external/bsd/openssl/dist/engines/ccgost/gost2001_keyx.c:1.2 --- src/crypto/external/bsd/openssl/dist/engines/ccgost/gost2001_keyx.c:1.1.1.1 Sun Jul 19 23:05:33 2009 +++ src/crypto/external/bsd/openssl/dist/engines/ccgost/gost2001_keyx.c Thu Jan 5 17:32:02 2012 @@ -280,6 +280,10 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX * } param = get_encryption_params(gkt->key_agreement_info->cipher); + if(!param){ + goto err; + } + gost_init(&ctx,param->sblock); OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8); memcpy(wrappedKey,gkt->key_agreement_info->eph_iv->data,8); Index: src/crypto/external/bsd/openssl/dist/engines/ccgost/gost94_keyx.c diff -u src/crypto/external/bsd/openssl/dist/engines/ccgost/gost94_keyx.c:1.1.1.1 src/crypto/external/bsd/openssl/dist/engines/ccgost/gost94_keyx.c:1.2 --- src/crypto/external/bsd/openssl/dist/engines/ccgost/gost94_keyx.c:1.1.1.1 Sun Jul 19 23:05:33 2009 +++ src/crypto/external/bsd/openssl/dist/engines/ccgost/gost94_keyx.c Thu Jan 5 17:32:02 2012 @@ -261,6 +261,10 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX * } param = get_encryption_params(gkt->key_agreement_info->cipher); + if(!param){ + goto err; + } + gost_init(&cctx,param->sblock); OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8); memcpy(wrappedKey,gkt->key_agreement_info->eph_iv->data,8); Index: src/crypto/external/bsd/openssl/dist/ssl/d1_pkt.c diff -u src/crypto/external/bsd/openssl/dist/ssl/d1_pkt.c:1.1.1.4 src/crypto/external/bsd/openssl/dist/ssl/d1_pkt.c:1.2 --- src/crypto/external/bsd/openssl/dist/ssl/d1_pkt.c:1.1.1.4 Sun Jun 5 15:00:32 2011 +++ src/crypto/external/bsd/openssl/dist/ssl/d1_pkt.c Thu Jan 5 17:32:02 2012 @@ -375,6 +375,7 @@ dtls1_process_record(SSL *s) SSL3_RECORD *rr; unsigned int mac_size; unsigned char md[EVP_MAX_MD_SIZE]; + int decryption_failed_or_bad_record_mac = 0; rr= &(s->s3->rrec); @@ -445,7 +446,7 @@ printf("\n"); SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); goto f_err; #else - goto err; + decryption_failed_or_bad_record_mac = 1; #endif } /* check the MAC for rr->input (it's in mac_size bytes at the tail) */ @@ -456,17 +457,25 @@ printf("\n"); SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT); goto f_err; #else - goto err; + decryption_failed_or_bad_record_mac = 1; #endif } rr->length-=mac_size; i=s->method->ssl3_enc->mac(s,md,0); if (i < 0 || memcmp(md,&(rr->data[rr->length]),mac_size) != 0) { - goto err; + decryption_failed_or_bad_record_mac = 1; } } + if (decryption_failed_or_bad_record_mac) + { + /* decryption failed, silently discard message */ + rr->length = 0; + s->packet_length = 0; + goto err; + } + /* r->length is now just compressed */ if (s->expand != NULL) { Index: src/crypto/external/bsd/openssl/dist/ssl/ssl.h diff -u src/crypto/external/bsd/openssl/dist/ssl/ssl.h:1.1.1.4 src/crypto/external/bsd/openssl/dist/ssl/ssl.h:1.2 --- src/crypto/external/bsd/openssl/dist/ssl/ssl.h:1.1.1.4 Sun Jun 5 15:00:44 2011 +++ src/crypto/external/bsd/openssl/dist/ssl/ssl.h Thu Jan 5 17:32:02 2012 @@ -2024,6 +2024,7 @@ void ERR_load_SSL_strings(void); #define SSL_F_SSL3_CALLBACK_CTRL 233 #define SSL_F_SSL3_CHANGE_CIPHER_STATE 129 #define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130 +#define SSL_F_SSL3_CHECK_CLIENT_HELLO 315 #define SSL_F_SSL3_CLIENT_HELLO 131 #define SSL_F_SSL3_CONNECT 132 #define SSL_F_SSL3_CTRL 213 @@ -2291,6 +2292,7 @@ void ERR_load_SSL_strings(void); #define SSL_R_MISSING_TMP_RSA_KEY 172 #define SSL_R_MISSING_TMP_RSA_PKEY 173 #define SSL_R_MISSING_VERIFY_MESSAGE 174 +#define SSL_R_MULTIPLE_SGC_RESTARTS 370 #define SSL_R_NON_SSLV2_INITIAL_PACKET 175 #define SSL_R_NO_CERTIFICATES_RETURNED 176 #define SSL_R_NO_CERTIFICATE_ASSIGNED 177 Index: src/crypto/external/bsd/openssl/dist/ssl/ssl_err.c diff -u src/crypto/external/bsd/openssl/dist/ssl/ssl_err.c:1.1.1.4 src/crypto/external/bsd/openssl/dist/ssl/ssl_err.c:1.2 --- src/crypto/external/bsd/openssl/dist/ssl/ssl_err.c:1.1.1.4 Sun Jun 5 15:00:47 2011 +++ src/crypto/external/bsd/openssl/dist/ssl/ssl_err.c Thu Jan 5 17:32:02 2012 @@ -137,6 +137,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_FUNC(SSL_F_SSL3_CALLBACK_CTRL), "SSL3_CALLBACK_CTRL"}, {ERR_FUNC(SSL_F_SSL3_CHANGE_CIPHER_STATE), "SSL3_CHANGE_CIPHER_STATE"}, {ERR_FUNC(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM), "SSL3_CHECK_CERT_AND_ALGORITHM"}, +{ERR_FUNC(SSL_F_SSL3_CHECK_CLIENT_HELLO), "SSL3_CHECK_CLIENT_HELLO"}, {ERR_FUNC(SSL_F_SSL3_CLIENT_HELLO), "SSL3_CLIENT_HELLO"}, {ERR_FUNC(SSL_F_SSL3_CONNECT), "SSL3_CONNECT"}, {ERR_FUNC(SSL_F_SSL3_CTRL), "SSL3_CTRL"}, @@ -407,6 +408,7 @@ static ERR_STRING_DATA SSL_str_reasons[] {ERR_REASON(SSL_R_MISSING_TMP_RSA_KEY) ,"missing tmp rsa key"}, {ERR_REASON(SSL_R_MISSING_TMP_RSA_PKEY) ,"missing tmp rsa pkey"}, {ERR_REASON(SSL_R_MISSING_VERIFY_MESSAGE),"missing verify message"}, +{ERR_REASON(SSL_R_MULTIPLE_SGC_RESTARTS) ,"multiple sgc restarts"}, {ERR_REASON(SSL_R_NON_SSLV2_INITIAL_PACKET),"non sslv2 initial packet"}, {ERR_REASON(SSL_R_NO_CERTIFICATES_RETURNED),"no certificates returned"}, {ERR_REASON(SSL_R_NO_CERTIFICATE_ASSIGNED),"no certificate assigned"}, Index: src/crypto/external/bsd/openssl/dist/ssl/s3_enc.c diff -u src/crypto/external/bsd/openssl/dist/ssl/s3_enc.c:1.3 src/crypto/external/bsd/openssl/dist/ssl/s3_enc.c:1.4 --- src/crypto/external/bsd/openssl/dist/ssl/s3_enc.c:1.3 Sun Jun 5 23:09:48 2011 +++ src/crypto/external/bsd/openssl/dist/ssl/s3_enc.c Thu Jan 5 17:32:02 2012 @@ -512,6 +512,9 @@ int ssl3_enc(SSL *s, int send) /* we need to add 'i-1' padding bytes */ l+=i; + /* the last of these zero bytes will be overwritten + * with the padding length. */ + memset(&rec->input[rec->length], 0, i); rec->length+=i; rec->input[l-1]=(i-1); } Index: src/crypto/external/bsd/openssl/dist/ssl/s3_srvr.c diff -u src/crypto/external/bsd/openssl/dist/ssl/s3_srvr.c:1.8 src/crypto/external/bsd/openssl/dist/ssl/s3_srvr.c:1.9 --- src/crypto/external/bsd/openssl/dist/ssl/s3_srvr.c:1.8 Thu Jul 7 18:11:19 2011 +++ src/crypto/external/bsd/openssl/dist/ssl/s3_srvr.c Thu Jan 5 17:32:02 2012 @@ -287,6 +287,7 @@ int ssl3_accept(SSL *s) } s->init_num=0; + s->s3->flags &= ~SSL3_FLAGS_SGC_RESTART_DONE; if (s->state != SSL_ST_RENEGOTIATE) { @@ -836,6 +837,14 @@ int ssl3_check_client_hello(SSL *s) int ok; long n; + /* We only allow the client to restart the handshake once per + * negotiation. */ + if (s->s3->flags & SSL3_FLAGS_SGC_RESTART_DONE) + { + SSLerr(SSL_F_SSL3_CHECK_CLIENT_HELLO, SSL_R_MULTIPLE_SGC_RESTARTS); + return -1; + } + /* this function is called when we really expect a Certificate message, * so permit appropriate message length */ n=s->method->ssl_get_message(s, @@ -859,6 +868,7 @@ int ssl3_check_client_hello(SSL *s) s->s3->tmp.dh = NULL; } #endif + s->s3->flags |= SSL3_FLAGS_SGC_RESTART_DONE; return 2; } return 1; Index: src/crypto/external/bsd/openssl/dist/ssl/ssl3.h diff -u src/crypto/external/bsd/openssl/dist/ssl/ssl3.h:1.1.1.3 src/crypto/external/bsd/openssl/dist/ssl/ssl3.h:1.2 --- src/crypto/external/bsd/openssl/dist/ssl/ssl3.h:1.1.1.3 Sun Jun 5 15:00:45 2011 +++ src/crypto/external/bsd/openssl/dist/ssl/ssl3.h Thu Jan 5 17:32:02 2012 @@ -384,6 +384,17 @@ typedef struct ssl3_buffer_st #define TLS1_FLAGS_TLS_PADDING_BUG 0x0008 #define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010 #define TLS1_FLAGS_KEEP_HANDSHAKE 0x0020 + +/* SSL3_FLAGS_SGC_RESTART_DONE is set when we + * restart a handshake because of MS SGC and so prevents us + * from restarting the handshake in a loop. It's reset on a + * renegotiation, so effectively limits the client to one restart + * per negotiation. This limits the possibility of a DDoS + * attack where the client handshakes in a loop using SGC to + * restart. Servers which permit renegotiation can still be + * effected, but we can't prevent that. + */ +#define SSL3_FLAGS_SGC_RESTART_DONE 0x0040 #ifndef OPENSSL_NO_SSL_INTERN