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