summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ssl/d1_srtp.c57
-rw-r--r--ssl/s3_srvr.c169
-rw-r--r--ssl/ssl_locl.h17
-rw-r--r--ssl/ssl_sess.c11
-rw-r--r--ssl/t1_lib.c407
-rw-r--r--ssl/t1_reneg.c19
6 files changed, 344 insertions, 336 deletions
diff --git a/ssl/d1_srtp.c b/ssl/d1_srtp.c
index 19cf6ff396..4384edabc6 100644
--- a/ssl/d1_srtp.c
+++ b/ssl/d1_srtp.c
@@ -266,38 +266,18 @@ int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
return 0;
}
-int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
- int *al)
+int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al)
{
SRTP_PROTECTION_PROFILE *sprof;
STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
- int ct;
- int mki_len;
+ unsigned int ct, mki_len, id;
int i, srtp_pref;
- unsigned int id;
-
- /* Length value + the MKI length */
- if (len < 3) {
- SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
- SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- *al = SSL_AD_DECODE_ERROR;
- return 1;
- }
-
- /* Pull off the length of the cipher suite list */
- n2s(d, ct);
- len -= 2;
+ PACKET subpkt;
- /* Check that it is even */
- if (ct % 2) {
- SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
- SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
- *al = SSL_AD_DECODE_ERROR;
- return 1;
- }
-
- /* Check that lengths are consistent */
- if (len < (ct + 1)) {
+ /* Pull off the length of the cipher suite list and check it is even */
+ if (!PACKET_get_net_2(pkt, &ct)
+ || (ct & 1) != 0
+ || !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
*al = SSL_AD_DECODE_ERROR;
@@ -309,10 +289,13 @@ int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
/* Search all profiles for a match initially */
srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
- while (ct) {
- n2s(d, id);
- ct -= 2;
- len -= 2;
+ while (PACKET_remaining(&subpkt)) {
+ if (!PACKET_get_net_2(&subpkt, &id)) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
/*
* Only look for match in profiles of higher preference than
@@ -333,11 +316,15 @@ int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
/*
* Now extract the MKI value as a sanity check, but discard it for now
*/
- mki_len = *d;
- d++;
- len--;
+ if (!PACKET_get_1(pkt, &mki_len)) {
+ SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+ SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+ *al = SSL_AD_DECODE_ERROR;
+ return 1;
+ }
- if (mki_len != len) {
+ if (!PACKET_forward(pkt, mki_len)
+ || PACKET_remaining(pkt)) {
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
SSL_R_BAD_SRTP_MKI_VALUE);
*al = SSL_AD_DECODE_ERROR;
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 718ca2c31b..bc7f84f2d1 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -862,11 +862,11 @@ int ssl3_send_hello_request(SSL *s)
int ssl3_get_client_hello(SSL *s)
{
- int i, complen, j, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
- unsigned int cookie_len;
+ int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
+ unsigned int j, cipherlen, complen;
+ unsigned int cookie_len = 0;
long n;
unsigned long id;
- unsigned char *p, *d;
SSL_CIPHER *c;
#ifndef OPENSSL_NO_COMP
unsigned char *q = NULL;
@@ -874,6 +874,8 @@ int ssl3_get_client_hello(SSL *s)
#endif
STACK_OF(SSL_CIPHER) *ciphers = NULL;
int protverr = 1;
+ PACKET pkt;
+ unsigned char *sess, *cdata;
if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet)
goto retry_cert;
@@ -897,10 +899,12 @@ int ssl3_get_client_hello(SSL *s)
if (!ok)
return ((int)n);
s->first_packet = 0;
- d = p = (unsigned char *)s->init_msg;
+ PACKET_buf_init(&pkt, s->init_msg, n);
/* First lets get s->client_version set correctly */
if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
+ unsigned int version;
+ unsigned int mt;
/*-
* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
* header is sent directly on the wire, not wrapped as a TLS
@@ -916,7 +920,8 @@ int ssl3_get_client_hello(SSL *s)
* ... ...
*/
- if (p[0] != SSL2_MT_CLIENT_HELLO) {
+ if (!PACKET_get_1(&pkt, &mt)
+ || mt != SSL2_MT_CLIENT_HELLO) {
/*
* Should never happen. We should have tested this in the record
* layer in order to have determined that this is a SSLv2 record
@@ -926,13 +931,18 @@ int ssl3_get_client_hello(SSL *s)
goto err;
}
- if ((p[1] == 0x00) && (p[2] == 0x02)) {
+ if (!PACKET_get_net_2(&pkt, &version)) {
+ /* No protocol version supplied! */
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+ goto err;
+ }
+ if (version == 0x0002) {
/* This is real SSLv2. We don't support it. */
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
goto err;
- } else if (p[1] == SSL3_VERSION_MAJOR) {
+ } else if ((version & 0xff00) == (SSL3_VERSION_MAJOR << 8)) {
/* SSLv3/TLS */
- s->client_version = (((int)p[1]) << 8) | (int)p[2];
+ s->client_version = version;
} else {
/* No idea what protocol this is */
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
@@ -940,20 +950,14 @@ int ssl3_get_client_hello(SSL *s)
}
} else {
/*
- * 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte
- * for session id length
+ * use version from inside client hello, not from record header (may
+ * differ: see RFC 2246, Appendix E, second paragraph)
*/
- if (n < 2 + SSL3_RANDOM_SIZE + 1) {
+ if(!PACKET_get_net_2(&pkt, (unsigned int *)&s->client_version)) {
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)
- */
- s->client_version = (((int)p[0]) << 8) | (int)p[1];
}
/* Do SSL/TLS version negotiation if applicable */
@@ -1032,15 +1036,9 @@ int ssl3_get_client_hello(SSL *s)
*/
unsigned int csl, sil, cl;
- p += 3;
- n2s(p, csl);
- n2s(p, sil);
- n2s(p, cl);
-
- if (csl + sil + cl + MIN_SSL2_RECORD_LEN != (unsigned int) n) {
- SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
- al = SSL_AD_DECODE_ERROR;
- goto f_err;
+ if (!PACKET_get_net_2(&pkt, &csl)
+ || !PACKET_get_net_2(&pkt, &sil)
+ || !PACKET_get_net_2(&pkt, &cl)) {
}
if (csl == 0) {
@@ -1050,7 +1048,13 @@ int ssl3_get_client_hello(SSL *s)
goto f_err;
}
- if (ssl_bytes_to_cipher_list(s, p, csl, &(ciphers), 1) == NULL) {
+ if (!PACKET_get_bytes(&pkt, &cdata, csl)) {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
+
+ if (ssl_bytes_to_cipher_list(s, cdata, csl, &(ciphers), 1) == NULL) {
goto err;
}
@@ -1058,6 +1062,11 @@ int ssl3_get_client_hello(SSL *s)
* Ignore any session id. We don't allow resumption in a backwards
* compatible ClientHello
*/
+ if (!PACKET_forward(&pkt, sil)) {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
s->hit = 0;
if (!ssl_get_new_session(s, 1))
@@ -1066,17 +1075,27 @@ int ssl3_get_client_hello(SSL *s)
/* Load the client random */
i = (cl > SSL3_RANDOM_SIZE) ? SSL3_RANDOM_SIZE : cl;
memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE);
- memcpy(s->s3->client_random, &(p[csl + sil]), i);
-
- /* Set p to end of packet to ensure we don't look for extensions */
- p = d + n;
+ if (!PACKET_peek_copy_bytes(&pkt, s->s3->client_random, i)
+ || !PACKET_forward(&pkt, cl)
+ || !PACKET_remaining(&pkt) == 0) {
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
+ al = SSL_AD_DECODE_ERROR;
+ goto f_err;
+ }
/* No compression, so set complen to 0 */
complen = 0;
} else {
/* If we get here we've got SSLv3+ in an SSLv3+ record */
- p += 2;
+ /* load the client random and get the session-id */
+ if (!PACKET_copy_bytes(&pkt, s->s3->client_random, SSL3_RANDOM_SIZE)
+ || !PACKET_get_1(&pkt, &j)
+ || !PACKET_get_bytes(&pkt, &sess, j)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
/*
* If we require cookies and this ClientHello doesn't contain one, just
@@ -1084,34 +1103,17 @@ int ssl3_get_client_hello(SSL *s)
* cookie length...
*/
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
- unsigned int session_length, cookie_length;
- session_length = *(p + SSL3_RANDOM_SIZE);
-
- if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) {
+ if (!PACKET_peek_1(&pkt, &cookie_len)) {
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)
+ if (cookie_len == 0)
return 1;
}
- /* load the client random */
- memcpy(s->s3->client_random, p, SSL3_RANDOM_SIZE);
- p += SSL3_RANDOM_SIZE;
-
- /* 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
@@ -1131,7 +1133,7 @@ int ssl3_get_client_hello(SSL *s)
if (!ssl_get_new_session(s, 1))
goto err;
} else {
- i = ssl_get_prev_session(s, p, j, d + n);
+ i = ssl_get_prev_session(s, &pkt, sess, j);
/*
* Only resume if the session's version matches the negotiated
* version.
@@ -1153,23 +1155,12 @@ int ssl3_get_client_hello(SSL *s)
}
}
- p += j;
-
if (SSL_IS_DTLS(s)) {
- /* cookie stuff */
- if (p + 1 > d + n) {
+ if (!PACKET_get_1(&pkt, &cookie_len)) {
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
@@ -1185,7 +1176,13 @@ int ssl3_get_client_hello(SSL *s)
/* verify the cookie if appropriate option is set. */
if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
&& cookie_len > 0) {
- memcpy(s->d1->rcvd_cookie, p, cookie_len);
+ /* Get cookie */
+ if (!PACKET_copy_bytes(&pkt, s->d1->rcvd_cookie,
+ cookie_len)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
if (s->ctx->app_verify_cookie_cb != NULL) {
if (s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie,
@@ -1206,9 +1203,15 @@ int ssl3_get_client_hello(SSL *s)
}
/* Set to -2 so if successful we return 2 */
ret = -2;
+ } else {
+ /* Skip over cookie */
+ if (!PACKET_forward(&pkt, cookie_len)) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
}
- p += cookie_len;
if (s->method->version == DTLS_ANY_VERSION) {
/* Select version to use */
if (s->client_version <= DTLS1_2_VERSION &&
@@ -1236,30 +1239,28 @@ int ssl3_get_client_hello(SSL *s)
}
}
- if (p + 2 > d + n) {
+ if (!PACKET_get_net_2(&pkt, &cipherlen)) {
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) {
+ if (cipherlen == 0) {
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
goto f_err;
}
- /* i bytes of cipher data + 1 byte for compression length later */
- if ((p + i + 1) > (d + n)) {
+ if (!PACKET_get_bytes(&pkt, &cdata, cipherlen)) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
- if (ssl_bytes_to_cipher_list(s, p, i, &(ciphers), 0) == NULL) {
+
+ if (ssl_bytes_to_cipher_list(s, cdata, cipherlen, &(ciphers), 0) == NULL) {
goto err;
}
- p += i;
/* If it is a hit, check that the cipher is in the list */
if (s->hit) {
@@ -1316,22 +1317,22 @@ int ssl3_get_client_hello(SSL *s)
}
/* compression */
- complen = *(p++);
- if ((p + complen) > (d + n)) {
+ if (!PACKET_get_1(&pkt, &complen)
+ || !PACKET_get_bytes(&pkt, &cdata, complen)) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
goto f_err;
}
+
#ifndef OPENSSL_NO_COMP
- q = p;
+ q = cdata;
#endif
for (j = 0; j < complen; j++) {
- if (p[j] == 0)
+ if (cdata[j] == 0)
break;
}
- p += complen;
if (j >= complen) {
/* no compress */
al = SSL_AD_DECODE_ERROR;
@@ -1342,7 +1343,7 @@ int ssl3_get_client_hello(SSL *s)
/* TLS extensions */
if (s->version >= SSL3_VERSION) {
- if (!ssl_parse_clienthello_tlsext(s, &p, d, n)) {
+ if (!ssl_parse_clienthello_tlsext(s, &pkt)) {
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
goto err;
}
@@ -1407,6 +1408,7 @@ int ssl3_get_client_hello(SSL *s)
/* This only happens if we have a cache hit */
if (s->session->compress_meth != 0) {
int m, comp_id = s->session->compress_meth;
+ unsigned int k;
/* Perform sanity checks on resumed compression algorithm */
/* Can't disable compression */
if (!ssl_allow_compression(s)) {
@@ -1428,11 +1430,11 @@ int ssl3_get_client_hello(SSL *s)
goto f_err;
}
/* Look for resumed method in compression list */
- for (m = 0; m < complen; m++) {
- if (q[m] == comp_id)
+ for (k = 0; k < complen; k++) {
+ if (q[k] == comp_id)
break;
}
- if (m >= complen) {
+ if (k >= complen) {
al = SSL_AD_ILLEGAL_PARAMETER;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING);
@@ -1442,7 +1444,8 @@ int ssl3_get_client_hello(SSL *s)
comp = NULL;
else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
/* See if we have a match */
- int m, nn, o, v, done = 0;
+ int m, nn, v, done = 0;
+ unsigned int o;
nn = sk_SSL_COMP_num(s->ctx->comp_methods);
for (m = 0; m < nn; m++) {
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 579b09b270..09975664e9 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1854,8 +1854,8 @@ __owur CERT *ssl_cert_dup(CERT *cert);
void ssl_cert_clear_certs(CERT *c);
void ssl_cert_free(CERT *c);
__owur int ssl_get_new_session(SSL *s, int session);
-__owur int ssl_get_prev_session(SSL *s, unsigned char *session, int len,
- const unsigned char *limit);
+__owur int ssl_get_prev_session(SSL *s, PACKET *pkt, unsigned char *session,
+ int len);
__owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
__owur 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);
@@ -2088,8 +2088,7 @@ __owur unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
unsigned char *limit, int *al);
__owur unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
unsigned char *limit, int *al);
-__owur int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data,
- unsigned char *d, int n);
+__owur int ssl_parse_clienthello_tlsext(SSL *s, PACKET *pkt);
__owur int tls1_set_server_sigalgs(SSL *s);
__owur int ssl_check_clienthello_tlsext_late(SSL *s);
__owur int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data,
@@ -2104,8 +2103,8 @@ __owur int tls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length)
__owur int dtls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length);
# endif
-__owur int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
- const unsigned char *limit, SSL_SESSION **ret);
+__owur int tls1_process_ticket(SSL *s, PACKET *pkt, unsigned char *session_id,
+ int len, SSL_SESSION **ret);
__owur int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
const EVP_MD *md);
@@ -2134,8 +2133,7 @@ __owur int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int l
int *al);
__owur int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
int maxlen);
-__owur int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
- int *al);
+__owur int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
__owur long ssl_get_algorithm2(SSL *s);
__owur size_t tls12_copy_sigalgs(SSL *s, unsigned char *out,
const unsigned char *psig, size_t psiglen);
@@ -2149,8 +2147,7 @@ __owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op);
__owur int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
int maxlen);
-__owur int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
- int *al);
+__owur int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al);
__owur int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
int maxlen);
__owur int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 9063bca415..26a3c43f24 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -547,8 +547,8 @@ int ssl_get_new_session(SSL *s, int session)
* - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1
* if the server should issue a new session ticket (to 0 otherwise).
*/
-int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
- const unsigned char *limit)
+int ssl_get_prev_session(SSL *s, PACKET *pkt, unsigned char *session_id,
+ int len)
{
/* This is used only by servers. */
@@ -560,16 +560,11 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
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;
/* sets s->tlsext_ticket_expected */
- r = tls1_process_ticket(s, session_id, len, limit, &ret);
+ r = tls1_process_ticket(s, pkt, session_id, len, &ret);
switch (r) {
case -1: /* Error during processing */
fatal = 1;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 47abf2b9f9..c0dd35f9c8 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1756,46 +1756,33 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
* alert value to send in the event of a non-zero return. returns: 0 on
* success.
*/
-static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data,
- unsigned data_len, int *al)
+static int tls1_alpn_handle_client_hello(SSL *s, PACKET *pkt, int *al)
{
- unsigned i;
- unsigned proto_len;
+ unsigned int data_len;
+ unsigned int proto_len;
const unsigned char *selected;
+ unsigned char *data;
unsigned char selected_len;
int r;
if (s->ctx->alpn_select_cb == NULL)
return 0;
- if (data_len < 2)
- goto parse_error;
-
/*
* data should contain a uint16 length followed by a series of 8-bit,
* length-prefixed strings.
*/
- i = ((unsigned)data[0]) << 8 | ((unsigned)data[1]);
- data_len -= 2;
- data += 2;
- if (data_len != i)
- goto parse_error;
-
- if (data_len < 2)
+ if (!PACKET_get_net_2(pkt, &data_len)
+ || PACKET_remaining(pkt) != data_len
+ || !PACKET_peek_bytes(pkt, &data, data_len))
goto parse_error;
- for (i = 0; i < data_len;) {
- proto_len = data[i];
- i++;
-
- if (proto_len == 0)
- goto parse_error;
-
- if (i + proto_len < i || i + proto_len > data_len)
+ do {
+ if (!PACKET_get_1(pkt, &proto_len)
+ || proto_len == 0
+ || !PACKET_forward(pkt, proto_len))
goto parse_error;
-
- i += proto_len;
- }
+ } while (PACKET_remaining(pkt));
r = s->ctx->alpn_select_cb(s, &selected, &selected_len, data, data_len,
s->ctx->alpn_select_cb_arg);
@@ -1830,10 +1817,11 @@ static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data,
* Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
* 10.8..10.8.3 (which don't work).
*/
-static void ssl_check_for_safari(SSL *s, const unsigned char *data,
- const unsigned char *d, int n)
+static void ssl_check_for_safari(SSL *s, PACKET *pkt)
{
- unsigned short type, size;
+ unsigned int type, size;
+ unsigned char *eblock1, *eblock2;
+
static const unsigned char kSafariExtensionsBlock[] = {
0x00, 0x0a, /* elliptic_curves extension */
0x00, 0x08, /* 8 bytes */
@@ -1860,38 +1848,34 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
0x02, 0x03, /* SHA-1/ECDSA */
};
- if (data >= (d + n - 2))
+ if (!PACKET_forward(pkt, 2)
+ || !PACKET_get_net_2(pkt, &type)
+ || !PACKET_get_net_2(pkt, &size)
+ || !PACKET_forward(pkt, size))
return;
- data += 2;
-
- if (data > (d + n - 4))
- return;
- n2s(data, type);
- n2s(data, size);
if (type != TLSEXT_TYPE_server_name)
return;
- if (data + size > d + n)
- return;
- data += size;
-
if (TLS1_get_client_version(s) >= TLS1_2_VERSION) {
const size_t len1 = sizeof(kSafariExtensionsBlock);
const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
- if (data + len1 + len2 != d + n)
+ if (!PACKET_get_bytes(pkt, &eblock1, len1)
+ || !PACKET_get_bytes(pkt, &eblock2, len2)
+ || PACKET_remaining(pkt))
return;
- if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
+ if (memcmp(eblock1, kSafariExtensionsBlock, len1) != 0)
return;
- if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0)
+ if (memcmp(eblock2, kSafariTLS12ExtensionsBlock, len2) != 0)
return;
} else {
const size_t len = sizeof(kSafariExtensionsBlock);
- if (data + len != d + n)
+ if (!PACKET_get_bytes(pkt, &eblock1, len)
+ || PACKET_remaining(pkt))
return;
- if (memcmp(data, kSafariExtensionsBlock, len) != 0)
+ if (memcmp(eblock1, kSafariExtensionsBlock, len) != 0)
return;
}
@@ -1899,13 +1883,12 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
}
#endif /* !OPENSSL_NO_EC */
-static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
- unsigned char *d, int n, int *al)
+static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
{
- unsigned short type;
- unsigned short size;
- unsigned short len;
- unsigned char *data = *p;
+ unsigned int type;
+ unsigned int size;
+ unsigned int len;
+ unsigned char *data;
int renegotiate_seen = 0;
s->servername_done = 0;
@@ -1923,8 +1906,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
#ifndef OPENSSL_NO_EC
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
- ssl_check_for_safari(s, data, d, n);
-#endif /* !OPENSSL_NO_EC */
+ ssl_check_for_safari(s, pkt);
+# endif /* !OPENSSL_NO_EC */
/* Clear any signature algorithms extension received */
OPENSSL_free(s->s3->tmp.peer_sigalgs);
@@ -1940,27 +1923,26 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
s->srtp_profile = NULL;
- if (data == d + n)
+ if (PACKET_remaining(pkt) == 0)
goto ri_check;
- if (data > (d + n - 2))
- goto err;
-
- n2s(data, len);
-
- if (data > (d + n - len))
+ if (!PACKET_get_net_2(pkt, &len))
goto err;
- while (data <= (d + n - 4)) {
- n2s(data, type);
- n2s(data, size);
+ while (PACKET_get_net_2(pkt, &type) && PACKET_get_net_2(pkt, &size)) {
+ PACKET subpkt;
- if (data + size > (d + n))
+ if (!PACKET_peek_bytes(pkt, &data, size))
goto err;
+
if (s->tlsext_debug_cb)
s->tlsext_debug_cb(s, 0, type, data, size, s->tlsext_debug_arg);
+
+ if (!PACKET_get_sub_packet(pkt, &subpkt, size))
+ goto err;
+
if (type == TLSEXT_TYPE_renegotiate) {
- if (!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
+ if (!ssl_parse_clienthello_renegotiate_ext(s, &subpkt, al))
return 0;
renegotiate_seen = 1;
} else if (s->version == SSL3_VERSION) {
@@ -1992,23 +1974,18 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
else if (type == TLSEXT_TYPE_server_name) {
unsigned char *sdata;
- int servname_type;
- int dsize;
+ unsigned int servname_type;
+ unsigned int dsize;
+ PACKET ssubpkt;
- if (size < 2)
+ if (!PACKET_get_net_2(&subpkt, &dsize)
+ || !PACKET_get_sub_packet(&subpkt, &ssubpkt, dsize))
goto err;
- n2s(data, dsize);
- size -= 2;
- if (dsize > size)
- goto err;
-
- sdata = data;
- while (dsize > 3) {
- servname_type = *(sdata++);
- n2s(sdata, len);
- dsize -= 3;
- if (len > dsize)
+ while (PACKET_remaining(&ssubpkt) > 3) {
+ if (!PACKET_get_1(&ssubpkt, &servname_type)
+ || !PACKET_get_net_2(&ssubpkt, &len)
+ || PACKET_remaining(&ssubpkt) < len)
goto err;
if (s->servername_done == 0)
@@ -2027,7 +2004,13 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
*al = TLS1_AD_INTERNAL_ERROR;
return 0;
}
- memcpy(s->session->tlsext_hostname, sdata, len);
+ if (!PACKET_copy_bytes(&ssubpkt,
+ (unsigned char *)s->session
+ ->tlsext_hostname,
+ len)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
s->session->tlsext_hostname[len] = '\0';
if (strlen(s->session->tlsext_hostname) != len) {
OPENSSL_free(s->session->tlsext_hostname);
@@ -2037,48 +2020,55 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
}
s->servername_done = 1;
- } else
+ } else {
+ if (!PACKET_get_bytes(&ssubpkt, &sdata, len)) {
+ *al = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
s->servername_done = s->session->tlsext_hostname
&& strlen(s->session->tlsext_hostname) == len
&& strncmp(s->session->tlsext_hostname,
(char *)sdata, len) == 0;
+ }
break;
default:
break;
}
-
- dsize -= len;
}
- if (dsize != 0)
+ /* We shouldn't have any bytes left */
+ if (PACKET_remaining(&ssubpkt))
goto err;
}
#ifndef OPENSSL_NO_SRP
else if (type == TLSEXT_TYPE_srp) {
- if (size == 0 || ((len = data[0])) != (size - 1))
- goto err;
- if (s->srp_ctx.login != NULL)
+ if (!PACKET_get_1(&subpkt, &len)
+ || 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);
+ if (!PACKET_copy_bytes(&subpkt, (unsigned char *)s->srp_ctx.login,
+ len))
+ goto err;
s->srp_ctx.login[len] = '\0';
- if (strlen(s->srp_ctx.login) != len)
+ if (strlen(s->srp_ctx.login) != len
+ || PACKET_remaining(&subpkt))
goto err;
}
#endif
#ifndef OPENSSL_NO_EC
else if (type == TLSEXT_TYPE_ec_point_formats) {
- unsigned char *sdata = data;
- int ecpointformatlist_length = *(sdata++);
+ unsigned int ecpointformatlist_length;
- if (ecpointformatlist_length != size - 1 ||
- ecpointformatlist_length < 1)
+ if (!PACKET_get_1(&subpkt, &ecpointformatlist_length)
+ || ecpointformatlist_length == 0)
goto err;
+
if (!s->hit) {
OPENSSL_free(s->session->tlsext_ecpointformatlist);
s->session->tlsext_ecpointformatlist = NULL;
@@ -2090,19 +2080,26 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
}
s->session->tlsext_ecpointformatlist_length =
ecpointformatlist_length;
- memcpy(s->session->tlsext_ecpointformatlist, sdata,
- ecpointformatlist_length);
+ if (!PACKET_copy_bytes(&subpkt,
+ s->session->tlsext_ecpointformatlist,
+ ecpointformatlist_length))
+ goto err;
+ } else if (!PACKET_forward(&subpkt, ecpointformatlist_length)) {
+ goto err;
+ }
+ /* We should have consumed all the bytes by now */
+ if (PACKET_remaining(&subpkt)) {
+ *al = TLS1_AD_DECODE_ERROR;
+ return 0;
}
} else if (type == TLSEXT_TYPE_elliptic_curves) {
- unsigned char *sdata = data;
- int ellipticcurvelist_length = (*(sdata++) << 8);
- ellipticcurvelist_length += (*(sdata++));
+ unsigned int ellipticcurvelist_length;
- if (ellipticcurvelist_length != size - 2 ||
- ellipticcurvelist_length < 1 ||
- /* Each NamedCurve is 2 bytes. */
- ellipticcurvelist_length & 1)
- goto err;
+ /* Each NamedCurve is 2 bytes and we must have at least 1 */
+ if (!PACKET_get_net_2(&subpkt, &ellipticcurvelist_length)
+ || ellipticcurvelist_length == 0
+ || (ellipticcurvelist_length & 1) != 0)
+ goto err;
if (!s->hit) {
if (s->session->tlsext_ellipticcurvelist)
@@ -2116,54 +2113,63 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
}
s->session->tlsext_ellipticcurvelist_length =
ellipticcurvelist_length;
-