tor-browser

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

pkix_pl_crl.c (33165B)


      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_crl.c
      6 *
      7 * CRL Function Definitions
      8 *
      9 */
     10 
     11 #include "pkix_pl_crl.h"
     12 #include "certxutl.h"
     13 
     14 extern PKIX_PL_HashTable *cachedCrlSigTable;
     15 
     16 /* --Private-CRL-Functions------------------------------------- */
     17 
     18 /*
     19 * FUNCTION: pkix_pl_CRL_GetVersion
     20 * DESCRIPTION:
     21 *
     22 *  Retrieves the version of the CRL pointed to by "crl" and stores it at
     23 *  "pVersion". The version number will either be 0 or 1 (corresponding to
     24 *  v1 or v2, respectively).
     25 *
     26 *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
     27 *
     28 * PARAMETERS:
     29 *  "crl"
     30 *      Address of CRL whose version is to be stored. Must be non-NULL.
     31 *  "pVersion"
     32 *      Address where a version will be stored. Must be non-NULL.
     33 *  "plContext"
     34 *      Platform-specific context pointer.
     35 * THREAD SAFETY:
     36 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     37 * RETURNS:
     38 *  Returns NULL if the function succeeds.
     39 *  Returns a CRL Error if the function fails in a non-fatal way.
     40 *  Returns a Fatal Error if the function fails in an unrecoverable way.
     41 */
     42 static PKIX_Error *
     43 pkix_pl_CRL_GetVersion(
     44        PKIX_PL_CRL *crl,
     45        PKIX_UInt32 *pVersion,
     46        void *plContext)
     47 {
     48        PKIX_UInt32 myVersion;
     49 
     50        PKIX_ENTER(CRL, "pkix_pl_CRL_GetVersion");
     51        PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pVersion);
     52      
     53        PKIX_NULLCHECK_ONE(crl->nssSignedCrl->crl.version.data);
     54 
     55        myVersion = *(crl->nssSignedCrl->crl.version.data);
     56 
     57        if (myVersion > 1) {
     58                PKIX_ERROR(PKIX_VERSIONVALUEMUSTBEV1ORV2);
     59        }
     60 
     61        *pVersion = myVersion;
     62 
     63 cleanup:
     64 
     65        PKIX_RETURN(CRL);
     66 }
     67 
     68 /*
     69 * FUNCTION: PKIX_PL_CRL_GetCRLNumber (see comments in pkix_pl_pki.h)
     70 */
     71 PKIX_Error *
     72 PKIX_PL_CRL_GetCRLNumber(
     73        PKIX_PL_CRL *crl,
     74        PKIX_PL_BigInt **pCrlNumber,
     75        void *plContext)
     76 {
     77        PKIX_PL_BigInt *crlNumber = NULL;
     78        SECItem nssCrlNumber;
     79        PLArenaPool *arena = NULL;
     80        SECStatus status;
     81        PKIX_UInt32 length = 0;
     82        char *bytes = NULL;
     83 
     84        PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCRLNumber");
     85        PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlNumber);
     86 
     87        /* Can call this function only with der been adopted. */
     88        PORT_Assert(crl->adoptedDerCrl);
     89 
     90        if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
     91 
     92            PKIX_OBJECT_LOCK(crl);
     93 
     94            if (!crl->crlNumberAbsent && crl->crlNumber == NULL) {
     95 
     96                nssCrlNumber.type = 0;
     97                nssCrlNumber.len = 0;
     98                nssCrlNumber.data = NULL;
     99 
    100                PKIX_CRL_DEBUG("\t\tCalling PORT_NewArena).\n");
    101                arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    102                if (arena == NULL) {
    103                        PKIX_ERROR(PKIX_OUTOFMEMORY);
    104                }
    105 
    106                PKIX_CRL_DEBUG("\t\tCalling CERT_FindCRLNumberExten\n");
    107                status = CERT_FindCRLNumberExten
    108                        (arena, &crl->nssSignedCrl->crl, &nssCrlNumber);
    109 
    110                if (status == SECSuccess) {
    111                        /* Get data in bytes then convert to bigint */
    112                        length = nssCrlNumber.len;
    113                        bytes = (char *)nssCrlNumber.data;
    114 
    115                        PKIX_CHECK(pkix_pl_BigInt_CreateWithBytes
    116                                    (bytes, length, &crlNumber, plContext),
    117                                    PKIX_BIGINTCREATEWITHBYTESFAILED);
    118 
    119                        /* arena release does the job 
    120                        PKIX_CRL_DEBUG("\t\tCalling SECITEM_FreeItem\n");
    121                        SECITEM_FreeItem(&nssCrlNumber, PKIX_FALSE);
    122                        */
    123                        crl->crlNumber = crlNumber;
    124 
    125                } else {
    126 
    127                        crl->crlNumberAbsent = PKIX_TRUE;
    128                }
    129            }
    130 
    131            PKIX_OBJECT_UNLOCK(crl);
    132 
    133        }
    134 
    135        PKIX_INCREF(crl->crlNumber);
    136 
    137        *pCrlNumber = crl->crlNumber;
    138 
    139 cleanup:
    140 
    141        if (arena){
    142                PKIX_CRL_DEBUG("\t\tCalling PORT_FreeArena).\n");
    143                PORT_FreeArena(arena, PR_FALSE);
    144        }
    145 
    146        PKIX_RETURN(CRL);
    147 }
    148 
    149 /*
    150 * FUNCTION: pkix_pl_CRL_GetSignatureAlgId
    151 *
    152 * DESCRIPTION:
    153 *  Retrieves a pointer to the OID that represents the signature algorithm of
    154 *  the CRL pointed to by "crl" and stores it at "pSignatureAlgId".
    155 *
    156 *  AlgorithmIdentifier  ::=  SEQUENCE  {
    157 *      algorithm               OBJECT IDENTIFIER,
    158 *      parameters              ANY DEFINED BY algorithm OPTIONAL  }
    159 *
    160 * PARAMETERS:
    161 *  "crl"
    162 *      Address of CRL whose signature algorithm OID is to be stored.
    163 *      Must be non-NULL.
    164 *  "pSignatureAlgId"
    165 *      Address where object pointer will be stored. Must be non-NULL.
    166 *  "plContext"
    167 *      Platform-specific context pointer.
    168 * THREAD SAFETY:
    169 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    170 * RETURNS:
    171 *  Returns NULL if the function succeeds.
    172 *  Returns a CRL Error if the function fails in a non-fatal way.
    173 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    174 */
    175 static PKIX_Error *
    176 pkix_pl_CRL_GetSignatureAlgId(
    177        PKIX_PL_CRL *crl,
    178        PKIX_PL_OID **pSignatureAlgId,
    179        void *plContext)
    180 {
    181        PKIX_PL_OID *signatureAlgId = NULL;
    182 
    183        PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId");
    184        PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId);
    185 
    186        /* if we don't have a cached copy from before, we create one */
    187        if (crl->signatureAlgId == NULL){
    188                PKIX_OBJECT_LOCK(crl);
    189                if (crl->signatureAlgId == NULL){
    190                    CERTCrl *nssCrl = &(crl->nssSignedCrl->crl);
    191                    SECAlgorithmID *algorithm = &nssCrl->signatureAlg;
    192                    SECItem *algBytes = &algorithm->algorithm;
    193 
    194                    if (!algBytes->data || !algBytes->len) {
    195                        PKIX_ERROR(PKIX_OIDBYTESLENGTH0);
    196                    }
    197                    PKIX_CHECK(PKIX_PL_OID_CreateBySECItem
    198                               (algBytes, &signatureAlgId, plContext),
    199                               PKIX_OIDCREATEFAILED);
    200                    
    201                    /* save a cached copy in case it is asked for again */
    202                    crl->signatureAlgId = signatureAlgId;
    203                    signatureAlgId = NULL;
    204                }
    205                PKIX_OBJECT_UNLOCK(crl);
    206        }
    207        PKIX_INCREF(crl->signatureAlgId);
    208        *pSignatureAlgId = crl->signatureAlgId;
    209 cleanup:
    210        PKIX_DECREF(signatureAlgId);
    211        PKIX_RETURN(CRL);
    212 }
    213 
    214 /*
    215 * FUNCTION: pkix_pl_CRL_GetCRLEntries
    216 * DESCRIPTION:
    217 *
    218 *  Retrieves a pointer to the List of CRLEntries found in the CRL pointed to
    219 *  by "crl" and stores it at "pCRLEntries". If there are no CRLEntries,
    220 *  this functions stores NULL at "pCRLEntries".
    221 *
    222 * PARAMETERS:
    223 *  "crl"
    224 *      Address of CRL whose CRL Entries are to be retrieved. Must be non-NULL.
    225 *  "pCRLEntries"
    226 *      Address where object pointer will be stored. Must be non-NULL.
    227 *  "plContext"
    228 *      Platform-specific context pointer.
    229 * THREAD SAFETY:
    230 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    231 * RETURNS:
    232 *  Returns NULL if the function succeeds.
    233 *  Returns a CRL Error if the function fails in a non-fatal way.
    234 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    235 */
    236 static PKIX_Error *
    237 pkix_pl_CRL_GetCRLEntries(
    238        PKIX_PL_CRL *crl,
    239        PKIX_List **pCrlEntries,
    240        void *plContext)
    241 {
    242        PKIX_List *entryList = NULL;
    243        CERTCrl *nssCrl = NULL;
    244 
    245        PKIX_ENTER(CRL, "pkix_pl_CRL_GetCRLEntries");
    246        PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCrlEntries);
    247 
    248        /* if we don't have a cached copy from before, we create one */
    249        if (crl->crlEntryList == NULL) {
    250 
    251                PKIX_OBJECT_LOCK(crl);
    252 
    253                if (crl->crlEntryList == NULL){
    254 
    255                        nssCrl = &(crl->nssSignedCrl->crl);
    256 
    257                        PKIX_CHECK(pkix_pl_CRLEntry_Create
    258                                    (nssCrl->entries, &entryList, plContext),
    259                                    PKIX_CRLENTRYCREATEFAILED);
    260 
    261                        PKIX_CHECK(PKIX_List_SetImmutable
    262                                    (entryList, plContext),
    263                                    PKIX_LISTSETIMMUTABLEFAILED);
    264 
    265                        crl->crlEntryList = entryList;
    266                }
    267 
    268                PKIX_OBJECT_UNLOCK(crl);
    269 
    270        }
    271 
    272        PKIX_INCREF(crl->crlEntryList);
    273 
    274        *pCrlEntries = crl->crlEntryList;
    275 
    276 cleanup:
    277 
    278        PKIX_RETURN(CRL);
    279 }
    280 
    281 /*
    282 * FUNCTION: pkix_pl_CRL_Destroy
    283 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
    284 */
    285 static PKIX_Error *
    286 pkix_pl_CRL_Destroy(
    287        PKIX_PL_Object *object,
    288        void *plContext)
    289 {
    290        PKIX_PL_CRL *crl = NULL;
    291 
    292        PKIX_ENTER(CRL, "pkix_pl_CRL_Destroy");
    293        PKIX_NULLCHECK_ONE(object);
    294 
    295        PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
    296                    PKIX_OBJECTNOTCRL);
    297 
    298        crl = (PKIX_PL_CRL*)object;
    299 
    300        PKIX_CRL_DEBUG("\t\tCalling CERT_DestroyCrl\n");
    301        if (crl->nssSignedCrl) {
    302            CERT_DestroyCrl(crl->nssSignedCrl);
    303        }
    304        if (crl->adoptedDerCrl) {
    305            SECITEM_FreeItem(crl->adoptedDerCrl, PR_TRUE);
    306        }
    307        crl->nssSignedCrl = NULL;
    308        crl->adoptedDerCrl = NULL;
    309        crl->crlNumberAbsent = PKIX_FALSE;
    310 
    311        PKIX_DECREF(crl->issuer);
    312        PKIX_DECREF(crl->signatureAlgId);
    313        PKIX_DECREF(crl->crlNumber);
    314        PKIX_DECREF(crl->crlEntryList);
    315        PKIX_DECREF(crl->critExtOids);
    316        if (crl->derGenName) {
    317            SECITEM_FreeItem(crl->derGenName, PR_TRUE);
    318        }
    319 
    320 cleanup:
    321 
    322        PKIX_RETURN(CRL);
    323 }
    324 
    325 /*
    326 * FUNCTION: pkix_pl_CRL_ToString_Helper
    327 * DESCRIPTION:
    328 *
    329 *  Helper function that creates a string representation of the CRL pointed
    330 *  to by "crl" and stores it at "pString".
    331 *
    332 * PARAMETERS
    333 *  "crl"
    334 *      Address of CRL whose string representation is desired.
    335 *      Must be non-NULL.
    336 *  "pString"
    337 *      Address where object pointer will be stored. Must be non-NULL.
    338 *  "plContext"
    339 *      Platform-specific context pointer.
    340 * THREAD SAFETY:
    341 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    342 * RETURNS:
    343 *  Returns NULL if the function succeeds.
    344 *  Returns a CRL Error if the function fails in a non-fatal way.
    345 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    346 */
    347 static PKIX_Error *
    348 pkix_pl_CRL_ToString_Helper(
    349        PKIX_PL_CRL *crl,
    350        PKIX_PL_String **pString,
    351        void *plContext)
    352 {
    353        char *asciiFormat = NULL;
    354        PKIX_UInt32 crlVersion = 0;
    355        PKIX_PL_X500Name *crlIssuer = NULL;
    356        PKIX_PL_OID *nssSignatureAlgId = NULL;
    357        PKIX_PL_BigInt *crlNumber = NULL;
    358        PKIX_List *crlEntryList = NULL;
    359        PKIX_List *critExtOIDs = NULL;
    360        PKIX_PL_String *formatString = NULL;
    361        PKIX_PL_String *crlIssuerString = NULL;
    362        PKIX_PL_String *lastUpdateString = NULL;
    363        PKIX_PL_String *nextUpdateString = NULL;
    364        PKIX_PL_String *nssSignatureAlgIdString = NULL;
    365        PKIX_PL_String *crlNumberString = NULL;
    366        PKIX_PL_String *crlEntryListString = NULL;
    367        PKIX_PL_String *critExtOIDsString = NULL;
    368        PKIX_PL_String *crlString = NULL;
    369 
    370        PKIX_ENTER(CRL, "pkix_pl_CRL_ToString_Helper");
    371        PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pString);
    372 
    373        asciiFormat =
    374                "[\n"
    375                "\tVersion:         v%d\n"
    376                "\tIssuer:          %s\n"
    377                "\tUpdate:   [Last: %s\n"
    378                "\t           Next: %s]\n"
    379                "\tSignatureAlgId:  %s\n"
    380                "\tCRL Number     : %s\n"
    381                "\n"
    382                "\tEntry List:      %s\n"
    383                "\n"
    384                "\tCritExtOIDs:     %s\n"
    385                "]\n";
    386 
    387        PKIX_CHECK(PKIX_PL_String_Create
    388                    (PKIX_ESCASCII,
    389                    asciiFormat,
    390                    0,
    391                    &formatString,
    392                    plContext),
    393                    PKIX_STRINGCREATEFAILED);
    394 
    395        /* Version */
    396        PKIX_CHECK(pkix_pl_CRL_GetVersion(crl, &crlVersion, plContext),
    397                    PKIX_CRLGETVERSIONFAILED);
    398 
    399        /* Issuer */
    400        PKIX_CHECK(PKIX_PL_CRL_GetIssuer(crl, &crlIssuer, plContext),
    401                    PKIX_CRLGETISSUERFAILED);
    402 
    403        PKIX_CHECK(PKIX_PL_Object_ToString
    404                    ((PKIX_PL_Object *)crlIssuer, &crlIssuerString, plContext),
    405                    PKIX_X500NAMETOSTRINGFAILED);
    406 
    407        /* This update - No Date object created, use nss data directly */
    408        PKIX_CHECK(pkix_pl_Date_ToString_Helper
    409                    (&(crl->nssSignedCrl->crl.lastUpdate),
    410                    &lastUpdateString,
    411                    plContext),
    412                    PKIX_DATETOSTRINGHELPERFAILED);
    413 
    414        /* Next update - No Date object created, use nss data directly */
    415        PKIX_CHECK(pkix_pl_Date_ToString_Helper
    416                    (&(crl->nssSignedCrl->crl.nextUpdate),
    417                    &nextUpdateString,
    418                    plContext),
    419                    PKIX_DATETOSTRINGHELPERFAILED);
    420 
    421        /* Signature Algorithm Id */
    422        PKIX_CHECK(pkix_pl_CRL_GetSignatureAlgId
    423                    (crl, &nssSignatureAlgId, plContext),
    424                    PKIX_CRLGETSIGNATUREALGIDFAILED);
    425 
    426        PKIX_CHECK(PKIX_PL_Object_ToString
    427                    ((PKIX_PL_Object *)nssSignatureAlgId,
    428                    &nssSignatureAlgIdString,
    429                    plContext),
    430                    PKIX_OIDTOSTRINGFAILED);
    431 
    432        /* CRL Number */
    433        PKIX_CHECK(PKIX_PL_CRL_GetCRLNumber
    434                    (crl, &crlNumber, plContext),
    435                    PKIX_CRLGETCRLNUMBERFAILED);
    436 
    437        PKIX_TOSTRING(crlNumber, &crlNumberString, plContext,
    438                    PKIX_BIGINTTOSTRINGFAILED);
    439 
    440        /* CRL Entries */
    441        PKIX_CHECK(pkix_pl_CRL_GetCRLEntries(crl, &crlEntryList, plContext),
    442                    PKIX_CRLGETCRLENTRIESFAILED);
    443 
    444        PKIX_TOSTRING(crlEntryList, &crlEntryListString, plContext,
    445                    PKIX_LISTTOSTRINGFAILED);
    446 
    447        /* CriticalExtensionOIDs */
    448        PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs
    449                    (crl, &critExtOIDs, plContext),
    450                    PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED);
    451 
    452        PKIX_TOSTRING(critExtOIDs, &critExtOIDsString, plContext,
    453                    PKIX_LISTTOSTRINGFAILED);
    454 
    455        PKIX_CHECK(PKIX_PL_Sprintf
    456                    (&crlString,
    457                    plContext,
    458                    formatString,
    459                    crlVersion + 1,
    460                    crlIssuerString,
    461                    lastUpdateString,
    462                    nextUpdateString,
    463                    nssSignatureAlgIdString,
    464                    crlNumberString,
    465                    crlEntryListString,
    466                    critExtOIDsString),
    467                    PKIX_SPRINTFFAILED);
    468 
    469        *pString = crlString;
    470 
    471 cleanup:
    472 
    473        PKIX_DECREF(crlIssuer);
    474        PKIX_DECREF(nssSignatureAlgId);
    475        PKIX_DECREF(crlNumber);
    476        PKIX_DECREF(crlEntryList);
    477        PKIX_DECREF(critExtOIDs);
    478        PKIX_DECREF(crlIssuerString);
    479        PKIX_DECREF(lastUpdateString);
    480        PKIX_DECREF(nextUpdateString);
    481        PKIX_DECREF(nssSignatureAlgIdString);
    482        PKIX_DECREF(crlNumberString);
    483        PKIX_DECREF(crlEntryListString);
    484        PKIX_DECREF(critExtOIDsString);
    485        PKIX_DECREF(formatString);
    486 
    487        PKIX_RETURN(CRL);
    488 }
    489 
    490 /*
    491 * FUNCTION: pkix_pl_CRL_ToString
    492 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
    493 */
    494 static PKIX_Error *
    495 pkix_pl_CRL_ToString(
    496        PKIX_PL_Object *object,
    497        PKIX_PL_String **pString,
    498        void *plContext)
    499 {
    500        PKIX_PL_String *crlString = NULL;
    501        PKIX_PL_CRL *crl = NULL;
    502 
    503        PKIX_ENTER(CRL, "pkix_pl_CRL_ToString");
    504        PKIX_NULLCHECK_TWO(object, pString);
    505 
    506        PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
    507                    PKIX_OBJECTNOTCRL);
    508 
    509        crl = (PKIX_PL_CRL *) object;
    510 
    511        PKIX_CHECK(pkix_pl_CRL_ToString_Helper(crl, &crlString, plContext),
    512                    PKIX_CRLTOSTRINGHELPERFAILED);
    513 
    514        *pString = crlString;
    515 
    516 cleanup:
    517 
    518        PKIX_RETURN(CRL);
    519 }
    520 
    521 /*
    522 * FUNCTION: pkix_pl_CRL_Hashcode
    523 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
    524 */
    525 static PKIX_Error *
    526 pkix_pl_CRL_Hashcode(
    527        PKIX_PL_Object *object,
    528        PKIX_UInt32 *pHashcode,
    529        void *plContext)
    530 {
    531        PKIX_PL_CRL *crl = NULL;
    532        PKIX_UInt32 certHash;
    533        SECItem *crlDer = NULL;
    534        
    535        PKIX_ENTER(CRL, "pkix_pl_CRL_Hashcode");
    536        PKIX_NULLCHECK_TWO(object, pHashcode);
    537 
    538        PKIX_CHECK(pkix_CheckType(object, PKIX_CRL_TYPE, plContext),
    539                    PKIX_OBJECTNOTCRL);
    540 
    541        crl = (PKIX_PL_CRL *)object;
    542        if (crl->adoptedDerCrl) {
    543            crlDer = crl->adoptedDerCrl;
    544        } else if (crl->nssSignedCrl && crl->nssSignedCrl->derCrl) { 
    545            crlDer = crl->nssSignedCrl->derCrl;
    546        }
    547        if (!crlDer || !crlDer->data) {
    548            PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
    549        }
    550 
    551        PKIX_CHECK(pkix_hash(crlDer->data, crlDer->len,
    552                             &certHash, plContext),
    553                   PKIX_ERRORINHASH);
    554 
    555        *pHashcode = certHash;
    556 
    557 cleanup:
    558 
    559        PKIX_RETURN(CRL);
    560 }
    561 
    562 /*
    563 * FUNCTION: pkix_pl_CRL_Equals
    564 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
    565 */
    566 static PKIX_Error *
    567 pkix_pl_CRL_Equals(
    568        PKIX_PL_Object *firstObject,
    569        PKIX_PL_Object *secondObject,
    570        PKIX_Boolean *pResult,
    571        void *plContext)
    572 {
    573        PKIX_PL_CRL *firstCrl = NULL;
    574        PKIX_PL_CRL *secondCrl = NULL;
    575        SECItem *crlDerOne = NULL, *crlDerTwo = NULL;
    576        PKIX_UInt32 secondType;
    577 
    578        PKIX_ENTER(CRL, "pkix_pl_CRL_Equals");
    579        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
    580 
    581        /* test that firstObject is a CRL */
    582        PKIX_CHECK(pkix_CheckType(firstObject, PKIX_CRL_TYPE, plContext),
    583                    PKIX_FIRSTOBJECTNOTCRL);
    584 
    585        firstCrl = (PKIX_PL_CRL *)firstObject;
    586        secondCrl = (PKIX_PL_CRL *)secondObject;
    587 
    588        /*
    589         * Since we know firstObject is a CRL, if both references are
    590         * identical, they must be equal
    591         */
    592        if (firstCrl == secondCrl){
    593                *pResult = PKIX_TRUE;
    594                goto cleanup;
    595        }
    596 
    597        /*
    598         * If secondCrl isn't a CRL, we don't throw an error.
    599         * We simply return a Boolean result of FALSE
    600         */
    601        *pResult = PKIX_FALSE;
    602        PKIX_CHECK(PKIX_PL_Object_GetType
    603                    ((PKIX_PL_Object *)secondCrl, &secondType, plContext),
    604                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
    605        if (secondType != PKIX_CRL_TYPE) goto cleanup;
    606 
    607        if (firstCrl->adoptedDerCrl) {
    608            crlDerOne = firstCrl->adoptedDerCrl;
    609        } else if (firstCrl->nssSignedCrl && firstCrl->nssSignedCrl->derCrl) {
    610            crlDerOne = firstCrl->nssSignedCrl->derCrl;
    611        }
    612 
    613        if (secondCrl->adoptedDerCrl) {
    614            crlDerTwo = secondCrl->adoptedDerCrl;
    615        } else if (secondCrl->nssSignedCrl && secondCrl->nssSignedCrl->derCrl) {
    616            crlDerTwo = secondCrl->nssSignedCrl->derCrl;
    617        }
    618 
    619        if (SECITEM_CompareItem(crlDerOne, crlDerTwo) == SECEqual) {
    620            *pResult = PKIX_TRUE;
    621        }
    622 
    623 cleanup:
    624 
    625        PKIX_RETURN(CRL);
    626 }
    627 
    628 /*
    629 * FUNCTION: pkix_pl_CRL_RegisterSelf
    630 *
    631 * DESCRIPTION:
    632 *  Registers PKIX_CRL_TYPE and its related functions with systemClasses[]
    633 * THREAD SAFETY:
    634 *
    635 *  Not Thread Safe - for performance and complexity reasons
    636 *
    637 *  Since this function is only called by PKIX_PL_Initialize, which should
    638 *  only be called once, it is acceptable that this function is not
    639 *  thread-safe.
    640 */
    641 PKIX_Error *
    642 pkix_pl_CRL_RegisterSelf(void *plContext)
    643 {
    644        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
    645        pkix_ClassTable_Entry *entry = &systemClasses[PKIX_CRL_TYPE];
    646 
    647        PKIX_ENTER(CRL, "pkix_pl_CRL_RegisterSelf");
    648 
    649        entry->description = "CRL";
    650        entry->typeObjectSize = sizeof(PKIX_PL_CRL);
    651        entry->destructor = pkix_pl_CRL_Destroy;
    652        entry->equalsFunction = pkix_pl_CRL_Equals;
    653        entry->hashcodeFunction = pkix_pl_CRL_Hashcode;
    654        entry->toStringFunction = pkix_pl_CRL_ToString;
    655        entry->duplicateFunction = pkix_duplicateImmutable;
    656 
    657        PKIX_RETURN(CRL);
    658 }
    659 
    660 /*
    661 * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h)
    662 */
    663 PKIX_Error *
    664 PKIX_PL_CRL_VerifyUpdateTime(
    665        PKIX_PL_CRL *crl,
    666        PKIX_PL_Date *date,
    667        PKIX_Boolean *pResult,
    668        void *plContext)
    669 {
    670        PRTime timeToCheck;
    671        PRTime nextUpdate;
    672        PRTime lastUpdate;
    673        SECStatus status;
    674        CERTCrl *nssCrl = NULL;
    675        SECItem *nextUpdateDer = NULL;
    676        PKIX_Boolean haveNextUpdate = PR_FALSE;
    677 
    678        PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime");
    679        PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult);
    680 
    681        /* Can call this function only with der been adopted. */
    682        PORT_Assert(crl->adoptedDerCrl);
    683 
    684        nssCrl = &(crl->nssSignedCrl->crl);
    685        timeToCheck = date->nssTime;
    686 
    687        /* nextUpdate can be NULL. Checking before using it */
    688        nextUpdateDer = &nssCrl->nextUpdate;
    689        if (nextUpdateDer->data && nextUpdateDer->len) {
    690                haveNextUpdate = PR_TRUE;
    691                status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer);
    692                if (status != SECSuccess) {
    693                        PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED);
    694                }
    695        }
    696 
    697        status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate));
    698        if (status != SECSuccess) {
    699                PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED);
    700        }
    701 
    702        if (!haveNextUpdate || nextUpdate < timeToCheck) {
    703                *pResult = PKIX_FALSE;
    704                goto cleanup;
    705        }
    706 
    707        if (lastUpdate <= timeToCheck) {
    708                *pResult = PKIX_TRUE;
    709        } else {
    710                *pResult = PKIX_FALSE;
    711        }
    712 
    713 cleanup:
    714 
    715        PKIX_RETURN(CRL);
    716 }
    717 
    718 /*
    719 * FUNCTION: pkix_pl_CRL_CreateWithSignedCRL
    720 * DESCRIPTION:
    721 *
    722 *  Creates a new CRL using the CERTSignedCrl pointed to by "nssSignedCrl"
    723 *  and stores it at "pCRL". If the decoding of the CERTSignedCrl fails,
    724 *  a PKIX_Error is returned.
    725 *
    726 * PARAMETERS:
    727 *  "nssSignedCrl"
    728 *      Address of CERTSignedCrl. Must be non-NULL.
    729 *  "adoptedDerCrl"
    730 *      SECItem ponter that if not NULL is indicating that memory used
    731 *      for der should be adopted by crl that is about to be created.
    732 *  "pCRL"
    733 *      Address where object pointer will be stored. Must be non-NULL.
    734 *  "plContext"
    735 *      Platform-specific context pointer.
    736 * THREAD SAFETY:
    737 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    738 * RETURNS:
    739 *  Returns NULL if the function succeeds.
    740 *  Returns a CRL Error if the function fails in a non-fatal way.
    741 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    742 */
    743 PKIX_Error *
    744 pkix_pl_CRL_CreateWithSignedCRL(
    745        CERTSignedCrl *nssSignedCrl,
    746        SECItem *adoptedDerCrl,
    747        SECItem *derGenName,
    748        PKIX_PL_CRL **pCrl,
    749        void *plContext)
    750 {
    751        PKIX_PL_CRL *crl = NULL;
    752 
    753        PKIX_ENTER(CRL, "pkix_pl_CRL_CreateWithSignedCRL");
    754        PKIX_NULLCHECK_ONE(pCrl);
    755 
    756        /* create a PKIX_PL_CRL object */
    757        PKIX_CHECK(PKIX_PL_Object_Alloc
    758                    (PKIX_CRL_TYPE,
    759                    sizeof (PKIX_PL_CRL),
    760                    (PKIX_PL_Object **)&crl,
    761                    plContext),
    762                    PKIX_COULDNOTCREATECRLOBJECT);
    763 
    764        /* populate the nssSignedCrl field */
    765        crl->nssSignedCrl = nssSignedCrl;
    766        crl->adoptedDerCrl = adoptedDerCrl;
    767        crl->issuer = NULL;
    768        crl->signatureAlgId = NULL;
    769        crl->crlNumber = NULL;
    770        crl->crlNumberAbsent = PKIX_FALSE;
    771        crl->crlEntryList = NULL;
    772        crl->critExtOids = NULL;
    773        if (derGenName) {
    774            crl->derGenName =
    775                SECITEM_DupItem(derGenName);
    776            if (!crl->derGenName) {
    777                PKIX_ERROR(PKIX_ALLOCERROR);
    778            }
    779        }
    780 
    781        *pCrl = crl;
    782 
    783 cleanup:
    784 
    785        if (PKIX_ERROR_RECEIVED){
    786                PKIX_DECREF(crl);
    787        }
    788 
    789        PKIX_RETURN(CRL);
    790 }
    791 
    792 /* --Public-CRL-Functions------------------------------------- */
    793 
    794 /*
    795 * FUNCTION: PKIX_PL_CRL_Create (see comments in pkix_pl_pki.h)
    796 */
    797 PKIX_Error *
    798 PKIX_PL_CRL_Create(
    799        PKIX_PL_ByteArray *byteArray,
    800        PKIX_PL_CRL **pCrl,
    801        void *plContext)
    802 {
    803        CERTSignedCrl *nssSignedCrl = NULL;
    804        SECItem derItem, *derCrl = NULL;
    805        PKIX_PL_CRL *crl = NULL;
    806 
    807        PKIX_ENTER(CRL, "PKIX_PL_CRL_Create");
    808        PKIX_NULLCHECK_TWO(byteArray, pCrl);
    809 
    810        if (byteArray->length == 0){
    811            PKIX_ERROR(PKIX_ZEROLENGTHBYTEARRAYFORCRLENCODING);
    812        }
    813        derItem.type = siBuffer;
    814        derItem.data = byteArray->array;
    815        derItem.len = byteArray->length;
    816        derCrl = SECITEM_DupItem(&derItem);
    817        if (!derCrl) {
    818            PKIX_ERROR(PKIX_ALLOCERROR);
    819        }
    820        nssSignedCrl =
    821            CERT_DecodeDERCrlWithFlags(NULL, derCrl, SEC_CRL_TYPE,
    822                                       CRL_DECODE_DONT_COPY_DER |
    823                                       CRL_DECODE_SKIP_ENTRIES);
    824        if (!nssSignedCrl) {
    825            PKIX_ERROR(PKIX_CERTDECODEDERCRLFAILED);
    826        }
    827        PKIX_CHECK(
    828            pkix_pl_CRL_CreateWithSignedCRL(nssSignedCrl, derCrl, NULL,
    829                                            &crl, plContext),
    830            PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
    831        nssSignedCrl = NULL;
    832        derCrl = NULL;
    833        *pCrl = crl;
    834 
    835 cleanup:
    836        if (derCrl) {
    837            SECITEM_FreeItem(derCrl, PR_TRUE);
    838        }
    839        if (nssSignedCrl) {
    840            SEC_DestroyCrl(nssSignedCrl);
    841        } 
    842 
    843        PKIX_RETURN(CRL);
    844 }
    845 
    846 /*
    847 * FUNCTION: PKIX_PL_CRL_GetIssuer (see comments in pkix_pl_pki.h)
    848 */
    849 PKIX_Error *
    850 PKIX_PL_CRL_GetIssuer(
    851        PKIX_PL_CRL *crl,
    852        PKIX_PL_X500Name **pCRLIssuer,
    853        void *plContext)
    854 {
    855        PKIX_PL_String *crlString = NULL;
    856        PKIX_PL_X500Name *issuer = NULL;
    857        SECItem  *derIssuerName = NULL;
    858        CERTName *issuerName = NULL;
    859 
    860        PKIX_ENTER(CRL, "PKIX_PL_CRL_GetIssuer");
    861        PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pCRLIssuer);
    862 
    863        /* Can call this function only with der been adopted. */
    864        PORT_Assert(crl->adoptedDerCrl);
    865 
    866        /* if we don't have a cached copy from before, we create one */
    867        if (crl->issuer == NULL){
    868 
    869                PKIX_OBJECT_LOCK(crl);
    870 
    871                if (crl->issuer == NULL) {
    872 
    873                        issuerName = &crl->nssSignedCrl->crl.name;
    874                        derIssuerName = &crl->nssSignedCrl->crl.derName;
    875 
    876                        PKIX_CHECK(
    877                            PKIX_PL_X500Name_CreateFromCERTName(derIssuerName,
    878                                                                issuerName,
    879                                                                &issuer,
    880                                                                plContext),
    881                            PKIX_X500NAMECREATEFROMCERTNAMEFAILED);
    882                        
    883                        /* save a cached copy in case it is asked for again */
    884                        crl->issuer = issuer;
    885                }
    886 
    887                PKIX_OBJECT_UNLOCK(crl);
    888 
    889        }
    890 
    891        PKIX_INCREF(crl->issuer);
    892 
    893        *pCRLIssuer = crl->issuer;
    894 
    895 cleanup:
    896 
    897        PKIX_DECREF(crlString);
    898 
    899        PKIX_RETURN(CRL);
    900 }
    901 
    902 
    903 /*
    904 * FUNCTION: PKIX_PL_CRL_GetCriticalExtensionOIDs
    905 * (see comments in pkix_pl_pki.h)
    906 */
    907 PKIX_Error *
    908 PKIX_PL_CRL_GetCriticalExtensionOIDs(
    909        PKIX_PL_CRL *crl,
    910        PKIX_List **pExtensions,   /* list of PKIX_PL_OID */
    911        void *plContext)
    912 {
    913        PKIX_List *oidsList = NULL;
    914        CERTCertExtension **extensions = NULL;
    915        CERTCrl *nssSignedCrl = NULL;
    916 
    917        PKIX_ENTER(CRL, "PKIX_PL_CRL_GetCriticalExtensionOIDs");
    918        PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pExtensions);
    919 
    920        /* Can call this function only with der been adopted. */
    921        PORT_Assert(crl->adoptedDerCrl);
    922 
    923        /* if we don't have a cached copy from before, we create one */
    924        if (crl->critExtOids == NULL) {
    925 
    926                PKIX_OBJECT_LOCK(crl);
    927 
    928                nssSignedCrl = &(crl->nssSignedCrl->crl);
    929                extensions = nssSignedCrl->extensions;
    930 
    931                if (crl->critExtOids == NULL) {
    932 
    933                        PKIX_CHECK(pkix_pl_OID_GetCriticalExtensionOIDs
    934                                    (extensions, &oidsList, plContext),
    935                                    PKIX_GETCRITICALEXTENSIONOIDSFAILED);
    936 
    937                        crl->critExtOids = oidsList;
    938                }
    939 
    940                PKIX_OBJECT_UNLOCK(crl);
    941 
    942        }
    943 
    944        /* We should return a copy of the List since this list changes */
    945        PKIX_DUPLICATE(crl->critExtOids, pExtensions, plContext,
    946                PKIX_OBJECTDUPLICATELISTFAILED);
    947 
    948 cleanup:
    949 
    950        PKIX_RETURN(CRL);
    951 }
    952 
    953 /*
    954 * FUNCTION: PKIX_PL_CRL_VerifySignature (see comments in pkix_pl_pki.h)
    955 */
    956 PKIX_Error *
    957 PKIX_PL_CRL_VerifySignature(
    958        PKIX_PL_CRL *crl,
    959        PKIX_PL_PublicKey *pubKey,
    960        void *plContext)
    961 {
    962        PKIX_PL_CRL *cachedCrl = NULL;
    963        PKIX_Error *verifySig = NULL;
    964        PKIX_Error *cachedSig = NULL;
    965        PKIX_Boolean crlEqual = PKIX_FALSE;
    966        PKIX_Boolean crlInHash= PKIX_FALSE;
    967        CERTSignedCrl *nssSignedCrl = NULL;
    968        SECKEYPublicKey *nssPubKey = NULL;
    969        CERTSignedData *tbsCrl = NULL;
    970        void* wincx = NULL;
    971        SECStatus status;
    972 
    973        PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifySignature");
    974        PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pubKey);
    975 
    976        /* Can call this function only with der been adopted. */
    977        PORT_Assert(crl->adoptedDerCrl);
    978 
    979        verifySig = PKIX_PL_HashTable_Lookup
    980                (cachedCrlSigTable,
    981                (PKIX_PL_Object *) pubKey,
    982                (PKIX_PL_Object **) &cachedCrl,
    983                plContext);
    984 
    985        if (cachedCrl != NULL && verifySig == NULL) {
    986                /* Cached Signature Table lookup succeed */
    987                PKIX_EQUALS(crl, cachedCrl, &crlEqual, plContext,
    988                            PKIX_OBJECTEQUALSFAILED);
    989                if (crlEqual == PKIX_TRUE) {
    990                        goto cleanup;
    991                }
    992                /* Different PubKey may hash to same value, skip add */
    993                crlInHash = PKIX_TRUE;
    994        }
    995 
    996        nssSignedCrl = crl->nssSignedCrl;
    997        tbsCrl = &nssSignedCrl->signatureWrap;
    998 
    999        PKIX_CRL_DEBUG("\t\tCalling SECKEY_ExtractPublicKey\n");
   1000        nssPubKey = SECKEY_ExtractPublicKey(pubKey->nssSPKI);
   1001        if (!nssPubKey){
   1002                PKIX_ERROR(PKIX_SECKEYEXTRACTPUBLICKEYFAILED);
   1003        }
   1004 
   1005        PKIX_CHECK(pkix_pl_NssContext_GetWincx
   1006                   ((PKIX_PL_NssContext *)plContext, &wincx),
   1007                   PKIX_NSSCONTEXTGETWINCXFAILED);
   1008 
   1009        PKIX_CRL_DEBUG("\t\tCalling CERT_VerifySignedDataWithPublicKey\n");
   1010        status = CERT_VerifySignedDataWithPublicKey(tbsCrl, nssPubKey, wincx);
   1011 
   1012        if (status != SECSuccess) {
   1013                PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
   1014                PKIX_ERROR(PKIX_SIGNATUREDIDNOTVERIFYWITHTHEPUBLICKEY);
   1015        }
   1016 
   1017        if (crlInHash == PKIX_FALSE) {
   1018                cachedSig = PKIX_PL_HashTable_Add
   1019                        (cachedCrlSigTable,
   1020                        (PKIX_PL_Object *) pubKey,
   1021                        (PKIX_PL_Object *) crl,
   1022                        plContext);
   1023 
   1024                if (cachedSig != NULL) {
   1025                        PKIX_DEBUG("PKIX_PL_HashTable_Add skipped: entry existed\n");
   1026                }
   1027        }
   1028 
   1029 cleanup:
   1030 
   1031        if (nssPubKey){
   1032                PKIX_CRL_DEBUG("\t\tCalling SECKEY_DestroyPublicKey\n");
   1033                SECKEY_DestroyPublicKey(nssPubKey);
   1034                nssPubKey = NULL;
   1035        }
   1036 
   1037        PKIX_DECREF(cachedCrl);
   1038        PKIX_DECREF(verifySig);
   1039        PKIX_DECREF(cachedSig);
   1040 
   1041        PKIX_RETURN(CRL);
   1042 }
   1043 
   1044 PKIX_Error*
   1045 PKIX_PL_CRL_ReleaseDerCrl(PKIX_PL_CRL *crl,
   1046                         SECItem **derCrl,
   1047                         void *plContext)
   1048 {
   1049    PKIX_ENTER(CRL, "PKIX_PL_CRL_ReleaseDerCrl");
   1050    *derCrl = crl->adoptedDerCrl;
   1051    crl->adoptedDerCrl = NULL;
   1052        
   1053    PKIX_RETURN(CRL);
   1054 }
   1055 
   1056 PKIX_Error*
   1057 PKIX_PL_CRL_AdoptDerCrl(PKIX_PL_CRL *crl,
   1058                         SECItem *derCrl,
   1059                         void *plContext)
   1060 {
   1061    PKIX_ENTER(CRL, "PKIX_PL_CRL_AquireDerCrl");
   1062    if (crl->adoptedDerCrl) {
   1063        PKIX_ERROR(PKIX_CANNOTAQUIRECRLDER);
   1064    }
   1065    crl->adoptedDerCrl = derCrl;
   1066 cleanup:        
   1067    PKIX_RETURN(CRL);
   1068 }