ocsp_vfy.c revision 1.17
1/* $OpenBSD: ocsp_vfy.c,v 1.17 2021/11/01 20:53:08 tb Exp $ */ 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3 * project 2000. 4 */ 5/* ==================================================================== 6 * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59#include <openssl/ocsp.h> 60#include <openssl/err.h> 61#include <string.h> 62 63#include "x509_lcl.h" 64 65static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, 66 STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags); 67static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id); 68static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, 69 unsigned long flags); 70static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret); 71static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, 72 STACK_OF(OCSP_SINGLERESP) *sresp); 73static int ocsp_check_delegated(X509 *x, int flags); 74static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, 75 X509_NAME *nm, STACK_OF(X509) *certs, X509_STORE *st, 76 unsigned long flags); 77 78/* Verify a basic response message */ 79int 80OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st, 81 unsigned long flags) 82{ 83 X509 *signer, *x; 84 STACK_OF(X509) *chain = NULL; 85 STACK_OF(X509) *untrusted = NULL; 86 X509_STORE_CTX ctx; 87 int i, ret = 0; 88 89 ret = ocsp_find_signer(&signer, bs, certs, st, flags); 90 if (!ret) { 91 OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); 92 goto end; 93 } 94 if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) 95 flags |= OCSP_NOVERIFY; 96 if (!(flags & OCSP_NOSIGS)) { 97 EVP_PKEY *skey; 98 99 skey = X509_get_pubkey(signer); 100 if (skey) { 101 ret = OCSP_BASICRESP_verify(bs, skey, 0); 102 EVP_PKEY_free(skey); 103 } 104 if (!skey || ret <= 0) { 105 OCSPerror(OCSP_R_SIGNATURE_FAILURE); 106 goto end; 107 } 108 } 109 if (!(flags & OCSP_NOVERIFY)) { 110 int init_res; 111 112 if (flags & OCSP_NOCHAIN) { 113 untrusted = NULL; 114 } else if (bs->certs && certs) { 115 untrusted = sk_X509_dup(bs->certs); 116 for (i = 0; i < sk_X509_num(certs); i++) { 117 if (!sk_X509_push(untrusted, 118 sk_X509_value(certs, i))) { 119 OCSPerror(ERR_R_MALLOC_FAILURE); 120 goto end; 121 } 122 } 123 } else 124 untrusted = bs->certs; 125 init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted); 126 if (!init_res) { 127 ret = -1; 128 OCSPerror(ERR_R_X509_LIB); 129 goto end; 130 } 131 132 if (X509_STORE_CTX_set_purpose(&ctx, 133 X509_PURPOSE_OCSP_HELPER) == 0) { 134 X509_STORE_CTX_cleanup(&ctx); 135 ret = -1; 136 goto end; 137 } 138 ret = X509_verify_cert(&ctx); 139 chain = X509_STORE_CTX_get1_chain(&ctx); 140 X509_STORE_CTX_cleanup(&ctx); 141 if (ret <= 0) { 142 i = X509_STORE_CTX_get_error(&ctx); 143 OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR); 144 ERR_asprintf_error_data("Verify error:%s", 145 X509_verify_cert_error_string(i)); 146 goto end; 147 } 148 if (flags & OCSP_NOCHECKS) { 149 ret = 1; 150 goto end; 151 } 152 /* At this point we have a valid certificate chain 153 * need to verify it against the OCSP issuer criteria. 154 */ 155 ret = ocsp_check_issuer(bs, chain, flags); 156 157 /* If fatal error or valid match then finish */ 158 if (ret != 0) 159 goto end; 160 161 /* Easy case: explicitly trusted. Get root CA and 162 * check for explicit trust 163 */ 164 if (flags & OCSP_NOEXPLICIT) 165 goto end; 166 167 x = sk_X509_value(chain, sk_X509_num(chain) - 1); 168 if (X509_check_trust(x, NID_OCSP_sign, 0) != 169 X509_TRUST_TRUSTED) { 170 OCSPerror(OCSP_R_ROOT_CA_NOT_TRUSTED); 171 goto end; 172 } 173 ret = 1; 174 } 175 176end: 177 if (chain) 178 sk_X509_pop_free(chain, X509_free); 179 if (bs->certs && certs) 180 sk_X509_free(untrusted); 181 return ret; 182} 183 184int 185OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer, 186 STACK_OF(X509) *extra_certs) 187{ 188 return ocsp_find_signer(signer, bs, extra_certs, NULL, 0) > 0; 189} 190 191static int 192ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 193 X509_STORE *st, unsigned long flags) 194{ 195 X509 *signer; 196 OCSP_RESPID *rid = bs->tbsResponseData->responderId; 197 198 if ((signer = ocsp_find_signer_sk(certs, rid))) { 199 *psigner = signer; 200 return 2; 201 } 202 if (!(flags & OCSP_NOINTERN) && 203 (signer = ocsp_find_signer_sk(bs->certs, rid))) { 204 *psigner = signer; 205 return 1; 206 } 207 /* Maybe lookup from store if by subject name */ 208 209 *psigner = NULL; 210 return 0; 211} 212 213static X509 * 214ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) 215{ 216 int i; 217 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 218 X509 *x; 219 220 /* Easy if lookup by name */ 221 if (id->type == V_OCSP_RESPID_NAME) 222 return X509_find_by_subject(certs, id->value.byName); 223 224 /* Lookup by key hash */ 225 226 /* If key hash isn't SHA1 length then forget it */ 227 if (id->value.byKey->length != SHA_DIGEST_LENGTH) 228 return NULL; 229 keyhash = id->value.byKey->data; 230 /* Calculate hash of each key and compare */ 231 for (i = 0; i < sk_X509_num(certs); i++) { 232 x = sk_X509_value(certs, i); 233 X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 234 if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 235 return x; 236 } 237 return NULL; 238} 239 240static int 241ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, 242 unsigned long flags) 243{ 244 STACK_OF(OCSP_SINGLERESP) *sresp; 245 X509 *signer, *sca; 246 OCSP_CERTID *caid = NULL; 247 int i; 248 249 sresp = bs->tbsResponseData->responses; 250 251 if (sk_X509_num(chain) <= 0) { 252 OCSPerror(OCSP_R_NO_CERTIFICATES_IN_CHAIN); 253 return -1; 254 } 255 256 /* See if the issuer IDs match. */ 257 i = ocsp_check_ids(sresp, &caid); 258 259 /* If ID mismatch or other error then return */ 260 if (i <= 0) 261 return i; 262 263 signer = sk_X509_value(chain, 0); 264 /* Check to see if OCSP responder CA matches request CA */ 265 if (sk_X509_num(chain) > 1) { 266 sca = sk_X509_value(chain, 1); 267 i = ocsp_match_issuerid(sca, caid, sresp); 268 if (i < 0) 269 return i; 270 if (i) { 271 /* We have a match, if extensions OK then success */ 272 if (ocsp_check_delegated(signer, flags)) 273 return 1; 274 return 0; 275 } 276 } 277 278 /* Otherwise check if OCSP request signed directly by request CA */ 279 return ocsp_match_issuerid(signer, caid, sresp); 280} 281 282/* Check the issuer certificate IDs for equality. If there is a mismatch with the same 283 * algorithm then there's no point trying to match any certificates against the issuer. 284 * If the issuer IDs all match then we just need to check equality against one of them. 285 */ 286static int 287ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret) 288{ 289 OCSP_CERTID *tmpid, *cid; 290 int i, idcount; 291 292 idcount = sk_OCSP_SINGLERESP_num(sresp); 293 if (idcount <= 0) { 294 OCSPerror(OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA); 295 return -1; 296 } 297 298 cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; 299 300 *ret = NULL; 301 302 for (i = 1; i < idcount; i++) { 303 tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; 304 /* Check to see if IDs match */ 305 if (OCSP_id_issuer_cmp(cid, tmpid)) { 306 return 0; 307 } 308 } 309 310 /* All IDs match: only need to check one ID */ 311 *ret = cid; 312 return 1; 313} 314 315static int 316ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, 317 STACK_OF(OCSP_SINGLERESP) *sresp) 318{ 319 /* If only one ID to match then do it */ 320 if (cid) { 321 const EVP_MD *dgst; 322 X509_NAME *iname; 323 int mdlen; 324 unsigned char md[EVP_MAX_MD_SIZE]; 325 326 if (!(dgst = 327 EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) { 328 OCSPerror(OCSP_R_UNKNOWN_MESSAGE_DIGEST); 329 return -1; 330 } 331 332 mdlen = EVP_MD_size(dgst); 333 if (mdlen < 0) 334 return -1; 335 if (cid->issuerNameHash->length != mdlen || 336 cid->issuerKeyHash->length != mdlen) 337 return 0; 338 iname = X509_get_subject_name(cert); 339 if (!X509_NAME_digest(iname, dgst, md, NULL)) 340 return -1; 341 if (memcmp(md, cid->issuerNameHash->data, mdlen)) 342 return 0; 343 X509_pubkey_digest(cert, dgst, md, NULL); 344 if (memcmp(md, cid->issuerKeyHash->data, mdlen)) 345 return 0; 346 347 return 1; 348 } else { 349 /* We have to match the whole lot */ 350 int i, ret; 351 OCSP_CERTID *tmpid; 352 353 for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) { 354 tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; 355 ret = ocsp_match_issuerid(cert, tmpid, NULL); 356 if (ret <= 0) 357 return ret; 358 } 359 return 1; 360 } 361} 362 363static int 364ocsp_check_delegated(X509 *x, int flags) 365{ 366 X509_check_purpose(x, -1, 0); 367 if ((x->ex_flags & EXFLAG_XKUSAGE) && (x->ex_xkusage & XKU_OCSP_SIGN)) 368 return 1; 369 OCSPerror(OCSP_R_MISSING_OCSPSIGNING_USAGE); 370 return 0; 371} 372 373/* Verify an OCSP request. This is fortunately much easier than OCSP 374 * response verify. Just find the signers certificate and verify it 375 * against a given trust value. 376 */ 377int 378OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, 379 unsigned long flags) 380{ 381 X509 *signer; 382 X509_NAME *nm; 383 GENERAL_NAME *gen; 384 int ret; 385 X509_STORE_CTX ctx; 386 387 if (!req->optionalSignature) { 388 OCSPerror(OCSP_R_REQUEST_NOT_SIGNED); 389 return 0; 390 } 391 gen = req->tbsRequest->requestorName; 392 if (!gen || gen->type != GEN_DIRNAME) { 393 OCSPerror(OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE); 394 return 0; 395 } 396 nm = gen->d.directoryName; 397 ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags); 398 if (ret <= 0) { 399 OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); 400 return 0; 401 } 402 if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) 403 flags |= OCSP_NOVERIFY; 404 if (!(flags & OCSP_NOSIGS)) { 405 EVP_PKEY *skey; 406 407 skey = X509_get_pubkey(signer); 408 ret = OCSP_REQUEST_verify(req, skey); 409 EVP_PKEY_free(skey); 410 if (ret <= 0) { 411 OCSPerror(OCSP_R_SIGNATURE_FAILURE); 412 return 0; 413 } 414 } 415 if (!(flags & OCSP_NOVERIFY)) { 416 int init_res; 417 418 if (flags & OCSP_NOCHAIN) 419 init_res = X509_STORE_CTX_init(&ctx, store, signer, 420 NULL); 421 else 422 init_res = X509_STORE_CTX_init(&ctx, store, signer, 423 req->optionalSignature->certs); 424 if (!init_res) { 425 OCSPerror(ERR_R_X509_LIB); 426 return 0; 427 } 428 429 if (X509_STORE_CTX_set_purpose(&ctx, 430 X509_PURPOSE_OCSP_HELPER) == 0 || 431 X509_STORE_CTX_set_trust(&ctx, 432 X509_TRUST_OCSP_REQUEST) == 0) { 433 X509_STORE_CTX_cleanup(&ctx); 434 return 0; 435 } 436 ret = X509_verify_cert(&ctx); 437 X509_STORE_CTX_cleanup(&ctx); 438 if (ret <= 0) { 439 ret = X509_STORE_CTX_get_error(&ctx); 440 OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR); 441 ERR_asprintf_error_data("Verify error:%s", 442 X509_verify_cert_error_string(ret)); 443 return 0; 444 } 445 } 446 return 1; 447} 448 449static int 450ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, 451 STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags) 452{ 453 X509 *signer; 454 455 if (!(flags & OCSP_NOINTERN)) { 456 signer = X509_find_by_subject(req->optionalSignature->certs, nm); 457 if (signer) { 458 *psigner = signer; 459 return 1; 460 } 461 } 462 463 signer = X509_find_by_subject(certs, nm); 464 if (signer) { 465 *psigner = signer; 466 return 2; 467 } 468 return 0; 469} 470