18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * X.509v3 certificate parsing and processing (RFC 3280 profile) 30e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt * Copyright (c) 2006-2015, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "asn1.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "x509v3.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 170e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtvoid x509_free_name(struct x509_name *name) 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < name->num_attr; i++) { 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->attr[i].value); 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->attr[i].value = NULL; 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->attr[i].type = X509_NAME_ATTR_NOT_USED; 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->num_attr = 0; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->email); 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->email = NULL; 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->alt_email); 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->dns); 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->uri); 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->ip); 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->alt_email = name->dns = name->uri = NULL; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->ip = NULL; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->ip_len = 0; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&name->rid, 0, sizeof(name->rid)); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_free - Free an X.509 certificate 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: Certificate to be freed 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid x509_certificate_free(struct x509_certificate *cert) 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert == NULL) 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->next) { 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: x509_certificate_free: cer=%p " 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "was still on a list (next=%p)\n", 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert, cert->next); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(&cert->issuer); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(&cert->subject); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cert->public_key); 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cert->sign_value); 580e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt os_free(cert->subject_dn); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cert); 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_free - Free an X.509 certificate chain 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: Pointer to the first certificate in the chain 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid x509_certificate_chain_free(struct x509_certificate *cert) 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *next; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (cert) { 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next = cert->next; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->next = NULL; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = next; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_whitespace(char c) 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return c == ' ' || c == '\t'; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void x509_str_strip_whitespace(char *a) 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *ipos, *opos; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int remove_whitespace = 1; 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ipos = opos = a; 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*ipos) { 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (remove_whitespace && x509_whitespace(*ipos)) 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ipos++; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt remove_whitespace = x509_whitespace(*ipos); 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *opos++ = *ipos++; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *opos-- = '\0'; 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (opos > a && x509_whitespace(*opos)) 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *opos = '\0'; 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_str_compare(const char *a, const char *b) 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *aa, *bb; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!a && b) 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a && !b) 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!a && !b) 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aa = os_strdup(a); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bb = os_strdup(b); 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aa == NULL || bb == NULL) { 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(aa); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(bb); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return os_strcasecmp(a, b); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_str_strip_whitespace(aa); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_str_strip_whitespace(bb); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_strcasecmp(aa, bb); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(aa); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(bb); 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_name_compare - Compare X.509 certificate names 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @a: Certificate name 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @b: Certificate name 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: <0, 0, or >0 based on whether a is less than, equal to, or 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * greater than b 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint x509_name_compare(struct x509_name *a, struct x509_name *b) 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!a && b) 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a && !b) 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!a && !b) 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a->num_attr < b->num_attr) 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a->num_attr > b->num_attr) 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < a->num_attr; i++) { 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a->attr[i].type < b->attr[i].type) 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a->attr[i].type > b->attr[i].type) 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_str_compare(a->attr[i].value, b->attr[i].value); 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_str_compare(a->email, b->email); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1810e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtint x509_parse_algorithm_identifier(const u8 *buf, size_t len, 1820e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt struct x509_algorithm_identifier *id, 1830e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt const u8 **next) 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AlgorithmIdentifier ::= SEQUENCE { 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * algorithm OBJECT IDENTIFIER, 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parameters ANY DEFINED BY algorithm OPTIONAL 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(buf, len, &hdr) < 0 || 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(AlgorithmIdentifier) - found class %d tag 0x%x", 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 203d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (hdr.length > buf + len - hdr.payload) 204d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt return -1; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + hdr.length; 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *next = end; 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_oid(pos, end - pos, &id->oid, &pos)) 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: optional parameters */ 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_public_key(const u8 *buf, size_t len, 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert, 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 **next) 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SubjectPublicKeyInfo ::= SEQUENCE { 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * algorithm AlgorithmIdentifier, 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * subjectPublicKey BIT STRING 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = buf + len; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(SubjectPublicKeyInfo) - found class %d tag 0x%x", 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 246d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (hdr.length > end - pos) 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + hdr.length; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *next = end; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_algorithm_identifier(pos, end - pos, 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->public_key_alg, &pos)) 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_BITSTRING) { 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(subjectPublicKey) - found class %d tag 0x%x", 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length < 1) 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos) { 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: should this be rejected? X.509 certificates are 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * unlikely to use such a construction. Now we would end up 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * including the extra bits in the buffer which may also be 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ok. 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cert->public_key); 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->public_key = os_malloc(hdr.length - 1); 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->public_key == NULL) { 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "public key"); 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cert->public_key, pos + 1, hdr.length - 1); 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->public_key_len = hdr.length - 1; 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: subjectPublicKey", 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->public_key, cert->public_key_len); 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2920e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtint x509_parse_name(const u8 *buf, size_t len, struct x509_name *name, 2930e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt const u8 **next) 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_oid oid; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *val; 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Name ::= CHOICE { RDNSequence } 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AttributeTypeAndValue ::= SEQUENCE { 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * type AttributeType, 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value AttributeValue 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AttributeType ::= OBJECT IDENTIFIER 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AttributeValue ::= ANY DEFINED BY AttributeType 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(buf, len, &hdr) < 0 || 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Name / RDNSequencer) - found class %d tag 0x%x", 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 322d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (hdr.length > buf + len - pos) 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = *next = pos + hdr.length; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos < end) { 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum x509_name_attr_type type; 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SET) { 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SET " 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(RelativeDistinguishedName) - found class " 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "%d tag 0x%x", hdr.class, hdr.tag); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(name); 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt set_pos = hdr.payload; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = set_end = hdr.payload + hdr.length; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 || 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(AttributeTypeAndValue) - found class %d " 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tag 0x%x", hdr.class, hdr.tag); 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(name); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt seq_pos = hdr.payload; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt seq_end = hdr.payload + hdr.length; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_oid(seq_pos, seq_end - seq_pos, &oid, &seq_pos)) { 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(name); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(seq_pos, seq_end - seq_pos, &hdr) < 0 || 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL) { 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to parse " 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "AttributeValue"); 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(name); 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 3280: 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MUST: country, organization, organizational-unit, 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * distinguished name qualifier, state or province name, 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * common name, serial number. 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * SHOULD: locality, title, surname, given name, initials, 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pseudonym, generation qualifier. 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * MUST: domainComponent (RFC 2247). 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = X509_NAME_ATTR_NOT_USED; 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (oid.len == 4 && 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) { 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* id-at ::= 2.5.4 */ 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (oid.oid[3]) { 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 3: 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* commonName */ 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = X509_NAME_ATTR_CN; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 6: 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* countryName */ 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = X509_NAME_ATTR_C; 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 7: 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* localityName */ 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = X509_NAME_ATTR_L; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 8: 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* stateOrProvinceName */ 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = X509_NAME_ATTR_ST; 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 10: 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* organizationName */ 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = X509_NAME_ATTR_O; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 11: 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* organizationalUnitName */ 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = X509_NAME_ATTR_OU; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (oid.len == 7 && 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.oid[0] == 1 && oid.oid[1] == 2 && 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.oid[2] == 840 && oid.oid[3] == 113549 && 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.oid[4] == 1 && oid.oid[5] == 9 && 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.oid[6] == 1) { 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1.2.840.113549.1.9.1 - e-mailAddress */ 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->email); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->email = os_malloc(hdr.length + 1); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->email == NULL) { 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(name); 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(name->email, hdr.payload, hdr.length); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->email[hdr.length] = '\0'; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else if (oid.len == 7 && 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.oid[0] == 0 && oid.oid[1] == 9 && 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.oid[2] == 2342 && oid.oid[3] == 19200300 && 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.oid[4] == 100 && oid.oid[5] == 1 && 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.oid[6] == 25) { 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 0.9.2342.19200300.100.1.25 - domainComponent */ 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt type = X509_NAME_ATTR_DC; 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (type == X509_NAME_ATTR_NOT_USED) { 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID", 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) oid.oid, 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid.len * sizeof(oid.oid[0])); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "X509: Attribute Data", 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.payload, hdr.length); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->num_attr == X509_MAX_NAME_ATTRIBUTES) { 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Too many Name attributes"); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(name); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4464b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt val = dup_binstr(hdr.payload, hdr.length); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (val == NULL) { 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(name); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strlen(val) != hdr.length) { 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Reject certificate with " 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "embedded NUL byte in a string (%s[NUL])", 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt val); 4554b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt os_free(val); 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_free_name(name); 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->attr[name->num_attr].type = type; 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->attr[name->num_attr].value = val; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->num_attr++; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic char * x509_name_attr_str(enum x509_name_attr_type type) 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (type) { 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case X509_NAME_ATTR_NOT_USED: 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "[N/A]"; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case X509_NAME_ATTR_DC: 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "DC"; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case X509_NAME_ATTR_CN: 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "CN"; 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case X509_NAME_ATTR_C: 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "C"; 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case X509_NAME_ATTR_L: 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "L"; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case X509_NAME_ATTR_ST: 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "ST"; 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case X509_NAME_ATTR_O: 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "O"; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case X509_NAME_ATTR_OU: 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "OU"; 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "?"; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_name_string - Convert an X.509 certificate name into a string 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @name: Name to convert 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for the string 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Maximum buffer length 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid x509_name_string(struct x509_name *name, char *buf, size_t len) 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos, *end; 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len == 0) 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = buf + len; 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < name->num_attr; i++) { 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, end - pos, "%s=%s, ", 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_attr_str(name->attr[i].type), 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->attr[i].value); 515fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (os_snprintf_error(end - pos, ret)) 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') { 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos--; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos--; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos = '\0'; 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->email) { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, end - pos, "/emailAddress=%s", 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->email); 530fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (os_snprintf_error(end - pos, ret)) 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto done; 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtdone: 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end[-1] = '\0'; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5400e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtint x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, os_time_t *val) 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int year, month, day, hour, min, sec; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Time ::= CHOICE { 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * utcTime UTCTime, 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generalTime GeneralizedTime 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * UTCTime: YYMMDDHHMMSSZ 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GeneralizedTime: YYYYMMDDHHMMSSZ 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const char *) buf; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (asn1_tag) { 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ASN1_TAG_UTCTIME: 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len != 13 || buf[12] != 'Z') { 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "UTCTime format", buf, len); 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &year) != 1) { 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "UTCTime year", buf, len); 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (year < 50) 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt year += 2000; 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt year += 1900; 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ASN1_TAG_GENERALIZEDTIME: 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len != 15 || buf[14] != 'Z') { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GeneralizedTime format", buf, len); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%04d", &year) != 1) { 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GeneralizedTime year", buf, len); 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected UTCTime or " 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GeneralizedTime - found tag 0x%x", asn1_tag); 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &month) != 1) { 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(month)", buf, len); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &day) != 1) { 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(day)", buf, len); 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &hour) != 1) { 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(hour)", buf, len); 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &min) != 1) { 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(min)", buf, len); 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &sec) != 1) { 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(sec)", buf, len); 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_mktime(year, month, day, hour, min, sec, val) < 0) { 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time", 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, len); 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (year < 1970) { 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * At least some test certificates have been configured 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to use dates prior to 1970. Set the date to 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * beginning of 1970 to handle these case. 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - " 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume epoch as the time", year); 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *val = 0; 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_validity(const u8 *buf, size_t len, 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert, const u8 **next) 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Validity ::= SEQUENCE { 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * notBefore Time, 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * notAfter Time 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 3280, 4.1.2.5: 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * CAs conforming to this profile MUST always encode certificate 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * validity dates through the year 2049 as UTCTime; certificate 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * validity dates in 2050 or later MUST be encoded as GeneralizedTime. 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(buf, len, &hdr) < 0 || 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Validity) - found class %d tag 0x%x", 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = hdr.length; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 679d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (plen > (size_t) (buf + len - pos)) 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *next = pos + plen; 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, plen, &hdr) < 0 || 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_parse_time(hdr.payload, hdr.length, hdr.tag, 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->not_before) < 0) { 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore " 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Time", hdr.payload, hdr.length); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload + hdr.length; 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = *next - pos; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, plen, &hdr) < 0 || 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_parse_time(hdr.payload, hdr.length, hdr.tag, 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->not_after) < 0) { 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter " 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Time", hdr.payload, hdr.length); 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: Validity: notBefore: %lu notAfter: %lu", 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) cert->not_before, 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) cert->not_after); 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_id_ce_oid(struct asn1_oid *oid) 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* id-ce arc from X.509 for standard X.509v3 extensions */ 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len >= 4 && 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[0] == 2 /* joint-iso-ccitt */ && 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[1] == 5 /* ds */ && 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[2] == 29 /* id-ce */; 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 723d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtstatic int x509_any_ext_key_usage_oid(struct asn1_oid *oid) 724d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 725d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return oid->len == 6 && 726d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt x509_id_ce_oid(oid) && 727d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[3] == 37 /* extKeyUsage */ && 728d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[4] == 0 /* anyExtendedKeyUsage */; 729d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 730d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 731d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_key_usage(struct x509_certificate *cert, 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * KeyUsage ::= BIT STRING { 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * digitalSignature (0), 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nonRepudiation (1), 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keyEncipherment (2), 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * dataEncipherment (3), 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keyAgreement (4), 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keyCertSign (5), 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cRLSign (6), 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encipherOnly (7), 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * decipherOnly (8) } 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_BITSTRING || 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length < 1) { 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in " 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "KeyUsage; found %d tag 0x%x len %d", 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag, hdr.length); 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_KEY_USAGE; 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->key_usage = asn1_bit_string_to_long(hdr.payload, hdr.length); 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: KeyUsage 0x%lx", cert->key_usage); 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_basic_constraints(struct x509_certificate *cert, 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned long value; 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * BasicConstraints ::= SEQUENCE { 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cA BOOLEAN DEFAULT FALSE, 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pathLenConstraint INTEGER (0..MAX) OPTIONAL } 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BasicConstraints; found %d tag 0x%x", 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_BASIC_CONSTRAINTS; 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL) { 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to parse " 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BasicConstraints"); 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag == ASN1_TAG_BOOLEAN) { 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length != 1) { 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected " 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Boolean length (%u) in BasicConstraints", 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->ca = hdr.payload[0]; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 812d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (hdr.length == pos + len - hdr.payload) { 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d", 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->ca); 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length, 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &hdr) < 0 || 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL) { 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to parse " 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BasicConstraints"); 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag != ASN1_TAG_INTEGER) { 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in " 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BasicConstraints; found class %d tag 0x%x", 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = hdr.length; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = 0; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left) { 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value <<= 8; 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value |= *pos++; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left--; 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->path_len_constraint = value; 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_PATH_LEN_CONSTRAINT; 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d " 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pathLenConstraint=%lu", 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->ca, cert->path_len_constraint); 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_rfc8222(struct x509_name *name, 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* rfc822Name IA5String */ 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - rfc822Name", pos, len); 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->alt_email); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->alt_email = os_zalloc(len + 1); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->alt_email == NULL) 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(name->alt_email, pos, len); 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strlen(name->alt_email) != len) { 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Reject certificate with " 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "embedded NUL byte in rfc822Name (%s[NUL])", 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->alt_email); 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->alt_email); 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->alt_email = NULL; 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_dns(struct x509_name *name, 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dNSName IA5String */ 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - dNSName", pos, len); 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->dns); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->dns = os_zalloc(len + 1); 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->dns == NULL) 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(name->dns, pos, len); 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strlen(name->dns) != len) { 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Reject certificate with " 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "embedded NUL byte in dNSName (%s[NUL])", 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->dns); 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->dns); 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->dns = NULL; 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_uri(struct x509_name *name, 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* uniformResourceIdentifier IA5String */ 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "X509: altName - uniformResourceIdentifier", 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, len); 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->uri); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->uri = os_zalloc(len + 1); 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->uri == NULL) 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(name->uri, pos, len); 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strlen(name->uri) != len) { 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Reject certificate with " 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "embedded NUL byte in uniformResourceIdentifier " 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s[NUL])", name->uri); 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->uri); 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->uri = NULL; 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_ip(struct x509_name *name, 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* iPAddress OCTET STRING */ 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: altName - iPAddress", pos, len); 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->ip); 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->ip = os_malloc(len); 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->ip == NULL) 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(name->ip, pos, len); 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->ip_len = len; 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_rid(struct x509_name *name, 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[80]; 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* registeredID OBJECT IDENTIFIER */ 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_parse_oid(pos, len, &name->rid) < 0) 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt asn1_oid_to_str(&name->rid, buf, sizeof(buf)); 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: altName - registeredID: %s", buf); 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_alt_name(struct x509_name *name, 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *p, *end; 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GeneralName ::= CHOICE { 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * otherName [0] OtherName, 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rfc822Name [1] IA5String, 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * dNSName [2] IA5String, 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x400Address [3] ORAddress, 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * directoryName [4] Name, 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ediPartyName [5] EDIPartyName, 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * uniformResourceIdentifier [6] IA5String, 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * iPAddress [7] OCTET STRING, 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * registeredID [8] OBJECT IDENTIFIER } 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * OtherName ::= SEQUENCE { 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * type-id OBJECT IDENTIFIER, 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value [0] EXPLICIT ANY DEFINED BY type-id } 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EDIPartyName ::= SEQUENCE { 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nameAssigner [0] DirectoryString OPTIONAL, 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * partyName [1] DirectoryString } 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (p = pos, end = pos + len; p < end; p = hdr.payload + hdr.length) { 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(p, end - p, &hdr) < 0) { 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to parse " 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SubjectAltName item"); 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr.tag) { 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_rfc8222(name, hdr.payload, 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 2: 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_dns(name, hdr.payload, 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 6: 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_uri(name, hdr.payload, 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 7: 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_ip(name, hdr.payload, 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 8: 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_rid(name, hdr.payload, 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 0: /* TODO: otherName */ 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 3: /* TODO: x500Address */ 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 4: /* TODO: directoryName */ 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 5: /* TODO: ediPartyName */ 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = 0; 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_subject_alt_name(struct x509_certificate *cert, 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SubjectAltName ::= GeneralNames */ 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SubjectAltName; found %d tag 0x%x", 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: SubjectAltName"); 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_SUBJECT_ALT_NAME; 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_alt_name(&cert->subject, hdr.payload, 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_issuer_alt_name(struct x509_certificate *cert, 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IssuerAltName ::= GeneralNames */ 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IssuerAltName; found %d tag 0x%x", 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: IssuerAltName"); 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_ISSUER_ALT_NAME; 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_alt_name(&cert->issuer, hdr.payload, 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1085d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtstatic int x509_id_pkix_oid(struct asn1_oid *oid) 1086d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 1087d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return oid->len >= 7 && 1088d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[0] == 1 /* iso */ && 1089d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[1] == 3 /* identified-organization */ && 1090d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[2] == 6 /* dod */ && 1091d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[3] == 1 /* internet */ && 1092d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[4] == 5 /* security */ && 1093d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[5] == 5 /* mechanisms */ && 1094d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[6] == 7 /* id-pkix */; 1095d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 1096d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1097d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1098d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtstatic int x509_id_kp_oid(struct asn1_oid *oid) 1099d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 1100d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt /* id-kp */ 1101d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return oid->len >= 8 && 1102d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt x509_id_pkix_oid(oid) && 1103d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[7] == 3 /* id-kp */; 1104d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 1105d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1106d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1107d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtstatic int x509_id_kp_server_auth_oid(struct asn1_oid *oid) 1108d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 1109d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt /* id-kp */ 1110d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return oid->len == 9 && 1111d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt x509_id_kp_oid(oid) && 1112d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[8] == 1 /* id-kp-serverAuth */; 1113d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 1114d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1115d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1116d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtstatic int x509_id_kp_client_auth_oid(struct asn1_oid *oid) 1117d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 1118d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt /* id-kp */ 1119d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return oid->len == 9 && 1120d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt x509_id_kp_oid(oid) && 1121d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[8] == 2 /* id-kp-clientAuth */; 1122d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 1123d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1124d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 11250e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtstatic int x509_id_kp_ocsp_oid(struct asn1_oid *oid) 11260e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt{ 11270e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt /* id-kp */ 11280e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt return oid->len == 9 && 11290e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt x509_id_kp_oid(oid) && 11300e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt oid->oid[8] == 9 /* id-kp-OCSPSigning */; 11310e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt} 11320e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt 11330e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt 1134d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtstatic int x509_parse_ext_ext_key_usage(struct x509_certificate *cert, 1135d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt const u8 *pos, size_t len) 1136d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 1137d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct asn1_hdr hdr; 1138d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt const u8 *end; 1139d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt struct asn1_oid oid; 1140d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1141d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt /* 1142d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId 1143d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * 1144d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt * KeyPurposeId ::= OBJECT IDENTIFIER 1145d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt */ 1146d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1147d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 1148d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 1149d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 1150d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 1151d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "(ExtKeyUsageSyntax) - found class %d tag 0x%x", 1152d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt hdr.class, hdr.tag); 1153d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 1154d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 1155d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (hdr.length > pos + len - hdr.payload) 1156d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 1157d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt pos = hdr.payload; 1158d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt end = pos + hdr.length; 1159d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1160d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: ExtKeyUsageSyntax", pos, end - pos); 1161d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1162d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt while (pos < end) { 1163d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt char buf[80]; 1164d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1165d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos)) 1166d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 1167d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (x509_any_ext_key_usage_oid(&oid)) { 1168d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt os_strlcpy(buf, "anyExtendedKeyUsage", sizeof(buf)); 1169d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cert->ext_key_usage |= X509_EXT_KEY_USAGE_ANY; 1170d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } else if (x509_id_kp_server_auth_oid(&oid)) { 1171d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt os_strlcpy(buf, "id-kp-serverAuth", sizeof(buf)); 1172d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cert->ext_key_usage |= X509_EXT_KEY_USAGE_SERVER_AUTH; 1173d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } else if (x509_id_kp_client_auth_oid(&oid)) { 1174d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt os_strlcpy(buf, "id-kp-clientAuth", sizeof(buf)); 1175d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cert->ext_key_usage |= X509_EXT_KEY_USAGE_CLIENT_AUTH; 11760e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt } else if (x509_id_kp_ocsp_oid(&oid)) { 11770e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt os_strlcpy(buf, "id-kp-OCSPSigning", sizeof(buf)); 11780e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt cert->ext_key_usage |= X509_EXT_KEY_USAGE_OCSP; 1179d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } else { 1180d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt asn1_oid_to_str(&oid, buf, sizeof(buf)); 1181d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 1182d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, "ExtKeyUsage KeyPurposeId: %s", buf); 1183d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 1184d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1185d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt cert->extensions_present |= X509_EXT_EXT_KEY_USAGE; 1186d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1187d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return 0; 1188d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 1189d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1190d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_extension_data(struct x509_certificate *cert, 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_oid *oid, 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!x509_id_ce_oid(oid)) 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add other extensions required by RFC 3280, Ch 4.2: 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * certificate policies (section 4.2.1.5) 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * name constraints (section 4.2.1.11) 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * policy constraints (section 4.2.1.12) 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * inhibit any-policy (section 4.2.1.15) 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (oid->oid[3]) { 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 15: /* id-ce-keyUsage */ 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_key_usage(cert, pos, len); 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 17: /* id-ce-subjectAltName */ 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_subject_alt_name(cert, pos, len); 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 18: /* id-ce-issuerAltName */ 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_issuer_alt_name(cert, pos, len); 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 19: /* id-ce-basicConstraints */ 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_basic_constraints(cert, pos, len); 1213d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt case 37: /* id-ce-extKeyUsage */ 1214d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return x509_parse_ext_ext_key_usage(cert, pos, len); 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_extension(struct x509_certificate *cert, 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len, const u8 **next) 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end; 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_oid oid; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int critical_ext = 0, res; 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[80]; 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Extension ::= SEQUENCE { 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * extnID OBJECT IDENTIFIER, 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * critical BOOLEAN DEFAULT FALSE, 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * extnValue OCTET STRING 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extensions: class %d tag 0x%x; expected SEQUENCE", 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *next = end = pos + hdr.length; 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data for " 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extension (expected OID)"); 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (hdr.tag != ASN1_TAG_BOOLEAN && 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING)) { 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extensions: class %d tag 0x%x; expected BOOLEAN " 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "or OCTET STRING", hdr.class, hdr.tag); 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag == ASN1_TAG_BOOLEAN) { 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length != 1) { 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected " 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Boolean length (%u)", hdr.length); 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt critical_ext = hdr.payload[0]; 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (hdr.class != ASN1_CLASS_UNIVERSAL && 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_PRIVATE) || 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING) { 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header " 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in Extensions: class %d tag 0x%x; " 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expected OCTET STRING", 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt asn1_oid_to_str(&oid, buf, sizeof(buf)); 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Extension: extnID=%s critical=%d", 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, critical_ext); 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: extnValue", hdr.payload, hdr.length); 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_extension_data(cert, &oid, hdr.payload, hdr.length); 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 1 && critical_ext) { 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Unknown critical extension %s", 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf); 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_extensions(struct x509_certificate *cert, 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end; 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data " 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for Extensions: class %d tag 0x%x; " 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expected SEQUENCE", hdr.class, hdr.tag); 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + hdr.length; 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos < end) { 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_extension(cert, pos, end - pos, &pos) 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_tbs_certificate(const u8 *buf, size_t len, 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert, 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 **next) 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char sbuf[128]; 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned long value; 1342d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt const u8 *subject_dn; 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* tbsCertificate TBSCertificate ::= SEQUENCE */ 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(buf, len, &hdr) < 0 || 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start " 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with a valid SEQUENCE - found class %d tag 0x%x", 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = *next = pos + hdr.length; 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * version [0] EXPLICIT Version DEFAULT v1 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Version ::= INTEGER { v1(0), v2(1), v3(2) } 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) { 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_UNIVERSAL || 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_INTEGER) { 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version field - found class %d tag 0x%x", 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length != 1) { 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected version field " 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length %u (expected 1)", hdr.length); 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = hdr.length; 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = 0; 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left) { 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value <<= 8; 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value |= *pos++; 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left--; 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version = value; 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->version != X509_CERT_V1 && 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version != X509_CERT_V2 && 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version != X509_CERT_V3) { 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unsupported version %d", 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version + 1); 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version = X509_CERT_V1; 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: Version X.509v%d", cert->version + 1); 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* serialNumber CertificateSerialNumber ::= INTEGER */ 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_UNIVERSAL || 14060e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt hdr.tag != ASN1_TAG_INTEGER || 14070e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt hdr.length < 1 || hdr.length > X509_MAX_SERIAL_NUM_LEN) { 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " 14090e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt "serialNumber; class=%d tag=0x%x length=%u", 14100e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt hdr.class, hdr.tag, hdr.length); 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14140e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt pos = hdr.payload + hdr.length; 14150e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt while (hdr.length > 0 && hdr.payload[0] == 0) { 14160e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt hdr.payload++; 14170e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt hdr.length--; 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14190e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt os_memcpy(cert->serial_number, hdr.payload, hdr.length); 14200e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt cert->serial_number_len = hdr.length; 14210e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: serialNumber", cert->serial_number, 14220e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt cert->serial_number_len); 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* signature AlgorithmIdentifier */ 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature, 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &pos)) 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* issuer Name */ 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_name(pos, end - pos, &cert->issuer, &pos)) 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->issuer, sbuf, sizeof(sbuf)); 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: issuer %s", sbuf); 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* validity Validity */ 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_validity(pos, end - pos, cert, &pos)) 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* subject Name */ 14400e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt subject_dn = pos; 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_name(pos, end - pos, &cert->subject, &pos)) 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14430e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt cert->subject_dn = os_malloc(pos - subject_dn); 14440e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt if (!cert->subject_dn) 14450e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt return -1; 14460e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt cert->subject_dn_len = pos - subject_dn; 14470e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt os_memcpy(cert->subject_dn, subject_dn, cert->subject_dn_len); 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->subject, sbuf, sizeof(sbuf)); 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: subject %s", sbuf); 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* subjectPublicKeyInfo SubjectPublicKeyInfo */ 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_public_key(pos, end - pos, cert, &pos)) 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == end) 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->version == X509_CERT_V1) 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " tag to parse optional tbsCertificate " 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "field(s); parsed class %d tag 0x%x", 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag == 1) { 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL */ 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: issuerUniqueID"); 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: parse UniqueIdentifier ::= BIT STRING */ 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14755a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt pos = hdr.payload + hdr.length; 14765a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (pos == end) 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " tag to parse optional tbsCertificate " 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "field(s); parsed class %d tag 0x%x", 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag == 2) { 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL */ 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: subjectUniqueID"); 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: parse UniqueIdentifier ::= BIT STRING */ 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14945a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt pos = hdr.payload + hdr.length; 14955a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (pos == end) 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " tag to parse optional tbsCertificate " 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "field(s); parsed class %d tag 0x%x", 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag != 3) { 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Ignored unexpected " 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Context-Specific tag %d in optional " 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tbsCertificate fields", hdr.tag); 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* extensions [3] EXPLICIT Extensions OPTIONAL */ 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->version != X509_CERT_V3) { 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and " 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extensions data which are only allowed for " 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version 3", cert->version + 1); 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0) 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload + hdr.length; 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos < end) { 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "X509: Ignored extra tbsCertificate data", 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, end - pos); 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_rsadsi_oid(struct asn1_oid *oid) 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len >= 4 && 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[0] == 1 /* iso */ && 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[1] == 2 /* member-body */ && 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[2] == 840 /* us */ && 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[3] == 113549 /* rsadsi */; 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_pkcs_oid(struct asn1_oid *oid) 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len >= 5 && 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_rsadsi_oid(oid) && 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[4] == 1 /* pkcs */; 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_digest_oid(struct asn1_oid *oid) 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len >= 5 && 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_rsadsi_oid(oid) && 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[4] == 2 /* digestAlgorithm */; 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15640e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtint x509_sha1_oid(struct asn1_oid *oid) 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len == 6 && 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[0] == 1 /* iso */ && 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[1] == 3 /* identified-organization */ && 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[2] == 14 /* oiw */ && 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[3] == 3 /* secsig */ && 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[4] == 2 /* algorithms */ && 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[5] == 26 /* id-sha1 */; 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1576d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidtstatic int x509_sha2_oid(struct asn1_oid *oid) 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len == 9 && 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[0] == 2 /* joint-iso-itu-t */ && 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[1] == 16 /* country */ && 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[2] == 840 /* us */ && 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[3] == 1 /* organization */ && 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[4] == 101 /* gov */ && 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[5] == 3 /* csor */ && 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[6] == 4 /* nistAlgorithm */ && 1586d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[7] == 2 /* hashAlgs */; 1587d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 1588d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1589d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 15900e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtint x509_sha256_oid(struct asn1_oid *oid) 1591d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 1592d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return x509_sha2_oid(oid) && 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[8] == 1 /* sha256 */; 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15970e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtint x509_sha384_oid(struct asn1_oid *oid) 1598d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 1599d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return x509_sha2_oid(oid) && 1600d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[8] == 2 /* sha384 */; 1601d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 1602d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1603d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 16040e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtint x509_sha512_oid(struct asn1_oid *oid) 1605d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt{ 1606d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return x509_sha2_oid(oid) && 1607d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt oid->oid[8] == 3 /* sha512 */; 1608d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt} 1609d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1610d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_parse - Parse a X.509 certificate in DER format 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the X.509 certificate in DER format 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer length 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the parsed certificate or %NULL on failure 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Caller is responsible for freeing the returned certificate by calling 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_free(). 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end, *hash_start; 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert; 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = os_zalloc(sizeof(*cert) + len); 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert == NULL) 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cert + 1, buf, len); 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->cert_start = (u8 *) (cert + 1); 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->cert_len = len; 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = buf + len; 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */ 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Certificate ::= SEQUENCE */ 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate did not start with " 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "a valid SEQUENCE - found class %d tag 0x%x", 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1650d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (hdr.length > end - pos) { 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1655d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (hdr.length < end - pos) { 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER " 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encoded certificate", 1658cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt pos + hdr.length, end - (pos + hdr.length)); 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + hdr.length; 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_start = pos; 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->tbs_cert_start = cert->cert_start + (hash_start - buf); 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) { 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->tbs_cert_len = pos - hash_start; 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* signatureAlgorithm AlgorithmIdentifier */ 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_algorithm_identifier(pos, end - pos, 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->signature_alg, &pos)) { 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* signatureValue BIT STRING */ 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_BITSTRING) { 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(signatureValue) - found class %d tag 0x%x", 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length < 1) { 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos) { 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos); 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PKCS #1 v1.5 10.2.1: 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * It is an error if the length in bits of the signature S is 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not a multiple of eight. 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cert->sign_value); 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->sign_value = os_malloc(hdr.length - 1); 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->sign_value == NULL) { 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "signatureValue"); 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cert->sign_value, pos + 1, hdr.length - 1); 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->sign_value_len = hdr.length - 1; 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: signature", 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->sign_value, cert->sign_value_len); 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return cert; 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_check_signature - Verify certificate signature 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @issuer: Issuer certificate 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: Certificate to be verified 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 if cert has a valid signature that was signed by the issuer, 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -1 if not 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint x509_certificate_check_signature(struct x509_certificate *issuer, 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert) 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 17290e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt return x509_check_signature(issuer, &cert->signature, 17300e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt cert->sign_value, cert->sign_value_len, 17310e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt cert->tbs_cert_start, cert->tbs_cert_len); 17320e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt} 17330e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt 17340e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt 17350e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtint x509_check_signature(struct x509_certificate *issuer, 17360e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt struct x509_algorithm_identifier *signature, 17370e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt const u8 *sign_value, size_t sign_value_len, 17380e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt const u8 *signed_data, size_t signed_data_len) 17390e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt{ 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_public_key *pk; 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *data; 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end, *next, *da_end; 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len; 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_oid oid; 1746d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt u8 hash[64]; 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t hash_len; 17480e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt const u8 *addr[1] = { signed_data }; 17490e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt size_t len[1] = { signed_data_len }; 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17510e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt if (!x509_pkcs_oid(&signature->oid) || 17520e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt signature->oid.len != 7 || 17530e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt signature->oid.oid[5] != 1 /* pkcs-1 */) { 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unrecognized signature " 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "algorithm"); 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pk = crypto_public_key_import(issuer->public_key, 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt issuer->public_key_len); 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pk == NULL) 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17640e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt data_len = sign_value_len; 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_malloc(data_len); 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) { 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_public_key_free(pk); 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17710e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt if (crypto_public_key_decrypt_pkcs1(pk, sign_value, 17720e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt sign_value_len, data, 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data_len) < 0) { 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature"); 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_public_key_free(pk); 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_public_key_free(pk); 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len); 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PKCS #1 v1.5, 10.1.2: 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * DigestInfo ::= SEQUENCE { 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * digestAlgorithm DigestAlgorithmIdentifier, 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * digest Digest 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Digest ::= OCTET STRING 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(data, data_len, &hdr) < 0 || 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(DigestInfo) - found class %d tag 0x%x", 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + hdr.length; 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * X.509: 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AlgorithmIdentifier ::= SEQUENCE { 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * algorithm OBJECT IDENTIFIER, 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parameters ANY DEFINED BY algorithm OPTIONAL 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(AlgorithmIdentifier) - found class %d tag 0x%x", 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt da_end = hdr.payload + hdr.length; 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm"); 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_sha1_oid(&oid)) { 18350e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt if (signature->oid.oid[6] != 5 /* sha-1WithRSAEncryption */) { 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 " 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "does not match with certificate " 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "signatureAlgorithm (%lu)", 18390e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt signature->oid.oid[6]); 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_digest_oid; 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_sha256_oid(&oid)) { 18470e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt if (signature->oid.oid[6] != 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11 /* sha2561WithRSAEncryption */) { 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA256 " 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "does not match with certificate " 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "signatureAlgorithm (%lu)", 18520e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt signature->oid.oid[6]); 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_digest_oid; 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1859d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (x509_sha384_oid(&oid)) { 18600e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt if (signature->oid.oid[6] != 12 /* sha384WithRSAEncryption */) { 1861d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA384 " 1862d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "does not match with certificate " 1863d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "signatureAlgorithm (%lu)", 18640e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt signature->oid.oid[6]); 1865d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt os_free(data); 1866d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 1867d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 1868d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt goto skip_digest_oid; 1869d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 1870d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 1871d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt if (x509_sha512_oid(&oid)) { 18720e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt if (signature->oid.oid[6] != 13 /* sha512WithRSAEncryption */) { 1873d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA512 " 1874d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "does not match with certificate " 1875d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt "signatureAlgorithm (%lu)", 18760e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt signature->oid.oid[6]); 1877d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt os_free(data); 1878d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt return -1; 1879d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 1880d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt goto skip_digest_oid; 1881d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt } 1882d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!x509_digest_oid(&oid)) { 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (oid.oid[5]) { 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 5: /* md5 */ 18900e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt if (signature->oid.oid[6] != 4 /* md5WithRSAEncryption */) { 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does " 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with certificate " 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "signatureAlgorithm (%lu)", 18940e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt signature->oid.oid[6]); 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 2: /* md2 */ 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 4: /* md4 */ 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm " 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%lu)", oid.oid[5]); 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_digest_oid: 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Digest ::= OCTET STRING */ 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = da_end; 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = data + data_len; 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING) { 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING " 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Digest) - found class %d tag 0x%x", 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest", 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.payload, hdr.length); 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19250e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt switch (signature->oid.oid[6]) { 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 4: /* md5WithRSAEncryption */ 19270e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt md5_vector(1, addr, len, hash); 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = 16; 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)", 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash, hash_len); 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 5: /* sha-1WithRSAEncryption */ 19330e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt sha1_vector(1, addr, len, hash); 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = 20; 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)", 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash, hash_len); 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 11: /* sha256WithRSAEncryption */ 19390e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt sha256_vector(1, addr, len, hash); 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = 32; 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)", 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash, hash_len); 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 12: /* sha384WithRSAEncryption */ 19450e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt sha384_vector(1, addr, len, hash); 1946d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt hash_len = 48; 1947d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA384)", 1948d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt hash, hash_len); 1949d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt break; 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 13: /* sha512WithRSAEncryption */ 19510e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt sha512_vector(1, addr, len, hash); 1952d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt hash_len = 64; 1953d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA512)", 1954d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt hash, hash_len); 1955d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt break; 1956d7ff03d48f825360eec2a371e3361306f2fd721bDmitry Shmidt case 2: /* md2WithRSAEncryption */ 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " 19590e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt "algorithm (%lu)", signature->oid.oid[6]); 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length != hash_len || 1965c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memcmp_const(hdr.payload, hash, hdr.length) != 0) { 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Certificate Digest does not match " 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with calculated tbsCertificate hash"); 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 197250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt if (hdr.payload + hdr.length < data + data_len) { 197350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt wpa_hexdump(MSG_INFO, 197450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt "X509: Extra data after certificate signature hash", 197550b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt hdr.payload + hdr.length, 197650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt data + data_len - hdr.payload - hdr.length); 197750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt os_free(data); 197850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt return -1; 197950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } 198050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with " 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "calculated tbsCertificate hash"); 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_valid_issuer(const struct x509_certificate *cert) 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) && 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !cert->ca) { 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an " 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "issuer"); 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->version == X509_CERT_V3 && 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "include BasicConstraints extension"); 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((cert->extensions_present & X509_EXT_KEY_USAGE) && 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { 20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "keyCertSign bit in Key Usage"); 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_chain_validate - Validate X.509 certificate chain 20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @trusted: List of trusted certificates 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @chain: Certificate chain to be validated (first chain must be issued by 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * signed by the second certificate in the chain and so on) 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reason: Buffer for returning failure reason (X509_VALIDATE_*) 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 if chain is valid, -1 if not 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint x509_certificate_chain_validate(struct x509_certificate *trusted, 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *chain, 2027c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt int *reason, int disable_time_checks) 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt long unsigned idx; 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int chain_trusted = 0; 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert, *trust; 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[128]; 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_OK; 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Validate certificate chain"); 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { 2041d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt cert->issuer_trusted = 0; 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->subject, buf, sizeof(buf)); 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chain_trusted) 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (!disable_time_checks && 2049c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt ((unsigned long) now.sec < 2050c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt (unsigned long) cert->not_before || 2051c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt (unsigned long) now.sec > 2052c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt (unsigned long) cert->not_after)) { 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Certificate not valid " 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(now=%lu not_before=%lu not_after=%lu)", 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt now.sec, cert->not_before, cert->not_after); 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_CERTIFICATE_EXPIRED; 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->next) { 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_name_compare(&cert->issuer, 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->next->subject) != 0) { 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate " 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "chain issuer name mismatch"); 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->issuer, buf, 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(buf)); 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: cert issuer: %s", 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf); 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->next->subject, buf, 20708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(buf)); 20718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: next cert " 20728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subject: %s", buf); 20738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN; 20748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_valid_issuer(cert->next) < 0) { 20788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 20798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((cert->next->extensions_present & 20838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt X509_EXT_PATH_LEN_CONSTRAINT) && 20848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx > cert->next->path_len_constraint) { 20858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" 20868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " not met (idx=%lu issuer " 20878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pathLenConstraint=%lu)", idx, 20888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->next->path_len_constraint); 20898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 20908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 20918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_certificate_check_signature(cert->next, cert) 20948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) { 20958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Invalid " 20968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate signature within " 20978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "chain"); 20988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 20998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (trust = trusted; trust; trust = trust->next) { 21048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_name_compare(&cert->issuer, &trust->subject) 21058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == 0) 21068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 21078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (trust) { 21108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Found issuer from the " 21118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "list of trusted certificates"); 21128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_valid_issuer(trust) < 0) { 21138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 21148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_certificate_check_signature(trust, cert) < 0) 21188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 21198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Invalid " 21208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate signature"); 21218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 21228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Trusted certificate " 21268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found to complete the chain"); 2127d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt cert->issuer_trusted = 1; 21288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chain_trusted = 1; 21298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!chain_trusted) { 21338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers " 21348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from the list of trusted certificates"); 21358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (trusted) { 21368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_UNKNOWN_CA; 21378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 21388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate chain validation " 21408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "disabled - ignore unknown CA issue"); 21418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate chain valid"); 21448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 21468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_get_subject - Get a certificate based on Subject name 21518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @chain: Certificate chain to search through 21528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @name: Subject name to search for 21538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the certificate with the given Subject name or 21548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * %NULL on failure 21558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct x509_certificate * 21578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtx509_certificate_get_subject(struct x509_certificate *chain, 21588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_name *name) 21598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert; 21618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (cert = chain; cert; cert = cert->next) { 21638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_name_compare(&cert->subject, name) == 0) 21648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return cert; 21658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 21668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 21678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 21688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 21708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 21718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_self_signed - Is the certificate self-signed? 21728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: Certificate 21738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if certificate is self-signed, 0 if not 21748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 21758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint x509_certificate_self_signed(struct x509_certificate *cert) 21768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 21778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_name_compare(&cert->issuer, &cert->subject) == 0; 21788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2179