mirror of
https://github.com/openssl/openssl.git
synced 2024-11-21 01:15:20 +08:00
PACKETise ClientHello processing
Uses the new PACKET code to process the incoming ClientHello including all extensions etc. Reviewed-by: Tim Hudson <tjh@openssl.org>
This commit is contained in:
parent
6fc2ef20a9
commit
9ceb2426b0
@ -266,38 +266,18 @@ int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
|
int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al)
|
||||||
int *al)
|
|
||||||
{
|
{
|
||||||
SRTP_PROTECTION_PROFILE *sprof;
|
SRTP_PROTECTION_PROFILE *sprof;
|
||||||
STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
|
STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
|
||||||
int ct;
|
unsigned int ct, mki_len, id;
|
||||||
int mki_len;
|
|
||||||
int i, srtp_pref;
|
int i, srtp_pref;
|
||||||
unsigned int id;
|
PACKET subpkt;
|
||||||
|
|
||||||
/* Length value + the MKI length */
|
/* Pull off the length of the cipher suite list and check it is even */
|
||||||
if (len < 3) {
|
if (!PACKET_get_net_2(pkt, &ct)
|
||||||
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
|
|| (ct & 1) != 0
|
||||||
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
|| !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pull off the length of the cipher suite list */
|
|
||||||
n2s(d, ct);
|
|
||||||
len -= 2;
|
|
||||||
|
|
||||||
/* 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)) {
|
|
||||||
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
|
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
|
||||||
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
*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 */
|
/* Search all profiles for a match initially */
|
||||||
srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
|
srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
|
||||||
|
|
||||||
while (ct) {
|
while (PACKET_remaining(&subpkt)) {
|
||||||
n2s(d, id);
|
if (!PACKET_get_net_2(&subpkt, &id)) {
|
||||||
ct -= 2;
|
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
|
||||||
len -= 2;
|
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
||||||
|
*al = SSL_AD_DECODE_ERROR;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only look for match in profiles of higher preference than
|
* 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
|
* Now extract the MKI value as a sanity check, but discard it for now
|
||||||
*/
|
*/
|
||||||
mki_len = *d;
|
if (!PACKET_get_1(pkt, &mki_len)) {
|
||||||
d++;
|
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
|
||||||
len--;
|
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,
|
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
|
||||||
SSL_R_BAD_SRTP_MKI_VALUE);
|
SSL_R_BAD_SRTP_MKI_VALUE);
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
*al = SSL_AD_DECODE_ERROR;
|
||||||
|
169
ssl/s3_srvr.c
169
ssl/s3_srvr.c
@ -862,11 +862,11 @@ int ssl3_send_hello_request(SSL *s)
|
|||||||
|
|
||||||
int ssl3_get_client_hello(SSL *s)
|
int ssl3_get_client_hello(SSL *s)
|
||||||
{
|
{
|
||||||
int i, complen, j, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
|
int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
|
||||||
unsigned int cookie_len;
|
unsigned int j, cipherlen, complen;
|
||||||
|
unsigned int cookie_len = 0;
|
||||||
long n;
|
long n;
|
||||||
unsigned long id;
|
unsigned long id;
|
||||||
unsigned char *p, *d;
|
|
||||||
SSL_CIPHER *c;
|
SSL_CIPHER *c;
|
||||||
#ifndef OPENSSL_NO_COMP
|
#ifndef OPENSSL_NO_COMP
|
||||||
unsigned char *q = NULL;
|
unsigned char *q = NULL;
|
||||||
@ -874,6 +874,8 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
#endif
|
#endif
|
||||||
STACK_OF(SSL_CIPHER) *ciphers = NULL;
|
STACK_OF(SSL_CIPHER) *ciphers = NULL;
|
||||||
int protverr = 1;
|
int protverr = 1;
|
||||||
|
PACKET pkt;
|
||||||
|
unsigned char *sess, *cdata;
|
||||||
|
|
||||||
if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet)
|
if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet)
|
||||||
goto retry_cert;
|
goto retry_cert;
|
||||||
@ -897,10 +899,12 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
if (!ok)
|
if (!ok)
|
||||||
return ((int)n);
|
return ((int)n);
|
||||||
s->first_packet = 0;
|
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 */
|
/* First lets get s->client_version set correctly */
|
||||||
if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
|
if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
|
||||||
|
unsigned int version;
|
||||||
|
unsigned int mt;
|
||||||
/*-
|
/*-
|
||||||
* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
|
* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
|
||||||
* header is sent directly on the wire, not wrapped as a TLS
|
* 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
|
* Should never happen. We should have tested this in the record
|
||||||
* layer in order to have determined that this is a SSLv2 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;
|
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. */
|
/* This is real SSLv2. We don't support it. */
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
|
||||||
goto err;
|
goto err;
|
||||||
} else if (p[1] == SSL3_VERSION_MAJOR) {
|
} else if ((version & 0xff00) == (SSL3_VERSION_MAJOR << 8)) {
|
||||||
/* SSLv3/TLS */
|
/* SSLv3/TLS */
|
||||||
s->client_version = (((int)p[1]) << 8) | (int)p[2];
|
s->client_version = version;
|
||||||
} else {
|
} else {
|
||||||
/* No idea what protocol this is */
|
/* No idea what protocol this is */
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
|
||||||
@ -940,20 +950,14 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte
|
* use version from inside client hello, not from record header (may
|
||||||
* for session id length
|
* 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;
|
al = SSL_AD_DECODE_ERROR;
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
|
||||||
goto f_err;
|
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 */
|
/* Do SSL/TLS version negotiation if applicable */
|
||||||
@ -1032,15 +1036,9 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
*/
|
*/
|
||||||
unsigned int csl, sil, cl;
|
unsigned int csl, sil, cl;
|
||||||
|
|
||||||
p += 3;
|
if (!PACKET_get_net_2(&pkt, &csl)
|
||||||
n2s(p, csl);
|
|| !PACKET_get_net_2(&pkt, &sil)
|
||||||
n2s(p, sil);
|
|| !PACKET_get_net_2(&pkt, &cl)) {
|
||||||
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 (csl == 0) {
|
if (csl == 0) {
|
||||||
@ -1050,7 +1048,13 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
goto f_err;
|
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;
|
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
|
* Ignore any session id. We don't allow resumption in a backwards
|
||||||
* compatible ClientHello
|
* 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;
|
s->hit = 0;
|
||||||
|
|
||||||
if (!ssl_get_new_session(s, 1))
|
if (!ssl_get_new_session(s, 1))
|
||||||
@ -1066,17 +1075,27 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
/* Load the client random */
|
/* Load the client random */
|
||||||
i = (cl > SSL3_RANDOM_SIZE) ? SSL3_RANDOM_SIZE : cl;
|
i = (cl > SSL3_RANDOM_SIZE) ? SSL3_RANDOM_SIZE : cl;
|
||||||
memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE);
|
memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE);
|
||||||
memcpy(s->s3->client_random, &(p[csl + sil]), i);
|
if (!PACKET_peek_copy_bytes(&pkt, s->s3->client_random, i)
|
||||||
|
|| !PACKET_forward(&pkt, cl)
|
||||||
/* Set p to end of packet to ensure we don't look for extensions */
|
|| !PACKET_remaining(&pkt) == 0) {
|
||||||
p = d + n;
|
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 */
|
/* No compression, so set complen to 0 */
|
||||||
complen = 0;
|
complen = 0;
|
||||||
} else {
|
} else {
|
||||||
/* If we get here we've got SSLv3+ in an SSLv3+ record */
|
/* 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
|
* 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...
|
* cookie length...
|
||||||
*/
|
*/
|
||||||
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
|
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
|
||||||
unsigned int session_length, cookie_length;
|
|
||||||
|
|
||||||
session_length = *(p + SSL3_RANDOM_SIZE);
|
if (!PACKET_peek_1(&pkt, &cookie_len)) {
|
||||||
|
|
||||||
if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) {
|
|
||||||
al = SSL_AD_DECODE_ERROR;
|
al = SSL_AD_DECODE_ERROR;
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);
|
|
||||||
|
|
||||||
if (cookie_length == 0)
|
if (cookie_len == 0)
|
||||||
return 1;
|
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;
|
s->hit = 0;
|
||||||
/*
|
/*
|
||||||
* Versions before 0.9.7 always allow clients to resume sessions in
|
* 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))
|
if (!ssl_get_new_session(s, 1))
|
||||||
goto err;
|
goto err;
|
||||||
} else {
|
} 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
|
* Only resume if the session's version matches the negotiated
|
||||||
* version.
|
* version.
|
||||||
@ -1153,23 +1155,12 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p += j;
|
|
||||||
|
|
||||||
if (SSL_IS_DTLS(s)) {
|
if (SSL_IS_DTLS(s)) {
|
||||||
/* cookie stuff */
|
if (!PACKET_get_1(&pkt, &cookie_len)) {
|
||||||
if (p + 1 > d + n) {
|
|
||||||
al = SSL_AD_DECODE_ERROR;
|
al = SSL_AD_DECODE_ERROR;
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
|
||||||
goto f_err;
|
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
|
* The ClientHello may contain a cookie even if the
|
||||||
* HelloVerify message has not been sent--make sure that it
|
* 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. */
|
/* verify the cookie if appropriate option is set. */
|
||||||
if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
|
if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
|
||||||
&& cookie_len > 0) {
|
&& 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 != NULL) {
|
||||||
if (s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie,
|
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 */
|
/* Set to -2 so if successful we return 2 */
|
||||||
ret = -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) {
|
if (s->method->version == DTLS_ANY_VERSION) {
|
||||||
/* Select version to use */
|
/* Select version to use */
|
||||||
if (s->client_version <= DTLS1_2_VERSION &&
|
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;
|
al = SSL_AD_DECODE_ERROR;
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
n2s(p, i);
|
|
||||||
|
|
||||||
if (i == 0) {
|
if (cipherlen == 0) {
|
||||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* i bytes of cipher data + 1 byte for compression length later */
|
if (!PACKET_get_bytes(&pkt, &cdata, cipherlen)) {
|
||||||
if ((p + i + 1) > (d + n)) {
|
|
||||||
/* not enough data */
|
/* not enough data */
|
||||||
al = SSL_AD_DECODE_ERROR;
|
al = SSL_AD_DECODE_ERROR;
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||||
goto f_err;
|
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;
|
goto err;
|
||||||
}
|
}
|
||||||
p += i;
|
|
||||||
|
|
||||||
/* If it is a hit, check that the cipher is in the list */
|
/* If it is a hit, check that the cipher is in the list */
|
||||||
if (s->hit) {
|
if (s->hit) {
|
||||||
@ -1316,22 +1317,22 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* compression */
|
/* compression */
|
||||||
complen = *(p++);
|
if (!PACKET_get_1(&pkt, &complen)
|
||||||
if ((p + complen) > (d + n)) {
|
|| !PACKET_get_bytes(&pkt, &cdata, complen)) {
|
||||||
/* not enough data */
|
/* not enough data */
|
||||||
al = SSL_AD_DECODE_ERROR;
|
al = SSL_AD_DECODE_ERROR;
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_COMP
|
#ifndef OPENSSL_NO_COMP
|
||||||
q = p;
|
q = cdata;
|
||||||
#endif
|
#endif
|
||||||
for (j = 0; j < complen; j++) {
|
for (j = 0; j < complen; j++) {
|
||||||
if (p[j] == 0)
|
if (cdata[j] == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
p += complen;
|
|
||||||
if (j >= complen) {
|
if (j >= complen) {
|
||||||
/* no compress */
|
/* no compress */
|
||||||
al = SSL_AD_DECODE_ERROR;
|
al = SSL_AD_DECODE_ERROR;
|
||||||
@ -1342,7 +1343,7 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
|
|
||||||
/* TLS extensions */
|
/* TLS extensions */
|
||||||
if (s->version >= SSL3_VERSION) {
|
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);
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -1407,6 +1408,7 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
/* This only happens if we have a cache hit */
|
/* This only happens if we have a cache hit */
|
||||||
if (s->session->compress_meth != 0) {
|
if (s->session->compress_meth != 0) {
|
||||||
int m, comp_id = s->session->compress_meth;
|
int m, comp_id = s->session->compress_meth;
|
||||||
|
unsigned int k;
|
||||||
/* Perform sanity checks on resumed compression algorithm */
|
/* Perform sanity checks on resumed compression algorithm */
|
||||||
/* Can't disable compression */
|
/* Can't disable compression */
|
||||||
if (!ssl_allow_compression(s)) {
|
if (!ssl_allow_compression(s)) {
|
||||||
@ -1428,11 +1430,11 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
goto f_err;
|
goto f_err;
|
||||||
}
|
}
|
||||||
/* Look for resumed method in compression list */
|
/* Look for resumed method in compression list */
|
||||||
for (m = 0; m < complen; m++) {
|
for (k = 0; k < complen; k++) {
|
||||||
if (q[m] == comp_id)
|
if (q[k] == comp_id)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (m >= complen) {
|
if (k >= complen) {
|
||||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
|
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
|
||||||
SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING);
|
SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING);
|
||||||
@ -1442,7 +1444,8 @@ int ssl3_get_client_hello(SSL *s)
|
|||||||
comp = NULL;
|
comp = NULL;
|
||||||
else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
|
else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
|
||||||
/* See if we have a match */
|
/* 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);
|
nn = sk_SSL_COMP_num(s->ctx->comp_methods);
|
||||||
for (m = 0; m < nn; m++) {
|
for (m = 0; m < nn; m++) {
|
||||||
|
@ -1854,8 +1854,8 @@ __owur CERT *ssl_cert_dup(CERT *cert);
|
|||||||
void ssl_cert_clear_certs(CERT *c);
|
void ssl_cert_clear_certs(CERT *c);
|
||||||
void ssl_cert_free(CERT *c);
|
void ssl_cert_free(CERT *c);
|
||||||
__owur int ssl_get_new_session(SSL *s, int session);
|
__owur int ssl_get_new_session(SSL *s, int session);
|
||||||
__owur int ssl_get_prev_session(SSL *s, unsigned char *session, int len,
|
__owur int ssl_get_prev_session(SSL *s, PACKET *pkt, unsigned char *session,
|
||||||
const unsigned char *limit);
|
int len);
|
||||||
__owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
|
__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);
|
__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);
|
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);
|
unsigned char *limit, int *al);
|
||||||
__owur unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
|
__owur unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
|
||||||
unsigned char *limit, int *al);
|
unsigned char *limit, int *al);
|
||||||
__owur int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data,
|
__owur int ssl_parse_clienthello_tlsext(SSL *s, PACKET *pkt);
|
||||||
unsigned char *d, int n);
|
|
||||||
__owur int tls1_set_server_sigalgs(SSL *s);
|
__owur int tls1_set_server_sigalgs(SSL *s);
|
||||||
__owur int ssl_check_clienthello_tlsext_late(SSL *s);
|
__owur int ssl_check_clienthello_tlsext_late(SSL *s);
|
||||||
__owur int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data,
|
__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);
|
__owur int dtls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
__owur int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
|
__owur int tls1_process_ticket(SSL *s, PACKET *pkt, unsigned char *session_id,
|
||||||
const unsigned char *limit, SSL_SESSION **ret);
|
int len, SSL_SESSION **ret);
|
||||||
|
|
||||||
__owur int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
|
__owur int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
|
||||||
const EVP_MD *md);
|
const EVP_MD *md);
|
||||||
@ -2134,8 +2133,7 @@ __owur int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int l
|
|||||||
int *al);
|
int *al);
|
||||||
__owur int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
|
__owur int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
|
||||||
int maxlen);
|
int maxlen);
|
||||||
__owur int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
|
__owur int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
|
||||||
int *al);
|
|
||||||
__owur long ssl_get_algorithm2(SSL *s);
|
__owur long ssl_get_algorithm2(SSL *s);
|
||||||
__owur size_t tls12_copy_sigalgs(SSL *s, unsigned char *out,
|
__owur size_t tls12_copy_sigalgs(SSL *s, unsigned char *out,
|
||||||
const unsigned char *psig, size_t psiglen);
|
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,
|
__owur int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
|
||||||
int maxlen);
|
int maxlen);
|
||||||
__owur int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
|
__owur int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al);
|
||||||
int *al);
|
|
||||||
__owur int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
|
__owur int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
|
||||||
int maxlen);
|
int maxlen);
|
||||||
__owur int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,
|
__owur int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,
|
||||||
|
@ -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
|
* - 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).
|
* 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,
|
int ssl_get_prev_session(SSL *s, PACKET *pkt, unsigned char *session_id,
|
||||||
const unsigned char *limit)
|
int len)
|
||||||
{
|
{
|
||||||
/* This is used only by servers. */
|
/* 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)
|
if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (session_id + len > limit) {
|
|
||||||
fatal = 1;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
try_session_cache = 0;
|
try_session_cache = 0;
|
||||||
|
|
||||||
/* sets s->tlsext_ticket_expected */
|
/* 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) {
|
switch (r) {
|
||||||
case -1: /* Error during processing */
|
case -1: /* Error during processing */
|
||||||
fatal = 1;
|
fatal = 1;
|
||||||
|
407
ssl/t1_lib.c
407
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
|
* alert value to send in the event of a non-zero return. returns: 0 on
|
||||||
* success.
|
* success.
|
||||||
*/
|
*/
|
||||||
static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data,
|
static int tls1_alpn_handle_client_hello(SSL *s, PACKET *pkt, int *al)
|
||||||
unsigned data_len, int *al)
|
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned int data_len;
|
||||||
unsigned proto_len;
|
unsigned int proto_len;
|
||||||
const unsigned char *selected;
|
const unsigned char *selected;
|
||||||
|
unsigned char *data;
|
||||||
unsigned char selected_len;
|
unsigned char selected_len;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (s->ctx->alpn_select_cb == NULL)
|
if (s->ctx->alpn_select_cb == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (data_len < 2)
|
|
||||||
goto parse_error;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* data should contain a uint16 length followed by a series of 8-bit,
|
* data should contain a uint16 length followed by a series of 8-bit,
|
||||||
* length-prefixed strings.
|
* length-prefixed strings.
|
||||||
*/
|
*/
|
||||||
i = ((unsigned)data[0]) << 8 | ((unsigned)data[1]);
|
if (!PACKET_get_net_2(pkt, &data_len)
|
||||||
data_len -= 2;
|
|| PACKET_remaining(pkt) != data_len
|
||||||
data += 2;
|
|| !PACKET_peek_bytes(pkt, &data, data_len))
|
||||||
if (data_len != i)
|
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
|
|
||||||
if (data_len < 2)
|
do {
|
||||||
goto parse_error;
|
if (!PACKET_get_1(pkt, &proto_len)
|
||||||
|
|| proto_len == 0
|
||||||
for (i = 0; i < data_len;) {
|
|| !PACKET_forward(pkt, proto_len))
|
||||||
proto_len = data[i];
|
|
||||||
i++;
|
|
||||||
|
|
||||||
if (proto_len == 0)
|
|
||||||
goto parse_error;
|
goto parse_error;
|
||||||
|
} while (PACKET_remaining(pkt));
|
||||||
if (i + proto_len < i || i + proto_len > data_len)
|
|
||||||
goto parse_error;
|
|
||||||
|
|
||||||
i += proto_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
r = s->ctx->alpn_select_cb(s, &selected, &selected_len, data, data_len,
|
r = s->ctx->alpn_select_cb(s, &selected, &selected_len, data, data_len,
|
||||||
s->ctx->alpn_select_cb_arg);
|
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
|
* Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
|
||||||
* 10.8..10.8.3 (which don't work).
|
* 10.8..10.8.3 (which don't work).
|
||||||
*/
|
*/
|
||||||
static void ssl_check_for_safari(SSL *s, const unsigned char *data,
|
static void ssl_check_for_safari(SSL *s, PACKET *pkt)
|
||||||
const unsigned char *d, int n)
|
|
||||||
{
|
{
|
||||||
unsigned short type, size;
|
unsigned int type, size;
|
||||||
|
unsigned char *eblock1, *eblock2;
|
||||||
|
|
||||||
static const unsigned char kSafariExtensionsBlock[] = {
|
static const unsigned char kSafariExtensionsBlock[] = {
|
||||||
0x00, 0x0a, /* elliptic_curves extension */
|
0x00, 0x0a, /* elliptic_curves extension */
|
||||||
0x00, 0x08, /* 8 bytes */
|
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 */
|
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;
|
return;
|
||||||
data += 2;
|
|
||||||
|
|
||||||
if (data > (d + n - 4))
|
|
||||||
return;
|
|
||||||
n2s(data, type);
|
|
||||||
n2s(data, size);
|
|
||||||
|
|
||||||
if (type != TLSEXT_TYPE_server_name)
|
if (type != TLSEXT_TYPE_server_name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (data + size > d + n)
|
|
||||||
return;
|
|
||||||
data += size;
|
|
||||||
|
|
||||||
if (TLS1_get_client_version(s) >= TLS1_2_VERSION) {
|
if (TLS1_get_client_version(s) >= TLS1_2_VERSION) {
|
||||||
const size_t len1 = sizeof(kSafariExtensionsBlock);
|
const size_t len1 = sizeof(kSafariExtensionsBlock);
|
||||||
const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
|
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;
|
return;
|
||||||
if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
|
if (memcmp(eblock1, kSafariExtensionsBlock, len1) != 0)
|
||||||
return;
|
return;
|
||||||
if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0)
|
if (memcmp(eblock2, kSafariTLS12ExtensionsBlock, len2) != 0)
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
const size_t len = sizeof(kSafariExtensionsBlock);
|
const size_t len = sizeof(kSafariExtensionsBlock);
|
||||||
|
|
||||||
if (data + len != d + n)
|
if (!PACKET_get_bytes(pkt, &eblock1, len)
|
||||||
|
|| PACKET_remaining(pkt))
|
||||||
return;
|
return;
|
||||||
if (memcmp(data, kSafariExtensionsBlock, len) != 0)
|
if (memcmp(eblock1, kSafariExtensionsBlock, len) != 0)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1899,13 +1883,12 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
|
|||||||
}
|
}
|
||||||
#endif /* !OPENSSL_NO_EC */
|
#endif /* !OPENSSL_NO_EC */
|
||||||
|
|
||||||
static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
|
static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
|
||||||
unsigned char *d, int n, int *al)
|
|
||||||
{
|
{
|
||||||
unsigned short type;
|
unsigned int type;
|
||||||
unsigned short size;
|
unsigned int size;
|
||||||
unsigned short len;
|
unsigned int len;
|
||||||
unsigned char *data = *p;
|
unsigned char *data;
|
||||||
int renegotiate_seen = 0;
|
int renegotiate_seen = 0;
|
||||||
|
|
||||||
s->servername_done = 0;
|
s->servername_done = 0;
|
||||||
@ -1923,8 +1906,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
|
|||||||
|
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
|
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
|
||||||
ssl_check_for_safari(s, data, d, n);
|
ssl_check_for_safari(s, pkt);
|
||||||
#endif /* !OPENSSL_NO_EC */
|
# endif /* !OPENSSL_NO_EC */
|
||||||
|
|
||||||
/* Clear any signature algorithms extension received */
|
/* Clear any signature algorithms extension received */
|
||||||
OPENSSL_free(s->s3->tmp.peer_sigalgs);
|
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;
|
s->srtp_profile = NULL;
|
||||||
|
|
||||||
if (data == d + n)
|
if (PACKET_remaining(pkt) == 0)
|
||||||
goto ri_check;
|
goto ri_check;
|
||||||
|
|
||||||
if (data > (d + n - 2))
|
if (!PACKET_get_net_2(pkt, &len))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
n2s(data, len);
|
while (PACKET_get_net_2(pkt, &type) && PACKET_get_net_2(pkt, &size)) {
|
||||||
|
PACKET subpkt;
|
||||||
|
|
||||||
if (data > (d + n - len))
|
if (!PACKET_peek_bytes(pkt, &data, size))
|
||||||
goto err;
|
|
||||||
|
|
||||||
while (data <= (d + n - 4)) {
|
|
||||||
n2s(data, type);
|
|
||||||
n2s(data, size);
|
|
||||||
|
|
||||||
if (data + size > (d + n))
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (s->tlsext_debug_cb)
|
if (s->tlsext_debug_cb)
|
||||||
s->tlsext_debug_cb(s, 0, type, data, size, s->tlsext_debug_arg);
|
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 (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;
|
return 0;
|
||||||
renegotiate_seen = 1;
|
renegotiate_seen = 1;
|
||||||
} else if (s->version == SSL3_VERSION) {
|
} 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) {
|
else if (type == TLSEXT_TYPE_server_name) {
|
||||||
unsigned char *sdata;
|
unsigned char *sdata;
|
||||||
int servname_type;
|
unsigned int servname_type;
|
||||||
int dsize;
|
unsigned int dsize;
|
||||||
|
PACKET ssubpkt;
|
||||||
|
|
||||||
if (size < 2)
|
if (!PACKET_get_net_2(&subpkt, &dsize)
|
||||||
goto err;
|
|| !PACKET_get_sub_packet(&subpkt, &ssubpkt, dsize))
|
||||||
n2s(data, dsize);
|
|
||||||
size -= 2;
|
|
||||||
if (dsize > size)
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
sdata = data;
|
while (PACKET_remaining(&ssubpkt) > 3) {
|
||||||
while (dsize > 3) {
|
if (!PACKET_get_1(&ssubpkt, &servname_type)
|
||||||
servname_type = *(sdata++);
|
|| !PACKET_get_net_2(&ssubpkt, &len)
|
||||||
n2s(sdata, len);
|
|| PACKET_remaining(&ssubpkt) < len)
|
||||||
dsize -= 3;
|
|
||||||
|
|
||||||
if (len > dsize)
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (s->servername_done == 0)
|
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;
|
*al = TLS1_AD_INTERNAL_ERROR;
|
||||||
return 0;
|
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';
|
s->session->tlsext_hostname[len] = '\0';
|
||||||
if (strlen(s->session->tlsext_hostname) != len) {
|
if (strlen(s->session->tlsext_hostname) != len) {
|
||||||
OPENSSL_free(s->session->tlsext_hostname);
|
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;
|
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
|
s->servername_done = s->session->tlsext_hostname
|
||||||
&& strlen(s->session->tlsext_hostname) == len
|
&& strlen(s->session->tlsext_hostname) == len
|
||||||
&& strncmp(s->session->tlsext_hostname,
|
&& strncmp(s->session->tlsext_hostname,
|
||||||
(char *)sdata, len) == 0;
|
(char *)sdata, len) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsize -= len;
|
|
||||||
}
|
}
|
||||||
if (dsize != 0)
|
/* We shouldn't have any bytes left */
|
||||||
|
if (PACKET_remaining(&ssubpkt))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifndef OPENSSL_NO_SRP
|
#ifndef OPENSSL_NO_SRP
|
||||||
else if (type == TLSEXT_TYPE_srp) {
|
else if (type == TLSEXT_TYPE_srp) {
|
||||||
if (size == 0 || ((len = data[0])) != (size - 1))
|
if (!PACKET_get_1(&subpkt, &len)
|
||||||
goto err;
|
|| s->srp_ctx.login != NULL)
|
||||||
if (s->srp_ctx.login != NULL)
|
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if ((s->srp_ctx.login = OPENSSL_malloc(len + 1)) == NULL)
|
if ((s->srp_ctx.login = OPENSSL_malloc(len + 1)) == NULL)
|
||||||
return -1;
|
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';
|
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;
|
goto err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
else if (type == TLSEXT_TYPE_ec_point_formats) {
|
else if (type == TLSEXT_TYPE_ec_point_formats) {
|
||||||
unsigned char *sdata = data;
|
unsigned int ecpointformatlist_length;
|
||||||
int ecpointformatlist_length = *(sdata++);
|
|
||||||
|
|
||||||
if (ecpointformatlist_length != size - 1 ||
|
if (!PACKET_get_1(&subpkt, &ecpointformatlist_length)
|
||||||
ecpointformatlist_length < 1)
|
|| ecpointformatlist_length == 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!s->hit) {
|
if (!s->hit) {
|
||||||
OPENSSL_free(s->session->tlsext_ecpointformatlist);
|
OPENSSL_free(s->session->tlsext_ecpointformatlist);
|
||||||
s->session->tlsext_ecpointformatlist = NULL;
|
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 =
|
s->session->tlsext_ecpointformatlist_length =
|
||||||
ecpointformatlist_length;
|
ecpointformatlist_length;
|
||||||
memcpy(s->session->tlsext_ecpointformatlist, sdata,
|
if (!PACKET_copy_bytes(&subpkt,
|
||||||
ecpointformatlist_length);
|
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) {
|
} else if (type == TLSEXT_TYPE_elliptic_curves) {
|
||||||
unsigned char *sdata = data;
|
unsigned int ellipticcurvelist_length;
|
||||||
int ellipticcurvelist_length = (*(sdata++) << 8);
|
|
||||||
ellipticcurvelist_length += (*(sdata++));
|
|
||||||
|
|
||||||
if (ellipticcurvelist_length != size - 2 ||
|
/* Each NamedCurve is 2 bytes and we must have at least 1 */
|
||||||
ellipticcurvelist_length < 1 ||
|
if (!PACKET_get_net_2(&subpkt, &ellipticcurvelist_length)
|
||||||
/* Each NamedCurve is 2 bytes. */
|
|| ellipticcurvelist_length == 0
|
||||||
ellipticcurvelist_length & 1)
|
|| (ellipticcurvelist_length & 1) != 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!s->hit) {
|
if (!s->hit) {
|
||||||
if (s->session->tlsext_ellipticcurvelist)
|
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 =
|
s->session->tlsext_ellipticcurvelist_length =
|
||||||
ellipticcurvelist_length;
|
ellipticcurvelist_length;
|
||||||
memcpy(s->session->tlsext_ellipticcurvelist, sdata,
|
if (!PACKET_copy_bytes(&subpkt,
|
||||||
ellipticcurvelist_length);
|
s->session->tlsext_ellipticcurvelist,
|
||||||
|
ellipticcurvelist_length))
|
||||||
|
goto err;
|
||||||
|
} else if (!PACKET_forward(&subpkt, ellipticcurvelist_length)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* We should have consumed all the bytes by now */
|
||||||
|
if (PACKET_remaining(&subpkt)) {
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* OPENSSL_NO_EC */
|
#endif /* OPENSSL_NO_EC */
|
||||||
else if (type == TLSEXT_TYPE_session_ticket) {
|
else if (type == TLSEXT_TYPE_session_ticket) {
|
||||||
if (s->tls_session_ticket_ext_cb &&
|
if (!PACKET_forward(&subpkt, size)
|
||||||
!s->tls_session_ticket_ext_cb(s, data, size,
|
|| (s->tls_session_ticket_ext_cb &&
|
||||||
s->tls_session_ticket_ext_cb_arg))
|
!s->tls_session_ticket_ext_cb(s, data, size,
|
||||||
{
|
s->tls_session_ticket_ext_cb_arg))) {
|
||||||
*al = TLS1_AD_INTERNAL_ERROR;
|
*al = TLS1_AD_INTERNAL_ERROR;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else if (type == TLSEXT_TYPE_signature_algorithms) {
|
} else if (type == TLSEXT_TYPE_signature_algorithms) {
|
||||||
int dsize;
|
unsigned int dsize;
|
||||||
if (s->s3->tmp.peer_sigalgs || size < 2)
|
|
||||||
goto err;
|
if (s->s3->tmp.peer_sigalgs
|
||||||
n2s(data, dsize);
|
|| !PACKET_get_net_2(&subpkt, &dsize)
|
||||||
size -= 2;
|
|| (dsize & 1) != 0
|
||||||
if (dsize != size || dsize & 1 || !dsize)
|
|| (dsize == 0)
|
||||||
goto err;
|
|| !PACKET_get_bytes(&subpkt, &data, dsize)
|
||||||
if (!tls1_save_sigalgs(s, data, dsize))
|
|| PACKET_remaining(&subpkt)
|
||||||
|
|| !tls1_save_sigalgs(s, data, dsize)) {
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
} else if (type == TLSEXT_TYPE_status_request) {
|
} else if (type == TLSEXT_TYPE_status_request) {
|
||||||
|
PACKET ssubpkt;
|
||||||
|
|
||||||
if (size < 5)
|
if (!PACKET_get_1(&subpkt,
|
||||||
|
(unsigned int *)&s->tlsext_status_type))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
s->tlsext_status_type = *data++;
|
|
||||||
size--;
|
|
||||||
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
|
if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
|
||||||
const unsigned char *sdata;
|
const unsigned char *sdata;
|
||||||
int dsize;
|
unsigned int dsize;
|
||||||
/* Read in responder_id_list */
|
/* Read in responder_id_list */
|
||||||
n2s(data, dsize);
|
if (!PACKET_get_net_2(&subpkt, &dsize)
|
||||||
size -= 2;
|
|| !PACKET_get_sub_packet(&subpkt, &ssubpkt, dsize))
|
||||||
if (dsize > size)
|
|
||||||
goto err;
|
goto err;
|
||||||
while (dsize > 0) {
|
|
||||||
|
while (PACKET_remaining(&ssubpkt)) {
|
||||||
OCSP_RESPID *id;
|
OCSP_RESPID *id;
|
||||||
int idsize;
|
unsigned int idsize;
|
||||||
if (dsize < 4)
|
|
||||||
goto err;
|
if (PACKET_remaining(&ssubpkt) < 4
|
||||||
n2s(data, idsize);
|
|| !PACKET_get_net_2(&ssubpkt, &idsize)
|
||||||
dsize -= 2 + idsize;
|
|| !PACKET_get_bytes(&ssubpkt, &data, idsize)) {
|
||||||
size -= 2 + idsize;
|
|
||||||
if (dsize < 0)
|
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
sdata = data;
|
sdata = data;
|
||||||
data += idsize;
|
data += idsize;
|
||||||
id = d2i_OCSP_RESPID(NULL, &sdata, idsize);
|
id = d2i_OCSP_RESPID(NULL, &sdata, idsize);
|
||||||
@ -2188,12 +2194,11 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read in request_extensions */
|
/* Read in request_extensions */
|
||||||
if (size < 2)
|
if (!PACKET_get_net_2(&subpkt, &dsize)
|
||||||
goto err;
|
|| !PACKET_get_bytes(&subpkt, &data, dsize)
|
||||||
n2s(data, dsize);
|
|| PACKET_remaining(&subpkt)) {
|
||||||
size -= 2;
|
|
||||||
if (dsize != size)
|
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
sdata = data;
|
sdata = data;
|
||||||
if (dsize > 0) {
|
if (dsize > 0) {
|
||||||
sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
|
sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
|
||||||
@ -2212,7 +2217,14 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
|
|||||||
}
|
}
|
||||||
#ifndef OPENSSL_NO_HEARTBEATS
|
#ifndef OPENSSL_NO_HEARTBEATS
|
||||||
else if (type == TLSEXT_TYPE_heartbeat) {
|
else if (type == TLSEXT_TYPE_heartbeat) {
|
||||||
switch (data[0]) {
|
unsigned int hbtype;
|
||||||
|
|
||||||
|
if (!PACKET_get_1(&subpkt, &hbtype)
|
||||||
|
|| PACKET_remaining(&subpkt)) {
|
||||||
|
*al = SSL_AD_DECODE_ERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
switch (hbtype) {
|
||||||
case 0x01: /* Client allows us to send HB requests */
|
case 0x01: /* Client allows us to send HB requests */
|
||||||
s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
|
s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
|
||||||
break;
|
break;
|
||||||
@ -2253,7 +2265,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
|
|||||||
|
|
||||||
else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation &&
|
else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation &&
|
||||||
s->ctx->alpn_select_cb && s->s3->tmp.finish_md_len == 0) {
|
s->ctx->alpn_select_cb && s->s3->tmp.finish_md_len == 0) {
|
||||||
if (tls1_alpn_handle_client_hello(s, data, size, al) != 0)
|
if (tls1_alpn_handle_client_hello(s, &subpkt, al) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
/* ALPN takes precedence over NPN. */
|
/* ALPN takes precedence over NPN. */
|
||||||
@ -2265,7 +2277,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
|
|||||||
#ifndef OPENSSL_NO_SRTP
|
#ifndef OPENSSL_NO_SRTP
|
||||||
else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
|
else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
|
||||||
&& type == TLSEXT_TYPE_use_srtp) {
|
&& type == TLSEXT_TYPE_use_srtp) {
|
||||||
if (ssl_parse_clienthello_use_srtp_ext(s, data, size, al))
|
if (ssl_parse_clienthello_use_srtp_ext(s, &subpkt, al))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2288,16 +2300,12 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
|
|||||||
if (custom_ext_parse(s, 1, type, data, size, al) <= 0)
|
if (custom_ext_parse(s, 1, type, data, size, al) <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
data += size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spurious data on the end */
|
/* Spurious data on the end */
|
||||||
if (data != d + n)
|
if (PACKET_remaining(pkt) != 0)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
*p = data;
|
|
||||||
|
|
||||||
ri_check:
|
ri_check:
|
||||||
|
|
||||||
/* Need RI if renegotiating */
|
/* Need RI if renegotiating */
|
||||||
@ -2316,12 +2324,11 @@ err:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
|
int ssl_parse_clienthello_tlsext(SSL *s, PACKET *pkt)
|
||||||
int n)
|
|
||||||
{
|
{
|
||||||
int al = -1;
|
int al = -1;
|
||||||
custom_ext_init(&s->cert->srv_ext);
|
custom_ext_init(&s->cert->srv_ext);
|
||||||
if (ssl_scan_clienthello_tlsext(s, p, d, n, &al) <= 0) {
|
if (ssl_scan_clienthello_tlsext(s, pkt, &al) <= 0) {
|
||||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2934,12 +2941,12 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
|
|||||||
* s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket.
|
* s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket.
|
||||||
* Otherwise, s->tlsext_ticket_expected is set to 0.
|
* Otherwise, s->tlsext_ticket_expected is set to 0.
|
||||||
*/
|
*/
|
||||||
int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
|
int tls1_process_ticket(SSL *s, PACKET *pkt, unsigned char *session_id,
|
||||||
const unsigned char *limit, SSL_SESSION **ret)
|
int len, SSL_SESSION **ret)
|
||||||
{
|
{
|
||||||
/* Point after session ID in client hello */
|
unsigned int i;
|
||||||
const unsigned char *p = session_id + len;
|
size_t bookmark = 0;
|
||||||
unsigned short i;
|
int retv = -1;
|
||||||
|
|
||||||
*ret = NULL;
|
*ret = NULL;
|
||||||
s->tlsext_ticket_expected = 0;
|
s->tlsext_ticket_expected = 0;
|
||||||
@ -2950,46 +2957,60 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
|
|||||||
*/
|
*/
|
||||||
if (!tls_use_ticket(s))
|
if (!tls_use_ticket(s))
|
||||||
return 0;
|
return 0;
|
||||||
if ((s->version <= SSL3_VERSION) || !limit)
|
if ((s->version <= SSL3_VERSION))
|
||||||
return 0;
|
return 0;
|
||||||
if (p >= limit)
|
|
||||||
|
if (!PACKET_get_bookmark(pkt, &bookmark)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Skip past DTLS cookie */
|
/* Skip past DTLS cookie */
|
||||||
if (SSL_IS_DTLS(s)) {
|
if (SSL_IS_DTLS(s)) {
|
||||||
i = *(p++);
|
if (!PACKET_get_1(pkt, &i)
|
||||||
p += i;
|
|| !PACKET_forward(pkt, i)) {
|
||||||
if (p >= limit)
|
retv = -1;
|
||||||
return -1;
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Skip past cipher list */
|
/* Skip past cipher list and compression algorithm list */
|
||||||
n2s(p, i);
|
if (!PACKET_get_net_2(pkt, &i)
|
||||||
p += i;
|
|| !PACKET_forward(pkt, i)
|
||||||
if (p >= limit)
|
|| !PACKET_get_1(pkt, &i)
|
||||||
return -1;
|
|| !PACKET_forward(pkt, i)) {
|
||||||
/* Skip past compression algorithm list */
|
retv = -1;
|
||||||
i = *(p++);
|
goto end;
|
||||||
p += i;
|
}
|
||||||
if (p > limit)
|
|
||||||
return -1;
|
|
||||||
/* Now at start of extensions */
|
/* Now at start of extensions */
|
||||||
if ((p + 2) >= limit)
|
if (!PACKET_get_net_2(pkt, &i)) {
|
||||||
return 0;
|
retv = 0;
|
||||||
n2s(p, i);
|
goto end;
|
||||||
while ((p + 4) <= limit) {
|
}
|
||||||
unsigned short type, size;
|
while (PACKET_remaining (pkt) >= 4) {
|
||||||
n2s(p, type);
|
unsigned int type, size;
|
||||||
n2s(p, size);
|
|
||||||
if (p + size > limit)
|
if (!PACKET_get_net_2(pkt, &type)
|
||||||
return 0;
|
|| !PACKET_get_net_2(pkt, &size)) {
|
||||||
|
/* Shouldn't ever happen */
|
||||||
|
retv = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (PACKET_remaining(pkt) < size) {
|
||||||
|
retv = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
if (type == TLSEXT_TYPE_session_ticket) {
|
if (type == TLSEXT_TYPE_session_ticket) {
|
||||||
int r;
|
int r;
|
||||||
|
unsigned char *etick;
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
/*
|
/*
|
||||||
* The client will accept a ticket but doesn't currently have
|
* The client will accept a ticket but doesn't currently have
|
||||||
* one.
|
* one.
|
||||||
*/
|
*/
|
||||||
s->tlsext_ticket_expected = 1;
|
s->tlsext_ticket_expected = 1;
|
||||||
return 1;
|
retv = 1;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
if (s->tls_session_secret_cb) {
|
if (s->tls_session_secret_cb) {
|
||||||
/*
|
/*
|
||||||
@ -2998,25 +3019,39 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
|
|||||||
* abbreviated handshake based on external mechanism to
|
* abbreviated handshake based on external mechanism to
|
||||||
* calculate the master secret later.
|
* calculate the master secret later.
|
||||||
*/
|
*/
|
||||||
return 2;
|
retv = 2;
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
r = tls_decrypt_ticket(s, p, size, session_id, len, ret);
|
if (!PACKET_get_bytes(pkt, &etick, size)) {
|
||||||
|
/* Shouldn't ever happen */
|
||||||
|
retv = -1;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
r = tls_decrypt_ticket(s, etick, size, session_id, len, ret);
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case 2: /* ticket couldn't be decrypted */
|
case 2: /* ticket couldn't be decrypted */
|
||||||
s->tlsext_ticket_expected = 1;
|
s->tlsext_ticket_expected = 1;
|
||||||
return 2;
|
retv = 2;
|
||||||
|
break;
|
||||||
case 3: /* ticket was decrypted */
|
case 3: /* ticket was decrypted */
|
||||||
return r;
|
retv = r;
|
||||||
|
break;
|
||||||
case 4: /* ticket decrypted but need to renew */
|
case 4: /* ticket decrypted but need to renew */
|
||||||
s->tlsext_ticket_expected = 1;
|
s->tlsext_ticket_expected = 1;
|
||||||
return 3;
|
retv = 3;
|
||||||
|
break;
|
||||||
default: /* fatal error */
|
default: /* fatal error */
|
||||||
return -1;
|
retv = -1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
p += size;
|
|
||||||
}
|
}
|
||||||
return 0;
|
retv = 0;
|
||||||
|
end:
|
||||||
|
if (!PACKET_goto_bookmark(pkt, bookmark))
|
||||||
|
return -1;
|
||||||
|
return retv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
|
@ -143,23 +143,14 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
|
|||||||
/*
|
/*
|
||||||
* Parse the client's renegotiation binding and abort if it's not right
|
* Parse the client's renegotiation binding and abort if it's not right
|
||||||
*/
|
*/
|
||||||
int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
|
int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al)
|
||||||
int *al)
|
|
||||||
{
|
{
|
||||||
int ilen;
|
unsigned int ilen;
|
||||||
|
unsigned char *d;
|
||||||
|
|
||||||
/* Parse the length byte */
|
/* Parse the length byte */
|
||||||
if (len < 1) {
|
if (!PACKET_get_1(pkt, &ilen)
|
||||||
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
|
|| !PACKET_get_bytes(pkt, &d, ilen)) {
|
||||||
SSL_R_RENEGOTIATION_ENCODING_ERR);
|
|
||||||
*al = SSL_AD_ILLEGAL_PARAMETER;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ilen = *d;
|
|
||||||
d++;
|
|
||||||
|
|
||||||
/* Consistency check */
|
|
||||||
if ((ilen + 1) != len) {
|
|
||||||
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
|
SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
|
||||||
SSL_R_RENEGOTIATION_ENCODING_ERR);
|
SSL_R_RENEGOTIATION_ENCODING_ERR);
|
||||||
*al = SSL_AD_ILLEGAL_PARAMETER;
|
*al = SSL_AD_ILLEGAL_PARAMETER;
|
||||||
|
Loading…
Reference in New Issue
Block a user