tor-browser

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

crmfreq.c (19271B)


      1 /* -*- Mode: C; tab-width: 8 -*-*/
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "crmf.h"
      7 #include "crmfi.h"
      8 #include "keyhi.h"
      9 #include "secder.h"
     10 
     11 /*
     12 * Macro that returns PR_TRUE if the pointer is not NULL.
     13 * If the pointer is NULL, then the macro will return PR_FALSE.
     14 */
     15 #define IS_NOT_NULL(ptr) ((ptr) == NULL) ? PR_FALSE : PR_TRUE
     16 
     17 const unsigned char hexTrue = 0xff;
     18 const unsigned char hexFalse = 0x00;
     19 
     20 SECStatus
     21 crmf_encode_integer(PLArenaPool *poolp, SECItem *dest, long value)
     22 {
     23    SECItem *dummy;
     24 
     25    dummy = SEC_ASN1EncodeInteger(poolp, dest, value);
     26    PORT_Assert(dummy == dest);
     27    if (dummy == NULL) {
     28        return SECFailure;
     29    }
     30    return SECSuccess;
     31 }
     32 
     33 SECStatus
     34 crmf_encode_unsigned_integer(PLArenaPool *poolp, SECItem *dest,
     35                             unsigned long value)
     36 {
     37    SECItem *dummy;
     38 
     39    dummy = SEC_ASN1EncodeUnsignedInteger(poolp, dest, value);
     40    PORT_Assert(dummy == dest);
     41    if (dummy != dest) {
     42        return SECFailure;
     43    }
     44    return SECSuccess;
     45 }
     46 
     47 static SECStatus
     48 crmf_copy_secitem(PLArenaPool *poolp, SECItem *dest, SECItem *src)
     49 {
     50    return SECITEM_CopyItem(poolp, dest, src);
     51 }
     52 
     53 PRBool
     54 CRMF_DoesRequestHaveField(CRMFCertRequest *inCertReq,
     55                          CRMFCertTemplateField inField)
     56 {
     57 
     58    PORT_Assert(inCertReq != NULL);
     59    if (inCertReq == NULL) {
     60        return PR_FALSE;
     61    }
     62    switch (inField) {
     63        case crmfVersion:
     64            return inCertReq->certTemplate.version.data != NULL;
     65        case crmfSerialNumber:
     66            return inCertReq->certTemplate.serialNumber.data != NULL;
     67        case crmfSigningAlg:
     68            return inCertReq->certTemplate.signingAlg != NULL;
     69        case crmfIssuer:
     70            return inCertReq->certTemplate.issuer != NULL;
     71        case crmfValidity:
     72            return inCertReq->certTemplate.validity != NULL;
     73        case crmfSubject:
     74            return inCertReq->certTemplate.subject != NULL;
     75        case crmfPublicKey:
     76            return inCertReq->certTemplate.publicKey != NULL;
     77        case crmfIssuerUID:
     78            return inCertReq->certTemplate.issuerUID.data != NULL;
     79        case crmfSubjectUID:
     80            return inCertReq->certTemplate.subjectUID.data != NULL;
     81        case crmfExtension:
     82            return CRMF_CertRequestGetNumberOfExtensions(inCertReq) != 0;
     83    }
     84    return PR_FALSE;
     85 }
     86 
     87 CRMFCertRequest *
     88 CRMF_CreateCertRequest(PRUint32 inRequestID)
     89 {
     90    PLArenaPool *poolp;
     91    CRMFCertRequest *certReq;
     92    SECStatus rv;
     93 
     94    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
     95    if (poolp == NULL) {
     96        goto loser;
     97    }
     98 
     99    certReq = PORT_ArenaZNew(poolp, CRMFCertRequest);
    100    if (certReq == NULL) {
    101        goto loser;
    102    }
    103 
    104    certReq->poolp = poolp;
    105    certReq->requestID = inRequestID;
    106 
    107    rv = crmf_encode_unsigned_integer(poolp, &(certReq->certReqId),
    108                                      inRequestID);
    109    if (rv != SECSuccess) {
    110        goto loser;
    111    }
    112 
    113    return certReq;
    114 loser:
    115    if (poolp) {
    116        PORT_FreeArena(poolp, PR_FALSE);
    117    }
    118    return NULL;
    119 }
    120 
    121 SECStatus
    122 CRMF_DestroyCertRequest(CRMFCertRequest *inCertReq)
    123 {
    124    PORT_Assert(inCertReq != NULL);
    125    if (inCertReq != NULL) {
    126        if (inCertReq->certTemplate.extensions) {
    127            PORT_Free(inCertReq->certTemplate.extensions);
    128        }
    129        if (inCertReq->controls) {
    130            /* Right now we don't support EnveloppedData option,
    131             * so we won't go through and delete each occurrence of
    132             * an EnveloppedData in the control.
    133             */
    134            PORT_Free(inCertReq->controls);
    135        }
    136        if (inCertReq->poolp) {
    137            PORT_FreeArena(inCertReq->poolp, PR_TRUE);
    138        }
    139    }
    140    return SECSuccess;
    141 }
    142 
    143 static SECStatus
    144 crmf_template_add_version(PLArenaPool *poolp, SECItem *dest, long version)
    145 {
    146    return (crmf_encode_integer(poolp, dest, version));
    147 }
    148 
    149 static SECStatus
    150 crmf_template_add_serialnumber(PLArenaPool *poolp, SECItem *dest, long serial)
    151 {
    152    return (crmf_encode_integer(poolp, dest, serial));
    153 }
    154 
    155 SECStatus
    156 crmf_template_copy_secalg(PLArenaPool *poolp, SECAlgorithmID **dest,
    157                          SECAlgorithmID *src)
    158 {
    159    SECStatus rv;
    160    void *mark = NULL;
    161    SECAlgorithmID *mySecAlg;
    162 
    163    if (!poolp) {
    164        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    165        return SECFailure;
    166    }
    167 
    168    mark = PORT_ArenaMark(poolp);
    169    *dest = mySecAlg = PORT_ArenaZNew(poolp, SECAlgorithmID);
    170    if (mySecAlg == NULL) {
    171        goto loser;
    172    }
    173    rv = SECOID_CopyAlgorithmID(poolp, mySecAlg, src);
    174    if (rv != SECSuccess) {
    175        goto loser;
    176    }
    177    if (mark) {
    178        PORT_ArenaUnmark(poolp, mark);
    179    }
    180    return SECSuccess;
    181 
    182 loser:
    183    *dest = NULL;
    184    if (mark) {
    185        PORT_ArenaRelease(poolp, mark);
    186    }
    187    return SECFailure;
    188 }
    189 
    190 SECStatus
    191 crmf_copy_cert_name(PLArenaPool *poolp, CERTName **dest,
    192                    CERTName *src)
    193 {
    194    CERTName *newName;
    195    SECStatus rv;
    196    void *mark;
    197 
    198    mark = PORT_ArenaMark(poolp);
    199    *dest = newName = PORT_ArenaZNew(poolp, CERTName);
    200    if (newName == NULL) {
    201        goto loser;
    202    }
    203 
    204    rv = CERT_CopyName(poolp, newName, src);
    205    if (rv != SECSuccess) {
    206        goto loser;
    207    }
    208    PORT_ArenaUnmark(poolp, mark);
    209    return SECSuccess;
    210 loser:
    211    PORT_ArenaRelease(poolp, mark);
    212    *dest = NULL;
    213    return SECFailure;
    214 }
    215 
    216 static SECStatus
    217 crmf_template_add_issuer(PLArenaPool *poolp, CERTName **dest,
    218                         CERTName *issuerName)
    219 {
    220    return crmf_copy_cert_name(poolp, dest, issuerName);
    221 }
    222 
    223 static SECStatus
    224 crmf_template_add_validity(PLArenaPool *poolp, CRMFOptionalValidity **dest,
    225                           CRMFValidityCreationInfo *info)
    226 {
    227    SECStatus rv;
    228    void *mark;
    229    CRMFOptionalValidity *myValidity;
    230 
    231    /*First off, let's make sure at least one of the two fields is present*/
    232    if (!info || (!info->notBefore && !info->notAfter)) {
    233        return SECFailure;
    234    }
    235    mark = PORT_ArenaMark(poolp);
    236    *dest = myValidity = PORT_ArenaZNew(poolp, CRMFOptionalValidity);
    237    if (myValidity == NULL) {
    238        goto loser;
    239    }
    240 
    241    if (info->notBefore) {
    242        rv = DER_EncodeTimeChoice(poolp, &myValidity->notBefore,
    243                                  *info->notBefore);
    244        if (rv != SECSuccess) {
    245            goto loser;
    246        }
    247    }
    248    if (info->notAfter) {
    249        rv = DER_EncodeTimeChoice(poolp, &myValidity->notAfter,
    250                                  *info->notAfter);
    251        if (rv != SECSuccess) {
    252            goto loser;
    253        }
    254    }
    255    PORT_ArenaUnmark(poolp, mark);
    256    return SECSuccess;
    257 loser:
    258    PORT_ArenaRelease(poolp, mark);
    259    *dest = NULL;
    260    return SECFailure;
    261 }
    262 
    263 static SECStatus
    264 crmf_template_add_subject(PLArenaPool *poolp, CERTName **dest,
    265                          CERTName *subject)
    266 {
    267    return crmf_copy_cert_name(poolp, dest, subject);
    268 }
    269 
    270 SECStatus
    271 crmf_template_add_public_key(PLArenaPool *poolp,
    272                             CERTSubjectPublicKeyInfo **dest,
    273                             CERTSubjectPublicKeyInfo *pubKey)
    274 {
    275    CERTSubjectPublicKeyInfo *spki;
    276    SECStatus rv;
    277 
    278    *dest = spki = (poolp == NULL) ? PORT_ZNew(CERTSubjectPublicKeyInfo) : PORT_ArenaZNew(poolp, CERTSubjectPublicKeyInfo);
    279    if (spki == NULL) {
    280        goto loser;
    281    }
    282    rv = SECKEY_CopySubjectPublicKeyInfo(poolp, spki, pubKey);
    283    if (rv != SECSuccess) {
    284        goto loser;
    285    }
    286    return SECSuccess;
    287 loser:
    288    if (poolp == NULL && spki != NULL) {
    289        SECKEY_DestroySubjectPublicKeyInfo(spki);
    290    }
    291    *dest = NULL;
    292    return SECFailure;
    293 }
    294 
    295 static SECStatus
    296 crmf_copy_bitstring(PLArenaPool *poolp, SECItem *dest, const SECItem *src)
    297 {
    298    SECStatus rv;
    299    SECItem byteSrc;
    300 
    301    byteSrc = *src;
    302    byteSrc.len = CRMF_BITS_TO_BYTES(byteSrc.len);
    303    rv = crmf_copy_secitem(poolp, dest, &byteSrc);
    304    dest->len = src->len;
    305    return rv;
    306 }
    307 
    308 static SECStatus
    309 crmf_template_add_issuer_uid(PLArenaPool *poolp, SECItem *dest,
    310                             const SECItem *issuerUID)
    311 {
    312    return crmf_copy_bitstring(poolp, dest, issuerUID);
    313 }
    314 
    315 static SECStatus
    316 crmf_template_add_subject_uid(PLArenaPool *poolp, SECItem *dest,
    317                              const SECItem *subjectUID)
    318 {
    319    return crmf_copy_bitstring(poolp, dest, subjectUID);
    320 }
    321 
    322 static void
    323 crmf_zeroize_new_extensions(CRMFCertExtension **extensions,
    324                            int numToZeroize)
    325 {
    326    PORT_Memset((void *)extensions, 0, sizeof(CERTCertExtension *) * numToZeroize);
    327 }
    328 
    329 /*
    330 * The strategy for adding templates will differ from all the other
    331 * attributes in the template.  First, we want to allow the client
    332 * of this API to set extensions more than just once.  So we will
    333 * need the ability grow the array of extensions.  Since arenas don't
    334 * give us the realloc function, we'll use the generic PORT_* functions
    335 * to allocate the array of pointers *ONLY*.  Then we will allocate each
    336 * individual extension from the arena that comes along with the certReq
    337 * structure that owns this template.
    338 */
    339 static SECStatus
    340 crmf_template_add_extensions(PLArenaPool *poolp, CRMFCertTemplate *inTemplate,
    341                             CRMFCertExtCreationInfo *extensions)
    342 {
    343    void *mark;
    344    int newSize, oldSize, i;
    345    SECStatus rv;
    346    CRMFCertExtension **extArray;
    347    CRMFCertExtension *newExt, *currExt;
    348 
    349    mark = PORT_ArenaMark(poolp);
    350    if (inTemplate->extensions == NULL) {
    351        newSize = extensions->numExtensions;
    352        extArray = PORT_ZNewArray(CRMFCertExtension *, newSize + 1);
    353    } else {
    354        newSize = inTemplate->numExtensions + extensions->numExtensions;
    355        extArray = PORT_Realloc(inTemplate->extensions,
    356                                sizeof(CRMFCertExtension *) * (newSize + 1));
    357    }
    358    if (extArray == NULL) {
    359        goto loser;
    360    }
    361    oldSize = inTemplate->numExtensions;
    362    inTemplate->extensions = extArray;
    363    inTemplate->numExtensions = newSize;
    364    for (i = oldSize; i < newSize; i++) {
    365        newExt = PORT_ArenaZNew(poolp, CRMFCertExtension);
    366        if (newExt == NULL) {
    367            goto loser2;
    368        }
    369        currExt = extensions->extensions[i - oldSize];
    370        rv = crmf_copy_secitem(poolp, &(newExt->id), &(currExt->id));
    371        if (rv != SECSuccess) {
    372            goto loser2;
    373        }
    374        rv = crmf_copy_secitem(poolp, &(newExt->critical),
    375                               &(currExt->critical));
    376        if (rv != SECSuccess) {
    377            goto loser2;
    378        }
    379        rv = crmf_copy_secitem(poolp, &(newExt->value), &(currExt->value));
    380        if (rv != SECSuccess) {
    381            goto loser2;
    382        }
    383        extArray[i] = newExt;
    384    }
    385    extArray[newSize] = NULL;
    386    PORT_ArenaUnmark(poolp, mark);
    387    return SECSuccess;
    388 loser2:
    389    crmf_zeroize_new_extensions(&(inTemplate->extensions[oldSize]),
    390                                extensions->numExtensions);
    391    inTemplate->numExtensions = oldSize;
    392 loser:
    393    PORT_ArenaRelease(poolp, mark);
    394    return SECFailure;
    395 }
    396 
    397 SECStatus
    398 CRMF_CertRequestSetTemplateField(CRMFCertRequest *inCertReq,
    399                                 CRMFCertTemplateField inTemplateField,
    400                                 void *data)
    401 {
    402    CRMFCertTemplate *certTemplate;
    403    PLArenaPool *poolp;
    404    SECStatus rv = SECFailure;
    405    void *mark;
    406 
    407    if (inCertReq == NULL) {
    408        return SECFailure;
    409    }
    410 
    411    certTemplate = &(inCertReq->certTemplate);
    412 
    413    poolp = inCertReq->poolp;
    414    mark = PORT_ArenaMark(poolp);
    415    switch (inTemplateField) {
    416        case crmfVersion:
    417            rv = crmf_template_add_version(poolp, &(certTemplate->version),
    418                                           *(long *)data);
    419            break;
    420        case crmfSerialNumber:
    421            rv = crmf_template_add_serialnumber(poolp,
    422                                                &(certTemplate->serialNumber),
    423                                                *(long *)data);
    424            break;
    425        case crmfSigningAlg:
    426            rv = crmf_template_copy_secalg(poolp, &(certTemplate->signingAlg),
    427                                           (SECAlgorithmID *)data);
    428            break;
    429        case crmfIssuer:
    430            rv = crmf_template_add_issuer(poolp, &(certTemplate->issuer),
    431                                          (CERTName *)data);
    432            break;
    433        case crmfValidity:
    434            rv = crmf_template_add_validity(poolp, &(certTemplate->validity),
    435                                            (CRMFValidityCreationInfo *)data);
    436            break;
    437        case crmfSubject:
    438            rv = crmf_template_add_subject(poolp, &(certTemplate->subject),
    439                                           (CERTName *)data);
    440            break;
    441        case crmfPublicKey:
    442            rv = crmf_template_add_public_key(poolp, &(certTemplate->publicKey),
    443                                              (CERTSubjectPublicKeyInfo *)data);
    444            break;
    445        case crmfIssuerUID:
    446            rv = crmf_template_add_issuer_uid(poolp, &(certTemplate->issuerUID),
    447                                              (SECItem *)data);
    448            break;
    449        case crmfSubjectUID:
    450            rv = crmf_template_add_subject_uid(poolp, &(certTemplate->subjectUID),
    451                                               (SECItem *)data);
    452            break;
    453        case crmfExtension:
    454            rv = crmf_template_add_extensions(poolp, certTemplate,
    455                                              (CRMFCertExtCreationInfo *)data);
    456            break;
    457    }
    458    if (rv != SECSuccess) {
    459        PORT_ArenaRelease(poolp, mark);
    460    } else {
    461        PORT_ArenaUnmark(poolp, mark);
    462    }
    463    return rv;
    464 }
    465 
    466 SECStatus
    467 CRMF_CertReqMsgSetCertRequest(CRMFCertReqMsg *inCertReqMsg,
    468                              CRMFCertRequest *inCertReq)
    469 {
    470    PORT_Assert(inCertReqMsg != NULL && inCertReq != NULL);
    471    if (inCertReqMsg == NULL || inCertReq == NULL) {
    472        return SECFailure;
    473    }
    474    inCertReqMsg->certReq = crmf_copy_cert_request(inCertReqMsg->poolp,
    475                                                   inCertReq);
    476    return (inCertReqMsg->certReq == NULL) ? SECFailure : SECSuccess;
    477 }
    478 
    479 CRMFCertReqMsg *
    480 CRMF_CreateCertReqMsg(void)
    481 {
    482    PLArenaPool *poolp;
    483    CRMFCertReqMsg *reqMsg;
    484 
    485    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
    486    if (poolp == NULL) {
    487        goto loser;
    488    }
    489    reqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg);
    490    if (reqMsg == NULL) {
    491        goto loser;
    492    }
    493    reqMsg->poolp = poolp;
    494    return reqMsg;
    495 
    496 loser:
    497    if (poolp) {
    498        PORT_FreeArena(poolp, PR_FALSE);
    499    }
    500    return NULL;
    501 }
    502 
    503 SECStatus
    504 CRMF_DestroyCertReqMsg(CRMFCertReqMsg *inCertReqMsg)
    505 {
    506    PORT_Assert(inCertReqMsg != NULL && inCertReqMsg->poolp != NULL);
    507    if (!inCertReqMsg->isDecoded) {
    508        if (inCertReqMsg->certReq->certTemplate.extensions != NULL) {
    509            PORT_Free(inCertReqMsg->certReq->certTemplate.extensions);
    510        }
    511        if (inCertReqMsg->certReq->controls != NULL) {
    512            PORT_Free(inCertReqMsg->certReq->controls);
    513        }
    514    }
    515    PORT_FreeArena(inCertReqMsg->poolp, PR_TRUE);
    516    return SECSuccess;
    517 }
    518 
    519 CRMFCertExtension *
    520 crmf_create_cert_extension(PLArenaPool *poolp,
    521                           SECOidTag id,
    522                           PRBool isCritical,
    523                           SECItem *data)
    524 {
    525    CRMFCertExtension *newExt;
    526    SECOidData *oidData;
    527    SECStatus rv;
    528 
    529    newExt = (poolp == NULL) ? PORT_ZNew(CRMFCertExtension) : PORT_ArenaZNew(poolp, CRMFCertExtension);
    530    if (newExt == NULL) {
    531        goto loser;
    532    }
    533    oidData = SECOID_FindOIDByTag(id);
    534    if (oidData == NULL ||
    535        oidData->supportedExtension != SUPPORTED_CERT_EXTENSION) {
    536        goto loser;
    537    }
    538 
    539    rv = SECITEM_CopyItem(poolp, &(newExt->id), &(oidData->oid));
    540    if (rv != SECSuccess) {
    541        goto loser;
    542    }
    543 
    544    rv = SECITEM_CopyItem(poolp, &(newExt->value), data);
    545    if (rv != SECSuccess) {
    546        goto loser;
    547    }
    548 
    549    if (isCritical) {
    550        newExt->critical.data = (poolp == NULL) ? PORT_New(unsigned char)
    551                                                : PORT_ArenaNew(poolp, unsigned char);
    552        if (newExt->critical.data == NULL) {
    553            goto loser;
    554        }
    555        newExt->critical.data[0] = hexTrue;
    556        newExt->critical.len = 1;
    557    }
    558    return newExt;
    559 loser:
    560    if (newExt != NULL && poolp == NULL) {
    561        CRMF_DestroyCertExtension(newExt);
    562    }
    563    return NULL;
    564 }
    565 
    566 CRMFCertExtension *
    567 CRMF_CreateCertExtension(SECOidTag id,
    568                         PRBool isCritical,
    569                         SECItem *data)
    570 {
    571    return crmf_create_cert_extension(NULL, id, isCritical, data);
    572 }
    573 
    574 static SECStatus
    575 crmf_destroy_cert_extension(CRMFCertExtension *inExtension, PRBool freeit)
    576 {
    577    if (inExtension != NULL) {
    578        SECITEM_FreeItem(&(inExtension->id), PR_FALSE);
    579        SECITEM_FreeItem(&(inExtension->value), PR_FALSE);
    580        SECITEM_FreeItem(&(inExtension->critical), PR_FALSE);
    581        if (freeit) {
    582            PORT_Free(inExtension);
    583        }
    584    }
    585    return SECSuccess;
    586 }
    587 
    588 SECStatus
    589 CRMF_DestroyCertExtension(CRMFCertExtension *inExtension)
    590 {
    591    return crmf_destroy_cert_extension(inExtension, PR_TRUE);
    592 }
    593 
    594 SECStatus
    595 CRMF_DestroyCertReqMessages(CRMFCertReqMessages *inCertReqMsgs)
    596 {
    597    PORT_Assert(inCertReqMsgs != NULL);
    598    if (inCertReqMsgs != NULL) {
    599        PORT_FreeArena(inCertReqMsgs->poolp, PR_TRUE);
    600    }
    601    return SECSuccess;
    602 }
    603 
    604 static PRBool
    605 crmf_item_has_data(SECItem *item)
    606 {
    607    if (item != NULL && item->data != NULL) {
    608        return PR_TRUE;
    609    }
    610    return PR_FALSE;
    611 }
    612 
    613 PRBool
    614 CRMF_CertRequestIsFieldPresent(CRMFCertRequest *inCertReq,
    615                               CRMFCertTemplateField inTemplateField)
    616 {
    617    PRBool retVal;
    618    CRMFCertTemplate *certTemplate;
    619 
    620    PORT_Assert(inCertReq != NULL);
    621    if (inCertReq == NULL) {
    622        /* This is probably some kind of error, but this is
    623         * the safest return value for this function.
    624         */
    625        return PR_FALSE;
    626    }
    627    certTemplate = &inCertReq->certTemplate;
    628    switch (inTemplateField) {
    629        case crmfVersion:
    630            retVal = crmf_item_has_data(&certTemplate->version);
    631            break;
    632        case crmfSerialNumber:
    633            retVal = crmf_item_has_data(&certTemplate->serialNumber);
    634            break;
    635        case crmfSigningAlg:
    636            retVal = IS_NOT_NULL(certTemplate->signingAlg);
    637            break;
    638        case crmfIssuer:
    639            retVal = IS_NOT_NULL(certTemplate->issuer);
    640            break;
    641        case crmfValidity:
    642            retVal = IS_NOT_NULL(certTemplate->validity);
    643            break;
    644        case crmfSubject:
    645            retVal = IS_NOT_NULL(certTemplate->subject);
    646            break;
    647        case crmfPublicKey:
    648            retVal = IS_NOT_NULL(certTemplate->publicKey);
    649            break;
    650        case crmfIssuerUID:
    651            retVal = crmf_item_has_data(&certTemplate->issuerUID);
    652            break;
    653        case crmfSubjectUID:
    654            retVal = crmf_item_has_data(&certTemplate->subjectUID);
    655            break;
    656        case crmfExtension:
    657            retVal = IS_NOT_NULL(certTemplate->extensions);
    658            break;
    659        default:
    660            retVal = PR_FALSE;
    661    }
    662    return retVal;
    663 }