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 <j@w1.fi>
This commit is contained in:
Jouni Malinen 2020-01-26 16:44:49 +02:00
parent 31a3d4c234
commit d165b32f38
3 changed files with 144 additions and 1 deletions

View 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);
}

View 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:

View 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.