PageRenderTime 60ms CodeModel.GetById 2ms app.highlight 51ms RepoModel.GetById 2ms app.codeStats 0ms

/security/nss/lib/libpkix/pkix_pl_nss/pki/pkix_pl_crlentry.c

http://github.com/zpao/v8monkey
C | 913 lines | 520 code | 161 blank | 232 comment | 59 complexity | 5d567ceaa5e41b44be0b18907ad06882 MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  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/
  8 *
  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.
 13 *
 14 * The Original Code is the PKIX-C library.
 15 *
 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.
 20 *
 21 * Contributor(s):
 22 *   Sun Microsystems, Inc.
 23 *
 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.
 35 *
 36 * ***** END LICENSE BLOCK ***** */
 37/*
 38 * pkix_pl_crlentry.c
 39 *
 40 * CRLENTRY Function Definitions
 41 *
 42 */
 43
 44#include "pkix_pl_crlentry.h"
 45
 46/* --Private-CRLEntry-Functions------------------------------------- */
 47
 48/*
 49 * FUNCTION: pkix_pl_CRLEntry_Destroy
 50 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
 51 */
 52static PKIX_Error *
 53pkix_pl_CRLEntry_Destroy(
 54        PKIX_PL_Object *object,
 55        void *plContext)
 56{
 57        PKIX_PL_CRLEntry *crlEntry = NULL;
 58
 59        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Destroy");
 60        PKIX_NULLCHECK_ONE(object);
 61
 62        PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
 63                    PKIX_OBJECTNOTCRLENTRY);
 64
 65        crlEntry = (PKIX_PL_CRLEntry*)object;
 66
 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);
 73
 74cleanup:
 75
 76        PKIX_RETURN(CRLENTRY);
 77}
 78
 79/*
 80 * FUNCTION: pkix_pl_CRLEntry_ToString_Helper
 81 *
 82 * DESCRIPTION:
 83 *  Helper function that creates a string representation of the CRLEntry
 84 *  pointed to by "crlEntry" and stores it at "pString".
 85 *
 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.
100 */
101PKIX_Error *
102pkix_pl_CRLEntry_ToString_Helper(
103        PKIX_PL_CRLEntry *crlEntry,
104        PKIX_PL_String **pString,
105        void *plContext)
106{
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;
115
116        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString_Helper");
117        PKIX_NULLCHECK_FOUR
118                (crlEntry,
119                crlEntry->serialNumber,
120                crlEntry->nssCrlEntry,
121                pString);
122
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";
130
131        PKIX_CHECK(PKIX_PL_String_Create
132                    (PKIX_ESCASCII,
133                    asciiFormat,
134                    0,
135                    &formatString,
136                    plContext),
137                    PKIX_STRINGCREATEFAILED);
138
139        /* SerialNumber */
140        PKIX_CHECK(PKIX_PL_Object_ToString
141                    ((PKIX_PL_Object *)crlEntry->serialNumber,
142                    &crlSerialNumberString,
143                    plContext),
144                    PKIX_BIGINTTOSTRINGHELPERFAILED);
145
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);
152
153        /* CriticalExtensionOIDs */
154        PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
155                    (crlEntry, &critExtOIDs, plContext),
156                    PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED);
157
158        PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
159                    PKIX_LISTTOSTRINGFAILED);
160
161        /* Revocation Reason Code */
162        PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
163                            (crlEntry, &reasonCode, plContext),
164                            PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
165
166        PKIX_CHECK(PKIX_PL_Sprintf
167                    (&crlEntryString,
168                    plContext,
169                    formatString,
170                    crlSerialNumberString,
171                    reasonCode,
172                    crlRevocationDateString,
173                    critExtOIDsString),
174                    PKIX_SPRINTFFAILED);
175
176        *pString = crlEntryString;
177
178cleanup:
179
180        PKIX_DECREF(critExtOIDs);
181        PKIX_DECREF(crlSerialNumberString);
182        PKIX_DECREF(crlRevocationDateString);
183        PKIX_DECREF(critExtOIDsString);
184        PKIX_DECREF(formatString);
185
186        PKIX_RETURN(CRLENTRY);
187}
188
189/*
190 * FUNCTION: pkix_pl_CRLEntry_ToString
191 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
192 */
193static PKIX_Error *
194pkix_pl_CRLEntry_ToString(
195        PKIX_PL_Object *object,
196        PKIX_PL_String **pString,
197        void *plContext)
198{
199        PKIX_PL_String *crlEntryString = NULL;
200        PKIX_PL_CRLEntry *crlEntry = NULL;
201
202        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_ToString");
203        PKIX_NULLCHECK_TWO(object, pString);
204
205        PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
206                    PKIX_OBJECTNOTCRLENTRY);
207
208        crlEntry = (PKIX_PL_CRLEntry *) object;
209
210        PKIX_CHECK(pkix_pl_CRLEntry_ToString_Helper
211                    (crlEntry, &crlEntryString, plContext),
212                    PKIX_CRLENTRYTOSTRINGHELPERFAILED);
213
214        *pString = crlEntryString;
215
216cleanup:
217
218        PKIX_RETURN(CRLENTRY);
219}
220
221/*
222 * FUNCTION: pkix_pl_CRLEntry_Extensions_Hashcode
223 * DESCRIPTION:
224 *
225 *  For each CRL Entry extension stored at NSS structure CERTCertExtension,
226 *  get its derbyte data and do the hash.
227 *
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.
246 */
247static PKIX_Error *
248pkix_pl_CRLEntry_Extensions_Hashcode(
249        CERTCertExtension **extensions,
250        PKIX_UInt32 *pHashValue,
251        void *plContext)
252{
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;
259
260        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Hashcode");
261        PKIX_NULLCHECK_TWO(extensions, pHashValue);
262
263        if (extensions) {
264
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);
269                }
270
271                while (*extensions) {
272
273                        extension = *extensions++;
274
275                        PKIX_NULLCHECK_ONE(extension);
276
277                        PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
278                        derBytes = PORT_ArenaZNew(arena, SECItem);
279                        if (derBytes == NULL) {
280                                PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
281                        }
282
283                        PKIX_CRLENTRY_DEBUG
284                                ("\t\tCalling SEC_ASN1EncodeItem\n");
285                        resultSecItem = SEC_ASN1EncodeItem
286                                (arena,
287                                derBytes,
288                                extension,
289                                CERT_CertExtensionTemplate);
290
291                        if (resultSecItem == NULL){
292                                PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
293                        }
294
295                        PKIX_CHECK(pkix_hash
296                                (derBytes->data,
297                                derBytes->len,
298                                &extHash,
299                                plContext),
300                                PKIX_HASHFAILED);
301
302                        hashValue += (extHash << 7);
303
304                }
305        }
306
307        *pHashValue = hashValue;
308
309cleanup:
310
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;
316        }
317        PKIX_RETURN(CRLENTRY);
318}
319
320/*
321 * FUNCTION: pkix_pl_CRLEntry_Hashcode
322 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
323 */
324static PKIX_Error *
325pkix_pl_CRLEntry_Hashcode(
326        PKIX_PL_Object *object,
327        PKIX_UInt32 *pHashcode,
328        void *plContext)
329{
330        SECItem *nssDate = NULL;
331        PKIX_PL_CRLEntry *crlEntry = NULL;
332        PKIX_UInt32 crlEntryHash;
333        PKIX_UInt32 hashValue;
334        PKIX_Int32 reasonCode = 0;
335
336        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Hashcode");
337        PKIX_NULLCHECK_TWO(object, pHashcode);
338
339        PKIX_CHECK(pkix_CheckType(object, PKIX_CRLENTRY_TYPE, plContext),
340                    PKIX_OBJECTNOTCRLENTRY);
341
342        crlEntry = (PKIX_PL_CRLEntry *)object;
343
344        PKIX_NULLCHECK_ONE(crlEntry->nssCrlEntry);
345        nssDate = &(crlEntry->nssCrlEntry->revocationDate);
346
347        PKIX_NULLCHECK_ONE(nssDate->data);
348
349        PKIX_CHECK(pkix_hash
350                ((const unsigned char *)nssDate->data,
351                nssDate->len,
352                &crlEntryHash,
353                plContext),
354                PKIX_ERRORGETTINGHASHCODE);
355
356        PKIX_CHECK(PKIX_PL_Object_Hashcode
357                ((PKIX_PL_Object *)crlEntry->serialNumber,
358                &hashValue,
359                plContext),
360                PKIX_OBJECTHASHCODEFAILED);
361
362        crlEntryHash += (hashValue << 7);
363
364        hashValue = 0;
365
366        if (crlEntry->nssCrlEntry->extensions) {
367
368                PKIX_CHECK(pkix_pl_CRLEntry_Extensions_Hashcode
369                    (crlEntry->nssCrlEntry->extensions, &hashValue, plContext),
370                    PKIX_CRLENTRYEXTENSIONSHASHCODEFAILED);
371        }
372
373        crlEntryHash += (hashValue << 7);
374
375        PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
376                (crlEntry, &reasonCode, plContext),
377                PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);
378
379        crlEntryHash += (reasonCode + 777) << 3;
380
381        *pHashcode = crlEntryHash;
382
383cleanup:
384
385        PKIX_RETURN(CRLENTRY);
386}
387
388/*
389 * FUNCTION: pkix_pl_CRLENTRY_Extensions_Equals
390 * DESCRIPTION:
391 *
392 *  Compare each extension's DERbyte data in "firstExtensions" with extension
393 *  in "secondExtensions" in sequential order and store the result in
394 *  "pResult".
395 *
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.
417 */
418static PKIX_Error *
419pkix_pl_CRLEntry_Extensions_Equals(
420        CERTCertExtension **extensions1,
421        CERTCertExtension **extensions2,
422        PKIX_Boolean *pResult,
423        void *plContext)
424{
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;
438
439        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Extensions_Equals");
440        PKIX_NULLCHECK_THREE(extensions1, extensions2, pResult);
441
442        firstExtensions = extensions1;
443        secondExtensions = extensions2;
444
445        if (firstExtensions) {
446                while (*firstExtensions) {
447                        firstExtension = *firstExtensions++;
448                        firstNumExt++;
449                }
450        }
451
452        if (secondExtensions) {
453                while (*secondExtensions) {
454                        secondExtension = *secondExtensions++;
455                        secondNumExt++;
456                }
457        }
458
459        if (firstNumExt != secondNumExt) {
460                *pResult = PKIX_FALSE;
461                goto cleanup;
462        }
463
464        if (firstNumExt == 0 && secondNumExt == 0) {
465                *pResult = PKIX_TRUE;
466                goto cleanup;
467        }
468
469        /* now have equal number, but non-zero extension items to compare */
470
471        firstExtensions = extensions1;
472        secondExtensions = extensions2;
473
474        cmpResult = PKIX_TRUE;
475
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);
480        }
481
482        while (firstNumExt--) {
483
484                firstExtension = *firstExtensions++;
485                secondExtension = *secondExtensions++;
486
487                PKIX_NULLCHECK_TWO(firstExtension, secondExtension);
488
489                PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
490                firstDerBytes = PORT_ArenaZNew(arena, SECItem);
491                if (firstDerBytes == NULL) {
492                        PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
493                }
494
495                PKIX_CRLENTRY_DEBUG("\t\tCalling PORT_ArenaZNew\n");
496                secondDerBytes = PORT_ArenaZNew(arena, SECItem);
497                if (secondDerBytes == NULL) {
498                        PKIX_ERROR(PKIX_PORTARENAALLOCFAILED);
499                }
500
501                PKIX_CRLENTRY_DEBUG
502                        ("\t\tCalling SEC_ASN1EncodeItem\n");
503                firstResultSecItem = SEC_ASN1EncodeItem
504                        (arena,
505                        firstDerBytes,
506                        firstExtension,
507                        CERT_CertExtensionTemplate);
508
509                if (firstResultSecItem == NULL){
510                        PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
511                }
512
513                PKIX_CRLENTRY_DEBUG
514                        ("\t\tCalling SEC_ASN1EncodeItem\n");
515                secondResultSecItem = SEC_ASN1EncodeItem
516                        (arena,
517                        secondDerBytes,
518                        secondExtension,
519                        CERT_CertExtensionTemplate);
520
521                if (secondResultSecItem == NULL){
522                        PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
523                }
524
525                PKIX_CRLENTRY_DEBUG("\t\tCalling SECITEM_CompareItem\n");
526                secResult = SECITEM_CompareItem
527                        (firstResultSecItem, secondResultSecItem);
528
529                if (secResult != SECEqual) {
530                        cmpResult = PKIX_FALSE;
531                        break;
532                }
533
534        }
535
536        *pResult = cmpResult;
537
538cleanup:
539
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;
545        }
546
547        PKIX_RETURN(CRLENTRY);
548}
549
550/*
551 * FUNCTION: pkix_pl_CRLEntry_Equals
552 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
553 */
554static PKIX_Error *
555pkix_pl_CRLEntry_Equals(
556        PKIX_PL_Object *firstObject,
557        PKIX_PL_Object *secondObject,
558        PKIX_Boolean *pResult,
559        void *plContext)
560{
561        PKIX_PL_CRLEntry *firstCrlEntry = NULL;
562        PKIX_PL_CRLEntry *secondCrlEntry = NULL;
563        PKIX_UInt32 secondType;
564        PKIX_Boolean cmpResult = PKIX_FALSE;
565
566        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Equals");
567        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
568
569        /* test that firstObject is a CRLEntry */
570        PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRLENTRY_TYPE, plContext),
571                PKIX_FIRSTOBJECTNOTCRLENTRY);
572
573        firstCrlEntry = (PKIX_PL_CRLEntry *)firstObject;
574        secondCrlEntry = (PKIX_PL_CRLEntry *)secondObject;
575
576        PKIX_NULLCHECK_TWO
577                (firstCrlEntry->nssCrlEntry, secondCrlEntry->nssCrlEntry);
578
579        /*
580         * Since we know firstObject is a CRLEntry, if both references are
581         * identical, they must be equal
582         */
583        if (firstCrlEntry == secondCrlEntry){
584                *pResult = PKIX_TRUE;
585                goto cleanup;
586        }
587
588        /*
589         * If secondCrlEntry isn't a CRL Entry, we don't throw an error.
590         * We simply return a Boolean result of FALSE
591         */
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;
597
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;
606        }
607
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;
618        }
619
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);
627
628        if (cmpResult != PKIX_TRUE){
629                *pResult = PKIX_FALSE;
630                goto cleanup;
631        }
632
633        cmpResult = (firstCrlEntry->userReasonCode ==
634                    secondCrlEntry->userReasonCode);
635
636        *pResult = cmpResult;
637
638cleanup:
639
640        PKIX_RETURN(CRLENTRY);
641}
642
643/*
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
649 *
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.
653 */
654PKIX_Error *
655pkix_pl_CRLEntry_RegisterSelf(void *plContext)
656{
657
658        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
659        pkix_ClassTable_Entry entry;
660
661        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_RegisterSelf");
662
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;
672
673        systemClasses[PKIX_CRLENTRY_TYPE] = entry;
674
675        PKIX_RETURN(CRLENTRY);
676}
677
678/*
679 * FUNCTION: pkix_pl_CRLEntry_CreateEntry
680 * DESCRIPTION:
681 *
682 *  Creates a new CRLEntry using the CertCrlEntry pointed to by "nssCrlEntry"
683 *  and stores it at "pCrlEntry". Once created, a CRLEntry is immutable.
684 *
685 *  revokedCertificates SEQUENCE OF SEQUENCE  {
686 *              userCertificate         CertificateSerialNumber,
687 *              revocationDate          Time,
688 *              crlEntryExtensions      Extensions OPTIONAL
689 *                                      -- if present, MUST be v2
690 *
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.
705 */
706static PKIX_Error *
707pkix_pl_CRLEntry_CreateEntry(
708        CERTCrlEntry *nssCrlEntry, /* entry data to be created from */
709        PKIX_PL_CRLEntry **pCrlEntry,
710        void *plContext)
711{
712        PKIX_PL_CRLEntry *crlEntry = NULL;
713
714        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_CreateEntry");
715        PKIX_NULLCHECK_TWO(nssCrlEntry, pCrlEntry);
716
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);
723
724        crlEntry->nssCrlEntry = nssCrlEntry;
725        crlEntry->serialNumber = NULL;
726        crlEntry->critExtOids = NULL;
727        crlEntry->userReasonCode = 0;
728        crlEntry->userReasonCodeAbsent = PKIX_FALSE;
729
730        *pCrlEntry = crlEntry;
731
732cleanup:
733
734        PKIX_RETURN(CRLENTRY);
735}
736
737/*
738 * FUNCTION: pkix_pl_CRLEntry_Create
739 * DESCRIPTION:
740 *
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".
744 *                              }
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.
759 */
760PKIX_Error *
761pkix_pl_CRLEntry_Create(
762        CERTCrlEntry **nssCrlEntries, /* head of entry list */
763        PKIX_List **pCrlEntryList,
764        void *plContext)
765{
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;
773
774        PKIX_ENTER(CRLENTRY, "pkix_pl_CRLEntry_Create");
775        PKIX_NULLCHECK_ONE(pCrlEntryList);
776
777        entries = nssCrlEntries;
778
779        PKIX_CHECK(PKIX_List_Create(&entryList, plContext),
780                    PKIX_LISTCREATEFAILED);
781
782        if (entries) {
783            while (*entries){
784                PKIX_CHECK(pkix_pl_CRLEntry_CreateEntry
785                            (*entries, &crlEntry, plContext),
786                            PKIX_COULDNOTCREATECRLENTRYOBJECT);
787
788                /* Get Serial Number */
789                serialNumberItem = (*entries)->serialNumber;
790                length = serialNumberItem.len;
791                bytes = (char *)serialNumberItem.data;
792
793                PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
794                            (bytes, length, &serialNumber, plContext),
795                            PKIX_BIGINTCREATEWITHBYTESFAILED);
796
797                crlEntry->serialNumber = serialNumber;
798                crlEntry->nssCrlEntry = *entries;
799
800                PKIX_CHECK(PKIX_List_AppendItem
801                            (entryList, (PKIX_PL_Object *)crlEntry, plContext),
802                            PKIX_LISTAPPENDITEMFAILED);
803
804                PKIX_DECREF(crlEntry);
805
806                entries++;
807            }
808        }
809
810        *pCrlEntryList = entryList;
811
812cleanup:
813        PKIX_DECREF(crlEntry);
814
815        if (PKIX_ERROR_RECEIVED){
816                PKIX_DECREF(entryList);
817        }
818
819        PKIX_RETURN(CRLENTRY);
820}
821
822/* --Public-CRLENTRY-Functions------------------------------------- */
823
824/*
825 * FUNCTION: PKIX_PL_CRLEntry_GetCRLEntryReasonCode
826 * (see comments in pkix_pl_pki.h)
827 */
828PKIX_Error *
829PKIX_PL_CRLEntry_GetCRLEntryReasonCode (
830        PKIX_PL_CRLEntry *crlEntry,
831        PKIX_Int32 *pReason,
832        void *plContext)
833{
834        SECStatus status;
835        CERTCRLEntryReasonCode nssReasonCode;
836
837        PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCRLEntryReasonCode");
838        PKIX_NULLCHECK_TWO(crlEntry, pReason);
839
840        if (!crlEntry->userReasonCodeAbsent && crlEntry->userReasonCode == 0) {
841
842            PKIX_OBJECT_LOCK(crlEntry);
843
844            if (!crlEntry->userReasonCodeAbsent &&
845                crlEntry->userReasonCode == 0) {
846
847                /* reason code has not been cached in */
848                PKIX_CRLENTRY_DEBUG("\t\tCERT_FindCRLEntryReasonExten.\n");
849                status = CERT_FindCRLEntryReasonExten
850                        (crlEntry->nssCrlEntry, &nssReasonCode);
851
852                if (status == SECSuccess) {
853                        crlEntry->userReasonCode = (PKIX_Int32) nssReasonCode;
854                } else {
855                        crlEntry->userReasonCodeAbsent = PKIX_TRUE;
856                }
857            }
858
859            PKIX_OBJECT_UNLOCK(crlEntry);
860
861        }
862
863        *pReason = crlEntry->userReasonCode;
864
865cleanup:
866
867        PKIX_RETURN(CRLENTRY);
868}
869
870/*
871 * FUNCTION: PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
872 * (see comments in pkix_pl_pki.h)
873 */
874PKIX_Error *
875PKIX_PL_CRLEntry_GetCriticalExtensionOIDs (
876        PKIX_PL_CRLEntry *crlEntry,
877        PKIX_List **pList,  /* list of PKIX_PL_OID */
878        void *plContext)
879{
880        PKIX_List *oidsList = NULL;
881        CERTCertExtension **extensions;
882
883        PKIX_ENTER(CRLENTRY, "PKIX_PL_CRLEntry_GetCriticalExtensionOIDs");
884        PKIX_NULLCHECK_THREE(crlEntry, crlEntry->nssCrlEntry, pList);
885
886        /* if we don't have a cached copy from before, we create one */
887        if (crlEntry->critExtOids == NULL) {
888
889                PKIX_OBJECT_LOCK(crlEntry);
890
891                if (crlEntry->critExtOids == NULL) {
892
893                        extensions = crlEntry->nssCrlEntry->extensions;
894
895                        PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
896                                    (extensions, &oidsList, plContext),
897                                    PKIX_GETCRITICALEXTENSIONOIDSFAILED);
898
899                        crlEntry->critExtOids = oidsList;
900                }
901
902                PKIX_OBJECT_UNLOCK(crlEntry);
903
904        }
905
906        /* We should return a copy of the List since this list changes */
907        PKIX_DUPLICATE(crlEntry->critExtOids, pList, plContext,
908                PKIX_OBJECTDUPLICATELISTFAILED);
909
910cleanup:
911
912        PKIX_RETURN(CRLENTRY);
913}