tor-browser

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

servget.c (27002B)


      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 "cmmf.h"
      7 #include "cmmfi.h"
      8 #include "secitem.h"
      9 #include "keyhi.h"
     10 #include "secder.h"
     11 
     12 CRMFEncryptedKeyChoice
     13 CRMF_EncryptedKeyGetChoice(CRMFEncryptedKey *inEncrKey)
     14 {
     15    PORT_Assert(inEncrKey != NULL);
     16    if (inEncrKey == NULL) {
     17        return crmfNoEncryptedKeyChoice;
     18    }
     19    return inEncrKey->encKeyChoice;
     20 }
     21 
     22 CRMFEncryptedValue *
     23 CRMF_EncryptedKeyGetEncryptedValue(CRMFEncryptedKey *inEncrKey)
     24 {
     25    CRMFEncryptedValue *newEncrValue = NULL;
     26    SECStatus rv;
     27 
     28    PORT_Assert(inEncrKey != NULL);
     29    if (inEncrKey == NULL ||
     30        CRMF_EncryptedKeyGetChoice(inEncrKey) != crmfEncryptedValueChoice) {
     31        goto loser;
     32    }
     33    newEncrValue = PORT_ZNew(CRMFEncryptedValue);
     34    if (newEncrValue == NULL) {
     35        goto loser;
     36    }
     37    rv = crmf_copy_encryptedvalue(NULL, &inEncrKey->value.encryptedValue,
     38                                  newEncrValue);
     39    if (rv != SECSuccess) {
     40        goto loser;
     41    }
     42    return newEncrValue;
     43 loser:
     44    if (newEncrValue != NULL) {
     45        CRMF_DestroyEncryptedValue(newEncrValue);
     46    }
     47    return NULL;
     48 }
     49 
     50 static SECItem *
     51 crmf_get_encvalue_bitstring(SECItem *srcItem)
     52 {
     53    SECItem *newItem = NULL;
     54    SECStatus rv;
     55 
     56    if (srcItem->data == NULL) {
     57        return NULL;
     58    }
     59    newItem = PORT_ZNew(SECItem);
     60    if (newItem == NULL) {
     61        goto loser;
     62    }
     63    rv = crmf_make_bitstring_copy(NULL, newItem, srcItem);
     64    if (rv != SECSuccess) {
     65        goto loser;
     66    }
     67    return newItem;
     68 loser:
     69    if (newItem != NULL) {
     70        SECITEM_FreeItem(newItem, PR_TRUE);
     71    }
     72    return NULL;
     73 }
     74 
     75 SECItem *
     76 CRMF_EncryptedValueGetEncSymmKey(CRMFEncryptedValue *inEncValue)
     77 {
     78    if (inEncValue == NULL) {
     79        return NULL;
     80    }
     81    return crmf_get_encvalue_bitstring(&inEncValue->encSymmKey);
     82 }
     83 
     84 SECItem *
     85 CRMF_EncryptedValueGetEncValue(CRMFEncryptedValue *inEncrValue)
     86 {
     87    if (inEncrValue == NULL || inEncrValue->encValue.data == NULL) {
     88        return NULL;
     89    }
     90    return crmf_get_encvalue_bitstring(&inEncrValue->encValue);
     91 }
     92 
     93 static SECAlgorithmID *
     94 crmf_get_encvalue_algid(SECAlgorithmID *srcAlg)
     95 {
     96    SECStatus rv;
     97    SECAlgorithmID *newAlgID;
     98 
     99    if (srcAlg == NULL) {
    100        return NULL;
    101    }
    102    rv = crmf_copy_encryptedvalue_secalg(NULL, srcAlg, &newAlgID);
    103    if (rv != SECSuccess) {
    104        return NULL;
    105    }
    106    return newAlgID;
    107 }
    108 
    109 SECAlgorithmID *
    110 CRMF_EncryptedValueGetIntendedAlg(CRMFEncryptedValue *inEncValue)
    111 {
    112    if (inEncValue == NULL) {
    113        return NULL;
    114    }
    115    return crmf_get_encvalue_algid(inEncValue->intendedAlg);
    116 }
    117 
    118 SECAlgorithmID *
    119 CRMF_EncryptedValueGetKeyAlg(CRMFEncryptedValue *inEncValue)
    120 {
    121    if (inEncValue == NULL) {
    122        return NULL;
    123    }
    124    return crmf_get_encvalue_algid(inEncValue->keyAlg);
    125 }
    126 
    127 SECAlgorithmID *
    128 CRMF_EncryptedValueGetSymmAlg(CRMFEncryptedValue *inEncValue)
    129 {
    130    if (inEncValue == NULL) {
    131        return NULL;
    132    }
    133    return crmf_get_encvalue_algid(inEncValue->symmAlg);
    134 }
    135 
    136 SECItem *
    137 CRMF_EncryptedValueGetValueHint(CRMFEncryptedValue *inEncValue)
    138 {
    139    if (inEncValue == NULL || inEncValue->valueHint.data == NULL) {
    140        return NULL;
    141    }
    142    return SECITEM_DupItem(&inEncValue->valueHint);
    143 }
    144 
    145 SECStatus
    146 CRMF_PKIArchiveOptionsGetArchiveRemGenPrivKey(CRMFPKIArchiveOptions *inOpt,
    147                                              PRBool *destVal)
    148 {
    149    if (inOpt == NULL || destVal == NULL ||
    150        CRMF_PKIArchiveOptionsGetOptionType(inOpt) != crmfArchiveRemGenPrivKey) {
    151        return SECFailure;
    152    }
    153    *destVal = (inOpt->option.archiveRemGenPrivKey.data[0] == hexFalse)
    154                   ? PR_FALSE
    155                   : PR_TRUE;
    156    return SECSuccess;
    157 }
    158 
    159 CRMFEncryptedKey *
    160 CRMF_PKIArchiveOptionsGetEncryptedPrivKey(CRMFPKIArchiveOptions *inOpts)
    161 {
    162    CRMFEncryptedKey *newEncrKey = NULL;
    163    SECStatus rv;
    164 
    165    PORT_Assert(inOpts != NULL);
    166    if (inOpts == NULL ||
    167        CRMF_PKIArchiveOptionsGetOptionType(inOpts) != crmfEncryptedPrivateKey) {
    168        return NULL;
    169    }
    170    newEncrKey = PORT_ZNew(CRMFEncryptedKey);
    171    if (newEncrKey == NULL) {
    172        goto loser;
    173    }
    174    rv = crmf_copy_encryptedkey(NULL, &inOpts->option.encryptedKey,
    175                                newEncrKey);
    176    if (rv != SECSuccess) {
    177        goto loser;
    178    }
    179    return newEncrKey;
    180 loser:
    181    if (newEncrKey != NULL) {
    182        CRMF_DestroyEncryptedKey(newEncrKey);
    183    }
    184    return NULL;
    185 }
    186 
    187 SECItem *
    188 CRMF_PKIArchiveOptionsGetKeyGenParameters(CRMFPKIArchiveOptions *inOptions)
    189 {
    190    if (inOptions == NULL ||
    191        CRMF_PKIArchiveOptionsGetOptionType(inOptions) != crmfKeyGenParameters ||
    192        inOptions->option.keyGenParameters.data == NULL) {
    193        return NULL;
    194    }
    195    return SECITEM_DupItem(&inOptions->option.keyGenParameters);
    196 }
    197 
    198 CRMFPKIArchiveOptionsType
    199 CRMF_PKIArchiveOptionsGetOptionType(CRMFPKIArchiveOptions *inOptions)
    200 {
    201    PORT_Assert(inOptions != NULL);
    202    if (inOptions == NULL) {
    203        return crmfNoArchiveOptions;
    204    }
    205    return inOptions->archOption;
    206 }
    207 
    208 static SECStatus
    209 crmf_extract_long_from_item(SECItem *intItem, long *destLong)
    210 {
    211    *destLong = DER_GetInteger(intItem);
    212    return (*destLong == -1) ? SECFailure : SECSuccess;
    213 }
    214 
    215 SECStatus
    216 CRMF_POPOPrivGetKeySubseqMess(CRMFPOPOPrivKey *inKey,
    217                              CRMFSubseqMessOptions *destOpt)
    218 {
    219    long value;
    220    SECStatus rv;
    221 
    222    PORT_Assert(inKey != NULL);
    223    if (inKey == NULL ||
    224        inKey->messageChoice != crmfSubsequentMessage) {
    225        return SECFailure;
    226    }
    227    rv = crmf_extract_long_from_item(&inKey->message.subsequentMessage, &value);
    228    if (rv != SECSuccess) {
    229        return SECFailure;
    230    }
    231    switch (value) {
    232        case 0:
    233            *destOpt = crmfEncrCert;
    234            break;
    235        case 1:
    236            *destOpt = crmfChallengeResp;
    237            break;
    238        default:
    239            rv = SECFailure;
    240    }
    241    if (rv != SECSuccess) {
    242        return rv;
    243    }
    244    return SECSuccess;
    245 }
    246 
    247 CRMFPOPOPrivKeyChoice
    248 CRMF_POPOPrivKeyGetChoice(CRMFPOPOPrivKey *inPrivKey)
    249 {
    250    PORT_Assert(inPrivKey != NULL);
    251    if (inPrivKey != NULL) {
    252        return inPrivKey->messageChoice;
    253    }
    254    return crmfNoMessage;
    255 }
    256 
    257 SECStatus
    258 CRMF_POPOPrivKeyGetDHMAC(CRMFPOPOPrivKey *inKey, SECItem *destMAC)
    259 {
    260    PORT_Assert(inKey != NULL);
    261    if (inKey == NULL || inKey->message.dhMAC.data == NULL) {
    262        return SECFailure;
    263    }
    264    return crmf_make_bitstring_copy(NULL, destMAC, &inKey->message.dhMAC);
    265 }
    266 
    267 SECStatus
    268 CRMF_POPOPrivKeyGetThisMessage(CRMFPOPOPrivKey *inKey,
    269                               SECItem *destString)
    270 {
    271    PORT_Assert(inKey != NULL);
    272    if (inKey == NULL ||
    273        inKey->messageChoice != crmfThisMessage) {
    274        return SECFailure;
    275    }
    276 
    277    return crmf_make_bitstring_copy(NULL, destString,
    278                                    &inKey->message.thisMessage);
    279 }
    280 
    281 SECAlgorithmID *
    282 CRMF_POPOSigningKeyGetAlgID(CRMFPOPOSigningKey *inSignKey)
    283 {
    284    SECAlgorithmID *newAlgId = NULL;
    285    SECStatus rv;
    286 
    287    PORT_Assert(inSignKey != NULL);
    288    if (inSignKey == NULL) {
    289        return NULL;
    290    }
    291    newAlgId = PORT_ZNew(SECAlgorithmID);
    292    if (newAlgId == NULL) {
    293        goto loser;
    294    }
    295    rv = SECOID_CopyAlgorithmID(NULL, newAlgId,
    296                                inSignKey->algorithmIdentifier);
    297    if (rv != SECSuccess) {
    298        goto loser;
    299    }
    300    return newAlgId;
    301 
    302 loser:
    303    if (newAlgId != NULL) {
    304        SECOID_DestroyAlgorithmID(newAlgId, PR_TRUE);
    305    }
    306    return NULL;
    307 }
    308 
    309 SECItem *
    310 CRMF_POPOSigningKeyGetInput(CRMFPOPOSigningKey *inSignKey)
    311 {
    312    PORT_Assert(inSignKey != NULL);
    313    if (inSignKey == NULL || inSignKey->derInput.data == NULL) {
    314        return NULL;
    315    }
    316    return SECITEM_DupItem(&inSignKey->derInput);
    317 }
    318 
    319 SECItem *
    320 CRMF_POPOSigningKeyGetSignature(CRMFPOPOSigningKey *inSignKey)
    321 {
    322    SECItem *newSig = NULL;
    323    SECStatus rv;
    324 
    325    PORT_Assert(inSignKey != NULL);
    326    if (inSignKey == NULL) {
    327        return NULL;
    328    }
    329    newSig = PORT_ZNew(SECItem);
    330    if (newSig == NULL) {
    331        goto loser;
    332    }
    333    rv = crmf_make_bitstring_copy(NULL, newSig, &inSignKey->signature);
    334    if (rv != SECSuccess) {
    335        goto loser;
    336    }
    337    return newSig;
    338 loser:
    339    if (newSig != NULL) {
    340        SECITEM_FreeItem(newSig, PR_TRUE);
    341    }
    342    return NULL;
    343 }
    344 
    345 static SECStatus
    346 crmf_copy_poposigningkey(PLArenaPool *poolp,
    347                         CRMFPOPOSigningKey *inPopoSignKey,
    348                         CRMFPOPOSigningKey *destPopoSignKey)
    349 {
    350    SECStatus rv;
    351 
    352    /* We don't support use of the POPOSigningKeyInput, so we'll only
    353     * store away the DER encoding.
    354     */
    355    if (inPopoSignKey->derInput.data != NULL) {
    356        rv = SECITEM_CopyItem(poolp, &destPopoSignKey->derInput,
    357                              &inPopoSignKey->derInput);
    358        if (rv != SECSuccess) {
    359            goto loser;
    360        }
    361    }
    362    destPopoSignKey->algorithmIdentifier = (poolp == NULL) ? PORT_ZNew(SECAlgorithmID)
    363                                                           : PORT_ArenaZNew(poolp, SECAlgorithmID);
    364 
    365    if (destPopoSignKey->algorithmIdentifier == NULL) {
    366        goto loser;
    367    }
    368    rv = SECOID_CopyAlgorithmID(poolp, destPopoSignKey->algorithmIdentifier,
    369                                inPopoSignKey->algorithmIdentifier);
    370    if (rv != SECSuccess) {
    371        goto loser;
    372    }
    373 
    374    rv = crmf_make_bitstring_copy(poolp, &destPopoSignKey->signature,
    375                                  &inPopoSignKey->signature);
    376    if (rv != SECSuccess) {
    377        goto loser;
    378    }
    379    return SECSuccess;
    380 loser:
    381    if (poolp == NULL) {
    382        CRMF_DestroyPOPOSigningKey(destPopoSignKey);
    383    }
    384    return SECFailure;
    385 }
    386 
    387 static SECStatus
    388 crmf_copy_popoprivkey(PLArenaPool *poolp,
    389                      CRMFPOPOPrivKey *srcPrivKey,
    390                      CRMFPOPOPrivKey *destPrivKey)
    391 {
    392    SECStatus rv;
    393 
    394    destPrivKey->messageChoice = srcPrivKey->messageChoice;
    395    switch (destPrivKey->messageChoice) {
    396        case crmfThisMessage:
    397        case crmfDHMAC:
    398            /* I've got a union, so taking the address of one, will also give
    399             * me a pointer to the other (eg, message.dhMAC)
    400             */
    401            rv = crmf_make_bitstring_copy(poolp, &destPrivKey->message.thisMessage,
    402                                          &srcPrivKey->message.thisMessage);
    403            break;
    404        case crmfSubsequentMessage:
    405            rv = SECITEM_CopyItem(poolp, &destPrivKey->message.subsequentMessage,
    406                                  &srcPrivKey->message.subsequentMessage);
    407            break;
    408        default:
    409            rv = SECFailure;
    410    }
    411 
    412    if (rv != SECSuccess && poolp == NULL) {
    413        CRMF_DestroyPOPOPrivKey(destPrivKey);
    414    }
    415    return rv;
    416 }
    417 
    418 static CRMFProofOfPossession *
    419 crmf_copy_pop(PLArenaPool *poolp, CRMFProofOfPossession *srcPOP)
    420 {
    421    CRMFProofOfPossession *newPOP;
    422    SECStatus rv;
    423 
    424    /*
    425     * Proof Of Possession structures are always part of the Request
    426     * message, so there will always be an arena for allocating memory.
    427     */
    428    if (poolp == NULL) {
    429        return NULL;
    430    }
    431    newPOP = PORT_ArenaZNew(poolp, CRMFProofOfPossession);
    432    if (newPOP == NULL) {
    433        return NULL;
    434    }
    435    switch (srcPOP->popUsed) {
    436        case crmfRAVerified:
    437            newPOP->popChoice.raVerified.data = NULL;
    438            newPOP->popChoice.raVerified.len = 0;
    439            break;
    440        case crmfSignature:
    441            rv = crmf_copy_poposigningkey(poolp, &srcPOP->popChoice.signature,
    442                                          &newPOP->popChoice.signature);
    443            if (rv != SECSuccess) {
    444                goto loser;
    445            }
    446            break;
    447        case crmfKeyEncipherment:
    448        case crmfKeyAgreement:
    449            /* We've got a union, so a pointer to one, is a pointer to the
    450             * other one.
    451             */
    452            rv = crmf_copy_popoprivkey(poolp, &srcPOP->popChoice.keyEncipherment,
    453                                       &newPOP->popChoice.keyEncipherment);
    454            if (rv != SECSuccess) {
    455                goto loser;
    456            }
    457            break;
    458        default:
    459            goto loser;
    460    }
    461    newPOP->popUsed = srcPOP->popUsed;
    462    return newPOP;
    463 
    464 loser:
    465    return NULL;
    466 }
    467 
    468 static CRMFCertReqMsg *
    469 crmf_copy_cert_req_msg(CRMFCertReqMsg *srcReqMsg)
    470 {
    471    CRMFCertReqMsg *newReqMsg;
    472    PLArenaPool *poolp;
    473 
    474    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
    475    if (poolp == NULL) {
    476        return NULL;
    477    }
    478    newReqMsg = PORT_ArenaZNew(poolp, CRMFCertReqMsg);
    479    if (newReqMsg == NULL) {
    480        PORT_FreeArena(poolp, PR_TRUE);
    481        return NULL;
    482    }
    483 
    484    newReqMsg->poolp = poolp;
    485    newReqMsg->certReq = crmf_copy_cert_request(poolp, srcReqMsg->certReq);
    486    if (newReqMsg->certReq == NULL) {
    487        goto loser;
    488    }
    489    newReqMsg->pop = crmf_copy_pop(poolp, srcReqMsg->pop);
    490    if (newReqMsg->pop == NULL) {
    491        goto loser;
    492    }
    493    /* None of my set/get routines operate on the regInfo field, so
    494     * for now, that won't get copied over.
    495     */
    496    return newReqMsg;
    497 
    498 loser:
    499    CRMF_DestroyCertReqMsg(newReqMsg);
    500    return NULL;
    501 }
    502 
    503 CRMFCertReqMsg *
    504 CRMF_CertReqMessagesGetCertReqMsgAtIndex(CRMFCertReqMessages *inReqMsgs,
    505                                         int index)
    506 {
    507    int numMsgs;
    508 
    509    PORT_Assert(inReqMsgs != NULL && index >= 0);
    510    if (inReqMsgs == NULL) {
    511        return NULL;
    512    }
    513    numMsgs = CRMF_CertReqMessagesGetNumMessages(inReqMsgs);
    514    if (index < 0 || index >= numMsgs) {
    515        return NULL;
    516    }
    517    return crmf_copy_cert_req_msg(inReqMsgs->messages[index]);
    518 }
    519 
    520 int
    521 CRMF_CertReqMessagesGetNumMessages(CRMFCertReqMessages *inCertReqMsgs)
    522 {
    523    int numMessages = 0;
    524 
    525    PORT_Assert(inCertReqMsgs != NULL);
    526    if (inCertReqMsgs == NULL) {
    527        return 0;
    528    }
    529    while (inCertReqMsgs->messages[numMessages] != NULL) {
    530        numMessages++;
    531    }
    532    return numMessages;
    533 }
    534 
    535 CRMFCertRequest *
    536 CRMF_CertReqMsgGetCertRequest(CRMFCertReqMsg *inCertReqMsg)
    537 {
    538    PLArenaPool *poolp = NULL;
    539    CRMFCertRequest *newCertReq = NULL;
    540 
    541    PORT_Assert(inCertReqMsg != NULL);
    542 
    543    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
    544    if (poolp == NULL) {
    545        goto loser;
    546    }
    547    newCertReq = crmf_copy_cert_request(poolp, inCertReqMsg->certReq);
    548    if (newCertReq == NULL) {
    549        goto loser;
    550    }
    551    newCertReq->poolp = poolp;
    552    return newCertReq;
    553 loser:
    554    if (poolp != NULL) {
    555        PORT_FreeArena(poolp, PR_FALSE);
    556    }
    557    return NULL;
    558 }
    559 
    560 SECStatus
    561 CRMF_CertReqMsgGetID(CRMFCertReqMsg *inCertReqMsg, long *destID)
    562 {
    563    PORT_Assert(inCertReqMsg != NULL && destID != NULL);
    564    if (inCertReqMsg == NULL || inCertReqMsg->certReq == NULL) {
    565        return SECFailure;
    566    }
    567    return crmf_extract_long_from_item(&inCertReqMsg->certReq->certReqId,
    568                                       destID);
    569 }
    570 
    571 SECStatus
    572 CRMF_CertReqMsgGetPOPKeyAgreement(CRMFCertReqMsg *inCertReqMsg,
    573                                  CRMFPOPOPrivKey **destKey)
    574 {
    575    PORT_Assert(inCertReqMsg != NULL && destKey != NULL);
    576    if (inCertReqMsg == NULL || destKey == NULL ||
    577        CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfKeyAgreement) {
    578        return SECFailure;
    579    }
    580    *destKey = PORT_ZNew(CRMFPOPOPrivKey);
    581    if (*destKey == NULL) {
    582        return SECFailure;
    583    }
    584    return crmf_copy_popoprivkey(NULL,
    585                                 &inCertReqMsg->pop->popChoice.keyAgreement,
    586                                 *destKey);
    587 }
    588 
    589 SECStatus
    590 CRMF_CertReqMsgGetPOPKeyEncipherment(CRMFCertReqMsg *inCertReqMsg,
    591                                     CRMFPOPOPrivKey **destKey)
    592 {
    593    PORT_Assert(inCertReqMsg != NULL && destKey != NULL);
    594    if (inCertReqMsg == NULL || destKey == NULL ||
    595        CRMF_CertReqMsgGetPOPType(inCertReqMsg) != crmfKeyEncipherment) {
    596        return SECFailure;
    597    }
    598    *destKey = PORT_ZNew(CRMFPOPOPrivKey);
    599    if (*destKey == NULL) {
    600        return SECFailure;
    601    }
    602    return crmf_copy_popoprivkey(NULL,
    603                                 &inCertReqMsg->pop->popChoice.keyEncipherment,
    604                                 *destKey);
    605 }
    606 
    607 SECStatus
    608 CRMF_CertReqMsgGetPOPOSigningKey(CRMFCertReqMsg *inCertReqMsg,
    609                                 CRMFPOPOSigningKey **destKey)
    610 {
    611    CRMFProofOfPossession *pop;
    612    PORT_Assert(inCertReqMsg != NULL);
    613    if (inCertReqMsg == NULL) {
    614        return SECFailure;
    615    }
    616    pop = inCertReqMsg->pop;
    617    ;
    618    if (pop->popUsed != crmfSignature) {
    619        return SECFailure;
    620    }
    621    *destKey = PORT_ZNew(CRMFPOPOSigningKey);
    622    if (*destKey == NULL) {
    623        return SECFailure;
    624    }
    625    return crmf_copy_poposigningkey(NULL, &pop->popChoice.signature, *destKey);
    626 }
    627 
    628 static SECStatus
    629 crmf_copy_name(CERTName *destName, CERTName *srcName)
    630 {
    631    PLArenaPool *poolp = NULL;
    632    SECStatus rv;
    633 
    634    if (destName->arena != NULL) {
    635        poolp = destName->arena;
    636    } else {
    637        poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
    638    }
    639    if (poolp == NULL) {
    640        return SECFailure;
    641    }
    642    /* Need to do this so that CERT_CopyName doesn't free out
    643     * the arena from underneath us.
    644     */
    645    destName->arena = NULL;
    646    rv = CERT_CopyName(poolp, destName, srcName);
    647    destName->arena = poolp;
    648    return rv;
    649 }
    650 
    651 SECStatus
    652 CRMF_CertRequestGetCertTemplateIssuer(CRMFCertRequest *inCertReq,
    653                                      CERTName *destIssuer)
    654 {
    655    PORT_Assert(inCertReq != NULL);
    656    if (inCertReq == NULL) {
    657        return SECFailure;
    658    }
    659    if (CRMF_DoesRequestHaveField(inCertReq, crmfIssuer)) {
    660        return crmf_copy_name(destIssuer,
    661                              inCertReq->certTemplate.issuer);
    662    }
    663    return SECFailure;
    664 }
    665 
    666 SECStatus
    667 CRMF_CertRequestGetCertTemplateIssuerUID(CRMFCertRequest *inCertReq,
    668                                         SECItem *destIssuerUID)
    669 {
    670    PORT_Assert(inCertReq != NULL);
    671    if (inCertReq == NULL) {
    672        return SECFailure;
    673    }
    674    if (CRMF_DoesRequestHaveField(inCertReq, crmfIssuerUID)) {
    675        return crmf_make_bitstring_copy(NULL, destIssuerUID,
    676                                        &inCertReq->certTemplate.issuerUID);
    677    }
    678    return SECFailure;
    679 }
    680 
    681 SECStatus
    682 CRMF_CertRequestGetCertTemplatePublicKey(CRMFCertRequest *inCertReq,
    683                                         CERTSubjectPublicKeyInfo *destPublicKey)
    684 {
    685    PORT_Assert(inCertReq != NULL);
    686    if (inCertReq == NULL) {
    687        return SECFailure;
    688    }
    689    if (CRMF_DoesRequestHaveField(inCertReq, crmfPublicKey)) {
    690        return SECKEY_CopySubjectPublicKeyInfo(NULL, destPublicKey,
    691                                               inCertReq->certTemplate.publicKey);
    692    }
    693    return SECFailure;
    694 }
    695 
    696 SECStatus
    697 CRMF_CertRequestGetCertTemplateSerialNumber(CRMFCertRequest *inCertReq,
    698                                            long *serialNumber)
    699 {
    700    PORT_Assert(inCertReq != NULL);
    701    if (inCertReq == NULL) {
    702        return SECFailure;
    703    }
    704    if (CRMF_DoesRequestHaveField(inCertReq, crmfSerialNumber)) {
    705        return crmf_extract_long_from_item(&inCertReq->certTemplate.serialNumber,
    706                                           serialNumber);
    707    }
    708    return SECFailure;
    709 }
    710 
    711 SECStatus
    712 CRMF_CertRequestGetCertTemplateSigningAlg(CRMFCertRequest *inCertReq,
    713                                          SECAlgorithmID *destAlg)
    714 {
    715    PORT_Assert(inCertReq != NULL);
    716    if (inCertReq == NULL) {
    717        return SECFailure;
    718    }
    719    if (CRMF_DoesRequestHaveField(inCertReq, crmfSigningAlg)) {
    720        return SECOID_CopyAlgorithmID(NULL, destAlg,
    721                                      inCertReq->certTemplate.signingAlg);
    722    }
    723    return SECFailure;
    724 }
    725 
    726 SECStatus
    727 CRMF_CertRequestGetCertTemplateSubject(CRMFCertRequest *inCertReq,
    728                                       CERTName *destSubject)
    729 {
    730    PORT_Assert(inCertReq != NULL);
    731    if (inCertReq == NULL) {
    732        return SECFailure;
    733    }
    734    if (CRMF_DoesRequestHaveField(inCertReq, crmfSubject)) {
    735        return crmf_copy_name(destSubject, inCertReq->certTemplate.subject);
    736    }
    737    return SECFailure;
    738 }
    739 
    740 SECStatus
    741 CRMF_CertRequestGetCertTemplateSubjectUID(CRMFCertRequest *inCertReq,
    742                                          SECItem *destSubjectUID)
    743 {
    744    PORT_Assert(inCertReq != NULL);
    745    if (inCertReq == NULL) {
    746        return SECFailure;
    747    }
    748    if (CRMF_DoesRequestHaveField(inCertReq, crmfSubjectUID)) {
    749        return crmf_make_bitstring_copy(NULL, destSubjectUID,
    750                                        &inCertReq->certTemplate.subjectUID);
    751    }
    752    return SECFailure;
    753 }
    754 
    755 SECStatus
    756 CRMF_CertRequestGetCertTemplateVersion(CRMFCertRequest *inCertReq,
    757                                       long *version)
    758 {
    759    PORT_Assert(inCertReq != NULL);
    760    if (inCertReq == NULL) {
    761        return SECFailure;
    762    }
    763    if (CRMF_DoesRequestHaveField(inCertReq, crmfVersion)) {
    764        return crmf_extract_long_from_item(&inCertReq->certTemplate.version,
    765                                           version);
    766    }
    767    return SECFailure;
    768 }
    769 
    770 static SECStatus
    771 crmf_copy_validity(CRMFGetValidity *destValidity,
    772                   CRMFOptionalValidity *src)
    773 {
    774    SECStatus rv;
    775 
    776    destValidity->notBefore = destValidity->notAfter = NULL;
    777    if (src->notBefore.data != NULL) {
    778        rv = crmf_create_prtime(&src->notBefore,
    779                                &destValidity->notBefore);
    780        if (rv != SECSuccess) {
    781            return rv;
    782        }
    783    }
    784    if (src->notAfter.data != NULL) {
    785        rv = crmf_create_prtime(&src->notAfter,
    786                                &destValidity->notAfter);
    787        if (rv != SECSuccess) {
    788            return rv;
    789        }
    790    }
    791    return SECSuccess;
    792 }
    793 
    794 SECStatus
    795 CRMF_CertRequestGetCertTemplateValidity(CRMFCertRequest *inCertReq,
    796                                        CRMFGetValidity *destValidity)
    797 {
    798    PORT_Assert(inCertReq != NULL);
    799    if (inCertReq == NULL) {
    800        return SECFailure;
    801    }
    802    if (CRMF_DoesRequestHaveField(inCertReq, crmfValidity)) {
    803        return crmf_copy_validity(destValidity,
    804                                  inCertReq->certTemplate.validity);
    805    }
    806    return SECFailure;
    807 }
    808 
    809 CRMFControl *
    810 CRMF_CertRequestGetControlAtIndex(CRMFCertRequest *inCertReq, int index)
    811 {
    812    CRMFControl *newControl, *srcControl;
    813    int numControls;
    814    SECStatus rv;
    815 
    816    PORT_Assert(inCertReq != NULL);
    817    if (inCertReq == NULL) {
    818        return NULL;
    819    }
    820    numControls = CRMF_CertRequestGetNumControls(inCertReq);
    821    if (index >= numControls || index < 0) {
    822        return NULL;
    823    }
    824    newControl = PORT_ZNew(CRMFControl);
    825    if (newControl == NULL) {
    826        return NULL;
    827    }
    828    srcControl = inCertReq->controls[index];
    829    newControl->tag = srcControl->tag;
    830    rv = SECITEM_CopyItem(NULL, &newControl->derTag, &srcControl->derTag);
    831    if (rv != SECSuccess) {
    832        goto loser;
    833    }
    834 
    835    rv = SECITEM_CopyItem(NULL, &newControl->derValue,
    836                          &srcControl->derValue);
    837    if (rv != SECSuccess) {
    838        goto loser;
    839    }
    840    /* Copy over the PKIArchiveOptions stuff */
    841    switch (srcControl->tag) {
    842        case SEC_OID_PKIX_REGCTRL_REGTOKEN:
    843        case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
    844            /* No further processing necessary for these types. */
    845            rv = SECSuccess;
    846            break;
    847        case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
    848        case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
    849        case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
    850            /* These aren't supported yet, so no post-processing will
    851             * be done at this time.  But we don't want to fail in case
    852             * we read in DER that has one of these options.
    853             */
    854            rv = SECSuccess;
    855            break;
    856        case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
    857            rv = crmf_copy_pkiarchiveoptions(NULL,
    858                                             &newControl->value.archiveOptions,
    859                                             &srcControl->value.archiveOptions);
    860            break;
    861        default:
    862            rv = SECFailure;
    863    }
    864    if (rv != SECSuccess) {
    865        goto loser;
    866    }
    867    return newControl;
    868 loser:
    869    CRMF_DestroyControl(newControl);
    870    return NULL;
    871 }
    872 
    873 static SECItem *
    874 crmf_copy_control_value(CRMFControl *inControl)
    875 {
    876    return SECITEM_DupItem(&inControl->derValue);
    877 }
    878 
    879 SECItem *
    880 CRMF_ControlGetAuthenticatorControlValue(CRMFControl *inControl)
    881 {
    882    PORT_Assert(inControl != NULL);
    883    if (inControl == NULL ||
    884        CRMF_ControlGetControlType(inControl) != crmfAuthenticatorControl) {
    885        return NULL;
    886    }
    887    return crmf_copy_control_value(inControl);
    888 }
    889 
    890 CRMFControlType
    891 CRMF_ControlGetControlType(CRMFControl *inControl)
    892 {
    893    CRMFControlType retType;
    894 
    895    PORT_Assert(inControl != NULL);
    896    switch (inControl->tag) {
    897        case SEC_OID_PKIX_REGCTRL_REGTOKEN:
    898            retType = crmfRegTokenControl;
    899            break;
    900        case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
    901            retType = crmfAuthenticatorControl;
    902            break;
    903        case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
    904            retType = crmfPKIPublicationInfoControl;
    905            break;
    906        case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
    907            retType = crmfPKIArchiveOptionsControl;
    908            break;
    909        case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
    910            retType = crmfOldCertIDControl;
    911            break;
    912        case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
    913            retType = crmfProtocolEncrKeyControl;
    914            break;
    915        default:
    916            retType = crmfNoControl;
    917    }
    918    return retType;
    919 }
    920 
    921 CRMFPKIArchiveOptions *
    922 CRMF_ControlGetPKIArchiveOptions(CRMFControl *inControl)
    923 {
    924    CRMFPKIArchiveOptions *newOpt = NULL;
    925    SECStatus rv;
    926 
    927    PORT_Assert(inControl != NULL);
    928    if (inControl == NULL ||
    929        CRMF_ControlGetControlType(inControl) != crmfPKIArchiveOptionsControl) {
    930        goto loser;
    931    }
    932    newOpt = PORT_ZNew(CRMFPKIArchiveOptions);
    933    if (newOpt == NULL) {
    934        goto loser;
    935    }
    936    rv = crmf_copy_pkiarchiveoptions(NULL, newOpt,
    937                                     &inControl->value.archiveOptions);
    938    if (rv != SECSuccess) {
    939        goto loser;
    940    }
    941 
    942 loser:
    943    if (newOpt != NULL) {
    944        CRMF_DestroyPKIArchiveOptions(newOpt);
    945    }
    946    return NULL;
    947 }
    948 
    949 SECItem *
    950 CRMF_ControlGetRegTokenControlValue(CRMFControl *inControl)
    951 {
    952    PORT_Assert(inControl != NULL);
    953    if (inControl == NULL ||
    954        CRMF_ControlGetControlType(inControl) != crmfRegTokenControl) {
    955        return NULL;
    956    }
    957    return crmf_copy_control_value(inControl);
    958    ;
    959 }
    960 
    961 CRMFCertExtension *
    962 CRMF_CertRequestGetExtensionAtIndex(CRMFCertRequest *inCertReq,
    963                                    int index)
    964 {
    965    int numExtensions;
    966 
    967    PORT_Assert(inCertReq != NULL);
    968    numExtensions = CRMF_CertRequestGetNumberOfExtensions(inCertReq);
    969    if (index >= numExtensions || index < 0) {
    970        return NULL;
    971    }
    972    return crmf_copy_cert_extension(NULL,
    973                                    inCertReq->certTemplate.extensions[index]);
    974 }