ocsp_vfy.c revision 1.14
1/* $OpenBSD: ocsp_vfy.c,v 1.14 2016/11/05 13:27:53 miod 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 63static int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, 64 STACK_OF(X509) *certs, X509_STORE *st, unsigned long flags); 65static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id); 66static int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, 67 unsigned long flags); 68static int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret); 69static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, 70 STACK_OF(OCSP_SINGLERESP) *sresp); 71static int ocsp_check_delegated(X509 *x, int flags); 72static int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, 73 X509_NAME *nm, STACK_OF(X509) *certs, X509_STORE *st, 74 unsigned long flags); 75 76/* Verify a basic response message */ 77int 78OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, X509_STORE *st, 79 unsigned long flags) 80{ 81 X509 *signer, *x; 82 STACK_OF(X509) *chain = NULL; 83 STACK_OF(X509) *untrusted = NULL; 84 X509_STORE_CTX ctx; 85 int i, ret = 0; 86 87 ret = ocsp_find_signer(&signer, bs, certs, st, flags); 88 if (!ret) { 89 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, 90 OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); 91 goto end; 92 } 93 if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) 94 flags |= OCSP_NOVERIFY; 95 if (!(flags & OCSP_NOSIGS)) { 96 EVP_PKEY *skey; 97 98 skey = X509_get_pubkey(signer); 99 if (skey) { 100 ret = OCSP_BASICRESP_verify(bs, skey, 0); 101 EVP_PKEY_free(skey); 102 } 103 if (!skey || ret <= 0) { 104 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, 105 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 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, 120 ERR_R_MALLOC_FAILURE); 121 goto end; 122 } 123 } 124 } else 125 untrusted = bs->certs; 126 init_res = X509_STORE_CTX_init(&ctx, st, signer, untrusted); 127 if (!init_res) { 128 ret = -1; 129 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_X509_LIB); 130 goto end; 131 } 132 133 if (X509_STORE_CTX_set_purpose(&ctx, 134 X509_PURPOSE_OCSP_HELPER) == 0) { 135 X509_STORE_CTX_cleanup(&ctx); 136 ret = -1; 137 goto end; 138 } 139 ret = X509_verify_cert(&ctx); 140 chain = X509_STORE_CTX_get1_chain(&ctx); 141 X509_STORE_CTX_cleanup(&ctx); 142 if (ret <= 0) { 143 i = X509_STORE_CTX_get_error(&ctx); 144 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, 145 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 OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, 173 OCSP_R_ROOT_CA_NOT_TRUSTED); 174 goto end; 175 } 176 ret = 1; 177 } 178 179end: 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 187static int 188ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 189 X509_STORE *st, unsigned long flags) 190{ 191 X509 *signer; 192 OCSP_RESPID *rid = bs->tbsResponseData->responderId; 193 194 if ((signer = ocsp_find_signer_sk(certs, rid))) { 195 *psigner = signer; 196 return 2; 197 } 198 if (!(flags & OCSP_NOINTERN) && 199 (signer = ocsp_find_signer_sk(bs->certs, rid))) { 200 *psigner = signer; 201 return 1; 202 } 203 /* Maybe lookup from store if by subject name */ 204 205 *psigner = NULL; 206 return 0; 207} 208 209static X509 * 210ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) 211{ 212 int i; 213 unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 214 X509 *x; 215 216 /* Easy if lookup by name */ 217 if (id->type == V_OCSP_RESPID_NAME) 218 return X509_find_by_subject(certs, id->value.byName); 219 220 /* Lookup by key hash */ 221 222 /* If key hash isn't SHA1 length then forget it */ 223 if (id->value.byKey->length != SHA_DIGEST_LENGTH) 224 return NULL; 225 keyhash = id->value.byKey->data; 226 /* Calculate hash of each key and compare */ 227 for (i = 0; i < sk_X509_num(certs); i++) { 228 x = sk_X509_value(certs, i); 229 X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 230 if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 231 return x; 232 } 233 return NULL; 234} 235 236static int 237ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, 238 unsigned long flags) 239{ 240 STACK_OF(OCSP_SINGLERESP) *sresp; 241 X509 *signer, *sca; 242 OCSP_CERTID *caid = NULL; 243 int i; 244 245 sresp = bs->tbsResponseData->responses; 246 247 if (sk_X509_num(chain) <= 0) { 248 OCSPerr(OCSP_F_OCSP_CHECK_ISSUER, 249 OCSP_R_NO_CERTIFICATES_IN_CHAIN); 250 return -1; 251 } 252 253 /* See if the issuer IDs match. */ 254 i = ocsp_check_ids(sresp, &caid); 255 256 /* If ID mismatch or other error then return */ 257 if (i <= 0) 258 return i; 259 260 signer = sk_X509_value(chain, 0); 261 /* Check to see if OCSP responder CA matches request CA */ 262 if (sk_X509_num(chain) > 1) { 263 sca = sk_X509_value(chain, 1); 264 i = ocsp_match_issuerid(sca, caid, sresp); 265 if (i < 0) 266 return i; 267 if (i) { 268 /* We have a match, if extensions OK then success */ 269 if (ocsp_check_delegated(signer, flags)) 270 return 1; 271 return 0; 272 } 273 } 274 275 /* Otherwise check if OCSP request signed directly by request CA */ 276 return ocsp_match_issuerid(signer, caid, sresp); 277} 278 279/* Check the issuer certificate IDs for equality. If there is a mismatch with the same 280 * algorithm then there's no point trying to match any certificates against the issuer. 281 * If the issuer IDs all match then we just need to check equality against one of them. 282 */ 283static int 284ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret) 285{ 286 OCSP_CERTID *tmpid, *cid; 287 int i, idcount; 288 289 idcount = sk_OCSP_SINGLERESP_num(sresp); 290 if (idcount <= 0) { 291 OCSPerr(OCSP_F_OCSP_CHECK_IDS, 292 OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA); 293 return -1; 294 } 295 296 cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; 297 298 *ret = NULL; 299 300 for (i = 1; i < idcount; i++) { 301 tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; 302 /* Check to see if IDs match */ 303 if (OCSP_id_issuer_cmp(cid, tmpid)) { 304 return 0; 305 } 306 } 307 308 /* All IDs match: only need to check one ID */ 309 *ret = cid; 310 return 1; 311} 312 313static int 314ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, 315 STACK_OF(OCSP_SINGLERESP) *sresp) 316{ 317 /* If only one ID to match then do it */ 318 if (cid) { 319 const EVP_MD *dgst; 320 X509_NAME *iname; 321 int mdlen; 322 unsigned char md[EVP_MAX_MD_SIZE]; 323 324 if (!(dgst = 325 EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) { 326 OCSPerr(OCSP_F_OCSP_MATCH_ISSUERID, 327 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 OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, 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 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED); 388 return 0; 389 } 390 gen = req->tbsRequest->requestorName; 391 if (!gen || gen->type != GEN_DIRNAME) { 392 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 393 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 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 400 OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); 401 return 0; 402 } 403 if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) 404 flags |= OCSP_NOVERIFY; 405 if (!(flags & OCSP_NOSIGS)) { 406 EVP_PKEY *skey; 407 408 skey = X509_get_pubkey(signer); 409 ret = OCSP_REQUEST_verify(req, skey); 410 EVP_PKEY_free(skey); 411 if (ret <= 0) { 412 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 413 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 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 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 OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 443 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 452static int 453ocsp_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