xref: /freebsd/contrib/wpa/src/tls/tlsv1_client_ocsp.c (revision c1d255d3ffdbe447de3ab875bf4e7d7accc5bfc5)
1780fb4a2SCy Schubert /*
2780fb4a2SCy Schubert  * TLSv1 client - OCSP
3780fb4a2SCy Schubert  * Copyright (c) 2015, Jouni Malinen <j@w1.fi>
4780fb4a2SCy Schubert  *
5780fb4a2SCy Schubert  * This software may be distributed under the terms of the BSD license.
6780fb4a2SCy Schubert  * See README for more details.
7780fb4a2SCy Schubert  */
8780fb4a2SCy Schubert 
9780fb4a2SCy Schubert #include "includes.h"
10780fb4a2SCy Schubert 
11780fb4a2SCy Schubert #include "common.h"
12780fb4a2SCy Schubert #include "crypto/tls.h"
13780fb4a2SCy Schubert #include "crypto/sha1.h"
14780fb4a2SCy Schubert #include "asn1.h"
15780fb4a2SCy Schubert #include "x509v3.h"
16780fb4a2SCy Schubert #include "tlsv1_common.h"
17780fb4a2SCy Schubert #include "tlsv1_record.h"
18780fb4a2SCy Schubert #include "tlsv1_client.h"
19780fb4a2SCy Schubert #include "tlsv1_client_i.h"
20780fb4a2SCy Schubert 
21780fb4a2SCy Schubert 
22780fb4a2SCy Schubert /* RFC 6960, 4.2.1: OCSPResponseStatus ::= ENUMERATED */
23780fb4a2SCy Schubert enum ocsp_response_status {
24780fb4a2SCy Schubert 	OCSP_RESP_STATUS_SUCCESSFUL = 0,
25780fb4a2SCy Schubert 	OCSP_RESP_STATUS_MALFORMED_REQ = 1,
26780fb4a2SCy Schubert 	OCSP_RESP_STATUS_INT_ERROR = 2,
27780fb4a2SCy Schubert 	OCSP_RESP_STATUS_TRY_LATER = 3,
28780fb4a2SCy Schubert 	/* 4 not used */
29780fb4a2SCy Schubert 	OCSP_RESP_STATUS_SIG_REQUIRED = 5,
30780fb4a2SCy Schubert 	OCSP_RESP_STATUS_UNAUTHORIZED = 6,
31780fb4a2SCy Schubert };
32780fb4a2SCy Schubert 
33780fb4a2SCy Schubert 
is_oid_basic_ocsp_resp(struct asn1_oid * oid)34780fb4a2SCy Schubert static int is_oid_basic_ocsp_resp(struct asn1_oid *oid)
35780fb4a2SCy Schubert {
36780fb4a2SCy Schubert 	return oid->len == 10 &&
37780fb4a2SCy Schubert 		oid->oid[0] == 1 /* iso */ &&
38780fb4a2SCy Schubert 		oid->oid[1] == 3 /* identified-organization */ &&
39780fb4a2SCy Schubert 		oid->oid[2] == 6 /* dod */ &&
40780fb4a2SCy Schubert 		oid->oid[3] == 1 /* internet */ &&
41780fb4a2SCy Schubert 		oid->oid[4] == 5 /* security */ &&
42780fb4a2SCy Schubert 		oid->oid[5] == 5 /* mechanisms */ &&
43780fb4a2SCy Schubert 		oid->oid[6] == 7 /* id-pkix */ &&
44780fb4a2SCy Schubert 		oid->oid[7] == 48 /* id-ad */ &&
45780fb4a2SCy Schubert 		oid->oid[8] == 1 /* id-pkix-ocsp */ &&
46780fb4a2SCy Schubert 		oid->oid[9] == 1 /* id-pkix-ocsp-basic */;
47780fb4a2SCy Schubert }
48780fb4a2SCy Schubert 
49780fb4a2SCy Schubert 
ocsp_responder_id_match(struct x509_certificate * signer,struct x509_name * name,const u8 * key_hash)50780fb4a2SCy Schubert static int ocsp_responder_id_match(struct x509_certificate *signer,
51780fb4a2SCy Schubert 				   struct x509_name *name, const u8 *key_hash)
52780fb4a2SCy Schubert {
53780fb4a2SCy Schubert 	if (key_hash) {
54780fb4a2SCy Schubert 		u8 hash[SHA1_MAC_LEN];
55780fb4a2SCy Schubert 		const u8 *addr[1] = { signer->public_key };
56780fb4a2SCy Schubert 		size_t len[1] = { signer->public_key_len };
57780fb4a2SCy Schubert 
58780fb4a2SCy Schubert 		if (sha1_vector(1, addr, len, hash) < 0)
59780fb4a2SCy Schubert 			return 0;
60780fb4a2SCy Schubert 		return os_memcmp(hash, key_hash, SHA1_MAC_LEN) == 0;
61780fb4a2SCy Schubert 	}
62780fb4a2SCy Schubert 
63780fb4a2SCy Schubert 	return x509_name_compare(&signer->subject, name) == 0;
64780fb4a2SCy Schubert }
65780fb4a2SCy Schubert 
66780fb4a2SCy Schubert 
ocsp_hash_data(struct asn1_oid * alg,const u8 * data,size_t data_len,u8 * hash)67780fb4a2SCy Schubert static unsigned int ocsp_hash_data(struct asn1_oid *alg, const u8 *data,
68780fb4a2SCy Schubert 				   size_t data_len, u8 *hash)
69780fb4a2SCy Schubert {
70780fb4a2SCy Schubert 	const u8 *addr[1] = { data };
71780fb4a2SCy Schubert 	size_t len[1] = { data_len };
72780fb4a2SCy Schubert 	char buf[100];
73780fb4a2SCy Schubert 
74780fb4a2SCy Schubert 	if (x509_sha1_oid(alg)) {
75780fb4a2SCy Schubert 		if (sha1_vector(1, addr, len, hash) < 0)
76780fb4a2SCy Schubert 			return 0;
77780fb4a2SCy Schubert 		wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA1)", hash, 20);
78780fb4a2SCy Schubert 		return 20;
79780fb4a2SCy Schubert 	}
80780fb4a2SCy Schubert 
81780fb4a2SCy Schubert 	if (x509_sha256_oid(alg)) {
82780fb4a2SCy Schubert 		if (sha256_vector(1, addr, len, hash) < 0)
83780fb4a2SCy Schubert 			return 0;
84780fb4a2SCy Schubert 		wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA256)", hash, 32);
85780fb4a2SCy Schubert 		return 32;
86780fb4a2SCy Schubert 	}
87780fb4a2SCy Schubert 
88780fb4a2SCy Schubert 	if (x509_sha384_oid(alg)) {
89780fb4a2SCy Schubert 		if (sha384_vector(1, addr, len, hash) < 0)
90780fb4a2SCy Schubert 			return 0;
91780fb4a2SCy Schubert 		wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA384)", hash, 48);
92780fb4a2SCy Schubert 		return 48;
93780fb4a2SCy Schubert 	}
94780fb4a2SCy Schubert 
95780fb4a2SCy Schubert 	if (x509_sha512_oid(alg)) {
96780fb4a2SCy Schubert 		if (sha512_vector(1, addr, len, hash) < 0)
97780fb4a2SCy Schubert 			return 0;
98780fb4a2SCy Schubert 		wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA512)", hash, 64);
99780fb4a2SCy Schubert 		return 64;
100780fb4a2SCy Schubert 	}
101780fb4a2SCy Schubert 
102780fb4a2SCy Schubert 
103780fb4a2SCy Schubert 	asn1_oid_to_str(alg, buf, sizeof(buf));
104780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "OCSP: Could not calculate hash with alg %s",
105780fb4a2SCy Schubert 		   buf);
106780fb4a2SCy Schubert 	return 0;
107780fb4a2SCy Schubert }
108780fb4a2SCy Schubert 
109780fb4a2SCy Schubert 
tls_process_ocsp_single_response(struct tlsv1_client * conn,struct x509_certificate * cert,struct x509_certificate * issuer,const u8 * resp,size_t len,enum tls_ocsp_result * res)110780fb4a2SCy Schubert static int tls_process_ocsp_single_response(struct tlsv1_client *conn,
111780fb4a2SCy Schubert 					    struct x509_certificate *cert,
112780fb4a2SCy Schubert 					    struct x509_certificate *issuer,
113780fb4a2SCy Schubert 					    const u8 *resp, size_t len,
114780fb4a2SCy Schubert 					    enum tls_ocsp_result *res)
115780fb4a2SCy Schubert {
116780fb4a2SCy Schubert 	struct asn1_hdr hdr;
117780fb4a2SCy Schubert 	const u8 *pos, *end;
118780fb4a2SCy Schubert 	struct x509_algorithm_identifier alg;
119780fb4a2SCy Schubert 	const u8 *name_hash, *key_hash;
120780fb4a2SCy Schubert 	size_t name_hash_len, key_hash_len;
121780fb4a2SCy Schubert 	const u8 *serial_number;
122780fb4a2SCy Schubert 	size_t serial_number_len;
123780fb4a2SCy Schubert 	u8 hash[64];
124780fb4a2SCy Schubert 	unsigned int hash_len;
125780fb4a2SCy Schubert 	unsigned int cert_status;
126780fb4a2SCy Schubert 	os_time_t update;
127780fb4a2SCy Schubert 	struct os_time now;
128780fb4a2SCy Schubert 
129780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "OCSP: SingleResponse", resp, len);
130780fb4a2SCy Schubert 
131780fb4a2SCy Schubert 	/*
132780fb4a2SCy Schubert 	 * SingleResponse ::= SEQUENCE {
133780fb4a2SCy Schubert 	 *    certID                       CertID,
134780fb4a2SCy Schubert 	 *    certStatus                   CertStatus,
135780fb4a2SCy Schubert 	 *    thisUpdate                   GeneralizedTime,
136780fb4a2SCy Schubert 	 *    nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
137780fb4a2SCy Schubert 	 *    singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
138780fb4a2SCy Schubert 	 */
139780fb4a2SCy Schubert 
140780fb4a2SCy Schubert 	/* CertID ::= SEQUENCE */
141*c1d255d3SCy Schubert 	if (asn1_get_next(resp, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
142*c1d255d3SCy Schubert 		asn1_unexpected(&hdr, "OCSP: Expected SEQUENCE (CertID)");
143780fb4a2SCy Schubert 		return -1;
144780fb4a2SCy Schubert 	}
145780fb4a2SCy Schubert 	pos = hdr.payload;
146780fb4a2SCy Schubert 	end = hdr.payload + hdr.length;
147780fb4a2SCy Schubert 
148780fb4a2SCy Schubert 	/*
149780fb4a2SCy Schubert 	 * CertID ::= SEQUENCE {
150780fb4a2SCy Schubert 	 *    hashAlgorithm           AlgorithmIdentifier,
151780fb4a2SCy Schubert 	 *    issuerNameHash          OCTET STRING,
152780fb4a2SCy Schubert 	 *    issuerKeyHash           OCTET STRING,
153780fb4a2SCy Schubert 	 *    serialNumber            CertificateSerialNumber }
154780fb4a2SCy Schubert 	 */
155780fb4a2SCy Schubert 
156780fb4a2SCy Schubert 	/* hashAlgorithm  AlgorithmIdentifier */
157780fb4a2SCy Schubert 	if (x509_parse_algorithm_identifier(pos, end - pos, &alg, &pos))
158780fb4a2SCy Schubert 		return -1;
159780fb4a2SCy Schubert 
160780fb4a2SCy Schubert 	/* issuerNameHash  OCTET STRING */
161780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
162*c1d255d3SCy Schubert 	    !asn1_is_octetstring(&hdr)) {
163*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
164*c1d255d3SCy Schubert 				"OCSP: Expected OCTET STRING (issuerNameHash)");
165780fb4a2SCy Schubert 		return -1;
166780fb4a2SCy Schubert 	}
167780fb4a2SCy Schubert 	name_hash = hdr.payload;
168780fb4a2SCy Schubert 	name_hash_len = hdr.length;
169780fb4a2SCy Schubert 	wpa_hexdump(MSG_DEBUG, "OCSP: issuerNameHash",
170780fb4a2SCy Schubert 		    name_hash, name_hash_len);
171780fb4a2SCy Schubert 	pos = hdr.payload + hdr.length;
172780fb4a2SCy Schubert 
173780fb4a2SCy Schubert 	wpa_hexdump(MSG_DEBUG, "OCSP: Issuer subject DN",
174780fb4a2SCy Schubert 		    issuer->subject_dn, issuer->subject_dn_len);
175780fb4a2SCy Schubert 	hash_len = ocsp_hash_data(&alg.oid, issuer->subject_dn,
176780fb4a2SCy Schubert 				  issuer->subject_dn_len, hash);
177780fb4a2SCy Schubert 	if (hash_len == 0 || name_hash_len != hash_len ||
178780fb4a2SCy Schubert 	    os_memcmp(name_hash, hash, hash_len) != 0) {
179780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: issuerNameHash mismatch");
180780fb4a2SCy Schubert 		wpa_hexdump(MSG_DEBUG, "OCSP: Calculated issuerNameHash",
181780fb4a2SCy Schubert 			    hash, hash_len);
182780fb4a2SCy Schubert 		return -1;
183780fb4a2SCy Schubert 	}
184780fb4a2SCy Schubert 
185780fb4a2SCy Schubert 	/* issuerKeyHash  OCTET STRING */
186780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
187*c1d255d3SCy Schubert 	    !asn1_is_octetstring(&hdr)) {
188*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
189*c1d255d3SCy Schubert 				"OCSP: Expected OCTET STRING (issuerKeyHash)");
190780fb4a2SCy Schubert 		return -1;
191780fb4a2SCy Schubert 	}
192780fb4a2SCy Schubert 	key_hash = hdr.payload;
193780fb4a2SCy Schubert 	key_hash_len = hdr.length;
194780fb4a2SCy Schubert 	wpa_hexdump(MSG_DEBUG, "OCSP: issuerKeyHash", key_hash, key_hash_len);
195780fb4a2SCy Schubert 	pos = hdr.payload + hdr.length;
196780fb4a2SCy Schubert 
197780fb4a2SCy Schubert 	hash_len = ocsp_hash_data(&alg.oid, issuer->public_key,
198780fb4a2SCy Schubert 				  issuer->public_key_len, hash);
199780fb4a2SCy Schubert 	if (hash_len == 0 || key_hash_len != hash_len ||
200780fb4a2SCy Schubert 	    os_memcmp(key_hash, hash, hash_len) != 0) {
201780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: issuerKeyHash mismatch");
202780fb4a2SCy Schubert 		wpa_hexdump(MSG_DEBUG, "OCSP: Calculated issuerKeyHash",
203780fb4a2SCy Schubert 			    hash, hash_len);
204780fb4a2SCy Schubert 		return -1;
205780fb4a2SCy Schubert 	}
206780fb4a2SCy Schubert 
207780fb4a2SCy Schubert 	/* serialNumber CertificateSerialNumber ::= INTEGER */
208780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
209*c1d255d3SCy Schubert 	    !asn1_is_integer(&hdr) ||
210780fb4a2SCy Schubert 	    hdr.length < 1 || hdr.length > X509_MAX_SERIAL_NUM_LEN) {
211*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
212*c1d255d3SCy Schubert 				"OCSP: No INTEGER tag found for serialNumber");
213780fb4a2SCy Schubert 		return -1;
214780fb4a2SCy Schubert 	}
215780fb4a2SCy Schubert 	serial_number = hdr.payload;
216780fb4a2SCy Schubert 	serial_number_len = hdr.length;
217780fb4a2SCy Schubert 	while (serial_number_len > 0 && serial_number[0] == 0) {
218780fb4a2SCy Schubert 		serial_number++;
219780fb4a2SCy Schubert 		serial_number_len--;
220780fb4a2SCy Schubert 	}
221780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "OCSP: serialNumber", serial_number,
222780fb4a2SCy Schubert 		    serial_number_len);
223780fb4a2SCy Schubert 
224780fb4a2SCy Schubert 	if (serial_number_len != cert->serial_number_len ||
225780fb4a2SCy Schubert 	    os_memcmp(serial_number, cert->serial_number,
226780fb4a2SCy Schubert 		      serial_number_len) != 0) {
227780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: serialNumber mismatch");
228780fb4a2SCy Schubert 		return -1;
229780fb4a2SCy Schubert 	}
230780fb4a2SCy Schubert 
231780fb4a2SCy Schubert 	pos = end;
232780fb4a2SCy Schubert 	end = resp + len;
233780fb4a2SCy Schubert 
234*c1d255d3SCy Schubert 	/* certStatus CertStatus ::= CHOICE
235*c1d255d3SCy Schubert 	 *
236*c1d255d3SCy Schubert 	 * CertStatus ::= CHOICE {
237*c1d255d3SCy Schubert 	 *     good        [0]     IMPLICIT NULL,
238*c1d255d3SCy Schubert 	 *     revoked     [1]     IMPLICIT RevokedInfo,
239*c1d255d3SCy Schubert 	 *     unknown     [2]     IMPLICIT UnknownInfo }
240*c1d255d3SCy Schubert 	 */
241780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
242780fb4a2SCy Schubert 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
243*c1d255d3SCy Schubert 		asn1_unexpected(&hdr, "OCSP: Expected CHOICE (CertStatus)");
244780fb4a2SCy Schubert 		return -1;
245780fb4a2SCy Schubert 	}
246780fb4a2SCy Schubert 	cert_status = hdr.tag;
247780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "OCSP: certStatus=%u", cert_status);
248780fb4a2SCy Schubert 	wpa_hexdump(MSG_DEBUG, "OCSP: CertStatus additional data",
249780fb4a2SCy Schubert 		    hdr.payload, hdr.length);
250780fb4a2SCy Schubert 	pos = hdr.payload + hdr.length;
251780fb4a2SCy Schubert 
252780fb4a2SCy Schubert 	os_get_time(&now);
253780fb4a2SCy Schubert 	/* thisUpdate  GeneralizedTime */
254780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
255*c1d255d3SCy Schubert 	    !asn1_is_generalizedtime(&hdr) ||
256780fb4a2SCy Schubert 	    x509_parse_time(hdr.payload, hdr.length, hdr.tag, &update) < 0) {
257780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: Failed to parse thisUpdate");
258780fb4a2SCy Schubert 		return -1;
259780fb4a2SCy Schubert 	}
260780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "OCSP: thisUpdate %lu", (unsigned long) update);
261780fb4a2SCy Schubert 	pos = hdr.payload + hdr.length;
262780fb4a2SCy Schubert 	if ((unsigned long) now.sec < (unsigned long) update) {
263780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
264780fb4a2SCy Schubert 			   "OCSP: thisUpdate time in the future (response not yet valid)");
265780fb4a2SCy Schubert 		return -1;
266780fb4a2SCy Schubert 	}
267780fb4a2SCy Schubert 
268780fb4a2SCy Schubert 	/* nextUpdate  [0]  EXPLICIT GeneralizedTime OPTIONAL */
269780fb4a2SCy Schubert 	if (pos < end) {
270780fb4a2SCy Schubert 		if (asn1_get_next(pos, end - pos, &hdr) < 0)
271780fb4a2SCy Schubert 			return -1;
272*c1d255d3SCy Schubert 		if (asn1_is_cs_tag(&hdr, 0) && hdr.constructed) {
273780fb4a2SCy Schubert 			const u8 *next = hdr.payload + hdr.length;
274780fb4a2SCy Schubert 
275780fb4a2SCy Schubert 			if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
276*c1d255d3SCy Schubert 			    !asn1_is_generalizedtime(&hdr) ||
277780fb4a2SCy Schubert 			    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
278780fb4a2SCy Schubert 					    &update) < 0) {
279780fb4a2SCy Schubert 				wpa_printf(MSG_DEBUG,
280780fb4a2SCy Schubert 					   "OCSP: Failed to parse nextUpdate");
281780fb4a2SCy Schubert 				return -1;
282780fb4a2SCy Schubert 			}
283780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG, "OCSP: nextUpdate %lu",
284780fb4a2SCy Schubert 				   (unsigned long) update);
285780fb4a2SCy Schubert 			pos = next;
286780fb4a2SCy Schubert 			if ((unsigned long) now.sec > (unsigned long) update) {
287780fb4a2SCy Schubert 				wpa_printf(MSG_DEBUG, "OCSP: nextUpdate time in the past (response has expired)");
288780fb4a2SCy Schubert 				return -1;
289780fb4a2SCy Schubert 			}
290780fb4a2SCy Schubert 		}
291780fb4a2SCy Schubert 	}
292780fb4a2SCy Schubert 
293780fb4a2SCy Schubert 	/* singleExtensions  [1]  EXPLICIT Extensions OPTIONAL */
294780fb4a2SCy Schubert 	if (pos < end) {
295780fb4a2SCy Schubert 		wpa_hexdump(MSG_MSGDUMP, "OCSP: singleExtensions",
296780fb4a2SCy Schubert 			    pos, end - pos);
297780fb4a2SCy Schubert 		/* Ignore for now */
298780fb4a2SCy Schubert 	}
299780fb4a2SCy Schubert 
300780fb4a2SCy Schubert 	if (cert_status == 0 /* good */)
301780fb4a2SCy Schubert 		*res = TLS_OCSP_GOOD;
302780fb4a2SCy Schubert 	else if (cert_status == 1 /* revoked */)
303780fb4a2SCy Schubert 		*res = TLS_OCSP_REVOKED;
304780fb4a2SCy Schubert 	else
305780fb4a2SCy Schubert 		return -1;
306780fb4a2SCy Schubert 	return 0;
307780fb4a2SCy Schubert }
308780fb4a2SCy Schubert 
309780fb4a2SCy Schubert 
310780fb4a2SCy Schubert static enum tls_ocsp_result
tls_process_ocsp_responses(struct tlsv1_client * conn,struct x509_certificate * cert,struct x509_certificate * issuer,const u8 * resp,size_t len)311780fb4a2SCy Schubert tls_process_ocsp_responses(struct tlsv1_client *conn,
312780fb4a2SCy Schubert 			   struct x509_certificate *cert,
313780fb4a2SCy Schubert 			   struct x509_certificate *issuer, const u8 *resp,
314780fb4a2SCy Schubert 			   size_t len)
315780fb4a2SCy Schubert {
316780fb4a2SCy Schubert 	struct asn1_hdr hdr;
317780fb4a2SCy Schubert 	const u8 *pos, *end;
318780fb4a2SCy Schubert 	enum tls_ocsp_result res;
319780fb4a2SCy Schubert 
320780fb4a2SCy Schubert 	pos = resp;
321780fb4a2SCy Schubert 	end = resp + len;
322780fb4a2SCy Schubert 	while (pos < end) {
323780fb4a2SCy Schubert 		/* SingleResponse ::= SEQUENCE */
324780fb4a2SCy Schubert 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
325*c1d255d3SCy Schubert 		    !asn1_is_sequence(&hdr)) {
326*c1d255d3SCy Schubert 			asn1_unexpected(&hdr,
327*c1d255d3SCy Schubert 					"OCSP: Expected SEQUENCE (SingleResponse)");
328780fb4a2SCy Schubert 			return TLS_OCSP_INVALID;
329780fb4a2SCy Schubert 		}
330780fb4a2SCy Schubert 		if (tls_process_ocsp_single_response(conn, cert, issuer,
331780fb4a2SCy Schubert 						     hdr.payload, hdr.length,
332780fb4a2SCy Schubert 						     &res) == 0)
333780fb4a2SCy Schubert 			return res;
334780fb4a2SCy Schubert 		pos = hdr.payload + hdr.length;
335780fb4a2SCy Schubert 	}
336780fb4a2SCy Schubert 
337780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG,
338780fb4a2SCy Schubert 		   "OCSP: Did not find a response matching the server certificate");
339780fb4a2SCy Schubert 	return TLS_OCSP_NO_RESPONSE;
340780fb4a2SCy Schubert }
341780fb4a2SCy Schubert 
342780fb4a2SCy Schubert 
343780fb4a2SCy Schubert static enum tls_ocsp_result
tls_process_basic_ocsp_response(struct tlsv1_client * conn,struct x509_certificate * srv_cert,const u8 * resp,size_t len)344780fb4a2SCy Schubert tls_process_basic_ocsp_response(struct tlsv1_client *conn,
345780fb4a2SCy Schubert 				struct x509_certificate *srv_cert,
346780fb4a2SCy Schubert 				const u8 *resp, size_t len)
347780fb4a2SCy Schubert {
348780fb4a2SCy Schubert 	struct asn1_hdr hdr;
349780fb4a2SCy Schubert 	const u8 *pos, *end;
350780fb4a2SCy Schubert 	const u8 *resp_data, *sign_value, *key_hash = NULL, *responses;
351780fb4a2SCy Schubert 	const u8 *resp_data_signed;
352780fb4a2SCy Schubert 	size_t resp_data_len, sign_value_len, responses_len;
353780fb4a2SCy Schubert 	size_t resp_data_signed_len;
354780fb4a2SCy Schubert 	struct x509_algorithm_identifier alg;
355780fb4a2SCy Schubert 	struct x509_certificate *certs = NULL, *last_cert = NULL;
356780fb4a2SCy Schubert 	struct x509_certificate *issuer, *signer;
357780fb4a2SCy Schubert 	struct x509_name name; /* used if key_hash == NULL */
358780fb4a2SCy Schubert 	char buf[100];
359780fb4a2SCy Schubert 	os_time_t produced_at;
360780fb4a2SCy Schubert 	enum tls_ocsp_result res;
361780fb4a2SCy Schubert 
362780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "OCSP: BasicOCSPResponse", resp, len);
363780fb4a2SCy Schubert 
364780fb4a2SCy Schubert 	os_memset(&name, 0, sizeof(name));
365780fb4a2SCy Schubert 
366780fb4a2SCy Schubert 	/*
367780fb4a2SCy Schubert 	 * RFC 6960, 4.2.1:
368780fb4a2SCy Schubert 	 * BasicOCSPResponse       ::= SEQUENCE {
369780fb4a2SCy Schubert 	 *    tbsResponseData      ResponseData,
370780fb4a2SCy Schubert 	 *    signatureAlgorithm   AlgorithmIdentifier,
371780fb4a2SCy Schubert 	 *    signature            BIT STRING,
372780fb4a2SCy Schubert 	 *    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
373780fb4a2SCy Schubert 	 */
374780fb4a2SCy Schubert 
375*c1d255d3SCy Schubert 	if (asn1_get_next(resp, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
376*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
377*c1d255d3SCy Schubert 				"OCSP: Expected SEQUENCE (BasicOCSPResponse)");
378780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
379780fb4a2SCy Schubert 	}
380780fb4a2SCy Schubert 	pos = hdr.payload;
381780fb4a2SCy Schubert 	end = hdr.payload + hdr.length;
382780fb4a2SCy Schubert 
383780fb4a2SCy Schubert 	/* ResponseData ::= SEQUENCE */
384780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
385*c1d255d3SCy Schubert 	    !asn1_is_sequence(&hdr)) {
386*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
387*c1d255d3SCy Schubert 				"OCSP: Expected SEQUENCE (ResponseData)");
388780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
389780fb4a2SCy Schubert 	}
390780fb4a2SCy Schubert 	resp_data = hdr.payload;
391780fb4a2SCy Schubert 	resp_data_len = hdr.length;
392780fb4a2SCy Schubert 	resp_data_signed = pos;
393780fb4a2SCy Schubert 	pos = hdr.payload + hdr.length;
394780fb4a2SCy Schubert 	resp_data_signed_len = pos - resp_data_signed;
395780fb4a2SCy Schubert 
396780fb4a2SCy Schubert 	/* signatureAlgorithm  AlgorithmIdentifier */
397780fb4a2SCy Schubert 	if (x509_parse_algorithm_identifier(pos, end - pos, &alg, &pos))
398780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
399780fb4a2SCy Schubert 
400780fb4a2SCy Schubert 	/* signature  BIT STRING */
401780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
402*c1d255d3SCy Schubert 	    !asn1_is_bitstring(&hdr)) {
403*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
404*c1d255d3SCy Schubert 				"OCSP: Expected BITSTRING (signature)");
405780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
406780fb4a2SCy Schubert 	}
407780fb4a2SCy Schubert 	if (hdr.length < 1)
408780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
409780fb4a2SCy Schubert 	pos = hdr.payload;
410780fb4a2SCy Schubert 	if (*pos) {
411780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: BITSTRING - %d unused bits", *pos);
412780fb4a2SCy Schubert 		/* PKCS #1 v1.5 10.2.1:
413780fb4a2SCy Schubert 		 * It is an error if the length in bits of the signature S is
414780fb4a2SCy Schubert 		 * not a multiple of eight.
415780fb4a2SCy Schubert 		 */
416780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
417780fb4a2SCy Schubert 	}
418780fb4a2SCy Schubert 	sign_value = pos + 1;
419780fb4a2SCy Schubert 	sign_value_len = hdr.length - 1;
420780fb4a2SCy Schubert 	pos += hdr.length;
421780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "OCSP: signature", sign_value, sign_value_len);
422780fb4a2SCy Schubert 
423780fb4a2SCy Schubert 	/* certs  [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL */
424780fb4a2SCy Schubert 	if (pos < end) {
425780fb4a2SCy Schubert 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
426*c1d255d3SCy Schubert 		    !hdr.constructed || !asn1_is_cs_tag(&hdr, 0)) {
427*c1d255d3SCy Schubert 			asn1_unexpected(&hdr,
428*c1d255d3SCy Schubert 					"OCSP: Expected [0] EXPLICIT (certs)");
429780fb4a2SCy Schubert 			return TLS_OCSP_INVALID;
430780fb4a2SCy Schubert 		}
431780fb4a2SCy Schubert 		wpa_hexdump(MSG_MSGDUMP, "OCSP: certs",
432780fb4a2SCy Schubert 			    hdr.payload, hdr.length);
433780fb4a2SCy Schubert 		pos = hdr.payload;
434780fb4a2SCy Schubert 		end = hdr.payload + hdr.length;
435780fb4a2SCy Schubert 		while (pos < end) {
436780fb4a2SCy Schubert 			struct x509_certificate *cert;
437780fb4a2SCy Schubert 
438780fb4a2SCy Schubert 			if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
439*c1d255d3SCy Schubert 			    !asn1_is_sequence(&hdr)) {
440*c1d255d3SCy Schubert 				asn1_unexpected(&hdr,
441*c1d255d3SCy Schubert 						"OCSP: Expected SEQUENCE (Certificate)");
442780fb4a2SCy Schubert 				goto fail;
443780fb4a2SCy Schubert 			}
444780fb4a2SCy Schubert 
445780fb4a2SCy Schubert 			cert = x509_certificate_parse(hdr.payload, hdr.length);
446780fb4a2SCy Schubert 			if (!cert)
447780fb4a2SCy Schubert 				goto fail;
448780fb4a2SCy Schubert 			if (last_cert) {
449780fb4a2SCy Schubert 				last_cert->next = cert;
450780fb4a2SCy Schubert 				last_cert = cert;
451780fb4a2SCy Schubert 			} else {
452780fb4a2SCy Schubert 				last_cert = certs = cert;
453780fb4a2SCy Schubert 			}
454780fb4a2SCy Schubert 			pos = hdr.payload + hdr.length;
455780fb4a2SCy Schubert 		}
456780fb4a2SCy Schubert 	}
457780fb4a2SCy Schubert 
458780fb4a2SCy Schubert 	/*
459780fb4a2SCy Schubert 	 * ResponseData ::= SEQUENCE {
460780fb4a2SCy Schubert 	 *    version              [0] EXPLICIT Version DEFAULT v1,
461780fb4a2SCy Schubert 	 *    responderID              ResponderID,
462780fb4a2SCy Schubert 	 *    producedAt               GeneralizedTime,
463780fb4a2SCy Schubert 	 *    responses                SEQUENCE OF SingleResponse,
464780fb4a2SCy Schubert 	 *    responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
465780fb4a2SCy Schubert 	 */
466780fb4a2SCy Schubert 	pos = resp_data;
467780fb4a2SCy Schubert 	end = resp_data + resp_data_len;
468780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "OCSP: ResponseData", pos, end - pos);
469780fb4a2SCy Schubert 
470780fb4a2SCy Schubert 	/*
471780fb4a2SCy Schubert 	 * version [0] EXPLICIT Version DEFAULT v1
472780fb4a2SCy Schubert 	 * Version ::= INTEGER { v1(0) }
473780fb4a2SCy Schubert 	 */
474*c1d255d3SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) == 0 && hdr.constructed &&
475*c1d255d3SCy Schubert 	    asn1_is_cs_tag(&hdr, 0)) {
476780fb4a2SCy Schubert 		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
477*c1d255d3SCy Schubert 		    !asn1_is_integer(&hdr) || hdr.length != 1) {
478*c1d255d3SCy Schubert 			asn1_unexpected(&hdr,
479*c1d255d3SCy Schubert 					"OCSP: No INTEGER (len=1) tag found for version field");
480780fb4a2SCy Schubert 			goto fail;
481780fb4a2SCy Schubert 		}
482780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: ResponseData version %u",
483780fb4a2SCy Schubert 			   hdr.payload[0]);
484780fb4a2SCy Schubert 		if (hdr.payload[0] != 0) {
485780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
486780fb4a2SCy Schubert 				   "OCSP: Unsupported ResponseData version %u",
487780fb4a2SCy Schubert 				   hdr.payload[0]);
488780fb4a2SCy Schubert 			goto no_resp;
489780fb4a2SCy Schubert 		}
490780fb4a2SCy Schubert 		pos = hdr.payload + hdr.length;
491780fb4a2SCy Schubert 	} else {
492780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
493780fb4a2SCy Schubert 			   "OCSP: Default ResponseData version (v1)");
494780fb4a2SCy Schubert 	}
495780fb4a2SCy Schubert 
496780fb4a2SCy Schubert 	/*
497780fb4a2SCy Schubert 	 * ResponderID ::= CHOICE {
498780fb4a2SCy Schubert 	 *    byName              [1] Name,
499780fb4a2SCy Schubert 	 *    byKey               [2] KeyHash }
500780fb4a2SCy Schubert 	 */
501780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
502780fb4a2SCy Schubert 	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
503*c1d255d3SCy Schubert 		asn1_unexpected(&hdr, "OCSP: Expected CHOICE (ResponderID)");
504780fb4a2SCy Schubert 		goto fail;
505780fb4a2SCy Schubert 	}
506780fb4a2SCy Schubert 
507780fb4a2SCy Schubert 	if (hdr.tag == 1) {
508780fb4a2SCy Schubert 		/* Name */
509780fb4a2SCy Schubert 		if (x509_parse_name(hdr.payload, hdr.length, &name, &pos) < 0)
510780fb4a2SCy Schubert 			goto fail;
511780fb4a2SCy Schubert 		x509_name_string(&name, buf, sizeof(buf));
512780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: ResponderID byName Name: %s", buf);
513780fb4a2SCy Schubert 	} else if (hdr.tag == 2) {
514780fb4a2SCy Schubert 		/* KeyHash ::= OCTET STRING */
515780fb4a2SCy Schubert 		if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
516*c1d255d3SCy Schubert 		    !asn1_is_octetstring(&hdr)) {
517*c1d255d3SCy Schubert 			asn1_unexpected(&hdr,
518*c1d255d3SCy Schubert 					"OCSP: Expected OCTET STRING (KeyHash)");
519780fb4a2SCy Schubert 			goto fail;
520780fb4a2SCy Schubert 		}
521780fb4a2SCy Schubert 		key_hash = hdr.payload;
522780fb4a2SCy Schubert 		wpa_hexdump(MSG_DEBUG, "OCSP: ResponderID byKey KeyHash",
523780fb4a2SCy Schubert 			    key_hash, hdr.length);
524780fb4a2SCy Schubert 		if (hdr.length != SHA1_MAC_LEN) {
525780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
526780fb4a2SCy Schubert 				   "OCSP: Unexpected byKey KeyHash length %u - expected %u for SHA-1",
527780fb4a2SCy Schubert 				   hdr.length, SHA1_MAC_LEN);
528780fb4a2SCy Schubert 			goto fail;
529780fb4a2SCy Schubert 		}
530780fb4a2SCy Schubert 		pos = hdr.payload + hdr.length;
531780fb4a2SCy Schubert 	} else {
532780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: Unexpected ResponderID CHOICE %u",
533780fb4a2SCy Schubert 			   hdr.tag);
534780fb4a2SCy Schubert 		goto fail;
535780fb4a2SCy Schubert 	}
536780fb4a2SCy Schubert 
537780fb4a2SCy Schubert 	/* producedAt  GeneralizedTime */
538780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
539*c1d255d3SCy Schubert 	    !asn1_is_generalizedtime(&hdr) ||
540780fb4a2SCy Schubert 	    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
541780fb4a2SCy Schubert 			    &produced_at) < 0) {
542780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: Failed to parse producedAt");
543780fb4a2SCy Schubert 		goto fail;
544780fb4a2SCy Schubert 	}
545780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "OCSP: producedAt %lu",
546780fb4a2SCy Schubert 		   (unsigned long) produced_at);
547780fb4a2SCy Schubert 	pos = hdr.payload + hdr.length;
548780fb4a2SCy Schubert 
549780fb4a2SCy Schubert 	/* responses  SEQUENCE OF SingleResponse */
550780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
551*c1d255d3SCy Schubert 	    !asn1_is_sequence(&hdr)) {
552*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
553*c1d255d3SCy Schubert 				"OCSP: Expected SEQUENCE (responses)");
554780fb4a2SCy Schubert 		goto fail;
555780fb4a2SCy Schubert 	}
556780fb4a2SCy Schubert 	responses = hdr.payload;
557780fb4a2SCy Schubert 	responses_len = hdr.length;
558780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "OCSP: responses", responses, responses_len);
559780fb4a2SCy Schubert 	pos = hdr.payload + hdr.length;
560780fb4a2SCy Schubert 
561780fb4a2SCy Schubert 	if (pos < end) {
562780fb4a2SCy Schubert 		/* responseExtensions  [1] EXPLICIT Extensions OPTIONAL */
563780fb4a2SCy Schubert 		wpa_hexdump(MSG_MSGDUMP, "OCSP: responseExtensions",
564780fb4a2SCy Schubert 			    pos, end - pos);
565780fb4a2SCy Schubert 		/* Ignore for now. */
566780fb4a2SCy Schubert 	}
567780fb4a2SCy Schubert 
568780fb4a2SCy Schubert 	if (!srv_cert) {
569780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
570780fb4a2SCy Schubert 			   "OCSP: Server certificate not known - cannot check OCSP response");
571780fb4a2SCy Schubert 		goto no_resp;
572780fb4a2SCy Schubert 	}
573780fb4a2SCy Schubert 
574780fb4a2SCy Schubert 	if (srv_cert->next) {
575780fb4a2SCy Schubert 		/* Issuer has already been verified in the chain */
576780fb4a2SCy Schubert 		issuer = srv_cert->next;
577780fb4a2SCy Schubert 	} else {
578780fb4a2SCy Schubert 		/* Find issuer from the set of trusted certificates */
579780fb4a2SCy Schubert 		for (issuer = conn->cred ? conn->cred->trusted_certs : NULL;
580780fb4a2SCy Schubert 		     issuer; issuer = issuer->next) {
581780fb4a2SCy Schubert 			if (x509_name_compare(&srv_cert->issuer,
582780fb4a2SCy Schubert 					      &issuer->subject) == 0)
583780fb4a2SCy Schubert 				break;
584780fb4a2SCy Schubert 		}
585780fb4a2SCy Schubert 	}
586780fb4a2SCy Schubert 	if (!issuer) {
587780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
588780fb4a2SCy Schubert 			   "OCSP: Server certificate issuer not known - cannot check OCSP response");
589780fb4a2SCy Schubert 		goto no_resp;
590780fb4a2SCy Schubert 	}
591780fb4a2SCy Schubert 
592780fb4a2SCy Schubert 	if (ocsp_responder_id_match(issuer, &name, key_hash)) {
593780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
594780fb4a2SCy Schubert 			   "OCSP: Server certificate issuer certificate matches ResponderID");
595780fb4a2SCy Schubert 		signer = issuer;
596780fb4a2SCy Schubert 	} else {
597780fb4a2SCy Schubert 		for (signer = certs; signer; signer = signer->next) {
598780fb4a2SCy Schubert 			if (!ocsp_responder_id_match(signer, &name, key_hash) ||
599780fb4a2SCy Schubert 			    x509_name_compare(&srv_cert->issuer,
600780fb4a2SCy Schubert 					      &issuer->subject) != 0 ||
601780fb4a2SCy Schubert 			    !(signer->ext_key_usage &
602780fb4a2SCy Schubert 			      X509_EXT_KEY_USAGE_OCSP) ||
603780fb4a2SCy Schubert 			    x509_certificate_check_signature(issuer, signer) <
604780fb4a2SCy Schubert 			    0)
605780fb4a2SCy Schubert 				continue;
606780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
607780fb4a2SCy Schubert 				   "OCSP: An extra certificate from the response matches ResponderID and is trusted as an OCSP signer");
608780fb4a2SCy Schubert 			break;
609780fb4a2SCy Schubert 		}
610780fb4a2SCy Schubert 		if (!signer) {
611780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
612780fb4a2SCy Schubert 				   "OCSP: Could not find OCSP signer certificate");
613780fb4a2SCy Schubert 			goto no_resp;
614780fb4a2SCy Schubert 		}
615780fb4a2SCy Schubert 	}
616780fb4a2SCy Schubert 
617780fb4a2SCy Schubert 	x509_free_name(&name);
618780fb4a2SCy Schubert 	os_memset(&name, 0, sizeof(name));
619780fb4a2SCy Schubert 	x509_certificate_chain_free(certs);
620780fb4a2SCy Schubert 	certs = NULL;
621780fb4a2SCy Schubert 
622780fb4a2SCy Schubert 	if (x509_check_signature(signer, &alg, sign_value, sign_value_len,
623780fb4a2SCy Schubert 				 resp_data_signed, resp_data_signed_len) < 0) {
624780fb4a2SCy Schubert 		    wpa_printf(MSG_DEBUG, "OCSP: Invalid signature");
625780fb4a2SCy Schubert 		    return TLS_OCSP_INVALID;
626780fb4a2SCy Schubert 	}
627780fb4a2SCy Schubert 
628780fb4a2SCy Schubert 	res = tls_process_ocsp_responses(conn, srv_cert, issuer,
629780fb4a2SCy Schubert 					 responses, responses_len);
630780fb4a2SCy Schubert 	if (res == TLS_OCSP_REVOKED)
631780fb4a2SCy Schubert 		srv_cert->ocsp_revoked = 1;
632780fb4a2SCy Schubert 	else if (res == TLS_OCSP_GOOD)
633780fb4a2SCy Schubert 		srv_cert->ocsp_good = 1;
634780fb4a2SCy Schubert 	return res;
635780fb4a2SCy Schubert 
636780fb4a2SCy Schubert no_resp:
637780fb4a2SCy Schubert 	x509_free_name(&name);
638780fb4a2SCy Schubert 	x509_certificate_chain_free(certs);
639780fb4a2SCy Schubert 	return TLS_OCSP_NO_RESPONSE;
640780fb4a2SCy Schubert 
641780fb4a2SCy Schubert fail:
642780fb4a2SCy Schubert 	x509_free_name(&name);
643780fb4a2SCy Schubert 	x509_certificate_chain_free(certs);
644780fb4a2SCy Schubert 	return TLS_OCSP_INVALID;
645780fb4a2SCy Schubert }
646780fb4a2SCy Schubert 
647780fb4a2SCy Schubert 
tls_process_ocsp_response(struct tlsv1_client * conn,const u8 * resp,size_t len)648780fb4a2SCy Schubert enum tls_ocsp_result tls_process_ocsp_response(struct tlsv1_client *conn,
649780fb4a2SCy Schubert 					       const u8 *resp, size_t len)
650780fb4a2SCy Schubert {
651780fb4a2SCy Schubert 	struct asn1_hdr hdr;
652780fb4a2SCy Schubert 	const u8 *pos, *end;
653780fb4a2SCy Schubert 	u8 resp_status;
654780fb4a2SCy Schubert 	struct asn1_oid oid;
655780fb4a2SCy Schubert 	char obuf[80];
656780fb4a2SCy Schubert 	struct x509_certificate *cert;
657780fb4a2SCy Schubert 	enum tls_ocsp_result res = TLS_OCSP_NO_RESPONSE;
658780fb4a2SCy Schubert 	enum tls_ocsp_result res_first = res;
659780fb4a2SCy Schubert 
660780fb4a2SCy Schubert 	wpa_hexdump(MSG_MSGDUMP, "TLSv1: OCSPResponse", resp, len);
661780fb4a2SCy Schubert 
662780fb4a2SCy Schubert 	/*
663780fb4a2SCy Schubert 	 * RFC 6960, 4.2.1:
664780fb4a2SCy Schubert 	 * OCSPResponse ::= SEQUENCE {
665780fb4a2SCy Schubert 	 *    responseStatus  OCSPResponseStatus,
666780fb4a2SCy Schubert 	 *    responseBytes   [0] EXPLICIT ResponseBytes OPTIONAL }
667780fb4a2SCy Schubert 	 */
668780fb4a2SCy Schubert 
669*c1d255d3SCy Schubert 	if (asn1_get_next(resp, len, &hdr) < 0 || !asn1_is_sequence(&hdr)) {
670*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
671*c1d255d3SCy Schubert 				"OCSP: Expected SEQUENCE (OCSPResponse)");
672780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
673780fb4a2SCy Schubert 	}
674780fb4a2SCy Schubert 	pos = hdr.payload;
675780fb4a2SCy Schubert 	end = hdr.payload + hdr.length;
676780fb4a2SCy Schubert 
677780fb4a2SCy Schubert 	/* OCSPResponseStatus ::= ENUMERATED */
678780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
679*c1d255d3SCy Schubert 	    !asn1_is_enumerated(&hdr) || hdr.length != 1) {
680*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
681*c1d255d3SCy Schubert 				"OCSP: Expected ENUMERATED (responseStatus)");
682780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
683780fb4a2SCy Schubert 	}
684780fb4a2SCy Schubert 	resp_status = hdr.payload[0];
685780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "OCSP: responseStatus %u", resp_status);
686780fb4a2SCy Schubert 	pos = hdr.payload + hdr.length;
687780fb4a2SCy Schubert 	if (resp_status != OCSP_RESP_STATUS_SUCCESSFUL) {
688780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: No stapling result");
689780fb4a2SCy Schubert 		return TLS_OCSP_NO_RESPONSE;
690780fb4a2SCy Schubert 	}
691780fb4a2SCy Schubert 
692780fb4a2SCy Schubert 	/* responseBytes   [0] EXPLICIT ResponseBytes OPTIONAL */
693780fb4a2SCy Schubert 	if (pos == end)
694780fb4a2SCy Schubert 		return TLS_OCSP_NO_RESPONSE;
695780fb4a2SCy Schubert 
696*c1d255d3SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 || !hdr.constructed ||
697*c1d255d3SCy Schubert 	    !asn1_is_cs_tag(&hdr, 0)) {
698*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
699*c1d255d3SCy Schubert 				"OCSP: Expected [0] EXPLICIT (responseBytes)");
700780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
701780fb4a2SCy Schubert 	}
702780fb4a2SCy Schubert 
703780fb4a2SCy Schubert 	/*
704780fb4a2SCy Schubert 	 * ResponseBytes ::= SEQUENCE {
705780fb4a2SCy Schubert 	 *     responseType   OBJECT IDENTIFIER,
706780fb4a2SCy Schubert 	 *     response       OCTET STRING }
707780fb4a2SCy Schubert 	 */
708780fb4a2SCy Schubert 
709780fb4a2SCy Schubert 	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
710*c1d255d3SCy Schubert 	    !asn1_is_sequence(&hdr)) {
711*c1d255d3SCy Schubert 		asn1_unexpected(&hdr,
712*c1d255d3SCy Schubert 				"OCSP: Expected SEQUENCE (ResponseBytes)");
713780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
714780fb4a2SCy Schubert 	}
715780fb4a2SCy Schubert 	pos = hdr.payload;
716780fb4a2SCy Schubert 	end = hdr.payload + hdr.length;
717780fb4a2SCy Schubert 
718780fb4a2SCy Schubert 	/* responseType   OBJECT IDENTIFIER */
719780fb4a2SCy Schubert 	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
720780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
721780fb4a2SCy Schubert 			   "OCSP: Failed to parse OID (responseType)");
722780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
723780fb4a2SCy Schubert 	}
724780fb4a2SCy Schubert 	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
725780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "OCSP: responseType %s", obuf);
726780fb4a2SCy Schubert 	if (!is_oid_basic_ocsp_resp(&oid)) {
727780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OCSP: Ignore unsupported response type");
728780fb4a2SCy Schubert 		return TLS_OCSP_NO_RESPONSE;
729780fb4a2SCy Schubert 	}
730780fb4a2SCy Schubert 
731780fb4a2SCy Schubert 	/* response       OCTET STRING */
732780fb4a2SCy Schubert 	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
733*c1d255d3SCy Schubert 	    !asn1_is_octetstring(&hdr)) {
734*c1d255d3SCy Schubert 		asn1_unexpected(&hdr, "OCSP: Expected OCTET STRING (response)");
735780fb4a2SCy Schubert 		return TLS_OCSP_INVALID;
736780fb4a2SCy Schubert 	}
737780fb4a2SCy Schubert 
738780fb4a2SCy Schubert 	cert = conn->server_cert;
739780fb4a2SCy Schubert 	while (cert) {
740780fb4a2SCy Schubert 		if (!cert->ocsp_good && !cert->ocsp_revoked) {
741780fb4a2SCy Schubert 			char sbuf[128];
742780fb4a2SCy Schubert 
743780fb4a2SCy Schubert 			x509_name_string(&cert->subject, sbuf, sizeof(sbuf));
744780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
745780fb4a2SCy Schubert 				   "OCSP: Trying to find certificate status for %s",
746780fb4a2SCy Schubert 				   sbuf);
747780fb4a2SCy Schubert 
748780fb4a2SCy Schubert 			res = tls_process_basic_ocsp_response(conn, cert,
749780fb4a2SCy Schubert 							      hdr.payload,
750780fb4a2SCy Schubert 							      hdr.length);
751780fb4a2SCy Schubert 			if (cert == conn->server_cert)
752780fb4a2SCy Schubert 				res_first = res;
753780fb4a2SCy Schubert 		}
754780fb4a2SCy Schubert 		if (res == TLS_OCSP_REVOKED || cert->issuer_trusted)
755780fb4a2SCy Schubert 			break;
756780fb4a2SCy Schubert 		cert = cert->next;
757780fb4a2SCy Schubert 	}
758780fb4a2SCy Schubert 	return res == TLS_OCSP_REVOKED ? res : res_first;
759780fb4a2SCy Schubert }
760