tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_pl_crlentry.c (28432B)


      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 *
     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 *
     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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 *
    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 }