nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_crl.c
blob84a62418579b4a9e257f980dd39a727f247d43fb
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
21 * Contributor(s):
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_pl_crl.c
40 * CRL Function Definitions
44 #include "pkix_pl_crl.h"
46 extern PKIX_PL_HashTable *cachedCrlSigTable;
48 /* --Private-CRL-Functions------------------------------------- */
51 * FUNCTION: pkix_pl_CRL_GetVersion
52 * DESCRIPTION:
54 * Retrieves the version of the CRL pointed to by "crl" and stores it at
55 * "pVersion". The version number will either be 0 or 1 (corresponding to
56 * v1 or v2, respectively).
58 * Version ::= INTEGER { v1(0), v2(1), v3(2) }
60 * PARAMETERS:
61 * "crl"
62 * Address of CRL whose version is to be stored. Must be non-NULL.
63 * "pVersion"
64 * Address where a version will be stored. Must be non-NULL.
65 * "plContext"
66 * Platform-specific context pointer.
67 * THREAD SAFETY:
68 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
69 * RETURNS:
70 * Returns NULL if the function succeeds.
71 * Returns a CRL Error if the function fails in a non-fatal way.
72 * Returns a Fatal Error if the function fails in an unrecoverable way.
74 static PKIX_Error *
75 pkix_pl_CRL_GetVersion(
76 PKIX_PL_CRL *crl,
77 PKIX_UInt32 *pVersion,
78 void *plContext)
80 PKIX_UInt32 myVersion;
82 PKIX_ENTER(CRL, "pkix_pl_CRL_GetVersion");
83 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pVersion);
85 PKIX_NULLCHECK_ONE(crl->nssSignedCrl->crl.version.data);
87 myVersion = *(crl->nssSignedCrl->crl.version.data);
89 if (myVersion > 1) {
90 PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1ORV2);
93 *pVersion = myVersion;
95 cleanup:
97 PKIX_RETURN(CRL);
101 * FUNCTION: PKIX_PL_CRL_GetCRLNumber (see comments in pkix_pl_pki.h)
103 PKIX_Error *
104 PKIX_PL_CRL_GetCRLNumber(
105 PKIX_PL_CRL *crl,
106 PKIX_PL_BigInt **pCrlNumber,
107 void *plContext)
109 PKIX_PL_BigInt *crlNumber = NULL;
110 SECItem nssCrlNumber;
111 PLArenaPool *arena = NULL;
112 SECStatus status;
113 PKIX_UInt32 length = 0;
114 char *bytes = NULL;
116 PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLNumber");
117 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlNumber);
119 if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
121 PKIX_OBJECT_LOCK(crl);
123 if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
125 nssCrlNumber.type = 0;
126 nssCrlNumber.len = 0;
127 nssCrlNumber.data = NULL;
129 PKIX_CRL_DEBUG("\t\tCalling PORT_NewArena).\n");
130 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
131 if (arena == NULL) {
132 PKIX_ERROR(PKIX_OUTOFMEMORY);
135 PKIX_CRL_DEBUG("\t\tCalling CERT_FindCRLNumberExten\n");
136 status = CERT_FindCRLNumberExten
137 (arena, &crl->nssSignedCrl->crl, &nssCrlNumber);
139 if (status == SECSuccess) {
140 /* Get data in bytes then convert to bigint */
141 length = nssCrlNumber.len;
142 bytes = (char *)nssCrlNumber.data;
144 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
145 (bytes, length, &crlNumber, plContext),
146 PKIX_BIGINTCREATEWITHBYTESFAILED);
148 /* arena release does the job
149 PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n");
150 SECITEM_FreeItem(&nssCrlNumber, PKIX_FALSE);
152 crl->crlNumber = crlNumber;
154 } else {
156 crl->crlNumberAbsent = PKIX_TRUE;
160 PKIX_OBJECT_UNLOCK(crl);
164 PKIX_INCREF(crl->crlNumber);
166 *pCrlNumber = crl->crlNumber;
168 cleanup:
170 if (arena){
171 PKIX_CRL_DEBUG("\t\tCalling PORT_FreeArena).\n");
172 PORT_FreeArena(arena, PR_FALSE);
175 PKIX_RETURN(CRL);
179 * FUNCTION: pkix_pl_CRL_GetSignatureAlgId
181 * DESCRIPTION:
182 * Retrieves a pointer to the OID that represents the signature algorithm of
183 * the CRL pointed to by "crl" and stores it at "pSignatureAlgId".
185 * AlgorithmIdentifier ::= SEQUENCE {
186 * algorithm OBJECT IDENTIFIER,
187 * parameters ANY DEFINED BY algorithm OPTIONAL }
189 * PARAMETERS:
190 * "crl"
191 * Address of CRL whose signature algorithm OID is to be stored.
192 * Must be non-NULL.
193 * "pSignatureAlgId"
194 * Address where object pointer will be stored. Must be non-NULL.
195 * "plContext"
196 * Platform-specific context pointer.
197 * THREAD SAFETY:
198 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
199 * RETURNS:
200 * Returns NULL if the function succeeds.
201 * Returns a CRL Error if the function fails in a non-fatal way.
202 * Returns a Fatal Error if the function fails in an unrecoverable way.
204 static PKIX_Error *
205 pkix_pl_CRL_GetSignatureAlgId(
206 PKIX_PL_CRL *crl,
207 PKIX_PL_OID **pSignatureAlgId,
208 void *plContext)
210 CERTCrl *nssCrl = NULL;
211 PKIX_PL_OID *signatureAlgId = NULL;
212 SECAlgorithmID algorithm;
213 SECItem algBytes;
214 char *asciiOID = NULL;
216 PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId");
217 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId);
219 /* if we don't have a cached copy from before, we create one */
220 if (crl->signatureAlgId == NULL){
222 PKIX_OBJECT_LOCK(crl);
224 if (crl->signatureAlgId == NULL){
226 nssCrl = &(crl->nssSignedCrl->crl);
227 algorithm = nssCrl->signatureAlg;
228 algBytes = algorithm.algorithm;
230 PKIX_NULLCHECK_ONE(algBytes.data);
231 if (algBytes.len == 0) {
232 PKIX_ERROR_FATAL(PKIX_OIDBYTESLENGTH0);
235 PKIX_CHECK(pkix_pl_oidBytes2Ascii
236 (&algBytes, &asciiOID, plContext),
237 PKIX_OIDBYTES2ASCIIFAILED);
239 PKIX_CHECK(PKIX_PL_OID_Create
240 (asciiOID, &signatureAlgId, plContext),
241 PKIX_OIDCREATEFAILED);
243 /* save a cached copy in case it is asked for again */
244 crl->signatureAlgId = signatureAlgId;
247 PKIX_OBJECT_UNLOCK(crl);
251 PKIX_INCREF(crl->signatureAlgId);
252 *pSignatureAlgId = crl->signatureAlgId;
254 cleanup:
256 PKIX_FREE(asciiOID);
258 PKIX_RETURN(CRL);
262 * FUNCTION: pkix_pl_CRL_GetCRLEntries
263 * DESCRIPTION:
265 * Retrieves a pointer to the List of CRLEntries found in the CRL pointed to
266 * by "crl" and stores it at "pCRLEntries". If there are no CRLEntries,
267 * this functions stores NULL at "pCRLEntries".
269 * PARAMETERS:
270 * "crl"
271 * Address of CRL whose CRL Entries are to be retrieved. Must be non-NULL.
272 * "pCRLEntries"
273 * Address where object pointer will be stored. Must be non-NULL.
274 * "plContext"
275 * Platform-specific context pointer.
276 * THREAD SAFETY:
277 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
278 * RETURNS:
279 * Returns NULL if the function succeeds.
280 * Returns a CRL Error if the function fails in a non-fatal way.
281 * Returns a Fatal Error if the function fails in an unrecoverable way.
283 static PKIX_Error *
284 pkix_pl_CRL_GetCRLEntries(
285 PKIX_PL_CRL *crl,
286 PKIX_List **pCrlEntries,
287 void *plContext)
289 PKIX_List *entryList = NULL;
290 CERTCrl *nssCrl = NULL;
292 PKIX_ENTER(CRL, "pkix_pl_CRL_GetCRLEntries");
293 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlEntries);
295 /* if we don't have a cached copy from before, we create one */
296 if (crl->crlEntryList == NULL) {
298 PKIX_OBJECT_LOCK(crl);
300 if (crl->crlEntryList == NULL){
302 nssCrl = &(crl->nssSignedCrl->crl);
304 PKIX_CHECK(pkix_pl_CRLEntry_Create
305 (nssCrl->entries, &entryList, plContext),
306 PKIX_CRLENTRYCREATEFAILED);
308 PKIX_CHECK(PKIX_List_SetImmutable
309 (entryList, plContext),
310 PKIX_LISTSETIMMUTABLEFAILED);
312 crl->crlEntryList = entryList;
315 PKIX_OBJECT_UNLOCK(crl);
319 PKIX_INCREF(crl->crlEntryList);
321 *pCrlEntries = crl->crlEntryList;
323 cleanup:
325 PKIX_RETURN(CRL);
329 * FUNCTION: pkix_pl_CRL_Destroy
330 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
332 static PKIX_Error *
333 pkix_pl_CRL_Destroy(
334 PKIX_PL_Object *object,
335 void *plContext)
337 PKIX_PL_CRL *crl = NULL;
339 PKIX_ENTER(CRL, "pkix_pl_CRL_Destroy");
340 PKIX_NULLCHECK_ONE(object);
342 PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
343 PKIX_OBJECTNOTCRL);
345 crl = (PKIX_PL_CRL*)object;
347 PKIX_NULLCHECK_ONE(crl->nssSignedCrl);
349 PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n");
350 CERT_DestroyCrl(crl->nssSignedCrl);
351 crl->nssSignedCrl = NULL;
352 crl->crlNumberAbsent = PKIX_FALSE;
354 PKIX_DECREF(crl->issuer);
355 PKIX_DECREF(crl->signatureAlgId);
356 PKIX_DECREF(crl->crlNumber);
357 PKIX_DECREF(crl->crlEntryList);
358 PKIX_DECREF(crl->critExtOids);
360 cleanup:
362 PKIX_RETURN(CRL);
366 * FUNCTION: pkix_pl_CRL_ToString_Helper
367 * DESCRIPTION:
369 * Helper function that creates a string representation of the CRL pointed
370 * to by "crl" and stores it at "pString".
372 * PARAMETERS
373 * "crl"
374 * Address of CRL whose string representation is desired.
375 * Must be non-NULL.
376 * "pString"
377 * Address where object pointer will be stored. Must be non-NULL.
378 * "plContext"
379 * Platform-specific context pointer.
380 * THREAD SAFETY:
381 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
382 * RETURNS:
383 * Returns NULL if the function succeeds.
384 * Returns a CRL Error if the function fails in a non-fatal way.
385 * Returns a Fatal Error if the function fails in an unrecoverable way.
387 static PKIX_Error *
388 pkix_pl_CRL_ToString_Helper(
389 PKIX_PL_CRL *crl,
390 PKIX_PL_String **pString,
391 void *plContext)
393 char *asciiFormat = NULL;
394 PKIX_UInt32 crlVersion;
395 PKIX_PL_X500Name *crlIssuer = NULL;
396 PKIX_PL_OID *nssSignatureAlgId = NULL;
397 PKIX_PL_BigInt *crlNumber = NULL;
398 PKIX_List *crlEntryList = NULL;
399 PKIX_List *critExtOIDs = NULL;
400 PKIX_PL_String *formatString = NULL;
401 PKIX_PL_String *crlIssuerString = NULL;
402 PKIX_PL_String *lastUpdateString = NULL;
403 PKIX_PL_String *nextUpdateString = NULL;
404 PKIX_PL_String *nssSignatureAlgIdString = NULL;
405 PKIX_PL_String *crlNumberString = NULL;
406 PKIX_PL_String *crlEntryListString = NULL;
407 PKIX_PL_String *critExtOIDsString = NULL;
408 PKIX_PL_String *crlString = NULL;
410 PKIX_ENTER(CRL, "pkix_pl_CRL_ToString_Helper");
411 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pString);
413 asciiFormat =
414 "[\n"
415 "\tVersion: v%d\n"
416 "\tIssuer: %s\n"
417 "\tUpdate: [Last: %s\n"
418 "\t Next: %s]\n"
419 "\tSignatureAlgId: %s\n"
420 "\tCRL Number : %s\n"
421 "\n"
422 "\tEntry List: %s\n"
423 "\n"
424 "\tCritExtOIDs: %s\n"
425 "]\n";
427 PKIX_CHECK(PKIX_PL_String_Create
428 (PKIX_ESCASCII,
429 asciiFormat,
431 &formatString,
432 plContext),
433 PKIX_STRINGCREATEFAILED);
435 /* Version */
436 PKIX_CHECK(pkix_pl_CRL_GetVersion(crl, &crlVersion, plContext),
437 PKIX_CRLGETVERSIONFAILED);
439 /* Issuer */
440 PKIX_CHECK(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext),
441 PKIX_CRLGETISSUERFAILED);
443 PKIX_CHECK(PKIX_PL_Object_ToString
444 ((PKIX_PL_Object *)crlIssuer, &crlIssuerString, plContext),
445 PKIX_X500NAMETOSTRINGFAILED);
447 /* This update - No Date object created, use nss data directly */
448 PKIX_CHECK(pkix_pl_Date_ToString_Helper
449 (&(crl->nssSignedCrl->crl.lastUpdate),
450 &lastUpdateString,
451 plContext),
452 PKIX_DATETOSTRINGHELPERFAILED);
454 /* Next update - No Date object created, use nss data directly */
455 PKIX_CHECK(pkix_pl_Date_ToString_Helper
456 (&(crl->nssSignedCrl->crl.nextUpdate),
457 &nextUpdateString,
458 plContext),
459 PKIX_DATETOSTRINGHELPERFAILED);
461 /* Signature Algorithm Id */
462 PKIX_CHECK(pkix_pl_CRL_GetSignatureAlgId
463 (crl, &nssSignatureAlgId, plContext),
464 PKIX_CRLGETSIGNATUREALGIDFAILED);
466 PKIX_CHECK(PKIX_PL_Object_ToString
467 ((PKIX_PL_Object *)nssSignatureAlgId,
468 &nssSignatureAlgIdString,
469 plContext),
470 PKIX_OIDTOSTRINGFAILED);
472 /* CRL Number */
473 PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber
474 (crl, &crlNumber, plContext),
475 PKIX_CRLGETCRLNUMBERFAILED);
477 PKIX_TOSTRING(crlNumber, &crlNumberString, plContext,
478 PKIX_BIGINTTOSTRINGFAILED);
480 /* CRL Entries */
481 PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext),
482 PKIX_CRLGETCRLENTRIESFAILED);
484 PKIX_TOSTRING(crlEntryList, &crlEntryListString, plContext,
485 PKIX_LISTTOSTRINGFAILED);
487 /* CriticalExtensionOIDs */
488 PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs
489 (crl, &critExtOIDs, plContext),
490 PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED);
492 PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
493 PKIX_LISTTOSTRINGFAILED);
495 PKIX_CHECK(PKIX_PL_Sprintf
496 (&crlString,
497 plContext,
498 formatString,
499 crlVersion + 1,
500 crlIssuerString,
501 lastUpdateString,
502 nextUpdateString,
503 nssSignatureAlgIdString,
504 crlNumberString,
505 crlEntryListString,
506 critExtOIDsString),
507 PKIX_SPRINTFFAILED);
509 *pString = crlString;
511 cleanup:
513 PKIX_DECREF(crlIssuer);
514 PKIX_DECREF(nssSignatureAlgId);
515 PKIX_DECREF(crlNumber);
516 PKIX_DECREF(crlEntryList);
517 PKIX_DECREF(critExtOIDs);
518 PKIX_DECREF(crlIssuerString);
519 PKIX_DECREF(lastUpdateString);
520 PKIX_DECREF(nextUpdateString);
521 PKIX_DECREF(nssSignatureAlgIdString);
522 PKIX_DECREF(crlNumberString);
523 PKIX_DECREF(crlEntryListString);
524 PKIX_DECREF(critExtOIDsString);
525 PKIX_DECREF(formatString);
527 PKIX_RETURN(CRL);
531 * FUNCTION: pkix_pl_CRL_ToString
532 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
534 static PKIX_Error *
535 pkix_pl_CRL_ToString(
536 PKIX_PL_Object *object,
537 PKIX_PL_String **pString,
538 void *plContext)
540 PKIX_PL_String *crlString = NULL;
541 PKIX_PL_CRL *crl = NULL;
543 PKIX_ENTER(CRL, "pkix_pl_CRL_ToString");
544 PKIX_NULLCHECK_TWO(object, pString);
546 PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
547 PKIX_OBJECTNOTCRL);
549 crl = (PKIX_PL_CRL *) object;
551 PKIX_CHECK(pkix_pl_CRL_ToString_Helper(crl, &crlString, plContext),
552 PKIX_CRLTOSTRINGHELPERFAILED);
554 *pString = crlString;
556 cleanup:
558 PKIX_RETURN(CRL);
562 * FUNCTION: pkix_pl_CRL_Hashcode
563 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
565 static PKIX_Error *
566 pkix_pl_CRL_Hashcode(
567 PKIX_PL_Object *object,
568 PKIX_UInt32 *pHashcode,
569 void *plContext)
571 PKIX_PL_CRL *crl = NULL;
572 unsigned char *derBytes = NULL;
573 PKIX_UInt32 derLength;
574 PKIX_UInt32 certHash;
576 PKIX_ENTER(CRL, "pkix_pl_CRL_Hashcode");
577 PKIX_NULLCHECK_TWO(object, pHashcode);
579 PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
580 PKIX_OBJECTNOTCRL);
582 crl = (PKIX_PL_CRL *)object;
584 PKIX_NULLCHECK_TWO(crl->nssSignedCrl, crl->nssSignedCrl->derCrl);
586 derBytes = (crl->nssSignedCrl->derCrl)->data;
587 derLength = (crl->nssSignedCrl->derCrl)->len;
589 PKIX_NULLCHECK_ONE(derBytes);
590 PKIX_CHECK(pkix_hash(derBytes, derLength, &certHash, plContext),
591 PKIX_ERRORINHASH);
593 *pHashcode = certHash;
595 cleanup:
597 PKIX_RETURN(CRL);
601 * FUNCTION: pkix_pl_CRL_Equals
602 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
604 static PKIX_Error *
605 pkix_pl_CRL_Equals(
606 PKIX_PL_Object *firstObject,
607 PKIX_PL_Object *secondObject,
608 PKIX_Boolean *pResult,
609 void *plContext)
611 PKIX_PL_CRL *firstCrl = NULL;
612 PKIX_PL_CRL *secondCrl = NULL;
613 PKIX_UInt32 secondType;
615 PKIX_ENTER(CRL, "pkix_pl_CRL_Equals");
616 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
618 /* test that firstObject is a CRL */
619 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRL_TYPE, plContext),
620 PKIX_FIRSTOBJECTNOTCRL);
622 firstCrl = (PKIX_PL_CRL *)firstObject;
623 secondCrl = (PKIX_PL_CRL *)secondObject;
626 * Since we know firstObject is a CRL, if both references are
627 * identical, they must be equal
629 if (firstCrl == secondCrl){
630 *pResult = PKIX_TRUE;
631 goto cleanup;
635 * If secondCrl isn't a CRL, we don't throw an error.
636 * We simply return a Boolean result of FALSE
638 *pResult = PKIX_FALSE;
639 PKIX_CHECK(PKIX_PL_Object_GetType
640 ((PKIX_PL_Object *)secondCrl, &secondType, plContext),
641 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
642 if (secondType != PKIX_CRL_TYPE) goto cleanup;
644 /* Compare DER Bytes */
645 PKIX_NULLCHECK_TWO
646 (firstCrl->nssSignedCrl,
647 firstCrl->nssSignedCrl->derCrl);
649 PKIX_NULLCHECK_TWO
650 (secondCrl->nssSignedCrl,
651 secondCrl->nssSignedCrl->derCrl);
653 PKIX_CRL_DEBUG("\t\tCalling SECITEM_CompareItem on derCrl\n");
654 if (SECITEM_CompareItem(firstCrl->nssSignedCrl->derCrl,
655 secondCrl->nssSignedCrl->derCrl) == SECEqual) {
656 *pResult = PKIX_TRUE;
659 cleanup:
661 PKIX_RETURN(CRL);
665 * FUNCTION: pkix_pl_CRL_RegisterSelf
667 * DESCRIPTION:
668 * Registers PKIX_CRL_TYPE and its related functions with systemClasses[]
669 * THREAD SAFETY:
671 * Not Thread Safe - for performance and complexity reasons
673 * Since this function is only called by PKIX_PL_Initialize, which should
674 * only be called once, it is acceptable that this function is not
675 * thread-safe.
677 PKIX_Error *
678 pkix_pl_CRL_RegisterSelf(void *plContext)
681 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
682 pkix_ClassTable_Entry entry;
684 PKIX_ENTER(CRL, "pkix_pl_CRL_RegisterSelf");
686 entry.description = "CRL";
687 entry.objCounter = 0;
688 entry.typeObjectSize = sizeof(PKIX_PL_CRL);
689 entry.destructor = pkix_pl_CRL_Destroy;
690 entry.equalsFunction = pkix_pl_CRL_Equals;
691 entry.hashcodeFunction = pkix_pl_CRL_Hashcode;
692 entry.toStringFunction = pkix_pl_CRL_ToString;
693 entry.comparator = NULL;
694 entry.duplicateFunction = pkix_duplicateImmutable;
696 systemClasses[PKIX_CRL_TYPE] = entry;
698 PKIX_RETURN(CRL);
702 * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h)
704 PKIX_Error *
705 PKIX_PL_CRL_VerifyUpdateTime(
706 PKIX_PL_CRL *crl,
707 PKIX_PL_Date *date,
708 PKIX_Boolean *pResult,
709 void *plContext)
711 PRTime timeToCheck;
712 PRTime nextUpdate;
713 PRTime lastUpdate;
714 SECStatus status;
715 CERTCrl *nssCrl = NULL;
716 SECItem *nextUpdateDer = NULL;
717 PKIX_Boolean haveNextUpdate = PR_FALSE;
719 PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime");
720 PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult);
722 nssCrl = &(crl->nssSignedCrl->crl);
724 PKIX_CRL_DEBUG("\t\tCalling DER_DecodeTimeChoice on date\n");
725 status = DER_DecodeTimeChoice(&timeToCheck, &(date->nssTime));
726 if (status != SECSuccess) {
727 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED);
730 /* nextUpdate can be NULL. Checking before using it */
731 nextUpdateDer = &nssCrl->nextUpdate;
732 if (nextUpdateDer->data && nextUpdateDer->len) {
733 haveNextUpdate = PR_TRUE;
734 status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer);
735 if (status != SECSuccess) {
736 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED);
740 status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate));
741 if (status != SECSuccess) {
742 PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED);
745 if (!haveNextUpdate || nextUpdate < timeToCheck) {
746 *pResult = PKIX_FALSE;
747 goto cleanup;
750 if (lastUpdate <= timeToCheck) {
751 *pResult = PKIX_TRUE;
752 } else {
753 *pResult = PKIX_FALSE;
756 cleanup:
758 PKIX_RETURN(CRL);
762 * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL
763 * DESCRIPTION:
765 * Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl"
766 * and stores it at "pCRL". If the decoding of the CERTSignedCrl fails,
767 * a PKIX_Error is returned.
769 * PARAMETERS:
770 * "nssSignedCrl"
771 * Address of CERTSignedCrl. Must be non-NULL.
772 * "pCRL"
773 * Address where object pointer will be stored. Must be non-NULL.
774 * "plContext"
775 * Platform-specific context pointer.
776 * THREAD SAFETY:
777 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
778 * RETURNS:
779 * Returns NULL if the function succeeds.
780 * Returns a CRL Error if the function fails in a non-fatal way.
781 * Returns a Fatal Error if the function fails in an unrecoverable way.
783 PKIX_Error *
784 pkix_pl_CRL_CreateWithSignedCRL(
785 CERTSignedCrl *nssSignedCrl,
786 PKIX_PL_CRL **pCrl,
787 void *plContext)
789 SECStatus status;
790 PKIX_PL_CRL *crl = NULL;
792 PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL");
793 PKIX_NULLCHECK_TWO(nssSignedCrl, pCrl);
795 /* create a PKIX_PL_CRL object */
796 PKIX_CHECK(PKIX_PL_Object_Alloc
797 (PKIX_CRL_TYPE,
798 sizeof (PKIX_PL_CRL),
799 (PKIX_PL_Object **)&crl,
800 plContext),
801 PKIX_COULDNOTCREATECRLOBJECT);
803 /* populate the nssSignedCrl field */
804 crl->nssSignedCrl = nssSignedCrl;
806 PKIX_CRL_DEBUG("\t\tCalling CERT_CompleteCRLDecodeEntries\n");
807 status = CERT_CompleteCRLDecodeEntries(crl->nssSignedCrl);
809 if (status != SECSuccess) {
810 PKIX_ERROR(PKIX_CERTCOMPLETECRLDECODEDENTRIESFAILED);
813 crl->issuer = NULL;
814 crl->signatureAlgId = NULL;
815 crl->crlNumber = NULL;
816 crl->crlNumberAbsent = PKIX_FALSE;
817 crl->crlEntryList = NULL;
818 crl->critExtOids = NULL;
820 *pCrl = crl;
822 cleanup:
824 if (PKIX_ERROR_RECEIVED){
825 PKIX_DECREF(crl);
828 PKIX_RETURN(CRL);
832 * FUNCTION: pkix_pl_CRL_CreateToList
833 * DESCRIPTION:
835 * This function decodes a DER-encoded Certificate Revocation List pointed to
836 * by "derCrlItem", adding the resulting PKIX_PL_CRL, if the decoding was
837 * successful, to the List (possibly empty) pointed to by "crlList".
839 * PARAMETERS:
840 * "derCrlItem"
841 * The address of the SECItem containing the DER-encoded Certificate
842 * Revocation List. Must be non-NULL.
843 * "crlList"
844 * The address of the List to which the decoded CRL is added. May be
845 * empty, but must be non-NULL.
846 * "plContext"
847 * Platform-specific context pointer.
848 * THREAD SAFETY:
849 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
850 * RETURNS:
851 * Returns NULL if the function succeeds.
852 * Returns a CertStore Error if the function fails in a non-fatal way.
853 * Returns a Fatal Error if the function fails in an unrecoverable way.
855 PKIX_Error *
856 pkix_pl_CRL_CreateToList(
857 SECItem *derCrlItem,
858 PKIX_List *crlList,
859 void *plContext)
861 CERTSignedCrl *nssCrl = NULL;
862 PKIX_PL_CRL *crl = NULL;
864 PKIX_ENTER(CRL, "pkix_pl_CRL_CreateToList");
865 PKIX_NULLCHECK_TWO(derCrlItem, crlList);
867 nssCrl = CERT_DecodeDERCrl(NULL, derCrlItem, SEC_CRL_TYPE);
868 if (nssCrl == NULL) {
869 goto cleanup;
872 PKIX_CHECK(pkix_pl_CRL_CreateWithSignedCRL
873 (nssCrl, &crl, plContext),
874 PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
876 nssCrl = NULL;
878 PKIX_CHECK(PKIX_List_AppendItem
879 (crlList, (PKIX_PL_Object *) crl, plContext),
880 PKIX_LISTAPPENDITEMFAILED);
882 cleanup:
883 if (nssCrl) {
884 SEC_DestroyCrl(nssCrl);
887 PKIX_DECREF(crl);
889 PKIX_RETURN(CRL);
892 /* --Public-CRL-Functions------------------------------------- */
895 * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h)
897 PKIX_Error *
898 PKIX_PL_CRL_Create(
899 PKIX_PL_ByteArray *byteArray,
900 PKIX_PL_CRL **pCrl,
901 void *plContext)
903 CERTSignedCrl *nssSignedCrl = NULL;
904 SECItem *derCrlItem = NULL;
905 void *derBytes = NULL;
906 PKIX_UInt32 derLength;
907 PKIX_PL_CRL *crl = NULL;
909 PKIX_ENTER(CRL, "PKIX_PL_CRL_Create");
910 PKIX_NULLCHECK_TWO(byteArray, pCrl);
912 PKIX_CHECK(PKIX_PL_ByteArray_GetLength
913 (byteArray, &derLength, plContext),
914 PKIX_BYTEARRAYGETLENGTHFAILED);
916 if (derLength == 0){
917 PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING);
920 PKIX_CHECK(PKIX_PL_ByteArray_GetPointer
921 (byteArray, &derBytes, plContext),
922 PKIX_BYTEARRAYGETPOINTERFAILED);
924 PKIX_CRL_DEBUG("\t\tCalling SECITEM_AllocItem\n");
925 derCrlItem = SECITEM_AllocItem(NULL, NULL, derLength);
926 if (derCrlItem == NULL){
927 PKIX_ERROR(PKIX_OUTOFMEMORY);
930 PKIX_CRL_DEBUG("\t\tCalling PORT_Memcpy\n");
931 (void) PORT_Memcpy(derCrlItem->data, derBytes, derLength);
933 PKIX_CRL_DEBUG("\t\tCalling CERT_DecodeDERCrl\n");
934 nssSignedCrl = CERT_DecodeDERCrl(NULL, derCrlItem, SEC_CRL_TYPE);
935 if (nssSignedCrl == NULL){
936 PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED);
939 PKIX_CHECK(pkix_pl_CRL_CreateWithSignedCRL
940 (nssSignedCrl, &crl, plContext),
941 PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
943 *pCrl = crl;
945 cleanup:
947 if (derCrlItem != NULL){
948 PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n");
949 SECITEM_FreeItem(derCrlItem, PKIX_TRUE);
950 derCrlItem = NULL;
953 if (PKIX_ERROR_RECEIVED){
954 if (nssSignedCrl != NULL) {
955 PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n");
956 CERT_DestroyCrl(nssSignedCrl);
957 nssSignedCrl = NULL;
960 PKIX_DECREF(crl);
963 PKIX_FREE(derBytes);
965 PKIX_RETURN(CRL);
969 * FUNCTION: PKIX_PL_CRL_GetIssuer (see comments in pkix_pl_pki.h)
971 PKIX_Error *
972 PKIX_PL_CRL_GetIssuer(
973 PKIX_PL_CRL *crl,
974 PKIX_PL_X500Name **pCRLIssuer,
975 void *plContext)
977 PKIX_PL_String *crlString = NULL;
978 PKIX_PL_X500Name *issuer = NULL;
979 SECItem *derIssuerName = NULL;
980 CERTName *issuerName = NULL;
982 PKIX_ENTER(CRL, "PKIX_PL_CRL_GetIssuer");
983 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCRLIssuer);
985 /* if we don't have a cached copy from before, we create one */
986 if (crl->issuer == NULL){
988 PKIX_OBJECT_LOCK(crl);
990 if (crl->issuer == NULL) {
992 issuerName = &crl->nssSignedCrl->crl.name;
993 derIssuerName = &crl->nssSignedCrl->crl.derName;
995 PKIX_CHECK(
996 PKIX_PL_X500Name_CreateFromCERTName(derIssuerName,
997 issuerName,
998 &issuer,
999 plContext),
1000 PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
1002 /* save a cached copy in case it is asked for again */
1003 crl->issuer = issuer;
1006 PKIX_OBJECT_UNLOCK(crl);
1010 PKIX_INCREF(crl->issuer);
1012 *pCRLIssuer = crl->issuer;
1014 cleanup:
1016 PKIX_DECREF(crlString);
1018 PKIX_RETURN(CRL);
1023 * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs
1024 * (see comments in pkix_pl_pki.h)
1026 PKIX_Error *
1027 PKIX_PL_CRL_GetCriticalExtensionOIDs(
1028 PKIX_PL_CRL *crl,
1029 PKIX_List **pExtensions, /* list of PKIX_PL_OID */
1030 void *plContext)
1032 PKIX_List *oidsList = NULL;
1033 CERTCertExtension **extensions = NULL;
1034 CERTCrl *nssSignedCrl = NULL;
1036 PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCriticalExtensionOIDs");
1037 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pExtensions);
1039 /* if we don't have a cached copy from before, we create one */
1040 if (crl->critExtOids == NULL) {
1042 PKIX_OBJECT_LOCK(crl);
1044 nssSignedCrl = &(crl->nssSignedCrl->crl);
1045 extensions = nssSignedCrl->extensions;
1047 if (crl->critExtOids == NULL) {
1049 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
1050 (extensions, &oidsList, plContext),
1051 PKIX_GETCRITICALEXTENSIONOIDSFAILED);
1053 crl->critExtOids = oidsList;
1056 PKIX_OBJECT_UNLOCK(crl);
1060 /* We should return a copy of the List since this list changes */
1061 PKIX_DUPLICATE(crl->critExtOids, pExtensions, plContext,
1062 PKIX_OBJECTDUPLICATELISTFAILED);
1064 cleanup:
1066 PKIX_RETURN(CRL);
1071 * FUNCTION: PKIX_PL_CRL_GetCRLEntryForSerialNumber
1072 * (see comments in pkix_pl_pki.h)
1074 PKIX_Error *
1075 PKIX_PL_CRL_GetCRLEntryForSerialNumber(
1076 PKIX_PL_CRL *crl,
1077 PKIX_PL_BigInt *serialNumber,
1078 PKIX_PL_CRLEntry **pCRLEntry,
1079 void *plContext)
1081 PKIX_PL_CRLEntry *crlEntry = NULL;
1082 PKIX_List *crlEntryList = NULL;
1083 PKIX_UInt32 numEntries = 0;
1084 PKIX_UInt32 i = 0;
1085 PKIX_Boolean cmpResult = PKIX_FALSE;
1087 PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLEntryForSerialNumber");
1088 PKIX_NULLCHECK_THREE(crl, serialNumber, pCRLEntry);
1090 /* Assume there is no entry for Serial Number at start */
1091 *pCRLEntry = NULL;
1093 PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext),
1094 PKIX_CRLGETCRLENTRIESFAILED);
1096 if (crlEntryList == NULL) {
1097 goto cleanup;
1100 PKIX_CHECK(PKIX_List_GetLength(crlEntryList, &numEntries, plContext),
1101 PKIX_LISTGETLENGTHFAILED);
1103 for (i = 0; i < numEntries; i++){
1105 PKIX_CHECK(PKIX_List_GetItem
1106 (crlEntryList,
1108 (PKIX_PL_Object **)&crlEntry,
1109 plContext),
1110 PKIX_LISTGETITEMFAILED);
1112 PKIX_CHECK(PKIX_PL_Object_Equals
1113 ((PKIX_PL_Object *)crlEntry->serialNumber,
1114 (PKIX_PL_Object *)serialNumber,
1115 &cmpResult,
1116 plContext),
1117 PKIX_OBJECTEQUALSFAILED);
1119 /* Found the entry for Serial Number */
1120 if (cmpResult == PKIX_TRUE) {
1121 *pCRLEntry = crlEntry;
1122 goto cleanup;
1125 PKIX_DECREF(crlEntry);
1128 cleanup:
1130 PKIX_DECREF(crlEntryList);
1132 if (PKIX_ERROR_RECEIVED){
1133 PKIX_DECREF(crlEntry);
1136 PKIX_RETURN(CRL);
1140 * FUNCTION: PKIX_PL_CRL_VerifySignature (see comments in pkix_pl_pki.h)
1142 PKIX_Error *
1143 PKIX_PL_CRL_VerifySignature(
1144 PKIX_PL_CRL *crl,
1145 PKIX_PL_PublicKey *pubKey,
1146 void *plContext)
1148 PKIX_PL_CRL *cachedCrl = NULL;
1149 PKIX_Error *verifySig = NULL;
1150 PKIX_Error *cachedSig = NULL;
1151 PKIX_Boolean crlEqual = PKIX_FALSE;
1152 PKIX_Boolean crlInHash= PKIX_FALSE;
1153 CERTSignedCrl *nssSignedCrl = NULL;
1154 SECKEYPublicKey *nssPubKey = NULL;
1155 CERTSignedData *tbsCrl = NULL;
1156 SECStatus status;
1158 PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifySignature");
1159 PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pubKey);
1161 verifySig = PKIX_PL_HashTable_Lookup
1162 (cachedCrlSigTable,
1163 (PKIX_PL_Object *) pubKey,
1164 (PKIX_PL_Object **) &cachedCrl,
1165 plContext);
1167 if (cachedCrl != NULL && verifySig == NULL) {
1168 /* Cached Signature Table lookup succeed */
1169 PKIX_EQUALS(crl, cachedCrl, &crlEqual, plContext,
1170 PKIX_OBJECTEQUALSFAILED);
1171 if (crlEqual == PKIX_TRUE) {
1172 goto cleanup;
1174 /* Different PubKey may hash to same value, skip add */
1175 crlInHash = PKIX_TRUE;
1178 nssSignedCrl = crl->nssSignedCrl;
1179 tbsCrl = &nssSignedCrl->signatureWrap;
1181 PKIX_CRL_DEBUG("\t\tCalling SECKEY_ExtractPublicKey\n");
1182 nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
1183 if (!nssPubKey){
1184 PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
1187 PKIX_CRL_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey\n");
1188 status = CERT_VerifySignedDataWithPublicKey(tbsCrl, nssPubKey, NULL);
1190 if (status != SECSuccess) {
1191 PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
1194 if (crlInHash == PKIX_FALSE) {
1195 cachedSig = PKIX_PL_HashTable_Add
1196 (cachedCrlSigTable,
1197 (PKIX_PL_Object *) pubKey,
1198 (PKIX_PL_Object *) crl,
1199 plContext);
1201 if (cachedSig != NULL) {
1202 PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
1206 cleanup:
1208 if (nssPubKey){
1209 PKIX_CRL_DEBUG("\t\tCalling SECKEY_DestroyPublicKey\n");
1210 SECKEY_DestroyPublicKey(nssPubKey);
1211 nssPubKey = NULL;
1214 PKIX_DECREF(cachedCrl);
1215 PKIX_DECREF(verifySig);
1216 PKIX_DECREF(cachedSig);
1218 PKIX_RETURN(CRL);