ocsp_vfy.c revision 296465
1193323Sed/* ocsp_vfy.c */ 2193323Sed/* 3193323Sed * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4193323Sed * 2000. 5193323Sed */ 6193323Sed/* ==================================================================== 7193323Sed * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved. 8193323Sed * 9193323Sed * Redistribution and use in source and binary forms, with or without 10193323Sed * modification, are permitted provided that the following conditions 11193323Sed * are met: 12193323Sed * 13193323Sed * 1. Redistributions of source code must retain the above copyright 14193323Sed * notice, this list of conditions and the following disclaimer. 15193323Sed * 16193323Sed * 2. Redistributions in binary form must reproduce the above copyright 17193323Sed * notice, this list of conditions and the following disclaimer in 18193323Sed * the documentation and/or other materials provided with the 19249423Sdim * distribution. 20193323Sed * 21198090Srdivacky * 3. All advertising materials mentioning features or use of this 22249423Sdim * software must display the following acknowledgment: 23249423Sdim * "This product includes software developed by the OpenSSL Project 24249423Sdim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25193323Sed * 26193323Sed * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27226633Sdim * endorse or promote products derived from this software without 28239462Sdim * prior written permission. For written permission, please contact 29193323Sed * licensing@OpenSSL.org. 30193323Sed * 31193323Sed * 5. Products derived from this software may not be called "OpenSSL" 32193323Sed * nor may "OpenSSL" appear in their names without prior written 33193323Sed * permission of the OpenSSL Project. 34193323Sed * 35193323Sed * 6. Redistributions of any form whatsoever must retain the following 36198892Srdivacky * acknowledgment: 37193323Sed * "This product includes software developed by the OpenSSL Project 38193323Sed * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39193323Sed * 40193323Sed * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41218893Sdim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42218893Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43218893Sdim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44193323Sed * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45198090Srdivacky * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46193323Sed * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47193323Sed * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49193323Sed * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50193323Sed * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51193323Sed * OF THE POSSIBILITY OF SUCH DAMAGE. 52193323Sed * ==================================================================== 53193323Sed * 54193323Sed * This product includes cryptographic software written by Eric Young 55193323Sed * (eay@cryptsoft.com). This product includes software written by Tim 56218893Sdim * Hudson (tjh@cryptsoft.com). 57226633Sdim * 58218893Sdim */ 59218893Sdim 60218893Sdim#include <openssl/ocsp.h> 61218893Sdim#include <openssl/err.h> 62226633Sdim#include <string.h> 63193323Sed 64193323Sedstatic int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, 65193323Sed STACK_OF(X509) *certs, X509_STORE *st, 66193323Sed unsigned long flags); 67193323Sedstatic X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id); 68193323Sedstatic int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, 69193323Sed unsigned long flags); 70193323Sedstatic int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, 71193323Sed OCSP_CERTID **ret); 72193323Sedstatic int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, 73212904Sdim STACK_OF(OCSP_SINGLERESP) *sresp); 74218893Sdimstatic int ocsp_check_delegated(X509 *x, int flags); 75193323Sedstatic int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, 76193323Sed X509_NAME *nm, STACK_OF(X509) *certs, 77193323Sed X509_STORE *st, unsigned long flags); 78193323Sed 79198090Srdivacky/* Verify a basic response message */ 80193323Sed 81198090Srdivackyint OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 82198090Srdivacky X509_STORE *st, unsigned long flags) 83198090Srdivacky{ 84193323Sed X509 *signer, *x; 85193323Sed STACK_OF(X509) *chain = NULL; 86199481Srdivacky STACK_OF(X509) *untrusted = NULL; 87199481Srdivacky X509_STORE_CTX ctx; 88199481Srdivacky int i, ret = 0; 89199481Srdivacky ret = ocsp_find_signer(&signer, bs, certs, st, flags); 90193323Sed if (!ret) { 91198090Srdivacky OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, 92193323Sed OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); 93193323Sed goto end; 94198090Srdivacky } 95198090Srdivacky if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) 96198090Srdivacky flags |= OCSP_NOVERIFY; 97198090Srdivacky if (!(flags & OCSP_NOSIGS)) { 98193323Sed EVP_PKEY *skey; 99198090Srdivacky skey = X509_get_pubkey(signer); 100198090Srdivacky if (skey) { 101198090Srdivacky ret = OCSP_BASICRESP_verify(bs, skey, 0); 102198090Srdivacky EVP_PKEY_free(skey); 103198090Srdivacky } 104226633Sdim if (!skey || ret <= 0) { 105198090Srdivacky OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE); 106226633Sdim goto end; 107198090Srdivacky } 108198090Srdivacky } 109198090Srdivacky if (!(flags & OCSP_NOVERIFY)) { 110198090Srdivacky int init_res; 111198090Srdivacky if (flags & OCSP_NOCHAIN) { 112198090Srdivacky untrusted = NULL; 113198090Srdivacky } else if (bs->certs && certs) { 114198090Srdivacky untrusted = sk_X509_dup(bs->certs); 115193323Sed for (i = 0; i < sk_X509_num(certs); i++) { 116198090Srdivacky if (!sk_X509_push(untrusted, sk_X509_value(certs, i))) { 117226633Sdim OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_MALLOC_FAILURE); 118198090Srdivacky goto end; 119226633Sdim } 120226633Sdim } 121226633Sdim } else { 122226633Sdim untrusted = bs->certs; 123226633Sdim } 124226633Sdim init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted); 125226633Sdim if (!init_res) { 126226633Sdim ret = -1; 127226633Sdim OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_X509_LIB); 128226633Sdim goto end; 129226633Sdim } 130226633Sdim 131226633Sdim X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER); 132226633Sdim ret = X509_verify_cert(&ctx); 133198090Srdivacky chain = X509_STORE_CTX_get1_chain(&ctx); 134198090Srdivacky X509_STORE_CTX_cleanup(&ctx); 135239462Sdim if (ret <= 0) { 136239462Sdim i = X509_STORE_CTX_get_error(&ctx); 137198090Srdivacky OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, 138198090Srdivacky OCSP_R_CERTIFICATE_VERIFY_ERROR); 139198090Srdivacky ERR_add_error_data(2, "Verify error:", 140198090Srdivacky X509_verify_cert_error_string(i)); 141193323Sed goto end; 142198090Srdivacky } 143193323Sed if (flags & OCSP_NOCHECKS) { 144193323Sed ret = 1; 145193323Sed goto end; 146193323Sed } 147193323Sed /* 148193323Sed * At this point we have a valid certificate chain need to verify it 149193323Sed * against the OCSP issuer criteria. 150193323Sed */ 151198090Srdivacky ret = ocsp_check_issuer(bs, chain, flags); 152193323Sed 153193323Sed /* If fatal error or valid match then finish */ 154193323Sed if (ret != 0) 155193323Sed goto end; 156193323Sed 157193323Sed /* 158193323Sed * Easy case: explicitly trusted. Get root CA and check for explicit 159193323Sed * trust 160193323Sed */ 161193323Sed if (flags & OCSP_NOEXPLICIT) 162193323Sed goto end; 163193323Sed 164193323Sed x = sk_X509_value(chain, sk_X509_num(chain) - 1); 165193323Sed if (X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED) { 166193323Sed OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_ROOT_CA_NOT_TRUSTED); 167193323Sed goto end; 168193323Sed } 169226633Sdim ret = 1; 170193323Sed } 171193323Sed 172193323Sed end: 173193323Sed if (chain) 174193323Sed sk_X509_pop_free(chain, X509_free); 175212904Sdim if (bs->certs && certs) 176193323Sed sk_X509_free(untrusted); 177193323Sed return ret; 178193323Sed} 179193323Sed 180193323Sedstatic int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, 181193323Sed STACK_OF(X509) *certs, X509_STORE *st, 182193323Sed unsigned long flags) 183193323Sed{ 184193323Sed X509 *signer; 185212904Sdim OCSP_RESPID *rid = bs->tbsResponseData->responderId; 186212904Sdim if ((signer = ocsp_find_signer_sk(certs, rid))) { 187218893Sdim *psigner = signer; 188193323Sed return 2; 189193323Sed } 190193323Sed if (!(flags & OCSP_NOINTERN) && 191193323Sed (signer = ocsp_find_signer_sk(bs->certs, rid))) { 192226633Sdim *psigner = signer; 193212904Sdim return 1; 194193323Sed } 195193323Sed /* Maybe lookup from store if by subject name */ 196193323Sed 197193323Sed *psigner = NULL; 198193323Sed return 0; 199193323Sed} 200198090Srdivacky 201198090Srdivackystatic X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) 202193323Sed{ 203193323Sed int i; 204193323Sed unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 205193323Sed X509 *x; 206193323Sed 207193323Sed /* Easy if lookup by name */ 208193323Sed if (id->type == V_OCSP_RESPID_NAME) 209193323Sed return X509_find_by_subject(certs, id->value.byName); 210193323Sed 211193323Sed /* Lookup by key hash */ 212193323Sed 213193323Sed /* If key hash isn't SHA1 length then forget it */ 214226633Sdim if (id->value.byKey->length != SHA_DIGEST_LENGTH) 215226633Sdim return NULL; 216226633Sdim keyhash = id->value.byKey->data; 217226633Sdim /* Calculate hash of each key and compare */ 218226633Sdim for (i = 0; i < sk_X509_num(certs); i++) { 219226633Sdim x = sk_X509_value(certs, i); 220226633Sdim X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 221226633Sdim if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 222226633Sdim return x; 223226633Sdim } 224226633Sdim return NULL; 225226633Sdim} 226226633Sdim 227226633Sdimstatic int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, 228226633Sdim unsigned long flags) 229226633Sdim{ 230226633Sdim STACK_OF(OCSP_SINGLERESP) *sresp; 231226633Sdim X509 *signer, *sca; 232226633Sdim OCSP_CERTID *caid = NULL; 233226633Sdim int i; 234226633Sdim sresp = bs->tbsResponseData->responses; 235226633Sdim 236226633Sdim if (sk_X509_num(chain) <= 0) { 237226633Sdim OCSPerr(OCSP_F_OCSP_CHECK_ISSUER, OCSP_R_NO_CERTIFICATES_IN_CHAIN); 238226633Sdim return -1; 239226633Sdim } 240226633Sdim 241226633Sdim /* See if the issuer IDs match. */ 242226633Sdim i = ocsp_check_ids(sresp, &caid); 243226633Sdim 244226633Sdim /* If ID mismatch or other error then return */ 245193323Sed if (i <= 0) 246193323Sed return i; 247193323Sed 248193323Sed signer = sk_X509_value(chain, 0); 249193323Sed /* Check to see if OCSP responder CA matches request CA */ 250193323Sed if (sk_X509_num(chain) > 1) { 251193323Sed sca = sk_X509_value(chain, 1); 252193323Sed i = ocsp_match_issuerid(sca, caid, sresp); 253193323Sed if (i < 0) 254193323Sed return i; 255193323Sed if (i) { 256193323Sed /* We have a match, if extensions OK then success */ 257193323Sed if (ocsp_check_delegated(signer, flags)) 258193323Sed return 1; 259193323Sed return 0; 260193323Sed } 261193323Sed } 262193323Sed 263193323Sed /* Otherwise check if OCSP request signed directly by request CA */ 264193323Sed return ocsp_match_issuerid(signer, caid, sresp); 265193323Sed} 266193323Sed 267193323Sed/* 268193323Sed * Check the issuer certificate IDs for equality. If there is a mismatch with 269193323Sed * the same algorithm then there's no point trying to match any certificates 270193323Sed * against the issuer. If the issuer IDs all match then we just need to check 271193323Sed * equality against one of them. 272193323Sed */ 273193323Sed 274193323Sedstatic int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret) 275193323Sed{ 276193323Sed OCSP_CERTID *tmpid, *cid; 277193323Sed int i, idcount; 278193323Sed 279193323Sed idcount = sk_OCSP_SINGLERESP_num(sresp); 280193323Sed if (idcount <= 0) { 281193323Sed OCSPerr(OCSP_F_OCSP_CHECK_IDS, 282193323Sed OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA); 283193323Sed return -1; 284193323Sed } 285193323Sed 286193323Sed cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; 287226633Sdim 288226633Sdim *ret = NULL; 289193323Sed 290193323Sed for (i = 1; i < idcount; i++) { 291193323Sed tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; 292226633Sdim /* Check to see if IDs match */ 293193323Sed if (OCSP_id_issuer_cmp(cid, tmpid)) { 294226633Sdim /* If algoritm mismatch let caller deal with it */ 295226633Sdim if (OBJ_cmp(tmpid->hashAlgorithm->algorithm, 296226633Sdim cid->hashAlgorithm->algorithm)) 297226633Sdim return 2; 298226633Sdim /* Else mismatch */ 299226633Sdim return 0; 300239462Sdim } 301226633Sdim } 302193323Sed 303193323Sed /* All IDs match: only need to check one ID */ 304193323Sed *ret = cid; 305 return 1; 306} 307 308static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, 309 STACK_OF(OCSP_SINGLERESP) *sresp) 310{ 311 /* If only one ID to match then do it */ 312 if (cid) { 313 const EVP_MD *dgst; 314 X509_NAME *iname; 315 int mdlen; 316 unsigned char md[EVP_MAX_MD_SIZE]; 317 if (!(dgst = EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) { 318 OCSPerr(OCSP_F_OCSP_MATCH_ISSUERID, 319 OCSP_R_UNKNOWN_MESSAGE_DIGEST); 320 return -1; 321 } 322 323 mdlen = EVP_MD_size(dgst); 324 if ((cid->issuerNameHash->length != mdlen) || 325 (cid->issuerKeyHash->length != mdlen)) 326 return 0; 327 iname = X509_get_subject_name(cert); 328 if (!X509_NAME_digest(iname, dgst, md, NULL)) 329 return -1; 330 if (memcmp(md, cid->issuerNameHash->data, mdlen)) 331 return 0; 332 X509_pubkey_digest(cert, EVP_sha1(), md, NULL); 333 if (memcmp(md, cid->issuerKeyHash->data, mdlen)) 334 return 0; 335 336 return 1; 337 338 } else { 339 /* We have to match the whole lot */ 340 int i, ret; 341 OCSP_CERTID *tmpid; 342 for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) { 343 tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; 344 ret = ocsp_match_issuerid(cert, tmpid, NULL); 345 if (ret <= 0) 346 return ret; 347 } 348 return 1; 349 } 350 351} 352 353static int ocsp_check_delegated(X509 *x, int flags) 354{ 355 X509_check_purpose(x, -1, 0); 356 if ((x->ex_flags & EXFLAG_XKUSAGE) && (x->ex_xkusage & XKU_OCSP_SIGN)) 357 return 1; 358 OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE); 359 return 0; 360} 361 362/* 363 * Verify an OCSP request. This is fortunately much easier than OCSP response 364 * verify. Just find the signers certificate and verify it against a given 365 * trust value. 366 */ 367 368int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, 369 X509_STORE *store, unsigned long flags) 370{ 371 X509 *signer; 372 X509_NAME *nm; 373 GENERAL_NAME *gen; 374 int ret; 375 X509_STORE_CTX ctx; 376 if (!req->optionalSignature) { 377 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED); 378 return 0; 379 } 380 gen = req->tbsRequest->requestorName; 381 if (!gen || gen->type != GEN_DIRNAME) { 382 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 383 OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE); 384 return 0; 385 } 386 nm = gen->d.directoryName; 387 ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags); 388 if (ret <= 0) { 389 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 390 OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); 391 return 0; 392 } 393 if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) 394 flags |= OCSP_NOVERIFY; 395 if (!(flags & OCSP_NOSIGS)) { 396 EVP_PKEY *skey; 397 skey = X509_get_pubkey(signer); 398 ret = OCSP_REQUEST_verify(req, skey); 399 EVP_PKEY_free(skey); 400 if (ret <= 0) { 401 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE); 402 return 0; 403 } 404 } 405 if (!(flags & OCSP_NOVERIFY)) { 406 int init_res; 407 if (flags & OCSP_NOCHAIN) 408 init_res = X509_STORE_CTX_init(&ctx, store, signer, NULL); 409 else 410 init_res = X509_STORE_CTX_init(&ctx, store, signer, 411 req->optionalSignature->certs); 412 if (!init_res) { 413 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_X509_LIB); 414 return 0; 415 } 416 417 X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER); 418 X509_STORE_CTX_set_trust(&ctx, X509_TRUST_OCSP_REQUEST); 419 ret = X509_verify_cert(&ctx); 420 X509_STORE_CTX_cleanup(&ctx); 421 if (ret <= 0) { 422 ret = X509_STORE_CTX_get_error(&ctx); 423 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 424 OCSP_R_CERTIFICATE_VERIFY_ERROR); 425 ERR_add_error_data(2, "Verify error:", 426 X509_verify_cert_error_string(ret)); 427 return 0; 428 } 429 } 430 return 1; 431} 432 433static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, 434 X509_NAME *nm, STACK_OF(X509) *certs, 435 X509_STORE *st, unsigned long flags) 436{ 437 X509 *signer; 438 if (!(flags & OCSP_NOINTERN)) { 439 signer = X509_find_by_subject(req->optionalSignature->certs, nm); 440 *psigner = signer; 441 return 1; 442 } 443 444 signer = X509_find_by_subject(certs, nm); 445 if (signer) { 446 *psigner = signer; 447 return 2; 448 } 449 return 0; 450} 451