TLS: Avoid undefined behavior in pointer arithmetic
Reorder terms in a way that no invalid pointers are generated with pos+len operations. end-pos is always defined (with a valid pos pointer) while pos+len could end up pointing beyond the end pointer which would be undefined behavior. Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
2461724c05
commit
d2eb91e08f
3 changed files with 32 additions and 16 deletions
|
@ -134,6 +134,11 @@ static int tls_write_client_certificate(struct tlsv1_client *conn,
|
||||||
struct x509_certificate *cert;
|
struct x509_certificate *cert;
|
||||||
|
|
||||||
pos = *msgpos;
|
pos = *msgpos;
|
||||||
|
if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) {
|
||||||
|
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
TLS_ALERT_INTERNAL_ERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate");
|
wpa_printf(MSG_DEBUG, "TLSv1: Send Certificate");
|
||||||
rhdr = pos;
|
rhdr = pos;
|
||||||
|
@ -154,7 +159,7 @@ static int tls_write_client_certificate(struct tlsv1_client *conn,
|
||||||
pos += 3;
|
pos += 3;
|
||||||
cert = conn->cred ? conn->cred->cert : NULL;
|
cert = conn->cred ? conn->cred->cert : NULL;
|
||||||
while (cert) {
|
while (cert) {
|
||||||
if (pos + 3 + cert->cert_len > end) {
|
if (3 + cert->cert_len > (size_t) (end - pos)) {
|
||||||
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
|
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
|
||||||
"for Certificate (cert_len=%lu left=%lu)",
|
"for Certificate (cert_len=%lu left=%lu)",
|
||||||
(unsigned long) cert->cert_len,
|
(unsigned long) cert->cert_len,
|
||||||
|
@ -265,9 +270,16 @@ static int tlsv1_key_x_dh(struct tlsv1_client *conn, u8 **pos, u8 *end)
|
||||||
wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
|
wpa_hexdump(MSG_DEBUG, "TLSv1: DH Yc (client's public value)",
|
||||||
dh_yc, dh_yc_len);
|
dh_yc, dh_yc_len);
|
||||||
|
|
||||||
|
if (end - *pos < 2) {
|
||||||
|
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
TLS_ALERT_INTERNAL_ERROR);
|
||||||
|
os_free(csecret);
|
||||||
|
os_free(dh_yc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
WPA_PUT_BE16(*pos, dh_yc_len);
|
WPA_PUT_BE16(*pos, dh_yc_len);
|
||||||
*pos += 2;
|
*pos += 2;
|
||||||
if (*pos + dh_yc_len > end) {
|
if (dh_yc_len > (size_t) (end - *pos)) {
|
||||||
wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the "
|
wpa_printf(MSG_DEBUG, "TLSv1: Not enough room in the "
|
||||||
"message buffer for Yc");
|
"message buffer for Yc");
|
||||||
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
tls_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
|
|
@ -168,6 +168,11 @@ static int tls_write_server_certificate(struct tlsv1_server *conn,
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = *msgpos;
|
pos = *msgpos;
|
||||||
|
if (TLS_RECORD_HEADER_LEN + 1 + 3 + 3 > end - pos) {
|
||||||
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
TLS_ALERT_INTERNAL_ERROR);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
tlsv1_server_log(conn, "Send Certificate");
|
tlsv1_server_log(conn, "Send Certificate");
|
||||||
rhdr = pos;
|
rhdr = pos;
|
||||||
|
@ -188,7 +193,7 @@ static int tls_write_server_certificate(struct tlsv1_server *conn,
|
||||||
pos += 3;
|
pos += 3;
|
||||||
cert = conn->cred->cert;
|
cert = conn->cred->cert;
|
||||||
while (cert) {
|
while (cert) {
|
||||||
if (pos + 3 + cert->cert_len > end) {
|
if (3 + cert->cert_len > (size_t) (end - pos)) {
|
||||||
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
|
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space "
|
||||||
"for Certificate (cert_len=%lu left=%lu)",
|
"for Certificate (cert_len=%lu left=%lu)",
|
||||||
(unsigned long) cert->cert_len,
|
(unsigned long) cert->cert_len,
|
||||||
|
@ -371,7 +376,7 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
|
||||||
/* body - ServerDHParams */
|
/* body - ServerDHParams */
|
||||||
server_params = pos;
|
server_params = pos;
|
||||||
/* dh_p */
|
/* dh_p */
|
||||||
if (pos + 2 + dh_p_len > end) {
|
if (2 + dh_p_len > (size_t) (end - pos)) {
|
||||||
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
|
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
|
||||||
"dh_p");
|
"dh_p");
|
||||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
@ -385,7 +390,7 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
|
||||||
pos += dh_p_len;
|
pos += dh_p_len;
|
||||||
|
|
||||||
/* dh_g */
|
/* dh_g */
|
||||||
if (pos + 2 + conn->cred->dh_g_len > end) {
|
if (2 + conn->cred->dh_g_len > (size_t) (end - pos)) {
|
||||||
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
|
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
|
||||||
"dh_g");
|
"dh_g");
|
||||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
@ -399,7 +404,7 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
|
||||||
pos += conn->cred->dh_g_len;
|
pos += conn->cred->dh_g_len;
|
||||||
|
|
||||||
/* dh_Ys */
|
/* dh_Ys */
|
||||||
if (pos + 2 + dh_ys_len > end) {
|
if (2 + dh_ys_len > (size_t) (end - pos)) {
|
||||||
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
|
wpa_printf(MSG_DEBUG, "TLSv1: Not enough buffer space for "
|
||||||
"dh_Ys");
|
"dh_Ys");
|
||||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
|
@ -457,7 +462,7 @@ static int tls_write_server_key_exchange(struct tlsv1_server *conn,
|
||||||
* SignatureAlgorithm signature;
|
* SignatureAlgorithm signature;
|
||||||
* } SignatureAndHashAlgorithm;
|
* } SignatureAndHashAlgorithm;
|
||||||
*/
|
*/
|
||||||
if (hlen < 0 || pos + 2 > end) {
|
if (hlen < 0 || end - pos < 2) {
|
||||||
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL,
|
||||||
TLS_ALERT_INTERNAL_ERROR);
|
TLS_ALERT_INTERNAL_ERROR);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -199,12 +199,11 @@ static int x509_parse_algorithm_identifier(
|
||||||
hdr.class, hdr.tag);
|
hdr.class, hdr.tag);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (hdr.length > buf + len - hdr.payload)
|
||||||
|
return -1;
|
||||||
pos = hdr.payload;
|
pos = hdr.payload;
|
||||||
end = pos + hdr.length;
|
end = pos + hdr.length;
|
||||||
|
|
||||||
if (end > buf + len)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
*next = end;
|
*next = end;
|
||||||
|
|
||||||
if (asn1_get_oid(pos, end - pos, &id->oid, &pos))
|
if (asn1_get_oid(pos, end - pos, &id->oid, &pos))
|
||||||
|
@ -243,7 +242,7 @@ static int x509_parse_public_key(const u8 *buf, size_t len,
|
||||||
}
|
}
|
||||||
pos = hdr.payload;
|
pos = hdr.payload;
|
||||||
|
|
||||||
if (pos + hdr.length > end)
|
if (hdr.length > end - pos)
|
||||||
return -1;
|
return -1;
|
||||||
end = pos + hdr.length;
|
end = pos + hdr.length;
|
||||||
*next = end;
|
*next = end;
|
||||||
|
@ -319,7 +318,7 @@ static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
|
||||||
}
|
}
|
||||||
pos = hdr.payload;
|
pos = hdr.payload;
|
||||||
|
|
||||||
if (pos + hdr.length > buf + len)
|
if (hdr.length > buf + len - pos)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
end = *next = pos + hdr.length;
|
end = *next = pos + hdr.length;
|
||||||
|
@ -677,7 +676,7 @@ static int x509_parse_validity(const u8 *buf, size_t len,
|
||||||
pos = hdr.payload;
|
pos = hdr.payload;
|
||||||
plen = hdr.length;
|
plen = hdr.length;
|
||||||
|
|
||||||
if (pos + plen > buf + len)
|
if (plen > (size_t) (buf + len - pos))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
*next = pos + plen;
|
*next = pos + plen;
|
||||||
|
@ -801,7 +800,7 @@ static int x509_parse_ext_basic_constraints(struct x509_certificate *cert,
|
||||||
}
|
}
|
||||||
cert->ca = hdr.payload[0];
|
cert->ca = hdr.payload[0];
|
||||||
|
|
||||||
if (hdr.payload + hdr.length == pos + len) {
|
if (hdr.length == pos + len - hdr.payload) {
|
||||||
wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d",
|
wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d",
|
||||||
cert->ca);
|
cert->ca);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1503,12 +1502,12 @@ struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len)
|
||||||
}
|
}
|
||||||
pos = hdr.payload;
|
pos = hdr.payload;
|
||||||
|
|
||||||
if (pos + hdr.length > end) {
|
if (hdr.length > end - pos) {
|
||||||
x509_certificate_free(cert);
|
x509_certificate_free(cert);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos + hdr.length < end) {
|
if (hdr.length < end - pos) {
|
||||||
wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER "
|
wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER "
|
||||||
"encoded certificate",
|
"encoded certificate",
|
||||||
pos + hdr.length, end - (pos + hdr.length));
|
pos + hdr.length, end - (pos + hdr.length));
|
||||||
|
|
Loading…
Add table
Reference in a new issue