xref: /freebsd/contrib/wpa/src/crypto/tls_openssl_ocsp.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
1780fb4a2SCy Schubert /*
2780fb4a2SCy Schubert  * SSL/TLS interface functions for OpenSSL - BoringSSL OCSP
3780fb4a2SCy Schubert  * Copyright (c) 2004-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 <openssl/ssl.h>
12780fb4a2SCy Schubert #include <openssl/err.h>
13780fb4a2SCy Schubert #include <openssl/x509v3.h>
14780fb4a2SCy Schubert #ifdef OPENSSL_IS_BORINGSSL
15780fb4a2SCy Schubert #include <openssl/asn1.h>
16780fb4a2SCy Schubert #include <openssl/asn1t.h>
17780fb4a2SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
18780fb4a2SCy Schubert 
19780fb4a2SCy Schubert #include "common.h"
20780fb4a2SCy Schubert #include "tls_openssl.h"
21780fb4a2SCy Schubert 
22780fb4a2SCy Schubert 
23780fb4a2SCy Schubert #ifdef OPENSSL_IS_BORINGSSL
24780fb4a2SCy Schubert 
tls_show_errors(int level,const char * func,const char * txt)25780fb4a2SCy Schubert static void tls_show_errors(int level, const char *func, const char *txt)
26780fb4a2SCy Schubert {
27780fb4a2SCy Schubert 	unsigned long err;
28780fb4a2SCy Schubert 
29780fb4a2SCy Schubert 	wpa_printf(level, "OpenSSL: %s - %s %s",
30780fb4a2SCy Schubert 		   func, txt, ERR_error_string(ERR_get_error(), NULL));
31780fb4a2SCy Schubert 
32780fb4a2SCy Schubert 	while ((err = ERR_get_error())) {
33780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "OpenSSL: pending error: %s",
34780fb4a2SCy Schubert 			   ERR_error_string(err, NULL));
35780fb4a2SCy Schubert 	}
36780fb4a2SCy Schubert }
37780fb4a2SCy Schubert 
38780fb4a2SCy Schubert 
39780fb4a2SCy Schubert /*
40780fb4a2SCy Schubert  * CertID ::= SEQUENCE {
41780fb4a2SCy Schubert  *     hashAlgorithm      AlgorithmIdentifier,
42780fb4a2SCy Schubert  *     issuerNameHash     OCTET STRING, -- Hash of Issuer's DN
43780fb4a2SCy Schubert  *     issuerKeyHash      OCTET STRING, -- Hash of Issuer's public key
44780fb4a2SCy Schubert  *     serialNumber       CertificateSerialNumber }
45780fb4a2SCy Schubert  */
46780fb4a2SCy Schubert typedef struct {
47780fb4a2SCy Schubert 	X509_ALGOR *hashAlgorithm;
48780fb4a2SCy Schubert 	ASN1_OCTET_STRING *issuerNameHash;
49780fb4a2SCy Schubert 	ASN1_OCTET_STRING *issuerKeyHash;
50780fb4a2SCy Schubert 	ASN1_INTEGER *serialNumber;
51780fb4a2SCy Schubert } CertID;
52780fb4a2SCy Schubert 
53780fb4a2SCy Schubert /*
54780fb4a2SCy Schubert  * ResponseBytes ::=       SEQUENCE {
55780fb4a2SCy Schubert  *     responseType   OBJECT IDENTIFIER,
56780fb4a2SCy Schubert  *     response       OCTET STRING }
57780fb4a2SCy Schubert  */
58780fb4a2SCy Schubert typedef struct {
59780fb4a2SCy Schubert 	ASN1_OBJECT *responseType;
60780fb4a2SCy Schubert 	ASN1_OCTET_STRING *response;
61780fb4a2SCy Schubert } ResponseBytes;
62780fb4a2SCy Schubert 
63780fb4a2SCy Schubert /*
64780fb4a2SCy Schubert  * OCSPResponse ::= SEQUENCE {
65780fb4a2SCy Schubert  *    responseStatus         OCSPResponseStatus,
66780fb4a2SCy Schubert  *    responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
67780fb4a2SCy Schubert  */
68780fb4a2SCy Schubert typedef struct {
69780fb4a2SCy Schubert 	ASN1_ENUMERATED *responseStatus;
70780fb4a2SCy Schubert 	ResponseBytes *responseBytes;
71780fb4a2SCy Schubert } OCSPResponse;
72780fb4a2SCy Schubert 
73780fb4a2SCy Schubert ASN1_SEQUENCE(ResponseBytes) = {
74780fb4a2SCy Schubert 	ASN1_SIMPLE(ResponseBytes, responseType, ASN1_OBJECT),
75780fb4a2SCy Schubert 	ASN1_SIMPLE(ResponseBytes, response, ASN1_OCTET_STRING)
76780fb4a2SCy Schubert } ASN1_SEQUENCE_END(ResponseBytes);
77780fb4a2SCy Schubert 
78780fb4a2SCy Schubert ASN1_SEQUENCE(OCSPResponse) = {
79780fb4a2SCy Schubert 	ASN1_SIMPLE(OCSPResponse, responseStatus, ASN1_ENUMERATED),
80780fb4a2SCy Schubert 	ASN1_EXP_OPT(OCSPResponse, responseBytes, ResponseBytes, 0)
81780fb4a2SCy Schubert } ASN1_SEQUENCE_END(OCSPResponse);
82780fb4a2SCy Schubert 
83780fb4a2SCy Schubert IMPLEMENT_ASN1_FUNCTIONS(OCSPResponse);
84780fb4a2SCy Schubert 
85780fb4a2SCy Schubert /*
86780fb4a2SCy Schubert  * ResponderID ::= CHOICE {
87780fb4a2SCy Schubert  *    byName               [1] Name,
88780fb4a2SCy Schubert  *    byKey                [2] KeyHash }
89780fb4a2SCy Schubert  */
90780fb4a2SCy Schubert typedef struct {
91780fb4a2SCy Schubert 	int type;
92780fb4a2SCy Schubert 	union {
93780fb4a2SCy Schubert 		X509_NAME *byName;
94780fb4a2SCy Schubert 		ASN1_OCTET_STRING *byKey;
95780fb4a2SCy Schubert 	} value;
96780fb4a2SCy Schubert } ResponderID;
97780fb4a2SCy Schubert 
98780fb4a2SCy Schubert /*
99780fb4a2SCy Schubert  * RevokedInfo ::= SEQUENCE {
100780fb4a2SCy Schubert  *     revocationTime              GeneralizedTime,
101780fb4a2SCy Schubert  *     revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
102780fb4a2SCy Schubert  */
103780fb4a2SCy Schubert typedef struct {
104780fb4a2SCy Schubert 	ASN1_GENERALIZEDTIME *revocationTime;
105780fb4a2SCy Schubert 	ASN1_ENUMERATED *revocationReason;
106780fb4a2SCy Schubert } RevokedInfo;
107780fb4a2SCy Schubert 
108780fb4a2SCy Schubert /*
109780fb4a2SCy Schubert  * CertStatus ::= CHOICE {
110780fb4a2SCy Schubert  *     good        [0]     IMPLICIT NULL,
111780fb4a2SCy Schubert  *     revoked     [1]     IMPLICIT RevokedInfo,
112780fb4a2SCy Schubert  *     unknown     [2]     IMPLICIT UnknownInfo }
113780fb4a2SCy Schubert  */
114780fb4a2SCy Schubert typedef struct {
115780fb4a2SCy Schubert 	int type;
116780fb4a2SCy Schubert 	union {
117780fb4a2SCy Schubert 		ASN1_NULL *good;
118780fb4a2SCy Schubert 		RevokedInfo *revoked;
119780fb4a2SCy Schubert 		ASN1_NULL *unknown;
120780fb4a2SCy Schubert 	} value;
121780fb4a2SCy Schubert } CertStatus;
122780fb4a2SCy Schubert 
123780fb4a2SCy Schubert /*
124780fb4a2SCy Schubert  * SingleResponse ::= SEQUENCE {
125780fb4a2SCy Schubert  *    certID                       CertID,
126780fb4a2SCy Schubert  *    certStatus                   CertStatus,
127780fb4a2SCy Schubert  *    thisUpdate                   GeneralizedTime,
128780fb4a2SCy Schubert  *    nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
129780fb4a2SCy Schubert  *    singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
130780fb4a2SCy Schubert  */
131780fb4a2SCy Schubert typedef struct {
132780fb4a2SCy Schubert 	CertID *certID;
133780fb4a2SCy Schubert 	CertStatus *certStatus;
134780fb4a2SCy Schubert 	ASN1_GENERALIZEDTIME *thisUpdate;
135780fb4a2SCy Schubert 	ASN1_GENERALIZEDTIME *nextUpdate;
136780fb4a2SCy Schubert 	STACK_OF(X509_EXTENSION) *singleExtensions;
137780fb4a2SCy Schubert } SingleResponse;
138780fb4a2SCy Schubert 
139780fb4a2SCy Schubert /*
140780fb4a2SCy Schubert  * ResponseData ::= SEQUENCE {
141780fb4a2SCy Schubert  *   version              [0] EXPLICIT Version DEFAULT v1,
142780fb4a2SCy Schubert  *   responderID              ResponderID,
143780fb4a2SCy Schubert  *   producedAt               GeneralizedTime,
144780fb4a2SCy Schubert  *   responses                SEQUENCE OF SingleResponse,
145780fb4a2SCy Schubert  *   responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
146780fb4a2SCy Schubert  */
147780fb4a2SCy Schubert typedef struct {
148780fb4a2SCy Schubert 	ASN1_INTEGER *version;
149780fb4a2SCy Schubert 	ResponderID *responderID;
150780fb4a2SCy Schubert 	ASN1_GENERALIZEDTIME *producedAt;
151780fb4a2SCy Schubert 	STACK_OF(SingleResponse) *responses;
152780fb4a2SCy Schubert 	STACK_OF(X509_EXTENSION) *responseExtensions;
153780fb4a2SCy Schubert } ResponseData;
154780fb4a2SCy Schubert 
155780fb4a2SCy Schubert /*
156780fb4a2SCy Schubert  * BasicOCSPResponse       ::= SEQUENCE {
157780fb4a2SCy Schubert  *   tbsResponseData      ResponseData,
158780fb4a2SCy Schubert  *   signatureAlgorithm   AlgorithmIdentifier,
159780fb4a2SCy Schubert  *   signature            BIT STRING,
160780fb4a2SCy Schubert  *   certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
161780fb4a2SCy Schubert  */
162780fb4a2SCy Schubert typedef struct {
163780fb4a2SCy Schubert 	ResponseData *tbsResponseData;
164780fb4a2SCy Schubert 	X509_ALGOR *signatureAlgorithm;
165780fb4a2SCy Schubert 	ASN1_BIT_STRING *signature;
166780fb4a2SCy Schubert 	STACK_OF(X509) *certs;
167780fb4a2SCy Schubert } BasicOCSPResponse;
168780fb4a2SCy Schubert 
169780fb4a2SCy Schubert ASN1_SEQUENCE(CertID) = {
170780fb4a2SCy Schubert 	ASN1_SIMPLE(CertID, hashAlgorithm, X509_ALGOR),
171780fb4a2SCy Schubert 	ASN1_SIMPLE(CertID, issuerNameHash, ASN1_OCTET_STRING),
172780fb4a2SCy Schubert 	ASN1_SIMPLE(CertID, issuerKeyHash, ASN1_OCTET_STRING),
173780fb4a2SCy Schubert 	ASN1_SIMPLE(CertID, serialNumber, ASN1_INTEGER)
174780fb4a2SCy Schubert } ASN1_SEQUENCE_END(CertID);
175780fb4a2SCy Schubert 
176780fb4a2SCy Schubert ASN1_CHOICE(ResponderID) = {
177780fb4a2SCy Schubert 	ASN1_EXP(ResponderID, value.byName, X509_NAME, 1),
178780fb4a2SCy Schubert 	ASN1_EXP(ResponderID, value.byKey, ASN1_OCTET_STRING, 2)
179780fb4a2SCy Schubert } ASN1_CHOICE_END(ResponderID);
180780fb4a2SCy Schubert 
181780fb4a2SCy Schubert ASN1_SEQUENCE(RevokedInfo) = {
182780fb4a2SCy Schubert 	ASN1_SIMPLE(RevokedInfo, revocationTime, ASN1_GENERALIZEDTIME),
183780fb4a2SCy Schubert 	ASN1_EXP_OPT(RevokedInfo, revocationReason, ASN1_ENUMERATED, 0)
184780fb4a2SCy Schubert } ASN1_SEQUENCE_END(RevokedInfo);
185780fb4a2SCy Schubert 
186780fb4a2SCy Schubert ASN1_CHOICE(CertStatus) = {
187780fb4a2SCy Schubert 	ASN1_IMP(CertStatus, value.good, ASN1_NULL, 0),
188780fb4a2SCy Schubert 	ASN1_IMP(CertStatus, value.revoked, RevokedInfo, 1),
189780fb4a2SCy Schubert 	ASN1_IMP(CertStatus, value.unknown, ASN1_NULL, 2)
190780fb4a2SCy Schubert } ASN1_CHOICE_END(CertStatus);
191780fb4a2SCy Schubert 
192780fb4a2SCy Schubert ASN1_SEQUENCE(SingleResponse) = {
193780fb4a2SCy Schubert 	ASN1_SIMPLE(SingleResponse, certID, CertID),
194780fb4a2SCy Schubert 	ASN1_SIMPLE(SingleResponse, certStatus, CertStatus),
195780fb4a2SCy Schubert 	ASN1_SIMPLE(SingleResponse, thisUpdate, ASN1_GENERALIZEDTIME),
196780fb4a2SCy Schubert 	ASN1_EXP_OPT(SingleResponse, nextUpdate, ASN1_GENERALIZEDTIME, 0),
197780fb4a2SCy Schubert 	ASN1_EXP_SEQUENCE_OF_OPT(SingleResponse, singleExtensions,
198780fb4a2SCy Schubert 				 X509_EXTENSION, 1)
199780fb4a2SCy Schubert } ASN1_SEQUENCE_END(SingleResponse);
200780fb4a2SCy Schubert 
201780fb4a2SCy Schubert ASN1_SEQUENCE(ResponseData) = {
202780fb4a2SCy Schubert 	ASN1_EXP_OPT(ResponseData, version, ASN1_INTEGER, 0),
203780fb4a2SCy Schubert 	ASN1_SIMPLE(ResponseData, responderID, ResponderID),
204780fb4a2SCy Schubert 	ASN1_SIMPLE(ResponseData, producedAt, ASN1_GENERALIZEDTIME),
205780fb4a2SCy Schubert 	ASN1_SEQUENCE_OF(ResponseData, responses, SingleResponse),
206780fb4a2SCy Schubert 	ASN1_EXP_SEQUENCE_OF_OPT(ResponseData, responseExtensions,
207780fb4a2SCy Schubert 				 X509_EXTENSION, 1)
208780fb4a2SCy Schubert } ASN1_SEQUENCE_END(ResponseData);
209780fb4a2SCy Schubert 
210780fb4a2SCy Schubert ASN1_SEQUENCE(BasicOCSPResponse) = {
211780fb4a2SCy Schubert 	ASN1_SIMPLE(BasicOCSPResponse, tbsResponseData, ResponseData),
212780fb4a2SCy Schubert 	ASN1_SIMPLE(BasicOCSPResponse, signatureAlgorithm, X509_ALGOR),
213780fb4a2SCy Schubert 	ASN1_SIMPLE(BasicOCSPResponse, signature, ASN1_BIT_STRING),
214780fb4a2SCy Schubert 	ASN1_EXP_SEQUENCE_OF_OPT(BasicOCSPResponse, certs, X509, 0)
215780fb4a2SCy Schubert } ASN1_SEQUENCE_END(BasicOCSPResponse);
216780fb4a2SCy Schubert 
217780fb4a2SCy Schubert IMPLEMENT_ASN1_FUNCTIONS(BasicOCSPResponse);
218780fb4a2SCy Schubert 
DEFINE_STACK_OF(SingleResponse)219*a90b9d01SCy Schubert DEFINE_STACK_OF(SingleResponse)
220780fb4a2SCy Schubert 
221780fb4a2SCy Schubert static char * mem_bio_to_str(BIO *out)
222780fb4a2SCy Schubert {
223780fb4a2SCy Schubert 	char *txt;
224780fb4a2SCy Schubert 	size_t rlen;
225780fb4a2SCy Schubert 	int res;
226780fb4a2SCy Schubert 
227780fb4a2SCy Schubert 	rlen = BIO_ctrl_pending(out);
228780fb4a2SCy Schubert 	txt = os_malloc(rlen + 1);
229780fb4a2SCy Schubert 	if (!txt) {
230780fb4a2SCy Schubert 		BIO_free(out);
231780fb4a2SCy Schubert 		return NULL;
232780fb4a2SCy Schubert 	}
233780fb4a2SCy Schubert 
234780fb4a2SCy Schubert 	res = BIO_read(out, txt, rlen);
235780fb4a2SCy Schubert 	BIO_free(out);
236780fb4a2SCy Schubert 	if (res < 0) {
237780fb4a2SCy Schubert 		os_free(txt);
238780fb4a2SCy Schubert 		return NULL;
239780fb4a2SCy Schubert 	}
240780fb4a2SCy Schubert 
241780fb4a2SCy Schubert 	txt[res] = '\0';
242780fb4a2SCy Schubert 	return txt;
243780fb4a2SCy Schubert }
244780fb4a2SCy Schubert 
245780fb4a2SCy Schubert 
generalizedtime_str(ASN1_GENERALIZEDTIME * t)246780fb4a2SCy Schubert static char * generalizedtime_str(ASN1_GENERALIZEDTIME *t)
247780fb4a2SCy Schubert {
248780fb4a2SCy Schubert 	BIO *out;
249780fb4a2SCy Schubert 
250780fb4a2SCy Schubert 	out = BIO_new(BIO_s_mem());
251780fb4a2SCy Schubert 	if (!out)
252780fb4a2SCy Schubert 		return NULL;
253780fb4a2SCy Schubert 
254780fb4a2SCy Schubert 	if (!ASN1_GENERALIZEDTIME_print(out, t)) {
255780fb4a2SCy Schubert 		BIO_free(out);
256780fb4a2SCy Schubert 		return NULL;
257780fb4a2SCy Schubert 	}
258780fb4a2SCy Schubert 
259780fb4a2SCy Schubert 	return mem_bio_to_str(out);
260780fb4a2SCy Schubert }
261780fb4a2SCy Schubert 
262780fb4a2SCy Schubert 
responderid_str(ResponderID * rid)263780fb4a2SCy Schubert static char * responderid_str(ResponderID *rid)
264780fb4a2SCy Schubert {
265780fb4a2SCy Schubert 	BIO *out;
266780fb4a2SCy Schubert 
267780fb4a2SCy Schubert 	out = BIO_new(BIO_s_mem());
268780fb4a2SCy Schubert 	if (!out)
269780fb4a2SCy Schubert 		return NULL;
270780fb4a2SCy Schubert 
271780fb4a2SCy Schubert 	switch (rid->type) {
272780fb4a2SCy Schubert 	case 0:
273780fb4a2SCy Schubert 		X509_NAME_print_ex(out, rid->value.byName, 0, XN_FLAG_ONELINE);
274780fb4a2SCy Schubert 		break;
275780fb4a2SCy Schubert 	case 1:
276780fb4a2SCy Schubert 		i2a_ASN1_STRING(out, rid->value.byKey, V_ASN1_OCTET_STRING);
277780fb4a2SCy Schubert 		break;
278780fb4a2SCy Schubert 	default:
279780fb4a2SCy Schubert 		BIO_free(out);
280780fb4a2SCy Schubert 		return NULL;
281780fb4a2SCy Schubert 	}
282780fb4a2SCy Schubert 
283780fb4a2SCy Schubert 	return mem_bio_to_str(out);
284780fb4a2SCy Schubert }
285780fb4a2SCy Schubert 
286780fb4a2SCy Schubert 
octet_string_str(ASN1_OCTET_STRING * o)287780fb4a2SCy Schubert static char * octet_string_str(ASN1_OCTET_STRING *o)
288780fb4a2SCy Schubert {
289780fb4a2SCy Schubert 	BIO *out;
290780fb4a2SCy Schubert 
291780fb4a2SCy Schubert 	out = BIO_new(BIO_s_mem());
292780fb4a2SCy Schubert 	if (!out)
293780fb4a2SCy Schubert 		return NULL;
294780fb4a2SCy Schubert 
295780fb4a2SCy Schubert 	i2a_ASN1_STRING(out, o, V_ASN1_OCTET_STRING);
296780fb4a2SCy Schubert 	return mem_bio_to_str(out);
297780fb4a2SCy Schubert }
298780fb4a2SCy Schubert 
299780fb4a2SCy Schubert 
integer_str(ASN1_INTEGER * i)300780fb4a2SCy Schubert static char * integer_str(ASN1_INTEGER *i)
301780fb4a2SCy Schubert {
302780fb4a2SCy Schubert 	BIO *out;
303780fb4a2SCy Schubert 
304780fb4a2SCy Schubert 	out = BIO_new(BIO_s_mem());
305780fb4a2SCy Schubert 	if (!out)
306780fb4a2SCy Schubert 		return NULL;
307780fb4a2SCy Schubert 
308780fb4a2SCy Schubert 	i2a_ASN1_INTEGER(out, i);
309780fb4a2SCy Schubert 	return mem_bio_to_str(out);
310780fb4a2SCy Schubert }
311780fb4a2SCy Schubert 
312780fb4a2SCy Schubert 
algor_str(X509_ALGOR * alg)313780fb4a2SCy Schubert static char * algor_str(X509_ALGOR *alg)
314780fb4a2SCy Schubert {
315780fb4a2SCy Schubert 	BIO *out;
316780fb4a2SCy Schubert 
317780fb4a2SCy Schubert 	out = BIO_new(BIO_s_mem());
318780fb4a2SCy Schubert 	if (!out)
319780fb4a2SCy Schubert 		return NULL;
320780fb4a2SCy Schubert 
321780fb4a2SCy Schubert 	i2a_ASN1_OBJECT(out, alg->algorithm);
322780fb4a2SCy Schubert 	return mem_bio_to_str(out);
323780fb4a2SCy Schubert }
324780fb4a2SCy Schubert 
325780fb4a2SCy Schubert 
extensions_str(const char * title,STACK_OF (X509_EXTENSION)* ext)326780fb4a2SCy Schubert static char * extensions_str(const char *title, STACK_OF(X509_EXTENSION) *ext)
327780fb4a2SCy Schubert {
328780fb4a2SCy Schubert 	BIO *out;
329780fb4a2SCy Schubert 
330780fb4a2SCy Schubert 	if (!ext)
331780fb4a2SCy Schubert 		return NULL;
332780fb4a2SCy Schubert 
333780fb4a2SCy Schubert 	out = BIO_new(BIO_s_mem());
334780fb4a2SCy Schubert 	if (!out)
335780fb4a2SCy Schubert 		return NULL;
336780fb4a2SCy Schubert 
337780fb4a2SCy Schubert 	if (!X509V3_extensions_print(out, title, ext, 0, 0)) {
338780fb4a2SCy Schubert 		BIO_free(out);
339780fb4a2SCy Schubert 		return NULL;
340780fb4a2SCy Schubert 	}
341780fb4a2SCy Schubert 	return mem_bio_to_str(out);
342780fb4a2SCy Schubert }
343780fb4a2SCy Schubert 
344780fb4a2SCy Schubert 
ocsp_resp_valid(ASN1_GENERALIZEDTIME * thisupd,ASN1_GENERALIZEDTIME * nextupd)345780fb4a2SCy Schubert static int ocsp_resp_valid(ASN1_GENERALIZEDTIME *thisupd,
346780fb4a2SCy Schubert 			   ASN1_GENERALIZEDTIME *nextupd)
347780fb4a2SCy Schubert {
348780fb4a2SCy Schubert 	time_t now, tmp;
349780fb4a2SCy Schubert 
350780fb4a2SCy Schubert 	if (!ASN1_GENERALIZEDTIME_check(thisupd)) {
351780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
352780fb4a2SCy Schubert 			   "OpenSSL: Invalid OCSP response thisUpdate");
353780fb4a2SCy Schubert 		return 0;
354780fb4a2SCy Schubert 	}
355780fb4a2SCy Schubert 
356780fb4a2SCy Schubert 	time(&now);
357780fb4a2SCy Schubert 	tmp = now + 5 * 60; /* allow five minute clock difference */
358780fb4a2SCy Schubert 	if (X509_cmp_time(thisupd, &tmp) > 0) {
359780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response not yet valid");
360780fb4a2SCy Schubert 		return 0;
361780fb4a2SCy Schubert 	}
362780fb4a2SCy Schubert 
363780fb4a2SCy Schubert 	if (!nextupd)
364780fb4a2SCy Schubert 		return 1; /* OK - no limit on response age */
365780fb4a2SCy Schubert 
366780fb4a2SCy Schubert 	if (!ASN1_GENERALIZEDTIME_check(nextupd)) {
367780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
368780fb4a2SCy Schubert 			   "OpenSSL: Invalid OCSP response nextUpdate");
369780fb4a2SCy Schubert 		return 0;
370780fb4a2SCy Schubert 	}
371780fb4a2SCy Schubert 
372780fb4a2SCy Schubert 	tmp = now - 5 * 60; /* allow five minute clock difference */
373780fb4a2SCy Schubert 	if (X509_cmp_time(nextupd, &tmp) < 0) {
374780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP response expired");
375780fb4a2SCy Schubert 		return 0;
376780fb4a2SCy Schubert 	}
377780fb4a2SCy Schubert 
378780fb4a2SCy Schubert 	if (ASN1_STRING_cmp(nextupd, thisupd) < 0) {
379780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
380780fb4a2SCy Schubert 			   "OpenSSL: OCSP response nextUpdate before thisUpdate");
381780fb4a2SCy Schubert 		return 0;
382780fb4a2SCy Schubert 	}
383780fb4a2SCy Schubert 
384780fb4a2SCy Schubert 	/* Both thisUpdate and nextUpdate are valid */
385780fb4a2SCy Schubert 	return -1;
386780fb4a2SCy Schubert }
387780fb4a2SCy Schubert 
388780fb4a2SCy Schubert 
issuer_match(X509 * cert,X509 * issuer,CertID * certid)389780fb4a2SCy Schubert static int issuer_match(X509 *cert, X509 *issuer, CertID *certid)
390780fb4a2SCy Schubert {
391780fb4a2SCy Schubert 	X509_NAME *iname;
392780fb4a2SCy Schubert 	ASN1_BIT_STRING *ikey;
393780fb4a2SCy Schubert 	const EVP_MD *dgst;
394780fb4a2SCy Schubert 	unsigned int len;
395780fb4a2SCy Schubert 	unsigned char md[EVP_MAX_MD_SIZE];
396780fb4a2SCy Schubert 	ASN1_OCTET_STRING *hash;
397780fb4a2SCy Schubert 	char *txt;
398780fb4a2SCy Schubert 
399780fb4a2SCy Schubert 	dgst = EVP_get_digestbyobj(certid->hashAlgorithm->algorithm);
400780fb4a2SCy Schubert 	if (!dgst) {
401780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
402780fb4a2SCy Schubert 			   "OpenSSL: Could not find matching hash algorithm for OCSP");
403780fb4a2SCy Schubert 		return -1;
404780fb4a2SCy Schubert 	}
405780fb4a2SCy Schubert 
406780fb4a2SCy Schubert 	iname = X509_get_issuer_name(cert);
407780fb4a2SCy Schubert 	if (!X509_NAME_digest(iname, dgst, md, &len))
408780fb4a2SCy Schubert 		return -1;
409780fb4a2SCy Schubert 	hash = ASN1_OCTET_STRING_new();
410780fb4a2SCy Schubert 	if (!hash)
411780fb4a2SCy Schubert 		return -1;
412780fb4a2SCy Schubert 	if (!ASN1_OCTET_STRING_set(hash, md, len)) {
413780fb4a2SCy Schubert 		ASN1_OCTET_STRING_free(hash);
414780fb4a2SCy Schubert 		return -1;
415780fb4a2SCy Schubert 	}
416780fb4a2SCy Schubert 
417780fb4a2SCy Schubert 	txt = octet_string_str(hash);
418780fb4a2SCy Schubert 	if (txt) {
419780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: calculated issuerNameHash: %s",
420780fb4a2SCy Schubert 			   txt);
421780fb4a2SCy Schubert 		os_free(txt);
422780fb4a2SCy Schubert 	}
423780fb4a2SCy Schubert 
424780fb4a2SCy Schubert 	if (ASN1_OCTET_STRING_cmp(certid->issuerNameHash, hash)) {
425780fb4a2SCy Schubert 		ASN1_OCTET_STRING_free(hash);
426780fb4a2SCy Schubert 		return -1;
427780fb4a2SCy Schubert 	}
428780fb4a2SCy Schubert 
429780fb4a2SCy Schubert 	ikey = X509_get0_pubkey_bitstr(issuer);
430780fb4a2SCy Schubert 	if (!ikey ||
431780fb4a2SCy Schubert 	    !EVP_Digest(ikey->data, ikey->length, md, &len, dgst, NULL) ||
432780fb4a2SCy Schubert 	    !ASN1_OCTET_STRING_set(hash, md, len)) {
433780fb4a2SCy Schubert 		ASN1_OCTET_STRING_free(hash);
434780fb4a2SCy Schubert 		return -1;
435780fb4a2SCy Schubert 	}
436780fb4a2SCy Schubert 
437780fb4a2SCy Schubert 	txt = octet_string_str(hash);
438780fb4a2SCy Schubert 	if (txt) {
439780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: calculated issuerKeyHash: %s",
440780fb4a2SCy Schubert 			   txt);
441780fb4a2SCy Schubert 		os_free(txt);
442780fb4a2SCy Schubert 	}
443780fb4a2SCy Schubert 
444780fb4a2SCy Schubert 	if (ASN1_OCTET_STRING_cmp(certid->issuerKeyHash, hash)) {
445780fb4a2SCy Schubert 		ASN1_OCTET_STRING_free(hash);
446780fb4a2SCy Schubert 		return -1;
447780fb4a2SCy Schubert 	}
448780fb4a2SCy Schubert 
449780fb4a2SCy Schubert 	ASN1_OCTET_STRING_free(hash);
450780fb4a2SCy Schubert 	return 0;
451780fb4a2SCy Schubert }
452780fb4a2SCy Schubert 
453780fb4a2SCy Schubert 
ocsp_find_signer(STACK_OF (X509)* certs,ResponderID * rid)454780fb4a2SCy Schubert static X509 * ocsp_find_signer(STACK_OF(X509) *certs, ResponderID *rid)
455780fb4a2SCy Schubert {
456780fb4a2SCy Schubert 	unsigned int i;
457780fb4a2SCy Schubert 	unsigned char hash[SHA_DIGEST_LENGTH];
458780fb4a2SCy Schubert 
459780fb4a2SCy Schubert 	if (rid->type == 0) {
460780fb4a2SCy Schubert 		/* byName */
461780fb4a2SCy Schubert 		return X509_find_by_subject(certs, rid->value.byName);
462780fb4a2SCy Schubert 	}
463780fb4a2SCy Schubert 
464780fb4a2SCy Schubert 	/* byKey */
465780fb4a2SCy Schubert 	if (rid->value.byKey->length != SHA_DIGEST_LENGTH)
466780fb4a2SCy Schubert 		return NULL;
467780fb4a2SCy Schubert 	for (i = 0; i < sk_X509_num(certs); i++) {
468780fb4a2SCy Schubert 		X509 *x = sk_X509_value(certs, i);
469780fb4a2SCy Schubert 
470780fb4a2SCy Schubert 		X509_pubkey_digest(x, EVP_sha1(), hash, NULL);
471780fb4a2SCy Schubert 		if (os_memcmp(rid->value.byKey->data, hash,
472780fb4a2SCy Schubert 			      SHA_DIGEST_LENGTH) == 0)
473780fb4a2SCy Schubert 			return x;
474780fb4a2SCy Schubert 	}
475780fb4a2SCy Schubert 
476780fb4a2SCy Schubert 	return NULL;
477780fb4a2SCy Schubert }
478780fb4a2SCy Schubert 
479780fb4a2SCy Schubert 
check_ocsp_resp(SSL_CTX * ssl_ctx,SSL * ssl,X509 * cert,X509 * issuer,X509 * issuer_issuer)480780fb4a2SCy Schubert enum ocsp_result check_ocsp_resp(SSL_CTX *ssl_ctx, SSL *ssl, X509 *cert,
481780fb4a2SCy Schubert 				 X509 *issuer, X509 *issuer_issuer)
482780fb4a2SCy Schubert {
483780fb4a2SCy Schubert 	const uint8_t *resp_data;
484780fb4a2SCy Schubert 	size_t resp_len;
485780fb4a2SCy Schubert 	OCSPResponse *resp;
486780fb4a2SCy Schubert 	int status;
487780fb4a2SCy Schubert 	ResponseBytes *bytes;
488780fb4a2SCy Schubert 	const u8 *basic_data;
489780fb4a2SCy Schubert 	size_t basic_len;
490780fb4a2SCy Schubert 	BasicOCSPResponse *basic;
491780fb4a2SCy Schubert 	ResponseData *rd;
492780fb4a2SCy Schubert 	char *txt;
493780fb4a2SCy Schubert 	int i, num;
494780fb4a2SCy Schubert 	unsigned int j, num_resp;
495780fb4a2SCy Schubert 	SingleResponse *matching_resp = NULL, *cmp_sresp;
496780fb4a2SCy Schubert 	enum ocsp_result result = OCSP_INVALID;
497780fb4a2SCy Schubert 	X509_STORE *store;
498780fb4a2SCy Schubert 	STACK_OF(X509) *untrusted = NULL, *certs = NULL, *chain = NULL;
499*a90b9d01SCy Schubert 	X509_STORE_CTX *ctx = NULL;
500780fb4a2SCy Schubert 	X509 *signer, *tmp_cert;
501780fb4a2SCy Schubert 	int signer_trusted = 0;
502780fb4a2SCy Schubert 	EVP_PKEY *skey;
503780fb4a2SCy Schubert 	int ret;
504780fb4a2SCy Schubert 	char buf[256];
505780fb4a2SCy Schubert 
506780fb4a2SCy Schubert 	txt = integer_str(X509_get_serialNumber(cert));
507780fb4a2SCy Schubert 	if (txt) {
508780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
509780fb4a2SCy Schubert 			   "OpenSSL: Searching OCSP response for peer certificate serialNumber: %s", txt);
510780fb4a2SCy Schubert 		os_free(txt);
511780fb4a2SCy Schubert 	}
512780fb4a2SCy Schubert 
513780fb4a2SCy Schubert 	SSL_get0_ocsp_response(ssl, &resp_data, &resp_len);
514780fb4a2SCy Schubert 	if (resp_data == NULL || resp_len == 0) {
515780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP response received");
516780fb4a2SCy Schubert 		return OCSP_NO_RESPONSE;
517780fb4a2SCy Schubert 	}
518780fb4a2SCy Schubert 
519780fb4a2SCy Schubert 	wpa_hexdump(MSG_DEBUG, "OpenSSL: OCSP response", resp_data, resp_len);
520780fb4a2SCy Schubert 
521780fb4a2SCy Schubert 	resp = d2i_OCSPResponse(NULL, &resp_data, resp_len);
522780fb4a2SCy Schubert 	if (!resp) {
523780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "OpenSSL: Failed to parse OCSPResponse");
524780fb4a2SCy Schubert 		return OCSP_INVALID;
525780fb4a2SCy Schubert 	}
526780fb4a2SCy Schubert 
527780fb4a2SCy Schubert 	status = ASN1_ENUMERATED_get(resp->responseStatus);
528780fb4a2SCy Schubert 	if (status != 0) {
529780fb4a2SCy Schubert 		wpa_printf(MSG_INFO, "OpenSSL: OCSP responder error %d",
530780fb4a2SCy Schubert 			   status);
531780fb4a2SCy Schubert 		return OCSP_INVALID;
532780fb4a2SCy Schubert 	}
533780fb4a2SCy Schubert 
534780fb4a2SCy Schubert 	bytes = resp->responseBytes;
535780fb4a2SCy Schubert 
536780fb4a2SCy Schubert 	if (!bytes ||
537780fb4a2SCy Schubert 	    OBJ_obj2nid(bytes->responseType) != NID_id_pkix_OCSP_basic) {
538780fb4a2SCy Schubert 		wpa_printf(MSG_INFO,
539780fb4a2SCy Schubert 			   "OpenSSL: Could not find BasicOCSPResponse");
540780fb4a2SCy Schubert 		return OCSP_INVALID;
541780fb4a2SCy Schubert 	}
542780fb4a2SCy Schubert 
543780fb4a2SCy Schubert 	basic_data = ASN1_STRING_data(bytes->response);
544780fb4a2SCy Schubert 	basic_len = ASN1_STRING_length(bytes->response);
545780fb4a2SCy Schubert 	wpa_hexdump(MSG_DEBUG, "OpenSSL: BasicOCSPResponse",
546780fb4a2SCy Schubert 		    basic_data, basic_len);
547780fb4a2SCy Schubert 
548780fb4a2SCy Schubert 	basic = d2i_BasicOCSPResponse(NULL, &basic_data, basic_len);
549780fb4a2SCy Schubert 	if (!basic) {
550780fb4a2SCy Schubert 		wpa_printf(MSG_INFO,
551780fb4a2SCy Schubert 			   "OpenSSL: Could not parse BasicOCSPResponse");
552780fb4a2SCy Schubert 		OCSPResponse_free(resp);
553780fb4a2SCy Schubert 		return OCSP_INVALID;
554780fb4a2SCy Schubert 	}
555780fb4a2SCy Schubert 
556780fb4a2SCy Schubert 	rd = basic->tbsResponseData;
557780fb4a2SCy Schubert 
558780fb4a2SCy Schubert 	if (basic->certs) {
559780fb4a2SCy Schubert 		untrusted = sk_X509_dup(basic->certs);
560780fb4a2SCy Schubert 		if (!untrusted)
561780fb4a2SCy Schubert 			goto fail;
562780fb4a2SCy Schubert 
563780fb4a2SCy Schubert 		num = sk_X509_num(basic->certs);
564780fb4a2SCy Schubert 		for (i = 0; i < num; i++) {
565780fb4a2SCy Schubert 			X509 *extra_cert;
566780fb4a2SCy Schubert 
567780fb4a2SCy Schubert 			extra_cert = sk_X509_value(basic->certs, i);
568780fb4a2SCy Schubert 			X509_NAME_oneline(X509_get_subject_name(extra_cert),
569780fb4a2SCy Schubert 					  buf, sizeof(buf));
570780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
571780fb4a2SCy Schubert 				   "OpenSSL: BasicOCSPResponse cert %s", buf);
572780fb4a2SCy Schubert 
573780fb4a2SCy Schubert 			if (!sk_X509_push(untrusted, extra_cert)) {
574780fb4a2SCy Schubert 				wpa_printf(MSG_DEBUG,
575780fb4a2SCy Schubert 					   "OpenSSL: Could not add certificate to the untrusted stack");
576780fb4a2SCy Schubert 			}
577780fb4a2SCy Schubert 		}
578780fb4a2SCy Schubert 	}
579780fb4a2SCy Schubert 
580780fb4a2SCy Schubert 	store = SSL_CTX_get_cert_store(ssl_ctx);
581780fb4a2SCy Schubert 	if (issuer) {
582780fb4a2SCy Schubert 		if (X509_STORE_add_cert(store, issuer) != 1) {
583780fb4a2SCy Schubert 			tls_show_errors(MSG_INFO, __func__,
584780fb4a2SCy Schubert 					"OpenSSL: Could not add issuer to certificate store");
585780fb4a2SCy Schubert 		}
586780fb4a2SCy Schubert 		certs = sk_X509_new_null();
587780fb4a2SCy Schubert 		if (certs) {
588780fb4a2SCy Schubert 			tmp_cert = X509_dup(issuer);
589780fb4a2SCy Schubert 			if (tmp_cert && !sk_X509_push(certs, tmp_cert)) {
590780fb4a2SCy Schubert 				tls_show_errors(
591780fb4a2SCy Schubert 					MSG_INFO, __func__,
592780fb4a2SCy Schubert 					"OpenSSL: Could not add issuer to OCSP responder trust store");
593780fb4a2SCy Schubert 				X509_free(tmp_cert);
594780fb4a2SCy Schubert 				sk_X509_free(certs);
595780fb4a2SCy Schubert 				certs = NULL;
596780fb4a2SCy Schubert 			}
597780fb4a2SCy Schubert 			if (certs && issuer_issuer) {
598780fb4a2SCy Schubert 				tmp_cert = X509_dup(issuer_issuer);
599780fb4a2SCy Schubert 				if (tmp_cert &&
600780fb4a2SCy Schubert 				    !sk_X509_push(certs, tmp_cert)) {
601780fb4a2SCy Schubert 					tls_show_errors(
602780fb4a2SCy Schubert 						MSG_INFO, __func__,
603780fb4a2SCy Schubert 						"OpenSSL: Could not add issuer's issuer to OCSP responder trust store");
604780fb4a2SCy Schubert 					X509_free(tmp_cert);
605780fb4a2SCy Schubert 				}
606780fb4a2SCy Schubert 			}
607780fb4a2SCy Schubert 		}
608780fb4a2SCy Schubert 	}
609780fb4a2SCy Schubert 
610780fb4a2SCy Schubert 	signer = ocsp_find_signer(certs, rd->responderID);
611780fb4a2SCy Schubert 	if (!signer)
612780fb4a2SCy Schubert 		signer = ocsp_find_signer(untrusted, rd->responderID);
613780fb4a2SCy Schubert 	else
614780fb4a2SCy Schubert 		signer_trusted = 1;
615780fb4a2SCy Schubert 	if (!signer) {
616780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
617780fb4a2SCy Schubert 			   "OpenSSL: Could not find OCSP signer certificate");
618780fb4a2SCy Schubert 		goto fail;
619780fb4a2SCy Schubert 	}
620780fb4a2SCy Schubert 
621780fb4a2SCy Schubert 	skey = X509_get_pubkey(signer);
622780fb4a2SCy Schubert 	if (!skey) {
623780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
624780fb4a2SCy Schubert 			   "OpenSSL: Could not get OCSP signer public key");
625780fb4a2SCy Schubert 		goto fail;
626780fb4a2SCy Schubert 	}
627780fb4a2SCy Schubert 	if (ASN1_item_verify(ASN1_ITEM_rptr(ResponseData),
628780fb4a2SCy Schubert 			     basic->signatureAlgorithm, basic->signature,
629780fb4a2SCy Schubert 			     basic->tbsResponseData, skey) <= 0) {
630780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
631780fb4a2SCy Schubert 			   "OpenSSL: BasicOCSPResponse signature is invalid");
632780fb4a2SCy Schubert 		goto fail;
633780fb4a2SCy Schubert 	}
634780fb4a2SCy Schubert 
635780fb4a2SCy Schubert 	X509_NAME_oneline(X509_get_subject_name(signer), buf, sizeof(buf));
636780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG,
637780fb4a2SCy Schubert 		   "OpenSSL: Found OCSP signer certificate %s and verified BasicOCSPResponse signature",
638780fb4a2SCy Schubert 		   buf);
639780fb4a2SCy Schubert 
640*a90b9d01SCy Schubert 	ctx = X509_STORE_CTX_new();
641*a90b9d01SCy Schubert 	if (!ctx || !X509_STORE_CTX_init(ctx, store, signer, untrusted))
642780fb4a2SCy Schubert 		goto fail;
643*a90b9d01SCy Schubert 	X509_STORE_CTX_set_purpose(ctx, X509_PURPOSE_OCSP_HELPER);
644*a90b9d01SCy Schubert 	ret = X509_verify_cert(ctx);
645*a90b9d01SCy Schubert 	chain = X509_STORE_CTX_get1_chain(ctx);
646*a90b9d01SCy Schubert 	X509_STORE_CTX_cleanup(ctx);
647780fb4a2SCy Schubert 	if (ret <= 0) {
648780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
649780fb4a2SCy Schubert 			   "OpenSSL: Could not validate OCSP signer certificate");
650780fb4a2SCy Schubert 		goto fail;
651780fb4a2SCy Schubert 	}
652780fb4a2SCy Schubert 
653780fb4a2SCy Schubert 	if (!chain || sk_X509_num(chain) <= 0) {
654780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: No OCSP signer chain found");
655780fb4a2SCy Schubert 		goto fail;
656780fb4a2SCy Schubert 	}
657780fb4a2SCy Schubert 
658780fb4a2SCy Schubert 	if (!signer_trusted) {
659780fb4a2SCy Schubert 		X509_check_purpose(signer, -1, 0);
660*a90b9d01SCy Schubert 		if ((X509_get_extension_flags(signer) & EXFLAG_XKUSAGE) &&
661*a90b9d01SCy Schubert 		    (X509_get_extended_key_usage(signer) & XKU_OCSP_SIGN)) {
662780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
663780fb4a2SCy Schubert 				   "OpenSSL: OCSP signer certificate delegation OK");
664780fb4a2SCy Schubert 		} else {
665780fb4a2SCy Schubert 			tmp_cert = sk_X509_value(chain, sk_X509_num(chain) - 1);
666780fb4a2SCy Schubert 			if (X509_check_trust(tmp_cert, NID_OCSP_sign, 0) !=
667780fb4a2SCy Schubert 			    X509_TRUST_TRUSTED) {
668780fb4a2SCy Schubert 				wpa_printf(MSG_DEBUG,
669780fb4a2SCy Schubert 					   "OpenSSL: OCSP signer certificate not trusted");
670780fb4a2SCy Schubert 				result = OCSP_NO_RESPONSE;
671780fb4a2SCy Schubert 				goto fail;
672780fb4a2SCy Schubert 			}
673780fb4a2SCy Schubert 		}
674780fb4a2SCy Schubert 	}
675780fb4a2SCy Schubert 
676780fb4a2SCy Schubert 	wpa_printf(MSG_DEBUG, "OpenSSL: OCSP version: %lu",
677780fb4a2SCy Schubert 		   ASN1_INTEGER_get(rd->version));
678780fb4a2SCy Schubert 
679780fb4a2SCy Schubert 	txt = responderid_str(rd->responderID);
680780fb4a2SCy Schubert 	if (txt) {
681780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP responderID: %s",
682780fb4a2SCy Schubert 			   txt);
683780fb4a2SCy Schubert 		os_free(txt);
684780fb4a2SCy Schubert 	}
685780fb4a2SCy Schubert 
686780fb4a2SCy Schubert 	txt = generalizedtime_str(rd->producedAt);
687780fb4a2SCy Schubert 	if (txt) {
688780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP producedAt: %s",
689780fb4a2SCy Schubert 			   txt);
690780fb4a2SCy Schubert 		os_free(txt);
691780fb4a2SCy Schubert 	}
692780fb4a2SCy Schubert 
693780fb4a2SCy Schubert 	num_resp = sk_SingleResponse_num(rd->responses);
694780fb4a2SCy Schubert 	if (num_resp == 0) {
695780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
696780fb4a2SCy Schubert 			   "OpenSSL: No OCSP SingleResponse within BasicOCSPResponse");
697780fb4a2SCy Schubert 		result = OCSP_NO_RESPONSE;
698780fb4a2SCy Schubert 		goto fail;
699780fb4a2SCy Schubert 	}
700780fb4a2SCy Schubert 	cmp_sresp = sk_SingleResponse_value(rd->responses, 0);
701780fb4a2SCy Schubert 	for (j = 0; j < num_resp; j++) {
702780fb4a2SCy Schubert 		SingleResponse *sresp;
703780fb4a2SCy Schubert 		CertID *cid1, *cid2;
704780fb4a2SCy Schubert 
705780fb4a2SCy Schubert 		sresp = sk_SingleResponse_value(rd->responses, j);
706780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: OCSP SingleResponse %u/%u",
707780fb4a2SCy Schubert 			   j + 1, num_resp);
708780fb4a2SCy Schubert 
709780fb4a2SCy Schubert 		txt = algor_str(sresp->certID->hashAlgorithm);
710780fb4a2SCy Schubert 		if (txt) {
711780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
712780fb4a2SCy Schubert 				   "OpenSSL: certID hashAlgorithm: %s", txt);
713780fb4a2SCy Schubert 			os_free(txt);
714780fb4a2SCy Schubert 		}
715780fb4a2SCy Schubert 
716780fb4a2SCy Schubert 		txt = octet_string_str(sresp->certID->issuerNameHash);
717780fb4a2SCy Schubert 		if (txt) {
718780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
719780fb4a2SCy Schubert 				   "OpenSSL: certID issuerNameHash: %s", txt);
720780fb4a2SCy Schubert 			os_free(txt);
721780fb4a2SCy Schubert 		}
722780fb4a2SCy Schubert 
723780fb4a2SCy Schubert 		txt = octet_string_str(sresp->certID->issuerKeyHash);
724780fb4a2SCy Schubert 		if (txt) {
725780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
726780fb4a2SCy Schubert 				   "OpenSSL: certID issuerKeyHash: %s", txt);
727780fb4a2SCy Schubert 			os_free(txt);
728780fb4a2SCy Schubert 		}
729780fb4a2SCy Schubert 
730780fb4a2SCy Schubert 		txt = integer_str(sresp->certID->serialNumber);
731780fb4a2SCy Schubert 		if (txt) {
732780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
733780fb4a2SCy Schubert 				   "OpenSSL: certID serialNumber: %s", txt);
734780fb4a2SCy Schubert 			os_free(txt);
735780fb4a2SCy Schubert 		}
736780fb4a2SCy Schubert 
737780fb4a2SCy Schubert 		switch (sresp->certStatus->type) {
738780fb4a2SCy Schubert 		case 0:
739780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG, "OpenSSL: certStatus: good");
740780fb4a2SCy Schubert 			break;
741780fb4a2SCy Schubert 		case 1:
742780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG, "OpenSSL: certStatus: revoked");
743780fb4a2SCy Schubert 			break;
744780fb4a2SCy Schubert 		default:
745780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG, "OpenSSL: certStatus: unknown");
746780fb4a2SCy Schubert 			break;
747780fb4a2SCy Schubert 		}
748780fb4a2SCy Schubert 
749780fb4a2SCy Schubert 		txt = generalizedtime_str(sresp->thisUpdate);
750780fb4a2SCy Schubert 		if (txt) {
751780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG, "OpenSSL: thisUpdate: %s", txt);
752780fb4a2SCy Schubert 			os_free(txt);
753780fb4a2SCy Schubert 		}
754780fb4a2SCy Schubert 
755780fb4a2SCy Schubert 		if (sresp->nextUpdate) {
756780fb4a2SCy Schubert 			txt = generalizedtime_str(sresp->nextUpdate);
757780fb4a2SCy Schubert 			if (txt) {
758780fb4a2SCy Schubert 				wpa_printf(MSG_DEBUG, "OpenSSL: nextUpdate: %s",
759780fb4a2SCy Schubert 					   txt);
760780fb4a2SCy Schubert 				os_free(txt);
761780fb4a2SCy Schubert 			}
762780fb4a2SCy Schubert 		}
763780fb4a2SCy Schubert 
764780fb4a2SCy Schubert 		txt = extensions_str("singleExtensions",
765780fb4a2SCy Schubert 				     sresp->singleExtensions);
766780fb4a2SCy Schubert 		if (txt) {
767780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG, "OpenSSL: %s", txt);
768780fb4a2SCy Schubert 			os_free(txt);
769780fb4a2SCy Schubert 		}
770780fb4a2SCy Schubert 
771780fb4a2SCy Schubert 		cid1 = cmp_sresp->certID;
772780fb4a2SCy Schubert 		cid2 = sresp->certID;
773780fb4a2SCy Schubert 		if (j > 0 &&
774780fb4a2SCy Schubert 		    (OBJ_cmp(cid1->hashAlgorithm->algorithm,
775780fb4a2SCy Schubert 			     cid2->hashAlgorithm->algorithm) != 0 ||
776780fb4a2SCy Schubert 		     ASN1_OCTET_STRING_cmp(cid1->issuerNameHash,
777780fb4a2SCy Schubert 					   cid2->issuerNameHash) != 0 ||
778780fb4a2SCy Schubert 		     ASN1_OCTET_STRING_cmp(cid1->issuerKeyHash,
779780fb4a2SCy Schubert 					   cid2->issuerKeyHash) != 0)) {
780780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
781780fb4a2SCy Schubert 				   "OpenSSL: Different OCSP response issuer information between SingleResponse values within BasicOCSPResponse");
782780fb4a2SCy Schubert 			goto fail;
783780fb4a2SCy Schubert 		}
784780fb4a2SCy Schubert 
785780fb4a2SCy Schubert 		if (!matching_resp && issuer &&
786780fb4a2SCy Schubert 		    ASN1_INTEGER_cmp(sresp->certID->serialNumber,
787780fb4a2SCy Schubert 				     X509_get_serialNumber(cert)) == 0 &&
788780fb4a2SCy Schubert 		    issuer_match(cert, issuer, sresp->certID) == 0) {
789780fb4a2SCy Schubert 			wpa_printf(MSG_DEBUG,
790780fb4a2SCy Schubert 				   "OpenSSL: This response matches peer certificate");
791780fb4a2SCy Schubert 			matching_resp = sresp;
792780fb4a2SCy Schubert 		}
793780fb4a2SCy Schubert 	}
794780fb4a2SCy Schubert 
795780fb4a2SCy Schubert 	txt = extensions_str("responseExtensions", rd->responseExtensions);
796780fb4a2SCy Schubert 	if (txt) {
797780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG, "OpenSSL: %s", txt);
798780fb4a2SCy Schubert 		os_free(txt);
799780fb4a2SCy Schubert 	}
800780fb4a2SCy Schubert 
801780fb4a2SCy Schubert 	if (!matching_resp) {
802780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
803780fb4a2SCy Schubert 			   "OpenSSL: Could not find OCSP response that matches the peer certificate");
804780fb4a2SCy Schubert 		result = OCSP_NO_RESPONSE;
805780fb4a2SCy Schubert 		goto fail;
806780fb4a2SCy Schubert 	}
807780fb4a2SCy Schubert 
808780fb4a2SCy Schubert 	if (!ocsp_resp_valid(matching_resp->thisUpdate,
809780fb4a2SCy Schubert 			     matching_resp->nextUpdate)) {
810780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
811780fb4a2SCy Schubert 			   "OpenSSL: OCSP response not valid at this time");
812780fb4a2SCy Schubert 		goto fail;
813780fb4a2SCy Schubert 	}
814780fb4a2SCy Schubert 
815780fb4a2SCy Schubert 	if (matching_resp->certStatus->type == 1) {
816780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
817780fb4a2SCy Schubert 			   "OpenSSL: OCSP response indicated that the peer certificate has been revoked");
818780fb4a2SCy Schubert 		result = OCSP_REVOKED;
819780fb4a2SCy Schubert 		goto fail;
820780fb4a2SCy Schubert 	}
821780fb4a2SCy Schubert 
822780fb4a2SCy Schubert 	if (matching_resp->certStatus->type != 0) {
823780fb4a2SCy Schubert 		wpa_printf(MSG_DEBUG,
824780fb4a2SCy Schubert 			   "OpenSSL: OCSP response did not indicate good status");
825780fb4a2SCy Schubert 		result = OCSP_NO_RESPONSE;
826780fb4a2SCy Schubert 		goto fail;
827780fb4a2SCy Schubert 	}
828780fb4a2SCy Schubert 
829780fb4a2SCy Schubert 	/* OCSP response indicated the certificate is good. */
830780fb4a2SCy Schubert 	result = OCSP_GOOD;
831780fb4a2SCy Schubert fail:
832780fb4a2SCy Schubert 	sk_X509_pop_free(chain, X509_free);
833780fb4a2SCy Schubert 	sk_X509_free(untrusted);
834780fb4a2SCy Schubert 	sk_X509_pop_free(certs, X509_free);
835780fb4a2SCy Schubert 	BasicOCSPResponse_free(basic);
836780fb4a2SCy Schubert 	OCSPResponse_free(resp);
837*a90b9d01SCy Schubert 	X509_STORE_CTX_free(ctx);
838780fb4a2SCy Schubert 
839780fb4a2SCy Schubert 	return result;
840780fb4a2SCy Schubert }
841780fb4a2SCy Schubert 
842780fb4a2SCy Schubert #endif /* OPENSSL_IS_BORINGSSL */
843