]> git.saurik.com Git - apple/security.git/blame - OSX/libsecurity_apple_x509_tp/lib/TPDatabase.cpp
Security-59754.80.3.tar.gz
[apple/security.git] / OSX / libsecurity_apple_x509_tp / lib / TPDatabase.cpp
CommitLineData
b1ab9ed8 1/*
d8f41ccd
A
2 * Copyright (c) 2002-2009,2011-2012,2014 Apple Inc. All Rights Reserved.
3 *
b1ab9ed8
A
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
d8f41ccd 9 *
b1ab9ed8
A
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19/*
20 * TPDatabase.cpp - TP's DL/DB access functions.
21 *
b1ab9ed8
A
22 */
23
24#include <Security/cssmtype.h>
d8f41ccd 25#include <Security/cssmapi.h>
b1ab9ed8
A
26#include <security_cdsa_utilities/Schema.h> /* private API */
27#include <security_keychain/TrustKeychains.h> /* private SecTrustKeychainsGetMutex() */
28#include <Security/SecCertificatePriv.h> /* private SecInferLabelFromX509Name() */
29#include <Security/oidscert.h>
30#include "TPDatabase.h"
31#include "tpdebugging.h"
32#include "certGroupUtils.h"
33#include "TPCertInfo.h"
34#include "TPCrlInfo.h"
35#include "tpCrlVerify.h"
36#include "tpTime.h"
37
38
39/*
40 * Given a DL/DB, look up cert by subject name. Subsequent
41 * certs can be found using the returned result handle.
42 */
43static CSSM_DB_UNIQUE_RECORD_PTR tpCertLookup(
44 CSSM_DL_DB_HANDLE dlDb,
45 const CSSM_DATA *subjectName, // DER-encoded
46 CSSM_HANDLE_PTR resultHand, // RETURNED
47 CSSM_DATA_PTR cert) // RETURNED
48{
49 CSSM_QUERY query;
d8f41ccd 50 CSSM_SELECTION_PREDICATE predicate;
b1ab9ed8 51 CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
d8f41ccd 52
b1ab9ed8
A
53 cert->Data = NULL;
54 cert->Length = 0;
d8f41ccd 55
b1ab9ed8
A
56 /* SWAG until cert schema nailed down */
57 predicate.DbOperator = CSSM_DB_EQUAL;
d8f41ccd 58 predicate.Attribute.Info.AttributeNameFormat =
b1ab9ed8
A
59 CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
60 predicate.Attribute.Info.Label.AttributeName = (char*) "Subject";
61 predicate.Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
62 predicate.Attribute.Value = const_cast<CSSM_DATA_PTR>(subjectName);
63 predicate.Attribute.NumberOfValues = 1;
d8f41ccd 64
b1ab9ed8
A
65 query.RecordType = CSSM_DL_DB_RECORD_X509_CERTIFICATE;
66 query.Conjunctive = CSSM_DB_NONE;
67 query.NumSelectionPredicates = 1;
68 query.SelectionPredicate = &predicate;
69 query.QueryLimits.TimeLimit = 0; // FIXME - meaningful?
70 query.QueryLimits.SizeLimit = 1; // FIXME - meaningful?
71 query.QueryFlags = 0; // FIXME - used?
d8f41ccd 72
b1ab9ed8
A
73 CSSM_DL_DataGetFirst(dlDb,
74 &query,
75 resultHand,
76 NULL, // don't fetch attributes
77 cert,
78 &record);
79
80 return record;
81}
82
83/*
d8f41ccd 84 * Search a list of DBs for a cert which verifies specified subject item.
b1ab9ed8 85 * Just a boolean return - we found it, or not. If we did, we return
d8f41ccd 86 * TPCertInfo associated with the raw cert.
b1ab9ed8 87 * A true partialIssuerKey on return indicates that caller must deal
d8f41ccd 88 * with partial public key processing later.
b1ab9ed8 89 * If verifyCurrent is true, we will not return a cert which is not
d8f41ccd 90 * temporally valid; else we may well do so.
b1ab9ed8
A
91 */
92TPCertInfo *tpDbFindIssuerCert(
93 Allocator &alloc,
94 CSSM_CL_HANDLE clHand,
95 CSSM_CSP_HANDLE cspHand,
96 const TPClItemInfo *subjectItem,
97 const CSSM_DL_DB_LIST *dbList,
98 const char *verifyTime, // may be NULL
60c433a9
A
99 bool &partialIssuerKey, // RETURNED
100 TPCertInfo *oldRoot)
b1ab9ed8
A
101{
102 StLock<Mutex> _(SecTrustKeychainsGetMutex());
103
104 uint32 dbDex;
105 CSSM_HANDLE resultHand;
d8f41ccd 106 CSSM_DATA cert;
b1ab9ed8
A
107 CSSM_DL_DB_HANDLE dlDb;
108 CSSM_DB_UNIQUE_RECORD_PTR record;
109 TPCertInfo *issuerCert = NULL;
110 bool foundIt;
111 TPCertInfo *expiredIssuer = NULL;
d8f41ccd
A
112 TPCertInfo *nonRootIssuer = NULL;
113
b1ab9ed8
A
114 partialIssuerKey = false;
115 if(dbList == NULL) {
116 return NULL;
117 }
118 for(dbDex=0; dbDex<dbList->NumHandles; dbDex++) {
119 dlDb = dbList->DLDBHandle[dbDex];
120 cert.Data = NULL;
121 cert.Length = 0;
866f8763 122 resultHand = CSSM_INVALID_HANDLE;
b1ab9ed8
A
123 record = tpCertLookup(dlDb,
124 subjectItem->issuerName(),
125 &resultHand,
126 &cert);
d8f41ccd
A
127 /* remember we have to:
128 * -- abort this query regardless, and
129 * -- free the CSSM_DATA cert regardless, and
130 * -- free the unique record if we don't use it
b1ab9ed8
A
131 * (by placing it in issuerCert)...
132 */
133 if(record != NULL) {
134 /* Found one */
135 assert(cert.Data != NULL);
d8f41ccd 136 tpDbDebug("tpDbFindIssuerCert: found cert record (1) %p", record);
b1ab9ed8
A
137 issuerCert = NULL;
138 CSSM_RETURN crtn = CSSM_OK;
139 try {
140 issuerCert = new TPCertInfo(clHand, cspHand, &cert, TIC_CopyData, verifyTime);
141 }
142 catch(...) {
143 crtn = CSSMERR_TP_INVALID_CERTIFICATE;
144 }
145
146 /* we're done with raw cert data */
147 tpFreePluginMemory(dlDb.DLHandle, cert.Data);
148 cert.Data = NULL;
149 cert.Length = 0;
d8f41ccd 150
b1ab9ed8
A
151 /* Does it verify the subject cert? */
152 if(crtn == CSSM_OK) {
153 crtn = subjectItem->verifyWithIssuer(issuerCert);
154 }
d8f41ccd 155
b1ab9ed8 156 /*
d8f41ccd 157 * Handle temporal invalidity - if so and this is the first one
b1ab9ed8
A
158 * we've seen, hold on to it while we search for better one.
159 */
e3d460c9 160 if(crtn == CSSM_OK) {
b1ab9ed8 161 if(issuerCert->isExpired() || issuerCert->isNotValidYet()) {
d8f41ccd
A
162 /*
163 * Exact value not important here, this just uniquely identifies
b1ab9ed8
A
164 * this situation in the switch below.
165 */
166 tpDbDebug("tpDbFindIssuerCert: holding expired cert (1)");
167 crtn = CSSM_CERT_STATUS_EXPIRED;
e3d460c9
A
168 /* Delete old stashed expired issuer */
169 if (expiredIssuer) {
170 expiredIssuer->freeUniqueRecord();
171 delete expiredIssuer;
172 }
b1ab9ed8
A
173 expiredIssuer = issuerCert;
174 expiredIssuer->dlDbHandle(dlDb);
175 expiredIssuer->uniqueRecord(record);
176 }
177 }
d8f41ccd
A
178 /*
179 * Prefer a root over an intermediate issuer if we can get one
180 * (in case a cross-signed intermediate and root are both available)
181 */
e3d460c9
A
182 if(crtn == CSSM_OK && !issuerCert->isSelfSigned()) {
183 /*
184 * Exact value not important here, this just uniquely identifies
185 * this situation in the switch below.
186 */
187 tpDbDebug("tpDbFindIssuerCert: holding non-root cert (1)");
188 crtn = CSSM_CERT_STATUS_IS_ROOT;
189 /*
190 * If the old intermediate was temporally invalid, replace it.
191 * (Regardless of temporal validity of new one we found, because
192 * as far as this code is concerned they're equivalent.)
193 */
194 if(!nonRootIssuer ||
195 (nonRootIssuer && (nonRootIssuer->isExpired() || nonRootIssuer->isNotValidYet()))) {
196 if(nonRootIssuer) {
197 nonRootIssuer->freeUniqueRecord();
198 delete nonRootIssuer;
199 }
d8f41ccd
A
200 nonRootIssuer = issuerCert;
201 nonRootIssuer->dlDbHandle(dlDb);
202 nonRootIssuer->uniqueRecord(record);
203 }
e3d460c9
A
204 else {
205 delete issuerCert;
206 CSSM_DL_FreeUniqueRecord(dlDb, record);
207 issuerCert = NULL;
208 }
d8f41ccd 209 }
b1ab9ed8 210 switch(crtn) {
b1ab9ed8
A
211 case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE:
212 partialIssuerKey = true;
213 break;
60c433a9
A
214 case CSSM_OK:
215 if((oldRoot == NULL) ||
216 !tp_CompareCerts(issuerCert->itemData(), oldRoot->itemData())) {
217 /* We found a new root cert which does not match the old one */
218 break;
219 }
220 /* else fall through to search for a different one */
b1ab9ed8 221 default:
d8f41ccd
A
222 if(issuerCert != NULL) {
223 /* either holding onto this cert, or done with it. */
224 if(crtn != CSSM_CERT_STATUS_EXPIRED &&
225 crtn != CSSM_CERT_STATUS_IS_ROOT) {
226 delete issuerCert;
227 CSSM_DL_FreeUniqueRecord(dlDb, record);
228 }
229 issuerCert = NULL;
b1ab9ed8 230 }
d8f41ccd 231
b1ab9ed8 232 /*
d8f41ccd
A
233 * Continue searching this DB. Break on finding the holy
234 * grail or no more records found.
b1ab9ed8
A
235 */
236 for(;;) {
237 cert.Data = NULL;
238 cert.Length = 0;
239 record = NULL;
d8f41ccd 240 CSSM_RETURN crtn = CSSM_DL_DataGetNext(dlDb,
b1ab9ed8 241 resultHand,
d8f41ccd 242 NULL, // no attrs
b1ab9ed8
A
243 &cert,
244 &record);
245 if(crtn) {
246 /* no more, done with this DB */
247 assert(cert.Data == NULL);
248 break;
249 }
250 assert(cert.Data != NULL);
d8f41ccd
A
251 tpDbDebug("tpDbFindIssuerCert: found cert record (2) %p", record);
252
b1ab9ed8
A
253 /* found one - does it verify subject? */
254 try {
d8f41ccd 255 issuerCert = new TPCertInfo(clHand, cspHand, &cert, TIC_CopyData,
b1ab9ed8
A
256 verifyTime);
257 }
258 catch(...) {
259 crtn = CSSMERR_TP_INVALID_CERTIFICATE;
260 }
261 /* we're done with raw cert data */
262 tpFreePluginMemory(dlDb.DLHandle, cert.Data);
263 cert.Data = NULL;
264 cert.Length = 0;
d8f41ccd 265
b1ab9ed8
A
266 if(crtn == CSSM_OK) {
267 crtn = subjectItem->verifyWithIssuer(issuerCert);
268 }
269
270 /* temporal validity check, again */
e3d460c9 271 if(crtn == CSSM_OK) {
b1ab9ed8
A
272 if(issuerCert->isExpired() || issuerCert->isNotValidYet()) {
273 tpDbDebug("tpDbFindIssuerCert: holding expired cert (2)");
274 crtn = CSSM_CERT_STATUS_EXPIRED;
e3d460c9
A
275 /* Delete old stashed expired issuer */
276 if (expiredIssuer) {
277 expiredIssuer->freeUniqueRecord();
278 delete expiredIssuer;
279 }
b1ab9ed8
A
280 expiredIssuer = issuerCert;
281 expiredIssuer->dlDbHandle(dlDb);
282 expiredIssuer->uniqueRecord(record);
283 }
284 }
d8f41ccd 285 /* self-signed check, again */
e3d460c9
A
286 if(crtn == CSSM_OK && !issuerCert->isSelfSigned()) {
287 tpDbDebug("tpDbFindIssuerCert: holding non-root cert (2)");
288 crtn = CSSM_CERT_STATUS_IS_ROOT;
289 /*
290 * If the old intermediate was temporally invalid, replace it.
291 * (Regardless of temporal validity of new one we found, because
292 * as far as this code is concerned they're equivalent.)
293 */
294 if(!nonRootIssuer ||
295 (nonRootIssuer && (nonRootIssuer->isExpired() || nonRootIssuer->isNotValidYet()))) {
296 if(nonRootIssuer) {
297 nonRootIssuer->freeUniqueRecord();
298 delete nonRootIssuer;
299 }
d8f41ccd
A
300 nonRootIssuer = issuerCert;
301 nonRootIssuer->dlDbHandle(dlDb);
302 nonRootIssuer->uniqueRecord(record);
303 }
e3d460c9
A
304 else {
305 delete issuerCert;
306 CSSM_DL_FreeUniqueRecord(dlDb, record);
307 issuerCert = NULL;
308 }
d8f41ccd 309 }
b1ab9ed8
A
310
311 foundIt = false;
312 switch(crtn) {
313 case CSSM_OK:
60c433a9
A
314 /* duplicate check, again */
315 if((oldRoot == NULL) ||
316 !tp_CompareCerts(issuerCert->itemData(), oldRoot->itemData())) {
317 foundIt = true;
318 }
319 break;
b1ab9ed8
A
320 case CSSMERR_CSP_APPLE_PUBLIC_KEY_INCOMPLETE:
321 partialIssuerKey = true;
322 foundIt = true;
323 break;
324 default:
325 break;
326 }
327 if(foundIt) {
328 /* yes! */
329 break;
330 }
d8f41ccd
A
331 if(issuerCert != NULL) {
332 /* either holding onto this cert, or done with it. */
333 if(crtn != CSSM_CERT_STATUS_EXPIRED &&
334 crtn != CSSM_CERT_STATUS_IS_ROOT) {
335 delete issuerCert;
336 CSSM_DL_FreeUniqueRecord(dlDb, record);
337 }
338 issuerCert = NULL;
b1ab9ed8 339 }
b1ab9ed8
A
340 } /* searching subsequent records */
341 } /* switch verify */
342
343 if(record != NULL) {
344 /* NULL record --> end of search --> DB auto-aborted */
345 crtn = CSSM_DL_DataAbortQuery(dlDb, resultHand);
346 assert(crtn == CSSM_OK);
347 }
348 if(issuerCert != NULL) {
349 /* successful return */
350 tpDbDebug("tpDbFindIssuer: returning record %p", record);
351 issuerCert->dlDbHandle(dlDb);
352 issuerCert->uniqueRecord(record);
353 if(expiredIssuer != NULL) {
354 /* We found a replacement */
355 tpDbDebug("tpDbFindIssuer: discarding expired cert");
356 expiredIssuer->freeUniqueRecord();
357 delete expiredIssuer;
358 }
d8f41ccd
A
359 /* Avoid deleting the non-root cert if same as expired cert */
360 if(nonRootIssuer != NULL && nonRootIssuer != expiredIssuer) {
361 /* We found a replacement */
362 tpDbDebug("tpDbFindIssuer: discarding non-root cert");
363 nonRootIssuer->freeUniqueRecord();
364 delete nonRootIssuer;
365 }
b1ab9ed8
A
366 return issuerCert;
367 }
368 } /* tpCertLookup, i.e., CSSM_DL_DataGetFirst, succeeded */
369 else {
370 assert(cert.Data == NULL);
371 assert(resultHand == 0);
372 }
373 } /* main loop searching dbList */
374
d8f41ccd
A
375 if(nonRootIssuer != NULL) {
376 /* didn't find root issuer, so use this one */
377 tpDbDebug("tpDbFindIssuer: taking non-root issuer cert, record %p",
378 nonRootIssuer->uniqueRecord());
379 if(expiredIssuer != NULL && expiredIssuer != nonRootIssuer) {
380 expiredIssuer->freeUniqueRecord();
381 delete expiredIssuer;
382 }
383 return nonRootIssuer;
384 }
385
b1ab9ed8
A
386 if(expiredIssuer != NULL) {
387 /* OK, we'll take this one */
d8f41ccd 388 tpDbDebug("tpDbFindIssuer: taking expired cert after all, record %p",
b1ab9ed8
A
389 expiredIssuer->uniqueRecord());
390 return expiredIssuer;
391 }
392 /* issuer not found */
393 return NULL;
394}
395
396/*
d8f41ccd
A
397 * Given a DL/DB, look up CRL by issuer name and validity time.
398 * Subsequent CRLs can be found using the returned result handle.
b1ab9ed8
A
399 */
400#define SEARCH_BY_DATE 1
401
402static CSSM_DB_UNIQUE_RECORD_PTR tpCrlLookup(
403 CSSM_DL_DB_HANDLE dlDb,
404 const CSSM_DATA *issuerName, // DER-encoded
405 CSSM_TIMESTRING verifyTime, // may be NULL, implies "now"
406 CSSM_HANDLE_PTR resultHand, // RETURNED
407 CSSM_DATA_PTR crl) // RETURNED
408{
409 CSSM_QUERY query;
d8f41ccd 410 CSSM_SELECTION_PREDICATE pred[3];
b1ab9ed8
A
411 CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
412 char timeStr[CSSM_TIME_STRLEN + 1];
d8f41ccd 413
b1ab9ed8
A
414 crl->Data = NULL;
415 crl->Length = 0;
d8f41ccd 416
b1ab9ed8
A
417 /* Three predicates...first, the issuer name */
418 pred[0].DbOperator = CSSM_DB_EQUAL;
d8f41ccd 419 pred[0].Attribute.Info.AttributeNameFormat =
b1ab9ed8
A
420 CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
421 pred[0].Attribute.Info.Label.AttributeName = (char*) "Issuer";
422 pred[0].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
423 pred[0].Attribute.Value = const_cast<CSSM_DATA_PTR>(issuerName);
424 pred[0].Attribute.NumberOfValues = 1;
d8f41ccd 425
b1ab9ed8
A
426 /* now before/after. Cook up an appropriate time string. */
427 if(verifyTime != NULL) {
428 /* Caller spec'd tolerate any format */
427c49bc 429 int rtn = tpTimeToCssmTimestring(verifyTime, (unsigned)strlen(verifyTime), timeStr);
b1ab9ed8
A
430 if(rtn) {
431 tpErrorLog("tpCrlLookup: Invalid VerifyTime string\n");
432 return NULL;
433 }
434 }
435 else {
436 /* right now */
437 StLock<Mutex> _(tpTimeLock());
b54c578e 438 timeAtNowPlus(0, TP_TIME_CSSM, timeStr);
b1ab9ed8
A
439 }
440 CSSM_DATA timeData;
441 timeData.Data = (uint8 *)timeStr;
442 timeData.Length = CSSM_TIME_STRLEN;
d8f41ccd 443
b1ab9ed8
A
444 #if SEARCH_BY_DATE
445 pred[1].DbOperator = CSSM_DB_LESS_THAN;
446 pred[1].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
447 pred[1].Attribute.Info.Label.AttributeName = (char*) "NextUpdate";
448 pred[1].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
449 pred[1].Attribute.Value = &timeData;
450 pred[1].Attribute.NumberOfValues = 1;
d8f41ccd 451
b1ab9ed8
A
452 pred[2].DbOperator = CSSM_DB_GREATER_THAN;
453 pred[2].Attribute.Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
454 pred[2].Attribute.Info.Label.AttributeName = (char*) "ThisUpdate";
455 pred[2].Attribute.Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
456 pred[2].Attribute.Value = &timeData;
457 pred[2].Attribute.NumberOfValues = 1;
458 #endif
d8f41ccd 459
b1ab9ed8
A
460 query.RecordType = CSSM_DL_DB_RECORD_X509_CRL;
461 query.Conjunctive = CSSM_DB_AND;
462 #if SEARCH_BY_DATE
463 query.NumSelectionPredicates = 3;
464 #else
465 query.NumSelectionPredicates = 1;
466 #endif
467 query.SelectionPredicate = pred;
468 query.QueryLimits.TimeLimit = 0; // FIXME - meaningful?
469 query.QueryLimits.SizeLimit = 1; // FIXME - meaningful?
470 query.QueryFlags = 0; // FIXME - used?
d8f41ccd 471
b1ab9ed8
A
472 CSSM_DL_DataGetFirst(dlDb,
473 &query,
474 resultHand,
475 NULL, // don't fetch attributes
476 crl,
477 &record);
478 return record;
479}
480
481/*
d8f41ccd
A
482 * Search a list of DBs for a CRL from the specified issuer and (optional)
483 * TPVerifyContext.verifyTime.
b1ab9ed8
A
484 * Just a boolean return - we found it, or not. If we did, we return a
485 * TPCrlInfo which has been verified with the specified TPVerifyContext.
486 */
487TPCrlInfo *tpDbFindIssuerCrl(
488 TPVerifyContext &vfyCtx,
489 const CSSM_DATA &issuer,
490 TPCertInfo &forCert)
491{
492 StLock<Mutex> _(SecTrustKeychainsGetMutex());
493
494 uint32 dbDex;
495 CSSM_HANDLE resultHand;
d8f41ccd 496 CSSM_DATA crl;
b1ab9ed8
A
497 CSSM_DL_DB_HANDLE dlDb;
498 CSSM_DB_UNIQUE_RECORD_PTR record;
499 TPCrlInfo *issuerCrl = NULL;
500 CSSM_DL_DB_LIST_PTR dbList = vfyCtx.dbList;
501 CSSM_RETURN crtn;
d8f41ccd 502
b1ab9ed8
A
503 if(dbList == NULL) {
504 return NULL;
505 }
506 for(dbDex=0; dbDex<dbList->NumHandles; dbDex++) {
507 dlDb = dbList->DLDBHandle[dbDex];
508 crl.Data = NULL;
509 crl.Length = 0;
866f8763 510 resultHand = CSSM_INVALID_HANDLE;
b1ab9ed8
A
511 record = tpCrlLookup(dlDb,
512 &issuer,
513 vfyCtx.verifyTime,
514 &resultHand,
515 &crl);
d8f41ccd
A
516 /* remember we have to:
517 * -- abort this query regardless, and
518 * -- free the CSSM_DATA crl regardless, and
519 * -- free the unique record if we don't use it
b1ab9ed8
A
520 * (by placing it in issuerCert)...
521 */
522 if(record != NULL) {
523 /* Found one */
524 assert(crl.Data != NULL);
d8f41ccd 525 issuerCrl = new TPCrlInfo(vfyCtx.clHand,
b1ab9ed8 526 vfyCtx.cspHand,
d8f41ccd
A
527 &crl,
528 TIC_CopyData,
b1ab9ed8
A
529 vfyCtx.verifyTime);
530 /* we're done with raw CRL data */
d8f41ccd 531 /* FIXME this assumes that vfyCtx.alloc is the same as the
b1ab9ed8
A
532 * allocator associated with DlDB...OK? */
533 tpFreeCssmData(vfyCtx.alloc, &crl, CSSM_FALSE);
534 crl.Data = NULL;
535 crl.Length = 0;
d8f41ccd 536
b1ab9ed8
A
537 /* and we're done with the record */
538 CSSM_DL_FreeUniqueRecord(dlDb, record);
d8f41ccd 539
b1ab9ed8
A
540 /* Does it verify with specified context? */
541 crtn = issuerCrl->verifyWithContextNow(vfyCtx, &forCert);
542 if(crtn) {
d8f41ccd 543
b1ab9ed8
A
544 delete issuerCrl;
545 issuerCrl = NULL;
d8f41ccd 546
b1ab9ed8 547 /*
d8f41ccd
A
548 * Verify fail. Continue searching this DB. Break on
549 * finding the holy grail or no more records found.
b1ab9ed8
A
550 */
551 for(;;) {
552 crl.Data = NULL;
553 crl.Length = 0;
d8f41ccd 554 crtn = CSSM_DL_DataGetNext(dlDb,
b1ab9ed8 555 resultHand,
d8f41ccd 556 NULL, // no attrs
b1ab9ed8
A
557 &crl,
558 &record);
559 if(crtn) {
560 /* no more, done with this DB */
561 assert(crl.Data == NULL);
562 break;
563 }
564 assert(crl.Data != NULL);
d8f41ccd 565
b1ab9ed8 566 /* found one - is it any good? */
d8f41ccd 567 issuerCrl = new TPCrlInfo(vfyCtx.clHand,
b1ab9ed8 568 vfyCtx.cspHand,
d8f41ccd
A
569 &crl,
570 TIC_CopyData,
b1ab9ed8
A
571 vfyCtx.verifyTime);
572 /* we're done with raw CRL data */
d8f41ccd 573 /* FIXME this assumes that vfyCtx.alloc is the same as the
b1ab9ed8
A
574 * allocator associated with DlDB...OK? */
575 tpFreeCssmData(vfyCtx.alloc, &crl, CSSM_FALSE);
576 crl.Data = NULL;
577 crl.Length = 0;
578
579 CSSM_DL_FreeUniqueRecord(dlDb, record);
580
581 crtn = issuerCrl->verifyWithContextNow(vfyCtx, &forCert);
582 if(crtn == CSSM_OK) {
583 /* yes! */
584 break;
585 }
586 delete issuerCrl;
587 issuerCrl = NULL;
588 } /* searching subsequent records */
589 } /* verify fail */
590 /* else success! */
591
592 if(issuerCrl != NULL) {
593 /* successful return */
594 CSSM_DL_DataAbortQuery(dlDb, resultHand);
595 tpDebug("tpDbFindIssuerCrl: found CRL record %p", record);
596 return issuerCrl;
597 }
598 } /* tpCrlLookup, i.e., CSSM_DL_DataGetFirst, succeeded */
599 else {
600 assert(crl.Data == NULL);
601 }
602 /* in any case, abort the query for this db */
603 CSSM_DL_DataAbortQuery(dlDb, resultHand);
d8f41ccd 604
b1ab9ed8
A
605 } /* main loop searching dbList */
606
607 /* issuer not found */
608 return NULL;
609}
610