summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlaf Bergmann <bergmann@tzi.org>2015-08-26 21:20:49 +0200
committerPeter Wu <peter@lekensteyn.nl>2015-09-07 21:56:42 +0000
commita6360b6cc0dd60fbe250a7e3359b17858f15625f (patch)
tree13b2dd81f3181c7e4f8ac95d17b518777eb3943d
parent4496fdeef8e88c8200377e16fc56f44acfebc9a0 (diff)
downloadwireshark-a6360b6cc0dd60fbe250a7e3359b17858f15625f.tar.gz
SSL: bugfix for raw public keys in certificate message
RFC 7250 has changed the format of the Certificate structure from RFC 5246 to the following: opaque ASN.1Cert<1..2^24-1>; struct { select(certificate_type) { // certificate type defined in RFC 7250 case RawPublicKey: opaque ASN.1_subjectPublicKeyInfo<1..2^24-1>; // X.509 certificate defined in RFC 5246 case X.509: ASN.1Cert certificate_list<0..2^24-1>; }; } Certificate; Thus, ssl_dissect_hnd_cert() must parse subjectPublicKeyInfo immediately when the message's certificate type is SSL_HND_CERT_TYPE_RAW_PUBLIC_KEY. Otherwise, the message will contain a certificate_list. This modification first determines the certificate type and then handles both cases independently. For raw public keys, no subtree is created to reflect the flat structure of the certificate message. Bug: 11480 Change-Id: I1c55eca361c4e40fcbff5bc32bfc8de3576bdfbf Reviewed-on: https://code.wireshark.org/review/10272 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Peter Wu <peter@lekensteyn.nl>
-rw-r--r--epan/dissectors/packet-ssl-utils.c96
1 files changed, 65 insertions, 31 deletions
diff --git a/epan/dissectors/packet-ssl-utils.c b/epan/dissectors/packet-ssl-utils.c
index e8db3eac14..fb5bce333f 100644
--- a/epan/dissectors/packet-ssl-utils.c
+++ b/epan/dissectors/packet-ssl-utils.c
@@ -5737,15 +5737,22 @@ ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
guint32 offset, packet_info *pinfo,
const SslSession *session, gint is_from_server)
{
- /* opaque ASN.1Cert<2^24-1>;
+ /* opaque ASN.1Cert<1..2^24-1>;
*
* struct {
- * ASN.1Cert certificate_list<1..2^24-1>;
+ * select(certificate_type) {
+ *
+ * // certificate type defined in RFC 7250
+ * case RawPublicKey:
+ * opaque ASN.1_subjectPublicKeyInfo<1..2^24-1>;
+ *
+ * // X.509 certificate defined in RFC 5246
+ * case X.509:
+ * ASN.1Cert certificate_list<0..2^24-1>;
+ * };
* } Certificate;
*/
- guint32 certificate_list_length;
- proto_item *ti;
- proto_tree *subtree;
+ enum { CERT_X509, CERT_RPK } cert_type;
asn1_ctx_t asn1_ctx;
if (!tree)
@@ -5753,40 +5760,67 @@ ssl_dissect_hnd_cert(ssl_common_dissect_t *hf, tvbuff_t *tvb, proto_tree *tree,
asn1_ctx_init(&asn1_ctx, ASN1_ENC_BER, TRUE, pinfo);
- certificate_list_length = tvb_get_ntoh24(tvb, offset);
- proto_tree_add_uint(tree, hf->hf.hs_certificates_len,
- tvb, offset, 3, certificate_list_length);
- offset += 3; /* 24-bit length value */
-
- if (certificate_list_length > 0) {
- ti = proto_tree_add_none_format(tree,
- hf->hf.hs_certificates,
- tvb, offset, certificate_list_length,
- "Certificates (%u bytes)",
- certificate_list_length);
-
- /* make it a subtree */
- subtree = proto_item_add_subtree(ti, hf->ett.certificates);
+ if ((is_from_server && session->server_cert_type == SSL_HND_CERT_TYPE_RAW_PUBLIC_KEY) ||
+ (!is_from_server && session->client_cert_type == SSL_HND_CERT_TYPE_RAW_PUBLIC_KEY)) {
+ cert_type = CERT_RPK;
+ } else {
+ cert_type = CERT_X509;
+ }
- /* iterate through each certificate */
- while (certificate_list_length > 0) {
- /* get the length of the current certificate */
+ switch (cert_type) {
+ case CERT_RPK:
+ {
guint32 cert_length;
cert_length = tvb_get_ntoh24(tvb, offset);
- certificate_list_length -= 3 + cert_length;
- proto_tree_add_item(subtree, hf->hf.hs_certificate_len,
+ proto_tree_add_item(tree, hf->hf.hs_certificate_len,
tvb, offset, 3, ENC_BIG_ENDIAN);
offset += 3;
- if ((is_from_server && session->server_cert_type == SSL_HND_CERT_TYPE_RAW_PUBLIC_KEY) ||
- (!is_from_server && session->client_cert_type == SSL_HND_CERT_TYPE_RAW_PUBLIC_KEY)) {
- dissect_x509af_SubjectPublicKeyInfo(FALSE, tvb, offset, &asn1_ctx, subtree, hf->hf.hs_certificate);
- } else {
- dissect_x509af_Certificate(FALSE, tvb, offset, &asn1_ctx, subtree, hf->hf.hs_certificate);
- }
-
+ dissect_x509af_SubjectPublicKeyInfo(FALSE, tvb, offset, &asn1_ctx, tree, hf->hf.hs_certificate);
offset += cert_length;
+
+ break;
+ }
+ case CERT_X509:
+ {
+ guint32 certificate_list_length;
+ proto_item *ti;
+ proto_tree *subtree;
+
+ certificate_list_length = tvb_get_ntoh24(tvb, offset);
+
+ proto_tree_add_uint(tree, hf->hf.hs_certificates_len,
+ tvb, offset, 3, certificate_list_length);
+ offset += 3; /* 24-bit length value */
+
+ if (certificate_list_length > 0) {
+ ti = proto_tree_add_none_format(tree,
+ hf->hf.hs_certificates,
+ tvb, offset, certificate_list_length,
+ "Certificates (%u bytes)",
+ certificate_list_length);
+
+ /* make it a subtree */
+ 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 */
+ guint32 cert_length;
+ cert_length = tvb_get_ntoh24(tvb, offset);
+ certificate_list_length -= 3 + cert_length;
+
+ proto_tree_add_item(subtree, hf->hf.hs_certificate_len,
+ tvb, offset, 3, ENC_BIG_ENDIAN);
+ offset += 3;
+
+ dissect_x509af_Certificate(FALSE, tvb, offset, &asn1_ctx, subtree, hf->hf.hs_certificate);
+
+ offset += cert_length;
+ }
+ }
+ break;
}
}
}