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