ocsp_vfy.c revision 280297
1109998Smarkm/* ocsp_vfy.c */ 2280297Sjkim/* 3280297Sjkim * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project 4280297Sjkim * 2000. 5109998Smarkm */ 6109998Smarkm/* ==================================================================== 7127128Snectar * Copyright (c) 2000-2004 The OpenSSL Project. All rights reserved. 8109998Smarkm * 9109998Smarkm * Redistribution and use in source and binary forms, with or without 10109998Smarkm * modification, are permitted provided that the following conditions 11109998Smarkm * are met: 12109998Smarkm * 13109998Smarkm * 1. Redistributions of source code must retain the above copyright 14280297Sjkim * notice, this list of conditions and the following disclaimer. 15109998Smarkm * 16109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 17109998Smarkm * notice, this list of conditions and the following disclaimer in 18109998Smarkm * the documentation and/or other materials provided with the 19109998Smarkm * distribution. 20109998Smarkm * 21109998Smarkm * 3. All advertising materials mentioning features or use of this 22109998Smarkm * software must display the following acknowledgment: 23109998Smarkm * "This product includes software developed by the OpenSSL Project 24109998Smarkm * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25109998Smarkm * 26109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27109998Smarkm * endorse or promote products derived from this software without 28109998Smarkm * prior written permission. For written permission, please contact 29109998Smarkm * licensing@OpenSSL.org. 30109998Smarkm * 31109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 32109998Smarkm * nor may "OpenSSL" appear in their names without prior written 33109998Smarkm * permission of the OpenSSL Project. 34109998Smarkm * 35109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 36109998Smarkm * acknowledgment: 37109998Smarkm * "This product includes software developed by the OpenSSL Project 38109998Smarkm * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39109998Smarkm * 40109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 52109998Smarkm * ==================================================================== 53109998Smarkm * 54109998Smarkm * This product includes cryptographic software written by Eric Young 55109998Smarkm * (eay@cryptsoft.com). This product includes software written by Tim 56109998Smarkm * Hudson (tjh@cryptsoft.com). 57109998Smarkm * 58109998Smarkm */ 59109998Smarkm 60109998Smarkm#include <openssl/ocsp.h> 61109998Smarkm#include <openssl/err.h> 62109998Smarkm#include <string.h> 63109998Smarkm 64280297Sjkimstatic int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, 65280297Sjkim STACK_OF(X509) *certs, X509_STORE *st, 66280297Sjkim unsigned long flags); 67109998Smarkmstatic X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id); 68280297Sjkimstatic int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, 69280297Sjkim unsigned long flags); 70280297Sjkimstatic int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, 71280297Sjkim OCSP_CERTID **ret); 72280297Sjkimstatic int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, 73280297Sjkim STACK_OF(OCSP_SINGLERESP) *sresp); 74109998Smarkmstatic int ocsp_check_delegated(X509 *x, int flags); 75280297Sjkimstatic int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, 76280297Sjkim X509_NAME *nm, STACK_OF(X509) *certs, 77280297Sjkim X509_STORE *st, unsigned long flags); 78109998Smarkm 79109998Smarkm/* Verify a basic response message */ 80109998Smarkm 81109998Smarkmint OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs, 82280297Sjkim X509_STORE *st, unsigned long flags) 83280297Sjkim{ 84280297Sjkim X509 *signer, *x; 85280297Sjkim STACK_OF(X509) *chain = NULL; 86280297Sjkim X509_STORE_CTX ctx; 87280297Sjkim int i, ret = 0; 88280297Sjkim ret = ocsp_find_signer(&signer, bs, certs, st, flags); 89280297Sjkim if (!ret) { 90280297Sjkim OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, 91280297Sjkim OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); 92280297Sjkim goto end; 93280297Sjkim } 94280297Sjkim if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) 95280297Sjkim flags |= OCSP_NOVERIFY; 96280297Sjkim if (!(flags & OCSP_NOSIGS)) { 97280297Sjkim EVP_PKEY *skey; 98280297Sjkim skey = X509_get_pubkey(signer); 99280297Sjkim if (skey) { 100280297Sjkim ret = OCSP_BASICRESP_verify(bs, skey, 0); 101280297Sjkim EVP_PKEY_free(skey); 102280297Sjkim } 103280297Sjkim if (!skey || ret <= 0) { 104280297Sjkim OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_SIGNATURE_FAILURE); 105280297Sjkim goto end; 106280297Sjkim } 107280297Sjkim } 108280297Sjkim if (!(flags & OCSP_NOVERIFY)) { 109280297Sjkim int init_res; 110280297Sjkim if (flags & OCSP_NOCHAIN) 111280297Sjkim init_res = X509_STORE_CTX_init(&ctx, st, signer, NULL); 112280297Sjkim else 113280297Sjkim init_res = X509_STORE_CTX_init(&ctx, st, signer, bs->certs); 114280297Sjkim if (!init_res) { 115280297Sjkim ret = -1; 116280297Sjkim OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, ERR_R_X509_LIB); 117280297Sjkim goto end; 118280297Sjkim } 119109998Smarkm 120280297Sjkim X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER); 121280297Sjkim ret = X509_verify_cert(&ctx); 122280297Sjkim chain = X509_STORE_CTX_get1_chain(&ctx); 123280297Sjkim X509_STORE_CTX_cleanup(&ctx); 124280297Sjkim if (ret <= 0) { 125280297Sjkim i = X509_STORE_CTX_get_error(&ctx); 126280297Sjkim OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, 127280297Sjkim OCSP_R_CERTIFICATE_VERIFY_ERROR); 128280297Sjkim ERR_add_error_data(2, "Verify error:", 129280297Sjkim X509_verify_cert_error_string(i)); 130280297Sjkim goto end; 131280297Sjkim } 132280297Sjkim if (flags & OCSP_NOCHECKS) { 133280297Sjkim ret = 1; 134280297Sjkim goto end; 135280297Sjkim } 136280297Sjkim /* 137280297Sjkim * At this point we have a valid certificate chain need to verify it 138280297Sjkim * against the OCSP issuer criteria. 139280297Sjkim */ 140280297Sjkim ret = ocsp_check_issuer(bs, chain, flags); 141109998Smarkm 142280297Sjkim /* If fatal error or valid match then finish */ 143280297Sjkim if (ret != 0) 144280297Sjkim goto end; 145109998Smarkm 146280297Sjkim /* 147280297Sjkim * Easy case: explicitly trusted. Get root CA and check for explicit 148280297Sjkim * trust 149280297Sjkim */ 150280297Sjkim if (flags & OCSP_NOEXPLICIT) 151280297Sjkim goto end; 152109998Smarkm 153280297Sjkim x = sk_X509_value(chain, sk_X509_num(chain) - 1); 154280297Sjkim if (X509_check_trust(x, NID_OCSP_sign, 0) != X509_TRUST_TRUSTED) { 155280297Sjkim OCSPerr(OCSP_F_OCSP_BASIC_VERIFY, OCSP_R_ROOT_CA_NOT_TRUSTED); 156280297Sjkim goto end; 157280297Sjkim } 158280297Sjkim ret = 1; 159280297Sjkim } 160109998Smarkm 161280297Sjkim end: 162280297Sjkim if (chain) 163280297Sjkim sk_X509_pop_free(chain, X509_free); 164280297Sjkim return ret; 165280297Sjkim} 166109998Smarkm 167280297Sjkimstatic int ocsp_find_signer(X509 **psigner, OCSP_BASICRESP *bs, 168280297Sjkim STACK_OF(X509) *certs, X509_STORE *st, 169280297Sjkim unsigned long flags) 170280297Sjkim{ 171280297Sjkim X509 *signer; 172280297Sjkim OCSP_RESPID *rid = bs->tbsResponseData->responderId; 173280297Sjkim if ((signer = ocsp_find_signer_sk(certs, rid))) { 174280297Sjkim *psigner = signer; 175280297Sjkim return 2; 176280297Sjkim } 177280297Sjkim if (!(flags & OCSP_NOINTERN) && 178280297Sjkim (signer = ocsp_find_signer_sk(bs->certs, rid))) { 179280297Sjkim *psigner = signer; 180280297Sjkim return 1; 181280297Sjkim } 182280297Sjkim /* Maybe lookup from store if by subject name */ 183109998Smarkm 184280297Sjkim *psigner = NULL; 185280297Sjkim return 0; 186280297Sjkim} 187109998Smarkm 188109998Smarkmstatic X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) 189280297Sjkim{ 190280297Sjkim int i; 191280297Sjkim unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; 192280297Sjkim X509 *x; 193109998Smarkm 194280297Sjkim /* Easy if lookup by name */ 195280297Sjkim if (id->type == V_OCSP_RESPID_NAME) 196280297Sjkim return X509_find_by_subject(certs, id->value.byName); 197109998Smarkm 198280297Sjkim /* Lookup by key hash */ 199109998Smarkm 200280297Sjkim /* If key hash isn't SHA1 length then forget it */ 201280297Sjkim if (id->value.byKey->length != SHA_DIGEST_LENGTH) 202280297Sjkim return NULL; 203280297Sjkim keyhash = id->value.byKey->data; 204280297Sjkim /* Calculate hash of each key and compare */ 205280297Sjkim for (i = 0; i < sk_X509_num(certs); i++) { 206280297Sjkim x = sk_X509_value(certs, i); 207280297Sjkim X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); 208280297Sjkim if (!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) 209280297Sjkim return x; 210280297Sjkim } 211280297Sjkim return NULL; 212280297Sjkim} 213109998Smarkm 214280297Sjkimstatic int ocsp_check_issuer(OCSP_BASICRESP *bs, STACK_OF(X509) *chain, 215280297Sjkim unsigned long flags) 216280297Sjkim{ 217280297Sjkim STACK_OF(OCSP_SINGLERESP) *sresp; 218280297Sjkim X509 *signer, *sca; 219280297Sjkim OCSP_CERTID *caid = NULL; 220280297Sjkim int i; 221280297Sjkim sresp = bs->tbsResponseData->responses; 222109998Smarkm 223280297Sjkim if (sk_X509_num(chain) <= 0) { 224280297Sjkim OCSPerr(OCSP_F_OCSP_CHECK_ISSUER, OCSP_R_NO_CERTIFICATES_IN_CHAIN); 225280297Sjkim return -1; 226280297Sjkim } 227109998Smarkm 228280297Sjkim /* See if the issuer IDs match. */ 229280297Sjkim i = ocsp_check_ids(sresp, &caid); 230109998Smarkm 231280297Sjkim /* If ID mismatch or other error then return */ 232280297Sjkim if (i <= 0) 233280297Sjkim return i; 234109998Smarkm 235280297Sjkim signer = sk_X509_value(chain, 0); 236280297Sjkim /* Check to see if OCSP responder CA matches request CA */ 237280297Sjkim if (sk_X509_num(chain) > 1) { 238280297Sjkim sca = sk_X509_value(chain, 1); 239280297Sjkim i = ocsp_match_issuerid(sca, caid, sresp); 240280297Sjkim if (i < 0) 241280297Sjkim return i; 242280297Sjkim if (i) { 243280297Sjkim /* We have a match, if extensions OK then success */ 244280297Sjkim if (ocsp_check_delegated(signer, flags)) 245280297Sjkim return 1; 246280297Sjkim return 0; 247280297Sjkim } 248280297Sjkim } 249109998Smarkm 250280297Sjkim /* Otherwise check if OCSP request signed directly by request CA */ 251280297Sjkim return ocsp_match_issuerid(signer, caid, sresp); 252280297Sjkim} 253109998Smarkm 254280297Sjkim/* 255280297Sjkim * Check the issuer certificate IDs for equality. If there is a mismatch with 256280297Sjkim * the same algorithm then there's no point trying to match any certificates 257280297Sjkim * against the issuer. If the issuer IDs all match then we just need to check 258280297Sjkim * equality against one of them. 259280297Sjkim */ 260109998Smarkm 261109998Smarkmstatic int ocsp_check_ids(STACK_OF(OCSP_SINGLERESP) *sresp, OCSP_CERTID **ret) 262280297Sjkim{ 263280297Sjkim OCSP_CERTID *tmpid, *cid; 264280297Sjkim int i, idcount; 265109998Smarkm 266280297Sjkim idcount = sk_OCSP_SINGLERESP_num(sresp); 267280297Sjkim if (idcount <= 0) { 268280297Sjkim OCSPerr(OCSP_F_OCSP_CHECK_IDS, 269280297Sjkim OCSP_R_RESPONSE_CONTAINS_NO_REVOCATION_DATA); 270280297Sjkim return -1; 271280297Sjkim } 272109998Smarkm 273280297Sjkim cid = sk_OCSP_SINGLERESP_value(sresp, 0)->certId; 274109998Smarkm 275280297Sjkim *ret = NULL; 276109998Smarkm 277280297Sjkim for (i = 1; i < idcount; i++) { 278280297Sjkim tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; 279280297Sjkim /* Check to see if IDs match */ 280280297Sjkim if (OCSP_id_issuer_cmp(cid, tmpid)) { 281280297Sjkim /* If algoritm mismatch let caller deal with it */ 282280297Sjkim if (OBJ_cmp(tmpid->hashAlgorithm->algorithm, 283280297Sjkim cid->hashAlgorithm->algorithm)) 284280297Sjkim return 2; 285280297Sjkim /* Else mismatch */ 286280297Sjkim return 0; 287280297Sjkim } 288280297Sjkim } 289109998Smarkm 290280297Sjkim /* All IDs match: only need to check one ID */ 291280297Sjkim *ret = cid; 292280297Sjkim return 1; 293280297Sjkim} 294109998Smarkm 295109998Smarkmstatic int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, 296280297Sjkim STACK_OF(OCSP_SINGLERESP) *sresp) 297280297Sjkim{ 298280297Sjkim /* If only one ID to match then do it */ 299280297Sjkim if (cid) { 300280297Sjkim const EVP_MD *dgst; 301280297Sjkim X509_NAME *iname; 302280297Sjkim int mdlen; 303280297Sjkim unsigned char md[EVP_MAX_MD_SIZE]; 304280297Sjkim if (!(dgst = EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) { 305280297Sjkim OCSPerr(OCSP_F_OCSP_MATCH_ISSUERID, 306280297Sjkim OCSP_R_UNKNOWN_MESSAGE_DIGEST); 307280297Sjkim return -1; 308280297Sjkim } 309109998Smarkm 310280297Sjkim mdlen = EVP_MD_size(dgst); 311280297Sjkim if (mdlen < 0) 312280297Sjkim return -1; 313280297Sjkim if ((cid->issuerNameHash->length != mdlen) || 314280297Sjkim (cid->issuerKeyHash->length != mdlen)) 315280297Sjkim return 0; 316280297Sjkim iname = X509_get_subject_name(cert); 317280297Sjkim if (!X509_NAME_digest(iname, dgst, md, NULL)) 318280297Sjkim return -1; 319280297Sjkim if (memcmp(md, cid->issuerNameHash->data, mdlen)) 320280297Sjkim return 0; 321280297Sjkim X509_pubkey_digest(cert, dgst, md, NULL); 322280297Sjkim if (memcmp(md, cid->issuerKeyHash->data, mdlen)) 323280297Sjkim return 0; 324109998Smarkm 325280297Sjkim return 1; 326109998Smarkm 327280297Sjkim } else { 328280297Sjkim /* We have to match the whole lot */ 329280297Sjkim int i, ret; 330280297Sjkim OCSP_CERTID *tmpid; 331280297Sjkim for (i = 0; i < sk_OCSP_SINGLERESP_num(sresp); i++) { 332280297Sjkim tmpid = sk_OCSP_SINGLERESP_value(sresp, i)->certId; 333280297Sjkim ret = ocsp_match_issuerid(cert, tmpid, NULL); 334280297Sjkim if (ret <= 0) 335280297Sjkim return ret; 336280297Sjkim } 337280297Sjkim return 1; 338280297Sjkim } 339109998Smarkm 340280297Sjkim} 341280297Sjkim 342109998Smarkmstatic int ocsp_check_delegated(X509 *x, int flags) 343280297Sjkim{ 344280297Sjkim X509_check_purpose(x, -1, 0); 345280297Sjkim if ((x->ex_flags & EXFLAG_XKUSAGE) && (x->ex_xkusage & XKU_OCSP_SIGN)) 346280297Sjkim return 1; 347280297Sjkim OCSPerr(OCSP_F_OCSP_CHECK_DELEGATED, OCSP_R_MISSING_OCSPSIGNING_USAGE); 348280297Sjkim return 0; 349280297Sjkim} 350109998Smarkm 351280297Sjkim/* 352280297Sjkim * Verify an OCSP request. This is fortunately much easier than OCSP response 353280297Sjkim * verify. Just find the signers certificate and verify it against a given 354280297Sjkim * trust value. 355109998Smarkm */ 356109998Smarkm 357280297Sjkimint OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs, 358280297Sjkim X509_STORE *store, unsigned long flags) 359280297Sjkim{ 360280297Sjkim X509 *signer; 361280297Sjkim X509_NAME *nm; 362280297Sjkim GENERAL_NAME *gen; 363280297Sjkim int ret; 364280297Sjkim X509_STORE_CTX ctx; 365280297Sjkim if (!req->optionalSignature) { 366280297Sjkim OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_REQUEST_NOT_SIGNED); 367280297Sjkim return 0; 368280297Sjkim } 369280297Sjkim gen = req->tbsRequest->requestorName; 370280297Sjkim if (!gen || gen->type != GEN_DIRNAME) { 371280297Sjkim OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 372280297Sjkim OCSP_R_UNSUPPORTED_REQUESTORNAME_TYPE); 373280297Sjkim return 0; 374280297Sjkim } 375280297Sjkim nm = gen->d.directoryName; 376280297Sjkim ret = ocsp_req_find_signer(&signer, req, nm, certs, store, flags); 377280297Sjkim if (ret <= 0) { 378280297Sjkim OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 379280297Sjkim OCSP_R_SIGNER_CERTIFICATE_NOT_FOUND); 380280297Sjkim return 0; 381280297Sjkim } 382280297Sjkim if ((ret == 2) && (flags & OCSP_TRUSTOTHER)) 383280297Sjkim flags |= OCSP_NOVERIFY; 384280297Sjkim if (!(flags & OCSP_NOSIGS)) { 385280297Sjkim EVP_PKEY *skey; 386280297Sjkim skey = X509_get_pubkey(signer); 387280297Sjkim ret = OCSP_REQUEST_verify(req, skey); 388280297Sjkim EVP_PKEY_free(skey); 389280297Sjkim if (ret <= 0) { 390280297Sjkim OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, OCSP_R_SIGNATURE_FAILURE); 391280297Sjkim return 0; 392280297Sjkim } 393280297Sjkim } 394280297Sjkim if (!(flags & OCSP_NOVERIFY)) { 395280297Sjkim int init_res; 396280297Sjkim if (flags & OCSP_NOCHAIN) 397280297Sjkim init_res = X509_STORE_CTX_init(&ctx, store, signer, NULL); 398280297Sjkim else 399280297Sjkim init_res = X509_STORE_CTX_init(&ctx, store, signer, 400280297Sjkim req->optionalSignature->certs); 401280297Sjkim if (!init_res) { 402280297Sjkim OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, ERR_R_X509_LIB); 403280297Sjkim return 0; 404280297Sjkim } 405109998Smarkm 406280297Sjkim X509_STORE_CTX_set_purpose(&ctx, X509_PURPOSE_OCSP_HELPER); 407280297Sjkim X509_STORE_CTX_set_trust(&ctx, X509_TRUST_OCSP_REQUEST); 408280297Sjkim ret = X509_verify_cert(&ctx); 409280297Sjkim X509_STORE_CTX_cleanup(&ctx); 410280297Sjkim if (ret <= 0) { 411280297Sjkim ret = X509_STORE_CTX_get_error(&ctx); 412280297Sjkim OCSPerr(OCSP_F_OCSP_REQUEST_VERIFY, 413280297Sjkim OCSP_R_CERTIFICATE_VERIFY_ERROR); 414280297Sjkim ERR_add_error_data(2, "Verify error:", 415280297Sjkim X509_verify_cert_error_string(ret)); 416280297Sjkim return 0; 417109998Smarkm } 418280297Sjkim } 419280297Sjkim return 1; 420280297Sjkim} 421109998Smarkm 422280297Sjkimstatic int ocsp_req_find_signer(X509 **psigner, OCSP_REQUEST *req, 423280297Sjkim X509_NAME *nm, STACK_OF(X509) *certs, 424280297Sjkim X509_STORE *st, unsigned long flags) 425280297Sjkim{ 426280297Sjkim X509 *signer; 427280297Sjkim if (!(flags & OCSP_NOINTERN)) { 428280297Sjkim signer = X509_find_by_subject(req->optionalSignature->certs, nm); 429280297Sjkim if (signer) { 430280297Sjkim *psigner = signer; 431280297Sjkim return 1; 432280297Sjkim } 433280297Sjkim } 434109998Smarkm 435280297Sjkim signer = X509_find_by_subject(certs, nm); 436280297Sjkim if (signer) { 437280297Sjkim *psigner = signer; 438280297Sjkim return 2; 439280297Sjkim } 440280297Sjkim return 0; 441280297Sjkim} 442