11b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt/*
21b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * TLSv1 client - OCSP
31b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * Copyright (c) 2015, Jouni Malinen <j@w1.fi>
41b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt *
51b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * This software may be distributed under the terms of the BSD license.
61b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt * See README for more details.
71b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt */
81b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
91b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "includes.h"
101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "common.h"
121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "crypto/tls.h"
130e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt#include "crypto/sha1.h"
141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "asn1.h"
150e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt#include "x509v3.h"
161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "tlsv1_common.h"
171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "tlsv1_record.h"
181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "tlsv1_client.h"
191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt#include "tlsv1_client_i.h"
201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt/* RFC 6960, 4.2.1: OCSPResponseStatus ::= ENUMERATED */
231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtenum ocsp_response_status {
241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	OCSP_RESP_STATUS_SUCCESSFUL = 0,
251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	OCSP_RESP_STATUS_MALFORMED_REQ = 1,
261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	OCSP_RESP_STATUS_INT_ERROR = 2,
271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	OCSP_RESP_STATUS_TRY_LATER = 3,
281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	/* 4 not used */
291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	OCSP_RESP_STATUS_SIG_REQUIRED = 5,
301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	OCSP_RESP_STATUS_UNAUTHORIZED = 6,
311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt};
321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic int is_oid_basic_ocsp_resp(struct asn1_oid *oid)
351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{
361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	return oid->len == 10 &&
371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[0] == 1 /* iso */ &&
381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[1] == 3 /* identified-organization */ &&
391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[2] == 6 /* dod */ &&
401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[3] == 1 /* internet */ &&
411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[4] == 5 /* security */ &&
421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[5] == 5 /* mechanisms */ &&
431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[6] == 7 /* id-pkix */ &&
441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[7] == 48 /* id-ad */ &&
451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[8] == 1 /* id-pkix-ocsp */ &&
461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		oid->oid[9] == 1 /* id-pkix-ocsp-basic */;
471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt}
481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
500e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtstatic int ocsp_responder_id_match(struct x509_certificate *signer,
510e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   struct x509_name *name, const u8 *key_hash)
520e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt{
530e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (key_hash) {
540e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		u8 hash[SHA1_MAC_LEN];
550e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		const u8 *addr[1] = { signer->public_key };
560e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		size_t len[1] = { signer->public_key_len };
570e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
580e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (sha1_vector(1, addr, len, hash) < 0)
590e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			return 0;
600e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return os_memcmp(hash, key_hash, SHA1_MAC_LEN) == 0;
610e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
620e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
630e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	return x509_name_compare(&signer->subject, name) == 0;
640e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt}
650e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
660e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
670e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtstatic unsigned int ocsp_hash_data(struct asn1_oid *alg, const u8 *data,
680e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   size_t data_len, u8 *hash)
690e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt{
700e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	const u8 *addr[1] = { data };
710e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	size_t len[1] = { data_len };
720e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	char buf[100];
730e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
740e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (x509_sha1_oid(alg)) {
750e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (sha1_vector(1, addr, len, hash) < 0)
760e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			return 0;
770e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA1)", hash, 20);
780e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return 20;
790e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
800e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
810e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (x509_sha256_oid(alg)) {
820e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (sha256_vector(1, addr, len, hash) < 0)
830e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			return 0;
840e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA256)", hash, 32);
850e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return 32;
860e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
870e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
880e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (x509_sha384_oid(alg)) {
890e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (sha384_vector(1, addr, len, hash) < 0)
900e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			return 0;
910e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA384)", hash, 48);
920e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return 48;
930e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
940e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
950e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (x509_sha512_oid(alg)) {
960e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (sha512_vector(1, addr, len, hash) < 0)
970e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			return 0;
980e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "OCSP: Hash (SHA512)", hash, 64);
990e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return 64;
1000e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
1010e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1020e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1030e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	asn1_oid_to_str(alg, buf, sizeof(buf));
1040e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OCSP: Could not calculate hash with alg %s",
1050e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		   buf);
1060e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	return 0;
1070e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt}
1080e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1090e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1100e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtstatic int tls_process_ocsp_single_response(struct tlsv1_client *conn,
1110e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					    struct x509_certificate *cert,
1120e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					    struct x509_certificate *issuer,
1130e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					    const u8 *resp, size_t len,
1140e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					    enum tls_ocsp_result *res)
1150e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt{
1160e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	struct asn1_hdr hdr;
1170e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	const u8 *pos, *end;
1180e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	struct x509_algorithm_identifier alg;
1190e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	const u8 *name_hash, *key_hash;
1200e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	size_t name_hash_len, key_hash_len;
1210e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	const u8 *serial_number;
1220e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	size_t serial_number_len;
1230e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	u8 hash[64];
1240e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	unsigned int hash_len;
1250e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	unsigned int cert_status;
1260e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	os_time_t update;
1270e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	struct os_time now;
1280e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1290e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "OCSP: SingleResponse", resp, len);
1300e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1310e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/*
1320e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 * SingleResponse ::= SEQUENCE {
1330e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    certID                       CertID,
1340e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    certStatus                   CertStatus,
1350e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    thisUpdate                   GeneralizedTime,
1360e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
1370e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
1380e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 */
1390e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1400e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* CertID ::= SEQUENCE */
1410e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(resp, len, &hdr) < 0 ||
1420e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
1430e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
1440e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
1450e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Expected SEQUENCE (CertID) - found class %d tag 0x%x",
1460e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag);
1470e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
1480e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
1490e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload;
1500e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	end = hdr.payload + hdr.length;
1510e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1520e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/*
1530e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 * CertID ::= SEQUENCE {
1540e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    hashAlgorithm           AlgorithmIdentifier,
1550e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    issuerNameHash          OCTET STRING,
1560e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    issuerKeyHash           OCTET STRING,
1570e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    serialNumber            CertificateSerialNumber }
1580e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 */
1590e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1600e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* hashAlgorithm  AlgorithmIdentifier */
1610e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (x509_parse_algorithm_identifier(pos, end - pos, &alg, &pos))
1620e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
1630e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1640e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* issuerNameHash  OCTET STRING */
1650e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1660e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
1670e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_OCTETSTRING) {
1680e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
1690e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Expected OCTET STRING (issuerNameHash) - found class %d tag 0x%x",
1700e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag);
1710e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
1720e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
1730e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	name_hash = hdr.payload;
1740e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	name_hash_len = hdr.length;
1750e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "OCSP: issuerNameHash",
1760e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    name_hash, name_hash_len);
1770e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload + hdr.length;
1780e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1790e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "OCSP: Issuer subject DN",
1800e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    issuer->subject_dn, issuer->subject_dn_len);
1810e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	hash_len = ocsp_hash_data(&alg.oid, issuer->subject_dn,
1820e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				  issuer->subject_dn_len, hash);
1830e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (hash_len == 0 || name_hash_len != hash_len ||
1840e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    os_memcmp(name_hash, hash, hash_len) != 0) {
1850e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: issuerNameHash mismatch");
1860e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "OCSP: Calculated issuerNameHash",
1870e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    hash, hash_len);
1880e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
1890e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
1900e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
1910e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* issuerKeyHash  OCTET STRING */
1920e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
1930e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
1940e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_OCTETSTRING) {
1950e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
1960e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Expected OCTET STRING (issuerKeyHash) - found class %d tag 0x%x",
1970e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag);
1980e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
1990e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
2000e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	key_hash = hdr.payload;
2010e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	key_hash_len = hdr.length;
2020e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "OCSP: issuerKeyHash", key_hash, key_hash_len);
2030e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload + hdr.length;
2040e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
2050e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	hash_len = ocsp_hash_data(&alg.oid, issuer->public_key,
2060e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				  issuer->public_key_len, hash);
2070e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (hash_len == 0 || key_hash_len != hash_len ||
2080e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    os_memcmp(key_hash, hash, hash_len) != 0) {
2090e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: issuerKeyHash mismatch");
2100e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "OCSP: Calculated issuerKeyHash",
2110e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    hash, hash_len);
2120e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
2130e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
2140e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
2150e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* serialNumber CertificateSerialNumber ::= INTEGER */
2160e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
2170e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
2180e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_INTEGER ||
2190e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.length < 1 || hdr.length > X509_MAX_SERIAL_NUM_LEN) {
2200e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: No INTEGER tag found for serialNumber; class=%d tag=0x%x length=%u",
2210e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag, hdr.length);
2220e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
2230e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
2240e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	serial_number = hdr.payload;
2250e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	serial_number_len = hdr.length;
2260e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	while (serial_number_len > 0 && serial_number[0] == 0) {
2270e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		serial_number++;
2280e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		serial_number_len--;
2290e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
2300e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "OCSP: serialNumber", serial_number,
2310e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    serial_number_len);
2320e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
2330e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (serial_number_len != cert->serial_number_len ||
2340e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    os_memcmp(serial_number, cert->serial_number,
2350e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		      serial_number_len) != 0) {
2360e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: serialNumber mismatch");
2370e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
2380e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
2390e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
2400e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = end;
2410e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	end = resp + len;
2420e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
2430e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* certStatus CertStatus ::= CHOICE */
2440e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
2450e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
2460e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
2470e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Expected CHOICE (CertStatus) - found class %d tag 0x%x",
2480e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag);
2490e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
2500e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
2510e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	cert_status = hdr.tag;
2520e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OCSP: certStatus=%u", cert_status);
2530e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_hexdump(MSG_DEBUG, "OCSP: CertStatus additional data",
2540e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.payload, hdr.length);
2550e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload + hdr.length;
2560e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
2570e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	os_get_time(&now);
2580e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* thisUpdate  GeneralizedTime */
2590e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
2600e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
2610e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
2620e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    x509_parse_time(hdr.payload, hdr.length, hdr.tag, &update) < 0) {
2630e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: Failed to parse thisUpdate");
2640e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
2650e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
2660e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OCSP: thisUpdate %lu", (unsigned long) update);
2670e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload + hdr.length;
2680e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if ((unsigned long) now.sec < (unsigned long) update) {
2690e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
2700e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: thisUpdate time in the future (response not yet valid)");
2710e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
2720e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
2730e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
2740e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* nextUpdate  [0]  EXPLICIT GeneralizedTime OPTIONAL */
2750e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (pos < end) {
2760e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (asn1_get_next(pos, end - pos, &hdr) < 0)
2770e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			return -1;
2780e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && hdr.tag == 0) {
2790e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			const u8 *next = hdr.payload + hdr.length;
2800e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
2810e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
2820e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    hdr.class != ASN1_CLASS_UNIVERSAL ||
2830e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
2840e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
2850e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					    &update) < 0) {
2860e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				wpa_printf(MSG_DEBUG,
2870e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					   "OCSP: Failed to parse nextUpdate");
2880e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				return -1;
2890e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			}
2900e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			wpa_printf(MSG_DEBUG, "OCSP: nextUpdate %lu",
2910e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   (unsigned long) update);
2920e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			pos = next;
2930e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			if ((unsigned long) now.sec > (unsigned long) update) {
2940e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				wpa_printf(MSG_DEBUG, "OCSP: nextUpdate time in the past (response has expired)");
2950e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				return -1;
2960e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			}
2970e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
2980e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
2990e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3000e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* singleExtensions  [1]  EXPLICIT Extensions OPTIONAL */
3010e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (pos < end) {
3020e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "OCSP: singleExtensions",
3030e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    pos, end - pos);
3040e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		/* Ignore for now */
3050e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
3060e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3070e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (cert_status == 0 /* good */)
3080e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		*res = TLS_OCSP_GOOD;
3090e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	else if (cert_status == 1 /* revoked */)
3100e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		*res = TLS_OCSP_REVOKED;
3110e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	else
3120e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return -1;
3130e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	return 0;
3140e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt}
3150e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3160e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3170e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtstatic enum tls_ocsp_result
3180e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidttls_process_ocsp_responses(struct tlsv1_client *conn,
319d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			   struct x509_certificate *cert,
3200e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   struct x509_certificate *issuer, const u8 *resp,
3210e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   size_t len)
3220e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt{
3230e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	struct asn1_hdr hdr;
3240e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	const u8 *pos, *end;
3250e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	enum tls_ocsp_result res;
3260e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3270e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = resp;
3280e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	end = resp + len;
3290e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	while (pos < end) {
3300e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		/* SingleResponse ::= SEQUENCE */
3310e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
3320e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.class != ASN1_CLASS_UNIVERSAL ||
3330e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.tag != ASN1_TAG_SEQUENCE) {
3340e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			wpa_printf(MSG_DEBUG,
3350e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   "OCSP: Expected SEQUENCE (SingleResponse) - found class %d tag 0x%x",
3360e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   hdr.class, hdr.tag);
3370e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			return TLS_OCSP_INVALID;
3380e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
339d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		if (tls_process_ocsp_single_response(conn, cert, issuer,
3400e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt						     hdr.payload, hdr.length,
3410e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt						     &res) == 0)
3420e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			return res;
3430e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		pos = hdr.payload + hdr.length;
3440e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
3450e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3460e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_printf(MSG_DEBUG,
3470e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		   "OCSP: Did not find a response matching the server certificate");
3480e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	return TLS_OCSP_NO_RESPONSE;
3490e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt}
3500e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3510e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtstatic enum tls_ocsp_result
353d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidttls_process_basic_ocsp_response(struct tlsv1_client *conn,
354d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt				struct x509_certificate *srv_cert,
355d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt				const u8 *resp, size_t len)
3561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{
3570e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	struct asn1_hdr hdr;
3580e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	const u8 *pos, *end;
3590e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	const u8 *resp_data, *sign_value, *key_hash = NULL, *responses;
3600e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	const u8 *resp_data_signed;
3610e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	size_t resp_data_len, sign_value_len, responses_len;
3620e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	size_t resp_data_signed_len;
3630e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	struct x509_algorithm_identifier alg;
3640e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	struct x509_certificate *certs = NULL, *last_cert = NULL;
3650e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	struct x509_certificate *issuer, *signer;
3660e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	struct x509_name name; /* used if key_hash == NULL */
3670e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	char buf[100];
3680e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	os_time_t produced_at;
369d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	enum tls_ocsp_result res;
3700e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "OCSP: BasicOCSPResponse", resp, len);
3721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
3730e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	os_memset(&name, 0, sizeof(name));
3740e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	/*
3761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 * RFC 6960, 4.2.1:
3771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 * BasicOCSPResponse       ::= SEQUENCE {
3781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 *    tbsResponseData      ResponseData,
3791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 *    signatureAlgorithm   AlgorithmIdentifier,
3801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 *    signature            BIT STRING,
3811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 *    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
3821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 */
3831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
3840e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(resp, len, &hdr) < 0 ||
3850e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
3860e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
3870e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
3880e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Expected SEQUENCE (BasicOCSPResponse) - found class %d tag 0x%x",
3890e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag);
3900e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return TLS_OCSP_INVALID;
3910e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
3920e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload;
3930e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	end = hdr.payload + hdr.length;
3940e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
3950e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* ResponseData ::= SEQUENCE */
3960e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
3970e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
3980e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
3990e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
4000e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Expected SEQUENCE (ResponseData) - found class %d tag 0x%x",
4010e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag);
4020e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return TLS_OCSP_INVALID;
4030e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
4040e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	resp_data = hdr.payload;
4050e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	resp_data_len = hdr.length;
4060e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	resp_data_signed = pos;
4070e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload + hdr.length;
4080e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	resp_data_signed_len = pos - resp_data_signed;
4090e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
4100e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* signatureAlgorithm  AlgorithmIdentifier */
4110e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (x509_parse_algorithm_identifier(pos, end - pos, &alg, &pos))
4120e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return TLS_OCSP_INVALID;
4130e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
4140e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* signature  BIT STRING */
4150e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
4160e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
4170e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_BITSTRING) {
4180e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
4190e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Expected BITSTRING (signature) - found class %d tag 0x%x",
4200e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag);
4210e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return TLS_OCSP_INVALID;
4220e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
4230e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (hdr.length < 1)
4240e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return TLS_OCSP_INVALID;
4250e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload;
4260e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (*pos) {
4270e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: BITSTRING - %d unused bits", *pos);
4280e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		/* PKCS #1 v1.5 10.2.1:
4290e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		 * It is an error if the length in bits of the signature S is
4300e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		 * not a multiple of eight.
4310e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		 */
4320e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		return TLS_OCSP_INVALID;
4330e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
4340e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	sign_value = pos + 1;
4350e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	sign_value_len = hdr.length - 1;
4360e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos += hdr.length;
4370e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "OCSP: signature", sign_value, sign_value_len);
4380e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
4390e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* certs  [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL */
4400e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (pos < end) {
4410e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
4420e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
4430e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.tag != 0) {
4440e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			wpa_printf(MSG_DEBUG,
4450e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   "OCSP: Expected [0] EXPLICIT (certs) - found class %d tag 0x%x",
4460e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   hdr.class, hdr.tag);
4470e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			return TLS_OCSP_INVALID;
4480e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
4490e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "OCSP: certs",
4500e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    hdr.payload, hdr.length);
4510e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		pos = hdr.payload;
4520e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		end = hdr.payload + hdr.length;
4530e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		while (pos < end) {
4540e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			struct x509_certificate *cert;
4550e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
4560e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
4570e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    hdr.class != ASN1_CLASS_UNIVERSAL ||
4580e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    hdr.tag != ASN1_TAG_SEQUENCE) {
4590e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				wpa_printf(MSG_DEBUG,
4600e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					   "OCSP: Expected SEQUENCE (Certificate) - found class %d tag 0x%x",
4610e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					   hdr.class, hdr.tag);
4620e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				goto fail;
4630e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			}
4640e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
4650e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			cert = x509_certificate_parse(hdr.payload, hdr.length);
4660e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			if (!cert)
4670e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				goto fail;
4680e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			if (last_cert) {
4690e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				last_cert->next = cert;
4700e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				last_cert = cert;
4710e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			} else {
4720e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				last_cert = certs = cert;
4730e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			}
4740e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			pos = hdr.payload + hdr.length;
4750e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
4760e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
4770e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
4780e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/*
4790e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 * ResponseData ::= SEQUENCE {
4800e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    version              [0] EXPLICIT Version DEFAULT v1,
4810e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    responderID              ResponderID,
4820e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    producedAt               GeneralizedTime,
4830e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    responses                SEQUENCE OF SingleResponse,
4840e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
4850e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 */
4860e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = resp_data;
4870e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	end = resp_data + resp_data_len;
4880e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "OCSP: ResponseData", pos, end - pos);
4890e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
4900e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/*
4910e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 * version [0] EXPLICIT Version DEFAULT v1
4920e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 * Version ::= INTEGER { v1(0) }
4930e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 */
4940e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 &&
4950e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC &&
4960e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag == 0) {
4970e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
4980e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.class != ASN1_CLASS_UNIVERSAL ||
4990e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.tag != ASN1_TAG_INTEGER ||
5000e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.length != 1) {
5010e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			wpa_printf(MSG_DEBUG,
5020e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   "OCSP: No INTEGER (len=1) tag found for version field - found class %d tag 0x%x length %d",
5030e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   hdr.class, hdr.tag, hdr.length);
5040e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			goto fail;
5050e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
5060e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: ResponseData version %u",
5070e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.payload[0]);
5080e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (hdr.payload[0] != 0) {
5090e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			wpa_printf(MSG_DEBUG,
5100e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   "OCSP: Unsupported ResponseData version %u",
5110e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   hdr.payload[0]);
5120e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			goto no_resp;
5130e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
5140e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		pos = hdr.payload + hdr.length;
5150e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	} else {
5160e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
5170e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Default ResponseData version (v1)");
5180e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
5190e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
5200e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/*
5210e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 * ResponderID ::= CHOICE {
5220e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    byName              [1] Name,
5230e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 *    byKey               [2] KeyHash }
5240e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	 */
5250e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
5260e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC) {
5270e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
5280e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Expected CHOICE (ResponderID) - found class %d tag 0x%x",
5290e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag);
5300e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		goto fail;
5310e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
5320e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
5330e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (hdr.tag == 1) {
5340e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		/* Name */
5350e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (x509_parse_name(hdr.payload, hdr.length, &name, &pos) < 0)
5360e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			goto fail;
5370e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		x509_name_string(&name, buf, sizeof(buf));
5380e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: ResponderID byName Name: %s", buf);
5390e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	} else if (hdr.tag == 2) {
5400e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		/* KeyHash ::= OCTET STRING */
5410e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
5420e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.class != ASN1_CLASS_UNIVERSAL ||
5430e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    hdr.tag != ASN1_TAG_OCTETSTRING) {
5440e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			wpa_printf(MSG_DEBUG,
5450e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   "OCSP: Expected OCTET STRING (KeyHash) - found class %d tag 0x%x",
5460e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   hdr.class, hdr.tag);
5470e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			goto fail;
5480e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
5490e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		key_hash = hdr.payload;
5500e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "OCSP: ResponderID byKey KeyHash",
5510e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    key_hash, hdr.length);
5520e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (hdr.length != SHA1_MAC_LEN) {
5530e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			wpa_printf(MSG_DEBUG,
5540e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   "OCSP: Unexpected byKey KeyHash length %u - expected %u for SHA-1",
5550e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   hdr.length, SHA1_MAC_LEN);
5560e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			goto fail;
5570e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
5580e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		pos = hdr.payload + hdr.length;
5590e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	} else {
5600e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: Unexpected ResponderID CHOICE %u",
5610e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.tag);
5620e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		goto fail;
5630e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
5640e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
5650e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* producedAt  GeneralizedTime */
5660e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
5670e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
5680e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_GENERALIZEDTIME ||
5690e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    x509_parse_time(hdr.payload, hdr.length, hdr.tag,
5700e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    &produced_at) < 0) {
5710e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: Failed to parse producedAt");
5720e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		goto fail;
5730e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
5740e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_printf(MSG_DEBUG, "OCSP: producedAt %lu",
5750e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		   (unsigned long) produced_at);
5760e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload + hdr.length;
5770e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
5780e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	/* responses  SEQUENCE OF SingleResponse */
5790e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
5800e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
5810e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
5820e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
5830e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Expected SEQUENCE (responses) - found class %d tag 0x%x",
5840e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   hdr.class, hdr.tag);
5850e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		goto fail;
5860e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
5870e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	responses = hdr.payload;
5880e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	responses_len = hdr.length;
5890e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "OCSP: responses", responses, responses_len);
5900e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	pos = hdr.payload + hdr.length;
5910e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
5920e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (pos < end) {
5930e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		/* responseExtensions  [1] EXPLICIT Extensions OPTIONAL */
5940e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_hexdump(MSG_MSGDUMP, "OCSP: responseExtensions",
5950e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    pos, end - pos);
5960e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		/* Ignore for now. */
5970e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
5980e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
599d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (!srv_cert) {
6000e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
6010e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Server certificate not known - cannot check OCSP response");
6020e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		goto no_resp;
6030e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
6040e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
605d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (srv_cert->next) {
6060e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		/* Issuer has already been verified in the chain */
607d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		issuer = srv_cert->next;
6080e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	} else {
6090e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		/* Find issuer from the set of trusted certificates */
6100e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		for (issuer = conn->cred ? conn->cred->trusted_certs : NULL;
6110e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		     issuer; issuer = issuer->next) {
612d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			if (x509_name_compare(&srv_cert->issuer,
6130e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					      &issuer->subject) == 0)
6140e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				break;
6150e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
6160e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
6170e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (!issuer) {
6180e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
6190e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Server certificate issuer not known - cannot check OCSP response");
6200e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		goto no_resp;
6210e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
6220e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
6230e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (ocsp_responder_id_match(issuer, &name, key_hash)) {
6240e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		wpa_printf(MSG_DEBUG,
6250e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			   "OCSP: Server certificate issuer certificate matches ResponderID");
6260e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		signer = issuer;
6270e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	} else {
6280e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		for (signer = certs; signer; signer = signer->next) {
6290e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			if (!ocsp_responder_id_match(signer, &name, key_hash) ||
630d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			    x509_name_compare(&srv_cert->issuer,
6310e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt					      &issuer->subject) != 0 ||
6320e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    !(signer->ext_key_usage &
6330e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			      X509_EXT_KEY_USAGE_OCSP) ||
6340e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    x509_certificate_check_signature(issuer, signer) <
6350e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			    0)
6360e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				continue;
6370e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			wpa_printf(MSG_DEBUG,
6380e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   "OCSP: An extra certificate from the response matches ResponderID and is trusted as an OCSP signer");
6390e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			break;
6400e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
6410e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		if (!signer) {
6420e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			wpa_printf(MSG_DEBUG,
6430e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				   "OCSP: Could not find OCSP signer certificate");
6440e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt			goto no_resp;
6450e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		}
6460e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
6470e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
6480e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	x509_free_name(&name);
6490e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	os_memset(&name, 0, sizeof(name));
6500e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	x509_certificate_chain_free(certs);
6510e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	certs = NULL;
6520e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
6530e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	if (x509_check_signature(signer, &alg, sign_value, sign_value_len,
6540e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt				 resp_data_signed, resp_data_signed_len) < 0) {
6550e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    wpa_printf(MSG_DEBUG, "OCSP: Invalid signature");
6560e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt		    return TLS_OCSP_INVALID;
6570e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	}
6580e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
659d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	res = tls_process_ocsp_responses(conn, srv_cert, issuer,
660d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt					 responses, responses_len);
661d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	if (res == TLS_OCSP_REVOKED)
662d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		srv_cert->ocsp_revoked = 1;
663d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	else if (res == TLS_OCSP_GOOD)
664d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		srv_cert->ocsp_good = 1;
665d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	return res;
6660e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
6670e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtno_resp:
6680e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	x509_free_name(&name);
6690e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	x509_certificate_chain_free(certs);
6701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	return TLS_OCSP_NO_RESPONSE;
6710e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt
6720e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidtfail:
6730e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	x509_free_name(&name);
6740e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	x509_certificate_chain_free(certs);
6750e58d9be2680098adccaadeadf31375ca54b7256Dmitry Shmidt	return TLS_OCSP_INVALID;
6761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt}
6771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
6781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
6791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidtenum tls_ocsp_result tls_process_ocsp_response(struct tlsv1_client *conn,
6801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt					       const u8 *resp, size_t len)
6811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt{
6821b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	struct asn1_hdr hdr;
6831b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	const u8 *pos, *end;
6841b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	u8 resp_status;
6851b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	struct asn1_oid oid;
6861b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	char obuf[80];
687d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	struct x509_certificate *cert;
688d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	enum tls_ocsp_result res = TLS_OCSP_NO_RESPONSE;
689d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	enum tls_ocsp_result res_first = res;
6901b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
6911b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	wpa_hexdump(MSG_MSGDUMP, "TLSv1: OCSPResponse", resp, len);
6921b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
6931b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	/*
6941b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 * RFC 6960, 4.2.1:
6951b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 * OCSPResponse ::= SEQUENCE {
6961b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 *    responseStatus  OCSPResponseStatus,
6971b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 *    responseBytes   [0] EXPLICIT ResponseBytes OPTIONAL }
6981b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 */
6991b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
7001b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (asn1_get_next(resp, len, &hdr) < 0 ||
7011b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
7021b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
7031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		wpa_printf(MSG_DEBUG,
7041b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   "OCSP: Expected SEQUENCE (OCSPResponse) - found class %d tag 0x%x",
7051b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   hdr.class, hdr.tag);
7061b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return TLS_OCSP_INVALID;
7071b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	}
7081b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	pos = hdr.payload;
7091b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	end = hdr.payload + hdr.length;
7101b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
7111b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	/* OCSPResponseStatus ::= ENUMERATED */
7121b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
7131b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
7141b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.tag != ASN1_TAG_ENUMERATED ||
7151b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.length != 1) {
7161b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		wpa_printf(MSG_DEBUG,
7171b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   "OCSP: Expected ENUMERATED (responseStatus) - found class %d tag 0x%x length %u",
7181b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   hdr.class, hdr.tag, hdr.length);
7191b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return TLS_OCSP_INVALID;
7201b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	}
7211b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	resp_status = hdr.payload[0];
7221b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	wpa_printf(MSG_DEBUG, "OCSP: responseStatus %u", resp_status);
7231b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	pos = hdr.payload + hdr.length;
7241b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (resp_status != OCSP_RESP_STATUS_SUCCESSFUL) {
7251b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: No stapling result");
7261b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return TLS_OCSP_NO_RESPONSE;
7271b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	}
7281b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
7291b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	/* responseBytes   [0] EXPLICIT ResponseBytes OPTIONAL */
7301b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (pos == end)
7311b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return TLS_OCSP_NO_RESPONSE;
7321b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
7331b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
7341b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC ||
7351b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.tag != 0) {
7361b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		wpa_printf(MSG_DEBUG,
7371b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   "OCSP: Expected [0] EXPLICIT (responseBytes) - found class %d tag 0x%x",
7381b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   hdr.class, hdr.tag);
7391b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return TLS_OCSP_INVALID;
7401b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	}
7411b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
7421b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	/*
7431b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 * ResponseBytes ::= SEQUENCE {
7441b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 *     responseType   OBJECT IDENTIFIER,
7451b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 *     response       OCTET STRING }
7461b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	 */
7471b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
7481b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (asn1_get_next(hdr.payload, hdr.length, &hdr) < 0 ||
7491b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
7501b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.tag != ASN1_TAG_SEQUENCE) {
7511b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		wpa_printf(MSG_DEBUG,
7521b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   "OCSP: Expected SEQUENCE (ResponseBytes) - found class %d tag 0x%x",
7531b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   hdr.class, hdr.tag);
7541b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return TLS_OCSP_INVALID;
7551b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	}
7561b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	pos = hdr.payload;
7571b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	end = hdr.payload + hdr.length;
7581b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
7591b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	/* responseType   OBJECT IDENTIFIER */
7601b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (asn1_get_oid(pos, end - pos, &oid, &pos)) {
7611b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		wpa_printf(MSG_DEBUG,
7621b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   "OCSP: Failed to parse OID (responseType)");
7631b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return TLS_OCSP_INVALID;
7641b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	}
7651b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	asn1_oid_to_str(&oid, obuf, sizeof(obuf));
7661b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	wpa_printf(MSG_DEBUG, "OCSP: responseType %s", obuf);
7671b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (!is_oid_basic_ocsp_resp(&oid)) {
7681b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		wpa_printf(MSG_DEBUG, "OCSP: Ignore unsupported response type");
7691b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return TLS_OCSP_NO_RESPONSE;
7701b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	}
7711b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
7721b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	/* response       OCTET STRING */
7731b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
7741b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.class != ASN1_CLASS_UNIVERSAL ||
7751b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	    hdr.tag != ASN1_TAG_OCTETSTRING) {
7761b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		wpa_printf(MSG_DEBUG,
7771b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   "OCSP: Expected OCTET STRING (response) - found class %d tag 0x%x",
7781b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt			   hdr.class, hdr.tag);
7791b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt		return TLS_OCSP_INVALID;
7801b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt	}
7811b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt
782d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	cert = conn->server_cert;
783d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	while (cert) {
784d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		if (!cert->ocsp_good && !cert->ocsp_revoked) {
785d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			char sbuf[128];
786d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
787d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			x509_name_string(&cert->subject, sbuf, sizeof(sbuf));
788d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			wpa_printf(MSG_DEBUG,
789d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt				   "OCSP: Trying to find certificate status for %s",
790d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt				   sbuf);
791d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt
792d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			res = tls_process_basic_ocsp_response(conn, cert,
793d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt							      hdr.payload,
794d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt							      hdr.length);
795d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			if (cert == conn->server_cert)
796d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt				res_first = res;
797d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		}
798d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		if (res == TLS_OCSP_REVOKED || cert->issuer_trusted)
799d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt			break;
800d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt		cert = cert->next;
801d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	}
802d97138ded63ac5388da3a2b63dea563c8b44c8ecDmitry Shmidt	return res == TLS_OCSP_REVOKED ? res : res_first;
8031b46775bb44f06b3cc285481ff5f7a673559ed7dDmitry Shmidt}
804