]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
TLS: TOD-STRICT and TOD-TOFU certificate policies
authorJouni Malinen <j@w1.fi>
Sun, 26 Jan 2020 14:44:49 +0000 (16:44 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 26 Jan 2020 14:44:49 +0000 (16:44 +0200)
Add parsing of certificate policies for TOD-STRICT and TOD-TOFU when
using CONFIG_TLS=internal.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/tls/tlsv1_client_read.c
src/tls/x509v3.c
src/tls/x509v3.h

index a4797bbb886c9335d8ec06dacb3067fa81ada70d..3825a7380dd5eae6b6221e3441b89138634167e0 100644 (file)
@@ -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);
 }
index 1bd5aa009fb599c415608c55fc525b849af7ea3e..2b07431166a6122e3aff4ca0fbed1a11b055767f 100644 (file)
@@ -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:
index 7df8e2ab0870c9359c16c33118c480856bb864ff..e3b108ff43817073a0e2d54558e260e723a73c21 100644 (file)
@@ -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.