]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_apple_x509_tp/lib/tpOcspCertVfy.cpp
Security-57337.60.2.tar.gz
[apple/security.git] / OSX / libsecurity_apple_x509_tp / lib / tpOcspCertVfy.cpp
1 /*
2 * Copyright (c) 2004,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * tpOcspCertVfy.cpp - OCSP cert verification routines
26 */
27
28 #include "tpOcspCertVfy.h"
29 #include "tpdebugging.h"
30 #include "certGroupUtils.h"
31 #include <Security/oidscert.h>
32 #include <CommonCrypto/CommonDigest.h>
33 #include <security_ocspd/ocspdUtils.h>
34 #include "tpTime.h"
35
36 #ifndef NDEBUG
37 #include <Security/SecCertificate.h>
38 #endif
39
40 /*
41 * Is signerCert authorized to sign OCSP responses by issuerCert? IssuerCert is
42 * assumed to be (i.e., must, but we don't check that here) the signer of the
43 * cert being verified, which is not in the loop for this op. Just a bool returned;
44 * it's authorized or it's not.
45 */
46 static bool tpIsAuthorizedOcspSigner(
47 TPCertInfo &issuerCert, // issuer of cert being verified
48 TPCertInfo &signerCert) // potential signer of OCSP response
49 {
50 CSSM_DATA_PTR fieldValue = NULL; // mallocd by CL
51 CSSM_RETURN crtn;
52 bool ourRtn = false;
53 CE_ExtendedKeyUsage *eku = NULL;
54 bool foundEku = false;
55
56 /*
57 * First see if issuerCert issued signerCert (No signature vfy yet, just
58 * subject/issuer check).
59 */
60 if(!issuerCert.isIssuerOf(signerCert)) {
61 #ifndef NDEBUG
62 SecCertificateRef issuerRef = NULL;
63 SecCertificateRef signerRef = NULL;
64 const CSSM_DATA *issuerData = issuerCert.itemData();
65 const CSSM_DATA *signerData = signerCert.itemData();
66 crtn = SecCertificateCreateFromData(issuerData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_BER, &issuerRef);
67 crtn = SecCertificateCreateFromData(signerData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_BER, &signerRef);
68 CFStringRef issuerName = SecCertificateCopySubjectSummary(issuerRef);
69 CFStringRef signerName = SecCertificateCopySubjectSummary(signerRef);
70 if(issuerName) {
71 CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(issuerName), kCFStringEncodingUTF8) + 1;
72 char* buf = (char*) malloc(maxLength);
73 if (buf) {
74 if (CFStringGetCString(issuerName, buf, (CFIndex)maxLength, kCFStringEncodingUTF8)) {
75 tpOcspDebug("tpIsAuthorizedOcspSigner: issuerCert \"%s\"", buf);
76 }
77 free(buf);
78 }
79 CFRelease(issuerName);
80 }
81 if(signerName) {
82 CFIndex maxLength = CFStringGetMaximumSizeForEncoding(CFStringGetLength(signerName), kCFStringEncodingUTF8) + 1;
83 char* buf = (char*) malloc(maxLength);
84 if (buf) {
85 if (CFStringGetCString(signerName, buf, (CFIndex)maxLength, kCFStringEncodingUTF8)) {
86 tpOcspDebug("tpIsAuthorizedOcspSigner: signerCert \"%s\"", buf);
87 }
88 free(buf);
89 }
90 CFRelease(signerName);
91 }
92 if(issuerRef) {
93 CFRelease(issuerRef);
94 }
95 if(signerRef) {
96 CFRelease(signerRef);
97 }
98 #endif
99 tpOcspDebug("tpIsAuthorizedOcspSigner: signer is not issued by issuerCert");
100 return false;
101 }
102
103 /* Fetch ExtendedKeyUse field from signerCert */
104 crtn = signerCert.fetchField(&CSSMOID_ExtendedKeyUsage, &fieldValue);
105 if(crtn) {
106 tpOcspDebug("tpIsAuthorizedOcspSigner: signer is issued by issuer, no EKU");
107 return false;
108 }
109 CSSM_X509_EXTENSION *cssmExt = (CSSM_X509_EXTENSION *)fieldValue->Data;
110 if(cssmExt->format != CSSM_X509_DATAFORMAT_PARSED) {
111 tpOcspDebug("tpIsAuthorizedOcspSigner: bad extension format");
112 goto errOut;
113 }
114 eku = (CE_ExtendedKeyUsage *)cssmExt->value.parsedValue;
115
116 /* Look for OID_KP_OCSPSigning */
117 for(unsigned dex=0; dex<eku->numPurposes; dex++) {
118 if(tpCompareCssmData(&eku->purposes[dex], &CSSMOID_OCSPSigning)) {
119 foundEku = true;
120 break;
121 }
122 }
123 if(!foundEku) {
124 tpOcspDebug("tpIsAuthorizedOcspSigner: signer is issued by issuer, no OCSP "
125 "signing EKU");
126 goto errOut;
127 }
128
129 /*
130 * OK, signerCert is authorized by *someone* to sign OCSP requests, and
131 * it claims to be issued by issuer. Sig verify to be sure.
132 * FIXME this is not handling partial public keys, which would be a colossal
133 * mess to handle in this module...so we don't.
134 */
135 crtn = signerCert.verifyWithIssuer(&issuerCert, NULL);
136 if(crtn == CSSM_OK) {
137 tpOcspDebug("tpIsAuthorizedOcspSigner: FOUND authorized signer");
138 ourRtn = true;
139 }
140 else {
141 /* This is a highly irregular situation... */
142 tpOcspDebug("tpIsAuthorizedOcspSigner: signer sig verify FAIL");
143 }
144 errOut:
145 if(fieldValue != NULL) {
146 signerCert.freeField(&CSSMOID_ExtendedKeyUsage, fieldValue);
147 }
148 return ourRtn;
149 }
150
151 /*
152 * Check ResponderID linkage between an OCSPResponse and a cert we believe to
153 * be the issuer of both that response and the cert being verified. Returns
154 * true if OK.
155 */
156 static
157 bool tpOcspResponderIDCheck(
158 OCSPResponse &ocspResp,
159 TPCertInfo &signer)
160 {
161 bool shouldBeSigner = false;
162 if(ocspResp.responderIDTag() == RIT_Name) {
163 /*
164 * Name inside response must == signer's SubjectName.
165 * Note we can't use signer.subjectName(); that's normalized.
166 */
167
168 const CSSM_DATA *respIdName = ocspResp.encResponderName();
169 CSSM_DATA *subjectName = NULL;
170 CSSM_RETURN crtn = signer.fetchField(&CSSMOID_X509V1SubjectNameStd,
171 &subjectName);
172 if(crtn) {
173 /* bad cert */
174 tpOcspDebug("tpOcspResponderIDCheck: error on fetchField(subjectName");
175 return false;
176 }
177 if(tpCompareCssmData(respIdName, subjectName)) {
178 tpOcspDebug("tpOcspResponderIDCheck: good ResponderID.byName");
179 shouldBeSigner = true;
180 }
181 else {
182 tpOcspDebug("tpOcspResponderIDCheck: BAD ResponderID.byName");
183 }
184 signer.freeField(&CSSMOID_X509V1SubjectNameStd, subjectName);
185 }
186 else {
187 /* ResponderID.byKey must == SHA1(signer's public key) */
188 const CSSM_KEY_PTR pubKey = signer.pubKey();
189 assert(pubKey != NULL);
190 uint8 digest[CC_SHA1_DIGEST_LENGTH];
191 CSSM_DATA keyHash = {CC_SHA1_DIGEST_LENGTH, digest};
192 CSSM_DATA pubKeyBytes = {0, NULL};
193 ocspdGetPublicKeyBytes(NULL, pubKey, pubKeyBytes);
194 ocspdSha1(pubKeyBytes.Data, (CC_LONG)pubKeyBytes.Length, digest);
195 const CSSM_DATA *respKeyHash = &ocspResp.responderID().byKey;
196 if(tpCompareCssmData(&keyHash, respKeyHash)) {
197 tpOcspDebug("tpOcspResponderIDCheck: good ResponderID.byKey");
198 shouldBeSigner = true;
199 }
200 else {
201 tpOcspDebug("tpOcspResponderIDCheck: BAD ResponderID.byKey");
202 }
203 }
204 return shouldBeSigner;
205 }
206
207 /*
208 * Verify the signature of an OCSP response. Caller is responsible for all other
209 * verification of the response, this is just the crypto.
210 * Returns true on success.
211 */
212 static bool tpOcspResponseSigVerify(
213 TPVerifyContext &vfyCtx,
214 OCSPResponse &ocspResp, // parsed response
215 TPCertInfo &signer)
216 {
217 /* get signature algorithm in CSSM form from the response */
218 const SecAsn1OCSPBasicResponse &basicResp = ocspResp.basicResponse();
219 const CSSM_OID *algOid = &basicResp.algId.algorithm;
220 CSSM_ALGORITHMS sigAlg;
221
222 if(!cssmOidToAlg(algOid, &sigAlg)) {
223 tpOcspDebug("tpOcspResponseSigVerify: unknown signature algorithm");
224 }
225
226 /* signer's public key from the cert */
227 const CSSM_KEY *pubKey = signer.pubKey();
228
229 /* signature: on decode, length is in BITS */
230 CSSM_DATA sig = basicResp.sig;
231 sig.Length /= 8;
232
233 CSSM_RETURN crtn;
234 CSSM_CC_HANDLE sigHand;
235 bool ourRtn = false;
236 crtn = CSSM_CSP_CreateSignatureContext(vfyCtx.cspHand, sigAlg, NULL,
237 pubKey, &sigHand);
238 if(crtn) {
239 #ifndef NDEBUG
240 cssmPerror("tpOcspResponseSigVerify, CSSM_CSP_CreateSignatureContext", crtn);
241 #endif
242 return false;
243 }
244 crtn = CSSM_VerifyData(sigHand, &basicResp.tbsResponseData, 1,
245 CSSM_ALGID_NONE, &sig);
246 if(crtn) {
247 #ifndef NDEBUG
248 cssmPerror("tpOcspResponseSigVerify, CSSM_VerifyData", crtn);
249 #endif
250 }
251 else {
252 ourRtn = true;
253 }
254 CSSM_DeleteContext(sigHand);
255 return ourRtn;
256 }
257
258 /* possible return from tpIsOcspIssuer() */
259 typedef enum {
260 OIS_No, // not the issuer
261 OIS_Good, // is the issuer and signature matches
262 OIS_BadSig, // appears to be issuer, but signature doesn't match
263 } OcspIssuerStatus;
264
265 /* type of rawCert passed to tpIsOcspIssuer */
266 typedef enum {
267 OCT_Local, // LocalResponder - no checking other than signature
268 OCT_Issuer, // it's the issuer of the cert being verified
269 OCT_Provided, // came with response, provenance unknown
270 } OcspCertType;
271
272 /*
273 * Did specified cert issue the OCSP response?
274 *
275 * This implements the algorithm described in RFC2560, section 4.2.2.2,
276 * "Authorized Responders". It sees if the cert could be the issuer of the
277 * OCSP response per that algorithm; then if it could, it performs signature
278 * verification.
279 */
280 static OcspIssuerStatus tpIsOcspIssuer(
281 TPVerifyContext &vfyCtx,
282 OCSPResponse &ocspResp, // parsed response
283 /* on input specify at least one of the following two */
284 const CSSM_DATA *signerData,
285 TPCertInfo *signer,
286 OcspCertType certType, // where rawCert came from
287 TPCertInfo *issuer, // OPTIONAL, if known
288 TPCertInfo **signerRtn) // optionally RETURNED if at all possible
289 {
290 assert((signerData != NULL) || (signer != NULL));
291
292 /* get signer as TPCertInfo if caller hasn't provided */
293 TPCertInfo *tmpSigner = NULL;
294 if(signer == NULL) {
295 try {
296 tmpSigner = new TPCertInfo(vfyCtx.clHand, vfyCtx.cspHand, signerData,
297 TIC_CopyData, vfyCtx.verifyTime);
298 }
299 catch(...) {
300 tpOcspDebug("tpIsOcspIssuer: bad cert");
301 return OIS_No;
302 }
303 signer = tmpSigner;
304 }
305 if(signer == NULL) {
306 return OIS_No;
307 }
308 if(signerRtn != NULL) {
309 *signerRtn = signer;
310 }
311
312 /*
313 * Qualification of "this can be the signer" depends on where the
314 * signer came from.
315 */
316 bool shouldBeSigner = false;
317 OcspIssuerStatus ourRtn = OIS_No;
318
319 switch(certType) {
320 case OCT_Local: // caller trusts this and thinks it's the signer
321 shouldBeSigner = true;
322 break;
323 case OCT_Issuer: // last resort, the actual issuer
324 /* check ResponderID linkage */
325 shouldBeSigner = tpOcspResponderIDCheck(ocspResp, *signer);
326 break;
327 case OCT_Provided:
328 {
329 /*
330 * This cert came with the response.
331 */
332 if(issuer == NULL) {
333 /*
334 * careful, might not know the issuer...how would this path ever
335 * work then? I don't think it needs to because you can NOT
336 * do OCSP on a cert without its issuer in hand.
337 */
338 break;
339 }
340
341 /* check EKU linkage */
342 shouldBeSigner = tpIsAuthorizedOcspSigner(*issuer, *signer);
343 break;
344 }
345 }
346 if(!shouldBeSigner) {
347 goto errOut;
348 }
349
350 /* verify the signature */
351 if(tpOcspResponseSigVerify(vfyCtx, ocspResp, *signer)) {
352 ourRtn = OIS_Good;
353 }
354
355 errOut:
356 if((signerRtn == NULL) && (tmpSigner != NULL)) {
357 delete tmpSigner;
358 }
359 return ourRtn;
360
361 }
362
363 OcspRespStatus tpVerifyOcspResp(
364 TPVerifyContext &vfyCtx,
365 SecNssCoder &coder,
366 TPCertInfo *issuer, // issuer of the related cert, may be issuer of
367 // reply, may not be known
368 OCSPResponse &ocspResp,
369 CSSM_RETURN &cssmErr) // possible per-cert error
370 {
371 OcspRespStatus ourRtn = ORS_Unknown;
372 CSSM_RETURN crtn;
373 char *ocspResp_genTime = NULL;
374 char *ocspResp_cssmTime = NULL;
375 CSSM_TIMESTRING cssmTimeStr = NULL;
376
377 tpOcspDebug("tpVerifyOcspResp top");
378
379 switch(ocspResp.responseStatus()) {
380 case RS_Success:
381 crtn = CSSM_OK;
382 break;
383 case RS_MalformedRequest:
384 crtn = CSSMERR_APPLETP_OCSP_RESP_MALFORMED_REQ;
385 break;
386 case RS_InternalError:
387 crtn = CSSMERR_APPLETP_OCSP_RESP_INTERNAL_ERR;
388 break;
389 case RS_TryLater:
390 crtn = CSSMERR_APPLETP_OCSP_RESP_TRY_LATER;
391 break;
392 case RS_SigRequired:
393 crtn = CSSMERR_APPLETP_OCSP_RESP_SIG_REQUIRED;
394 break;
395 case RS_Unauthorized:
396 crtn = CSSMERR_APPLETP_OCSP_RESP_UNAUTHORIZED;
397 break;
398 default:
399 crtn = CSSMERR_APPLETP_OCSP_BAD_RESPONSE;
400 break;
401 }
402 if(crtn) {
403 tpOcspDebug("tpVerifyOcspResp aborting due to response status %d",
404 (int)(ocspResp.responseStatus()));
405 cssmErr = crtn;
406 return ORS_Unknown;
407 }
408 cssmErr = CSSM_OK;
409
410 /* one of our main jobs is to locate the signer of the response, here */
411 TPCertInfo *signerInfo = NULL;
412 TPCertInfo *signerInfoTBD = NULL; // if non NULL at end, we delete
413 /* we'll be verifying into this cert group */
414 TPCertGroup ocspCerts(vfyCtx.alloc, TGO_Caller);
415 CSSM_BOOL verifiedToRoot;
416 CSSM_BOOL verifiedToAnchor;
417 CSSM_BOOL verifiedViaTrustSetting;
418
419 const CSSM_APPLE_TP_OCSP_OPTIONS *ocspOpts = vfyCtx.ocspOpts;
420 OcspIssuerStatus issuerStat;
421
422 /* determine verification time for signer */
423 ocspResp_cssmTime = (char *)malloc(CSSM_TIME_STRLEN + 1);
424 ocspResp_genTime = (char *)malloc(GENERAL_TIME_STRLEN + 1);
425 if (ocspResp_cssmTime && ocspResp_genTime) {
426 cssmTimeStr = vfyCtx.verifyTime; // store old verify time for other ctx users
427 cfAbsTimeToGgenTime(ocspResp.producedAt(), ocspResp_genTime);
428 tpTimeToCssmTimestring(ocspResp_genTime,GENERAL_TIME_STRLEN,ocspResp_cssmTime);
429 vfyCtx.verifyTime = ocspResp_cssmTime;
430 }
431
432 /*
433 * Set true if we ever find an apparent issuer which does not correctly
434 * pass signature verify. If true and we never success, that's a XXX error.
435 */
436 bool foundBadIssuer = false;
437 bool foundLocalResponder = false;
438 uint32 numSignerCerts = ocspResp.numSignerCerts();
439
440 /*
441 * This cert group, allocated by AppleTPSession::CertGroupVerify(),
442 * serves two functions here:
443 *
444 * -- it accumulates certs we get from the net (as parts of OCSP responses)
445 * for user in verifying OCSPResponse-related certs.
446 * TPCertGroup::buildCertGroup() uses this group as one of the many
447 * sources of certs when building a cert chain.
448 *
449 * -- it provides a container into which to stash TPCertInfos which
450 * persist at least as long as the TPVerifyContext; it's of type TGO_Group,
451 * so all of the certs added to it get freed when the group does.
452 */
453 assert(vfyCtx.signerCerts != NULL);
454
455 TPCertGroup &gatheredCerts = vfyCtx.gatheredCerts;
456
457 /* set up for disposal of TPCertInfos created by TPCertGroup::buildCertGroup() */
458 TPCertGroup certsToBeFreed(vfyCtx.alloc, TGO_Group);
459
460 /*
461 * First job is to find the cert which signed this response.
462 * Give priority to caller's LocalResponderCert.
463 */
464 if((ocspOpts != NULL) && (ocspOpts->LocalResponderCert != NULL)) {
465 TPCertInfo *responderInfo = NULL;
466 issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp,
467 ocspOpts->LocalResponderCert, NULL,
468 OCT_Local, issuer, &responderInfo);
469 switch(issuerStat) {
470 case OIS_BadSig:
471 foundBadIssuer = true;
472 /* drop thru */
473 case OIS_No:
474 if(responderInfo != NULL) {
475 /* can't use it - should this be an immediate error? */
476 delete responderInfo;
477 }
478 break;
479 case OIS_Good:
480 assert(responderInfo != NULL);
481 signerInfo = signerInfoTBD = responderInfo;
482 foundLocalResponder = true;
483 tpOcspDebug("tpVerifyOcspResp: signer := LocalResponderCert");
484 break;
485 }
486 }
487
488 if((signerInfo == NULL) && (numSignerCerts != 0)) {
489 /*
490 * App did not specify a local responder (or provided a bad one)
491 * and the response came with some certs. Try those.
492 */
493 TPCertInfo *respCert = NULL;
494 for(unsigned dex=0; dex<numSignerCerts; dex++) {
495 const CSSM_DATA *certData = ocspResp.signerCert(dex);
496 if(signerInfo == NULL) {
497 /* stop trying this after we succeed... */
498 issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp,
499 certData, NULL,
500 OCT_Provided, issuer, &respCert);
501 switch(issuerStat) {
502 case OIS_No:
503 break;
504 case OIS_Good:
505 assert(respCert != NULL);
506 signerInfo = signerInfoTBD = respCert;
507 tpOcspDebug("tpVerifyOcspResp: signer := signerCert[%u]", dex);
508 break;
509 case OIS_BadSig:
510 foundBadIssuer = true;
511 break;
512 }
513 }
514 else {
515 /*
516 * At least add this cert to certGroup for verification.
517 * OcspCert will own the TPCertInfo.
518 */
519 try {
520 respCert = new TPCertInfo(vfyCtx.clHand, vfyCtx.cspHand, certData,
521 TIC_CopyData, vfyCtx.verifyTime);
522 }
523 catch(...) {
524 tpOcspDebug("tpVerifyOcspResp: BAD signerCert[%u]", dex);
525 }
526 }
527 /* if we got a TPCertInfo, and it's not the signer, add it to certGroup */
528 if((respCert != NULL) && (respCert != signerInfo)) {
529 gatheredCerts.appendCert(respCert);
530 }
531 }
532 }
533
534 if((signerInfo == NULL) && (issuer != NULL)) {
535 /*
536 * Haven't found it yet, try the actual issuer
537 */
538 issuerStat = tpIsOcspIssuer(vfyCtx, ocspResp,
539 NULL, issuer,
540 OCT_Issuer, issuer, NULL);
541 switch(issuerStat) {
542 case OIS_BadSig:
543 ourRtn = ORS_Unknown;
544 cssmErr = CSSMERR_APPLETP_OCSP_SIG_ERROR;
545 goto errOut;
546 case OIS_No:
547 break;
548 case OIS_Good:
549 signerInfo = issuer;
550 tpOcspDebug("tpVerifyOcspResp: signer := issuer");
551 break;
552 }
553 }
554
555 if(signerInfo == NULL) {
556 if((issuer != NULL) && !issuer->isStatusFatal(CSSMERR_APPLETP_OCSP_NO_SIGNER)) {
557 /* user wants to proceed without verifying! */
558 tpOcspDebug("tpVerifyOcspResp: no signer found, user allows!");
559 ourRtn = ORS_Good;
560 }
561 else {
562 tpOcspDebug("tpVerifyOcspResp: no signer found");
563 ourRtn = ORS_Unknown;
564 /* caller adds to per-cert status */
565 cssmErr = CSSMERR_APPLETP_OCSP_NO_SIGNER;
566 }
567 goto errOut;
568 }
569
570 if(signerInfo != NULL && !foundLocalResponder) {
571 /*
572 * tpIsOcspIssuer has verified that signerInfo is the signer of the
573 * OCSP response, and that it is either the issuer of the cert being
574 * checked or is a valid authorized responder for that issuer based on
575 * key id linkage and EKU. There is no stipulation in RFC2560 to also
576 * build the chain back to a trusted anchor; however, we'll continue to
577 * enforce this for the local responder case. (10742723)
578 */
579 /* check that the cert we found is temporally valid */
580 if (signerInfo->isExpired() || signerInfo->isNotValidYet()) {
581 tpOcspDebug("tpVerifyOcspResp ocspSigner expired or not yet valid");
582 ourRtn = ORS_Unknown;
583 cssmErr = CSSMERR_APPLETP_OCSP_NO_SIGNER;
584 goto errOut;
585 }
586 else {
587 tpOcspDebug("tpVerifyOcspResp SUCCESS");
588 ourRtn = ORS_Good;
589 goto errOut;
590 }
591 }
592
593 /*
594 * Last remaining task is to verify the signer, and all the certs back to
595 * an anchor
596 */
597
598 /* start from scratch with both of these groups */
599 gatheredCerts.setAllUnused();
600 vfyCtx.signerCerts->setAllUnused();
601 crtn = ocspCerts.buildCertGroup(
602 *signerInfo, // subject item
603 vfyCtx.signerCerts, // inCertGroup the original group-to-be-verified
604 vfyCtx.dbList, // optional
605 vfyCtx.clHand,
606 vfyCtx.cspHand,
607 vfyCtx.verifyTime,
608 vfyCtx.numAnchorCerts,
609 vfyCtx.anchorCerts,
610 certsToBeFreed, // local to-be-freed right now
611 &gatheredCerts, // accumulate gathered certs here
612 CSSM_FALSE, // subjectIsInGroup
613 vfyCtx.actionFlags,
614 vfyCtx.policyOid,
615 vfyCtx.policyStr,
616 vfyCtx.policyStrLen,
617 kSecTrustSettingsKeyUseSignRevocation,
618 verifiedToRoot,
619 verifiedToAnchor,
620 verifiedViaTrustSetting);
621 if(crtn) {
622 tpOcspDebug("tpVerifyOcspResp buildCertGroup failure");
623 cssmErr = crtn;
624 ourRtn = ORS_Unknown;
625 goto errOut;
626 }
627
628 /* Verify temporal validity of local OCSP signer chain */
629 crtn = ocspCerts.getReturnCode(crtn, NULL, vfyCtx.actionFlags);
630 if ((crtn == CSSMERR_TP_CERT_EXPIRED) || (crtn == CSSMERR_TP_CERT_NOT_VALID_YET)) {
631 tpOcspDebug("tpVerifyOcspResp ocspSigner expired or not yet valid");
632 ourRtn = ORS_Unknown;
633 cssmErr = CSSMERR_APPLETP_OCSP_NO_SIGNER;
634 goto errOut;
635 }
636
637 if(!verifiedToAnchor && !verifiedViaTrustSetting) {
638 /* required */
639 ourRtn = ORS_Unknown;
640 if(verifiedToRoot) {
641 /* verified to root which is not an anchor */
642 tpOcspDebug("tpVerifyOcspResp root, no anchor");
643 cssmErr = CSSMERR_APPLETP_OCSP_INVALID_ANCHOR_CERT;
644 }
645 else {
646 /* partial chain, no root, not verifiable by anchor */
647 tpOcspDebug("tpVerifyOcspResp no root, no anchor");
648 cssmErr = CSSMERR_APPLETP_OCSP_NOT_TRUSTED;
649 }
650 if((issuer != NULL) && !issuer->isStatusFatal(cssmErr)) {
651 tpOcspDebug("...ignoring last error per trust setting");
652 ourRtn = ORS_Good;
653 }
654 else {
655 ourRtn = ORS_Unknown;
656 }
657 }
658 else {
659 tpOcspDebug("tpVerifyOcspResp SUCCESS; chain verified");
660 ourRtn = ORS_Good;
661 }
662
663 /* FIXME policy verify? */
664
665 errOut:
666 delete signerInfoTBD;
667 if (ocspResp_genTime && ocspResp_cssmTime) vfyCtx.verifyTime = cssmTimeStr;
668 if (ocspResp_genTime) free(ocspResp_genTime);
669 if (ocspResp_cssmTime) free(ocspResp_cssmTime);
670 /* any other cleanup? */
671 return ourRtn;
672 }