aboutsummaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2015-06-11 17:56:16 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2015-06-11 17:56:16 +0000
commita9745f9a849725cad34f84351bed202839aade59 (patch)
tree686ec4279139441a2f9d947dceec492e54ff569c /ssl
parent3d2030852da420b820a661e7b19bb757487e2599 (diff)
downloadsrc-a9745f9a849725cad34f84351bed202839aade59.tar.gz
src-a9745f9a849725cad34f84351bed202839aade59.zip
Import OpenSSL 1.0.1n.vendor/openssl/1.0.1n
Notes
Notes: svn path=/vendor-crypto/openssl/dist/; revision=284278 svn path=/vendor-crypto/openssl/1.0.1n/; revision=284279; tag=vendor/openssl/1.0.1n
Diffstat (limited to 'ssl')
-rw-r--r--ssl/Makefile54
-rw-r--r--ssl/d1_both.c46
-rw-r--r--ssl/d1_clnt.c10
-rw-r--r--ssl/d1_lib.c3
-rw-r--r--ssl/d1_pkt.c2
-rw-r--r--ssl/d1_srvr.c28
-rw-r--r--ssl/s2_pkt.c14
-rw-r--r--ssl/s2_srvr.c104
-rw-r--r--ssl/s3_both.c2
-rw-r--r--ssl/s3_cbc.c16
-rw-r--r--ssl/s3_clnt.c273
-rw-r--r--ssl/s3_pkt.c13
-rw-r--r--ssl/s3_srvr.c230
-rw-r--r--ssl/ssl.h4
-rw-r--r--ssl/ssl_err.c3
-rw-r--r--ssl/ssl_lib.c8
-rw-r--r--ssl/ssl_locl.h1
-rw-r--r--ssl/ssl_sess.c131
-rw-r--r--ssl/ssl_stat.c6
-rw-r--r--ssl/ssltest.c20
-rw-r--r--ssl/t1_enc.c9
-rw-r--r--ssl/t1_lib.c176
-rw-r--r--ssl/tls_srp.c3
23 files changed, 813 insertions, 343 deletions
diff --git a/ssl/Makefile b/ssl/Makefile
index 8dd390e67f99..29d9e4528fc5 100644
--- a/ssl/Makefile
+++ b/ssl/Makefile
@@ -89,12 +89,13 @@ tests:
lint:
lint -DLINT $(INCLUDES) $(SRC)>fluff
-depend:
- @if [ -z "$(THIS)" ]; then \
- $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; \
- else \
- $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC); \
- fi
+update: local_depend
+ @if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi
+
+depend: local_depend
+ @if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi
+local_depend:
+ @[ -z "$(THIS)" ] || $(MAKEDEPEND) -- $(CFLAG) $(INCLUDES) $(DEPFLAG) -- $(PROGS) $(LIBSRC)
dclean:
$(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new
@@ -507,26 +508,27 @@ s2_pkt.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
s2_pkt.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
s2_pkt.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_pkt.c
s2_pkt.o: ssl_locl.h
-s2_srvr.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
-s2_srvr.o: ../include/openssl/buffer.h ../include/openssl/comp.h
-s2_srvr.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
-s2_srvr.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h
-s2_srvr.o: ../include/openssl/ec.h ../include/openssl/ecdh.h
-s2_srvr.o: ../include/openssl/ecdsa.h ../include/openssl/err.h
-s2_srvr.o: ../include/openssl/evp.h ../include/openssl/hmac.h
-s2_srvr.o: ../include/openssl/kssl.h ../include/openssl/lhash.h
-s2_srvr.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h
-s2_srvr.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h
-s2_srvr.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h
-s2_srvr.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h
-s2_srvr.o: ../include/openssl/pqueue.h ../include/openssl/rand.h
-s2_srvr.o: ../include/openssl/rsa.h ../include/openssl/safestack.h
-s2_srvr.o: ../include/openssl/sha.h ../include/openssl/srtp.h
-s2_srvr.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h
-s2_srvr.o: ../include/openssl/ssl23.h ../include/openssl/ssl3.h
-s2_srvr.o: ../include/openssl/stack.h ../include/openssl/symhacks.h
-s2_srvr.o: ../include/openssl/tls1.h ../include/openssl/x509.h
-s2_srvr.o: ../include/openssl/x509_vfy.h s2_srvr.c ssl_locl.h
+s2_srvr.o: ../crypto/constant_time_locl.h ../e_os.h ../include/openssl/asn1.h
+s2_srvr.o: ../include/openssl/bio.h ../include/openssl/buffer.h
+s2_srvr.o: ../include/openssl/comp.h ../include/openssl/crypto.h
+s2_srvr.o: ../include/openssl/dsa.h ../include/openssl/dtls1.h
+s2_srvr.o: ../include/openssl/e_os2.h ../include/openssl/ec.h
+s2_srvr.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h
+s2_srvr.o: ../include/openssl/err.h ../include/openssl/evp.h
+s2_srvr.o: ../include/openssl/hmac.h ../include/openssl/kssl.h
+s2_srvr.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h
+s2_srvr.o: ../include/openssl/objects.h ../include/openssl/opensslconf.h
+s2_srvr.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h
+s2_srvr.o: ../include/openssl/pem.h ../include/openssl/pem2.h
+s2_srvr.o: ../include/openssl/pkcs7.h ../include/openssl/pqueue.h
+s2_srvr.o: ../include/openssl/rand.h ../include/openssl/rsa.h
+s2_srvr.o: ../include/openssl/safestack.h ../include/openssl/sha.h
+s2_srvr.o: ../include/openssl/srtp.h ../include/openssl/ssl.h
+s2_srvr.o: ../include/openssl/ssl2.h ../include/openssl/ssl23.h
+s2_srvr.o: ../include/openssl/ssl3.h ../include/openssl/stack.h
+s2_srvr.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h
+s2_srvr.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s2_srvr.c
+s2_srvr.o: ssl_locl.h
s3_both.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h
s3_both.o: ../include/openssl/buffer.h ../include/openssl/comp.h
s3_both.o: ../include/openssl/crypto.h ../include/openssl/dsa.h
diff --git a/ssl/d1_both.c b/ssl/d1_both.c
index c18ec03bd14b..8dd8ea33ca79 100644
--- a/ssl/d1_both.c
+++ b/ssl/d1_both.c
@@ -485,6 +485,12 @@ long dtls1_get_message(SSL *s, int st1, int stn, int mt, long max, int *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
@@ -879,10 +899,6 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok)
&& !(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,17 +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;
@@ -944,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
@@ -1540,7 +1556,10 @@ int dtls1_process_heartbeat(SSL *s)
memcpy(bp, pl, payload);
bp += payload;
/* Random padding */
- RAND_pseudo_bytes(bp, padding);
+ if (RAND_pseudo_bytes(bp, padding) < 0) {
+ OPENSSL_free(buffer);
+ return -1;
+ }
r = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, write_length);
@@ -1574,7 +1593,7 @@ int dtls1_process_heartbeat(SSL *s)
int dtls1_heartbeat(SSL *s)
{
unsigned char *buf, *p;
- int ret;
+ int ret = -1;
unsigned int payload = 18; /* Sequence number + random bytes */
unsigned int padding = 16; /* Use minimum padding */
@@ -1622,10 +1641,12 @@ int dtls1_heartbeat(SSL *s)
/* Sequence number */
s2n(s->tlsext_hb_seq, p);
/* 16 random bytes */
- RAND_pseudo_bytes(p, 16);
+ if (RAND_pseudo_bytes(p, 16) < 0)
+ goto err;
p += 16;
/* Random padding */
- RAND_pseudo_bytes(p, padding);
+ if (RAND_pseudo_bytes(p, padding) < 0)
+ goto err;
ret = dtls1_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
if (ret >= 0) {
@@ -1638,6 +1659,7 @@ int dtls1_heartbeat(SSL *s)
s->tlsext_hb_pending = 1;
}
+err:
OPENSSL_free(buf);
return ret;
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index 1394781c047a..377c1e61f75c 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -212,6 +212,7 @@ int dtls1_connect(SSL *s)
(s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00)) {
SSLerr(SSL_F_DTLS1_CONNECT, ERR_R_INTERNAL_ERROR);
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -221,10 +222,12 @@ int dtls1_connect(SSL *s)
if (s->init_buf == NULL) {
if ((buf = BUF_MEM_new()) == NULL) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
s->init_buf = buf;
@@ -233,12 +236,14 @@ int dtls1_connect(SSL *s)
if (!ssl3_setup_buffers(s)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
/* setup buffing BIO */
if (!ssl_init_wbio_buffer(s, 0)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -417,6 +422,7 @@ int dtls1_connect(SSL *s)
*/
if (!ssl3_check_cert_and_algorithm(s)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
break;
@@ -548,6 +554,7 @@ int dtls1_connect(SSL *s)
#endif
if (!s->method->ssl3_enc->setup_key_block(s)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -555,6 +562,7 @@ int dtls1_connect(SSL *s)
SSL3_CHANGE_CIPHER_CLIENT_WRITE))
{
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
#ifndef OPENSSL_NO_SCTP
@@ -735,6 +743,7 @@ int dtls1_connect(SSL *s)
goto end;
/* break; */
+ case SSL_ST_ERR:
default:
SSLerr(SSL_F_DTLS1_CONNECT, SSL_R_UNKNOWN_STATE);
ret = -1;
@@ -945,6 +954,7 @@ static int dtls1_get_hello_verify(SSL *s)
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->state = SSL_ST_ERR;
return -1;
}
diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c
index 94acb15de638..011d7b7cbe69 100644
--- a/ssl/d1_lib.c
+++ b/ssl/d1_lib.c
@@ -496,6 +496,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/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 7b49a7dd7a6d..d659ed428e6d 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -1065,7 +1065,7 @@ int dtls1_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek)
(s->d1->handshake_fragment[3] != 0)) {
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_DTLS1_READ_BYTES, SSL_R_BAD_HELLO_REQUEST);
- goto err;
+ goto f_err;
}
/*
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index c4ec9fe10845..41c7dc519f1b 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -224,11 +224,13 @@ int dtls1_accept(SSL *s)
if (s->init_buf == NULL) {
if ((buf = BUF_MEM_new()) == NULL) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
BUF_MEM_free(buf);
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
s->init_buf = buf;
@@ -236,6 +238,7 @@ int dtls1_accept(SSL *s)
if (!ssl3_setup_buffers(s)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -257,6 +260,7 @@ int dtls1_accept(SSL *s)
#endif
if (!ssl_init_wbio_buffer(s, 1)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -470,7 +474,7 @@ int dtls1_accept(SSL *s)
#ifndef OPENSSL_NO_PSK
|| ((alg_k & SSL_kPSK) && s->ctx->psk_identity_hint)
#endif
- || (alg_k & (SSL_kEDH | SSL_kDHr | SSL_kDHd))
+ || (alg_k & SSL_kEDH)
|| (alg_k & SSL_kEECDH)
|| ((alg_k & SSL_kRSA)
&& (s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey == NULL
@@ -665,15 +669,6 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SR_CERT_VRFY_A:
case SSL3_ST_SR_CERT_VRFY_B:
- /*
- * This *should* be the first time we enable CCS, but be
- * extra careful about surrounding code changes. We need
- * to set this here because we don't know if we're
- * expecting a CertificateVerify or not.
- */
- if (!s->s3->change_cipher_spec)
- s->d1->change_cipher_spec_ok = 1;
- /* we should decide if we expected this one */
ret = ssl3_get_cert_verify(s);
if (ret <= 0)
goto end;
@@ -690,11 +685,10 @@ int dtls1_accept(SSL *s)
case SSL3_ST_SR_FINISHED_A:
case SSL3_ST_SR_FINISHED_B:
/*
- * Enable CCS for resumed handshakes.
- * In a full handshake, we end up here through
- * SSL3_ST_SR_CERT_VRFY_B, so change_cipher_spec_ok was
- * already set. Receiving a CCS clears the flag, so make
- * sure not to re-enable it to ban duplicates.
+ * Enable CCS. Receiving a CCS clears the flag, so make
+ * sure not to re-enable it to ban duplicates. This *should* be the
+ * first time we have received one - but we check anyway to be
+ * cautious.
* s->s3->change_cipher_spec is set when a CCS is
* processed in d1_pkt.c, and remains set until
* the client's Finished message is read.
@@ -744,6 +738,7 @@ int dtls1_accept(SSL *s)
s->session->cipher = s->s3->tmp.new_cipher;
if (!s->method->ssl3_enc->setup_key_block(s)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -772,6 +767,7 @@ int dtls1_accept(SSL *s)
SSL3_CHANGE_CIPHER_SERVER_WRITE))
{
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -852,6 +848,7 @@ int dtls1_accept(SSL *s)
goto end;
/* break; */
+ case SSL_ST_ERR:
default:
SSLerr(SSL_F_DTLS1_ACCEPT, SSL_R_UNKNOWN_STATE);
ret = -1;
@@ -932,6 +929,7 @@ int dtls1_send_hello_verify_request(SSL *s)
&(s->d1->cookie_len)) == 0) {
SSLerr(SSL_F_DTLS1_SEND_HELLO_VERIFY_REQUEST,
ERR_R_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
return 0;
}
diff --git a/ssl/s2_pkt.c b/ssl/s2_pkt.c
index 614b9a35d2ea..7a6188813431 100644
--- a/ssl/s2_pkt.c
+++ b/ssl/s2_pkt.c
@@ -576,6 +576,20 @@ static int n_do_ssl_write(SSL *s, const unsigned char *buf, unsigned int len)
s->s2->padding = p;
s->s2->mac_data = &(s->s2->wbuf[3]);
s->s2->wact_data = &(s->s2->wbuf[3 + mac_size]);
+
+ /*
+ * It would be clearer to write this as follows:
+ * if (mac_size + len + p > SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER)
+ * However |len| is user input that could in theory be very large. We
+ * know |mac_size| and |p| are small, so to avoid any possibility of
+ * overflow we write it like this.
+ *
+ * In theory this should never fail because the logic above should have
+ * modified |len| if it is too big. But we are being cautious.
+ */
+ if (len > (SSL2_MAX_RECORD_LENGTH_2_BYTE_HEADER - (mac_size + p))) {
+ return -1;
+ }
/* we copy the data into s->s2->wbuf */
memcpy(s->s2->wact_data, buf, len);
if (p)
diff --git a/ssl/s2_srvr.c b/ssl/s2_srvr.c
index 19bb48c9cd46..4289272b73d3 100644
--- a/ssl/s2_srvr.c
+++ b/ssl/s2_srvr.c
@@ -111,6 +111,7 @@
#include "ssl_locl.h"
#ifndef OPENSSL_NO_SSL2
+#include "../crypto/constant_time_locl.h"
# include <stdio.h>
# include <openssl/bio.h>
# include <openssl/rand.h>
@@ -372,12 +373,15 @@ int ssl2_accept(SSL *s)
static int get_client_master_key(SSL *s)
{
int is_export, i, n, keya;
- unsigned int ek;
+ unsigned int num_encrypted_key_bytes, key_length;
unsigned long len;
unsigned char *p;
const SSL_CIPHER *cp;
const EVP_CIPHER *c;
const EVP_MD *md;
+ unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
+ unsigned char decrypt_good;
+ size_t j;
p = (unsigned char *)s->init_buf->data;
if (s->state == SSL2_ST_GET_CLIENT_MASTER_KEY_A) {
@@ -465,12 +469,6 @@ static int get_client_master_key(SSL *s)
return (0);
}
- if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) {
- is_export = 1;
- ek = 8;
- } else
- ek = 5;
-
/*
* The format of the CLIENT-MASTER-KEY message is
* 1 byte message type
@@ -484,12 +482,27 @@ static int get_client_master_key(SSL *s)
*
* If the cipher is an export cipher, then the encrypted key bytes
* are a fixed portion of the total key (5 or 8 bytes). The size of
- * this portion is in |ek|. If the cipher is not an export cipher,
- * then the entire key material is encrypted (i.e., clear key length
- * must be zero).
+ * this portion is in |num_encrypted_key_bytes|. If the cipher is not an
+ * export cipher, then the entire key material is encrypted (i.e., clear
+ * key length must be zero).
*/
- if ((!is_export && s->s2->tmp.clear != 0) ||
- (is_export && s->s2->tmp.clear + ek != (unsigned int)EVP_CIPHER_key_length(c))) {
+ key_length = (unsigned int)EVP_CIPHER_key_length(c);
+ if (key_length > SSL_MAX_MASTER_KEY_LENGTH) {
+ ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+ SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
+ return -1;
+ }
+
+ if (s->session->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC) {
+ is_export = 1;
+ num_encrypted_key_bytes = 8;
+ } else if (is_export) {
+ num_encrypted_key_bytes = 5;
+ } else {
+ num_encrypted_key_bytes = key_length;
+ }
+
+ if (s->s2->tmp.clear + num_encrypted_key_bytes != key_length) {
ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_BAD_LENGTH);
return -1;
@@ -499,64 +512,49 @@ static int get_client_master_key(SSL *s)
* Decryption can't be expanding, so if we don't have enough encrypted
* bytes to fit the key in the buffer, stop now.
*/
- if ((is_export && s->s2->tmp.enc < ek) ||
- (!is_export && s->s2->tmp.enc < (unsigned int)EVP_CIPHER_key_length(c))) {
+ if (s->s2->tmp.enc < num_encrypted_key_bytes) {
ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
SSLerr(SSL_F_GET_CLIENT_MASTER_KEY,SSL_R_LENGTH_TOO_SHORT);
return -1;
}
+ /*
+ * We must not leak whether a decryption failure occurs because of
+ * Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
+ * section 7.4.7.1). The code follows that advice of the TLS RFC and
+ * generates a random premaster secret for the case that the decrypt
+ * fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
+ */
+
+ /*
+ * should be RAND_bytes, but we cannot work around a failure.
+ */
+ if (RAND_pseudo_bytes(rand_premaster_secret,
+ (int)num_encrypted_key_bytes) <= 0)
+ return 0;
+
i = ssl_rsa_private_decrypt(s->cert, s->s2->tmp.enc,
&(p[s->s2->tmp.clear]),
&(p[s->s2->tmp.clear]),
(s->s2->ssl2_rollback) ? RSA_SSLV23_PADDING :
RSA_PKCS1_PADDING);
-
- /* bad decrypt */
-# if 1
+ ERR_clear_error();
/*
* If a bad decrypt, continue with protocol but with a random master
* secret (Bleichenbacher attack)
*/
- if ((i < 0) || ((!is_export && i != EVP_CIPHER_key_length(c))
- || (is_export && i != (int)ek))) {
- ERR_clear_error();
- if (is_export)
- i = ek;
- else
- i = EVP_CIPHER_key_length(c);
- if (RAND_pseudo_bytes(&p[s->s2->tmp.clear], i) <= 0)
- return 0;
- }
-# else
- if (i < 0) {
- error = 1;
- SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_BAD_RSA_DECRYPT);
- }
- /* incorrect number of key bytes for non export cipher */
- else if ((!is_export && (i != EVP_CIPHER_key_length(c)))
- || (is_export && ((i != ek) || (s->s2->tmp.clear + i !=
- EVP_CIPHER_key_length(c))))) {
- error = 1;
- SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, SSL_R_WRONG_NUMBER_OF_KEY_BITS);
- }
- if (error) {
- ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
- return (-1);
+ decrypt_good = constant_time_eq_int_8(i, (int)num_encrypted_key_bytes);
+ for (j = 0; j < num_encrypted_key_bytes; j++) {
+ p[s->s2->tmp.clear + j] =
+ constant_time_select_8(decrypt_good, p[s->s2->tmp.clear + j],
+ rand_premaster_secret[j]);
}
-# endif
- if (is_export)
- i = EVP_CIPHER_key_length(c);
+ s->session->master_key_length = (int)key_length;
+ memcpy(s->session->master_key, p, key_length);
+ OPENSSL_cleanse(p, key_length);
- if (i > SSL_MAX_MASTER_KEY_LENGTH) {
- ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
- SSLerr(SSL_F_GET_CLIENT_MASTER_KEY, ERR_R_INTERNAL_ERROR);
- return -1;
- }
- s->session->master_key_length = i;
- memcpy(s->session->master_key, p, (unsigned int)i);
- return (1);
+ return 1;
}
static int get_client_hello(SSL *s)
diff --git a/ssl/s3_both.c b/ssl/s3_both.c
index 77374f41eebf..107b460f27b6 100644
--- a/ssl/s3_both.c
+++ b/ssl/s3_both.c
@@ -169,7 +169,7 @@ int ssl3_send_finished(SSL *s, int a, int b, const char *sender, int slen)
i = s->method->ssl3_enc->final_finish_mac(s,
sender, slen,
s->s3->tmp.finish_md);
- if (i == 0)
+ if (i <= 0)
return 0;
s->s3->tmp.finish_md_len = i;
memcpy(p, s->s3->tmp.finish_md, i);
diff --git a/ssl/s3_cbc.c b/ssl/s3_cbc.c
index 598d27edccb5..2fb71f277e9c 100644
--- a/ssl/s3_cbc.c
+++ b/ssl/s3_cbc.c
@@ -149,7 +149,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;
}
@@ -639,12 +639,22 @@ void ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
if (k > 0) {
if (is_sslv3) {
+ unsigned overhang;
+
/*
* The SSLv3 header is larger than a single block. overhang is
* the number of bytes beyond a single block that the header
- * consumes: either 7 bytes (SHA1) or 11 bytes (MD5).
+ * consumes: either 7 bytes (SHA1) or 11 bytes (MD5). There are no
+ * ciphersuites in SSLv3 that are not SHA1 or MD5 based and
+ * therefore we can be confident that the header_length will be
+ * greater than |md_block_size|. However we add a sanity check just
+ * in case
*/
- unsigned overhang = header_length - md_block_size;
+ if (header_length <= md_block_size) {
+ /* Should never happen */
+ return;
+ }
+ overhang = header_length - md_block_size;
md_transform(md_state.c, header);
memcpy(first_block, header + md_block_size, overhang);
memcpy(first_block + overhang, data, md_block_size - overhang);
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 0e5acecabb06..0879a0f8baae 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -168,6 +168,9 @@
#endif
static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b);
+#ifndef OPENSSL_NO_TLSEXT
+static int ssl3_check_finished(SSL *s);
+#endif
#ifndef OPENSSL_NO_SSL3_METHOD
static const SSL_METHOD *ssl3_get_client_method(int ver)
@@ -235,6 +238,7 @@ int ssl3_connect(SSL *s)
if ((s->version & 0xff00) != 0x0300) {
SSLerr(SSL_F_SSL3_CONNECT, ERR_R_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
ret = -1;
goto end;
}
@@ -245,10 +249,12 @@ int ssl3_connect(SSL *s)
if (s->init_buf == NULL) {
if ((buf = BUF_MEM_new()) == NULL) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
s->init_buf = buf;
@@ -263,6 +269,7 @@ int ssl3_connect(SSL *s)
/* setup buffing BIO */
if (!ssl_init_wbio_buffer(s, 0)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -317,12 +324,24 @@ int ssl3_connect(SSL *s)
case SSL3_ST_CR_CERT_A:
case SSL3_ST_CR_CERT_B:
+#ifndef OPENSSL_NO_TLSEXT
+ /* Noop (ret = 0) for everything but EAP-FAST. */
+ ret = ssl3_check_finished(s);
+ if (ret < 0)
+ goto end;
+ if (ret == 1) {
+ s->hit = 1;
+ s->state = SSL3_ST_CR_FINISHED_A;
+ s->init_num = 0;
+ break;
+ }
+#endif
/* Check if it is anon DH/ECDH, SRP auth */
/* or PSK */
if (!
(s->s3->tmp.
new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
-&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
+ && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
ret = ssl3_get_server_certificate(s);
if (ret <= 0)
goto end;
@@ -358,6 +377,7 @@ int ssl3_connect(SSL *s)
*/
if (!ssl3_check_cert_and_algorithm(s)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
break;
@@ -381,6 +401,7 @@ int ssl3_connect(SSL *s)
if ((ret = SRP_Calc_A_param(s)) <= 0) {
SSLerr(SSL_F_SSL3_CONNECT, SSL_R_SRP_A_CALC);
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
goto end;
}
}
@@ -472,6 +493,7 @@ int ssl3_connect(SSL *s)
#endif
if (!s->method->ssl3_enc->setup_key_block(s)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -479,6 +501,7 @@ int ssl3_connect(SSL *s)
SSL3_CHANGE_CIPHER_CLIENT_WRITE))
{
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -553,7 +576,8 @@ int ssl3_connect(SSL *s)
case SSL3_ST_CR_FINISHED_A:
case SSL3_ST_CR_FINISHED_B:
- s->s3->flags |= SSL3_FLAGS_CCS_OK;
+ if (!s->s3->change_cipher_spec)
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
ret = ssl3_get_finished(s, SSL3_ST_CR_FINISHED_A,
SSL3_ST_CR_FINISHED_B);
if (ret <= 0)
@@ -612,6 +636,7 @@ int ssl3_connect(SSL *s)
goto end;
/* break; */
+ case SSL_ST_ERR:
default:
SSLerr(SSL_F_SSL3_CONNECT, SSL_R_UNKNOWN_STATE);
ret = -1;
@@ -658,9 +683,17 @@ int ssl3_client_hello(SSL *s)
buf = (unsigned char *)s->init_buf->data;
if (s->state == SSL3_ST_CW_CLNT_HELLO_A) {
SSL_SESSION *sess = s->session;
- if ((sess == NULL) ||
- (sess->ssl_version != s->version) ||
- !sess->session_id_length || (sess->not_resumable)) {
+ if ((sess == NULL) || (sess->ssl_version != s->version) ||
+#ifdef OPENSSL_NO_TLSEXT
+ !sess->session_id_length ||
+#else
+ /*
+ * In the case of EAP-FAST, we can have a pre-shared
+ * "ticket" without a session ID.
+ */
+ (!sess->session_id_length && !sess->tlsext_tick) ||
+#endif
+ (sess->not_resumable)) {
if (!ssl_get_new_session(s, 0))
goto err;
}
@@ -798,6 +831,7 @@ int ssl3_client_hello(SSL *s)
/* SSL3_ST_CW_CLNT_HELLO_B */
return (ssl3_do_write(s, SSL3_RT_HANDSHAKE));
err:
+ s->state = SSL_ST_ERR;
return (-1);
}
@@ -867,10 +901,19 @@ int ssl3_get_server_hello(SSL *s)
}
#ifndef OPENSSL_NO_TLSEXT
/*
- * check if we want to resume the session based on external pre-shared
- * secret
+ * Check if we can resume the session based on external pre-shared secret.
+ * EAP-FAST (RFC 4851) supports two types of session resumption.
+ * Resumption based on server-side state works with session IDs.
+ * Resumption based on pre-shared Protected Access Credentials (PACs)
+ * works by overriding the SessionTicket extension at the application
+ * layer, and does not send a session ID. (We do not know whether EAP-FAST
+ * servers would honour the session ID.) Therefore, the session ID alone
+ * is not a reliable indicator of session resumption, so we first check if
+ * we can resume, and later peek at the next handshake message to see if the
+ * server wants to resume.
*/
- if (s->version >= TLS1_VERSION && s->tls_session_secret_cb) {
+ if (s->version >= TLS1_VERSION && s->tls_session_secret_cb &&
+ s->session->tlsext_tick) {
SSL_CIPHER *pref_cipher = NULL;
s->session->master_key_length = sizeof(s->session->master_key);
if (s->tls_session_secret_cb(s, s->session->master_key,
@@ -879,12 +922,15 @@ int ssl3_get_server_hello(SSL *s)
s->tls_session_secret_cb_arg)) {
s->session->cipher = pref_cipher ?
pref_cipher : ssl_get_cipher_by_char(s, p + j);
- s->hit = 1;
+ } else {
+ SSLerr(SSL_F_SSL3_GET_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ al = SSL_AD_INTERNAL_ERROR;
+ goto f_err;
}
}
#endif /* OPENSSL_NO_TLSEXT */
- if (!s->hit && j != 0 && j == s->session->session_id_length
+ if (j != 0 && j == s->session->session_id_length
&& memcmp(p, s->session->session_id, j) == 0) {
if (s->sid_ctx_length != s->session->sid_ctx_length
|| memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
@@ -895,12 +941,13 @@ int ssl3_get_server_hello(SSL *s)
goto f_err;
}
s->hit = 1;
- }
- /* a miss or crap from the other end */
- if (!s->hit) {
+ } else {
/*
- * If we were trying for session-id reuse, make a new SSL_SESSION so
- * we don't stuff up other people
+ * If we were trying for session-id reuse but the server
+ * didn't echo the ID, make a new SSL_SESSION.
+ * In the case of EAP-FAST and PAC, we do not send a session ID,
+ * so the PAC-based session secret is always preserved. It'll be
+ * overwritten if the server refuses resumption.
*/
if (s->session->session_id_length > 0) {
if (!ssl_get_new_session(s, 0)) {
@@ -1045,6 +1092,7 @@ int ssl3_get_server_hello(SSL *s)
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
+ s->state = SSL_ST_ERR;
return (-1);
}
@@ -1223,8 +1271,10 @@ int ssl3_get_server_certificate(SSL *s)
if (0) {
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
- }
err:
+ s->state = SSL_ST_ERR;
+ }
+
EVP_PKEY_free(pkey);
X509_free(x);
sk_X509_pop_free(sk, X509_free);
@@ -1546,6 +1596,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;
}
@@ -1894,6 +1951,7 @@ int ssl3_get_key_exchange(SSL *s)
EC_KEY_free(ecdh);
#endif
EVP_MD_CTX_cleanup(&md_ctx);
+ s->state = SSL_ST_ERR;
return (-1);
}
@@ -2050,7 +2108,10 @@ int ssl3_get_certificate_request(SSL *s)
ca_sk = NULL;
ret = 1;
+ goto done;
err:
+ s->state = SSL_ST_ERR;
+ done:
if (ca_sk != NULL)
sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
return (ret);
@@ -2085,6 +2146,38 @@ int ssl3_get_new_session_ticket(SSL *s)
}
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 */
@@ -2127,6 +2220,7 @@ int ssl3_get_new_session_ticket(SSL *s)
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
+ s->state = SSL_ST_ERR;
return (-1);
}
@@ -2187,6 +2281,7 @@ int ssl3_get_cert_status(SSL *s)
return 1;
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->state = SSL_ST_ERR;
return (-1);
}
#endif
@@ -2208,6 +2303,7 @@ int ssl3_get_server_done(SSL *s)
/* should contain no data */
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
SSLerr(SSL_F_SSL3_GET_SERVER_DONE, SSL_R_LENGTH_MISMATCH);
+ s->state = SSL_ST_ERR;
return -1;
}
ret = 1;
@@ -2506,8 +2602,6 @@ int ssl3_send_client_key_exchange(SSL *s)
n += 2;
DH_free(dh_clnt);
-
- /* perhaps clean things up a bit EAY EAY EAY EAY */
}
#endif
@@ -2729,7 +2823,10 @@ int ssl3_send_client_key_exchange(SSL *s)
EVP_PKEY_encrypt_init(pkey_ctx);
/* Generate session key */
- RAND_bytes(premaster_secret, 32);
+ if (RAND_bytes(premaster_secret, 32) <= 0) {
+ EVP_PKEY_CTX_free(pkey_ctx);
+ goto err;
+ }
/*
* If we have client certificate, use its secret as peer key
*/
@@ -2948,6 +3045,7 @@ int ssl3_send_client_key_exchange(SSL *s)
EC_KEY_free(clnt_ecdh);
EVP_PKEY_free(srvr_pub_pkey);
#endif
+ s->state = SSL_ST_ERR;
return (-1);
}
@@ -3081,6 +3179,7 @@ int ssl3_send_client_verify(SSL *s)
err:
EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_CTX_free(pctx);
+ s->state = SSL_ST_ERR;
return (-1);
}
@@ -3149,6 +3248,7 @@ int ssl3_send_client_certificate(SSL *s)
if (!l) {
SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
return 0;
}
s->init_num = (int)l;
@@ -3165,6 +3265,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;
@@ -3172,6 +3273,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;
@@ -3207,6 +3309,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);
@@ -3224,38 +3327,71 @@ 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);
- goto f_err;
+ 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)) {
+ }
+ 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)) {
+ 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
- if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i, EVP_PKT_EXP)) {
+ /* 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) &&
+ 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 >
+ 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;
@@ -3263,14 +3399,21 @@ int ssl3_check_cert_and_algorithm(SSL *s)
} else
#endif
#ifndef OPENSSL_NO_DH
- if (alg_k & (SSL_kEDH | SSL_kDHr | SSL_kDHd)) {
- if (dh == NULL
- || DH_size(dh) * 8 >
+ 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 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
{
@@ -3281,12 +3424,62 @@ int ssl3_check_cert_and_algorithm(SSL *s)
}
return (1);
f_err:
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
err:
return (0);
}
-#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
+#ifndef OPENSSL_NO_TLSEXT
+/*
+ * Normally, we can tell if the server is resuming the session from
+ * the session ID. EAP-FAST (RFC 4851), however, relies on the next server
+ * message after the ServerHello to determine if the server is resuming.
+ * Therefore, we allow EAP-FAST to peek ahead.
+ * ssl3_check_finished returns 1 if we are resuming from an external
+ * pre-shared secret, we have a "ticket" and the next server handshake message
+ * is Finished; and 0 otherwise. It returns -1 upon an error.
+ */
+static int ssl3_check_finished(SSL *s)
+{
+ int ok = 0;
+
+ if (s->version < TLS1_VERSION || !s->tls_session_secret_cb ||
+ !s->session->tlsext_tick)
+ return 0;
+
+ /* Need to permit this temporarily, in case the next message is Finished. */
+ s->s3->flags |= SSL3_FLAGS_CCS_OK;
+ /*
+ * This function is called when we might get a Certificate message instead,
+ * so permit appropriate message length.
+ * We ignore the return value as we're only interested in the message type
+ * and not its length.
+ */
+ s->method->ssl_get_message(s,
+ SSL3_ST_CR_CERT_A,
+ SSL3_ST_CR_CERT_B,
+ -1, s->max_cert_list, &ok);
+ s->s3->flags &= ~SSL3_FLAGS_CCS_OK;
+
+ if (!ok)
+ return -1;
+
+ s->s3->tmp.reuse_message = 1;
+
+ if (s->s3->tmp.message_type == SSL3_MT_FINISHED)
+ return 1;
+
+ /* If we're not done, then the CCS arrived early and we should bail. */
+ if (s->s3->change_cipher_spec) {
+ SSLerr(SSL_F_SSL3_CHECK_FINISHED, SSL_R_CCS_RECEIVED_EARLY);
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
+ return 0;
+}
+
+# ifndef OPENSSL_NO_NEXTPROTONEG
int ssl3_send_next_proto(SSL *s)
{
unsigned int len, padding_len;
@@ -3309,8 +3502,8 @@ int ssl3_send_next_proto(SSL *s)
return ssl3_do_write(s, SSL3_RT_HANDSHAKE);
}
-#endif /* !OPENSSL_NO_TLSEXT &&
- * !OPENSSL_NO_NEXTPROTONEG */
+#endif /* !OPENSSL_NO_NEXTPROTONEG */
+#endif /* !OPENSSL_NO_TLSEXT */
int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
{
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 7c9f20c8f99e..25cf929a55d6 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -347,11 +347,22 @@ static int ssl3_get_record(SSL *s)
if (version != s->version) {
SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER);
if ((s->version & 0xFF00) == (version & 0xFF00)
- && !s->enc_write_ctx && !s->write_hash)
+ && !s->enc_write_ctx && !s->write_hash) {
+ if (rr->type == SSL3_RT_ALERT) {
+ /*
+ * The record is using an incorrect version number, but
+ * what we've got appears to be an alert. We haven't
+ * read the body yet to check whether its a fatal or
+ * not - but chances are it is. We probably shouldn't
+ * send a fatal alert back. We'll just end.
+ */
+ goto err;
+ }
/*
* Send back error using their minor version number :-)
*/
s->version = (unsigned short)version;
+ }
al = SSL_AD_PROTOCOL_VERSION;
goto f_err;
}
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index b8f91bc94550..9aa329260ae7 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -266,6 +266,7 @@ int ssl3_accept(SSL *s)
if ((s->version >> 8) != 3) {
SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
return -1;
}
s->type = SSL_ST_ACCEPT;
@@ -273,11 +274,13 @@ int ssl3_accept(SSL *s)
if (s->init_buf == NULL) {
if ((buf = BUF_MEM_new()) == NULL) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
BUF_MEM_free(buf);
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
s->init_buf = buf;
@@ -285,6 +288,7 @@ int ssl3_accept(SSL *s)
if (!ssl3_setup_buffers(s)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -303,6 +307,7 @@ int ssl3_accept(SSL *s)
*/
if (!ssl_init_wbio_buffer(s, 1)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -320,6 +325,7 @@ int ssl3_accept(SSL *s)
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
} else {
/*
@@ -379,6 +385,7 @@ int ssl3_accept(SSL *s)
SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_CLIENTHELLO_TLSEXT);
ret = SSL_TLSEXT_ERR_ALERT_FATAL;
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
}
@@ -529,9 +536,12 @@ int ssl3_accept(SSL *s)
skip = 1;
s->s3->tmp.cert_request = 0;
s->state = SSL3_ST_SW_SRVR_DONE_A;
- if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
+ if (s->s3->handshake_buffer) {
+ if (!ssl3_digest_cached_records(s)) {
+ s->state = SSL_ST_ERR;
return -1;
+ }
+ }
} else {
s->s3->tmp.cert_request = 1;
ret = ssl3_send_certificate_request(s);
@@ -629,11 +639,14 @@ int ssl3_accept(SSL *s)
*/
if (!s->s3->handshake_buffer) {
SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
return -1;
}
s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
- if (!ssl3_digest_cached_records(s))
+ if (!ssl3_digest_cached_records(s)) {
+ s->state = SSL_ST_ERR;
return -1;
+ }
} else {
int offset = 0;
int dgst_num;
@@ -647,9 +660,12 @@ int ssl3_accept(SSL *s)
* CertificateVerify should be generalized. But it is next
* step
*/
- if (s->s3->handshake_buffer)
- if (!ssl3_digest_cached_records(s))
+ if (s->s3->handshake_buffer) {
+ if (!ssl3_digest_cached_records(s)) {
+ s->state = SSL_ST_ERR;
return -1;
+ }
+ }
for (dgst_num = 0; dgst_num < SSL_MAX_DIGEST; dgst_num++)
if (s->s3->handshake_dgst[dgst_num]) {
int dgst_size;
@@ -665,6 +681,7 @@ int ssl3_accept(SSL *s)
dgst_size =
EVP_MD_CTX_size(s->s3->handshake_dgst[dgst_num]);
if (dgst_size < 0) {
+ s->state = SSL_ST_ERR;
ret = -1;
goto end;
}
@@ -675,15 +692,6 @@ int ssl3_accept(SSL *s)
case SSL3_ST_SR_CERT_VRFY_A:
case SSL3_ST_SR_CERT_VRFY_B:
- /*
- * This *should* be the first time we enable CCS, but be
- * extra careful about surrounding code changes. We need
- * to set this here because we don't know if we're
- * expecting a CertificateVerify or not.
- */
- if (!s->s3->change_cipher_spec)
- s->s3->flags |= SSL3_FLAGS_CCS_OK;
- /* we should decide if we expected this one */
ret = ssl3_get_cert_verify(s);
if (ret <= 0)
goto end;
@@ -703,11 +711,10 @@ int ssl3_accept(SSL *s)
case SSL3_ST_SR_NEXT_PROTO_A:
case SSL3_ST_SR_NEXT_PROTO_B:
/*
- * Enable CCS for resumed handshakes with NPN.
- * In a full handshake with NPN, we end up here through
- * SSL3_ST_SR_CERT_VRFY_B, where SSL3_FLAGS_CCS_OK was
- * already set. Receiving a CCS clears the flag, so make
- * sure not to re-enable it to ban duplicates.
+ * Enable CCS for NPN. Receiving a CCS clears the flag, so make
+ * sure not to re-enable it to ban duplicates. This *should* be the
+ * first time we have received one - but we check anyway to be
+ * cautious.
* s->s3->change_cipher_spec is set when a CCS is
* processed in s3_pkt.c, and remains set until
* the client's Finished message is read.
@@ -726,10 +733,8 @@ int ssl3_accept(SSL *s)
case SSL3_ST_SR_FINISHED_A:
case SSL3_ST_SR_FINISHED_B:
/*
- * Enable CCS for resumed handshakes without NPN.
- * In a full handshake, we end up here through
- * SSL3_ST_SR_CERT_VRFY_B, where SSL3_FLAGS_CCS_OK was
- * already set. Receiving a CCS clears the flag, so make
+ * Enable CCS for handshakes without NPN. In NPN the CCS flag has
+ * already been set. Receiving a CCS clears the flag, so make
* sure not to re-enable it to ban duplicates.
* s->s3->change_cipher_spec is set when a CCS is
* processed in s3_pkt.c, and remains set until
@@ -779,6 +784,7 @@ int ssl3_accept(SSL *s)
s->session->cipher = s->s3->tmp.new_cipher;
if (!s->method->ssl3_enc->setup_key_block(s)) {
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -795,6 +801,7 @@ int ssl3_accept(SSL *s)
SSL3_CHANGE_CIPHER_SERVER_WRITE))
{
ret = -1;
+ s->state = SSL_ST_ERR;
goto end;
}
@@ -857,6 +864,7 @@ int ssl3_accept(SSL *s)
goto end;
/* break; */
+ case SSL_ST_ERR:
default:
SSLerr(SSL_F_SSL3_ACCEPT, SSL_R_UNKNOWN_STATE);
ret = -1;
@@ -992,6 +1000,16 @@ int ssl3_get_client_hello(SSL *s)
d = p = (unsigned char *)s->init_msg;
/*
+ * 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte
+ * for session id length
+ */
+ if (n < 2 + SSL3_RANDOM_SIZE + 1) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
+ /*
* use version from inside client hello, not from record header (may
* differ: see RFC 2246, Appendix E, second paragraph)
*/
@@ -1022,6 +1040,12 @@ int ssl3_get_client_hello(SSL *s)
unsigned int session_length, cookie_length;
session_length = *(p + SSL3_RANDOM_SIZE);
+
+ if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);
if (cookie_length == 0)
@@ -1035,6 +1059,12 @@ int ssl3_get_client_hello(SSL *s)
/* get the session-id */
j = *(p++);
+ if (p + j > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
s->hit = 0;
/*
* Versions before 0.9.7 always allow clients to resume sessions in
@@ -1079,8 +1109,19 @@ int ssl3_get_client_hello(SSL *s)
if (s->version == DTLS1_VERSION || s->version == DTLS1_BAD_VER) {
/* cookie stuff */
+ if (p + 1 > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
cookie_len = *(p++);
+ if (p + cookie_len > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
/*
* The ClientHello may contain a cookie even if the
* HelloVerify message has not been sent--make sure that it
@@ -1121,27 +1162,33 @@ int ssl3_get_client_hello(SSL *s)
p += cookie_len;
}
+ if (p + 2 > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
n2s(p, i);
- if ((i == 0) && (j != 0)) {
- /* we need a cipher if we are not resuming a session */
+
+ if (i == 0) {
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
goto f_err;
}
- if ((p + i) >= (d + n)) {
+
+ /* i bytes of cipher data + 1 byte for compression length later */
+ if ((p + i + 1) > (d + n)) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
- if ((i > 0) && (ssl_bytes_to_cipher_list(s, p, i, &(ciphers))
- == NULL)) {
+ if (ssl_bytes_to_cipher_list(s, p, i, &(ciphers)) == NULL) {
goto err;
}
p += i;
/* If it is a hit, check that the cipher is in the list */
- if ((s->hit) && (i > 0)) {
+ if (s->hit) {
j = 0;
id = s->session->cipher->id;
@@ -1377,8 +1424,8 @@ int ssl3_get_client_hello(SSL *s)
sk_SSL_CIPHER_free(s->session->ciphers);
s->session->ciphers = ciphers;
if (ciphers == NULL) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_PASSED);
+ al = SSL_AD_INTERNAL_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto f_err;
}
ciphers = NULL;
@@ -1450,8 +1497,10 @@ int ssl3_get_client_hello(SSL *s)
if (0) {
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
- }
err:
+ s->state = SSL_ST_ERR;
+ }
+
if (ciphers != NULL)
sk_SSL_CIPHER_free(ciphers);
return (ret);
@@ -1468,8 +1517,10 @@ int ssl3_send_server_hello(SSL *s)
buf = (unsigned char *)s->init_buf->data;
#ifdef OPENSSL_NO_TLSEXT
p = s->s3->server_random;
- if (ssl_fill_hello_random(s, 1, p, SSL3_RANDOM_SIZE) <= 0)
+ if (ssl_fill_hello_random(s, 1, p, SSL3_RANDOM_SIZE) <= 0) {
+ s->state = SSL_ST_ERR;
return -1;
+ }
#endif
/* Do the message type and length last */
d = p = &(buf[4]);
@@ -1504,6 +1555,7 @@ int ssl3_send_server_hello(SSL *s)
sl = s->session->session_id_length;
if (sl > (int)sizeof(s->session->session_id)) {
SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
return -1;
}
*(p++) = sl;
@@ -1526,6 +1578,7 @@ int ssl3_send_server_hello(SSL *s)
#ifndef OPENSSL_NO_TLSEXT
if (ssl_prepare_serverhello_tlsext(s) <= 0) {
SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT);
+ s->state = SSL_ST_ERR;
return -1;
}
if ((p =
@@ -1533,6 +1586,7 @@ int ssl3_send_server_hello(SSL *s)
buf + SSL3_RT_MAX_PLAIN_LENGTH)) ==
NULL) {
SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
return -1;
}
#endif
@@ -2016,6 +2070,7 @@ int ssl3_send_server_key_exchange(SSL *s)
BN_CTX_free(bn_ctx);
#endif
EVP_MD_CTX_cleanup(&md_ctx);
+ s->state = SSL_ST_ERR;
return (-1);
}
@@ -2113,6 +2168,7 @@ int ssl3_send_certificate_request(SSL *s)
/* SSL3_ST_SW_CERT_REQ_B */
return (ssl3_do_write(s, SSL3_RT_HANDSHAKE));
err:
+ s->state = SSL_ST_ERR;
return (-1);
}
@@ -2367,6 +2423,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);
@@ -2470,23 +2527,27 @@ 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)))) {
@@ -2503,7 +2564,8 @@ int ssl3_get_client_key_exchange(SSL *s)
if (!(s->options & SSL_OP_TLS_ROLLBACK_BUG)) {
SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
SSL_AD_DECODE_ERROR);
- goto err;
+ kerr = 1;
+ goto kclean;
}
}
@@ -2529,6 +2591,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 */
@@ -2847,6 +2914,7 @@ int ssl3_get_client_key_exchange(SSL *s)
s->
session->master_key,
premaster_secret, 32);
+ OPENSSL_cleanse(premaster_secret, sizeof(premaster_secret));
/* Check if pubkey from client certificate was used */
if (EVP_PKEY_CTX_ctrl
(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
@@ -2879,6 +2947,7 @@ int ssl3_get_client_key_exchange(SSL *s)
EC_KEY_free(srvr_ecdh);
BN_CTX_free(bn_ctx);
#endif
+ s->state = SSL_ST_ERR;
return (-1);
}
@@ -2894,39 +2963,31 @@ int ssl3_get_cert_verify(SSL *s)
EVP_MD_CTX mctx;
EVP_MD_CTX_init(&mctx);
+ /*
+ * We should only process a CertificateVerify message if we have received
+ * a Certificate from the client. If so then |s->session->peer| will be non
+ * NULL. In some instances a CertificateVerify message is not required even
+ * if the peer has sent a Certificate (e.g. such as in the case of static
+ * DH). In that case the ClientKeyExchange processing will skip the
+ * CertificateVerify state so we should not arrive here.
+ */
+ if (s->session->peer == NULL) {
+ ret = 1;
+ goto end;
+ }
+
n = s->method->ssl_get_message(s,
SSL3_ST_SR_CERT_VRFY_A,
SSL3_ST_SR_CERT_VRFY_B,
- -1, SSL3_RT_MAX_PLAIN_LENGTH, &ok);
+ SSL3_MT_CERTIFICATE_VERIFY,
+ SSL3_RT_MAX_PLAIN_LENGTH, &ok);
if (!ok)
return ((int)n);
- if (s->session->peer != NULL) {
- peer = s->session->peer;
- pkey = X509_get_pubkey(peer);
- type = X509_certificate_type(peer, pkey);
- } else {
- peer = NULL;
- pkey = NULL;
- }
-
- if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_VERIFY) {
- s->s3->tmp.reuse_message = 1;
- if (peer != NULL) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_MISSING_VERIFY_MESSAGE);
- goto f_err;
- }
- ret = 1;
- goto end;
- }
-
- if (peer == NULL) {
- SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_NO_CLIENT_CERT_RECEIVED);
- al = SSL_AD_UNEXPECTED_MESSAGE;
- goto f_err;
- }
+ peer = s->session->peer;
+ pkey = X509_get_pubkey(peer);
+ type = X509_certificate_type(peer, pkey);
if (!(type & EVP_PKT_SIGN)) {
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,
@@ -2935,12 +2996,6 @@ int ssl3_get_cert_verify(SSL *s)
goto f_err;
}
- if (s->s3->change_cipher_spec) {
- SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, SSL_R_CCS_RECEIVED_EARLY);
- al = SSL_AD_UNEXPECTED_MESSAGE;
- goto f_err;
- }
-
/* we now have a signature that we need to verify */
p = (unsigned char *)s->init_msg;
/* Check for broken implementations of GOST ciphersuites */
@@ -3093,6 +3148,7 @@ int ssl3_get_cert_verify(SSL *s)
if (0) {
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ s->state = SSL_ST_ERR;
}
end:
if (s->s3->handshake_buffer) {
@@ -3251,8 +3307,10 @@ int ssl3_get_client_certificate(SSL *s)
if (0) {
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
- }
err:
+ s->state = SSL_ST_ERR;
+ }
+
if (x != NULL)
X509_free(x);
if (sk != NULL)
@@ -3273,6 +3331,7 @@ int ssl3_send_server_certificate(SSL *s)
(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kKRB5)) {
SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
return (0);
}
}
@@ -3280,6 +3339,7 @@ int ssl3_send_server_certificate(SSL *s)
l = ssl3_output_cert_chain(s, x);
if (!l) {
SSLerr(SSL_F_SSL3_SEND_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
+ s->state = SSL_ST_ERR;
return (0);
}
s->state = SSL3_ST_SW_CERT_B;
@@ -3315,11 +3375,15 @@ int ssl3_send_newsession_ticket(SSL *s)
* Some length values are 16 bits, so forget it if session is too
* long
*/
- if (slen_full == 0 || slen_full > 0xFF00)
+ if (slen_full == 0 || slen_full > 0xFF00) {
+ s->state = SSL_ST_ERR;
return -1;
+ }
senc = OPENSSL_malloc(slen_full);
- if (!senc)
+ if (!senc) {
+ s->state = SSL_ST_ERR;
return -1;
+ }
EVP_CIPHER_CTX_init(&ctx);
HMAC_CTX_init(&hctx);
@@ -3442,6 +3506,7 @@ int ssl3_send_newsession_ticket(SSL *s)
OPENSSL_free(senc);
EVP_CIPHER_CTX_cleanup(&ctx);
HMAC_CTX_cleanup(&hctx);
+ s->state = SSL_ST_ERR;
return -1;
}
@@ -3455,8 +3520,10 @@ int ssl3_send_cert_status(SSL *s)
* 1 (ocsp response type) + 3 (ocsp response length)
* + (ocsp response)
*/
- if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen))
+ if (!BUF_MEM_grow(s->init_buf, 8 + s->tlsext_ocsp_resplen)) {
+ s->state = SSL_ST_ERR;
return -1;
+ }
p = (unsigned char *)s->init_buf->data;
@@ -3499,6 +3566,7 @@ int ssl3_get_next_proto(SSL *s)
if (!s->s3->next_proto_neg_seen) {
SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,
SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
+ s->state = SSL_ST_ERR;
return -1;
}
@@ -3518,11 +3586,14 @@ int ssl3_get_next_proto(SSL *s)
*/
if (!s->s3->change_cipher_spec) {
SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS);
+ s->state = SSL_ST_ERR;
return -1;
}
- if (n < 2)
+ if (n < 2) {
+ s->state = SSL_ST_ERR;
return 0; /* The body must be > 1 bytes long */
+ }
p = (unsigned char *)s->init_msg;
@@ -3534,15 +3605,20 @@ int ssl3_get_next_proto(SSL *s)
* uint8 padding[padding_len];
*/
proto_len = p[0];
- if (proto_len + 2 > s->init_num)
+ if (proto_len + 2 > s->init_num) {
+ s->state = SSL_ST_ERR;
return 0;
+ }
padding_len = p[proto_len + 1];
- if (proto_len + padding_len + 2 != s->init_num)
+ if (proto_len + padding_len + 2 != s->init_num) {
+ s->state = SSL_ST_ERR;
return 0;
+ }
s->next_proto_negotiated = OPENSSL_malloc(proto_len);
if (!s->next_proto_negotiated) {
SSLerr(SSL_F_SSL3_GET_NEXT_PROTO, ERR_R_MALLOC_FAILURE);
+ s->state = SSL_ST_ERR;
return 0;
}
memcpy(s->next_proto_negotiated, p + 1, proto_len);
diff --git a/ssl/ssl.h b/ssl/ssl.h
index b93b67b14bb3..d2ab0c074c99 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1544,6 +1544,7 @@ extern "C" {
# define SSL_ST_BEFORE 0x4000
# define SSL_ST_OK 0x03
# define SSL_ST_RENEGOTIATE (0x04|SSL_ST_INIT)
+# define SSL_ST_ERR 0x05
# define SSL_CB_LOOP 0x01
# define SSL_CB_EXIT 0x02
@@ -2303,6 +2304,7 @@ void ERR_load_SSL_strings(void);
# define SSL_F_SSL3_CHANGE_CIPHER_STATE 129
# define SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM 130
# define SSL_F_SSL3_CHECK_CLIENT_HELLO 304
+# define SSL_F_SSL3_CHECK_FINISHED 339
# define SSL_F_SSL3_CLIENT_HELLO 131
# define SSL_F_SSL3_CONNECT 132
# define SSL_F_SSL3_CTRL 213
@@ -2408,6 +2410,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
@@ -2522,6 +2525,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/ssl/ssl_err.c b/ssl/ssl_err.c
index ac7312e31ba9..88621b72500f 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -160,6 +160,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
{ERR_FUNC(SSL_F_SSL3_DO_CHANGE_CIPHER_SPEC),
"SSL3_DO_CHANGE_CIPHER_SPEC"},
{ERR_FUNC(SSL_F_SSL3_ENC), "SSL3_ENC"},
+ {ERR_FUNC(SSL_F_SSL3_CHECK_FINISHED), "SSL3_CHECK_FINISHED"},
{ERR_FUNC(SSL_F_SSL3_GENERATE_KEY_BLOCK), "SSL3_GENERATE_KEY_BLOCK"},
{ERR_FUNC(SSL_F_SSL3_GET_CERTIFICATE_REQUEST),
"SSL3_GET_CERTIFICATE_REQUEST"},
@@ -298,6 +299,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),
@@ -440,6 +442,7 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
{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"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index dead126184a8..e11746a69508 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1440,9 +1440,13 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p,
SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
return (NULL);
}
- if ((skp == NULL) || (*skp == NULL))
+ if ((skp == NULL) || (*skp == NULL)) {
sk = sk_SSL_CIPHER_new_null(); /* change perhaps later */
- else {
+ if(sk == NULL) {
+ SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ } else {
sk = *skp;
sk_SSL_CIPHER_zero(sk);
}
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index aff3b65d1702..a7f3f8dad4aa 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -865,6 +865,7 @@ 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);
int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index fb4e8c52598f..1ad9dc79493c 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -227,6 +227,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)
{
@@ -478,9 +602,14 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
int r;
#endif
- if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
+ if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH)
goto err;
+ if (session_id + len > limit) {
+ fatal = 1;
+ goto err;
+ }
+
if (len == 0)
try_session_cache = 0;
diff --git a/ssl/ssl_stat.c b/ssl/ssl_stat.c
index d725d7834239..1b9069f978d2 100644
--- a/ssl/ssl_stat.c
+++ b/ssl/ssl_stat.c
@@ -117,6 +117,9 @@ const char *SSL_state_string_long(const SSL *s)
case SSL_ST_OK | SSL_ST_ACCEPT:
str = "ok/accept SSL initialization";
break;
+ case SSL_ST_ERR:
+ str = "error";
+ break;
#ifndef OPENSSL_NO_SSL2
case SSL2_ST_CLIENT_START_ENCRYPTION:
str = "SSLv2 client start encryption";
@@ -496,6 +499,9 @@ const char *SSL_state_string(const SSL *s)
case SSL_ST_OK:
str = "SSLOK ";
break;
+ case SSL_ST_ERR:
+ str = "SSLERR";
+ break;
#ifndef OPENSSL_NO_SSL2
case SSL2_ST_CLIENT_START_ENCRYPTION:
str = "2CSENC";
diff --git a/ssl/ssltest.c b/ssl/ssltest.c
index 8efbff738e81..6a0c293aa5ae 100644
--- a/ssl/ssltest.c
+++ b/ssl/ssltest.c
@@ -336,7 +336,9 @@ static void sv_usage(void)
" -bytes <val> - number of bytes to swap between client/server\n");
#ifndef OPENSSL_NO_DH
fprintf(stderr,
- " -dhe1024 - use 1024 bit key (safe prime) for DHE\n");
+ " -dhe512 - use 512 bit key for DHE (to test failure)\n");
+ fprintf(stderr,
+ " -dhe1024 - use 1024 bit key (safe prime) for DHE (default, no-op)\n");
fprintf(stderr,
" -dhe1024dsa - use 1024 bit key (with 160-bit subprime) for DHE\n");
fprintf(stderr, " -no_dhe - disable DHE\n");
@@ -531,7 +533,7 @@ int main(int argc, char *argv[])
long bytes = 256L;
#ifndef OPENSSL_NO_DH
DH *dh;
- int dhe1024 = 0, dhe1024dsa = 0;
+ int dhe512 = 0, dhe1024dsa = 0;
#endif
#ifndef OPENSSL_NO_ECDH
EC_KEY *ecdh = NULL;
@@ -611,19 +613,19 @@ int main(int argc, char *argv[])
debug = 1;
else if (strcmp(*argv, "-reuse") == 0)
reuse = 1;
- else if (strcmp(*argv, "-dhe1024") == 0) {
+ else if (strcmp(*argv, "-dhe512") == 0) {
#ifndef OPENSSL_NO_DH
- dhe1024 = 1;
+ dhe512 = 1;
#else
fprintf(stderr,
- "ignoring -dhe1024, since I'm compiled without DH\n");
+ "ignoring -dhe512, since I'm compiled without DH\n");
#endif
} else if (strcmp(*argv, "-dhe1024dsa") == 0) {
#ifndef OPENSSL_NO_DH
dhe1024dsa = 1;
#else
fprintf(stderr,
- "ignoring -dhe1024, since I'm compiled without DH\n");
+ "ignoring -dhe1024dsa, since I'm compiled without DH\n");
#endif
} else if (strcmp(*argv, "-no_dhe") == 0)
no_dhe = 1;
@@ -905,10 +907,10 @@ int main(int argc, char *argv[])
*/
SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
dh = get_dh1024dsa();
- } else if (dhe1024)
- dh = get_dh1024();
- else
+ } else if (dhe512)
dh = get_dh512();
+ else
+ dh = get_dh1024();
SSL_CTX_set_tmp_dh(s_ctx, dh);
DH_free(dh);
}
diff --git a/ssl/t1_enc.c b/ssl/t1_enc.c
index 4e2845fa6ec9..8f45294e5579 100644
--- a/ssl/t1_enc.c
+++ b/ssl/t1_enc.c
@@ -261,7 +261,7 @@ static int tls1_PRF(long digest_mask,
if ((m << TLS1_PRF_DGST_SHIFT) & digest_mask)
count++;
}
- if(!count) {
+ if (!count) {
/* Should never happen */
SSLerr(SSL_F_TLS1_PRF, ERR_R_INTERNAL_ERROR);
goto err;
@@ -785,7 +785,7 @@ int tls1_enc(SSL *s, int send)
bs = EVP_CIPHER_block_size(ds->cipher);
if (EVP_CIPHER_flags(ds->cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
- unsigned char buf[13], *seq;
+ unsigned char buf[EVP_AEAD_TLS1_AAD_LEN], *seq;
seq = send ? s->s3->write_sequence : s->s3->read_sequence;
@@ -809,7 +809,10 @@ int tls1_enc(SSL *s, int send)
buf[10] = (unsigned char)(s->version);
buf[11] = rec->length >> 8;
buf[12] = rec->length & 0xff;
- pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD, 13, buf);
+ pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
+ EVP_AEAD_TLS1_AAD_LEN, buf);
+ if (pad <= 0)
+ return -1;
if (send) {
l += pad;
rec->length += pad;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 243a70f7a608..c2d7d720712a 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1016,19 +1016,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
s->srtp_profile = NULL;
- if (data >= (d + n - 2))
- goto ri_check;
+ 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)) {
n2s(data, type);
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
@@ -1064,16 +1068,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
int servname_type;
int dsize;
- if (size < 2) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (size < 2)
+ goto err;
n2s(data, dsize);
size -= 2;
- if (dsize > size) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (dsize > size)
+ goto err;
sdata = data;
while (dsize > 3) {
@@ -1081,18 +1081,16 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
n2s(sdata, len);
dsize -= 3;
- if (len > dsize) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (len > dsize)
+ goto err;
+
if (s->servername_done == 0)
switch (servname_type) {
case TLSEXT_NAMETYPE_host_name:
if (!s->hit) {
- if (s->session->tlsext_hostname) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (s->session->tlsext_hostname)
+ goto err;
+
if (len > TLSEXT_MAXLEN_host_name) {
*al = TLS1_AD_UNRECOGNIZED_NAME;
return 0;
@@ -1126,31 +1124,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
dsize -= len;
}
- if (dsize != 0) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (dsize != 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;
- }
- if (s->srp_ctx.login != NULL) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (size == 0 || ((len = data[0])) != (size - 1))
+ goto err;
+ if (s->srp_ctx.login != NULL)
+ 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;
- }
+ if (strlen(s->srp_ctx.login) != len)
+ goto err;
}
# endif
@@ -1159,10 +1149,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
unsigned char *sdata = data;
int ecpointformatlist_length = *(sdata++);
- if (ecpointformatlist_length != size - 1) {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
+ if (ecpointformatlist_length != size - 1)
+ goto err;
if (!s->hit) {
if (s->session->tlsext_ecpointformatlist) {
OPENSSL_free(s->session->tlsext_ecpointformatlist);
@@ -1196,15 +1184,13 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
if (ellipticcurvelist_length != size - 2 ||
ellipticcurvelist_length < 1 ||
/* Each NamedCurve is 2 bytes. */
- ellipticcurvelist_length & 1) {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
+ ellipticcurvelist_length & 1)
+ goto err;
+
if (!s->hit) {
- if (s->session->tlsext_ellipticcurvelist) {
- *al = TLS1_AD_DECODE_ERROR;
- return 0;
- }
+ if (s->session->tlsext_ellipticcurvelist)
+ goto err;
+
s->session->tlsext_ellipticcurvelist_length = 0;
if ((s->session->tlsext_ellipticcurvelist =
OPENSSL_malloc(ellipticcurvelist_length)) == NULL) {
@@ -1273,28 +1259,20 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
renegotiate_seen = 1;
} else if (type == TLSEXT_TYPE_signature_algorithms) {
int dsize;
- if (sigalg_seen || size < 2) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (sigalg_seen || size < 2)
+ goto err;
sigalg_seen = 1;
n2s(data, dsize);
size -= 2;
- if (dsize != size || dsize & 1) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
- if (!tls1_process_sigalgs(s, data, dsize)) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (dsize != size || dsize & 1)
+ goto err;
+ if (!tls1_process_sigalgs(s, data, dsize))
+ goto err;
} else if (type == TLSEXT_TYPE_status_request &&
s->version != DTLS1_VERSION) {
- if (size < 5) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (size < 5)
+ goto err;
s->tlsext_status_type = *data++;
size--;
@@ -1304,35 +1282,26 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
/* Read in responder_id_list */
n2s(data, dsize);
size -= 2;
- if (dsize > size) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (dsize > size)
+ goto err;
while (dsize > 0) {
OCSP_RESPID *id;
int idsize;
- if (dsize < 4) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (dsize < 4)
+ goto err;
n2s(data, idsize);
dsize -= 2 + idsize;
size -= 2 + idsize;
- if (dsize < 0) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (dsize < 0)
+ goto err;
sdata = data;
data += idsize;
id = d2i_OCSP_RESPID(NULL, &sdata, idsize);
- if (!id) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (!id)
+ 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 =
@@ -1349,16 +1318,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
}
/* Read in request_extensions */
- if (size < 2) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (size < 2)
+ goto err;
n2s(data, dsize);
size -= 2;
- if (dsize != size) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (dsize != size)
+ goto err;
sdata = data;
if (dsize > 0) {
if (s->tlsext_ocsp_exts) {
@@ -1368,10 +1333,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
s->tlsext_ocsp_exts =
d2i_X509_EXTENSIONS(NULL, &sdata, dsize);
- if (!s->tlsext_ocsp_exts || (data + dsize != sdata)) {
- *al = SSL_AD_DECODE_ERROR;
- return 0;
- }
+ if (!s->tlsext_ocsp_exts || (data + dsize != sdata))
+ goto err;
}
}
/*
@@ -1432,6 +1395,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
data += size;
}
+ /* Spurious data on the end */
+ if (data != d + n)
+ goto err;
+
*p = data;
ri_check:
@@ -1447,6 +1414,9 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
}
return 1;
+err:
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
}
# ifndef OPENSSL_NO_NEXTPROTONEG
@@ -2612,7 +2582,10 @@ int tls1_process_heartbeat(SSL *s)
memcpy(bp, pl, payload);
bp += payload;
/* Random padding */
- RAND_pseudo_bytes(bp, padding);
+ if (RAND_pseudo_bytes(bp, padding) < 0) {
+ OPENSSL_free(buffer);
+ return -1;
+ }
r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer,
3 + payload + padding);
@@ -2647,7 +2620,7 @@ int tls1_process_heartbeat(SSL *s)
int tls1_heartbeat(SSL *s)
{
unsigned char *buf, *p;
- int ret;
+ int ret = -1;
unsigned int payload = 18; /* Sequence number + random bytes */
unsigned int padding = 16; /* Use minimum padding */
@@ -2695,10 +2668,16 @@ int tls1_heartbeat(SSL *s)
/* Sequence number */
s2n(s->tlsext_hb_seq, p);
/* 16 random bytes */
- RAND_pseudo_bytes(p, 16);
+ if (RAND_pseudo_bytes(p, 16) < 0) {
+ SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
p += 16;
/* Random padding */
- RAND_pseudo_bytes(p, padding);
+ if (RAND_pseudo_bytes(p, padding) < 0) {
+ SSLerr(SSL_F_TLS1_HEARTBEAT, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
ret = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buf, 3 + payload + padding);
if (ret >= 0) {
@@ -2710,6 +2689,7 @@ int tls1_heartbeat(SSL *s)
s->tlsext_hb_pending = 1;
}
+err:
OPENSSL_free(buf);
return ret;
diff --git a/ssl/tls_srp.c b/ssl/tls_srp.c
index d36cfa0a5c2d..bb719ba4cf9f 100644
--- a/ssl/tls_srp.c
+++ b/ssl/tls_srp.c
@@ -454,7 +454,8 @@ int SRP_Calc_A_param(SSL *s)
{
unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
- RAND_bytes(rnd, sizeof(rnd));
+ if (RAND_bytes(rnd, sizeof(rnd)) <= 0)
+ return -1;
s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
OPENSSL_cleanse(rnd, sizeof(rnd));