tor-browser

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

respcmn.c (11844B)


      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 "secder.h"
     10 
     11 SECStatus
     12 cmmf_DestroyPKIStatusInfo(CMMFPKIStatusInfo *info, PRBool freeit)
     13 {
     14    if (info->status.data != NULL) {
     15        PORT_Free(info->status.data);
     16        info->status.data = NULL;
     17    }
     18    if (info->statusString.data != NULL) {
     19        PORT_Free(info->statusString.data);
     20        info->statusString.data = NULL;
     21    }
     22    if (info->failInfo.data != NULL) {
     23        PORT_Free(info->failInfo.data);
     24        info->failInfo.data = NULL;
     25    }
     26    if (freeit) {
     27        PORT_Free(info);
     28    }
     29    return SECSuccess;
     30 }
     31 
     32 SECStatus
     33 CMMF_DestroyCertResponse(CMMFCertResponse *inCertResp)
     34 {
     35    PORT_Assert(inCertResp != NULL);
     36    if (inCertResp != NULL) {
     37        if (inCertResp->certReqId.data != NULL) {
     38            PORT_Free(inCertResp->certReqId.data);
     39        }
     40        cmmf_DestroyPKIStatusInfo(&inCertResp->status, PR_FALSE);
     41        if (inCertResp->certifiedKeyPair != NULL) {
     42            CMMF_DestroyCertifiedKeyPair(inCertResp->certifiedKeyPair);
     43        }
     44        PORT_Free(inCertResp);
     45    }
     46    return SECSuccess;
     47 }
     48 
     49 SECStatus
     50 CMMF_DestroyCertRepContent(CMMFCertRepContent *inCertRepContent)
     51 {
     52    PORT_Assert(inCertRepContent != NULL);
     53    if (inCertRepContent != NULL) {
     54        CMMFCertResponse **pResponse = inCertRepContent->response;
     55        if (pResponse != NULL) {
     56            for (; *pResponse != NULL; pResponse++) {
     57                CMMFCertifiedKeyPair *certKeyPair = (*pResponse)->certifiedKeyPair;
     58                /* XXX Why not call CMMF_DestroyCertifiedKeyPair or
     59                 ** XXX cmmf_DestroyCertOrEncCert ?
     60                 */
     61                if (certKeyPair != NULL &&
     62                    certKeyPair->certOrEncCert.choice == cmmfCertificate &&
     63                    certKeyPair->certOrEncCert.cert.certificate != NULL) {
     64                    CERT_DestroyCertificate(certKeyPair->certOrEncCert.cert.certificate);
     65                    certKeyPair->certOrEncCert.cert.certificate = NULL;
     66                }
     67            }
     68        }
     69        if (inCertRepContent->caPubs) {
     70            CERTCertificate **caPubs = inCertRepContent->caPubs;
     71            for (; *caPubs; ++caPubs) {
     72                CERT_DestroyCertificate(*caPubs);
     73                *caPubs = NULL;
     74            }
     75        }
     76        if (inCertRepContent->poolp != NULL) {
     77            PORT_FreeArena(inCertRepContent->poolp, PR_TRUE);
     78        }
     79    }
     80    return SECSuccess;
     81 }
     82 
     83 SECStatus
     84 CMMF_DestroyPOPODecKeyChallContent(CMMFPOPODecKeyChallContent *inDecKeyCont)
     85 {
     86    PORT_Assert(inDecKeyCont != NULL);
     87    if (inDecKeyCont != NULL && inDecKeyCont->poolp) {
     88        PORT_FreeArena(inDecKeyCont->poolp, PR_FALSE);
     89    }
     90    return SECSuccess;
     91 }
     92 
     93 SECStatus
     94 crmf_create_prtime(SECItem *src, PRTime **dest)
     95 {
     96    *dest = PORT_ZNew(PRTime);
     97    return DER_DecodeTimeChoice(*dest, src);
     98 }
     99 
    100 CRMFCertExtension *
    101 crmf_copy_cert_extension(PLArenaPool *poolp, CRMFCertExtension *inExtension)
    102 {
    103    PRBool isCritical;
    104    SECOidTag id;
    105    SECItem *data;
    106    CRMFCertExtension *newExt;
    107 
    108    PORT_Assert(inExtension != NULL);
    109    if (inExtension == NULL) {
    110        return NULL;
    111    }
    112    id = CRMF_CertExtensionGetOidTag(inExtension);
    113    isCritical = CRMF_CertExtensionGetIsCritical(inExtension);
    114    data = CRMF_CertExtensionGetValue(inExtension);
    115    newExt = crmf_create_cert_extension(poolp, id,
    116                                        isCritical,
    117                                        data);
    118    SECITEM_FreeItem(data, PR_TRUE);
    119    return newExt;
    120 }
    121 
    122 static SECItem *
    123 cmmf_encode_certificate(CERTCertificate *inCert)
    124 {
    125    return SEC_ASN1EncodeItem(NULL, NULL, inCert,
    126                              SEC_ASN1_GET(SEC_SignedCertificateTemplate));
    127 }
    128 
    129 CERTCertList *
    130 cmmf_MakeCertList(CERTCertificate **inCerts)
    131 {
    132    CERTCertList *certList;
    133    CERTCertificate *currCert;
    134    SECItem *derCert, *freeCert = NULL;
    135    SECStatus rv;
    136    int i;
    137 
    138    certList = CERT_NewCertList();
    139    if (certList == NULL) {
    140        return NULL;
    141    }
    142    for (i = 0; inCerts[i] != NULL; i++) {
    143        derCert = &inCerts[i]->derCert;
    144        if (derCert->data == NULL) {
    145            derCert = freeCert = cmmf_encode_certificate(inCerts[i]);
    146        }
    147        currCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
    148                                           derCert, NULL, PR_FALSE, PR_TRUE);
    149        if (freeCert != NULL) {
    150            SECITEM_FreeItem(freeCert, PR_TRUE);
    151            freeCert = NULL;
    152        }
    153        if (currCert == NULL) {
    154            goto loser;
    155        }
    156        rv = CERT_AddCertToListTail(certList, currCert);
    157        if (rv != SECSuccess) {
    158            goto loser;
    159        }
    160    }
    161    return certList;
    162 loser:
    163    CERT_DestroyCertList(certList);
    164    return NULL;
    165 }
    166 
    167 CMMFPKIStatus
    168 cmmf_PKIStatusInfoGetStatus(CMMFPKIStatusInfo *inStatus)
    169 {
    170    long derVal;
    171 
    172    derVal = DER_GetInteger(&inStatus->status);
    173    if (derVal == -1 || derVal < cmmfGranted || derVal >= cmmfNumPKIStatus) {
    174        return cmmfNoPKIStatus;
    175    }
    176    return (CMMFPKIStatus)derVal;
    177 }
    178 
    179 int
    180 CMMF_CertRepContentGetNumResponses(CMMFCertRepContent *inCertRepContent)
    181 {
    182    int numResponses = 0;
    183    PORT_Assert(inCertRepContent != NULL);
    184    if (inCertRepContent != NULL && inCertRepContent->response != NULL) {
    185        while (inCertRepContent->response[numResponses] != NULL) {
    186            numResponses++;
    187        }
    188    }
    189    return numResponses;
    190 }
    191 
    192 SECStatus
    193 cmmf_DestroyCertOrEncCert(CMMFCertOrEncCert *certOrEncCert, PRBool freeit)
    194 {
    195    switch (certOrEncCert->choice) {
    196        case cmmfCertificate:
    197            CERT_DestroyCertificate(certOrEncCert->cert.certificate);
    198            certOrEncCert->cert.certificate = NULL;
    199            break;
    200        case cmmfEncryptedCert:
    201            crmf_destroy_encrypted_value(certOrEncCert->cert.encryptedCert,
    202                                         PR_TRUE);
    203            certOrEncCert->cert.encryptedCert = NULL;
    204            break;
    205        default:
    206            break;
    207    }
    208    if (freeit) {
    209        PORT_Free(certOrEncCert);
    210    }
    211    return SECSuccess;
    212 }
    213 
    214 SECStatus
    215 cmmf_copy_secitem(PLArenaPool *poolp, SECItem *dest, SECItem *src)
    216 {
    217    SECStatus rv;
    218 
    219    if (src->data != NULL) {
    220        rv = SECITEM_CopyItem(poolp, dest, src);
    221    } else {
    222        dest->data = NULL;
    223        dest->len = 0;
    224        rv = SECSuccess;
    225    }
    226    return rv;
    227 }
    228 
    229 SECStatus
    230 CMMF_DestroyCertifiedKeyPair(CMMFCertifiedKeyPair *inCertKeyPair)
    231 {
    232    PORT_Assert(inCertKeyPair != NULL);
    233    if (inCertKeyPair != NULL) {
    234        cmmf_DestroyCertOrEncCert(&inCertKeyPair->certOrEncCert, PR_FALSE);
    235        if (inCertKeyPair->privateKey) {
    236            crmf_destroy_encrypted_value(inCertKeyPair->privateKey, PR_TRUE);
    237        }
    238        if (inCertKeyPair->derPublicationInfo.data) {
    239            PORT_Free(inCertKeyPair->derPublicationInfo.data);
    240        }
    241        PORT_Free(inCertKeyPair);
    242    }
    243    return SECSuccess;
    244 }
    245 
    246 SECStatus
    247 cmmf_CopyCertResponse(PLArenaPool *poolp,
    248                      CMMFCertResponse *dest,
    249                      CMMFCertResponse *src)
    250 {
    251    SECStatus rv;
    252 
    253    if (src->certReqId.data != NULL) {
    254        rv = SECITEM_CopyItem(poolp, &dest->certReqId, &src->certReqId);
    255        if (rv != SECSuccess) {
    256            return rv;
    257        }
    258    }
    259    rv = cmmf_CopyPKIStatusInfo(poolp, &dest->status, &src->status);
    260    if (rv != SECSuccess) {
    261        return rv;
    262    }
    263    if (src->certifiedKeyPair != NULL) {
    264        CMMFCertifiedKeyPair *destKeyPair;
    265 
    266        destKeyPair = (poolp == NULL) ? PORT_ZNew(CMMFCertifiedKeyPair) : PORT_ArenaZNew(poolp, CMMFCertifiedKeyPair);
    267        if (!destKeyPair) {
    268            return SECFailure;
    269        }
    270        rv = cmmf_CopyCertifiedKeyPair(poolp, destKeyPair,
    271                                       src->certifiedKeyPair);
    272        if (rv != SECSuccess) {
    273            if (!poolp) {
    274                CMMF_DestroyCertifiedKeyPair(destKeyPair);
    275            }
    276            return rv;
    277        }
    278        dest->certifiedKeyPair = destKeyPair;
    279    }
    280    return SECSuccess;
    281 }
    282 
    283 static SECStatus
    284 cmmf_CopyCertOrEncCert(PLArenaPool *poolp, CMMFCertOrEncCert *dest,
    285                       CMMFCertOrEncCert *src)
    286 {
    287    SECStatus rv = SECSuccess;
    288    CRMFEncryptedValue *encVal;
    289 
    290    dest->choice = src->choice;
    291    rv = cmmf_copy_secitem(poolp, &dest->derValue, &src->derValue);
    292    switch (src->choice) {
    293        case cmmfCertificate:
    294            dest->cert.certificate = CERT_DupCertificate(src->cert.certificate);
    295            break;
    296        case cmmfEncryptedCert:
    297            encVal = (poolp == NULL) ? PORT_ZNew(CRMFEncryptedValue) : PORT_ArenaZNew(poolp, CRMFEncryptedValue);
    298            if (encVal == NULL) {
    299                return SECFailure;
    300            }
    301            rv = crmf_copy_encryptedvalue(poolp, src->cert.encryptedCert, encVal);
    302            if (rv != SECSuccess) {
    303                if (!poolp) {
    304                    crmf_destroy_encrypted_value(encVal, PR_TRUE);
    305                }
    306                return rv;
    307            }
    308            dest->cert.encryptedCert = encVal;
    309            break;
    310        default:
    311            rv = SECFailure;
    312    }
    313    return rv;
    314 }
    315 
    316 SECStatus
    317 cmmf_CopyCertifiedKeyPair(PLArenaPool *poolp, CMMFCertifiedKeyPair *dest,
    318                          CMMFCertifiedKeyPair *src)
    319 {
    320    SECStatus rv;
    321 
    322    rv = cmmf_CopyCertOrEncCert(poolp, &dest->certOrEncCert,
    323                                &src->certOrEncCert);
    324    if (rv != SECSuccess) {
    325        return rv;
    326    }
    327 
    328    if (src->privateKey != NULL) {
    329        CRMFEncryptedValue *encVal;
    330 
    331        encVal = (poolp == NULL) ? PORT_ZNew(CRMFEncryptedValue) : PORT_ArenaZNew(poolp, CRMFEncryptedValue);
    332        if (encVal == NULL) {
    333            return SECFailure;
    334        }
    335        rv = crmf_copy_encryptedvalue(poolp, src->privateKey,
    336                                      encVal);
    337        if (rv != SECSuccess) {
    338            if (!poolp) {
    339                crmf_destroy_encrypted_value(encVal, PR_TRUE);
    340            }
    341            return rv;
    342        }
    343        dest->privateKey = encVal;
    344    }
    345    rv = cmmf_copy_secitem(poolp, &dest->derPublicationInfo,
    346                           &src->derPublicationInfo);
    347    return rv;
    348 }
    349 
    350 SECStatus
    351 cmmf_CopyPKIStatusInfo(PLArenaPool *poolp, CMMFPKIStatusInfo *dest,
    352                       CMMFPKIStatusInfo *src)
    353 {
    354    SECStatus rv;
    355 
    356    rv = cmmf_copy_secitem(poolp, &dest->status, &src->status);
    357    if (rv != SECSuccess) {
    358        return rv;
    359    }
    360    rv = cmmf_copy_secitem(poolp, &dest->statusString, &src->statusString);
    361    if (rv != SECSuccess) {
    362        return rv;
    363    }
    364    rv = cmmf_copy_secitem(poolp, &dest->failInfo, &src->failInfo);
    365    return rv;
    366 }
    367 
    368 CERTCertificate *
    369 cmmf_CertOrEncCertGetCertificate(CMMFCertOrEncCert *certOrEncCert,
    370                                 CERTCertDBHandle *certdb)
    371 {
    372    if (certOrEncCert->choice != cmmfCertificate ||
    373        certOrEncCert->cert.certificate == NULL) {
    374        return NULL;
    375    }
    376    return CERT_NewTempCertificate(certdb,
    377                                   &certOrEncCert->cert.certificate->derCert,
    378                                   NULL, PR_FALSE, PR_TRUE);
    379 }
    380 
    381 SECStatus
    382 cmmf_PKIStatusInfoSetStatus(CMMFPKIStatusInfo *statusInfo,
    383                            PLArenaPool *poolp,
    384                            CMMFPKIStatus inStatus)
    385 {
    386    SECItem *dummy;
    387 
    388    if (inStatus < cmmfGranted || inStatus >= cmmfNumPKIStatus) {
    389        return SECFailure;
    390    }
    391 
    392    dummy = SEC_ASN1EncodeInteger(poolp, &statusInfo->status, inStatus);
    393    PORT_Assert(dummy == &statusInfo->status);
    394    if (dummy != &statusInfo->status) {
    395        SECITEM_FreeItem(dummy, PR_TRUE);
    396        return SECFailure;
    397    }
    398    return SECSuccess;
    399 }