diff options
author | delphij <delphij@FreeBSD.org> | 2015-06-12 07:23:55 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2015-06-12 07:23:55 +0000 |
commit | 17b1c22cf566ffc540a06c72a7e24903d70bdbbc (patch) | |
tree | eaf6fd09e0241c3694090ffd493ceed2d38ba00d /crypto/openssl/ssl | |
parent | 1c7c9a70bbeba057be18a74724e6575871e447fb (diff) | |
download | FreeBSD-src-17b1c22cf566ffc540a06c72a7e24903d70bdbbc.zip FreeBSD-src-17b1c22cf566ffc540a06c72a7e24903d70bdbbc.tar.gz |
Fix OpenSSL multiple vulnerabilities.
Security: FreeBSD-SA-15:10.openssl
Approved by: so
Diffstat (limited to 'crypto/openssl/ssl')
-rw-r--r-- | crypto/openssl/ssl/d1_both.c | 33 | ||||
-rw-r--r-- | crypto/openssl/ssl/d1_lib.c | 3 | ||||
-rw-r--r-- | crypto/openssl/ssl/d1_pkt.c | 2 | ||||
-rw-r--r-- | crypto/openssl/ssl/s3_cbc.c | 2 | ||||
-rw-r--r-- | crypto/openssl/ssl/s3_clnt.c | 165 | ||||
-rw-r--r-- | crypto/openssl/ssl/s3_srvr.c | 21 | ||||
-rw-r--r-- | crypto/openssl/ssl/ssl.h | 2 | ||||
-rw-r--r-- | crypto/openssl/ssl/ssl_err.c | 2 | ||||
-rw-r--r-- | crypto/openssl/ssl/ssl_locl.h | 1 | ||||
-rw-r--r-- | crypto/openssl/ssl/ssl_sess.c | 124 | ||||
-rw-r--r-- | crypto/openssl/ssl/t1_lib.c | 133 |
11 files changed, 336 insertions, 152 deletions
diff --git a/crypto/openssl/ssl/d1_both.c b/crypto/openssl/ssl/d1_both.c index 1b9d64b..f08bf36 100644 --- a/crypto/openssl/ssl/d1_both.c +++ b/crypto/openssl/ssl/d1_both.c @@ -481,6 +481,12 @@ again: else if ( i <= 0 && !*ok) return i; + if (mt >= 0 && s->s3->tmp.message_type != mt) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_DTLS1_GET_MESSAGE, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + p = (unsigned char *)s->init_buf->data; msg_len = msg_hdr->msg_len; @@ -869,6 +875,20 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) /* parse the message fragment header */ dtls1_get_message_header(wire, &msg_hdr); + len = msg_hdr.msg_len; + frag_off = msg_hdr.frag_off; + frag_len = msg_hdr.frag_len; + + /* + * We must have at least frag_len bytes left in the record to be read. + * Fragments must not span records. + */ + if (frag_len > s->s3->rrec.length) { + al = SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT, SSL_R_BAD_LENGTH); + goto f_err; + } + /* * if this is a future (or stale) message it gets buffered * (or dropped)--no further processing at this time @@ -878,10 +898,6 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) if (msg_hdr.seq != s->d1->handshake_read_seq && !(s->d1->listen && msg_hdr.seq == 1)) return dtls1_process_out_of_seq_message(s, &msg_hdr, ok); - len = msg_hdr.msg_len; - frag_off = msg_hdr.frag_off; - frag_len = msg_hdr.frag_len; - if (frag_len && frag_len < len) return dtls1_reassemble_fragment(s, &msg_hdr, ok); @@ -913,16 +929,16 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) if ((al=dtls1_preprocess_fragment(s,&msg_hdr,max))) goto f_err; - /* XDTLS: ressurect this when restart is in place */ - s->state=stn; - if ( frag_len > 0) { unsigned char *p=(unsigned char *)s->init_buf->data+DTLS1_HM_HEADER_LENGTH; i=s->method->ssl_read_bytes(s,SSL3_RT_HANDSHAKE, &p[frag_off],frag_len,0); - /* XDTLS: fix this--message fragments cannot span multiple packets */ + /* + * This shouldn't ever fail due to NBIO because we already checked + * that we have enough data in the record + */ if (i <= 0) { s->rwstate=SSL_READING; @@ -943,6 +959,7 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) } *ok = 1; + s->state = stn; /* Note that s->init_num is *not* used as current offset in * s->init_buf->data, but as a counter summing up fragments' diff --git a/crypto/openssl/ssl/d1_lib.c b/crypto/openssl/ssl/d1_lib.c index 14337b31..48de079 100644 --- a/crypto/openssl/ssl/d1_lib.c +++ b/crypto/openssl/ssl/d1_lib.c @@ -509,6 +509,9 @@ int dtls1_listen(SSL *s, struct sockaddr *client) { int ret; + /* Ensure there is no state left over from a previous invocation */ + SSL_clear(s); + SSL_set_options(s, SSL_OP_COOKIE_EXCHANGE); s->d1->listen = 1; diff --git a/crypto/openssl/ssl/d1_pkt.c b/crypto/openssl/ssl/d1_pkt.c index 0059fe2..bce8619 100644 --- a/crypto/openssl/ssl/d1_pkt.c +++ b/crypto/openssl/ssl/d1_pkt.c @@ -1056,7 +1056,7 @@ start: { al=SSL_AD_DECODE_ERROR; SSLerr(SSL_F_DTLS1_READ_BYTES,SSL_R_BAD_HELLO_REQUEST); - goto err; + goto f_err; } /* no need to check sequence number on HELLO REQUEST messages */ diff --git a/crypto/openssl/ssl/s3_cbc.c b/crypto/openssl/ssl/s3_cbc.c index 11f13ad..e850e3e 100644 --- a/crypto/openssl/ssl/s3_cbc.c +++ b/crypto/openssl/ssl/s3_cbc.c @@ -143,7 +143,7 @@ int tls1_cbc_remove_padding(const SSL* s, if ( (s->options&SSL_OP_TLS_BLOCK_PADDING_BUG) && !s->expand) { /* First packet is even in size, so check */ - if ((memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0",8) == 0) && + if ((CRYPTO_memcmp(s->s3->read_sequence, "\0\0\0\0\0\0\0\0", 8) == 0) && !(padding_length & 1)) { s->s3->flags|=TLS1_FLAGS_TLS_PADDING_BUG; diff --git a/crypto/openssl/ssl/s3_clnt.c b/crypto/openssl/ssl/s3_clnt.c index 7692716..8628f1c 100644 --- a/crypto/openssl/ssl/s3_clnt.c +++ b/crypto/openssl/ssl/s3_clnt.c @@ -1606,6 +1606,13 @@ int ssl3_get_key_exchange(SSL *s) SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,ERR_R_INTERNAL_ERROR); goto err; } + + if (EVP_PKEY_bits(pkey) <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + al = SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } + s->session->sess_cert->peer_rsa_tmp=rsa; rsa=NULL; } @@ -2190,7 +2197,39 @@ int ssl3_get_new_session_ticket(SSL *s) goto f_err; } - p=d=(unsigned char *)s->init_msg; + p = d = (unsigned char *)s->init_msg; + + if (s->session->session_id_length > 0) { + int i = s->session_ctx->session_cache_mode; + SSL_SESSION *new_sess; + /* + * We reused an existing session, so we need to replace it with a new + * one + */ + if (i & SSL_SESS_CACHE_CLIENT) { + /* + * Remove the old session from the cache + */ + if (i & SSL_SESS_CACHE_NO_INTERNAL_STORE) { + if (s->session_ctx->remove_session_cb != NULL) + s->session_ctx->remove_session_cb(s->session_ctx, + s->session); + } else { + /* We carry on if this fails */ + SSL_CTX_remove_session(s->session_ctx, s->session); + } + } + + if ((new_sess = ssl_session_dup(s->session, 0)) == 0) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE); + goto f_err; + } + + SSL_SESSION_free(s->session); + s->session = new_sess; + } + n2l(p, s->session->tlsext_tick_lifetime_hint); n2s(p, ticklen); /* ticket_lifetime_hint + ticket_length + ticket */ @@ -3319,6 +3358,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) int i,idx; long alg_k,alg_a; EVP_PKEY *pkey=NULL; + int pkey_bits; SESS_CERT *sc; #ifndef OPENSSL_NO_RSA RSA *rsa; @@ -3326,6 +3366,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) #ifndef OPENSSL_NO_DH DH *dh; #endif + int al = SSL_AD_HANDSHAKE_FAILURE; alg_k=s->s3->tmp.new_cipher->algorithm_mkey; alg_a=s->s3->tmp.new_cipher->algorithm_auth; @@ -3367,6 +3408,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) } #endif pkey=X509_get_pubkey(sc->peer_pkeys[idx].x509); + pkey_bits = EVP_PKEY_bits(pkey); i=X509_certificate_type(sc->peer_pkeys[idx].x509,pkey); EVP_PKEY_free(pkey); @@ -3385,71 +3427,108 @@ int ssl3_check_cert_and_algorithm(SSL *s) } #endif #ifndef OPENSSL_NO_RSA - if ((alg_k & SSL_kRSA) && - !(has_bits(i,EVP_PK_RSA|EVP_PKT_ENC) || (rsa != NULL))) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_RSA_ENCRYPTING_CERT); + if (alg_k & SSL_kRSA) { + if (!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && + !has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_RSA_ENCRYPTING_CERT); goto f_err; - } + } else if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher)) { + if (pkey_bits <= SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + if (!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_RSA_ENCRYPTING_CERT); + goto f_err; + } + if (rsa != NULL) { + /* server key exchange is not allowed. */ + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR); + goto f_err; + } + } + } + } #endif #ifndef OPENSSL_NO_DH - if ((alg_k & SSL_kEDH) && - !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL))) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY); + if ((alg_k & SSL_kEDH) && dh == NULL) { + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR); goto f_err; } - else if ((alg_k & SSL_kDHr) && !has_bits(i,EVP_PK_DH|EVP_PKS_RSA)) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_RSA_CERT); + if ((alg_k & SSL_kDHr) && !has_bits(i, EVP_PK_DH | EVP_PKS_RSA)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_DH_RSA_CERT); goto f_err; } -#ifndef OPENSSL_NO_DSA - else if ((alg_k & SSL_kDHd) && !has_bits(i,EVP_PK_DH|EVP_PKS_DSA)) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_DSA_CERT); +# ifndef OPENSSL_NO_DSA + if ((alg_k & SSL_kDHd) && !has_bits(i, EVP_PK_DH | EVP_PKS_DSA)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_DH_DSA_CERT); goto f_err; } -#endif -#endif +# endif + + /* Check DHE only: static DH not implemented. */ + if (alg_k & SSL_kEDH) { + int dh_size = BN_num_bits(dh->p); + if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 768) + || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL); + goto f_err; + } + } +#endif /* !OPENSSL_NO_DH */ - if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP)) + if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && + pkey_bits > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { #ifndef OPENSSL_NO_RSA - if (alg_k & SSL_kRSA) - { - if (rsa == NULL - || RSA_size(rsa)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY); + if (alg_k & SSL_kRSA) { + if (rsa == NULL) { + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_RSA_KEY); goto f_err; + } else if (BN_num_bits(rsa->n) > + SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + /* We have a temporary RSA key but it's too large. */ + al = SSL_AD_EXPORT_RESTRICTION; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_RSA_KEY); + goto f_err; } - } - else + } else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) - { - if (dh == NULL - || DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) - { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY); + if (alg_k & SSL_kEDH) { + if (BN_num_bits(dh->p) > + SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) { + /* We have a temporary DH key but it's too large. */ + al = SSL_AD_EXPORT_RESTRICTION; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_DH_KEY); goto f_err; } - } - else + } else if (alg_k & (SSL_kDHr | SSL_kDHd)) { + /* The cert should have had an export DH key. */ + al = SSL_AD_EXPORT_RESTRICTION; + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_MISSING_EXPORT_TMP_DH_KEY); + goto f_err; + } else #endif { - SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); + SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, + SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE); goto f_err; } } - return(1); -f_err: - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); -err: - return(0); - } + return (1); + f_err: + ssl3_send_alert(s, SSL3_AL_FATAL, al); + err: + return (0); +} #if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) int ssl3_send_next_proto(SSL *s) diff --git a/crypto/openssl/ssl/s3_srvr.c b/crypto/openssl/ssl/s3_srvr.c index fadca74..6852e08 100644 --- a/crypto/openssl/ssl/s3_srvr.c +++ b/crypto/openssl/ssl/s3_srvr.c @@ -2418,6 +2418,7 @@ int ssl3_get_client_key_exchange(SSL *s) int padl, outl; krb5_timestamp authtime = 0; krb5_ticket_times ttimes; + int kerr = 0; EVP_CIPHER_CTX_init(&ciph_ctx); @@ -2530,26 +2531,30 @@ int ssl3_get_client_key_exchange(SSL *s) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DECRYPTION_FAILED); - goto err; + kerr = 1; + goto kclean; } if (outl > SSL_MAX_MASTER_KEY_LENGTH) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); - goto err; + kerr = 1; + goto kclean; } if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl)) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DECRYPTION_FAILED); - goto err; + kerr = 1; + goto kclean; } outl += padl; if (outl > SSL_MAX_MASTER_KEY_LENGTH) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_R_DATA_LENGTH_TOO_LONG); - goto err; + kerr = 1; + goto kclean; } if (!((pms[0] == (s->client_version>>8)) && (pms[1] == (s->client_version & 0xff)))) { @@ -2565,7 +2570,8 @@ int ssl3_get_client_key_exchange(SSL *s) { SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, SSL_AD_DECODE_ERROR); - goto err; + kerr = 1; + goto kclean; } } @@ -2591,6 +2597,11 @@ int ssl3_get_client_key_exchange(SSL *s) ** kssl_ctx = kssl_ctx_free(kssl_ctx); ** if (s->kssl_ctx) s->kssl_ctx = NULL; */ + + kclean: + OPENSSL_cleanse(pms, sizeof(pms)); + if (kerr) + goto err; } else #endif /* OPENSSL_NO_KRB5 */ diff --git a/crypto/openssl/ssl/ssl.h b/crypto/openssl/ssl/ssl.h index 2ba5923..1b98e29 100644 --- a/crypto/openssl/ssl/ssl.h +++ b/crypto/openssl/ssl/ssl.h @@ -2263,6 +2263,7 @@ void ERR_load_SSL_strings(void); #define SSL_F_SSL_READ 223 #define SSL_F_SSL_RSA_PRIVATE_DECRYPT 187 #define SSL_F_SSL_RSA_PUBLIC_ENCRYPT 188 +#define SSL_F_SSL_SESSION_DUP 348 #define SSL_F_SSL_SESSION_NEW 189 #define SSL_F_SSL_SESSION_PRINT_FP 190 #define SSL_F_SSL_SESSION_SET1_ID_CONTEXT 312 @@ -2377,6 +2378,7 @@ void ERR_load_SSL_strings(void); #define SSL_R_DATA_LENGTH_TOO_LONG 146 #define SSL_R_DECRYPTION_FAILED 147 #define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC 281 +#define SSL_R_DH_KEY_TOO_SMALL 372 #define SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG 148 #define SSL_R_DIGEST_CHECK_FAILED 149 #define SSL_R_DTLS_MESSAGE_TOO_BIG 334 diff --git a/crypto/openssl/ssl/ssl_err.c b/crypto/openssl/ssl/ssl_err.c index 1b7eb47..7b6aa99 100644 --- a/crypto/openssl/ssl/ssl_err.c +++ b/crypto/openssl/ssl/ssl_err.c @@ -245,6 +245,7 @@ static ERR_STRING_DATA SSL_str_functs[]= {ERR_FUNC(SSL_F_SSL_READ), "SSL_read"}, {ERR_FUNC(SSL_F_SSL_RSA_PRIVATE_DECRYPT), "SSL_RSA_PRIVATE_DECRYPT"}, {ERR_FUNC(SSL_F_SSL_RSA_PUBLIC_ENCRYPT), "SSL_RSA_PUBLIC_ENCRYPT"}, +{ERR_FUNC(SSL_F_SSL_SESSION_DUP), "ssl_session_dup"}, {ERR_FUNC(SSL_F_SSL_SESSION_NEW), "SSL_SESSION_new"}, {ERR_FUNC(SSL_F_SSL_SESSION_PRINT_FP), "SSL_SESSION_print_fp"}, {ERR_FUNC(SSL_F_SSL_SESSION_SET1_ID_CONTEXT), "SSL_SESSION_set1_id_context"}, @@ -362,6 +363,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {ERR_REASON(SSL_R_DATA_LENGTH_TOO_LONG) ,"data length too long"}, {ERR_REASON(SSL_R_DECRYPTION_FAILED) ,"decryption failed"}, {ERR_REASON(SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC),"decryption failed or bad record mac"}, +{ERR_REASON(SSL_R_DH_KEY_TOO_SMALL), "dh key too small"}, {ERR_REASON(SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG),"dh public value length is wrong"}, {ERR_REASON(SSL_R_DIGEST_CHECK_FAILED) ,"digest check failed"}, {ERR_REASON(SSL_R_DTLS_MESSAGE_TOO_BIG) ,"dtls message too big"}, diff --git a/crypto/openssl/ssl/ssl_locl.h b/crypto/openssl/ssl/ssl_locl.h index 1b8fa8c..12d07b2 100644 --- a/crypto/openssl/ssl/ssl_locl.h +++ b/crypto/openssl/ssl/ssl_locl.h @@ -831,6 +831,7 @@ void ssl_sess_cert_free(SESS_CERT *sc); int ssl_set_peer_cert_type(SESS_CERT *c, int type); int ssl_get_new_session(SSL *s, int session); int ssl_get_prev_session(SSL *s, unsigned char *session,int len, const unsigned char *limit); +SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket); int ssl_cipher_id_cmp(const SSL_CIPHER *a,const SSL_CIPHER *b); DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id); diff --git a/crypto/openssl/ssl/ssl_sess.c b/crypto/openssl/ssl/ssl_sess.c index 235f92d..31fbf23 100644 --- a/crypto/openssl/ssl/ssl_sess.c +++ b/crypto/openssl/ssl/ssl_sess.c @@ -224,6 +224,130 @@ SSL_SESSION *SSL_SESSION_new(void) return(ss); } +/* + * Create a new SSL_SESSION and duplicate the contents of |src| into it. If + * ticket == 0 then no ticket information is duplicated, otherwise it is. + */ +SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket) +{ + SSL_SESSION *dest; + + dest = OPENSSL_malloc(sizeof(*src)); + if (dest == NULL) { + goto err; + } + memcpy(dest, src, sizeof(*dest)); + + /* + * Set the various pointers to NULL so that we can call SSL_SESSION_free in + * the case of an error whilst halfway through constructing dest + */ +#ifndef OPENSSL_NO_PSK + dest->psk_identity_hint = NULL; + dest->psk_identity = NULL; +#endif + dest->ciphers = NULL; +#ifndef OPENSSL_NO_TLSEXT + dest->tlsext_hostname = NULL; +# ifndef OPENSSL_NO_EC + dest->tlsext_ecpointformatlist = NULL; + dest->tlsext_ellipticcurvelist = NULL; +# endif +#endif + dest->tlsext_tick = NULL; +#ifndef OPENSSL_NO_SRP + dest->srp_username = NULL; +#endif + memset(&dest->ex_data, 0, sizeof(dest->ex_data)); + + /* We deliberately don't copy the prev and next pointers */ + dest->prev = NULL; + dest->next = NULL; + + dest->references = 1; + + if (src->sess_cert != NULL) + CRYPTO_add(&src->sess_cert->references, 1, CRYPTO_LOCK_SSL_SESS_CERT); + + if (src->peer != NULL) + CRYPTO_add(&src->peer->references, 1, CRYPTO_LOCK_X509); + +#ifndef OPENSSL_NO_PSK + if (src->psk_identity_hint) { + dest->psk_identity_hint = BUF_strdup(src->psk_identity_hint); + if (dest->psk_identity_hint == NULL) { + goto err; + } + } + if (src->psk_identity) { + dest->psk_identity = BUF_strdup(src->psk_identity); + if (dest->psk_identity == NULL) { + goto err; + } + } +#endif + + if(src->ciphers != NULL) { + dest->ciphers = sk_SSL_CIPHER_dup(src->ciphers); + if (dest->ciphers == NULL) + goto err; + } + + if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, + &dest->ex_data, &src->ex_data)) { + goto err; + } + +#ifndef OPENSSL_NO_TLSEXT + if (src->tlsext_hostname) { + dest->tlsext_hostname = BUF_strdup(src->tlsext_hostname); + if (dest->tlsext_hostname == NULL) { + goto err; + } + } +# ifndef OPENSSL_NO_EC + if (src->tlsext_ecpointformatlist) { + dest->tlsext_ecpointformatlist = + BUF_memdup(src->tlsext_ecpointformatlist, + src->tlsext_ecpointformatlist_length); + if (dest->tlsext_ecpointformatlist == NULL) + goto err; + } + if (src->tlsext_ellipticcurvelist) { + dest->tlsext_ellipticcurvelist = + BUF_memdup(src->tlsext_ellipticcurvelist, + src->tlsext_ellipticcurvelist_length); + if (dest->tlsext_ellipticcurvelist == NULL) + goto err; + } +# endif +#endif + + if (ticket != 0) { + dest->tlsext_tick = BUF_memdup(src->tlsext_tick, src->tlsext_ticklen); + if(dest->tlsext_tick == NULL) + goto err; + } else { + dest->tlsext_tick_lifetime_hint = 0; + dest->tlsext_ticklen = 0; + } + +#ifndef OPENSSL_NO_SRP + if (src->srp_username) { + dest->srp_username = BUF_strdup(src->srp_username); + if (dest->srp_username == NULL) { + goto err; + } + } +#endif + + return dest; +err: + SSLerr(SSL_F_SSL_SESSION_DUP, ERR_R_MALLOC_FAILURE); + SSL_SESSION_free(dest); + return NULL; +} + const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s, unsigned int *len) { if(len) diff --git a/crypto/openssl/ssl/t1_lib.c b/crypto/openssl/ssl/t1_lib.c index 179b467..afd5eee 100644 --- a/crypto/openssl/ssl/t1_lib.c +++ b/crypto/openssl/ssl/t1_lib.c @@ -1015,12 +1015,16 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in s->srtp_profile = NULL; - if (data >= (d+n-2)) + if (data >= (d + n - 2)) { + if (data != d + n) + goto err; + else goto ri_check; + } n2s(data,len); if (data > (d+n-len)) - goto ri_check; + goto err; while (data <= (d+n-4)) { @@ -1028,7 +1032,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in n2s(data,size); if (data+size > (d+n)) - goto ri_check; + goto err; #if 0 fprintf(stderr,"Received extension type %d size %d\n",type,size); #endif @@ -1065,17 +1069,11 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in int dsize; if (size < 2) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; n2s(data,dsize); size -= 2; if (dsize > size ) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; sdata = data; while (dsize > 3) @@ -1085,10 +1083,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in dsize -= 3; if (len > dsize) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (s->servername_done == 0) switch (servname_type) { @@ -1096,10 +1091,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in if (!s->hit) { if(s->session->tlsext_hostname) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (len > TLSEXT_MAXLEN_host_name) { *al = TLS1_AD_UNRECOGNIZED_NAME; @@ -1135,36 +1127,24 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in dsize -= len; } if (dsize != 0) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; } #ifndef OPENSSL_NO_SRP else if (type == TLSEXT_TYPE_srp) { if (size <= 0 || ((len = data[0])) != (size -1)) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (s->srp_ctx.login != NULL) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if ((s->srp_ctx.login = OPENSSL_malloc(len+1)) == NULL) return -1; memcpy(s->srp_ctx.login, &data[1], len); s->srp_ctx.login[len]='\0'; if (strlen(s->srp_ctx.login) != len) - { - *al = SSL_AD_DECODE_ERROR; - return 0; + goto err; } - } #endif #ifndef OPENSSL_NO_EC @@ -1174,10 +1154,7 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in int ecpointformatlist_length = *(sdata++); if (ecpointformatlist_length != size - 1) - { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } + goto err; if (!s->hit) { if(s->session->tlsext_ecpointformatlist) @@ -1212,17 +1189,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in ellipticcurvelist_length < 1 || /* Each NamedCurve is 2 bytes. */ ellipticcurvelist_length & 1) - { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } + goto err; if (!s->hit) { if(s->session->tlsext_ellipticcurvelist) - { - *al = TLS1_AD_DECODE_ERROR; - return 0; - } + goto err; + s->session->tlsext_ellipticcurvelist_length = 0; if ((s->session->tlsext_ellipticcurvelist = OPENSSL_malloc(ellipticcurvelist_length)) == NULL) { @@ -1291,33 +1263,21 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in { int dsize; if (sigalg_seen || size < 2) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; sigalg_seen = 1; n2s(data,dsize); size -= 2; if (dsize != size || dsize & 1) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (!tls1_process_sigalgs(s, data, dsize)) - { - *al = SSL_AD_DECODE_ERROR; - return 0; + goto err; } - } else if (type == TLSEXT_TYPE_status_request && s->version != DTLS1_VERSION) { if (size < 5) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; s->tlsext_status_type = *data++; size--; @@ -1329,41 +1289,28 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in n2s(data,dsize); size -= 2; if (dsize > size ) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; while (dsize > 0) { OCSP_RESPID *id; int idsize; if (dsize < 4) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; n2s(data, idsize); dsize -= 2 + idsize; size -= 2 + idsize; if (dsize < 0) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; sdata = data; data += idsize; id = d2i_OCSP_RESPID(NULL, &sdata, idsize); if (!id) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; if (data != sdata) { OCSP_RESPID_free(id); - *al = SSL_AD_DECODE_ERROR; - return 0; + goto err; } if (!s->tlsext_ocsp_ids && !(s->tlsext_ocsp_ids = @@ -1384,17 +1331,11 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in /* Read in request_extensions */ if (size < 2) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; n2s(data,dsize); size -= 2; if (dsize != size) - { - *al = SSL_AD_DECODE_ERROR; - return 0; - } + goto err; sdata = data; if (dsize > 0) { @@ -1409,12 +1350,9 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in &sdata, dsize); if (!s->tlsext_ocsp_exts || (data + dsize != sdata)) - { - *al = SSL_AD_DECODE_ERROR; - return 0; + goto err; } } - } /* We don't know what to do with any other type * so ignore it. */ @@ -1475,6 +1413,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in data+=size; } + /* Spurious data on the end */ + if (data != d + n) + goto err; + *p = data; ri_check: @@ -1491,7 +1433,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in } return 1; - } +err: + *al = SSL_AD_DECODE_ERROR; + return 0; +} #ifndef OPENSSL_NO_NEXTPROTONEG /* ssl_next_proto_validate validates a Next Protocol Negotiation block. No |