1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /*
5  * pkix_pl_crlentry.c
6  *
7  * CRLENTRY Function Definitions
8  *
9  */
10 
11 #include "pkix_pl_crlentry.h"
12 
13 /* --Private-CRLEntry-Functions------------------------------------- */
14 
15 /*
16  * FUNCTION: pkix_pl_CRLEntry_Destroy
17  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
18  */
19 static PKIX_Error *
pkix_pl_CRLEntry_Destroy(PKIX_PL_Object * object,void * plContext)20 pkix_pl_CRLEntry_Destroy(
21         PKIX_PL_Object *object,
22         void *plContext)
23 {
24         PKIX_PL_CRLEntry *crlEntry = NULL;
25 
26         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Destroy");
27         PKIX_NULLCHECK_ONE(object);
28 
29         PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
30                     PKIX_OBJECTNOTCRLENTRY);
31 
32         crlEntry = (PKIX_PL_CRLEntry*)object;
33 
34         /* crlEntry->nssCrlEntry is freed by NSS when freeing CRL */
35         crlEntry->userReasonCode = 0;
36         crlEntry->userReasonCodeAbsent = PKIX_FALSE;
37         crlEntry->nssCrlEntry = NULL;
38         PKIX_DECREF(crlEntry->serialNumber);
39         PKIX_DECREF(crlEntry->critExtOids);
40 
41 cleanup:
42 
43         PKIX_RETURN(CRLENTRY);
44 }
45 
46 /*
47  * FUNCTION: pkix_pl_CRLEntry_ToString_Helper
48  *
49  * DESCRIPTION:
50  *  Helper function that creates a string representation of the CRLEntry
51  *  pointed to by "crlEntry" and stores it at "pString".
52  *
53  * PARAMETERS
54  *  "crlEntry"
55  *      Address of CRLEntry whose string representation is desired.
56  *      Must be non-NULL.
57  *  "pString"
58  *      Address where object pointer will be stored. Must be non-NULL.
59  *  "plContext"
60  *      Platform-specific context pointer.
61  * THREAD SAFETY:
62  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
63  * RETURNS:
64  *  Returns NULL if the function succeeds.
65  *  Returns a CRLEntry Error if the function fails in a non-fatal way.
66  *  Returns a Fatal Error if the function fails in an unrecoverable way.
67  */
68 PKIX_Error *
pkix_pl_CRLEntry_ToString_Helper(PKIX_PL_CRLEntry * crlEntry,PKIX_PL_String ** pString,void * plContext)69 pkix_pl_CRLEntry_ToString_Helper(
70         PKIX_PL_CRLEntry *crlEntry,
71         PKIX_PL_String **pString,
72         void *plContext)
73 {
74         char *asciiFormat = NULL;
75         PKIX_List *critExtOIDs = NULL;
76         PKIX_PL_String *crlEntryString = NULL;
77         PKIX_PL_String *formatString = NULL;
78         PKIX_PL_String *crlSerialNumberString = NULL;
79         PKIX_PL_String *crlRevocationDateString = NULL;
80         PKIX_PL_String *critExtOIDsString = NULL;
81         PKIX_Int32 reasonCode = 0;
82 
83         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString_Helper");
84         PKIX_NULLCHECK_FOUR
85                 (crlEntry,
86                 crlEntry->serialNumber,
87                 crlEntry->nssCrlEntry,
88                 pString);
89 
90         asciiFormat =
91                 "\n\t[\n"
92                 "\tSerialNumber:    %s\n"
93                 "\tReasonCode:      %d\n"
94                 "\tRevocationDate:  %s\n"
95                 "\tCritExtOIDs:     %s\n"
96                 "\t]\n\t";
97 
98         PKIX_CHECK(PKIX_PL_String_Create
99                     (PKIX_ESCASCII,
100                     asciiFormat,
101                     0,
102                     &formatString,
103                     plContext),
104                     PKIX_STRINGCREATEFAILED);
105 
106         /* SerialNumber */
107         PKIX_CHECK(PKIX_PL_Object_ToString
108                     ((PKIX_PL_Object *)crlEntry->serialNumber,
109                     &crlSerialNumberString,
110                     plContext),
111                     PKIX_BIGINTTOSTRINGHELPERFAILED);
112 
113         /* RevocationDate - No Date object created, use nss data directly */
114         PKIX_CHECK(pkix_pl_Date_ToString_Helper
115                     (&(crlEntry->nssCrlEntry->revocationDate),
116                     &crlRevocationDateString,
117                     plContext),
118                     PKIX_DATETOSTRINGHELPERFAILED);
119 
120         /* CriticalExtensionOIDs */
121         PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
122                     (crlEntry, &critExtOIDs, plContext),
123                     PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED);
124 
125         PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
126                     PKIX_LISTTOSTRINGFAILED);
127 
128         /* Revocation Reason Code */
129         PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
130                             (crlEntry, &reasonCode, plContext),
131                             PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
132 
133         PKIX_CHECK(PKIX_PL_Sprintf
134                     (&crlEntryString,
135                     plContext,
136                     formatString,
137                     crlSerialNumberString,
138                     reasonCode,
139                     crlRevocationDateString,
140                     critExtOIDsString),
141                     PKIX_SPRINTFFAILED);
142 
143         *pString = crlEntryString;
144 
145 cleanup:
146 
147         PKIX_DECREF(critExtOIDs);
148         PKIX_DECREF(crlSerialNumberString);
149         PKIX_DECREF(crlRevocationDateString);
150         PKIX_DECREF(critExtOIDsString);
151         PKIX_DECREF(formatString);
152 
153         PKIX_RETURN(CRLENTRY);
154 }
155 
156 /*
157  * FUNCTION: pkix_pl_CRLEntry_ToString
158  * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
159  */
160 static PKIX_Error *
pkix_pl_CRLEntry_ToString(PKIX_PL_Object * object,PKIX_PL_String ** pString,void * plContext)161 pkix_pl_CRLEntry_ToString(
162         PKIX_PL_Object *object,
163         PKIX_PL_String **pString,
164         void *plContext)
165 {
166         PKIX_PL_String *crlEntryString = NULL;
167         PKIX_PL_CRLEntry *crlEntry = NULL;
168 
169         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString");
170         PKIX_NULLCHECK_TWO(object, pString);
171 
172         PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
173                     PKIX_OBJECTNOTCRLENTRY);
174 
175         crlEntry = (PKIX_PL_CRLEntry *) object;
176 
177         PKIX_CHECK(pkix_pl_CRLEntry_ToString_Helper
178                     (crlEntry, &crlEntryString, plContext),
179                     PKIX_CRLENTRYTOSTRINGHELPERFAILED);
180 
181         *pString = crlEntryString;
182 
183 cleanup:
184 
185         PKIX_RETURN(CRLENTRY);
186 }
187 
188 /*
189  * FUNCTION: pkix_pl_CRLEntry_Extensions_Hashcode
190  * DESCRIPTION:
191  *
192  *  For each CRL Entry extension stored at NSS structure CERTCertExtension,
193  *  get its derbyte data and do the hash.
194  *
195  * PARAMETERS
196  *  "extensions"
197  *      Address of arrray of CERTCertExtension whose hash value is desired.
198  *      Must be non-NULL.
199  *  "pHashValue"
200  *      Address where the final hash value is returned. Must be non-NULL.
201  *  "plContext"
202  *      Platform-specific context pointer.
203  * THREAD SAFETY:
204  *  Conditional Thread Safe
205  *  Though the value of extensions once created is not supposed to change,
206  *  it may be de-allocated while we are accessing it. But since we are
207  *  validating the object, it is unlikely we or someone is de-allocating
208  *  at the moment.
209  * RETURNS:
210  *  Returns NULL if the function succeeds.
211  *  Returns an OID Error if the function fails in a non-fatal way.
212  *  Returns a Fatal Error if the function fails in an unrecoverable way.
213  */
214 static PKIX_Error *
pkix_pl_CRLEntry_Extensions_Hashcode(CERTCertExtension ** extensions,PKIX_UInt32 * pHashValue,void * plContext)215 pkix_pl_CRLEntry_Extensions_Hashcode(
216         CERTCertExtension **extensions,
217         PKIX_UInt32 *pHashValue,
218         void *plContext)
219 {
220         CERTCertExtension *extension = NULL;
221         PLArenaPool *arena = NULL;
222         PKIX_UInt32 extHash = 0;
223         PKIX_UInt32 hashValue = 0;
224         SECItem *derBytes = NULL;
225         SECItem *resultSecItem = NULL;
226 
227         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Hashcode");
228         PKIX_NULLCHECK_TWO(extensions, pHashValue);
229 
230         if (extensions) {
231 
232                 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n");
233                 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
234                 if (arena == NULL) {
235                         PKIX_ERROR(PKIX_OUTOFMEMORY);
236                 }
237 
238                 while (*extensions) {
239 
240                         extension = *extensions++;
241 
242                         PKIX_NULLCHECK_ONE(extension);
243 
244                         PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
245                         derBytes = PORT_ArenaZNew(arena, SECItem);
246                         if (derBytes == NULL) {
247                                 PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
248                         }
249 
250                         PKIX_CRLENTRY_DEBUG
251                                 ("\t\tCalling SEC_ASN1EncodeItem\n");
252                         resultSecItem = SEC_ASN1EncodeItem
253                                 (arena,
254                                 derBytes,
255                                 extension,
256                                 CERT_CertExtensionTemplate);
257 
258                         if (resultSecItem == NULL){
259                                 PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
260                         }
261 
262                         PKIX_CHECK(pkix_hash
263                                 (derBytes->data,
264                                 derBytes->len,
265                                 &extHash,
266                                 plContext),
267                                 PKIX_HASHFAILED);
268 
269                         hashValue += (extHash << 7);
270 
271                 }
272         }
273 
274         *pHashValue = hashValue;
275 
276 cleanup:
277 
278         if (arena){
279                 /* Note that freeing the arena also frees derBytes */
280                 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n");
281                 PORT_FreeArena(arena, PR_FALSE);
282                 arena = NULL;
283         }
284         PKIX_RETURN(CRLENTRY);
285 }
286 
287 /*
288  * FUNCTION: pkix_pl_CRLEntry_Hashcode
289  * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
290  */
291 static PKIX_Error *
pkix_pl_CRLEntry_Hashcode(PKIX_PL_Object * object,PKIX_UInt32 * pHashcode,void * plContext)292 pkix_pl_CRLEntry_Hashcode(
293         PKIX_PL_Object *object,
294         PKIX_UInt32 *pHashcode,
295         void *plContext)
296 {
297         SECItem *nssDate = NULL;
298         PKIX_PL_CRLEntry *crlEntry = NULL;
299         PKIX_UInt32 crlEntryHash;
300         PKIX_UInt32 hashValue;
301         PKIX_Int32 reasonCode = 0;
302 
303         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Hashcode");
304         PKIX_NULLCHECK_TWO(object, pHashcode);
305 
306         PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
307                     PKIX_OBJECTNOTCRLENTRY);
308 
309         crlEntry = (PKIX_PL_CRLEntry *)object;
310 
311         PKIX_NULLCHECK_ONE(crlEntry->nssCrlEntry);
312         nssDate = &(crlEntry->nssCrlEntry->revocationDate);
313 
314         PKIX_NULLCHECK_ONE(nssDate->data);
315 
316         PKIX_CHECK(pkix_hash
317                 ((const unsigned char *)nssDate->data,
318                 nssDate->len,
319                 &crlEntryHash,
320                 plContext),
321                 PKIX_ERRORGETTINGHASHCODE);
322 
323         PKIX_CHECK(PKIX_PL_Object_Hashcode
324                 ((PKIX_PL_Object *)crlEntry->serialNumber,
325                 &hashValue,
326                 plContext),
327                 PKIX_OBJECTHASHCODEFAILED);
328 
329         crlEntryHash += (hashValue << 7);
330 
331         hashValue = 0;
332 
333         if (crlEntry->nssCrlEntry->extensions) {
334 
335                 PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Hashcode
336                     (crlEntry->nssCrlEntry->extensions, &hashValue, plContext),
337                     PKIX_CRLENTRYEXTENSIONSHASHCODEFAILED);
338         }
339 
340         crlEntryHash += (hashValue << 7);
341 
342         PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
343                 (crlEntry, &reasonCode, plContext),
344                 PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
345 
346         crlEntryHash += (reasonCode + 777) << 3;
347 
348         *pHashcode = crlEntryHash;
349 
350 cleanup:
351 
352         PKIX_RETURN(CRLENTRY);
353 }
354 
355 /*
356  * FUNCTION: pkix_pl_CRLENTRY_Extensions_Equals
357  * DESCRIPTION:
358  *
359  *  Compare each extension's DERbyte data in "firstExtensions" with extension
360  *  in "secondExtensions" in sequential order and store the result in
361  *  "pResult".
362  *
363  * PARAMETERS
364  *  "firstExtensions"
365  *      Address of first NSS structure CERTCertExtension to be compared.
366  *      Must be non-NULL.
367  *  "secondExtensions"
368  *      Address of second NSS structure CERTCertExtension to be compared.
369  *      Must be non-NULL.
370  *  "pResult"
371  *      Address where the comparison result is returned. Must be non-NULL.
372  *  "plContext"
373  *      Platform-specific context pointer.
374  * THREAD SAFETY:
375  *  Conditionally Thread Safe
376  *  Though the value of extensions once created is not supposed to change,
377  *  it may be de-allocated while we are accessing it. But since we are
378  *  validating the object, it is unlikely we or someone is de-allocating
379  *  at the moment.
380  * RETURNS:
381  *  Returns NULL if the function succeeds.
382  *  Returns an OID Error if the function fails in a non-fatal way.
383  *  Returns a Fatal Error if the function fails in an unrecoverable way.
384  */
385 static PKIX_Error *
pkix_pl_CRLEntry_Extensions_Equals(CERTCertExtension ** extensions1,CERTCertExtension ** extensions2,PKIX_Boolean * pResult,void * plContext)386 pkix_pl_CRLEntry_Extensions_Equals(
387         CERTCertExtension **extensions1,
388         CERTCertExtension **extensions2,
389         PKIX_Boolean *pResult,
390         void *plContext)
391 {
392         CERTCertExtension **firstExtensions;
393         CERTCertExtension **secondExtensions;
394         CERTCertExtension *firstExtension = NULL;
395         CERTCertExtension *secondExtension = NULL;
396         PLArenaPool *arena = NULL;
397         PKIX_Boolean cmpResult = PKIX_FALSE;
398         SECItem *firstDerBytes = NULL;
399         SECItem *secondDerBytes = NULL;
400         SECItem *firstResultSecItem = NULL;
401         SECItem *secondResultSecItem = NULL;
402         PKIX_UInt32 firstNumExt = 0;
403         PKIX_UInt32 secondNumExt = 0;
404         SECComparison secResult;
405 
406         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Equals");
407         PKIX_NULLCHECK_THREE(extensions1, extensions2, pResult);
408 
409         firstExtensions = extensions1;
410         secondExtensions = extensions2;
411 
412         if (firstExtensions) {
413                 while (*firstExtensions) {
414                         firstExtension = *firstExtensions++;
415                         firstNumExt++;
416                 }
417         }
418 
419         if (secondExtensions) {
420                 while (*secondExtensions) {
421                         secondExtension = *secondExtensions++;
422                         secondNumExt++;
423                 }
424         }
425 
426         if (firstNumExt != secondNumExt) {
427                 *pResult = PKIX_FALSE;
428                 goto cleanup;
429         }
430 
431         if (firstNumExt == 0 && secondNumExt == 0) {
432                 *pResult = PKIX_TRUE;
433                 goto cleanup;
434         }
435 
436         /* now have equal number, but non-zero extension items to compare */
437 
438         firstExtensions = extensions1;
439         secondExtensions = extensions2;
440 
441         cmpResult = PKIX_TRUE;
442 
443         PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_NewArena\n");
444         arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE*2);
445         if (arena == NULL) {
446                 PKIX_ERROR(PKIX_OUTOFMEMORY);
447         }
448 
449         while (firstNumExt--) {
450 
451                 firstExtension = *firstExtensions++;
452                 secondExtension = *secondExtensions++;
453 
454                 PKIX_NULLCHECK_TWO(firstExtension, secondExtension);
455 
456                 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
457                 firstDerBytes = PORT_ArenaZNew(arena, SECItem);
458                 if (firstDerBytes == NULL) {
459                         PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
460                 }
461 
462                 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
463                 secondDerBytes = PORT_ArenaZNew(arena, SECItem);
464                 if (secondDerBytes == NULL) {
465                         PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
466                 }
467 
468                 PKIX_CRLENTRY_DEBUG
469                         ("\t\tCalling SEC_ASN1EncodeItem\n");
470                 firstResultSecItem = SEC_ASN1EncodeItem
471                         (arena,
472                         firstDerBytes,
473                         firstExtension,
474                         CERT_CertExtensionTemplate);
475 
476                 if (firstResultSecItem == NULL){
477                         PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
478                 }
479 
480                 PKIX_CRLENTRY_DEBUG
481                         ("\t\tCalling SEC_ASN1EncodeItem\n");
482                 secondResultSecItem = SEC_ASN1EncodeItem
483                         (arena,
484                         secondDerBytes,
485                         secondExtension,
486                         CERT_CertExtensionTemplate);
487 
488                 if (secondResultSecItem == NULL){
489                         PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
490                 }
491 
492                 PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
493                 secResult = SECITEM_CompareItem
494                         (firstResultSecItem, secondResultSecItem);
495 
496                 if (secResult != SECEqual) {
497                         cmpResult = PKIX_FALSE;
498                         break;
499                 }
500 
501         }
502 
503         *pResult = cmpResult;
504 
505 cleanup:
506 
507         if (arena){
508                 /* Note that freeing the arena also frees derBytes */
509                 PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_FreeArena\n");
510                 PORT_FreeArena(arena, PR_FALSE);
511                 arena = NULL;
512         }
513 
514         PKIX_RETURN(CRLENTRY);
515 }
516 
517 /*
518  * FUNCTION: pkix_pl_CRLEntry_Equals
519  * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
520  */
521 static PKIX_Error *
pkix_pl_CRLEntry_Equals(PKIX_PL_Object * firstObject,PKIX_PL_Object * secondObject,PKIX_Boolean * pResult,void * plContext)522 pkix_pl_CRLEntry_Equals(
523         PKIX_PL_Object *firstObject,
524         PKIX_PL_Object *secondObject,
525         PKIX_Boolean *pResult,
526         void *plContext)
527 {
528         PKIX_PL_CRLEntry *firstCrlEntry = NULL;
529         PKIX_PL_CRLEntry *secondCrlEntry = NULL;
530         PKIX_UInt32 secondType;
531         PKIX_Boolean cmpResult = PKIX_FALSE;
532 
533         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Equals");
534         PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
535 
536         /* test that firstObject is a CRLEntry */
537         PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRLENTRY_TYPE, plContext),
538                 PKIX_FIRSTOBJECTNOTCRLENTRY);
539 
540         firstCrlEntry = (PKIX_PL_CRLEntry *)firstObject;
541         secondCrlEntry = (PKIX_PL_CRLEntry *)secondObject;
542 
543         PKIX_NULLCHECK_TWO
544                 (firstCrlEntry->nssCrlEntry, secondCrlEntry->nssCrlEntry);
545 
546         /*
547          * Since we know firstObject is a CRLEntry, if both references are
548          * identical, they must be equal
549          */
550         if (firstCrlEntry == secondCrlEntry){
551                 *pResult = PKIX_TRUE;
552                 goto cleanup;
553         }
554 
555         /*
556          * If secondCrlEntry isn't a CRL Entry, we don't throw an error.
557          * We simply return a Boolean result of FALSE
558          */
559         *pResult = PKIX_FALSE;
560         PKIX_CHECK(PKIX_PL_Object_GetType
561                     ((PKIX_PL_Object *)secondCrlEntry, &secondType, plContext),
562                     PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
563         if (secondType != PKIX_CRLENTRY_TYPE) goto cleanup;
564 
565         /* Compare userSerialNumber */
566         PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
567         if (SECITEM_CompareItem(
568             &(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->serialNumber),
569             &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->serialNumber))
570             != SECEqual) {
571                 *pResult = PKIX_FALSE;
572                 goto cleanup;
573         }
574 
575         /* Compare revocationDate */
576         PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
577         if (SECITEM_CompareItem
578             (&(((PKIX_PL_CRLEntry *)firstCrlEntry)->nssCrlEntry->
579                 revocationDate),
580             &(((PKIX_PL_CRLEntry *)secondCrlEntry)->nssCrlEntry->
581                 revocationDate))
582             != SECEqual) {
583                 *pResult = PKIX_FALSE;
584                 goto cleanup;
585         }
586 
587         /* Compare Critical Extension List */
588         PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Equals
589                     (firstCrlEntry->nssCrlEntry->extensions,
590                     secondCrlEntry->nssCrlEntry->extensions,
591                     &cmpResult,
592                     plContext),
593                     PKIX_CRLENTRYEXTENSIONSEQUALSFAILED);
594 
595         if (cmpResult != PKIX_TRUE){
596                 *pResult = PKIX_FALSE;
597                 goto cleanup;
598         }
599 
600         cmpResult = (firstCrlEntry->userReasonCode ==
601                     secondCrlEntry->userReasonCode);
602 
603         *pResult = cmpResult;
604 
605 cleanup:
606 
607         PKIX_RETURN(CRLENTRY);
608 }
609 
610 /*
611  * FUNCTION: pkix_pl_CRLEntry_RegisterSelf
612  * DESCRIPTION:
613  *  Registers PKIX_CRLEntry_TYPE and its related functions with systemClasses[]
614  * THREAD SAFETY:
615  *  Not Thread Safe - for performance and complexity reasons
616  *
617  *  Since this function is only called by PKIX_PL_Initialize, which should
618  *  only be called once, it is acceptable that this function is not
619  *  thread-safe.
620  */
621 PKIX_Error *
pkix_pl_CRLEntry_RegisterSelf(void * plContext)622 pkix_pl_CRLEntry_RegisterSelf(void *plContext)
623 {
624 
625         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
626         pkix_ClassTable_Entry entry;
627 
628         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_RegisterSelf");
629 
630         entry.description = "CRLEntry";
631         entry.objCounter = 0;
632         entry.typeObjectSize = sizeof(PKIX_PL_CRLEntry);
633         entry.destructor = pkix_pl_CRLEntry_Destroy;
634         entry.equalsFunction = pkix_pl_CRLEntry_Equals;
635         entry.hashcodeFunction = pkix_pl_CRLEntry_Hashcode;
636         entry.toStringFunction = pkix_pl_CRLEntry_ToString;
637         entry.comparator = NULL;
638         entry.duplicateFunction = pkix_duplicateImmutable;
639 
640         systemClasses[PKIX_CRLENTRY_TYPE] = entry;
641 
642         PKIX_RETURN(CRLENTRY);
643 }
644 
645 /*
646  * FUNCTION: pkix_pl_CRLEntry_CreateEntry
647  * DESCRIPTION:
648  *
649  *  Creates a new CRLEntry using the CertCrlEntry pointed to by "nssCrlEntry"
650  *  and stores it at "pCrlEntry". Once created, a CRLEntry is immutable.
651  *
652  *  revokedCertificates SEQUENCE OF SEQUENCE  {
653  *              userCertificate         CertificateSerialNumber,
654  *              revocationDate          Time,
655  *              crlEntryExtensions      Extensions OPTIONAL
656  *                                      -- if present, MUST be v2
657  *
658  * PARAMETERS:
659  *  "nssCrlEntry"
660  *      Address of CERTCrlEntry representing an NSS CRL entry.
661  *      Must be non-NULL.
662  *  "pCrlEntry"
663  *      Address where object pointer will be stored. Must be non-NULL.
664  *  "plContext"
665  *      Platform-specific context pointer.
666  * THREAD SAFETY:
667  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
668  * RETURNS:
669  *  Returns NULL if the function succeeds.
670  *  Returns a CRLEntry Error if the function fails in a non-fatal way.
671  *  Returns a Fatal Error if the function fails in an unrecoverable way.
672  */
673 static PKIX_Error *
pkix_pl_CRLEntry_CreateEntry(CERTCrlEntry * nssCrlEntry,PKIX_PL_CRLEntry ** pCrlEntry,void * plContext)674 pkix_pl_CRLEntry_CreateEntry(
675         CERTCrlEntry *nssCrlEntry, /* entry data to be created from */
676         PKIX_PL_CRLEntry **pCrlEntry,
677         void *plContext)
678 {
679         PKIX_PL_CRLEntry *crlEntry = NULL;
680 
681         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_CreateEntry");
682         PKIX_NULLCHECK_TWO(nssCrlEntry, pCrlEntry);
683 
684         PKIX_CHECK(PKIX_PL_Object_Alloc
685                     (PKIX_CRLENTRY_TYPE,
686                     sizeof (PKIX_PL_CRLEntry),
687                     (PKIX_PL_Object **)&crlEntry,
688                     plContext),
689                     PKIX_COULDNOTCREATECRLENTRYOBJECT);
690 
691         crlEntry->nssCrlEntry = nssCrlEntry;
692         crlEntry->serialNumber = NULL;
693         crlEntry->critExtOids = NULL;
694         crlEntry->userReasonCode = 0;
695         crlEntry->userReasonCodeAbsent = PKIX_FALSE;
696 
697         *pCrlEntry = crlEntry;
698 
699 cleanup:
700 
701         PKIX_RETURN(CRLENTRY);
702 }
703 
704 /*
705  * FUNCTION: pkix_pl_CRLEntry_Create
706  * DESCRIPTION:
707  *
708  *  Creates a List of CRLEntries using the array of CERTCrlEntries pointed to
709  *  by "nssCrlEntries" and stores it at "pCrlEntryList". If "nssCrlEntries" is
710  *  NULL, this function stores an empty List at "pCrlEntryList".
711  *                              }
712  * PARAMETERS:
713  *  "nssCrlEntries"
714  *      Address of array of CERTCrlEntries representing NSS CRL entries.
715  *      Can be NULL if CRL has no NSS CRL entries.
716  *  "pCrlEntryList"
717  *      Address where object pointer will be stored. Must be non-NULL.
718  *  "plContext"
719  *      Platform-specific context pointer.
720  * THREAD SAFETY:
721  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
722  * RETURNS:
723  *  Returns NULL if the function succeeds.
724  *  Returns a CRLEntry Error if the function fails in a non-fatal way.
725  *  Returns a Fatal Error if the function fails in an unrecoverable way.
726  */
727 PKIX_Error *
pkix_pl_CRLEntry_Create(CERTCrlEntry ** nssCrlEntries,PKIX_List ** pCrlEntryList,void * plContext)728 pkix_pl_CRLEntry_Create(
729         CERTCrlEntry **nssCrlEntries, /* head of entry list */
730         PKIX_List **pCrlEntryList,
731         void *plContext)
732 {
733         PKIX_List *entryList = NULL;
734         PKIX_PL_CRLEntry *crlEntry = NULL;
735         CERTCrlEntry **entries = NULL;
736         SECItem serialNumberItem;
737         PKIX_PL_BigInt *serialNumber;
738         char *bytes = NULL;
739         PKIX_UInt32 length;
740 
741         PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Create");
742         PKIX_NULLCHECK_ONE(pCrlEntryList);
743 
744         entries = nssCrlEntries;
745 
746         PKIX_CHECK(PKIX_List_Create(&entryList, plContext),
747                     PKIX_LISTCREATEFAILED);
748 
749         if (entries) {
750             while (*entries){
751                 PKIX_CHECK(pkix_pl_CRLEntry_CreateEntry
752                             (*entries, &crlEntry, plContext),
753                             PKIX_COULDNOTCREATECRLENTRYOBJECT);
754 
755                 /* Get Serial Number */
756                 serialNumberItem = (*entries)->serialNumber;
757                 length = serialNumberItem.len;
758                 bytes = (char *)serialNumberItem.data;
759 
760                 PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
761                             (bytes, length, &serialNumber, plContext),
762                             PKIX_BIGINTCREATEWITHBYTESFAILED);
763 
764                 crlEntry->serialNumber = serialNumber;
765                 crlEntry->nssCrlEntry = *entries;
766 
767                 PKIX_CHECK(PKIX_List_AppendItem
768                             (entryList, (PKIX_PL_Object *)crlEntry, plContext),
769                             PKIX_LISTAPPENDITEMFAILED);
770 
771                 PKIX_DECREF(crlEntry);
772 
773                 entries++;
774             }
775         }
776 
777         *pCrlEntryList = entryList;
778 
779 cleanup:
780         PKIX_DECREF(crlEntry);
781 
782         if (PKIX_ERROR_RECEIVED){
783                 PKIX_DECREF(entryList);
784         }
785 
786         PKIX_RETURN(CRLENTRY);
787 }
788 
789 /* --Public-CRLENTRY-Functions------------------------------------- */
790 
791 /*
792  * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode
793  * (see comments in pkix_pl_pki.h)
794  */
795 PKIX_Error *
PKIX_PL_CRLEntry_GetCRLEntryReasonCode(PKIX_PL_CRLEntry * crlEntry,PKIX_Int32 * pReason,void * plContext)796 PKIX_PL_CRLEntry_GetCRLEntryReasonCode (
797         PKIX_PL_CRLEntry *crlEntry,
798         PKIX_Int32 *pReason,
799         void *plContext)
800 {
801         SECStatus status;
802         CERTCRLEntryReasonCode nssReasonCode;
803 
804         PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCRLEntryReasonCode");
805         PKIX_NULLCHECK_TWO(crlEntry, pReason);
806 
807         if (!crlEntry->userReasonCodeAbsent && crlEntry->userReasonCode == 0) {
808 
809             PKIX_OBJECT_LOCK(crlEntry);
810 
811             if (!crlEntry->userReasonCodeAbsent &&
812                 crlEntry->userReasonCode == 0) {
813 
814                 /* reason code has not been cached in */
815                 PKIX_CRLENTRY_DEBUG("\t\tCERT_FindCRLEntryReasonExten.\n");
816                 status = CERT_FindCRLEntryReasonExten
817                         (crlEntry->nssCrlEntry, &nssReasonCode);
818 
819                 if (status == SECSuccess) {
820                         crlEntry->userReasonCode = (PKIX_Int32) nssReasonCode;
821                 } else {
822                         crlEntry->userReasonCodeAbsent = PKIX_TRUE;
823                 }
824             }
825 
826             PKIX_OBJECT_UNLOCK(crlEntry);
827 
828         }
829 
830         *pReason = crlEntry->userReasonCode;
831 
832 cleanup:
833 
834         PKIX_RETURN(CRLENTRY);
835 }
836 
837 /*
838  * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
839  * (see comments in pkix_pl_pki.h)
840  */
841 PKIX_Error *
PKIX_PL_CRLEntry_GetCriticalExtensionOIDs(PKIX_PL_CRLEntry * crlEntry,PKIX_List ** pList,void * plContext)842 PKIX_PL_CRLEntry_GetCriticalExtensionOIDs (
843         PKIX_PL_CRLEntry *crlEntry,
844         PKIX_List **pList,  /* list of PKIX_PL_OID */
845         void *plContext)
846 {
847         PKIX_List *oidsList = NULL;
848         CERTCertExtension **extensions;
849 
850         PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCriticalExtensionOIDs");
851         PKIX_NULLCHECK_THREE(crlEntry, crlEntry->nssCrlEntry, pList);
852 
853         /* if we don't have a cached copy from before, we create one */
854         if (crlEntry->critExtOids == NULL) {
855 
856                 PKIX_OBJECT_LOCK(crlEntry);
857 
858                 if (crlEntry->critExtOids == NULL) {
859 
860                         extensions = crlEntry->nssCrlEntry->extensions;
861 
862                         PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
863                                     (extensions, &oidsList, plContext),
864                                     PKIX_GETCRITICALEXTENSIONOIDSFAILED);
865 
866                         crlEntry->critExtOids = oidsList;
867                 }
868 
869                 PKIX_OBJECT_UNLOCK(crlEntry);
870 
871         }
872 
873         /* We should return a copy of the List since this list changes */
874         PKIX_DUPLICATE(crlEntry->critExtOids, pList, plContext,
875                 PKIX_OBJECTDUPLICATELISTFAILED);
876 
877 cleanup:
878 
879         PKIX_RETURN(CRLENTRY);
880 }
881