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