forked from osmocom/wireshark
ssl-utils: add length validation for Certificate handshake message
This also introduces a new macro, "G_MAXUINT24" as symbol for 2^24-1 (this name does not exist in GLib and uncommon in Google). Change-Id: If000f41f6286161e3a7697357fc33ae16c1e11db Reviewed-on: https://code.wireshark.org/review/20003 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Peter Wu <peter@lekensteyn.nl>
This commit is contained in:
parent
b659c76c32
commit
746bbe7abf
|
@ -1290,7 +1290,7 @@ dissect_dtls_handshake(tvbuff_t *tvb, packet_info *pinfo,
|
|||
break;
|
||||
|
||||
case SSL_HND_CERTIFICATE:
|
||||
ssl_dissect_hnd_cert(&dissect_dtls_hf, sub_tvb, ssl_hand_tree, 0,
|
||||
ssl_dissect_hnd_cert(&dissect_dtls_hf, sub_tvb, ssl_hand_tree, 0, length,
|
||||
pinfo, session, ssl, dtls_key_hash, is_from_server);
|
||||
break;
|
||||
|
||||
|
|
|
@ -7021,7 +7021,7 @@ ssl_dissect_hnd_encrypted_extensions(ssl_common_dissect_t *hf, tvbuff_t *tvb,
|
|||
/* Certificate and Certificate Request dissections. {{{ */
|
||||
void
|
||||
ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
|
||||
guint32 offset, packet_info *pinfo,
|
||||
guint32 offset, guint32 offset_end, packet_info *pinfo,
|
||||
const SslSession *session, SslDecryptSession *ssl _U_,
|
||||
GHashTable *key_hash _U_, gint is_from_server)
|
||||
{
|
||||
|
@ -7056,6 +7056,7 @@ ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
|
|||
#if defined(HAVE_LIBGNUTLS) && defined(HAVE_LIBGCRYPT)
|
||||
gnutls_datum_t subjectPublicKeyInfo = { NULL, 0 };
|
||||
#endif
|
||||
guint32 next_offset;
|
||||
|
||||
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
|
||||
|
||||
|
@ -7075,8 +7076,12 @@ ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
|
|||
switch (cert_type) {
|
||||
case CERT_RPK:
|
||||
{
|
||||
proto_tree_add_item(tree, hf->hf.hs_certificate_len,
|
||||
tvb, offset, 3, ENC_BIG_ENDIAN);
|
||||
guint32 cert_length;
|
||||
/* opaque ASN.1_subjectPublicKeyInfo<1..2^24-1> */
|
||||
if (!ssl_add_vector(hf, tvb, pinfo, tree, offset, offset_end, &cert_length,
|
||||
hf->hf.hs_certificate_len, 1, G_MAXUINT24)) {
|
||||
return;
|
||||
}
|
||||
offset += 3;
|
||||
|
||||
dissect_x509af_SubjectPublicKeyInfo(FALSE, tvb, offset, &asn1_ctx, tree, hf->hf.hs_certificate);
|
||||
|
@ -7092,8 +7097,10 @@ ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
|
|||
/* TLS 1.3: opaque certificate_request_context<0..2^8-1> */
|
||||
if (session->version == TLSV1DOT3_VERSION) {
|
||||
guint32 context_length;
|
||||
proto_tree_add_item_ret_uint(tree, hf->hf.hs_certificate_request_context_length,
|
||||
tvb, offset, 1, ENC_NA, &context_length);
|
||||
if (!ssl_add_vector(hf, tvb, pinfo, tree, offset, offset_end, &context_length,
|
||||
hf->hf.hs_certificate_request_context_length, 0, G_MAXUINT8)) {
|
||||
return;
|
||||
}
|
||||
offset++;
|
||||
if (context_length > 0) {
|
||||
proto_tree_add_item(tree, hf->hf.hs_certificate_request_context,
|
||||
|
@ -7102,9 +7109,13 @@ ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
|
|||
}
|
||||
}
|
||||
|
||||
proto_tree_add_item_ret_uint(tree, hf->hf.hs_certificates_len,
|
||||
tvb, offset, 3, ENC_BIG_ENDIAN, &certificate_list_length);
|
||||
/* CertificateEntry certificate_list<0..2^24-1> */
|
||||
if (!ssl_add_vector(hf, tvb, pinfo, tree, offset, offset_end, &certificate_list_length,
|
||||
hf->hf.hs_certificates_len, 0, G_MAXUINT24)) {
|
||||
return;
|
||||
}
|
||||
offset += 3; /* 24-bit length value */
|
||||
next_offset = offset + certificate_list_length;
|
||||
|
||||
if (certificate_list_length > 0) {
|
||||
ti = proto_tree_add_none_format(tree,
|
||||
|
@ -7117,13 +7128,14 @@ ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
|
|||
subtree = proto_item_add_subtree(ti, hf->ett.certificates);
|
||||
|
||||
/* iterate through each certificate */
|
||||
while (certificate_list_length > 0) {
|
||||
/* get the length of the current certificate */
|
||||
while (offset < next_offset) {
|
||||
guint32 cert_length;
|
||||
proto_tree_add_item_ret_uint(subtree, hf->hf.hs_certificate_len,
|
||||
tvb, offset, 3, ENC_BIG_ENDIAN, &cert_length);
|
||||
/* opaque ASN1Cert<1..2^24-1> */
|
||||
if (!ssl_add_vector(hf, tvb, pinfo, subtree, offset, next_offset, &cert_length,
|
||||
hf->hf.hs_certificate_len, 1, G_MAXUINT24)) {
|
||||
return;
|
||||
}
|
||||
offset += 3;
|
||||
certificate_list_length -= 3 + cert_length;
|
||||
|
||||
dissect_x509af_Certificate(FALSE, tvb, offset, &asn1_ctx, subtree, hf->hf.hs_certificate);
|
||||
#if defined(HAVE_LIBGNUTLS) && defined(HAVE_LIBGCRYPT)
|
||||
|
@ -7136,14 +7148,15 @@ ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
|
|||
/* TLS 1.3: Extension extensions<0..2^16-1> */
|
||||
if (session->version == TLSV1DOT3_VERSION) {
|
||||
guint32 extensions_length;
|
||||
proto_tree_add_item_ret_uint(subtree, hf->hf.hs_exts_len,
|
||||
tvb, offset, 2, ENC_BIG_ENDIAN, &extensions_length);
|
||||
if (!ssl_add_vector(hf, tvb, pinfo, subtree, offset, next_offset, &extensions_length,
|
||||
hf->hf.hs_exts_len, 0, G_MAXUINT16)) {
|
||||
return;
|
||||
}
|
||||
offset += 2;
|
||||
|
||||
// XXX dissect OCSP and SCT extensions
|
||||
// https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.4.1.1
|
||||
offset += extensions_length;
|
||||
certificate_list_length -= 2 + extensions_length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -846,6 +846,9 @@ typedef struct {
|
|||
|
||||
|
||||
/* Helpers for dissecting Variable-Length Vectors. {{{ */
|
||||
/* Largest value that fits in a 24-bit number (2^24-1). */
|
||||
#define G_MAXUINT24 ((1U << 24) - 1)
|
||||
|
||||
/**
|
||||
* Helper for dissection of variable-length vectors (RFC 5246, section 4.3). It
|
||||
* adds a length field to the tree and writes the validated length value into
|
||||
|
@ -917,7 +920,7 @@ ssl_dissect_hnd_new_ses_ticket(ssl_common_dissect_t *hf, tvbuff_t *tvb, packet_i
|
|||
|
||||
extern void
|
||||
ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
|
||||
guint32 offset, packet_info *pinfo,
|
||||
guint32 offset, guint32 offset_end, packet_info *pinfo,
|
||||
const SslSession *session, SslDecryptSession *ssl,
|
||||
GHashTable *key_hash, gint is_from_server);
|
||||
|
||||
|
|
|
@ -2131,7 +2131,7 @@ dissect_ssl3_handshake(tvbuff_t *tvb, packet_info *pinfo,
|
|||
|
||||
case SSL_HND_CERTIFICATE:
|
||||
ssl_dissect_hnd_cert(&dissect_ssl3_hf, tvb, ssl_hand_tree,
|
||||
offset, pinfo, session, ssl, ssl_key_hash, is_from_server);
|
||||
offset, offset + length, pinfo, session, ssl, ssl_key_hash, is_from_server);
|
||||
break;
|
||||
|
||||
case SSL_HND_SERVER_KEY_EXCHG:
|
||||
|
|
Loading…
Reference in New Issue