summaryrefslogtreecommitdiffstats
path: root/crypto/openssl/ssl
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2015-06-12 07:23:55 +0000
committerdelphij <delphij@FreeBSD.org>2015-06-12 07:23:55 +0000
commit17b1c22cf566ffc540a06c72a7e24903d70bdbbc (patch)
treeeaf6fd09e0241c3694090ffd493ceed2d38ba00d /crypto/openssl/ssl
parent1c7c9a70bbeba057be18a74724e6575871e447fb (diff)
downloadFreeBSD-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.c33
-rw-r--r--crypto/openssl/ssl/d1_lib.c3
-rw-r--r--crypto/openssl/ssl/d1_pkt.c2
-rw-r--r--crypto/openssl/ssl/s3_cbc.c2
-rw-r--r--crypto/openssl/ssl/s3_clnt.c165
-rw-r--r--crypto/openssl/ssl/s3_srvr.c21
-rw-r--r--crypto/openssl/ssl/ssl.h2
-rw-r--r--crypto/openssl/ssl/ssl_err.c2
-rw-r--r--crypto/openssl/ssl/ssl_locl.h1
-rw-r--r--crypto/openssl/ssl/ssl_sess.c124
-rw-r--r--crypto/openssl/ssl/t1_lib.c133
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
OpenPOWER on IntegriCloud