nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_crlentry.c
blob3d742a94a29bc797da8f95d3c66a86736636bf2e
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_crlentry.c
40 * CRLENTRY Function Definitions
44 #include "pkix_pl_crlentry.h"
46 /* --Private-CRLEntry-Functions------------------------------------- */
49 * FUNCTION: pkix_pl_CRLEntry_Destroy
50 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
52 static PKIX_Error *
53 pkix_pl_CRLEntry_Destroy(
54 PKIX_PL_Object *object,
55 void *plContext)
57 PKIX_PL_CRLEntry *crlEntry = NULL;
59 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Destroy");
60 PKIX_NULLCHECK_ONE(object);
62 PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
63 PKIX_OBJECTNOTCRLENTRY);
65 crlEntry = (PKIX_PL_CRLEntry*)object;
67 /* crlEntry->nssCrlEntry is freed by NSS when freeing CRL */
68 crlEntry->userReasonCode = 0;
69 crlEntry->userReasonCodeAbsent = PKIX_FALSE;
70 crlEntry->nssCrlEntry = NULL;
71 PKIX_DECREF(crlEntry->serialNumber);
72 PKIX_DECREF(crlEntry->critExtOids);
74 cleanup:
76 PKIX_RETURN(CRLENTRY);
80 * FUNCTION: pkix_pl_CRLEntry_ToString_Helper
82 * DESCRIPTION:
83 * Helper function that creates a string representation of the CRLEntry
84 * pointed to by "crlEntry" and stores it at "pString".
86 * PARAMETERS
87 * "crlEntry"
88 * Address of CRLEntry whose string representation is desired.
89 * Must be non-NULL.
90 * "pString"
91 * Address where object pointer will be stored. Must be non-NULL.
92 * "plContext"
93 * Platform-specific context pointer.
94 * THREAD SAFETY:
95 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
96 * RETURNS:
97 * Returns NULL if the function succeeds.
98 * Returns a CRLEntry Error if the function fails in a non-fatal way.
99 * Returns a Fatal Error if the function fails in an unrecoverable way.
101 PKIX_Error *
102 pkix_pl_CRLEntry_ToString_Helper(
103 PKIX_PL_CRLEntry *crlEntry,
104 PKIX_PL_String **pString,
105 void *plContext)
107 char *asciiFormat = NULL;
108 PKIX_List *critExtOIDs = NULL;
109 PKIX_PL_String *crlEntryString = NULL;
110 PKIX_PL_String *formatString = NULL;
111 PKIX_PL_String *crlSerialNumberString = NULL;
112 PKIX_PL_String *crlRevocationDateString = NULL;
113 PKIX_PL_String *critExtOIDsString = NULL;
114 PKIX_Int32 reasonCode = 0;
116 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString_Helper");
117 PKIX_NULLCHECK_FOUR
118 (crlEntry,
119 crlEntry->serialNumber,
120 crlEntry->nssCrlEntry,
121 pString);
123 asciiFormat =
124 "\n\t[\n"
125 "\tSerialNumber: %s\n"
126 "\tReasonCode: %d\n"
127 "\tRevocationDate: %s\n"
128 "\tCritExtOIDs: %s\n"
129 "\t]\n\t";
131 PKIX_CHECK(PKIX_PL_String_Create
132 (PKIX_ESCASCII,
133 asciiFormat,
135 &formatString,
136 plContext),
137 PKIX_STRINGCREATEFAILED);
139 /* SerialNumber */
140 PKIX_CHECK(PKIX_PL_Object_ToString
141 ((PKIX_PL_Object *)crlEntry->serialNumber,
142 &crlSerialNumberString,
143 plContext),
144 PKIX_BIGINTTOSTRINGHELPERFAILED);
146 /* RevocationDate - No Date object created, use nss data directly */
147 PKIX_CHECK(pkix_pl_Date_ToString_Helper
148 (&(crlEntry->nssCrlEntry->revocationDate),
149 &crlRevocationDateString,
150 plContext),
151 PKIX_DATETOSTRINGHELPERFAILED);
153 /* CriticalExtensionOIDs */
154 PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
155 (crlEntry, &critExtOIDs, plContext),
156 PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED);
158 PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
159 PKIX_LISTTOSTRINGFAILED);
161 /* Revocation Reason Code */
162 PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
163 (crlEntry, &reasonCode, plContext),
164 PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
166 PKIX_CHECK(PKIX_PL_Sprintf
167 (&crlEntryString,
168 plContext,
169 formatString,
170 crlSerialNumberString,
171 reasonCode,
172 crlRevocationDateString,
173 critExtOIDsString),
174 PKIX_SPRINTFFAILED);
176 *pString = crlEntryString;
178 cleanup:
180 PKIX_DECREF(critExtOIDs);
181 PKIX_DECREF(crlSerialNumberString);
182 PKIX_DECREF(crlRevocationDateString);
183 PKIX_DECREF(critExtOIDsString);
184 PKIX_DECREF(formatString);
186 PKIX_RETURN(CRLENTRY);
190 * FUNCTION: pkix_pl_CRLEntry_ToString
191 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
193 static PKIX_Error *
194 pkix_pl_CRLEntry_ToString(
195 PKIX_PL_Object *object,
196 PKIX_PL_String **pString,
197 void *plContext)
199 PKIX_PL_String *crlEntryString = NULL;
200 PKIX_PL_CRLEntry *crlEntry = NULL;
202 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString");
203 PKIX_NULLCHECK_TWO(object, pString);
205 PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
206 PKIX_OBJECTNOTCRLENTRY);
208 crlEntry = (PKIX_PL_CRLEntry *) object;
210 PKIX_CHECK(pkix_pl_CRLEntry_ToString_Helper
211 (crlEntry, &crlEntryString, plContext),
212 PKIX_CRLENTRYTOSTRINGHELPERFAILED);
214 *pString = crlEntryString;
216 cleanup:
218 PKIX_RETURN(CRLENTRY);
222 * FUNCTION: pkix_pl_CRLEntry_Extensions_Hashcode
223 * DESCRIPTION:
225 * For each CRL Entry extension stored at NSS structure CERTCertExtension,
226 * get its derbyte data and do the hash.
228 * PARAMETERS
229 * "extensions"
230 * Address of arrray of CERTCertExtension whose hash value is desired.
231 * Must be non-NULL.
232 * "pHashValue"
233 * Address where the final hash value is returned. Must be non-NULL.
234 * "plContext"
235 * Platform-specific context pointer.
236 * THREAD SAFETY:
237 * Conditional Thread Safe
238 * Though the value of extensions once created is not supposed to change,
239 * it may be de-allocated while we are accessing it. But since we are
240 * validating the object, it is unlikely we or someone is de-allocating
241 * at the moment.
242 * RETURNS:
243 * Returns NULL if the function succeeds.
244 * Returns an OID Error if the function fails in a non-fatal way.
245 * Returns a Fatal Error if the function fails in an unrecoverable way.
247 static PKIX_Error *
248 pkix_pl_CRLEntry_Extensions_Hashcode(
249 CERTCertExtension **extensions,
250 PKIX_UInt32 *pHashValue,
251 void *plContext)
253 CERTCertExtension *extension = NULL;
254 PRArenaPool *arena = NULL;
255 PKIX_UInt32 extHash = 0;
256 PKIX_UInt32 hashValue = 0;
257 SECItem *derBytes = NULL;
258 SECItem *resultSecItem = NULL;
260 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Hashcode");
261 PKIX_NULLCHECK_TWO(extensions, pHashValue);
263 if (extensions) {
265 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n");
266 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
267 if (arena == NULL) {
268 PKIX_ERROR(PKIX_OUTOFMEMORY);
271 while (*extensions) {
273 extension = *extensions++;
275 PKIX_NULLCHECK_ONE(extension);
277 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
278 derBytes = PORT_ArenaZNew(arena, SECItem);
279 if (derBytes == NULL) {
280 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
283 PKIX_CRLENTRY_DEBUG
284 ("\t\tCalling SEC_ASN1EncodeItem\n");
285 resultSecItem = SEC_ASN1EncodeItem
286 (arena,
287 derBytes,
288 extension,
289 CERT_CertExtensionTemplate);
291 if (resultSecItem == NULL){
292 PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
295 PKIX_CHECK(pkix_hash
296 (derBytes->data,
297 derBytes->len,
298 &extHash,
299 plContext),
300 PKIX_HASHFAILED);
302 hashValue += (extHash << 7);
307 *pHashValue = hashValue;
309 cleanup:
311 if (arena){
312 /* Note that freeing the arena also frees derBytes */
313 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n");
314 PORT_FreeArena(arena, PR_FALSE);
315 arena = NULL;
317 PKIX_RETURN(CRLENTRY);
321 * FUNCTION: pkix_pl_CRLEntry_Hashcode
322 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
324 static PKIX_Error *
325 pkix_pl_CRLEntry_Hashcode(
326 PKIX_PL_Object *object,
327 PKIX_UInt32 *pHashcode,
328 void *plContext)
330 SECItem *nssDate = NULL;
331 PKIX_PL_CRLEntry *crlEntry = NULL;
332 PKIX_UInt32 crlEntryHash;
333 PKIX_UInt32 hashValue;
334 PKIX_Int32 reasonCode = 0;
336 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Hashcode");
337 PKIX_NULLCHECK_TWO(object, pHashcode);
339 PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
340 PKIX_OBJECTNOTCRLENTRY);
342 crlEntry = (PKIX_PL_CRLEntry *)object;
344 PKIX_NULLCHECK_ONE(crlEntry->nssCrlEntry);
345 nssDate = &(crlEntry->nssCrlEntry->revocationDate);
347 PKIX_NULLCHECK_ONE(nssDate->data);
349 PKIX_CHECK(pkix_hash
350 ((const unsigned char *)nssDate->data,
351 nssDate->len,
352 &crlEntryHash,
353 plContext),
354 PKIX_ERRORGETTINGHASHCODE);
356 PKIX_CHECK(PKIX_PL_Object_Hashcode
357 ((PKIX_PL_Object *)crlEntry->serialNumber,
358 &hashValue,
359 plContext),
360 PKIX_OBJECTHASHCODEFAILED);
362 crlEntryHash += (hashValue << 7);
364 hashValue = 0;
366 if (crlEntry->nssCrlEntry->extensions) {
368 PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Hashcode
369 (crlEntry->nssCrlEntry->extensions, &hashValue, plContext),
370 PKIX_CRLENTRYEXTENSIONSHASHCODEFAILED);
373 crlEntryHash += (hashValue << 7);
375 PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
376 (crlEntry, &reasonCode, plContext),
377 PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
379 crlEntryHash += (reasonCode + 777) << 3;
381 *pHashcode = crlEntryHash;
383 cleanup:
385 PKIX_RETURN(CRLENTRY);
389 * FUNCTION: pkix_pl_CRLENTRY_Extensions_Equals
390 * DESCRIPTION:
392 * Compare each extension's DERbyte data in "firstExtensions" with extension
393 * in "secondExtensions" in sequential order and store the result in
394 * "pResult".
396 * PARAMETERS
397 * "firstExtensions"
398 * Address of first NSS structure CERTCertExtension to be compared.
399 * Must be non-NULL.
400 * "secondExtensions"
401 * Address of second NSS structure CERTCertExtension to be compared.
402 * Must be non-NULL.
403 * "pResult"
404 * Address where the comparison result is returned. Must be non-NULL.
405 * "plContext"
406 * Platform-specific context pointer.
407 * THREAD SAFETY:
408 * Conditionally Thread Safe
409 * Though the value of extensions once created is not supposed to change,
410 * it may be de-allocated while we are accessing it. But since we are
411 * validating the object, it is unlikely we or someone is de-allocating
412 * at the moment.
413 * RETURNS:
414 * Returns NULL if the function succeeds.
415 * Returns an OID Error if the function fails in a non-fatal way.
416 * Returns a Fatal Error if the function fails in an unrecoverable way.
418 static PKIX_Error *
419 pkix_pl_CRLEntry_Extensions_Equals(
420 CERTCertExtension **extensions1,
421 CERTCertExtension **extensions2,
422 PKIX_Boolean *pResult,
423 void *plContext)
425 CERTCertExtension **firstExtensions;
426 CERTCertExtension **secondExtensions;
427 CERTCertExtension *firstExtension = NULL;
428 CERTCertExtension *secondExtension = NULL;
429 PRArenaPool *arena = NULL;
430 PKIX_Boolean cmpResult = PKIX_FALSE;
431 SECItem *firstDerBytes = NULL;
432 SECItem *secondDerBytes = NULL;
433 SECItem *firstResultSecItem = NULL;
434 SECItem *secondResultSecItem = NULL;
435 PKIX_UInt32 firstNumExt = 0;
436 PKIX_UInt32 secondNumExt = 0;
437 SECComparison secResult;
439 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Equals");
440 PKIX_NULLCHECK_THREE(extensions1, extensions2, pResult);
442 firstExtensions = extensions1;
443 secondExtensions = extensions2;
445 if (firstExtensions) {
446 while (*firstExtensions) {
447 firstExtension = *firstExtensions++;
448 firstNumExt++;
452 if (secondExtensions) {
453 while (*secondExtensions) {
454 secondExtension = *secondExtensions++;
455 secondNumExt++;
459 if (firstNumExt != secondNumExt) {
460 *pResult = PKIX_FALSE;
461 goto cleanup;
464 if (firstNumExt == 0 && secondNumExt == 0) {
465 *pResult = PKIX_TRUE;
466 goto cleanup;
469 /* now have equal number, but non-zero extension items to compare */
471 firstExtensions = extensions1;
472 secondExtensions = extensions2;
474 cmpResult = PKIX_TRUE;
476 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n");
477 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE*2);
478 if (arena == NULL) {
479 PKIX_ERROR(PKIX_OUTOFMEMORY);
482 while (firstNumExt--) {
484 firstExtension = *firstExtensions++;
485 secondExtension = *secondExtensions++;
487 PKIX_NULLCHECK_TWO(firstExtension, secondExtension);
489 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
490 firstDerBytes = PORT_ArenaZNew(arena, SECItem);
491 if (firstDerBytes == NULL) {
492 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
495 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
496 secondDerBytes = PORT_ArenaZNew(arena, SECItem);
497 if (secondDerBytes == NULL) {
498 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
501 PKIX_CRLENTRY_DEBUG
502 ("\t\tCalling SEC_ASN1EncodeItem\n");
503 firstResultSecItem = SEC_ASN1EncodeItem
504 (arena,
505 firstDerBytes,
506 firstExtension,
507 CERT_CertExtensionTemplate);
509 if (firstResultSecItem == NULL){
510 PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
513 PKIX_CRLENTRY_DEBUG
514 ("\t\tCalling SEC_ASN1EncodeItem\n");
515 secondResultSecItem = SEC_ASN1EncodeItem
516 (arena,
517 secondDerBytes,
518 secondExtension,
519 CERT_CertExtensionTemplate);
521 if (secondResultSecItem == NULL){
522 PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
525 PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
526 secResult = SECITEM_CompareItem
527 (firstResultSecItem, secondResultSecItem);
529 if (secResult != SECEqual) {
530 cmpResult = PKIX_FALSE;
531 break;
536 *pResult = cmpResult;
538 cleanup:
540 if (arena){
541 /* Note that freeing the arena also frees derBytes */
542 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n");
543 PORT_FreeArena(arena, PR_FALSE);
544 arena = NULL;
547 PKIX_RETURN(CRLENTRY);
551 * FUNCTION: pkix_pl_CRLEntry_Equals
552 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
554 static PKIX_Error *
555 pkix_pl_CRLEntry_Equals(
556 PKIX_PL_Object *firstObject,
557 PKIX_PL_Object *secondObject,
558 PKIX_Boolean *pResult,
559 void *plContext)
561 PKIX_PL_CRLEntry *firstCrlEntry = NULL;
562 PKIX_PL_CRLEntry *secondCrlEntry = NULL;
563 PKIX_UInt32 secondType;
564 PKIX_Boolean cmpResult = PKIX_FALSE;
566 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Equals");
567 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
569 /* test that firstObject is a CRLEntry */
570 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRLENTRY_TYPE, plContext),
571 PKIX_FIRSTOBJECTNOTCRLENTRY);
573 firstCrlEntry = (PKIX_PL_CRLEntry *)firstObject;
574 secondCrlEntry = (PKIX_PL_CRLEntry *)secondObject;
576 PKIX_NULLCHECK_TWO
577 (firstCrlEntry->nssCrlEntry, secondCrlEntry->nssCrlEntry);
580 * Since we know firstObject is a CRLEntry, if both references are
581 * identical, they must be equal
583 if (firstCrlEntry == secondCrlEntry){
584 *pResult = PKIX_TRUE;
585 goto cleanup;
589 * If secondCrlEntry isn't a CRL Entry, we don't throw an error.
590 * We simply return a Boolean result of FALSE
592 *pResult = PKIX_FALSE;
593 PKIX_CHECK(PKIX_PL_Object_GetType
594 ((PKIX_PL_Object *)secondCrlEntry, &secondType, plContext),
595 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
596 if (secondType != PKIX_CRLENTRY_TYPE) goto cleanup;
598 /* Compare userSerialNumber */
599 PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
600 if (SECITEM_CompareItem(
601 &(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->serialNumber),
602 &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->serialNumber))
603 != SECEqual) {
604 *pResult = PKIX_FALSE;
605 goto cleanup;
608 /* Compare revocationDate */
609 PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
610 if (SECITEM_CompareItem
611 (&(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->
612 revocationDate),
613 &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->
614 revocationDate))
615 != SECEqual) {
616 *pResult = PKIX_FALSE;
617 goto cleanup;
620 /* Compare Critical Extension List */
621 PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Equals
622 (firstCrlEntry->nssCrlEntry->extensions,
623 secondCrlEntry->nssCrlEntry->extensions,
624 &cmpResult,
625 plContext),
626 PKIX_CRLENTRYEXTENSIONSEQUALSFAILED);
628 if (cmpResult != PKIX_TRUE){
629 *pResult = PKIX_FALSE;
630 goto cleanup;
633 cmpResult = (firstCrlEntry->userReasonCode ==
634 secondCrlEntry->userReasonCode);
636 *pResult = cmpResult;
638 cleanup:
640 PKIX_RETURN(CRLENTRY);
644 * FUNCTION: pkix_pl_CRLEntry_RegisterSelf
645 * DESCRIPTION:
646 * Registers PKIX_CRLEntry_TYPE and its related functions with systemClasses[]
647 * THREAD SAFETY:
648 * Not Thread Safe - for performance and complexity reasons
650 * Since this function is only called by PKIX_PL_Initialize, which should
651 * only be called once, it is acceptable that this function is not
652 * thread-safe.
654 PKIX_Error *
655 pkix_pl_CRLEntry_RegisterSelf(void *plContext)
658 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
659 pkix_ClassTable_Entry entry;
661 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_RegisterSelf");
663 entry.description = "CRLEntry";
664 entry.objCounter = 0;
665 entry.typeObjectSize = sizeof(PKIX_PL_CRLEntry);
666 entry.destructor = pkix_pl_CRLEntry_Destroy;
667 entry.equalsFunction = pkix_pl_CRLEntry_Equals;
668 entry.hashcodeFunction = pkix_pl_CRLEntry_Hashcode;
669 entry.toStringFunction = pkix_pl_CRLEntry_ToString;
670 entry.comparator = NULL;
671 entry.duplicateFunction = pkix_duplicateImmutable;
673 systemClasses[PKIX_CRLENTRY_TYPE] = entry;
675 PKIX_RETURN(CRLENTRY);
679 * FUNCTION: pkix_pl_CRLEntry_CreateEntry
680 * DESCRIPTION:
682 * Creates a new CRLEntry using the CertCrlEntry pointed to by "nssCrlEntry"
683 * and stores it at "pCrlEntry". Once created, a CRLEntry is immutable.
685 * revokedCertificates SEQUENCE OF SEQUENCE {
686 * userCertificate CertificateSerialNumber,
687 * revocationDate Time,
688 * crlEntryExtensions Extensions OPTIONAL
689 * -- if present, MUST be v2
691 * PARAMETERS:
692 * "nssCrlEntry"
693 * Address of CERTCrlEntry representing an NSS CRL entry.
694 * Must be non-NULL.
695 * "pCrlEntry"
696 * Address where object pointer will be stored. Must be non-NULL.
697 * "plContext"
698 * Platform-specific context pointer.
699 * THREAD SAFETY:
700 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
701 * RETURNS:
702 * Returns NULL if the function succeeds.
703 * Returns a CRLEntry Error if the function fails in a non-fatal way.
704 * Returns a Fatal Error if the function fails in an unrecoverable way.
706 static PKIX_Error *
707 pkix_pl_CRLEntry_CreateEntry(
708 CERTCrlEntry *nssCrlEntry, /* entry data to be created from */
709 PKIX_PL_CRLEntry **pCrlEntry,
710 void *plContext)
712 PKIX_PL_CRLEntry *crlEntry = NULL;
714 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_CreateEntry");
715 PKIX_NULLCHECK_TWO(nssCrlEntry, pCrlEntry);
717 PKIX_CHECK(PKIX_PL_Object_Alloc
718 (PKIX_CRLENTRY_TYPE,
719 sizeof (PKIX_PL_CRLEntry),
720 (PKIX_PL_Object **)&crlEntry,
721 plContext),
722 PKIX_COULDNOTCREATECRLENTRYOBJECT);
724 crlEntry->nssCrlEntry = nssCrlEntry;
725 crlEntry->serialNumber = NULL;
726 crlEntry->critExtOids = NULL;
727 crlEntry->userReasonCode = 0;
728 crlEntry->userReasonCodeAbsent = PKIX_FALSE;
730 *pCrlEntry = crlEntry;
732 cleanup:
734 PKIX_RETURN(CRLENTRY);
738 * FUNCTION: pkix_pl_CRLEntry_Create
739 * DESCRIPTION:
741 * Creates a List of CRLEntries using the array of CERTCrlEntries pointed to
742 * by "nssCrlEntries" and stores it at "pCrlEntryList". If "nssCrlEntries" is
743 * NULL, this function stores an empty List at "pCrlEntryList".
745 * PARAMETERS:
746 * "nssCrlEntries"
747 * Address of array of CERTCrlEntries representing NSS CRL entries.
748 * Can be NULL if CRL has no NSS CRL entries.
749 * "pCrlEntryList"
750 * Address where object pointer will be stored. Must be non-NULL.
751 * "plContext"
752 * Platform-specific context pointer.
753 * THREAD SAFETY:
754 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
755 * RETURNS:
756 * Returns NULL if the function succeeds.
757 * Returns a CRLEntry Error if the function fails in a non-fatal way.
758 * Returns a Fatal Error if the function fails in an unrecoverable way.
760 PKIX_Error *
761 pkix_pl_CRLEntry_Create(
762 CERTCrlEntry **nssCrlEntries, /* head of entry list */
763 PKIX_List **pCrlEntryList,
764 void *plContext)
766 PKIX_List *entryList = NULL;
767 PKIX_PL_CRLEntry *crlEntry = NULL;
768 CERTCrlEntry **entries = NULL;
769 SECItem serialNumberItem;
770 PKIX_PL_BigInt *serialNumber;
771 char *bytes = NULL;
772 PKIX_UInt32 length;
774 PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Create");
775 PKIX_NULLCHECK_ONE(pCrlEntryList);
777 entries = nssCrlEntries;
779 PKIX_CHECK(PKIX_List_Create(&entryList, plContext),
780 PKIX_LISTCREATEFAILED);
782 if (entries) {
783 while (*entries){
784 PKIX_CHECK(pkix_pl_CRLEntry_CreateEntry
785 (*entries, &crlEntry, plContext),
786 PKIX_COULDNOTCREATECRLENTRYOBJECT);
788 /* Get Serial Number */
789 serialNumberItem = (*entries)->serialNumber;
790 length = serialNumberItem.len;
791 bytes = (char *)serialNumberItem.data;
793 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
794 (bytes, length, &serialNumber, plContext),
795 PKIX_BIGINTCREATEWITHBYTESFAILED);
797 crlEntry->serialNumber = serialNumber;
798 crlEntry->nssCrlEntry = *entries;
800 PKIX_CHECK(PKIX_List_AppendItem
801 (entryList, (PKIX_PL_Object *)crlEntry, plContext),
802 PKIX_LISTAPPENDITEMFAILED);
804 PKIX_DECREF(crlEntry);
806 entries++;
810 *pCrlEntryList = entryList;
812 cleanup:
813 PKIX_DECREF(crlEntry);
815 if (PKIX_ERROR_RECEIVED){
816 PKIX_DECREF(entryList);
819 PKIX_RETURN(CRLENTRY);
822 /* --Public-CRLENTRY-Functions------------------------------------- */
825 * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode
826 * (see comments in pkix_pl_pki.h)
828 PKIX_Error *
829 PKIX_PL_CRLEntry_GetCRLEntryReasonCode (
830 PKIX_PL_CRLEntry *crlEntry,
831 PKIX_Int32 *pReason,
832 void *plContext)
834 SECStatus status;
835 CERTCRLEntryReasonCode nssReasonCode;
837 PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCRLEntryReasonCode");
838 PKIX_NULLCHECK_TWO(crlEntry, pReason);
840 if (!crlEntry->userReasonCodeAbsent && crlEntry->userReasonCode == 0) {
842 PKIX_OBJECT_LOCK(crlEntry);
844 if (!crlEntry->userReasonCodeAbsent &&
845 crlEntry->userReasonCode == 0) {
847 /* reason code has not been cached in */
848 PKIX_CRLENTRY_DEBUG("\t\tCERT_FindCRLEntryReasonExten.\n");
849 status = CERT_FindCRLEntryReasonExten
850 (crlEntry->nssCrlEntry, &nssReasonCode);
852 if (status == SECSuccess) {
853 crlEntry->userReasonCode = (PKIX_Int32) nssReasonCode;
854 } else {
855 crlEntry->userReasonCodeAbsent = PKIX_TRUE;
859 PKIX_OBJECT_UNLOCK(crlEntry);
863 *pReason = crlEntry->userReasonCode;
865 cleanup:
867 PKIX_RETURN(CRLENTRY);
871 * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
872 * (see comments in pkix_pl_pki.h)
874 PKIX_Error *
875 PKIX_PL_CRLEntry_GetCriticalExtensionOIDs (
876 PKIX_PL_CRLEntry *crlEntry,
877 PKIX_List **pList, /* list of PKIX_PL_OID */
878 void *plContext)
880 PKIX_List *oidsList = NULL;
881 CERTCertExtension **extensions;
883 PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCriticalExtensionOIDs");
884 PKIX_NULLCHECK_THREE(crlEntry, crlEntry->nssCrlEntry, pList);
886 /* if we don't have a cached copy from before, we create one */
887 if (crlEntry->critExtOids == NULL) {
889 PKIX_OBJECT_LOCK(crlEntry);
891 if (crlEntry->critExtOids == NULL) {
893 extensions = crlEntry->nssCrlEntry->extensions;
895 PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
896 (extensions, &oidsList, plContext),
897 PKIX_GETCRITICALEXTENSIONOIDSFAILED);
899 crlEntry->critExtOids = oidsList;
902 PKIX_OBJECT_UNLOCK(crlEntry);
906 /* We should return a copy of the List since this list changes */
907 PKIX_DUPLICATE(crlEntry->critExtOids, pList, plContext,
908 PKIX_OBJECTDUPLICATELISTFAILED);
910 cleanup:
912 PKIX_RETURN(CRLENTRY);