ocsp_vfy.c revision 1.18
1/* $OpenBSD: ocsp_vfy.c,v 1.18 2021/11/24 19:29:19 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_get0_pubkey(signer); 100 if (skey) { 101 ret = OCSP_BASICRESP_verify(bs, skey, 0); 102 } 103 if (!skey || ret <= 0) { 104 OCSPerror(OCSP_R_SIGNATURE_FAILURE); 105 goto end; 106 } 107 } 108 if (!(flags & OCSP_NOVERIFY)) { 109 int init_res; 110 111 if (flags & OCSP_NOCHAIN) { 112 untrusted = NULL; 113 } else if (bs->certs && certs) { 114 untrusted = sk_X509_dup(bs->certs); 115 for (i = 0; i < sk_X509_num(certs); i++) { 116 if (!sk_X509_push(untrusted, 117 sk_X509_value(certs, i))) { 118 OCSPerror(ERR_R_MALLOC_FAILURE); 119 goto end; 120 } 121 } 122 } else 123 untrusted = bs->certs; 124 init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted); 125 if (!init_res) { 126 ret = -1; 127 OCSPerror(ERR_R_X509_LIB); 128 goto end; 129 } 130 131 if (X509_STORE_CTX_set_purpose(&ctx, 132 X509_PURPOSE_OCSP_HELPER) == 0) { 133 X509_STORE_CTX_cleanup(&ctx); 134 ret = -1; 135 goto end; 136 } 137 ret = X509_verify_cert(&ctx); 138 chain = X509_STORE_CTX_get1_chain(&ctx); 139 X509_STORE_CTX_cleanup(&ctx); 140 if (ret <= 0) { 141 i = X509_STORE_CTX_get_error(&ctx); 142 OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR); 143 ERR_asprintf_error_data("Verify error:%s", 144 X509_verify_cert_error_string(i)); 145 goto end; 146 } 147 if (flags & OCSP_NOCHECKS) { 148 ret = 1; 149 goto end; 150 } 151 /* At this point we have a valid certificate chain 152 * need to verify it against the OCSP issuer criteria. 153 */ 154 ret = ocsp_check_issuer(bs, chain, flags); 155 156 /* If fatal error or valid match then finish */ 157 if (ret != 0) 158 goto end; 159 160 /* Easy case: explicitly trusted. Get root CA and 161 * check for explicit trust 162 */ 163 if (flags & OCSP_NOEXPLICIT) 164 goto end; 165 166 x = sk_X509_value(chain, sk_X509_num(chain) - 1); 167 if (X509_check_trust(x, NID_OCSP_sign, 0) != 168 X509_TRUST_TRUSTED) { 169 OCSPerror(OCSP_R_ROOT_CA_NOT_TRUSTED); 170 goto end; 171 } 172 ret = 1; 173 } 174 175end: 176 if (chain) 177 sk_X509_pop_free(chain, X509_free); 178 if (bs->certs && certs) 179 sk_X509_free(untrusted); 180 return ret; 181} 182 183int 184OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer, 185 STACK_OF(X509) *extra_certs) 186{ 187 return ocsp_find_signer(signer, bs, extra_certs, NULL, 0) > 0; 188} 189 190static int 191ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 192 X509_STORE *st, unsigned long flags) 193{ 194 X509 *signer; 195 OCSP_RESPID *rid = bs->tbsResponseData->responderId; 196 197 if ((signer = ocsp_find_signer_sk(certs, rid))) { 198 *psigner = signer; 199 return 2; 200 } 201 if (!(flags & OCSP_NOINTERN) && 202 (signer = ocsp_find_signer_sk(bs->certs, rid))) { 203 *psigner = signer; 204 return 1; 205 } 206 /* Maybe lookup from store if by subject name */ 207 208 *psigner = NULL; 209 return 0; 210} 211 212static X509 * 213ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) 214{ 215 int i; 216 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 217 X509 *x; 218 219 /* Easy if lookup by name */ 220 if (id->type == V_OCSP_RESPID_NAME) 221 return X509_find_by_subject(certs, id->value.byName); 222 223 /* Lookup by key hash */ 224 225 /* If key hash isn't SHA1 length then forget it */ 226 if (id->value.byKey->length != SHA_DIGEST_LENGTH) 227 return NULL; 228 keyhash = id->value.byKey->data; 229 /* Calculate hash of each key and compare */ 230 for (i = 0; i < sk_X509_num(certs); i++) { 231 x = sk_X509_value(certs, i); 232 X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 233 if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 234 return x; 235 } 236 return NULL; 237} 238 239static int 240ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, 241 unsigned long flags) 242{ 243 STACK_OF(OCSP_SINGLERESP) *sresp; 244 X509 *signer, *sca; 245 OCSP_CERTID *caid = NULL; 246 int i; 247 248 sresp = bs->tbsResponseData->responses; 249 250 if (sk_X509_num(chain) <= 0) { 251 OCSPerror(OCSP_R_NO_CERTIFICATES_IN_CHAIN); 252 return -1; 253 } 254 255 /* See if the issuer IDs match. */ 256 i = ocsp_check_ids(sresp, &caid); 257 258 /* If ID mismatch or other error then return */ 259 if (i <= 0) 260 return i; 261 262 signer = sk_X509_value(chain, 0); 263 /* Check to see if OCSP responder CA matches request CA */ 264 if (sk_X509_num(chain) > 1) { 265 sca = sk_X509_value(chain, 1); 266 i = ocsp_match_issuerid(sca, caid, sresp); 267 if (i < 0) 268 return i; 269 if (i) { 270 /* We have a match, if extensions OK then success */ 271 if (ocsp_check_delegated(signer, flags)) 272 return 1; 273 return 0; 274 } 275 } 276 277 /* Otherwise check if OCSP request signed directly by request CA */ 278 return ocsp_match_issuerid(signer, caid, sresp); 279} 280 281/* Check the issuer certificate IDs for equality. If there is a mismatch with the same 282 * algorithm then there's no point trying to match any certificates against the issuer. 283 * If the issuer IDs all match then we just need to check equality against one of them. 284 */ 285static int 286ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret) 287{ 288 OCSP_CERTID *tmpid, *cid; 289 int i, idcount; 290 291 idcount = sk_OCSP_SINGLERESP_num(sresp); 292 if (idcount <= 0) { 293 OCSPerror(OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA); 294 return -1; 295 } 296 297 cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; 298 299 *ret = NULL; 300 301 for (i = 1; i < idcount; i++) { 302 tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; 303 /* Check to see if IDs match */ 304 if (OCSP_id_issuer_cmp(cid, tmpid)) { 305 return 0; 306 } 307 } 308 309 /* All IDs match: only need to check one ID */ 310 *ret = cid; 311 return 1; 312} 313 314static int 315ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, 316 STACK_OF(OCSP_SINGLERESP) *sresp) 317{ 318 /* If only one ID to match then do it */ 319 if (cid) { 320 const EVP_MD *dgst; 321 X509_NAME *iname; 322 int mdlen; 323 unsigned char md[EVP_MAX_MD_SIZE]; 324 325 if (!(dgst = 326 EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) { 327 OCSPerror(OCSP_R_UNKNOWN_MESSAGE_DIGEST); 328 return -1; 329 } 330 331 mdlen = EVP_MD_size(dgst); 332 if (mdlen < 0) 333 return -1; 334 if (cid->issuerNameHash->length != mdlen || 335 cid->issuerKeyHash->length != mdlen) 336 return 0; 337 iname = X509_get_subject_name(cert); 338 if (!X509_NAME_digest(iname, dgst, md, NULL)) 339 return -1; 340 if (memcmp(md, cid->issuerNameHash->data, mdlen)) 341 return 0; 342 X509_pubkey_digest(cert, dgst, md, NULL); 343 if (memcmp(md, cid->issuerKeyHash->data, mdlen)) 344 return 0; 345 346 return 1; 347 } else { 348 /* We have to match the whole lot */ 349 int i, ret; 350 OCSP_CERTID *tmpid; 351 352 for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) { 353 tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; 354 ret = ocsp_match_issuerid(cert, tmpid, NULL); 355 if (ret <= 0) 356 return ret; 357 } 358 return 1; 359 } 360} 361 362static int 363ocsp_check_delegated(X509 *x, int flags) 364{ 365 X509_check_purpose(x, -1, 0); 366 if ((x->ex_flags & EXFLAG_XKUSAGE) && (x->ex_xkusage & XKU_OCSP_SIGN)) 367 return 1; 368 OCSPerror(OCSP_R_MISSING_OCSPSIGNING_USAGE); 369 return 0; 370} 371 372/* Verify an OCSP request. This is fortunately much easier than OCSP 373 * response verify. Just find the signers certificate and verify it 374 * against a given trust value. 375 */ 376int 377OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, X509_STORE *store, 378 unsigned long flags) 379{ 380 X509 *signer; 381 X509_NAME *nm; 382 GENERAL_NAME *gen; 383 int ret; 384 X509_STORE_CTX ctx; 385 386 if (!req->optionalSignature) { 387 OCSPerror(OCSP_R_REQUEST_NOT_SIGNED); 388 return 0; 389 } 390 gen = req->tbsRequest->requestorName; 391 if (!gen || gen->type != GEN_DIRNAME) { 392 OCSPerror(OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE); 393 return 0; 394 } 395 nm = gen->d.directoryName; 396 ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags); 397 if (ret <= 0) { 398 OCSPerror(OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); 399 return 0; 400 } 401 if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) 402 flags |= OCSP_NOVERIFY; 403 if (!(flags & OCSP_NOSIGS)) { 404 EVP_PKEY *skey; 405 406 skey = X509_get_pubkey(signer); 407 ret = OCSP_REQUEST_verify(req, skey); 408 EVP_PKEY_free(skey); 409 if (ret <= 0) { 410 OCSPerror(OCSP_R_SIGNATURE_FAILURE); 411 return 0; 412 } 413 } 414 if (!(flags & OCSP_NOVERIFY)) { 415 int init_res; 416 417 if (flags & OCSP_NOCHAIN) 418 init_res = X509_STORE_CTX_init(&ctx, store, signer, 419 NULL); 420 else 421 init_res = X509_STORE_CTX_init(&ctx, store, signer, 422 req->optionalSignature->certs); 423 if (!init_res) { 424 OCSPerror(ERR_R_X509_LIB); 425 return 0; 426 } 427 428 if (X509_STORE_CTX_set_purpose(&ctx, 429 X509_PURPOSE_OCSP_HELPER) == 0 || 430 X509_STORE_CTX_set_trust(&ctx, 431 X509_TRUST_OCSP_REQUEST) == 0) { 432 X509_STORE_CTX_cleanup(&ctx); 433 return 0; 434 } 435 ret = X509_verify_cert(&ctx); 436 X509_STORE_CTX_cleanup(&ctx); 437 if (ret <= 0) { 438 ret = X509_STORE_CTX_get_error(&ctx); 439 OCSPerror(OCSP_R_CERTIFICATE_VERIFY_ERROR); 440 ERR_asprintf_error_data("Verify error:%s", 441 X509_verify_cert_error_string(ret)); 442 return 0; 443 } 444 } 445 return 1; 446} 447 448static int 449ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, X509_NAME *nm, 450 STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags) 451{ 452 X509 *signer; 453 454 if (!(flags & OCSP_NOINTERN)) { 455 signer = X509_find_by_subject(req->optionalSignature->certs, nm); 456 if (signer) { 457 *psigner = signer; 458 return 1; 459 } 460 } 461 462 signer = X509_find_by_subject(certs, nm); 463 if (signer) { 464 *psigner = signer; 465 return 2; 466 } 467 return 0; 468} 469