tor-browser

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

cmmfrec.c (10424B)


      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 /*
      7 * This file will implement the functions related to key recovery in
      8 * CMMF
      9 */
     10 
     11 #include "cmmf.h"
     12 #include "cmmfi.h"
     13 #include "secitem.h"
     14 #include "keyhi.h"
     15 
     16 CMMFKeyRecRepContent *
     17 CMMF_CreateKeyRecRepContent(void)
     18 {
     19    PLArenaPool *poolp;
     20    CMMFKeyRecRepContent *keyRecContent;
     21 
     22    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
     23    if (poolp == NULL) {
     24        return NULL;
     25    }
     26    keyRecContent = PORT_ArenaZNew(poolp, CMMFKeyRecRepContent);
     27    if (keyRecContent == NULL) {
     28        PORT_FreeArena(poolp, PR_FALSE);
     29        return NULL;
     30    }
     31    keyRecContent->poolp = poolp;
     32    return keyRecContent;
     33 }
     34 
     35 SECStatus
     36 CMMF_DestroyKeyRecRepContent(CMMFKeyRecRepContent *inKeyRecRep)
     37 {
     38    PORT_Assert(inKeyRecRep != NULL);
     39    if (inKeyRecRep != NULL && inKeyRecRep->poolp != NULL) {
     40        int i;
     41 
     42        if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert != NULL) {
     43            CERT_DestroyCertificate(inKeyRecRep->newSigCert);
     44        }
     45        if (inKeyRecRep->caCerts != NULL) {
     46            for (i = 0; inKeyRecRep->caCerts[i] != NULL; i++) {
     47                CERT_DestroyCertificate(inKeyRecRep->caCerts[i]);
     48            }
     49        }
     50        if (inKeyRecRep->keyPairHist != NULL) {
     51            for (i = 0; inKeyRecRep->keyPairHist[i] != NULL; i++) {
     52                if (inKeyRecRep->keyPairHist[i]->certOrEncCert.choice ==
     53                    cmmfCertificate) {
     54                    CERT_DestroyCertificate(inKeyRecRep->keyPairHist[i]->certOrEncCert.cert.certificate);
     55                }
     56            }
     57        }
     58        PORT_FreeArena(inKeyRecRep->poolp, PR_TRUE);
     59    }
     60    return SECSuccess;
     61 }
     62 
     63 SECStatus
     64 CMMF_KeyRecRepContentSetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep,
     65                                            CMMFPKIStatus inPKIStatus)
     66 {
     67    PORT_Assert(inKeyRecRep != NULL && inPKIStatus >= cmmfGranted &&
     68                inPKIStatus < cmmfNumPKIStatus);
     69    if (inKeyRecRep == NULL) {
     70        return SECFailure;
     71    }
     72 
     73    return cmmf_PKIStatusInfoSetStatus(&inKeyRecRep->status,
     74                                       inKeyRecRep->poolp,
     75                                       inPKIStatus);
     76 }
     77 
     78 SECStatus
     79 CMMF_KeyRecRepContentSetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep,
     80                                    CERTCertificate *inNewSignCert)
     81 {
     82    PORT_Assert(inKeyRecRep != NULL && inNewSignCert != NULL);
     83    if (inKeyRecRep == NULL || inNewSignCert == NULL) {
     84        return SECFailure;
     85    }
     86    if (!inKeyRecRep->isDecoded && inKeyRecRep->newSigCert) {
     87        CERT_DestroyCertificate(inKeyRecRep->newSigCert);
     88    }
     89    inKeyRecRep->isDecoded = PR_FALSE;
     90    inKeyRecRep->newSigCert = CERT_DupCertificate(inNewSignCert);
     91    return (inKeyRecRep->newSigCert == NULL) ? SECFailure : SECSuccess;
     92 }
     93 
     94 SECStatus
     95 CMMF_KeyRecRepContentSetCACerts(CMMFKeyRecRepContent *inKeyRecRep,
     96                                CERTCertList *inCACerts)
     97 {
     98    SECStatus rv;
     99    void *mark;
    100 
    101    PORT_Assert(inKeyRecRep != NULL && inCACerts != NULL);
    102    if (inKeyRecRep == NULL || inCACerts == NULL) {
    103        return SECFailure;
    104    }
    105    mark = PORT_ArenaMark(inKeyRecRep->poolp);
    106    rv = cmmf_ExtractCertsFromList(inCACerts, inKeyRecRep->poolp,
    107                                   &inKeyRecRep->caCerts);
    108    if (rv != SECSuccess) {
    109        PORT_ArenaRelease(inKeyRecRep->poolp, mark);
    110    } else {
    111        PORT_ArenaUnmark(inKeyRecRep->poolp, mark);
    112    }
    113    return rv;
    114 }
    115 
    116 SECStatus
    117 CMMF_KeyRecRepContentSetCertifiedKeyPair(CMMFKeyRecRepContent *inKeyRecRep,
    118                                         CERTCertificate *inCert,
    119                                         SECKEYPrivateKey *inPrivKey,
    120                                         SECKEYPublicKey *inPubKey)
    121 {
    122    CMMFCertifiedKeyPair *keyPair;
    123    CRMFEncryptedValue *dummy;
    124    PLArenaPool *poolp;
    125    void *mark;
    126    SECStatus rv;
    127 
    128    PORT_Assert(inKeyRecRep != NULL &&
    129                inCert != NULL &&
    130                inPrivKey != NULL &&
    131                inPubKey != NULL);
    132    if (inKeyRecRep == NULL ||
    133        inCert == NULL ||
    134        inPrivKey == NULL ||
    135        inPubKey == NULL) {
    136        return SECFailure;
    137    }
    138    poolp = inKeyRecRep->poolp;
    139    mark = PORT_ArenaMark(poolp);
    140    if (inKeyRecRep->keyPairHist == NULL) {
    141        inKeyRecRep->keyPairHist = PORT_ArenaNewArray(poolp,
    142                                                      CMMFCertifiedKeyPair *,
    143                                                      (CMMF_MAX_KEY_PAIRS + 1));
    144        if (inKeyRecRep->keyPairHist == NULL) {
    145            goto loser;
    146        }
    147        inKeyRecRep->allocKeyPairs = CMMF_MAX_KEY_PAIRS;
    148        inKeyRecRep->numKeyPairs = 0;
    149    }
    150 
    151    if (inKeyRecRep->allocKeyPairs == inKeyRecRep->numKeyPairs) {
    152        goto loser;
    153    }
    154 
    155    keyPair = PORT_ArenaZNew(poolp, CMMFCertifiedKeyPair);
    156    if (keyPair == NULL) {
    157        goto loser;
    158    }
    159    rv = cmmf_CertOrEncCertSetCertificate(&keyPair->certOrEncCert,
    160                                          poolp, inCert);
    161    if (rv != SECSuccess) {
    162        goto loser;
    163    }
    164    keyPair->privateKey = PORT_ArenaZNew(poolp, CRMFEncryptedValue);
    165    if (keyPair->privateKey == NULL) {
    166        goto loser;
    167    }
    168    dummy = crmf_create_encrypted_value_wrapped_privkey(inPrivKey, inPubKey,
    169                                                        keyPair->privateKey);
    170    PORT_Assert(dummy == keyPair->privateKey);
    171    if (dummy != keyPair->privateKey) {
    172        crmf_destroy_encrypted_value(dummy, PR_TRUE);
    173        goto loser;
    174    }
    175    inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = keyPair;
    176    inKeyRecRep->numKeyPairs++;
    177    inKeyRecRep->keyPairHist[inKeyRecRep->numKeyPairs] = NULL;
    178    PORT_ArenaUnmark(poolp, mark);
    179    return SECSuccess;
    180 
    181 loser:
    182    PORT_ArenaRelease(poolp, mark);
    183    return SECFailure;
    184 }
    185 
    186 CMMFPKIStatus
    187 CMMF_KeyRecRepContentGetPKIStatusInfoStatus(CMMFKeyRecRepContent *inKeyRecRep)
    188 {
    189    PORT_Assert(inKeyRecRep != NULL);
    190    if (inKeyRecRep == NULL) {
    191        return cmmfNoPKIStatus;
    192    }
    193    return cmmf_PKIStatusInfoGetStatus(&inKeyRecRep->status);
    194 }
    195 
    196 CERTCertificate *
    197 CMMF_KeyRecRepContentGetNewSignCert(CMMFKeyRecRepContent *inKeyRecRep)
    198 {
    199    PORT_Assert(inKeyRecRep != NULL);
    200    if (inKeyRecRep == NULL ||
    201        inKeyRecRep->newSigCert == NULL) {
    202        return NULL;
    203    }
    204    /* newSigCert may not be a real certificate, it may be a hand decoded
    205     * cert structure. This code makes sure we hand off a real, fully formed
    206     * CERTCertificate to the caller. TODO: This should move into the decode
    207     * portion so that we never wind up with a half formed CERTCertificate
    208     * here. In this case the call would be to CERT_DupCertificate.
    209     */
    210    return CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
    211                                   &inKeyRecRep->newSigCert->signatureWrap.data,
    212                                   NULL, PR_FALSE, PR_TRUE);
    213 }
    214 
    215 CERTCertList *
    216 CMMF_KeyRecRepContentGetCACerts(CMMFKeyRecRepContent *inKeyRecRep)
    217 {
    218    PORT_Assert(inKeyRecRep != NULL);
    219    if (inKeyRecRep == NULL || inKeyRecRep->caCerts == NULL) {
    220        return NULL;
    221    }
    222    return cmmf_MakeCertList(inKeyRecRep->caCerts);
    223 }
    224 
    225 int
    226 CMMF_KeyRecRepContentGetNumKeyPairs(CMMFKeyRecRepContent *inKeyRecRep)
    227 {
    228    PORT_Assert(inKeyRecRep != NULL);
    229    return (inKeyRecRep == NULL) ? 0 : inKeyRecRep->numKeyPairs;
    230 }
    231 
    232 PRBool
    233 cmmf_KeyRecRepContentIsValidIndex(CMMFKeyRecRepContent *inKeyRecRep,
    234                                  int inIndex)
    235 {
    236    int numKeyPairs = CMMF_KeyRecRepContentGetNumKeyPairs(inKeyRecRep);
    237 
    238    return (PRBool)(inIndex >= 0 && inIndex < numKeyPairs);
    239 }
    240 
    241 CMMFCertifiedKeyPair *
    242 CMMF_KeyRecRepContentGetCertKeyAtIndex(CMMFKeyRecRepContent *inKeyRecRep,
    243                                       int inIndex)
    244 {
    245    CMMFCertifiedKeyPair *newKeyPair;
    246    SECStatus rv;
    247 
    248    PORT_Assert(inKeyRecRep != NULL &&
    249                cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex));
    250    if (inKeyRecRep == NULL ||
    251        !cmmf_KeyRecRepContentIsValidIndex(inKeyRecRep, inIndex)) {
    252        return NULL;
    253    }
    254    newKeyPair = PORT_ZNew(CMMFCertifiedKeyPair);
    255    if (newKeyPair == NULL) {
    256        return NULL;
    257    }
    258    rv = cmmf_CopyCertifiedKeyPair(NULL, newKeyPair,
    259                                   inKeyRecRep->keyPairHist[inIndex]);
    260    if (rv != SECSuccess) {
    261        CMMF_DestroyCertifiedKeyPair(newKeyPair);
    262        newKeyPair = NULL;
    263    }
    264    return newKeyPair;
    265 }
    266 
    267 SECStatus
    268 CMMF_CertifiedKeyPairUnwrapPrivKey(CMMFCertifiedKeyPair *inKeyPair,
    269                                   SECKEYPrivateKey *inPrivKey,
    270                                   SECItem *inNickName,
    271                                   PK11SlotInfo *inSlot,
    272                                   CERTCertDBHandle *inCertdb,
    273                                   SECKEYPrivateKey **destPrivKey,
    274                                   void *wincx)
    275 {
    276    CERTCertificate *cert;
    277    SECItem keyUsageValue = { siBuffer, NULL, 0 };
    278    unsigned char keyUsage = 0x0;
    279    SECKEYPublicKey *pubKey;
    280    SECStatus rv;
    281 
    282    PORT_Assert(inKeyPair != NULL &&
    283                inPrivKey != NULL && inCertdb != NULL);
    284    if (inKeyPair == NULL ||
    285        inPrivKey == NULL ||
    286        inKeyPair->privateKey == NULL ||
    287        inCertdb == NULL) {
    288        return SECFailure;
    289    }
    290 
    291    cert = CMMF_CertifiedKeyPairGetCertificate(inKeyPair, inCertdb);
    292    CERT_FindKeyUsageExtension(cert, &keyUsageValue);
    293    if (keyUsageValue.data != NULL) {
    294        keyUsage = keyUsageValue.len ? keyUsageValue.data[0] : 0;
    295        PORT_Free(keyUsageValue.data);
    296    }
    297    pubKey = CERT_ExtractPublicKey(cert);
    298    rv = crmf_encrypted_value_unwrap_priv_key(NULL, inKeyPair->privateKey,
    299                                              inPrivKey, pubKey,
    300                                              inNickName, inSlot, keyUsage,
    301                                              destPrivKey, wincx);
    302    SECKEY_DestroyPublicKey(pubKey);
    303    CERT_DestroyCertificate(cert);
    304    return rv;
    305 }
    306 
    307 PRBool
    308 CMMF_KeyRecRepContentHasCACerts(CMMFKeyRecRepContent *inKeyRecRep)
    309 {
    310    PORT_Assert(inKeyRecRep != NULL);
    311    if (inKeyRecRep == NULL) {
    312        return PR_FALSE;
    313    }
    314    return (PRBool)(inKeyRecRep->caCerts != NULL &&
    315                    inKeyRecRep->caCerts[0] != NULL);
    316 }