Tighten extension handling
This adds additional checks to the processing of extensions in a ClientHello to ensure that either no extensions are present, or if they are then they take up the exact amount of space expected. With thanks to the Open Crypto Audit Project for reporting this issue. Reviewed-by: Stephen Henson <steve@openssl.org> Conflicts: ssl/t1_lib.c
This commit is contained in:
parent
f92b196723
commit
72df35acf2
158
ssl/t1_lib.c
158
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;
|
s->srtp_profile = NULL;
|
||||||
|
|
||||||
if (data >= (d + n - 2))
|
if (data >= (d + n - 2)) {
|
||||||
goto ri_check;
|
if (data != d + n)
|
||||||
|
goto err;
|
||||||
|
else
|
||||||
|
goto ri_check;
|
||||||
|
}
|
||||||
n2s(data, len);
|
n2s(data, len);
|
||||||
|
|
||||||
if (data > (d + n - len))
|
if (data > (d + n - len))
|
||||||
goto ri_check;
|
goto err;
|
||||||
|
|
||||||
while (data <= (d + n - 4)) {
|
while (data <= (d + n - 4)) {
|
||||||
n2s(data, type);
|
n2s(data, type);
|
||||||
n2s(data, size);
|
n2s(data, size);
|
||||||
|
|
||||||
if (data + size > (d + n))
|
if (data + size > (d + n))
|
||||||
goto ri_check;
|
goto err;
|
||||||
# if 0
|
# if 0
|
||||||
fprintf(stderr, "Received extension type %d size %d\n", type, size);
|
fprintf(stderr, "Received extension type %d size %d\n", type, size);
|
||||||
# endif
|
# endif
|
||||||
@ -1064,16 +1068,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
|
|||||||
int servname_type;
|
int servname_type;
|
||||||
int dsize;
|
int dsize;
|
||||||
|
|
||||||
if (size < 2) {
|
if (size < 2)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
n2s(data, dsize);
|
n2s(data, dsize);
|
||||||
size -= 2;
|
size -= 2;
|
||||||
if (dsize > size) {
|
if (dsize > size)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sdata = data;
|
sdata = data;
|
||||||
while (dsize > 3) {
|
while (dsize > 3) {
|
||||||
@ -1081,18 +1081,16 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
|
|||||||
n2s(sdata, len);
|
n2s(sdata, len);
|
||||||
dsize -= 3;
|
dsize -= 3;
|
||||||
|
|
||||||
if (len > dsize) {
|
if (len > dsize)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (s->servername_done == 0)
|
if (s->servername_done == 0)
|
||||||
switch (servname_type) {
|
switch (servname_type) {
|
||||||
case TLSEXT_NAMETYPE_host_name:
|
case TLSEXT_NAMETYPE_host_name:
|
||||||
if (!s->hit) {
|
if (!s->hit) {
|
||||||
if (s->session->tlsext_hostname) {
|
if (s->session->tlsext_hostname)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (len > TLSEXT_MAXLEN_host_name) {
|
if (len > TLSEXT_MAXLEN_host_name) {
|
||||||
*al = TLS1_AD_UNRECOGNIZED_NAME;
|
*al = TLS1_AD_UNRECOGNIZED_NAME;
|
||||||
return 0;
|
return 0;
|
||||||
@ -1126,31 +1124,23 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
|
|||||||
|
|
||||||
dsize -= len;
|
dsize -= len;
|
||||||
}
|
}
|
||||||
if (dsize != 0) {
|
if (dsize != 0)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
# 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 (size == 0 || ((len = data[0])) != (size - 1))
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
if (s->srp_ctx.login != NULL)
|
||||||
}
|
goto err;
|
||||||
if (s->srp_ctx.login != NULL) {
|
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
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);
|
memcpy(s->srp_ctx.login, &data[1], len);
|
||||||
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)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
@ -1159,10 +1149,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
|
|||||||
unsigned char *sdata = data;
|
unsigned char *sdata = data;
|
||||||
int ecpointformatlist_length = *(sdata++);
|
int ecpointformatlist_length = *(sdata++);
|
||||||
|
|
||||||
if (ecpointformatlist_length != size - 1) {
|
if (ecpointformatlist_length != size - 1)
|
||||||
*al = TLS1_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!s->hit) {
|
if (!s->hit) {
|
||||||
if (s->session->tlsext_ecpointformatlist) {
|
if (s->session->tlsext_ecpointformatlist) {
|
||||||
OPENSSL_free(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 ||
|
if (ellipticcurvelist_length != size - 2 ||
|
||||||
ellipticcurvelist_length < 1 ||
|
ellipticcurvelist_length < 1 ||
|
||||||
/* Each NamedCurve is 2 bytes. */
|
/* Each NamedCurve is 2 bytes. */
|
||||||
ellipticcurvelist_length & 1) {
|
ellipticcurvelist_length & 1)
|
||||||
*al = TLS1_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!s->hit) {
|
if (!s->hit) {
|
||||||
if (s->session->tlsext_ellipticcurvelist) {
|
if (s->session->tlsext_ellipticcurvelist)
|
||||||
*al = TLS1_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
s->session->tlsext_ellipticcurvelist_length = 0;
|
s->session->tlsext_ellipticcurvelist_length = 0;
|
||||||
if ((s->session->tlsext_ellipticcurvelist =
|
if ((s->session->tlsext_ellipticcurvelist =
|
||||||
OPENSSL_malloc(ellipticcurvelist_length)) == NULL) {
|
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;
|
renegotiate_seen = 1;
|
||||||
} else if (type == TLSEXT_TYPE_signature_algorithms) {
|
} else if (type == TLSEXT_TYPE_signature_algorithms) {
|
||||||
int dsize;
|
int dsize;
|
||||||
if (sigalg_seen || size < 2) {
|
if (sigalg_seen || size < 2)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sigalg_seen = 1;
|
sigalg_seen = 1;
|
||||||
n2s(data, dsize);
|
n2s(data, dsize);
|
||||||
size -= 2;
|
size -= 2;
|
||||||
if (dsize != size || dsize & 1) {
|
if (dsize != size || dsize & 1)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
if (!tls1_process_sigalgs(s, data, dsize))
|
||||||
}
|
goto err;
|
||||||
if (!tls1_process_sigalgs(s, data, dsize)) {
|
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else if (type == TLSEXT_TYPE_status_request &&
|
} else if (type == TLSEXT_TYPE_status_request &&
|
||||||
s->version != DTLS1_VERSION) {
|
s->version != DTLS1_VERSION) {
|
||||||
|
|
||||||
if (size < 5) {
|
if (size < 5)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->tlsext_status_type = *data++;
|
s->tlsext_status_type = *data++;
|
||||||
size--;
|
size--;
|
||||||
@ -1304,35 +1282,26 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
|
|||||||
/* Read in responder_id_list */
|
/* Read in responder_id_list */
|
||||||
n2s(data, dsize);
|
n2s(data, dsize);
|
||||||
size -= 2;
|
size -= 2;
|
||||||
if (dsize > size) {
|
if (dsize > size)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
while (dsize > 0) {
|
while (dsize > 0) {
|
||||||
OCSP_RESPID *id;
|
OCSP_RESPID *id;
|
||||||
int idsize;
|
int idsize;
|
||||||
if (dsize < 4) {
|
if (dsize < 4)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
n2s(data, idsize);
|
n2s(data, idsize);
|
||||||
dsize -= 2 + idsize;
|
dsize -= 2 + idsize;
|
||||||
size -= 2 + idsize;
|
size -= 2 + idsize;
|
||||||
if (dsize < 0) {
|
if (dsize < 0)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sdata = data;
|
sdata = data;
|
||||||
data += idsize;
|
data += idsize;
|
||||||
id = d2i_OCSP_RESPID(NULL, &sdata, idsize);
|
id = d2i_OCSP_RESPID(NULL, &sdata, idsize);
|
||||||
if (!id) {
|
if (!id)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (data != sdata) {
|
if (data != sdata) {
|
||||||
OCSP_RESPID_free(id);
|
OCSP_RESPID_free(id);
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if (!s->tlsext_ocsp_ids
|
if (!s->tlsext_ocsp_ids
|
||||||
&& !(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 */
|
/* Read in request_extensions */
|
||||||
if (size < 2) {
|
if (size < 2)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
n2s(data, dsize);
|
n2s(data, dsize);
|
||||||
size -= 2;
|
size -= 2;
|
||||||
if (dsize != size) {
|
if (dsize != size)
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sdata = data;
|
sdata = data;
|
||||||
if (dsize > 0) {
|
if (dsize > 0) {
|
||||||
if (s->tlsext_ocsp_exts) {
|
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 =
|
s->tlsext_ocsp_exts =
|
||||||
d2i_X509_EXTENSIONS(NULL, &sdata, dsize);
|
d2i_X509_EXTENSIONS(NULL, &sdata, dsize);
|
||||||
if (!s->tlsext_ocsp_exts || (data + dsize != sdata)) {
|
if (!s->tlsext_ocsp_exts || (data + dsize != sdata))
|
||||||
*al = SSL_AD_DECODE_ERROR;
|
goto err;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -1432,6 +1395,10 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
|
|||||||
data += size;
|
data += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Spurious data on the end */
|
||||||
|
if (data != d + n)
|
||||||
|
goto err;
|
||||||
|
|
||||||
*p = data;
|
*p = data;
|
||||||
|
|
||||||
ri_check:
|
ri_check:
|
||||||
@ -1447,6 +1414,9 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
|
|||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
err:
|
||||||
|
*al = SSL_AD_DECODE_ERROR;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# ifndef OPENSSL_NO_NEXTPROTONEG
|
# ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
|
Loading…
x
Reference in New Issue
Block a user