18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * X.509v3 certificate parsing and processing (RFC 3280 profile) 3c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt * Copyright (c) 2006-2011, 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 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void 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); 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cert); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_free - Free an X.509 certificate chain 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: Pointer to the first certificate in the chain 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid x509_certificate_chain_free(struct x509_certificate *cert) 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *next; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (cert) { 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt next = cert->next; 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->next = NULL; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = next; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_whitespace(char c) 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return c == ' ' || c == '\t'; 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void x509_str_strip_whitespace(char *a) 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *ipos, *opos; 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int remove_whitespace = 1; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ipos = opos = a; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (*ipos) { 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (remove_whitespace && x509_whitespace(*ipos)) 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ipos++; 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else { 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt remove_whitespace = x509_whitespace(*ipos); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *opos++ = *ipos++; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *opos-- = '\0'; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (opos > a && x509_whitespace(*opos)) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *opos = '\0'; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_str_compare(const char *a, const char *b) 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *aa, *bb; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!a && b) 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a && !b) 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!a && !b) 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aa = os_strdup(a); 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bb = os_strdup(b); 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (aa == NULL || bb == NULL) { 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(aa); 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(bb); 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return os_strcasecmp(a, b); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_str_strip_whitespace(aa); 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_str_strip_whitespace(bb); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_strcasecmp(aa, bb); 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(aa); 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(bb); 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_name_compare - Compare X.509 certificate names 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @a: Certificate name 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @b: Certificate name 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: <0, 0, or >0 based on whether a is less than, equal to, or 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * greater than b 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint x509_name_compare(struct x509_name *a, struct x509_name *b) 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!a && b) 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a && !b) 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!a && !b) 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a->num_attr < b->num_attr) 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a->num_attr > b->num_attr) 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < a->num_attr; i++) { 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a->attr[i].type < b->attr[i].type) 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (a->attr[i].type > b->attr[i].type) 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_str_compare(a->attr[i].value, b->attr[i].value); 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_str_compare(a->email, b->email); 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res) 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_algorithm_identifier( 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len, 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_algorithm_identifier *id, const u8 **next) 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AlgorithmIdentifier ::= SEQUENCE { 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * algorithm OBJECT IDENTIFIER, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parameters ANY DEFINED BY algorithm OPTIONAL 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(buf, len, &hdr) < 0 || 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(AlgorithmIdentifier) - found class %d tag 0x%x", 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + hdr.length; 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (end > buf + len) 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 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 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + hdr.length > end) 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 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name, 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry 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 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + hdr.length > buf + len) 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); 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - pos) 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); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret < 0 || ret >= end - pos) 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 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_time_t *val) 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const char *pos; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int year, month, day, hour, min, sec; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Time ::= CHOICE { 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * utcTime UTCTime, 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generalTime GeneralizedTime 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * UTCTime: YYMMDDHHMMSSZ 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GeneralizedTime: YYYYMMDDHHMMSSZ 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const char *) buf; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (asn1_tag) { 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ASN1_TAG_UTCTIME: 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len != 13 || buf[12] != 'Z') { 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "UTCTime format", buf, len); 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &year) != 1) { 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "UTCTime year", buf, len); 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (year < 50) 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt year += 2000; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt year += 1900; 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case ASN1_TAG_GENERALIZEDTIME: 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len != 15 || buf[14] != 'Z') { 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GeneralizedTime format", buf, len); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%04d", &year) != 1) { 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GeneralizedTime year", buf, len); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 4; 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected UTCTime or " 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "GeneralizedTime - found tag 0x%x", asn1_tag); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &month) != 1) { 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(month)", buf, len); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &day) != 1) { 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(day)", buf, len); 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &hour) != 1) { 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(hour)", buf, len); 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &min) != 1) { 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(min)", buf, len); 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sscanf(pos, "%02d", &sec) != 1) { 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(sec)", buf, len); 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_mktime(year, month, day, hour, min, sec, val) < 0) { 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time", 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, len); 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (year < 1970) { 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * At least some test certificates have been configured 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to use dates prior to 1970. Set the date to 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * beginning of 1970 to handle these case. 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - " 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "assume epoch as the time", year); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *val = 0; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_validity(const u8 *buf, size_t len, 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert, const u8 **next) 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t plen; 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Validity ::= SEQUENCE { 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * notBefore Time, 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * notAfter Time 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RFC 3280, 4.1.2.5: 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * CAs conforming to this profile MUST always encode certificate 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * validity dates through the year 2049 as UTCTime; certificate 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * validity dates in 2050 or later MUST be encoded as GeneralizedTime. 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(buf, len, &hdr) < 0 || 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Validity) - found class %d tag 0x%x", 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = hdr.length; 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + plen > buf + len) 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *next = pos + plen; 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, plen, &hdr) < 0 || 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_parse_time(hdr.payload, hdr.length, hdr.tag, 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->not_before) < 0) { 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore " 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Time", hdr.payload, hdr.length); 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload + hdr.length; 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = *next - pos; 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, plen, &hdr) < 0 || 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_parse_time(hdr.payload, hdr.length, hdr.tag, 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->not_after) < 0) { 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter " 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Time", hdr.payload, hdr.length); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: Validity: notBefore: %lu notAfter: %lu", 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) cert->not_before, 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned long) cert->not_after); 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_id_ce_oid(struct asn1_oid *oid) 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* id-ce arc from X.509 for standard X.509v3 extensions */ 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len >= 4 && 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[0] == 2 /* joint-iso-ccitt */ && 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[1] == 5 /* ds */ && 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[2] == 29 /* id-ce */; 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_key_usage(struct x509_certificate *cert, 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * KeyUsage ::= BIT STRING { 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * digitalSignature (0), 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nonRepudiation (1), 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keyEncipherment (2), 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * dataEncipherment (3), 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keyAgreement (4), 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keyCertSign (5), 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cRLSign (6), 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * encipherOnly (7), 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * decipherOnly (8) } 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_BITSTRING || 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length < 1) { 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in " 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "KeyUsage; found %d tag 0x%x len %d", 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag, hdr.length); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_KEY_USAGE; 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->key_usage = asn1_bit_string_to_long(hdr.payload, hdr.length); 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: KeyUsage 0x%lx", cert->key_usage); 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_basic_constraints(struct x509_certificate *cert, 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned long value; 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * BasicConstraints ::= SEQUENCE { 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cA BOOLEAN DEFAULT FALSE, 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pathLenConstraint INTEGER (0..MAX) OPTIONAL } 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BasicConstraints; found %d tag 0x%x", 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_BASIC_CONSTRAINTS; 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL) { 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to parse " 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BasicConstraints"); 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag == ASN1_TAG_BOOLEAN) { 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length != 1) { 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected " 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Boolean length (%u) in BasicConstraints", 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->ca = hdr.payload[0]; 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.payload + hdr.length == pos + len) { 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d", 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->ca); 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length, 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &hdr) < 0 || 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL) { 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to parse " 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BasicConstraints"); 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag != ASN1_TAG_INTEGER) { 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in " 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "BasicConstraints; found class %d tag 0x%x", 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = hdr.length; 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = 0; 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left) { 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value <<= 8; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value |= *pos++; 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left--; 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->path_len_constraint = value; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_PATH_LEN_CONSTRAINT; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d " 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pathLenConstraint=%lu", 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->ca, cert->path_len_constraint); 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_rfc8222(struct x509_name *name, 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* rfc822Name IA5String */ 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - rfc822Name", pos, len); 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->alt_email); 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->alt_email = os_zalloc(len + 1); 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->alt_email == NULL) 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(name->alt_email, pos, len); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strlen(name->alt_email) != len) { 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Reject certificate with " 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "embedded NUL byte in rfc822Name (%s[NUL])", 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->alt_email); 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->alt_email); 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->alt_email = NULL; 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_dns(struct x509_name *name, 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* dNSName IA5String */ 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "X509: altName - dNSName", pos, len); 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->dns); 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->dns = os_zalloc(len + 1); 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->dns == NULL) 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(name->dns, pos, len); 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strlen(name->dns) != len) { 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Reject certificate with " 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "embedded NUL byte in dNSName (%s[NUL])", 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->dns); 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->dns); 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->dns = NULL; 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_uri(struct x509_name *name, 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* uniformResourceIdentifier IA5String */ 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "X509: altName - uniformResourceIdentifier", 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, len); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->uri); 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->uri = os_zalloc(len + 1); 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->uri == NULL) 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(name->uri, pos, len); 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_strlen(name->uri) != len) { 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Reject certificate with " 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "embedded NUL byte in uniformResourceIdentifier " 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%s[NUL])", name->uri); 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->uri); 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->uri = NULL; 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_ip(struct x509_name *name, 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* iPAddress OCTET STRING */ 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: altName - iPAddress", pos, len); 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(name->ip); 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->ip = os_malloc(len); 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (name->ip == NULL) 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(name->ip, pos, len); 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt name->ip_len = len; 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_alt_name_rid(struct x509_name *name, 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[80]; 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* registeredID OBJECT IDENTIFIER */ 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_parse_oid(pos, len, &name->rid) < 0) 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt asn1_oid_to_str(&name->rid, buf, sizeof(buf)); 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: altName - registeredID: %s", buf); 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_alt_name(struct x509_name *name, 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *p, *end; 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * GeneralName ::= CHOICE { 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * otherName [0] OtherName, 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * rfc822Name [1] IA5String, 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * dNSName [2] IA5String, 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x400Address [3] ORAddress, 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * directoryName [4] Name, 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * ediPartyName [5] EDIPartyName, 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * uniformResourceIdentifier [6] IA5String, 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * iPAddress [7] OCTET STRING, 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * registeredID [8] OBJECT IDENTIFIER } 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * OtherName ::= SEQUENCE { 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * type-id OBJECT IDENTIFIER, 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * value [0] EXPLICIT ANY DEFINED BY type-id } 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EDIPartyName ::= SEQUENCE { 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * nameAssigner [0] DirectoryString OPTIONAL, 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * partyName [1] DirectoryString } 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (p = pos, end = pos + len; p < end; p = hdr.payload + hdr.length) { 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(p, end - p, &hdr) < 0) { 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to parse " 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SubjectAltName item"); 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (hdr.tag) { 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 1: 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_rfc8222(name, hdr.payload, 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 2: 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_dns(name, hdr.payload, 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 6: 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_uri(name, hdr.payload, 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 7: 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_ip(name, hdr.payload, 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 8: 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_alt_name_rid(name, hdr.payload, 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 0: /* TODO: otherName */ 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 3: /* TODO: x500Address */ 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 4: /* TODO: directoryName */ 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 5: /* TODO: ediPartyName */ 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = 0; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_subject_alt_name(struct x509_certificate *cert, 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* SubjectAltName ::= GeneralNames */ 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "SubjectAltName; found %d tag 0x%x", 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: SubjectAltName"); 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_SUBJECT_ALT_NAME; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_alt_name(&cert->subject, hdr.payload, 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_ext_issuer_alt_name(struct x509_certificate *cert, 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IssuerAltName ::= GeneralNames */ 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "IssuerAltName; found %d tag 0x%x", 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: IssuerAltName"); 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->extensions_present |= X509_EXT_ISSUER_ALT_NAME; 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length == 0) 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_alt_name(&cert->issuer, hdr.payload, 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.length); 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_extension_data(struct x509_certificate *cert, 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_oid *oid, 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!x509_id_ce_oid(oid)) 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add other extensions required by RFC 3280, Ch 4.2: 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * certificate policies (section 4.2.1.5) 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * name constraints (section 4.2.1.11) 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * policy constraints (section 4.2.1.12) 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * extended key usage (section 4.2.1.13) 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * inhibit any-policy (section 4.2.1.15) 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (oid->oid[3]) { 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 15: /* id-ce-keyUsage */ 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_key_usage(cert, pos, len); 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 17: /* id-ce-subjectAltName */ 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_subject_alt_name(cert, pos, len); 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 18: /* id-ce-issuerAltName */ 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_issuer_alt_name(cert, pos, len); 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 19: /* id-ce-basicConstraints */ 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_parse_ext_basic_constraints(cert, pos, len); 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_extension(struct x509_certificate *cert, 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len, const u8 **next) 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end; 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_oid oid; 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int critical_ext = 0, res; 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[80]; 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Extension ::= SEQUENCE { 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * extnID OBJECT IDENTIFIER, 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * critical BOOLEAN DEFAULT FALSE, 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * extnValue OCTET STRING 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extensions: class %d tag 0x%x; expected SEQUENCE", 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *next = end = pos + hdr.length; 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data for " 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extension (expected OID)"); 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (hdr.tag != ASN1_TAG_BOOLEAN && 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING)) { 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extensions: class %d tag 0x%x; expected BOOLEAN " 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "or OCTET STRING", hdr.class, hdr.tag); 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag == ASN1_TAG_BOOLEAN) { 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length != 1) { 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected " 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Boolean length (%u)", hdr.length); 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt critical_ext = hdr.payload[0]; 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (hdr.class != ASN1_CLASS_UNIVERSAL && 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_PRIVATE) || 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING) { 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header " 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "in Extensions: class %d tag 0x%x; " 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expected OCTET STRING", 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt asn1_oid_to_str(&oid, buf, sizeof(buf)); 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Extension: extnID=%s critical=%d", 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, critical_ext); 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: extnValue", hdr.payload, hdr.length); 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = x509_parse_extension_data(cert, &oid, hdr.payload, hdr.length); 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res < 0) 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return res; 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (res == 1 && critical_ext) { 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Unknown critical extension %s", 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf); 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_extensions(struct x509_certificate *cert, 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, size_t len) 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *end; 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data " 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for Extensions: class %d tag 0x%x; " 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expected SEQUENCE", hdr.class, hdr.tag); 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + hdr.length; 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos < end) { 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_extension(cert, pos, end - pos, &pos) 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_parse_tbs_certificate(const u8 *buf, size_t len, 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert, 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 **next) 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end; 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char sbuf[128]; 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt unsigned long value; 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* tbsCertificate TBSCertificate ::= SEQUENCE */ 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(buf, len, &hdr) < 0 || 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start " 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with a valid SEQUENCE - found class %d tag 0x%x", 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = *next = pos + hdr.length; 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * version [0] EXPLICIT Version DEFAULT v1 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Version ::= INTEGER { v1(0), v2(1), v3(2) } 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) { 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_UNIVERSAL || 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_INTEGER) { 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version field - found class %d tag 0x%x", 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length != 1) { 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unexpected version field " 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length %u (expected 1)", hdr.length); 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = hdr.length; 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value = 0; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left) { 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value <<= 8; 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt value |= *pos++; 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left--; 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version = value; 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->version != X509_CERT_V1 && 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version != X509_CERT_V2 && 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version != X509_CERT_V3) { 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unsupported version %d", 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version + 1); 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0) 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->version = X509_CERT_V1; 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: Version X.509v%d", cert->version + 1); 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* serialNumber CertificateSerialNumber ::= INTEGER */ 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.class != ASN1_CLASS_UNIVERSAL || 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_INTEGER) { 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "serialNumber; class=%d tag=0x%x", 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = hdr.length; 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (left) { 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->serial_number <<= 8; 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->serial_number |= *pos++; 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left--; 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: serialNumber %lu", cert->serial_number); 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* signature AlgorithmIdentifier */ 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature, 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &pos)) 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* issuer Name */ 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_name(pos, end - pos, &cert->issuer, &pos)) 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->issuer, sbuf, sizeof(sbuf)); 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: issuer %s", sbuf); 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* validity Validity */ 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_validity(pos, end - pos, cert, &pos)) 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* subject Name */ 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_name(pos, end - pos, &cert->subject, &pos)) 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->subject, sbuf, sizeof(sbuf)); 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "X509: subject %s", sbuf); 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* subjectPublicKeyInfo SubjectPublicKeyInfo */ 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_public_key(pos, end - pos, cert, &pos)) 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == end) 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->version == X509_CERT_V1) 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " tag to parse optional tbsCertificate " 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "field(s); parsed class %d tag 0x%x", 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag == 1) { 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL */ 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: issuerUniqueID"); 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: parse UniqueIdentifier ::= BIT STRING */ 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13515a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt pos = hdr.payload + hdr.length; 13525a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (pos == end) 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " tag to parse optional tbsCertificate " 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "field(s); parsed class %d tag 0x%x", 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag == 2) { 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL */ 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: subjectUniqueID"); 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: parse UniqueIdentifier ::= BIT STRING */ 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13705a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt pos = hdr.payload + hdr.length; 13715a1480c7c46c4236d93bfd303dde32062bee04acDmitry Shmidt if (pos == end) 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " tag to parse optional tbsCertificate " 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "field(s); parsed class %d tag 0x%x", 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.tag != 3) { 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Ignored unexpected " 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Context-Specific tag %d in optional " 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "tbsCertificate fields", hdr.tag); 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* extensions [3] EXPLICIT Extensions OPTIONAL */ 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->version != X509_CERT_V3) { 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and " 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extensions data which are only allowed for " 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "version 3", cert->version + 1); 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0) 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload + hdr.length; 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos < end) { 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "X509: Ignored extra tbsCertificate data", 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, end - pos); 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_rsadsi_oid(struct asn1_oid *oid) 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len >= 4 && 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[0] == 1 /* iso */ && 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[1] == 2 /* member-body */ && 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[2] == 840 /* us */ && 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[3] == 113549 /* rsadsi */; 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_pkcs_oid(struct asn1_oid *oid) 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len >= 5 && 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_rsadsi_oid(oid) && 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[4] == 1 /* pkcs */; 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_digest_oid(struct asn1_oid *oid) 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len >= 5 && 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_rsadsi_oid(oid) && 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[4] == 2 /* digestAlgorithm */; 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_sha1_oid(struct asn1_oid *oid) 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len == 6 && 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[0] == 1 /* iso */ && 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[1] == 3 /* identified-organization */ && 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[2] == 14 /* oiw */ && 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[3] == 3 /* secsig */ && 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[4] == 2 /* algorithms */ && 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[5] == 26 /* id-sha1 */; 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_sha256_oid(struct asn1_oid *oid) 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return oid->len == 9 && 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[0] == 2 /* joint-iso-itu-t */ && 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[1] == 16 /* country */ && 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[2] == 840 /* us */ && 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[3] == 1 /* organization */ && 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[4] == 101 /* gov */ && 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[5] == 3 /* csor */ && 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[6] == 4 /* nistAlgorithm */ && 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[7] == 2 /* hashAlgs */ && 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oid->oid[8] == 1 /* sha256 */; 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_parse - Parse a X.509 certificate in DER format 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Pointer to the X.509 certificate in DER format 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Buffer length 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the parsed certificate or %NULL on failure 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Caller is responsible for freeing the returned certificate by calling 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_free(). 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end, *hash_start; 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert; 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert = os_zalloc(sizeof(*cert) + len); 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert == NULL) 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cert + 1, buf, len); 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->cert_start = (u8 *) (cert + 1); 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->cert_len = len; 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = buf + len; 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */ 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Certificate ::= SEQUENCE */ 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, len, &hdr) < 0 || 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate did not start with " 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "a valid SEQUENCE - found class %d tag 0x%x", 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + hdr.length > end) { 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos + hdr.length < end) { 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER " 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "encoded certificate", 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos + hdr.length, end - pos + hdr.length); 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + hdr.length; 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_start = pos; 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->tbs_cert_start = cert->cert_start + (hash_start - buf); 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) { 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->tbs_cert_len = pos - hash_start; 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* signatureAlgorithm AlgorithmIdentifier */ 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_parse_algorithm_identifier(pos, end - pos, 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->signature_alg, &pos)) { 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* signatureValue BIT STRING */ 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_BITSTRING) { 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(signatureValue) - found class %d tag 0x%x", 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length < 1) { 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (*pos) { 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos); 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* PKCS #1 v1.5 10.2.1: 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * It is an error if the length in bits of the signature S is 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * not a multiple of eight. 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(cert->sign_value); 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->sign_value = os_malloc(hdr.length - 1); 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->sign_value == NULL) { 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "signatureValue"); 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_certificate_free(cert); 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(cert->sign_value, pos + 1, hdr.length - 1); 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->sign_value_len = hdr.length - 1; 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: signature", 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->sign_value, cert->sign_value_len); 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return cert; 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_check_signature - Verify certificate signature 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @issuer: Issuer certificate 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: Certificate to be verified 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 if cert has a valid signature that was signed by the issuer, 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * -1 if not 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint x509_certificate_check_signature(struct x509_certificate *issuer, 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert) 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct crypto_public_key *pk; 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *data; 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos, *end, *next, *da_end; 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t data_len; 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_hdr hdr; 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct asn1_oid oid; 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 hash[32]; 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t hash_len; 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!x509_pkcs_oid(&cert->signature.oid) || 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->signature.oid.len != 7 || 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->signature.oid.oid[5] != 1 /* pkcs-1 */) { 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unrecognized signature " 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "algorithm"); 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pk = crypto_public_key_import(issuer->public_key, 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt issuer->public_key_len); 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pk == NULL) 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data_len = cert->sign_value_len; 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_malloc(data_len); 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) { 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_public_key_free(pk); 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value, 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->sign_value_len, data, 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &data_len) < 0) { 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature"); 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_public_key_free(pk); 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt crypto_public_key_free(pk); 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len); 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * PKCS #1 v1.5, 10.1.2: 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * DigestInfo ::= SEQUENCE { 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * digestAlgorithm DigestAlgorithmIdentifier, 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * digest Digest 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Digest ::= OCTET STRING 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(data, data_len, &hdr) < 0 || 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(DigestInfo) - found class %d tag 0x%x", 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = hdr.payload; 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = pos + hdr.length; 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * X.509: 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AlgorithmIdentifier ::= SEQUENCE { 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * algorithm OBJECT IDENTIFIER, 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * parameters ANY DEFINED BY algorithm OPTIONAL 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * } 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_SEQUENCE) { 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(AlgorithmIdentifier) - found class %d tag 0x%x", 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt da_end = hdr.payload + hdr.length; 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm"); 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_sha1_oid(&oid)) { 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->signature.oid.oid[6] != 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5 /* sha-1WithRSAEncryption */) { 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 " 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "does not match with certificate " 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "signatureAlgorithm (%lu)", 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->signature.oid.oid[6]); 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_digest_oid; 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_sha256_oid(&oid)) { 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->signature.oid.oid[6] != 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11 /* sha2561WithRSAEncryption */) { 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA256 " 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "does not match with certificate " 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "signatureAlgorithm (%lu)", 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->signature.oid.oid[6]); 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_digest_oid; 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!x509_digest_oid(&oid)) { 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (oid.oid[5]) { 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 5: /* md5 */ 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */) 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does " 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with certificate " 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "signatureAlgorithm (%lu)", 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->signature.oid.oid[6]); 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 2: /* md2 */ 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 4: /* md4 */ 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm " 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(%lu)", oid.oid[5]); 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_digest_oid: 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Digest ::= OCTET STRING */ 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = da_end; 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt end = data + data_len; 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (asn1_get_next(pos, end - pos, &hdr) < 0 || 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class != ASN1_CLASS_UNIVERSAL || 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.tag != ASN1_TAG_OCTETSTRING) { 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING " 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Digest) - found class %d tag 0x%x", 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.class, hdr.tag); 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest", 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr.payload, hdr.length); 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (cert->signature.oid.oid[6]) { 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 4: /* md5WithRSAEncryption */ 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash); 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = 16; 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)", 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash, hash_len); 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 5: /* sha-1WithRSAEncryption */ 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash); 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = 20; 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)", 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash, hash_len); 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 11: /* sha256WithRSAEncryption */ 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash); 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash_len = 32; 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA256)", 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hash, hash_len); 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 2: /* md2WithRSAEncryption */ 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 12: /* sha384WithRSAEncryption */ 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case 13: /* sha512WithRSAEncryption */ 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "algorithm (%lu)", cert->signature.oid.oid[6]); 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hdr.length != hash_len || 1779c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memcmp_const(hdr.payload, hash, hdr.length) != 0) { 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Certificate Digest does not match " 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with calculated tbsCertificate hash"); 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178650b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt if (hdr.payload + hdr.length < data + data_len) { 178750b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt wpa_hexdump(MSG_INFO, 178850b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt "X509: Extra data after certificate signature hash", 178950b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt hdr.payload + hdr.length, 179050b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt data + data_len - hdr.payload - hdr.length); 179150b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt os_free(data); 179250b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt return -1; 179350b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt } 179450b691dc36a8075e8f594e8bea93cb524fa6b1d2Dmitry Shmidt 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with " 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "calculated tbsCertificate hash"); 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int x509_valid_issuer(const struct x509_certificate *cert) 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) && 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !cert->ca) { 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an " 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "issuer"); 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->version == X509_CERT_V3 && 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "include BasicConstraints extension"); 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((cert->extensions_present & X509_EXT_KEY_USAGE) && 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "keyCertSign bit in Key Usage"); 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_chain_validate - Validate X.509 certificate chain 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @trusted: List of trusted certificates 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @chain: Certificate chain to be validated (first chain must be issued by 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * signed by the second certificate in the chain and so on) 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @reason: Buffer for returning failure reason (X509_VALIDATE_*) 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 if chain is valid, -1 if not 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint x509_certificate_chain_validate(struct x509_certificate *trusted, 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *chain, 1841c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt int *reason, int disable_time_checks) 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt long unsigned idx; 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int chain_trusted = 0; 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert, *trust; 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char buf[128]; 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct os_time now; 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_OK; 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Validate certificate chain"); 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_get_time(&now); 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->subject, buf, sizeof(buf)); 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (chain_trusted) 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1861c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt if (!disable_time_checks && 1862c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt ((unsigned long) now.sec < 1863c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt (unsigned long) cert->not_before || 1864c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt (unsigned long) now.sec > 1865c55524ad84d13014e8019491c2b17e5dcf13545aDmitry Shmidt (unsigned long) cert->not_after)) { 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "X509: Certificate not valid " 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(now=%lu not_before=%lu not_after=%lu)", 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt now.sec, cert->not_before, cert->not_after); 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_CERTIFICATE_EXPIRED; 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cert->next) { 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_name_compare(&cert->issuer, 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt &cert->next->subject) != 0) { 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate " 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "chain issuer name mismatch"); 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->issuer, buf, 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(buf)); 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: cert issuer: %s", 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf); 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt x509_name_string(&cert->next->subject, buf, 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(buf)); 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: next cert " 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "subject: %s", buf); 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN; 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_valid_issuer(cert->next) < 0) { 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((cert->next->extensions_present & 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt X509_EXT_PATH_LEN_CONSTRAINT) && 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt idx > cert->next->path_len_constraint) { 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " not met (idx=%lu issuer " 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "pathLenConstraint=%lu)", idx, 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cert->next->path_len_constraint); 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_certificate_check_signature(cert->next, cert) 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt < 0) { 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Invalid " 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate signature within " 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "chain"); 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (trust = trusted; trust; trust = trust->next) { 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_name_compare(&cert->issuer, &trust->subject) 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt == 0) 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (trust) { 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Found issuer from the " 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "list of trusted certificates"); 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_valid_issuer(trust) < 0) { 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_certificate_check_signature(trust, cert) < 0) 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt { 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Invalid " 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "certificate signature"); 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_BAD_CERTIFICATE; 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Trusted certificate " 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "found to complete the chain"); 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt chain_trusted = 1; 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!chain_trusted) { 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers " 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from the list of trusted certificates"); 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (trusted) { 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *reason = X509_VALIDATE_UNKNOWN_CA; 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate chain validation " 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "disabled - ignore unknown CA issue"); 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "X509: Certificate chain valid"); 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_get_subject - Get a certificate based on Subject name 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @chain: Certificate chain to search through 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @name: Subject name to search for 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the certificate with the given Subject name or 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * %NULL on failure 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct x509_certificate * 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtx509_certificate_get_subject(struct x509_certificate *chain, 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_name *name) 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct x509_certificate *cert; 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (cert = chain; cert; cert = cert->next) { 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (x509_name_compare(&cert->subject, name) == 0) 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return cert; 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * x509_certificate_self_signed - Is the certificate self-signed? 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @cert: Certificate 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 1 if certificate is self-signed, 0 if not 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint x509_certificate_self_signed(struct x509_certificate *cert) 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return x509_name_compare(&cert->issuer, &cert->subject) == 0; 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1991