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