1845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/* 2845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * X.509v3 certificate parsing and processing (RFC 3280 profile) 3845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> 4845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 5845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * This program is free software; you can redistribute it and/or modify 6845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * it under the terms of the GNU General Public License version 2 as 7845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * published by the Free Software Foundation. 8845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 9845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Alternatively, this software may be distributed under the terms of BSD 10845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * license. 11845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 12845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * See README and COPYING for more details. 13845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 14845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 15845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "includes.h" 16845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 17845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "common.h" 18845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 19845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#ifdef CONFIG_INTERNAL_X509 20845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 21845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "asn1.h" 22845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "crypto.h" 23845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#include "x509v3.h" 24845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 25845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 26845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void x509_free_name(struct x509_name *name) 27845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 28845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(name->cn); 29845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(name->c); 30845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(name->l); 31845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(name->st); 32845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(name->o); 33845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(name->ou); 34845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(name->email); 35845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project name->cn = name->c = name->l = name->st = name->o = name->ou = NULL; 36845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project name->email = NULL; 37845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 38845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 39845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 40845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 41845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_certificate_free - Free an X.509 certificate 42845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @cert: Certificate to be freed 43845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 44845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid x509_certificate_free(struct x509_certificate *cert) 45845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 46845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert == NULL) 47845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 48845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->next) { 49845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: x509_certificate_free: cer=%p " 50845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "was still on a list (next=%p)\n", 51845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert, cert->next); 52845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 53845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_free_name(&cert->issuer); 54845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_free_name(&cert->subject); 55845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(cert->public_key); 56845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(cert->sign_value); 57845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(cert); 58845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 59845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 60845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 61845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 62845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_certificate_free - Free an X.509 certificate chain 63845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @cert: Pointer to the first certificate in the chain 64845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 65845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid x509_certificate_chain_free(struct x509_certificate *cert) 66845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 67845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_certificate *next; 68845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 69845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (cert) { 70845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project next = cert->next; 71845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->next = NULL; 72845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_certificate_free(cert); 73845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert = next; 74845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 75845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 76845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 77845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 78845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_whitespace(char c) 79845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 80845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return c == ' ' || c == '\t'; 81845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 82845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 83845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 84845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic void x509_str_strip_whitespace(char *a) 85845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 86845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char *ipos, *opos; 87845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int remove_whitespace = 1; 88845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 89845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ipos = opos = a; 90845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 91845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (*ipos) { 92845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (remove_whitespace && x509_whitespace(*ipos)) 93845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ipos++; 94845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project else { 95845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project remove_whitespace = x509_whitespace(*ipos); 96845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *opos++ = *ipos++; 97845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 98845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 99845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 100845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *opos-- = '\0'; 101845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (opos > a && x509_whitespace(*opos)) 102845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *opos = '\0'; 103845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 104845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 105845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 106845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_str_compare(const char *a, const char *b) 107845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 108845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char *aa, *bb; 109845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int ret; 110845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 111845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (!a && b) 112845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 113845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (a && !b) 114845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 1; 115845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (!a && !b) 116845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 117845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 118845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project aa = os_strdup(a); 119845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project bb = os_strdup(b); 120845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 121845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (aa == NULL || bb == NULL) { 122845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(aa); 123845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(bb); 124845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return os_strcasecmp(a, b); 125845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 126845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 127845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_str_strip_whitespace(aa); 128845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_str_strip_whitespace(bb); 129845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 130845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ret = os_strcasecmp(aa, bb); 131845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 132845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(aa); 133845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(bb); 134845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 135845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return ret; 136845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 137845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 138845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 139845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 140845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_name_compare - Compare X.509 certificate names 141845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @a: Certificate name 142845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @b: Certificate name 143845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: <0, 0, or >0 based on whether a is less than, equal to, or 144845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * greater than b 145845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 146845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint x509_name_compare(struct x509_name *a, struct x509_name *b) 147845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 148845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int res; 149845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 150845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (!a && b) 151845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 152845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (a && !b) 153845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 1; 154845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (!a && !b) 155845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 156845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 157845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = x509_str_compare(a->cn, b->cn); 158845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res) 159845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return res; 160845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = x509_str_compare(a->c, b->c); 161845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res) 162845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return res; 163845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = x509_str_compare(a->l, b->l); 164845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res) 165845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return res; 166845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = x509_str_compare(a->st, b->st); 167845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res) 168845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return res; 169845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = x509_str_compare(a->o, b->o); 170845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res) 171845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return res; 172845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = x509_str_compare(a->ou, b->ou); 173845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res) 174845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return res; 175845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = x509_str_compare(a->email, b->email); 176845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res) 177845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return res; 178845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 179845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 180845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 181845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 182845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 183845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_algorithm_identifier( 184845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *buf, size_t len, 185845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_algorithm_identifier *id, const u8 **next) 186845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 187845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 188845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, *end; 189845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 190845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 191845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * AlgorithmIdentifier ::= SEQUENCE { 192845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * algorithm OBJECT IDENTIFIER, 193845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * parameters ANY DEFINED BY algorithm OPTIONAL 194845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * } 195845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 196845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 197845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(buf, len, &hdr) < 0 || 198845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 199845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 200845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 201845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(AlgorithmIdentifier) - found class %d tag 0x%x", 202845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 203845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 204845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 205845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 206845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = pos + hdr.length; 207845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 208845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (end > buf + len) 209845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 210845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 211845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *next = end; 212845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 213845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_oid(pos, end - pos, &id->oid, &pos)) 214845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 215845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 216845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* TODO: optional parameters */ 217845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 218845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 219845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 220845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 221845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 222845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_public_key(const u8 *buf, size_t len, 223845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_certificate *cert, 224845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 **next) 225845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 226845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 227845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, *end; 228845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 229845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 230845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * SubjectPublicKeyInfo ::= SEQUENCE { 231845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * algorithm AlgorithmIdentifier, 232845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * subjectPublicKey BIT STRING 233845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * } 234845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 235845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 236845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = buf; 237845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = buf + len; 238845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 239845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 240845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 241845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 242845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 243845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(SubjectPublicKeyInfo) - found class %d tag 0x%x", 244845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 245845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 246845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 247845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 248845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 249845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (pos + hdr.length > end) 250845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 251845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = pos + hdr.length; 252845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *next = end; 253845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 254845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_algorithm_identifier(pos, end - pos, 255845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &cert->public_key_alg, &pos)) 256845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 257845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 258845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 259845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 260845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_BITSTRING) { 261845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " 262845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(subjectPublicKey) - found class %d tag 0x%x", 263845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 264845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 265845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 266845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.length < 1) 267845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 268845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 269845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (*pos) { 270845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", 271845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *pos); 272845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 273845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * TODO: should this be rejected? X.509 certificates are 274845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * unlikely to use such a construction. Now we would end up 275845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * including the extra bits in the buffer which may also be 276845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * ok. 277845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 278845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 279845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(cert->public_key); 280845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->public_key = os_malloc(hdr.length - 1); 281845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->public_key == NULL) { 282845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " 283845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "public key"); 284845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 285845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 286845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcpy(cert->public_key, pos + 1, hdr.length - 1); 287845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->public_key_len = hdr.length - 1; 288845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_MSGDUMP, "X509: subjectPublicKey", 289845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->public_key, cert->public_key_len); 290845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 291845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 292845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 293845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 294845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 295845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name, 296845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 **next) 297845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 298845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 299845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, *end, *set_pos, *set_end, *seq_pos, *seq_end; 300845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_oid oid; 301845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char **fieldp; 302845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 303845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 304845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Name ::= CHOICE { RDNSequence } 305845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName 306845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue 307845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * AttributeTypeAndValue ::= SEQUENCE { 308845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * type AttributeType, 309845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * value AttributeValue 310845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * } 311845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * AttributeType ::= OBJECT IDENTIFIER 312845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * AttributeValue ::= ANY DEFINED BY AttributeType 313845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 314845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 315845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(buf, len, &hdr) < 0 || 316845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 317845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 318845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 319845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(Name / RDNSequencer) - found class %d tag 0x%x", 320845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 321845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 322845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 323845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 324845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 325845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (pos + hdr.length > buf + len) 326845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 327845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 328845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = *next = pos + hdr.length; 329845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 330845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (pos < end) { 331845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 332845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 333845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SET) { 334845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected SET " 335845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(RelativeDistinguishedName) - found class " 336845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "%d tag 0x%x", hdr.class, hdr.tag); 337845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_free_name(name); 338845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 339845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 340845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 341845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project set_pos = hdr.payload; 342845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = set_end = hdr.payload + hdr.length; 343845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 344845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(set_pos, set_end - set_pos, &hdr) < 0 || 345845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 346845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 347845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 348845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(AttributeTypeAndValue) - found class %d " 349845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "tag 0x%x", hdr.class, hdr.tag); 350845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_free_name(name); 351845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 352845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 353845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 354845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project seq_pos = hdr.payload; 355845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project seq_end = hdr.payload + hdr.length; 356845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 357845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_oid(seq_pos, seq_end - seq_pos, &oid, &seq_pos)) { 358845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_free_name(name); 359845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 360845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 361845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 362845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(seq_pos, seq_end - seq_pos, &hdr) < 0 || 363845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL) { 364845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Failed to parse " 365845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "AttributeValue"); 366845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_free_name(name); 367845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 368845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 369845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 370845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* RFC 3280: 371845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * MUST: country, organization, organizational-unit, 372845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * distinguished name qualifier, state or province name, 373845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * common name, serial number. 374845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * SHOULD: locality, title, surname, given name, initials, 375845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * pseudonym, generation qualifier. 376845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * MUST: domainComponent (RFC 2247). 377845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 378845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fieldp = NULL; 379845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (oid.len == 4 && 380845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid.oid[0] == 2 && oid.oid[1] == 5 && oid.oid[2] == 4) { 381845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* id-at ::= 2.5.4 */ 382845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project switch (oid.oid[3]) { 383845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 3: 384845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* commonName */ 385845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fieldp = &name->cn; 386845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 387845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 6: 388845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* countryName */ 389845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fieldp = &name->c; 390845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 391845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 7: 392845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* localityName */ 393845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fieldp = &name->l; 394845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 395845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 8: 396845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* stateOrProvinceName */ 397845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fieldp = &name->st; 398845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 399845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 10: 400845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* organizationName */ 401845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fieldp = &name->o; 402845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 403845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 11: 404845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* organizationalUnitName */ 405845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fieldp = &name->ou; 406845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 407845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 408845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } else if (oid.len == 7 && 409845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid.oid[0] == 1 && oid.oid[1] == 2 && 410845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid.oid[2] == 840 && oid.oid[3] == 113549 && 411845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid.oid[4] == 1 && oid.oid[5] == 9 && 412845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid.oid[6] == 1) { 413845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 1.2.840.113549.1.9.1 - e-mailAddress */ 414845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project fieldp = &name->email; 415845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 416845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 417845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (fieldp == NULL) { 418845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_DEBUG, "X509: Unrecognized OID", 419845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (u8 *) oid.oid, 420845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid.len * sizeof(oid.oid[0])); 421845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_MSGDUMP, "X509: Attribute Data", 422845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.payload, hdr.length); 423845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project continue; 424845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 425845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 426845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(*fieldp); 427845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *fieldp = os_malloc(hdr.length + 1); 428845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (*fieldp == NULL) { 429845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_free_name(name); 430845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 431845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 432845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcpy(*fieldp, hdr.payload, hdr.length); 433845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (*fieldp)[hdr.length] = '\0'; 434845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 435845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 436845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 437845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 438845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 439845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 440845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 441845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_name_string - Convert an X.509 certificate name into a string 442845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @name: Name to convert 443845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @buf: Buffer for the string 444845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Maximum buffer length 445845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 446845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectvoid x509_name_string(struct x509_name *name, char *buf, size_t len) 447845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 448845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char *pos, *end; 449845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int ret; 450845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 451845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (len == 0) 452845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return; 453845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 454845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = buf; 455845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = buf + len; 456845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 457845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (name->c) { 458845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ret = os_snprintf(pos, end - pos, "C=%s, ", name->c); 459845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (ret < 0 || ret >= end - pos) 460845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto done; 461845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += ret; 462845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 463845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (name->st) { 464845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ret = os_snprintf(pos, end - pos, "ST=%s, ", name->st); 465845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (ret < 0 || ret >= end - pos) 466845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto done; 467845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += ret; 468845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 469845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (name->l) { 470845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ret = os_snprintf(pos, end - pos, "L=%s, ", name->l); 471845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (ret < 0 || ret >= end - pos) 472845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto done; 473845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += ret; 474845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 475845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (name->o) { 476845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ret = os_snprintf(pos, end - pos, "O=%s, ", name->o); 477845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (ret < 0 || ret >= end - pos) 478845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto done; 479845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += ret; 480845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 481845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (name->ou) { 482845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ret = os_snprintf(pos, end - pos, "OU=%s, ", name->ou); 483845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (ret < 0 || ret >= end - pos) 484845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto done; 485845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += ret; 486845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 487845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (name->cn) { 488845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ret = os_snprintf(pos, end - pos, "CN=%s, ", name->cn); 489845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (ret < 0 || ret >= end - pos) 490845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto done; 491845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += ret; 492845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 493845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 494845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (pos > buf + 1 && pos[-1] == ' ' && pos[-2] == ',') { 495845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *pos-- = '\0'; 496845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *pos-- = '\0'; 497845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 498845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 499845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (name->email) { 500845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project ret = os_snprintf(pos, end - pos, "/emailAddress=%s", 501845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project name->email); 502845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (ret < 0 || ret >= end - pos) 503845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto done; 504845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += ret; 505845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 506845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 507845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectdone: 508845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end[-1] = '\0'; 509845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 510845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 511845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 512845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, 513845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_time_t *val) 514845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 515845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const char *pos; 516845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int year, month, day, hour, min, sec; 517845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 518845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 519845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Time ::= CHOICE { 520845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * utcTime UTCTime, 521845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * generalTime GeneralizedTime 522845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * } 523845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 524845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * UTCTime: YYMMDDHHMMSSZ 525845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * GeneralizedTime: YYYYMMDDHHMMSSZ 526845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 527845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 528845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = (const char *) buf; 529845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 530845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project switch (asn1_tag) { 531845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case ASN1_TAG_UTCTIME: 532845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (len != 13 || buf[12] != 'Z') { 533845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " 534845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "UTCTime format", buf, len); 535845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 536845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 537845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (sscanf(pos, "%02d", &year) != 1) { 538845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " 539845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "UTCTime year", buf, len); 540845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 541845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 542845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (year < 50) 543845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project year += 2000; 544845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project else 545845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project year += 1900; 546845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += 2; 547845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 548845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case ASN1_TAG_GENERALIZEDTIME: 549845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (len != 15 || buf[14] != 'Z') { 550845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Unrecognized " 551845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "GeneralizedTime format", buf, len); 552845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 553845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 554845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (sscanf(pos, "%04d", &year) != 1) { 555845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse " 556845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "GeneralizedTime year", buf, len); 557845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 558845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 559845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += 4; 560845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 561845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project default: 562845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected UTCTime or " 563845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "GeneralizedTime - found tag 0x%x", asn1_tag); 564845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 565845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 566845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 567845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (sscanf(pos, "%02d", &month) != 1) { 568845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 569845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(month)", buf, len); 570845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 571845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 572845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += 2; 573845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 574845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (sscanf(pos, "%02d", &day) != 1) { 575845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 576845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(day)", buf, len); 577845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 578845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 579845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += 2; 580845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 581845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (sscanf(pos, "%02d", &hour) != 1) { 582845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 583845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(hour)", buf, len); 584845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 585845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 586845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += 2; 587845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 588845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (sscanf(pos, "%02d", &min) != 1) { 589845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 590845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(min)", buf, len); 591845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 592845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 593845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos += 2; 594845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 595845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (sscanf(pos, "%02d", &sec) != 1) { 596845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse Time " 597845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(sec)", buf, len); 598845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 599845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 600845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 601845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (os_mktime(year, month, day, hour, min, sec, val) < 0) { 602845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time", 603845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project buf, len); 604845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (year < 1970) { 605845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 606845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * At least some test certificates have been configured 607845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * to use dates prior to 1970. Set the date to 608845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * beginning of 1970 to handle these case. 609845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 610845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - " 611845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "assume epoch as the time", year); 612845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *val = 0; 613845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 614845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 615845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 616845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 617845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 618845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 619845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 620845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 621845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 622845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_validity(const u8 *buf, size_t len, 623845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_certificate *cert, const u8 **next) 624845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 625845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 626845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos; 627845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t plen; 628845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 629845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 630845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Validity ::= SEQUENCE { 631845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * notBefore Time, 632845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * notAfter Time 633845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * } 634845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 635845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * RFC 3280, 4.1.2.5: 636845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * CAs conforming to this profile MUST always encode certificate 637845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * validity dates through the year 2049 as UTCTime; certificate 638845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * validity dates in 2050 or later MUST be encoded as GeneralizedTime. 639845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 640845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 641845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(buf, len, &hdr) < 0 || 642845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 643845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 644845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 645845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(Validity) - found class %d tag 0x%x", 646845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 647845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 648845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 649845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 650845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project plen = hdr.length; 651845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 652845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (pos + plen > buf + len) 653845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 654845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 655845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *next = pos + plen; 656845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 657845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, plen, &hdr) < 0 || 658845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 659845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_parse_time(hdr.payload, hdr.length, hdr.tag, 660845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &cert->not_before) < 0) { 661845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notBefore " 662845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "Time", hdr.payload, hdr.length); 663845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 664845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 665845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 666845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload + hdr.length; 667845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project plen = *next - pos; 668845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 669845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, plen, &hdr) < 0 || 670845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 671845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_parse_time(hdr.payload, hdr.length, hdr.tag, 672845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &cert->not_after) < 0) { 673845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to parse notAfter " 674845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "Time", hdr.payload, hdr.length); 675845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 676845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 677845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 678845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_MSGDUMP, "X509: Validity: notBefore: %lu notAfter: %lu", 679845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (unsigned long) cert->not_before, 680845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (unsigned long) cert->not_after); 681845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 682845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 683845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 684845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 685845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 686845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_id_ce_oid(struct asn1_oid *oid) 687845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 688845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* id-ce arc from X.509 for standard X.509v3 extensions */ 689845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return oid->len >= 4 && 690845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[0] == 2 /* joint-iso-ccitt */ && 691845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[1] == 5 /* ds */ && 692845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[2] == 29 /* id-ce */; 693845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 694845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 695845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 696845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_ext_key_usage(struct x509_certificate *cert, 697845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, size_t len) 698845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 699845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 700845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 701845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 702845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * KeyUsage ::= BIT STRING { 703845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * digitalSignature (0), 704845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * nonRepudiation (1), 705845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * keyEncipherment (2), 706845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * dataEncipherment (3), 707845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * keyAgreement (4), 708845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * keyCertSign (5), 709845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * cRLSign (6), 710845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * encipherOnly (7), 711845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * decipherOnly (8) } 712845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 713845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 714845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, len, &hdr) < 0 || 715845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 716845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_BITSTRING || 717845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.length < 1) { 718845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected BIT STRING in " 719845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "KeyUsage; found %d tag 0x%x len %d", 720845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag, hdr.length); 721845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 722845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 723845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 724845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->extensions_present |= X509_EXT_KEY_USAGE; 725845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->key_usage = asn1_bit_string_to_long(hdr.payload, hdr.length); 726845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 727845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: KeyUsage 0x%lx", cert->key_usage); 728845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 729845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 730845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 731845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 732845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 733845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_ext_basic_constraints(struct x509_certificate *cert, 734845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, size_t len) 735845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 736845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 737845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project unsigned long value; 738845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t left; 739845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 740845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 741845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * BasicConstraints ::= SEQUENCE { 742845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * cA BOOLEAN DEFAULT FALSE, 743845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * pathLenConstraint INTEGER (0..MAX) OPTIONAL } 744845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 745845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 746845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, len, &hdr) < 0 || 747845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 748845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 749845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE in " 750845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "BasicConstraints; found %d tag 0x%x", 751845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 752845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 753845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 754845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 755845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->extensions_present |= X509_EXT_BASIC_CONSTRAINTS; 756845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 757845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.length == 0) 758845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 759845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 760845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 || 761845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL) { 762845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Failed to parse " 763845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "BasicConstraints"); 764845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 765845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 766845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 767845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.tag == ASN1_TAG_BOOLEAN) { 768845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.length != 1) { 769845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unexpected " 770845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "Boolean length (%u) in BasicConstraints", 771845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.length); 772845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 773845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 774845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->ca = hdr.payload[0]; 775845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 776845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.payload + hdr.length == pos + len) { 777845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d", 778845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->ca); 779845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 780845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 781845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 782845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length, 783845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &hdr) < 0 || 784845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL) { 785845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Failed to parse " 786845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "BasicConstraints"); 787845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 788845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 789845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 790845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 791845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.tag != ASN1_TAG_INTEGER) { 792845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected INTEGER in " 793845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "BasicConstraints; found class %d tag 0x%x", 794845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 795845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 796845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 797845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 798845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 799845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project left = hdr.length; 800845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project value = 0; 801845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (left) { 802845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project value <<= 8; 803845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project value |= *pos++; 804845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project left--; 805845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 806845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 807845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->path_len_constraint = value; 808845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->extensions_present |= X509_EXT_PATH_LEN_CONSTRAINT; 809845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 810845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: BasicConstraints - cA=%d " 811845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "pathLenConstraint=%lu", 812845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->ca, cert->path_len_constraint); 813845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 814845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 815845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 816845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 817845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 818845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_extension_data(struct x509_certificate *cert, 819845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_oid *oid, 820845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, size_t len) 821845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 822845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (!x509_id_ce_oid(oid)) 823845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 1; 824845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 825845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* TODO: add other extensions required by RFC 3280, Ch 4.2: 826845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * certificate policies (section 4.2.1.5) 827845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * the subject alternative name (section 4.2.1.7) 828845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * name constraints (section 4.2.1.11) 829845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * policy constraints (section 4.2.1.12) 830845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * extended key usage (section 4.2.1.13) 831845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * inhibit any-policy (section 4.2.1.15) 832845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 833845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project switch (oid->oid[3]) { 834845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 15: /* id-ce-keyUsage */ 835845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return x509_parse_ext_key_usage(cert, pos, len); 836845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 19: /* id-ce-basicConstraints */ 837845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return x509_parse_ext_basic_constraints(cert, pos, len); 838845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project default: 839845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 1; 840845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 841845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 842845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 843845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 844845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_extension(struct x509_certificate *cert, 845845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, size_t len, const u8 **next) 846845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 847845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *end; 848845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 849845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_oid oid; 850845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int critical_ext = 0, res; 851845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char buf[80]; 852845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 853845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 854845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Extension ::= SEQUENCE { 855845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * extnID OBJECT IDENTIFIER, 856845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * critical BOOLEAN DEFAULT FALSE, 857845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * extnValue OCTET STRING 858845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * } 859845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 860845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 861845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, len, &hdr) < 0 || 862845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 863845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 864845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " 865845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "Extensions: class %d tag 0x%x; expected SEQUENCE", 866845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 867845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 868845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 869845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 870845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *next = end = pos + hdr.length; 871845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 872845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { 873845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data for " 874845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "Extension (expected OID)"); 875845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 876845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 877845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 878845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 879845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 880845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (hdr.tag != ASN1_TAG_BOOLEAN && 881845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_OCTETSTRING)) { 882845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header in " 883845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "Extensions: class %d tag 0x%x; expected BOOLEAN " 884845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "or OCTET STRING", hdr.class, hdr.tag); 885845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 886845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 887845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 888845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.tag == ASN1_TAG_BOOLEAN) { 889845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.length != 1) { 890845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unexpected " 891845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "Boolean length (%u)", hdr.length); 892845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 893845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 894845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project critical_ext = hdr.payload[0]; 895845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 896845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 897845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (hdr.class != ASN1_CLASS_UNIVERSAL && 898845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_PRIVATE) || 899845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_OCTETSTRING) { 900845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 header " 901845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "in Extensions: class %d tag 0x%x; " 902845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "expected OCTET STRING", 903845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 904845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 905845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 906845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 907845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 908845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project asn1_oid_to_str(&oid, buf, sizeof(buf)); 909845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Extension: extnID=%s critical=%d", 910845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project buf, critical_ext); 911845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_MSGDUMP, "X509: extnValue", hdr.payload, hdr.length); 912845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 913845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project res = x509_parse_extension_data(cert, &oid, hdr.payload, hdr.length); 914845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res < 0) 915845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return res; 916845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (res == 1 && critical_ext) { 917845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_INFO, "X509: Unknown critical extension %s", 918845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project buf); 919845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 920845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 921845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 922845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 923845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 924845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 925845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 926845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_extensions(struct x509_certificate *cert, 927845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, size_t len) 928845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 929845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *end; 930845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 931845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 932845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ 933845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 934845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, len, &hdr) < 0 || 935845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 936845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 937845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unexpected ASN.1 data " 938845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "for Extensions: class %d tag 0x%x; " 939845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "expected SEQUENCE", hdr.class, hdr.tag); 940845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 941845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 942845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 943845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 944845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = pos + hdr.length; 945845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 946845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (pos < end) { 947845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_extension(cert, pos, end - pos, &pos) 948845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project < 0) 949845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 950845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 951845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 952845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 953845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 954845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 955845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 956845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_parse_tbs_certificate(const u8 *buf, size_t len, 957845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_certificate *cert, 958845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 **next) 959845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 960845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 961845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, *end; 962845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t left; 963845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char sbuf[128]; 964845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project unsigned long value; 965845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 966845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* tbsCertificate TBSCertificate ::= SEQUENCE */ 967845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(buf, len, &hdr) < 0 || 968845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 969845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 970845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: tbsCertificate did not start " 971845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "with a valid SEQUENCE - found class %d tag 0x%x", 972845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 973845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 974845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 975845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 976845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = *next = pos + hdr.length; 977845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 978845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 979845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * version [0] EXPLICIT Version DEFAULT v1 980845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Version ::= INTEGER { v1(0), v2(1), v3(2) } 981845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 982845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0) 983845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 984845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 985845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 986845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC) { 987845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0) 988845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 989845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 990845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.class != ASN1_CLASS_UNIVERSAL || 991845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_INTEGER) { 992845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " 993845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "version field - found class %d tag 0x%x", 994845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 995845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 996845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 997845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.length != 1) { 998845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unexpected version field " 999845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "length %u (expected 1)", hdr.length); 1000845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1001845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1002845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 1003845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project left = hdr.length; 1004845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project value = 0; 1005845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (left) { 1006845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project value <<= 8; 1007845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project value |= *pos++; 1008845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project left--; 1009845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1010845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1011845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->version = value; 1012845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->version != X509_CERT_V1 && 1013845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->version != X509_CERT_V2 && 1014845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->version != X509_CERT_V3) { 1015845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unsupported version %d", 1016845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->version + 1); 1017845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1018845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1019845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1020845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0) 1021845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1022845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } else 1023845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->version = X509_CERT_V1; 1024845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_MSGDUMP, "X509: Version X.509v%d", cert->version + 1); 1025845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1026845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* serialNumber CertificateSerialNumber ::= INTEGER */ 1027845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.class != ASN1_CLASS_UNIVERSAL || 1028845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_INTEGER) { 1029845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: No INTEGER tag found for " 1030845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "serialNumber; class=%d tag=0x%x", 1031845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 1032845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1033845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1034845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1035845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 1036845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project left = hdr.length; 1037845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project while (left) { 1038845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->serial_number <<= 8; 1039845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->serial_number |= *pos++; 1040845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project left--; 1041845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1042845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_MSGDUMP, "X509: serialNumber %lu", cert->serial_number); 1043845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1044845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* signature AlgorithmIdentifier */ 1045845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_algorithm_identifier(pos, end - pos, &cert->signature, 1046845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &pos)) 1047845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1048845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1049845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* issuer Name */ 1050845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_name(pos, end - pos, &cert->issuer, &pos)) 1051845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1052845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_name_string(&cert->issuer, sbuf, sizeof(sbuf)); 1053845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_MSGDUMP, "X509: issuer %s", sbuf); 1054845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1055845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* validity Validity */ 1056845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_validity(pos, end - pos, cert, &pos)) 1057845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1058845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1059845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* subject Name */ 1060845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_name(pos, end - pos, &cert->subject, &pos)) 1061845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1062845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_name_string(&cert->subject, sbuf, sizeof(sbuf)); 1063845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_MSGDUMP, "X509: subject %s", sbuf); 1064845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1065845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* subjectPublicKeyInfo SubjectPublicKeyInfo */ 1066845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_public_key(pos, end - pos, cert, &pos)) 1067845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1068845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1069845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (pos == end) 1070845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 1071845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1072845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->version == X509_CERT_V1) 1073845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 1074845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1075845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1076845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { 1077845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" 1078845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project " tag to parse optional tbsCertificate " 1079845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "field(s); parsed class %d tag 0x%x", 1080845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 1081845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1082845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1083845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1084845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.tag == 1) { 1085845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL */ 1086845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: issuerUniqueID"); 1087845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* TODO: parse UniqueIdentifier ::= BIT STRING */ 1088845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1089845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.payload + hdr.length == end) 1090845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 1091845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1092845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1093845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { 1094845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" 1095845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project " tag to parse optional tbsCertificate " 1096845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "field(s); parsed class %d tag 0x%x", 1097845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 1098845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1099845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1100845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1101845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1102845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.tag == 2) { 1103845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL */ 1104845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: subjectUniqueID"); 1105845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* TODO: parse UniqueIdentifier ::= BIT STRING */ 1106845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1107845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.payload + hdr.length == end) 1108845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 1109845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1110845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1111845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) { 1112845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected Context-Specific" 1113845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project " tag to parse optional tbsCertificate " 1114845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "field(s); parsed class %d tag 0x%x", 1115845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 1116845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1117845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1118845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1119845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1120845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.tag != 3) { 1121845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Ignored unexpected " 1122845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "Context-Specific tag %d in optional " 1123845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "tbsCertificate fields", hdr.tag); 1124845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 1125845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1126845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1127845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* extensions [3] EXPLICIT Extensions OPTIONAL */ 1128845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1129845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->version != X509_CERT_V3) { 1130845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: X.509%d certificate and " 1131845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "Extensions data which are only allowed for " 1132845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "version 3", cert->version + 1); 1133845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1134845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1135845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1136845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_extensions(cert, hdr.payload, hdr.length) < 0) 1137845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1138845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1139845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload + hdr.length; 1140845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (pos < end) { 1141845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_DEBUG, 1142845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "X509: Ignored extra tbsCertificate data", 1143845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos, end - pos); 1144845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1145845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1146845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 1147845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1148845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1149845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1150845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_rsadsi_oid(struct asn1_oid *oid) 1151845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1152845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return oid->len >= 4 && 1153845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[0] == 1 /* iso */ && 1154845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[1] == 2 /* member-body */ && 1155845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[2] == 840 /* us */ && 1156845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[3] == 113549 /* rsadsi */; 1157845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1158845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1159845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1160845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_pkcs_oid(struct asn1_oid *oid) 1161845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1162845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return oid->len >= 5 && 1163845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_rsadsi_oid(oid) && 1164845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[4] == 1 /* pkcs */; 1165845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1166845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1167845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1168845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_digest_oid(struct asn1_oid *oid) 1169845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1170845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return oid->len >= 5 && 1171845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_rsadsi_oid(oid) && 1172845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[4] == 2 /* digestAlgorithm */; 1173845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1174845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1175845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1176845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_sha1_oid(struct asn1_oid *oid) 1177845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1178845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return oid->len == 6 && 1179845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[0] == 1 /* iso */ && 1180845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[1] == 3 /* identified-organization */ && 1181845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[2] == 14 /* oiw */ && 1182845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[3] == 3 /* secsig */ && 1183845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[4] == 2 /* algorithms */ && 1184845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project oid->oid[5] == 26 /* id-sha1 */; 1185845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1186845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1187845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1188845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 1189845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_certificate_parse - Parse a X.509 certificate in DER format 1190845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @buf: Pointer to the X.509 certificate in DER format 1191845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @len: Buffer length 1192845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the parsed certificate or %NULL on failure 1193845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 1194845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Caller is responsible for freeing the returned certificate by calling 1195845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_certificate_free(). 1196845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 1197845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) 1198845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1199845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 1200845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, *end, *hash_start; 1201845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_certificate *cert; 1202845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1203845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert = os_zalloc(sizeof(*cert) + len); 1204845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert == NULL) 1205845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1206845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcpy(cert + 1, buf, len); 1207845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->cert_start = (u8 *) (cert + 1); 1208845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->cert_len = len; 1209845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1210845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = buf; 1211845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = buf + len; 1212845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1213845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* RFC 3280 - X.509 v3 certificate / ASN.1 DER */ 1214845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1215845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* Certificate ::= SEQUENCE */ 1216845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, len, &hdr) < 0 || 1217845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 1218845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 1219845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Certificate did not start with " 1220845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "a valid SEQUENCE - found class %d tag 0x%x", 1221845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 1222845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_certificate_free(cert); 1223845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1224845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1225845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 1226845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1227845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (pos + hdr.length > end) { 1228845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_certificate_free(cert); 1229845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1230845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1231845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1232845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (pos + hdr.length < end) { 1233845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER " 1234845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "encoded certificate", 1235845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos + hdr.length, end - pos + hdr.length); 1236845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = pos + hdr.length; 1237845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1238845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1239845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hash_start = pos; 1240845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->tbs_cert_start = cert->cert_start + (hash_start - buf); 1241845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_tbs_certificate(pos, end - pos, cert, &pos)) { 1242845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_certificate_free(cert); 1243845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1244845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1245845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->tbs_cert_len = pos - hash_start; 1246845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1247845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* signatureAlgorithm AlgorithmIdentifier */ 1248845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_parse_algorithm_identifier(pos, end - pos, 1249845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &cert->signature_alg, &pos)) { 1250845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_certificate_free(cert); 1251845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1252845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1253845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1254845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* signatureValue BIT STRING */ 1255845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1256845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 1257845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_BITSTRING) { 1258845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected BITSTRING " 1259845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(signatureValue) - found class %d tag 0x%x", 1260845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 1261845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_certificate_free(cert); 1262845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1263845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1264845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.length < 1) { 1265845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_certificate_free(cert); 1266845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1267845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1268845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 1269845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (*pos) { 1270845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", 1271845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *pos); 1272845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* PKCS #1 v1.5 10.2.1: 1273845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * It is an error if the length in bits of the signature S is 1274845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * not a multiple of eight. 1275845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 1276845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_certificate_free(cert); 1277845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1278845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1279845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(cert->sign_value); 1280845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->sign_value = os_malloc(hdr.length - 1); 1281845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->sign_value == NULL) { 1282845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Failed to allocate memory for " 1283845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "signatureValue"); 1284845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_certificate_free(cert); 1285845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1286845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1287845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcpy(cert->sign_value, pos + 1, hdr.length - 1); 1288845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->sign_value_len = hdr.length - 1; 1289845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_MSGDUMP, "X509: signature", 1290845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->sign_value, cert->sign_value_len); 1291845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1292845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return cert; 1293845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1294845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1295845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1296845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 1297845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_certificate_check_signature - Verify certificate signature 1298845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @issuer: Issuer certificate 1299845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @cert: Certificate to be verified 1300845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: 0 if cert has a valid signature that was signed by the issuer, 1301845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * -1 if not 1302845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 1303845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint x509_certificate_check_signature(struct x509_certificate *issuer, 1304845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_certificate *cert) 1305845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1306845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct crypto_public_key *pk; 1307845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project u8 *data; 1308845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project const u8 *pos, *end, *next, *da_end; 1309845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t data_len; 1310845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_hdr hdr; 1311845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct asn1_oid oid; 1312845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project u8 hash[20]; 1313845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project size_t hash_len; 1314845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1315845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (!x509_pkcs_oid(&cert->signature.oid) || 1316845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->signature.oid.len != 7 || 1317845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->signature.oid.oid[5] != 1 /* pkcs-1 */) { 1318845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unrecognized signature " 1319845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "algorithm"); 1320845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1321845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1322845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1323845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pk = crypto_public_key_import(issuer->public_key, 1324845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project issuer->public_key_len); 1325845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (pk == NULL) 1326845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1327845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1328845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project data_len = cert->sign_value_len; 1329845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project data = os_malloc(data_len); 1330845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (data == NULL) { 1331845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project crypto_public_key_free(pk); 1332845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1333845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1334845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1335845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (crypto_public_key_decrypt_pkcs1(pk, cert->sign_value, 1336845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->sign_value_len, data, 1337845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &data_len) < 0) { 1338845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Failed to decrypt signature"); 1339845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project crypto_public_key_free(pk); 1340845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1341845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1342845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1343845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project crypto_public_key_free(pk); 1344845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1345845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_MSGDUMP, "X509: Signature data D", data, data_len); 1346845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1347845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 1348845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * PKCS #1 v1.5, 10.1.2: 1349845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 1350845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * DigestInfo ::= SEQUENCE { 1351845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * digestAlgorithm DigestAlgorithmIdentifier, 1352845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * digest Digest 1353845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * } 1354845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 1355845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * DigestAlgorithmIdentifier ::= AlgorithmIdentifier 1356845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 1357845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Digest ::= OCTET STRING 1358845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * 1359845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 1360845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(data, data_len, &hdr) < 0 || 1361845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 1362845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 1363845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 1364845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(DigestInfo) - found class %d tag 0x%x", 1365845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 1366845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1367845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1368845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1369845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1370845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = hdr.payload; 1371845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = pos + hdr.length; 1372845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1373845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* 1374845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * X.509: 1375845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * AlgorithmIdentifier ::= SEQUENCE { 1376845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * algorithm OBJECT IDENTIFIER, 1377845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * parameters ANY DEFINED BY algorithm OPTIONAL 1378845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * } 1379845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 1380845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1381845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1382845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 1383845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_SEQUENCE) { 1384845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected SEQUENCE " 1385845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(AlgorithmIdentifier) - found class %d tag 0x%x", 1386845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 1387845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1388845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1389845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1390845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project da_end = hdr.payload + hdr.length; 1391845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1392845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_oid(hdr.payload, hdr.length, &oid, &next)) { 1393845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Failed to parse digestAlgorithm"); 1394845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1395845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1396845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1397845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1398845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_sha1_oid(&oid)) { 1399845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->signature.oid.oid[6] != 1400845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 5 /* sha-1WithRSAEncryption */) { 1401845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: digestAlgorithm SHA1 " 1402845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "does not match with certificate " 1403845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "signatureAlgorithm (%lu)", 1404845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->signature.oid.oid[6]); 1405845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1406845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1407845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1408845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project goto skip_digest_oid; 1409845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1410845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1411845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (!x509_digest_oid(&oid)) { 1412845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unrecognized digestAlgorithm"); 1413845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1414845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1415845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1416845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project switch (oid.oid[5]) { 1417845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 5: /* md5 */ 1418845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->signature.oid.oid[6] != 4 /* md5WithRSAEncryption */) 1419845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project { 1420845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: digestAlgorithm MD5 does " 1421845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "not match with certificate " 1422845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "signatureAlgorithm (%lu)", 1423845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->signature.oid.oid[6]); 1424845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1425845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1426845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1427845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 1428845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 2: /* md2 */ 1429845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 4: /* md4 */ 1430845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project default: 1431845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Unsupported digestAlgorithm " 1432845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(%lu)", oid.oid[5]); 1433845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1434845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1435845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1436845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1437845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectskip_digest_oid: 1438845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project /* Digest ::= OCTET STRING */ 1439845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project pos = da_end; 1440845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project end = data + data_len; 1441845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1442845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (asn1_get_next(pos, end - pos, &hdr) < 0 || 1443845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class != ASN1_CLASS_UNIVERSAL || 1444845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.tag != ASN1_TAG_OCTETSTRING) { 1445845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Expected OCTETSTRING " 1446845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(Digest) - found class %d tag 0x%x", 1447845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.class, hdr.tag); 1448845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1449845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1450845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1451845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_MSGDUMP, "X509: Decrypted Digest", 1452845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hdr.payload, hdr.length); 1453845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1454845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project switch (cert->signature.oid.oid[6]) { 1455845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 4: /* md5WithRSAEncryption */ 1456845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project md5_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, 1457845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hash); 1458845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hash_len = 16; 1459845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (MD5)", 1460845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hash, hash_len); 1461845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 1462845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 5: /* sha-1WithRSAEncryption */ 1463845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project sha1_vector(1, &cert->tbs_cert_start, &cert->tbs_cert_len, 1464845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hash); 1465845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hash_len = 20; 1466845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_hexdump(MSG_MSGDUMP, "X509: Certificate hash (SHA1)", 1467845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project hash, hash_len); 1468845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 1469845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 2: /* md2WithRSAEncryption */ 1470845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 11: /* sha256WithRSAEncryption */ 1471845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 12: /* sha384WithRSAEncryption */ 1472845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project case 13: /* sha512WithRSAEncryption */ 1473845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project default: 1474845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_INFO, "X509: Unsupported certificate signature " 1475845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "algorithm (%lu)", cert->signature.oid.oid[6]); 1476845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1477845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1478845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1479845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1480845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (hdr.length != hash_len || 1481845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_memcmp(hdr.payload, hash, hdr.length) != 0) { 1482845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_INFO, "X509: Certificate Digest does not match " 1483845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "with calculated tbsCertificate hash"); 1484845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1485845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1486845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1487845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1488845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_free(data); 1489845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1490845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with " 1491845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "calculated tbsCertificate hash"); 1492845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1493845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 1494845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1495845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1496845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1497845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstatic int x509_valid_issuer(const struct x509_certificate *cert) 1498845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1499845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if ((cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS) && 1500845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project !cert->ca) { 1501845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Non-CA certificate used as an " 1502845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "issuer"); 1503845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1504845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1505845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1506845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->version == X509_CERT_V3 && 1507845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { 1508845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " 1509845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "include BasicConstraints extension"); 1510845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1511845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1512845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1513845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if ((cert->extensions_present & X509_EXT_KEY_USAGE) && 1514845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { 1515845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " 1516845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "keyCertSign bit in Key Usage"); 1517845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1518845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1519845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1520845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 1521845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1522845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1523845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1524845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 1525845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_certificate_chain_validate - Validate X.509 certificate chain 1526845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @trusted: List of trusted certificates 1527845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @chain: Certificate chain to be validated (first chain must be issued by 1528845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * signed by the second certificate in the chain and so on) 1529845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @reason: Buffer for returning failure reason (X509_VALIDATE_*) 1530845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: 0 if chain is valid, -1 if not 1531845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 1532845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint x509_certificate_chain_validate(struct x509_certificate *trusted, 1533845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_certificate *chain, 1534845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int *reason) 1535845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1536845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project long unsigned idx; 1537845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project int chain_trusted = 0; 1538845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_certificate *cert, *trust; 1539845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project char buf[128]; 1540845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct os_time now; 1541845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1542845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reason = X509_VALIDATE_OK; 1543845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1544845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Validate certificate chain"); 1545845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project os_get_time(&now); 1546845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1547845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { 1548845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project x509_name_string(&cert->subject, buf, sizeof(buf)); 1549845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); 1550845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1551845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (chain_trusted) 1552845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project continue; 1553845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1554845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if ((unsigned long) now.sec < 1555845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (unsigned long) cert->not_before || 1556845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (unsigned long) now.sec > 1557845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project (unsigned long) cert->not_after) { 1558845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_INFO, "X509: Certificate not valid " 1559845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "(now=%lu not_before=%lu not_after=%lu)", 1560845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project now.sec, cert->not_before, cert->not_after); 1561845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reason = X509_VALIDATE_CERTIFICATE_EXPIRED; 1562845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1563845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1564845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1565845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (cert->next) { 1566845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_name_compare(&cert->issuer, 1567845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project &cert->next->subject) != 0) { 1568845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Certificate " 1569845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "chain issuer name mismatch"); 1570845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reason = X509_VALIDATE_CERTIFICATE_UNKNOWN; 1571845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1572845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1573845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1574845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_valid_issuer(cert->next) < 0) { 1575845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reason = X509_VALIDATE_BAD_CERTIFICATE; 1576845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1577845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1578845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1579845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if ((cert->next->extensions_present & 1580845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project X509_EXT_PATH_LEN_CONSTRAINT) && 1581845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project idx > cert->next->path_len_constraint) { 1582845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" 1583845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project " not met (idx=%lu issuer " 1584845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "pathLenConstraint=%lu)", idx, 1585845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project cert->next->path_len_constraint); 1586845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reason = X509_VALIDATE_BAD_CERTIFICATE; 1587845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1588845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1589845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1590845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_certificate_check_signature(cert->next, cert) 1591845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project < 0) { 1592845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Invalid " 1593845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "certificate signature within " 1594845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "chain"); 1595845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reason = X509_VALIDATE_BAD_CERTIFICATE; 1596845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1597845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1598845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1599845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1600845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project for (trust = trusted; trust; trust = trust->next) { 1601845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_name_compare(&cert->issuer, &trust->subject) 1602845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project == 0) 1603845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project break; 1604845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1605845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1606845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (trust) { 1607845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Found issuer from the " 1608845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "list of trusted certificates"); 1609845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_valid_issuer(trust) < 0) { 1610845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reason = X509_VALIDATE_BAD_CERTIFICATE; 1611845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1612845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1613845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1614845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_certificate_check_signature(trust, cert) < 0) 1615845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project { 1616845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Invalid " 1617845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "certificate signature"); 1618845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reason = X509_VALIDATE_BAD_CERTIFICATE; 1619845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1620845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1621845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1622845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Trusted certificate " 1623845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "found to complete the chain"); 1624845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project chain_trusted = 1; 1625845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1626845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1627845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1628845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (!chain_trusted) { 1629845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Did not find any of the issuers " 1630845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "from the list of trusted certificates"); 1631845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (trusted) { 1632845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project *reason = X509_VALIDATE_UNKNOWN_CA; 1633845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return -1; 1634845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1635845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Certificate chain validation " 1636845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project "disabled - ignore unknown CA issue"); 1637845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1638845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1639845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project wpa_printf(MSG_DEBUG, "X509: Certificate chain valid"); 1640845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1641845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return 0; 1642845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1643845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1644845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1645845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 1646845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_certificate_get_subject - Get a certificate based on Subject name 1647845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @chain: Certificate chain to search through 1648845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @name: Subject name to search for 1649845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: Pointer to the certificate with the given Subject name or 1650845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * %NULL on failure 1651845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 1652845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectstruct x509_certificate * 1653845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectx509_certificate_get_subject(struct x509_certificate *chain, 1654845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_name *name) 1655845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1656845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project struct x509_certificate *cert; 1657845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1658845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project for (cert = chain; cert; cert = cert->next) { 1659845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project if (x509_name_compare(&cert->subject, name) == 0) 1660845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return cert; 1661845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project } 1662845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return NULL; 1663845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1664845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1665845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1666845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project/** 1667845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * x509_certificate_self_signed - Is the certificate self-signed? 1668845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * @cert: Certificate 1669845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project * Returns: 1 if certificate is self-signed, 0 if not 1670845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project */ 1671845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Projectint x509_certificate_self_signed(struct x509_certificate *cert) 1672845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project{ 1673845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project return x509_name_compare(&cert->issuer, &cert->subject) == 0; 1674845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project} 1675845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project 1676845e0124d42b67ef926fbae32a7f61d2e5109ebdThe Android Open Source Project#endif /* CONFIG_INTERNAL_X509 */ 1677