From d165b32f388735ad921bd662eee2cafb56d4ee24 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 26 Jan 2020 16:44:49 +0200 Subject: [PATCH] TLS: TOD-STRICT and TOD-TOFU certificate policies Add parsing of certificate policies for TOD-STRICT and TOD-TOFU when using CONFIG_TLS=internal. Signed-off-by: Jouni Malinen --- src/tls/tlsv1_client_read.c | 8 +++ src/tls/x509v3.c | 130 +++++++++++++++++++++++++++++++++++- src/tls/x509v3.h | 7 ++ 3 files changed, 144 insertions(+), 1 deletion(-) diff --git a/src/tls/tlsv1_client_read.c b/src/tls/tlsv1_client_read.c index a4797bbb8..3825a7380 100644 --- a/src/tls/tlsv1_client_read.c +++ b/src/tls/tlsv1_client_read.c @@ -312,6 +312,14 @@ static void tls_peer_cert_event(struct tlsv1_client *conn, int depth, x509_name_string(&cert->subject, subject, sizeof(subject)); ev.peer_cert.subject = subject; + if (cert->extensions_present & X509_EXT_CERTIFICATE_POLICY) { + if (cert->certificate_policy & X509_EXT_CERT_POLICY_TOD_STRICT) + ev.peer_cert.tod = 1; + else if (cert->certificate_policy & + X509_EXT_CERT_POLICY_TOD_TOFU) + ev.peer_cert.tod = 2; + } + conn->event_cb(conn->cb_ctx, TLS_PEER_CERTIFICATE, &ev); wpabuf_free(cert_buf); } diff --git a/src/tls/x509v3.c b/src/tls/x509v3.c index 1bd5aa009..2b0743116 100644 --- a/src/tls/x509v3.c +++ b/src/tls/x509v3.c @@ -1120,6 +1120,133 @@ static int x509_parse_ext_issuer_alt_name(struct x509_certificate *cert, } +static int x509_id_cert_policy_any_oid(struct asn1_oid *oid) +{ + return oid->len == 5 && + oid->oid[0] == 2 /* iso/itu-t */ && + oid->oid[1] == 5 /* X.500 Directory Services */ && + oid->oid[2] == 29 /* id-ce */ && + oid->oid[3] == 32 /* id-ce-certificate-policies */ && + oid->oid[4] == 0 /* anyPolicy */; +} + + +static int x509_id_wfa_oid(struct asn1_oid *oid) +{ + return oid->len >= 7 && + oid->oid[0] == 1 /* iso */ && + oid->oid[1] == 3 /* identified-organization */ && + oid->oid[2] == 6 /* dod */ && + oid->oid[3] == 1 /* internet */ && + oid->oid[4] == 4 /* private */ && + oid->oid[5] == 1 /* enterprise */ && + oid->oid[6] == 40808 /* WFA */; +} + + +static int x509_id_wfa_tod_oid(struct asn1_oid *oid) +{ + return oid->len >= 9 && + x509_id_wfa_oid(oid) && + oid->oid[7] == 1 && + oid->oid[8] == 3; +} + + +static int x509_id_wfa_tod_strict_oid(struct asn1_oid *oid) +{ + return oid->len == 10 && + x509_id_wfa_tod_oid(oid) && + oid->oid[9] == 1; +} + + +static int x509_id_wfa_tod_tofu_oid(struct asn1_oid *oid) +{ + return oid->len == 10 && + x509_id_wfa_tod_oid(oid) && + oid->oid[9] == 2; +} + + +static int x509_parse_ext_certificate_policies(struct x509_certificate *cert, + const u8 *pos, size_t len) +{ + struct asn1_hdr hdr; + const u8 *end; + + /* + * certificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + * + * PolicyInformation ::= SEQUENCE { + * policyIdentifier CertPolicyId, + * policyQualifiers SEQUENCE SIZE (1..MAX) OF + * PolicyQualifierInfo OPTIONAL } + * + * CertPolicyId ::= OBJECT IDENTIFIER + */ + + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE (certificatePolicies) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + if (hdr.length > pos + len - hdr.payload) + return -1; + pos = hdr.payload; + end = pos + hdr.length; + + wpa_hexdump(MSG_MSGDUMP, "X509: certificatePolicies", pos, end - pos); + + while (pos < end) { + const u8 *pol_end; + struct asn1_oid oid; + char buf[80]; + + if (asn1_get_next(pos, len, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_SEQUENCE) { + wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE (PolicyInformation) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + if (hdr.length > pos + len - hdr.payload) + return -1; + pos = hdr.payload; + pol_end = pos + hdr.length; + wpa_hexdump(MSG_MSGDUMP, "X509: PolicyInformation", + pos, pol_end - pos); + + if (asn1_get_oid(pos, pol_end - pos, &oid, &pos)) + return -1; + if (x509_id_cert_policy_any_oid(&oid)) { + os_strlcpy(buf, "anyPolicy-STRICT", sizeof(buf)); + cert->certificate_policy |= + X509_EXT_CERT_POLICY_ANY; + } else if (x509_id_wfa_tod_strict_oid(&oid)) { + os_strlcpy(buf, "TOD-STRICT", sizeof(buf)); + cert->certificate_policy |= + X509_EXT_CERT_POLICY_TOD_STRICT; + } else if (x509_id_wfa_tod_tofu_oid(&oid)) { + os_strlcpy(buf, "TOD-TOFU", sizeof(buf)); + cert->certificate_policy |= + X509_EXT_CERT_POLICY_TOD_TOFU; + } else { + asn1_oid_to_str(&oid, buf, sizeof(buf)); + } + wpa_printf(MSG_DEBUG, "policyIdentifier: %s", buf); + + pos = pol_end; + } + + cert->extensions_present |= X509_EXT_CERTIFICATE_POLICY; + + return 0; +} + + static int x509_id_pkix_oid(struct asn1_oid *oid) { return oid->len >= 7 && @@ -1234,7 +1361,6 @@ static int x509_parse_extension_data(struct x509_certificate *cert, return 1; /* TODO: add other extensions required by RFC 3280, Ch 4.2: - * certificate policies (section 4.2.1.5) * name constraints (section 4.2.1.11) * policy constraints (section 4.2.1.12) * inhibit any-policy (section 4.2.1.15) @@ -1248,6 +1374,8 @@ static int x509_parse_extension_data(struct x509_certificate *cert, return x509_parse_ext_issuer_alt_name(cert, pos, len); case 19: /* id-ce-basicConstraints */ return x509_parse_ext_basic_constraints(cert, pos, len); + case 32: /* id-ce-certificatePolicies */ + return x509_parse_ext_certificate_policies(cert, pos, len); case 37: /* id-ce-extKeyUsage */ return x509_parse_ext_ext_key_usage(cert, pos, len); default: diff --git a/src/tls/x509v3.h b/src/tls/x509v3.h index 7df8e2ab0..e3b108ff4 100644 --- a/src/tls/x509v3.h +++ b/src/tls/x509v3.h @@ -74,6 +74,7 @@ struct x509_certificate { #define X509_EXT_SUBJECT_ALT_NAME (1 << 3) #define X509_EXT_ISSUER_ALT_NAME (1 << 4) #define X509_EXT_EXT_KEY_USAGE (1 << 5) +#define X509_EXT_CERTIFICATE_POLICY (1 << 6) /* BasicConstraints */ int ca; /* cA */ @@ -98,6 +99,12 @@ struct x509_certificate { #define X509_EXT_KEY_USAGE_CLIENT_AUTH (1 << 2) #define X509_EXT_KEY_USAGE_OCSP (1 << 3) + /* CertificatePolicy */ + unsigned long certificate_policy; +#define X509_EXT_CERT_POLICY_ANY (1 << 0) +#define X509_EXT_CERT_POLICY_TOD_STRICT (1 << 1) +#define X509_EXT_CERT_POLICY_TOD_TOFU (1 << 2) + /* * The DER format certificate follows struct x509_certificate. These * pointers point to that buffer.