tor-browser

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

pki3hack.c (49992B)


      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 /*
      6 * Hacks to integrate NSS 3.4 and NSS 4.0 certificates.
      7 */
      8 
      9 #ifndef NSSPKI_H
     10 #include "nsspki.h"
     11 #endif /* NSSPKI_H */
     12 
     13 #ifndef PKI_H
     14 #include "pki.h"
     15 #endif /* PKI_H */
     16 
     17 #ifndef PKIM_H
     18 #include "pkim.h"
     19 #endif /* PKIM_H */
     20 
     21 #ifndef DEV_H
     22 #include "dev.h"
     23 #endif /* DEV_H */
     24 
     25 #ifndef DEVNSS3HACK_H
     26 #include "dev3hack.h"
     27 #endif /* DEVNSS3HACK_H */
     28 
     29 #ifndef PKINSS3HACK_H
     30 #include "pki3hack.h"
     31 #endif /* PKINSS3HACK_H */
     32 
     33 #include "secitem.h"
     34 #include "certdb.h"
     35 #include "certt.h"
     36 #include "cert.h"
     37 #include "certi.h"
     38 #include "pk11func.h"
     39 #include "pkistore.h"
     40 #include "secmod.h"
     41 #include "nssrwlk.h"
     42 
     43 NSSTrustDomain *g_default_trust_domain = NULL;
     44 
     45 NSSCryptoContext *g_default_crypto_context = NULL;
     46 
     47 NSSTrustDomain *
     48 STAN_GetDefaultTrustDomain()
     49 {
     50    return g_default_trust_domain;
     51 }
     52 
     53 NSSCryptoContext *
     54 STAN_GetDefaultCryptoContext()
     55 {
     56    return g_default_crypto_context;
     57 }
     58 
     59 extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
     60 extern const NSSError NSS_ERROR_INTERNAL_ERROR;
     61 
     62 NSS_IMPLEMENT PRStatus
     63 STAN_InitTokenForSlotInfo(NSSTrustDomain *td, PK11SlotInfo *slot)
     64 {
     65    NSSToken *token;
     66    if (!td) {
     67        td = g_default_trust_domain;
     68        if (!td) {
     69            /* we're called while still initting. slot will get added
     70             * appropriately through normal init processes */
     71            return PR_SUCCESS;
     72        }
     73    }
     74    token = nssToken_CreateFromPK11SlotInfo(td, slot);
     75    if (token) {
     76        /* PK11Slot_SetNSSToken increments the refcount on |token| to 2 */
     77        PK11Slot_SetNSSToken(slot, token);
     78 
     79        /* we give our reference to |td->tokenList| */
     80        NSSRWLock_LockWrite(td->tokensLock);
     81        nssList_Add(td->tokenList, token);
     82        NSSRWLock_UnlockWrite(td->tokensLock);
     83    } else {
     84        PK11Slot_SetNSSToken(slot, NULL);
     85    }
     86    return PR_SUCCESS;
     87 }
     88 
     89 NSS_IMPLEMENT PRStatus
     90 STAN_ResetTokenInterator(NSSTrustDomain *td)
     91 {
     92    if (!td) {
     93        td = g_default_trust_domain;
     94        if (!td) {
     95            /* we're called while still initting. slot will get added
     96             * appropriately through normal init processes */
     97            return PR_SUCCESS;
     98        }
     99    }
    100    NSSRWLock_LockWrite(td->tokensLock);
    101    nssListIterator_Destroy(td->tokens);
    102    td->tokens = nssList_CreateIterator(td->tokenList);
    103    NSSRWLock_UnlockWrite(td->tokensLock);
    104    return PR_SUCCESS;
    105 }
    106 
    107 NSS_IMPLEMENT PRStatus
    108 STAN_LoadDefaultNSS3TrustDomain(
    109    void)
    110 {
    111    NSSTrustDomain *td;
    112    SECMODModuleList *mlp;
    113    SECMODListLock *moduleLock = SECMOD_GetDefaultModuleListLock();
    114    int i;
    115 
    116    if (g_default_trust_domain || g_default_crypto_context) {
    117        /* Stan is already initialized or a previous shutdown failed. */
    118        nss_SetError(NSS_ERROR_ALREADY_INITIALIZED);
    119        return PR_FAILURE;
    120    }
    121    td = NSSTrustDomain_Create(NULL, NULL, NULL, NULL);
    122    if (!td) {
    123        return PR_FAILURE;
    124    }
    125    /*
    126     * Deadlock warning: we should never acquire the moduleLock while
    127     * we hold the tokensLock. We can use the NSSRWLock Rank feature to
    128     * guarrentee this. tokensLock have a higher rank than module lock.
    129     */
    130    td->tokenList = nssList_Create(td->arena, PR_TRUE);
    131    if (!td->tokenList) {
    132        goto loser;
    133    }
    134    SECMOD_GetReadLock(moduleLock);
    135    NSSRWLock_LockWrite(td->tokensLock);
    136    for (mlp = SECMOD_GetDefaultModuleList(); mlp != NULL; mlp = mlp->next) {
    137        for (i = 0; i < mlp->module->slotCount; i++) {
    138            STAN_InitTokenForSlotInfo(td, mlp->module->slots[i]);
    139        }
    140    }
    141    td->tokens = nssList_CreateIterator(td->tokenList);
    142    NSSRWLock_UnlockWrite(td->tokensLock);
    143    SECMOD_ReleaseReadLock(moduleLock);
    144    if (!td->tokens) {
    145        goto loser;
    146    }
    147    g_default_crypto_context = NSSTrustDomain_CreateCryptoContext(td, NULL);
    148    if (!g_default_crypto_context) {
    149        goto loser;
    150    }
    151    g_default_trust_domain = td;
    152    return PR_SUCCESS;
    153 
    154 loser:
    155    NSSTrustDomain_Destroy(td);
    156    return PR_FAILURE;
    157 }
    158 
    159 /*
    160 * must be called holding the ModuleListLock (either read or write).
    161 */
    162 NSS_IMPLEMENT SECStatus
    163 STAN_AddModuleToDefaultTrustDomain(
    164    SECMODModule *module)
    165 {
    166    NSSTrustDomain *td;
    167    int i;
    168    td = STAN_GetDefaultTrustDomain();
    169    for (i = 0; i < module->slotCount; i++) {
    170        STAN_InitTokenForSlotInfo(td, module->slots[i]);
    171    }
    172    STAN_ResetTokenInterator(td);
    173    return SECSuccess;
    174 }
    175 
    176 /*
    177 * must be called holding the ModuleListLock (either read or write).
    178 */
    179 NSS_IMPLEMENT SECStatus
    180 STAN_RemoveModuleFromDefaultTrustDomain(
    181    SECMODModule *module)
    182 {
    183    NSSToken *token;
    184    NSSTrustDomain *td;
    185    int i;
    186    td = STAN_GetDefaultTrustDomain();
    187    for (i = 0; i < module->slotCount; i++) {
    188        token = PK11Slot_GetNSSToken(module->slots[i]);
    189        if (token) {
    190            nssToken_NotifyCertsNotVisible(token);
    191            NSSRWLock_LockWrite(td->tokensLock);
    192            nssList_Remove(td->tokenList, token);
    193            NSSRWLock_UnlockWrite(td->tokensLock);
    194            PK11Slot_SetNSSToken(module->slots[i], NULL);
    195            (void)nssToken_Destroy(token); /* for the |td->tokenList| reference */
    196            (void)nssToken_Destroy(token); /* for our PK11Slot_GetNSSToken reference */
    197        }
    198    }
    199    NSSRWLock_LockWrite(td->tokensLock);
    200    nssListIterator_Destroy(td->tokens);
    201    td->tokens = nssList_CreateIterator(td->tokenList);
    202    NSSRWLock_UnlockWrite(td->tokensLock);
    203    return SECSuccess;
    204 }
    205 
    206 NSS_IMPLEMENT PRStatus
    207 STAN_Shutdown()
    208 {
    209    PRStatus status = PR_SUCCESS;
    210    if (g_default_trust_domain) {
    211        if (NSSTrustDomain_Destroy(g_default_trust_domain) == PR_SUCCESS) {
    212            g_default_trust_domain = NULL;
    213        } else {
    214            status = PR_FAILURE;
    215        }
    216    }
    217    if (g_default_crypto_context) {
    218        if (NSSCryptoContext_Destroy(g_default_crypto_context) == PR_SUCCESS) {
    219            g_default_crypto_context = NULL;
    220        } else {
    221            status = PR_FAILURE;
    222        }
    223    }
    224    return status;
    225 }
    226 
    227 /* this function should not be a hack; it will be needed in 4.0 (rename) */
    228 NSS_IMPLEMENT NSSItem *
    229 STAN_GetCertIdentifierFromDER(NSSArena *arenaOpt, NSSDER *der)
    230 {
    231    NSSItem *rvKey;
    232    SECItem secDER;
    233    SECItem secKey = { 0 };
    234    SECStatus secrv;
    235    PLArenaPool *arena;
    236 
    237    SECITEM_FROM_NSSITEM(&secDER, der);
    238 
    239    /* nss3 call uses nss3 arena's */
    240    arena = PORT_NewArena(256);
    241    if (!arena) {
    242        return NULL;
    243    }
    244    secrv = CERT_KeyFromDERCert(arena, &secDER, &secKey);
    245    if (secrv != SECSuccess) {
    246        PORT_FreeArena(arena, PR_FALSE);
    247        return NULL;
    248    }
    249    rvKey = nssItem_Create(arenaOpt, NULL, secKey.len, (void *)secKey.data);
    250    PORT_FreeArena(arena, PR_FALSE);
    251    return rvKey;
    252 }
    253 
    254 NSS_IMPLEMENT PRStatus
    255 nssPKIX509_GetIssuerAndSerialFromDER(NSSDER *der,
    256                                     NSSDER *issuer, NSSDER *serial)
    257 {
    258    SECItem derCert = { 0 };
    259    SECItem derIssuer = { 0 };
    260    SECItem derSerial = { 0 };
    261    SECStatus secrv;
    262    derCert.data = (unsigned char *)der->data;
    263    derCert.len = der->size;
    264    secrv = CERT_IssuerNameFromDERCert(&derCert, &derIssuer);
    265    if (secrv != SECSuccess) {
    266        return PR_FAILURE;
    267    }
    268    secrv = CERT_SerialNumberFromDERCert(&derCert, &derSerial);
    269    if (secrv != SECSuccess) {
    270        PORT_Free(derSerial.data);
    271        return PR_FAILURE;
    272    }
    273    issuer->data = derIssuer.data;
    274    issuer->size = derIssuer.len;
    275    serial->data = derSerial.data;
    276    serial->size = derSerial.len;
    277    return PR_SUCCESS;
    278 }
    279 
    280 static NSSItem *
    281 nss3certificate_getIdentifier(nssDecodedCert *dc)
    282 {
    283    NSSItem *rvID;
    284    CERTCertificate *c = (CERTCertificate *)dc->data;
    285    rvID = nssItem_Create(NULL, NULL, c->certKey.len, c->certKey.data);
    286    return rvID;
    287 }
    288 
    289 static void *
    290 nss3certificate_getIssuerIdentifier(nssDecodedCert *dc)
    291 {
    292    CERTCertificate *c = (CERTCertificate *)dc->data;
    293    return (void *)c->authKeyID;
    294 }
    295 
    296 static nssCertIDMatch
    297 nss3certificate_matchIdentifier(nssDecodedCert *dc, void *id)
    298 {
    299    CERTCertificate *c = (CERTCertificate *)dc->data;
    300    CERTAuthKeyID *authKeyID = (CERTAuthKeyID *)id;
    301    SECItem skid;
    302    nssCertIDMatch match = nssCertIDMatch_Unknown;
    303 
    304    /* keyIdentifier */
    305    if (authKeyID->keyID.len > 0 &&
    306        CERT_FindSubjectKeyIDExtension(c, &skid) == SECSuccess) {
    307        PRBool skiEqual;
    308        skiEqual = SECITEM_ItemsAreEqual(&authKeyID->keyID, &skid);
    309        PORT_Free(skid.data);
    310        if (skiEqual) {
    311            /* change the state to positive match, but keep going */
    312            match = nssCertIDMatch_Yes;
    313        } else {
    314            /* exit immediately on failure */
    315            return nssCertIDMatch_No;
    316        }
    317    }
    318 
    319    /* issuer/serial (treated as pair) */
    320    if (authKeyID->authCertIssuer) {
    321        SECItem *caName = NULL;
    322        SECItem *caSN = &authKeyID->authCertSerialNumber;
    323 
    324        caName = (SECItem *)CERT_GetGeneralNameByType(
    325            authKeyID->authCertIssuer,
    326            certDirectoryName, PR_TRUE);
    327        if (caName != NULL &&
    328            SECITEM_ItemsAreEqual(&c->derIssuer, caName) &&
    329            SECITEM_ItemsAreEqual(&c->serialNumber, caSN)) {
    330            match = nssCertIDMatch_Yes;
    331        } else {
    332            match = nssCertIDMatch_Unknown;
    333        }
    334    }
    335    return match;
    336 }
    337 
    338 static PRBool
    339 nss3certificate_isValidIssuer(nssDecodedCert *dc)
    340 {
    341    CERTCertificate *c = (CERTCertificate *)dc->data;
    342    unsigned int ignore;
    343    return CERT_IsCACert(c, &ignore);
    344 }
    345 
    346 static NSSUsage *
    347 nss3certificate_getUsage(nssDecodedCert *dc)
    348 {
    349    /* CERTCertificate *c = (CERTCertificate *)dc->data; */
    350    return NULL;
    351 }
    352 
    353 static PRBool
    354 nss3certificate_isValidAtTime(nssDecodedCert *dc, NSSTime *time)
    355 {
    356    SECCertTimeValidity validity;
    357    CERTCertificate *c = (CERTCertificate *)dc->data;
    358    validity = CERT_CheckCertValidTimes(c, NSSTime_GetPRTime(time), PR_TRUE);
    359    if (validity == secCertTimeValid) {
    360        return PR_TRUE;
    361    }
    362    return PR_FALSE;
    363 }
    364 
    365 static PRBool
    366 nss3certificate_isNewerThan(nssDecodedCert *dc, nssDecodedCert *cmpdc)
    367 {
    368    /* I know this isn't right, but this is glue code anyway */
    369    if (cmpdc->type == dc->type) {
    370        CERTCertificate *certa = (CERTCertificate *)dc->data;
    371        CERTCertificate *certb = (CERTCertificate *)cmpdc->data;
    372        return CERT_IsNewer(certa, certb);
    373    }
    374    return PR_FALSE;
    375 }
    376 
    377 /* CERT_FilterCertListByUsage */
    378 static PRBool
    379 nss3certificate_matchUsage(nssDecodedCert *dc, const NSSUsage *usage)
    380 {
    381    CERTCertificate *cc;
    382    unsigned int requiredKeyUsage = 0;
    383    unsigned int requiredCertType = 0;
    384    SECStatus secrv;
    385    PRBool match;
    386    PRBool ca;
    387 
    388    /* This is for NSS 3.3 functions that do not specify a usage */
    389    if (usage->anyUsage) {
    390        return PR_TRUE;
    391    }
    392    ca = usage->nss3lookingForCA;
    393    secrv = CERT_KeyUsageAndTypeForCertUsage(usage->nss3usage, ca,
    394                                             &requiredKeyUsage,
    395                                             &requiredCertType);
    396    if (secrv != SECSuccess) {
    397        return PR_FALSE;
    398    }
    399    cc = (CERTCertificate *)dc->data;
    400    secrv = CERT_CheckKeyUsage(cc, requiredKeyUsage);
    401    match = (PRBool)(secrv == SECSuccess);
    402    if (match) {
    403        unsigned int certType = 0;
    404        if (ca) {
    405            (void)CERT_IsCACert(cc, &certType);
    406        } else {
    407            certType = cc->nsCertType;
    408        }
    409        if (!(certType & requiredCertType)) {
    410            match = PR_FALSE;
    411        }
    412    }
    413    return match;
    414 }
    415 
    416 static PRBool
    417 nss3certificate_isTrustedForUsage(nssDecodedCert *dc, const NSSUsage *usage)
    418 {
    419    CERTCertificate *cc;
    420    PRBool ca;
    421    SECStatus secrv;
    422    unsigned int requiredFlags;
    423    unsigned int trustFlags;
    424    SECTrustType trustType;
    425    CERTCertTrust trust;
    426 
    427    /* This is for NSS 3.3 functions that do not specify a usage */
    428    if (usage->anyUsage) {
    429        return PR_FALSE; /* XXX is this right? */
    430    }
    431    cc = (CERTCertificate *)dc->data;
    432    ca = usage->nss3lookingForCA;
    433    if (!ca) {
    434        PRBool trusted;
    435        unsigned int failedFlags;
    436        secrv = cert_CheckLeafTrust(cc, usage->nss3usage,
    437                                    &failedFlags, &trusted);
    438        return secrv == SECSuccess && trusted;
    439    }
    440    secrv = CERT_TrustFlagsForCACertUsage(usage->nss3usage, &requiredFlags,
    441                                          &trustType);
    442    if (secrv != SECSuccess) {
    443        return PR_FALSE;
    444    }
    445    secrv = CERT_GetCertTrust(cc, &trust);
    446    if (secrv != SECSuccess) {
    447        return PR_FALSE;
    448    }
    449    if (trustType == trustTypeNone) {
    450        /* normally trustTypeNone usages accept any of the given trust bits
    451         * being on as acceptable. */
    452        trustFlags = trust.sslFlags | trust.emailFlags |
    453                     trust.objectSigningFlags;
    454    } else {
    455        trustFlags = SEC_GET_TRUST_FLAGS(&trust, trustType);
    456    }
    457    return (trustFlags & requiredFlags) == requiredFlags;
    458 }
    459 
    460 static NSSASCII7 *
    461 nss3certificate_getEmailAddress(nssDecodedCert *dc)
    462 {
    463    CERTCertificate *cc = (CERTCertificate *)dc->data;
    464    return (cc && cc->emailAddr && cc->emailAddr[0])
    465               ? (NSSASCII7 *)cc->emailAddr
    466               : NULL;
    467 }
    468 
    469 static PRStatus
    470 nss3certificate_getDERSerialNumber(nssDecodedCert *dc,
    471                                   NSSDER *serial, NSSArena *arena)
    472 {
    473    CERTCertificate *cc = (CERTCertificate *)dc->data;
    474    SECItem derSerial = { 0 };
    475    SECStatus secrv;
    476    secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
    477    if (secrv == SECSuccess) {
    478        (void)nssItem_Create(arena, serial, derSerial.len, derSerial.data);
    479        PORT_Free(derSerial.data);
    480        return PR_SUCCESS;
    481    }
    482    return PR_FAILURE;
    483 }
    484 
    485 /* Returns NULL if "encoding" cannot be decoded. */
    486 NSS_IMPLEMENT nssDecodedCert *
    487 nssDecodedPKIXCertificate_Create(
    488    NSSArena *arenaOpt,
    489    NSSDER *encoding)
    490 {
    491    nssDecodedCert *rvDC = NULL;
    492    CERTCertificate *cert;
    493    SECItem secDER;
    494 
    495    SECITEM_FROM_NSSITEM(&secDER, encoding);
    496    cert = CERT_DecodeDERCertificate(&secDER, PR_TRUE, NULL);
    497    if (cert) {
    498        rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
    499        if (rvDC) {
    500            rvDC->type = NSSCertificateType_PKIX;
    501            rvDC->data = (void *)cert;
    502            rvDC->getIdentifier = nss3certificate_getIdentifier;
    503            rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
    504            rvDC->matchIdentifier = nss3certificate_matchIdentifier;
    505            rvDC->isValidIssuer = nss3certificate_isValidIssuer;
    506            rvDC->getUsage = nss3certificate_getUsage;
    507            rvDC->isValidAtTime = nss3certificate_isValidAtTime;
    508            rvDC->isNewerThan = nss3certificate_isNewerThan;
    509            rvDC->matchUsage = nss3certificate_matchUsage;
    510            rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
    511            rvDC->getEmailAddress = nss3certificate_getEmailAddress;
    512            rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
    513        } else {
    514            CERT_DestroyCertificate(cert);
    515        }
    516    }
    517    return rvDC;
    518 }
    519 
    520 static nssDecodedCert *
    521 create_decoded_pkix_cert_from_nss3cert(
    522    NSSArena *arenaOpt,
    523    CERTCertificate *cc)
    524 {
    525    nssDecodedCert *rvDC = nss_ZNEW(arenaOpt, nssDecodedCert);
    526    if (rvDC) {
    527        rvDC->type = NSSCertificateType_PKIX;
    528        rvDC->data = (void *)cc;
    529        rvDC->getIdentifier = nss3certificate_getIdentifier;
    530        rvDC->getIssuerIdentifier = nss3certificate_getIssuerIdentifier;
    531        rvDC->matchIdentifier = nss3certificate_matchIdentifier;
    532        rvDC->isValidIssuer = nss3certificate_isValidIssuer;
    533        rvDC->getUsage = nss3certificate_getUsage;
    534        rvDC->isValidAtTime = nss3certificate_isValidAtTime;
    535        rvDC->isNewerThan = nss3certificate_isNewerThan;
    536        rvDC->matchUsage = nss3certificate_matchUsage;
    537        rvDC->isTrustedForUsage = nss3certificate_isTrustedForUsage;
    538        rvDC->getEmailAddress = nss3certificate_getEmailAddress;
    539        rvDC->getDERSerialNumber = nss3certificate_getDERSerialNumber;
    540    }
    541    return rvDC;
    542 }
    543 
    544 NSS_IMPLEMENT PRStatus
    545 nssDecodedPKIXCertificate_Destroy(nssDecodedCert *dc)
    546 {
    547    CERTCertificate *cert = (CERTCertificate *)dc->data;
    548 
    549    /* The decoder may only be half initialized (the case where we find we
    550     * could not decode the certificate). In this case, there is not cert to
    551     * free, just free the dc structure. */
    552    if (cert) {
    553        PRBool freeSlot = cert->ownSlot;
    554        PK11SlotInfo *slot = cert->slot;
    555        PLArenaPool *arena = cert->arena;
    556        /* zero cert before freeing. Any stale references to this cert
    557         * after this point will probably cause an exception.  */
    558        PORT_Memset(cert, 0, sizeof *cert);
    559        /* free the arena that contains the cert. */
    560        PORT_FreeArena(arena, PR_FALSE);
    561        if (slot && freeSlot) {
    562            PK11_FreeSlot(slot);
    563        }
    564    }
    565    nss_ZFreeIf(dc);
    566    return PR_SUCCESS;
    567 }
    568 
    569 /* see pk11cert.c:pk11_HandleTrustObject */
    570 static unsigned int
    571 get_nss3trust_from_nss4trust(nssTrustLevel t)
    572 {
    573    unsigned int rt = 0;
    574    if (t == nssTrustLevel_Trusted) {
    575        rt |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
    576    }
    577    if (t == nssTrustLevel_TrustedDelegator) {
    578        rt |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
    579    }
    580    if (t == nssTrustLevel_NotTrusted) {
    581        rt |= CERTDB_TERMINAL_RECORD;
    582    }
    583    if (t == nssTrustLevel_ValidDelegator) {
    584        rt |= CERTDB_VALID_CA;
    585    }
    586    return rt;
    587 }
    588 
    589 static CERTCertTrust *
    590 cert_trust_from_stan_trust(NSSTrust *t, PLArenaPool *arena)
    591 {
    592    CERTCertTrust *rvTrust;
    593    unsigned int client;
    594    if (!t) {
    595        return NULL;
    596    }
    597    rvTrust = PORT_ArenaAlloc(arena, sizeof(CERTCertTrust));
    598    if (!rvTrust)
    599        return NULL;
    600    rvTrust->sslFlags = get_nss3trust_from_nss4trust(t->serverAuth);
    601    client = get_nss3trust_from_nss4trust(t->clientAuth);
    602    if (client & (CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA)) {
    603        client &= ~(CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA);
    604        rvTrust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA;
    605    }
    606    rvTrust->sslFlags |= client;
    607    rvTrust->emailFlags = get_nss3trust_from_nss4trust(t->emailProtection);
    608    rvTrust->objectSigningFlags = get_nss3trust_from_nss4trust(t->codeSigning);
    609    return rvTrust;
    610 }
    611 
    612 PRBool
    613 nssTrust_HandleTrustForCERTCert(CERTCertificate *cert, CERTCertTrust *trustPtr)
    614 {
    615    NSSCertificate *c = cert->nssCertificate;
    616    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
    617    NSSTrust *t;
    618    t = nssTrustDomain_FindTrustForCertificate(td, c);
    619    if (t) {
    620        CERTCertTrust *rvTrust;
    621        rvTrust = cert_trust_from_stan_trust(t, cert->arena);
    622        nssTrust_Destroy(t);
    623        if (rvTrust) {
    624            *trustPtr = *rvTrust;
    625            return PR_TRUE;
    626        }
    627    }
    628    return PR_FALSE;
    629 }
    630 
    631 CERTCertTrust *
    632 nssTrust_GetCERTCertTrustForCert(NSSCertificate *c, CERTCertificate *cc)
    633 {
    634    CERTCertTrust *rvTrust = NULL;
    635    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
    636    NSSTrust *t;
    637    t = nssTrustDomain_FindTrustForCertificate(td, c);
    638    if (t) {
    639        rvTrust = cert_trust_from_stan_trust(t, cc->arena);
    640        if (!rvTrust) {
    641            nssTrust_Destroy(t);
    642            return NULL;
    643        }
    644        nssTrust_Destroy(t);
    645    } else {
    646        rvTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
    647        if (!rvTrust) {
    648            return NULL;
    649        }
    650        memset(rvTrust, 0, sizeof(*rvTrust));
    651    }
    652    if (NSSCertificate_IsPrivateKeyAvailable(c, NULL, NULL)) {
    653        rvTrust->sslFlags |= CERTDB_USER;
    654        rvTrust->emailFlags |= CERTDB_USER;
    655        rvTrust->objectSigningFlags |= CERTDB_USER;
    656    }
    657    return rvTrust;
    658 }
    659 
    660 static nssCryptokiInstance *
    661 get_cert_instance(NSSCertificate *c)
    662 {
    663    nssCryptokiObject *instance, **ci;
    664    nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
    665    if (!instances) {
    666        return NULL;
    667    }
    668    instance = NULL;
    669    for (ci = instances; *ci; ci++) {
    670        if (!instance) {
    671            instance = nssCryptokiObject_Clone(*ci);
    672        } else {
    673            /* This only really works for two instances...  But 3.4 can't
    674             * handle more anyway.  The logic is, if there are multiple
    675             * instances, prefer the one that is not internal (e.g., on
    676             * a hardware device.
    677             */
    678            if (PK11_IsInternal(instance->token->pk11slot)) {
    679                nssCryptokiObject_Destroy(instance);
    680                instance = nssCryptokiObject_Clone(*ci);
    681            }
    682        }
    683    }
    684    nssCryptokiObjectArray_Destroy(instances);
    685    return instance;
    686 }
    687 
    688 char *
    689 STAN_GetCERTCertificateNameForInstance(
    690    PLArenaPool *arenaOpt,
    691    NSSCertificate *c,
    692    nssCryptokiInstance *instance)
    693 {
    694    NSSCryptoContext *context = c->object.cryptoContext;
    695    PRStatus nssrv;
    696    int nicklen, tokenlen, len;
    697    NSSUTF8 *tokenName = NULL;
    698    NSSUTF8 *stanNick = NULL;
    699    char *nickname = NULL;
    700    char *nick;
    701 
    702    if (instance) {
    703        stanNick = instance->label;
    704    } else if (context) {
    705        stanNick = c->object.tempName;
    706    }
    707    if (stanNick) {
    708        /* fill other fields needed by NSS3 functions using CERTCertificate */
    709        if (instance && (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||
    710                         PORT_Strchr(stanNick, ':') != NULL)) {
    711            tokenName = nssToken_GetName(instance->token);
    712            tokenlen = nssUTF8_Size(tokenName, &nssrv);
    713        } else {
    714            /* don't use token name for internal slot; 3.3 didn't */
    715            tokenlen = 0;
    716        }
    717        nicklen = nssUTF8_Size(stanNick, &nssrv);
    718        len = tokenlen + nicklen;
    719        if (arenaOpt) {
    720            nickname = PORT_ArenaAlloc(arenaOpt, len);
    721        } else {
    722            nickname = PORT_Alloc(len);
    723        }
    724        nick = nickname;
    725        if (tokenName) {
    726            memcpy(nick, tokenName, tokenlen - 1);
    727            nick += tokenlen - 1;
    728            *nick++ = ':';
    729        }
    730        memcpy(nick, stanNick, nicklen - 1);
    731        nickname[len - 1] = '\0';
    732    }
    733    return nickname;
    734 }
    735 
    736 char *
    737 STAN_GetCERTCertificateName(PLArenaPool *arenaOpt, NSSCertificate *c)
    738 {
    739    char *result;
    740    nssCryptokiInstance *instance = get_cert_instance(c);
    741    /* It's OK to call this function, even if instance is NULL */
    742    result = STAN_GetCERTCertificateNameForInstance(arenaOpt, c, instance);
    743    if (instance)
    744        nssCryptokiObject_Destroy(instance);
    745    return result;
    746 }
    747 
    748 static void
    749 fill_CERTCertificateFields(NSSCertificate *c, CERTCertificate *cc, PRBool forced)
    750 {
    751    CERTCertTrust *trust = NULL;
    752    NSSTrust *nssTrust;
    753    NSSCryptoContext *context = c->object.cryptoContext;
    754    nssCryptokiInstance *instance;
    755    NSSUTF8 *stanNick = NULL;
    756 
    757    /* We are holding the base class object's lock on entry of this function
    758     * This lock protects writes to fields of the CERTCertificate .
    759     * It is also needed by some functions to compute values such as trust.
    760     */
    761    instance = get_cert_instance(c);
    762 
    763    if (instance) {
    764        stanNick = instance->label;
    765    } else if (context) {
    766        stanNick = c->object.tempName;
    767    }
    768    /* fill other fields needed by NSS3 functions using CERTCertificate */
    769    if ((!cc->nickname && stanNick) || forced) {
    770        PRStatus nssrv;
    771        int nicklen, tokenlen, len;
    772        NSSUTF8 *tokenName = NULL;
    773        char *nick;
    774        if (instance &&
    775            (!PK11_IsInternalKeySlot(instance->token->pk11slot) ||
    776             (stanNick && PORT_Strchr(stanNick, ':') != NULL))) {
    777            tokenName = nssToken_GetName(instance->token);
    778            tokenlen = nssUTF8_Size(tokenName, &nssrv);
    779        } else {
    780            /* don't use token name for internal slot; 3.3 didn't */
    781            tokenlen = 0;
    782        }
    783        if (stanNick) {
    784            nicklen = nssUTF8_Size(stanNick, &nssrv);
    785            len = tokenlen + nicklen;
    786            nick = PORT_ArenaAlloc(cc->arena, len);
    787            if (tokenName) {
    788                memcpy(nick, tokenName, tokenlen - 1);
    789                nick[tokenlen - 1] = ':';
    790                memcpy(nick + tokenlen, stanNick, nicklen - 1);
    791            } else {
    792                memcpy(nick, stanNick, nicklen - 1);
    793            }
    794            nick[len - 1] = '\0';
    795            cc->nickname = nick;
    796        } else {
    797            cc->nickname = NULL;
    798        }
    799    }
    800    if (context) {
    801        /* trust */
    802        nssTrust = nssCryptoContext_FindTrustForCertificate(context, c);
    803        if (!nssTrust) {
    804            /* chicken and egg issue:
    805             *
    806             * c->issuer and c->serial are empty at this point, but
    807             * nssTrustDomain_FindTrustForCertificate use them to look up
    808             * up the trust object, so we point them to cc->derIssuer and
    809             * cc->serialNumber.
    810             *
    811             * Our caller will fill these in with proper arena copies when we
    812             * return. */
    813            c->issuer.data = cc->derIssuer.data;
    814            c->issuer.size = cc->derIssuer.len;
    815            c->serial.data = cc->serialNumber.data;
    816            c->serial.size = cc->serialNumber.len;
    817            nssTrust = nssTrustDomain_FindTrustForCertificate(context->td, c);
    818        }
    819        if (nssTrust) {
    820            trust = cert_trust_from_stan_trust(nssTrust, cc->arena);
    821            if (trust) {
    822                /* we should destroy cc->trust before replacing it, but it's
    823                   allocated in cc->arena, so memory growth will occur on each
    824                   refresh */
    825                CERT_LockCertTrust(cc);
    826                cc->trust = trust;
    827                CERT_UnlockCertTrust(cc);
    828            }
    829            nssTrust_Destroy(nssTrust);
    830        }
    831    } else if (instance) {
    832        /* slot */
    833        if (cc->slot != instance->token->pk11slot) {
    834            if (cc->slot) {
    835                PK11_FreeSlot(cc->slot);
    836            }
    837            cc->slot = PK11_ReferenceSlot(instance->token->pk11slot);
    838        }
    839        cc->ownSlot = PR_TRUE;
    840        /* pkcs11ID */
    841        cc->pkcs11ID = instance->handle;
    842        /* trust */
    843        trust = nssTrust_GetCERTCertTrustForCert(c, cc);
    844        if (trust) {
    845            /* we should destroy cc->trust before replacing it, but it's
    846               allocated in cc->arena, so memory growth will occur on each
    847               refresh */
    848            CERT_LockCertTrust(cc);
    849            cc->trust = trust;
    850            CERT_UnlockCertTrust(cc);
    851        }
    852        /* Read the distrust fields from a nssckbi/builtins certificate and
    853         * fill the fields in CERTCertificate structure when any valid date
    854         * is found. */
    855        if (PK11_IsReadOnly(cc->slot) && PK11_HasRootCerts(cc->slot)) {
    856            /* The values are hard-coded and readonly. Read just once. */
    857            if (cc->distrust == NULL) {
    858                CERTCertDistrust distrustModel;
    859                SECItem model = { siUTCTime, NULL, 0 };
    860                distrustModel.serverDistrustAfter = model;
    861                distrustModel.emailDistrustAfter = model;
    862                SECStatus rServer = PK11_ReadAttribute(
    863                    cc->slot, cc->pkcs11ID, CKA_NSS_SERVER_DISTRUST_AFTER,
    864                    cc->arena, &distrustModel.serverDistrustAfter);
    865                SECStatus rEmail = PK11_ReadAttribute(
    866                    cc->slot, cc->pkcs11ID, CKA_NSS_EMAIL_DISTRUST_AFTER,
    867                    cc->arena, &distrustModel.emailDistrustAfter);
    868                /* Only allocate the Distrust structure if a valid date is found.
    869                 * The result length of a encoded valid timestamp is exactly 13 */
    870                const unsigned int kDistrustFieldSize = 13;
    871                if ((rServer == SECSuccess && rEmail == SECSuccess) &&
    872                    (distrustModel.serverDistrustAfter.len == kDistrustFieldSize ||
    873                     distrustModel.emailDistrustAfter.len == kDistrustFieldSize)) {
    874                    CERTCertDistrust *tmpPtr = PORT_ArenaAlloc(
    875                        cc->arena, sizeof(CERTCertDistrust));
    876                    PORT_Memcpy(tmpPtr, &distrustModel,
    877                                sizeof(CERTCertDistrust));
    878                    cc->distrust = tmpPtr;
    879                }
    880            }
    881        }
    882    }
    883    if (instance) {
    884        nssCryptokiObject_Destroy(instance);
    885    }
    886    /* database handle is now the trust domain */
    887    cc->dbhandle = c->object.trustDomain;
    888    /* subjectList ? */
    889    /* istemp and isperm are supported in NSS 3.4 */
    890    CERT_LockCertTempPerm(cc);
    891    cc->istemp = PR_FALSE; /* CERT_NewTemp will override this */
    892    cc->isperm = PR_TRUE;  /* by default */
    893    /* pointer back */
    894    cc->nssCertificate = c;
    895    CERT_UnlockCertTempPerm(cc);
    896    if (trust) {
    897        /* force the cert type to be recomputed to include trust info */
    898        PRUint32 nsCertType = cert_ComputeCertType(cc);
    899 
    900        /* Assert that it is safe to cast &cc->nsCertType to "PRInt32 *" */
    901        PORT_Assert(sizeof(cc->nsCertType) == sizeof(PRInt32));
    902        PR_ATOMIC_SET((PRInt32 *)&cc->nsCertType, nsCertType);
    903    }
    904 }
    905 
    906 static CERTCertificate *
    907 stan_GetCERTCertificate(NSSCertificate *c, PRBool forceUpdate)
    908 {
    909    nssDecodedCert *dc = NULL;
    910    CERTCertificate *cc = NULL;
    911    CERTCertTrust certTrust;
    912 
    913    /* make sure object does not go away until we finish */
    914    nssPKIObject_AddRef(&c->object);
    915    nssPKIObject_Lock(&c->object);
    916 
    917    dc = c->decoding;
    918    if (!dc) {
    919        dc = nssDecodedPKIXCertificate_Create(NULL, &c->encoding);
    920        if (!dc) {
    921            goto loser;
    922        }
    923        cc = (CERTCertificate *)dc->data;
    924        PORT_Assert(cc); /* software error */
    925        if (!cc) {
    926            nssDecodedPKIXCertificate_Destroy(dc);
    927            nss_SetError(NSS_ERROR_INTERNAL_ERROR);
    928            goto loser;
    929        }
    930        PORT_Assert(!c->decoding);
    931        if (!c->decoding) {
    932            c->decoding = dc;
    933        } else {
    934            /* this should never happen. Fail. */
    935            nssDecodedPKIXCertificate_Destroy(dc);
    936            nss_SetError(NSS_ERROR_INTERNAL_ERROR);
    937            goto loser;
    938        }
    939    }
    940    cc = (CERTCertificate *)dc->data;
    941    PORT_Assert(cc);
    942    if (!cc) {
    943        nss_SetError(NSS_ERROR_INTERNAL_ERROR);
    944        goto loser;
    945    }
    946    CERT_LockCertTempPerm(cc);
    947    NSSCertificate *nssCert = cc->nssCertificate;
    948    CERT_UnlockCertTempPerm(cc);
    949    if (!nssCert || forceUpdate) {
    950        fill_CERTCertificateFields(c, cc, forceUpdate);
    951    } else if (CERT_GetCertTrust(cc, &certTrust) != SECSuccess) {
    952        CERTCertTrust *trust;
    953        if (!c->object.cryptoContext) {
    954            /* If it's a perm cert, it might have been stored before the
    955             * trust, so look for the trust again.
    956             */
    957            trust = nssTrust_GetCERTCertTrustForCert(c, cc);
    958        } else {
    959            /* If it's a temp cert, it might have been stored before the
    960             * builtin trust module is loaded, so look for the trust
    961             * again, but don't set the empty trust if it is not found.
    962             */
    963            NSSTrust *t = nssTrustDomain_FindTrustForCertificate(c->object.cryptoContext->td, c);
    964            if (!t) {
    965                goto loser;
    966            }
    967            trust = cert_trust_from_stan_trust(t, cc->arena);
    968            nssTrust_Destroy(t);
    969            if (!trust) {
    970                goto loser;
    971            }
    972        }
    973 
    974        CERT_LockCertTrust(cc);
    975        cc->trust = trust;
    976        CERT_UnlockCertTrust(cc);
    977    }
    978 
    979 loser:
    980    nssPKIObject_Unlock(&c->object);
    981    nssPKIObject_Destroy(&c->object);
    982    return cc;
    983 }
    984 
    985 NSS_IMPLEMENT CERTCertificate *
    986 STAN_ForceCERTCertificateUpdate(NSSCertificate *c)
    987 {
    988    if (c->decoding) {
    989        return stan_GetCERTCertificate(c, PR_TRUE);
    990    }
    991    return NULL;
    992 }
    993 
    994 NSS_IMPLEMENT CERTCertificate *
    995 STAN_GetCERTCertificate(NSSCertificate *c)
    996 {
    997    return stan_GetCERTCertificate(c, PR_FALSE);
    998 }
    999 /*
   1000 * many callers of STAN_GetCERTCertificate() intend that
   1001 * the CERTCertificate returned inherits the reference to the
   1002 * NSSCertificate. For these callers it's convenient to have
   1003 * this function 'own' the reference and either return a valid
   1004 * CERTCertificate structure which inherits the reference or
   1005 * destroy the reference to NSSCertificate and returns NULL.
   1006 */
   1007 NSS_IMPLEMENT CERTCertificate *
   1008 STAN_GetCERTCertificateOrRelease(NSSCertificate *c)
   1009 {
   1010    CERTCertificate *nss3cert = stan_GetCERTCertificate(c, PR_FALSE);
   1011    if (!nss3cert) {
   1012        nssCertificate_Destroy(c);
   1013    }
   1014    return nss3cert;
   1015 }
   1016 
   1017 static nssTrustLevel
   1018 get_stan_trust(unsigned int t, PRBool isClientAuth)
   1019 {
   1020    if (isClientAuth) {
   1021        if (t & CERTDB_TRUSTED_CLIENT_CA) {
   1022            return nssTrustLevel_TrustedDelegator;
   1023        }
   1024    } else {
   1025        if (t & CERTDB_TRUSTED_CA || t & CERTDB_NS_TRUSTED_CA) {
   1026            return nssTrustLevel_TrustedDelegator;
   1027        }
   1028    }
   1029    if (t & CERTDB_TRUSTED) {
   1030        return nssTrustLevel_Trusted;
   1031    }
   1032    if (t & CERTDB_TERMINAL_RECORD) {
   1033        return nssTrustLevel_NotTrusted;
   1034    }
   1035    if (t & CERTDB_VALID_CA) {
   1036        return nssTrustLevel_ValidDelegator;
   1037    }
   1038    return nssTrustLevel_MustVerify;
   1039 }
   1040 
   1041 NSS_EXTERN NSSCertificate *
   1042 STAN_GetNSSCertificate(CERTCertificate *cc)
   1043 {
   1044    NSSCertificate *c;
   1045    nssCryptokiInstance *instance;
   1046    nssPKIObject *pkiob;
   1047    NSSArena *arena;
   1048    CERT_LockCertTempPerm(cc);
   1049    c = cc->nssCertificate;
   1050    CERT_UnlockCertTempPerm(cc);
   1051    if (c) {
   1052        return c;
   1053    }
   1054    /* i don't think this should happen.  but if it can, need to create
   1055     * NSSCertificate from CERTCertificate values here.  */
   1056    /* Yup, it can happen. */
   1057    arena = NSSArena_Create();
   1058    if (!arena) {
   1059        return NULL;
   1060    }
   1061    c = nss_ZNEW(arena, NSSCertificate);
   1062    if (!c) {
   1063        nssArena_Destroy(arena);
   1064        return NULL;
   1065    }
   1066    NSSITEM_FROM_SECITEM(&c->encoding, &cc->derCert);
   1067    c->type = NSSCertificateType_PKIX;
   1068    pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKIMonitor);
   1069    if (!pkiob) {
   1070        nssArena_Destroy(arena);
   1071        return NULL;
   1072    }
   1073    c->object = *pkiob;
   1074    nssItem_Create(arena,
   1075                   &c->issuer, cc->derIssuer.len, cc->derIssuer.data);
   1076    nssItem_Create(arena,
   1077                   &c->subject, cc->derSubject.len, cc->derSubject.data);
   1078    /* CERTCertificate stores serial numbers decoded.  I need the DER
   1079     * here.  sigh.
   1080     */
   1081    SECItem derSerial;
   1082    SECStatus secrv;
   1083    secrv = CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
   1084    if (secrv == SECFailure) {
   1085        nssArena_Destroy(arena);
   1086        return NULL;
   1087    }
   1088    nssItem_Create(arena, &c->serial, derSerial.len, derSerial.data);
   1089    PORT_Free(derSerial.data);
   1090 
   1091    if (cc->emailAddr && cc->emailAddr[0]) {
   1092        c->email = nssUTF8_Create(arena,
   1093                                  nssStringType_PrintableString,
   1094                                  (NSSUTF8 *)cc->emailAddr,
   1095                                  PORT_Strlen(cc->emailAddr));
   1096    }
   1097    if (cc->slot) {
   1098        instance = nss_ZNEW(arena, nssCryptokiInstance);
   1099        if (!instance) {
   1100            nssArena_Destroy(arena);
   1101            return NULL;
   1102        }
   1103        instance->token = PK11Slot_GetNSSToken(cc->slot);
   1104        if (!instance->token) {
   1105            nssArena_Destroy(arena);
   1106            return NULL;
   1107        }
   1108        instance->handle = cc->pkcs11ID;
   1109        instance->isTokenObject = PR_TRUE;
   1110        if (cc->nickname) {
   1111            instance->label = nssUTF8_Create(arena,
   1112                                             nssStringType_UTF8String,
   1113                                             (NSSUTF8 *)cc->nickname,
   1114                                             PORT_Strlen(cc->nickname));
   1115        }
   1116        nssPKIObject_AddInstance(&c->object, instance);
   1117    }
   1118    c->decoding = create_decoded_pkix_cert_from_nss3cert(NULL, cc);
   1119    CERT_LockCertTempPerm(cc);
   1120    cc->nssCertificate = c;
   1121    CERT_UnlockCertTempPerm(cc);
   1122    return c;
   1123 }
   1124 
   1125 static NSSToken *
   1126 stan_GetTrustToken(
   1127    NSSCertificate *c)
   1128 {
   1129    NSSToken *ttok = NULL;
   1130    NSSToken *rtok = NULL;
   1131    NSSToken *tok = NULL;
   1132    nssCryptokiObject **ip;
   1133    nssCryptokiObject **instances = nssPKIObject_GetInstances(&c->object);
   1134    if (!instances) {
   1135        return PR_FALSE;
   1136    }
   1137    for (ip = instances; *ip; ip++) {
   1138        nssCryptokiObject *instance = *ip;
   1139        nssCryptokiObject *to =
   1140            nssToken_FindTrustForCertificate(instance->token, NULL,
   1141                                             &c->encoding, &c->issuer, &c->serial,
   1142                                             nssTokenSearchType_TokenOnly);
   1143        NSSToken *ctok = instance->token;
   1144        PRBool ro = PK11_IsReadOnly(ctok->pk11slot);
   1145 
   1146        if (to) {
   1147            nssCryptokiObject_Destroy(to);
   1148            ttok = ctok;
   1149            if (!ro) {
   1150                break;
   1151            }
   1152        } else {
   1153            if (!rtok && ro) {
   1154                rtok = ctok;
   1155            }
   1156            if (!tok && !ro) {
   1157                tok = ctok;
   1158            }
   1159        }
   1160    }
   1161    nssCryptokiObjectArray_Destroy(instances);
   1162    return ttok ? ttok : (tok ? tok : rtok);
   1163 }
   1164 
   1165 NSS_EXTERN PRStatus
   1166 STAN_ChangeCertTrust(CERTCertificate *cc, CERTCertTrust *trust)
   1167 {
   1168    PRStatus nssrv;
   1169    NSSCertificate *c = STAN_GetNSSCertificate(cc);
   1170    NSSToken *tok;
   1171    NSSTrustDomain *td;
   1172    NSSTrust *nssTrust;
   1173    NSSArena *arena;
   1174    CERTCertTrust *oldTrust;
   1175    CERTCertTrust *newTrust;
   1176    nssListIterator *tokens;
   1177    PRBool moving_object;
   1178    nssCryptokiObject *newInstance;
   1179    nssPKIObject *pkiob;
   1180 
   1181    if (c == NULL) {
   1182        return PR_FAILURE;
   1183    }
   1184    oldTrust = nssTrust_GetCERTCertTrustForCert(c, cc);
   1185    if (oldTrust) {
   1186        if (memcmp(oldTrust, trust, sizeof(CERTCertTrust)) == 0) {
   1187            /* ... and the new trust is no different, done) */
   1188            return PR_SUCCESS;
   1189        } else {
   1190            /* take over memory already allocated in cc's arena */
   1191            newTrust = oldTrust;
   1192        }
   1193    } else {
   1194        newTrust = PORT_ArenaAlloc(cc->arena, sizeof(CERTCertTrust));
   1195    }
   1196    memcpy(newTrust, trust, sizeof(CERTCertTrust));
   1197    CERT_LockCertTrust(cc);
   1198    cc->trust = newTrust;
   1199    CERT_UnlockCertTrust(cc);
   1200    /* Set the NSSCerticate's trust */
   1201    arena = nssArena_Create();
   1202    if (!arena)
   1203        return PR_FAILURE;
   1204    nssTrust = nss_ZNEW(arena, NSSTrust);
   1205    if (!nssTrust) {
   1206        nssArena_Destroy(arena);
   1207        return PR_FAILURE;
   1208    }
   1209    pkiob = nssPKIObject_Create(arena, NULL, cc->dbhandle, NULL, nssPKILock);
   1210    if (!pkiob) {
   1211        nssArena_Destroy(arena);
   1212        return PR_FAILURE;
   1213    }
   1214    nssTrust->object = *pkiob;
   1215    nssTrust->certificate = c;
   1216    nssTrust->serverAuth = get_stan_trust(trust->sslFlags, PR_FALSE);
   1217    nssTrust->clientAuth = get_stan_trust(trust->sslFlags, PR_TRUE);
   1218    nssTrust->emailProtection = get_stan_trust(trust->emailFlags, PR_FALSE);
   1219    nssTrust->codeSigning = get_stan_trust(trust->objectSigningFlags, PR_FALSE);
   1220    nssTrust->stepUpApproved =
   1221        (PRBool)(trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
   1222    if (c->object.cryptoContext != NULL) {
   1223        /* The cert is in a context, set the trust there */
   1224        NSSCryptoContext *cctx = c->object.cryptoContext;
   1225        nssrv = nssCryptoContext_ImportTrust(cctx, nssTrust);
   1226        if (nssrv != PR_SUCCESS) {
   1227            goto done;
   1228        }
   1229        if (c->object.numInstances == 0) {
   1230            /* The context is the only instance, finished */
   1231            goto done;
   1232        }
   1233    }
   1234    td = STAN_GetDefaultTrustDomain();
   1235    tok = stan_GetTrustToken(c);
   1236    moving_object = PR_FALSE;
   1237    if (tok && PK11_IsReadOnly(tok->pk11slot)) {
   1238        NSSRWLock_LockRead(td->tokensLock);
   1239        tokens = nssList_CreateIterator(td->tokenList);
   1240        if (!tokens) {
   1241            nssrv = PR_FAILURE;
   1242            NSSRWLock_UnlockRead(td->tokensLock);
   1243            goto done;
   1244        }
   1245        for (tok = (NSSToken *)nssListIterator_Start(tokens);
   1246             tok != (NSSToken *)NULL;
   1247             tok = (NSSToken *)nssListIterator_Next(tokens)) {
   1248            if (!PK11_IsReadOnly(tok->pk11slot))
   1249                break;
   1250        }
   1251        nssListIterator_Finish(tokens);
   1252        nssListIterator_Destroy(tokens);
   1253        NSSRWLock_UnlockRead(td->tokensLock);
   1254        moving_object = PR_TRUE;
   1255    }
   1256    if (tok) {
   1257        if (moving_object) {
   1258            /* this is kind of hacky.  the softoken needs the cert
   1259             * object in order to store trust.  forcing it to be perm
   1260             */
   1261            NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
   1262            NSSASCII7 *email = NULL;
   1263 
   1264            if (PK11_IsInternal(tok->pk11slot)) {
   1265                email = c->email;
   1266            }
   1267            newInstance = nssToken_ImportCertificate(tok, NULL,
   1268                                                     NSSCertificateType_PKIX,
   1269                                                     &c->id,
   1270                                                     nickname,
   1271                                                     &c->encoding,
   1272                                                     &c->issuer,
   1273                                                     &c->subject,
   1274                                                     &c->serial,
   1275                                                     email,
   1276                                                     PR_TRUE);
   1277            nss_ZFreeIf(nickname);
   1278            nickname = NULL;
   1279            if (!newInstance) {
   1280                nssrv = PR_FAILURE;
   1281                goto done;
   1282            }
   1283            nssPKIObject_AddInstance(&c->object, newInstance);
   1284        }
   1285        newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
   1286                                           &c->issuer, &c->serial,
   1287                                           nssTrust->serverAuth,
   1288                                           nssTrust->clientAuth,
   1289                                           nssTrust->codeSigning,
   1290                                           nssTrust->emailProtection,
   1291                                           nssTrust->stepUpApproved, PR_TRUE);
   1292        /* If the selected token can't handle trust, dump the trust on
   1293         * the internal token */
   1294        if (!newInstance && !PK11_IsInternalKeySlot(tok->pk11slot)) {
   1295            PK11SlotInfo *slot = PK11_GetInternalKeySlot();
   1296            NSSUTF8 *nickname = nssCertificate_GetNickname(c, NULL);
   1297            NSSASCII7 *email = c->email;
   1298            tok = PK11Slot_GetNSSToken(slot);
   1299            PK11_FreeSlot(slot);
   1300            if (!tok) {
   1301                nssrv = PR_FAILURE;
   1302                goto done;
   1303            }
   1304 
   1305            newInstance = nssToken_ImportCertificate(tok, NULL,
   1306                                                     NSSCertificateType_PKIX,
   1307                                                     &c->id,
   1308                                                     nickname,
   1309                                                     &c->encoding,
   1310                                                     &c->issuer,
   1311                                                     &c->subject,
   1312                                                     &c->serial,
   1313                                                     email,
   1314                                                     PR_TRUE);
   1315            nss_ZFreeIf(nickname);
   1316            nickname = NULL;
   1317            if (!newInstance) {
   1318                (void)nssToken_Destroy(tok);
   1319                nssrv = PR_FAILURE;
   1320                goto done;
   1321            }
   1322            nssPKIObject_AddInstance(&c->object, newInstance);
   1323            newInstance = nssToken_ImportTrust(tok, NULL, &c->encoding,
   1324                                               &c->issuer, &c->serial,
   1325                                               nssTrust->serverAuth,
   1326                                               nssTrust->clientAuth,
   1327                                               nssTrust->codeSigning,
   1328                                               nssTrust->emailProtection,
   1329                                               nssTrust->stepUpApproved, PR_TRUE);
   1330            (void)nssToken_Destroy(tok);
   1331        }
   1332        if (newInstance) {
   1333            nssCryptokiObject_Destroy(newInstance);
   1334            nssrv = PR_SUCCESS;
   1335        } else {
   1336            nssrv = PR_FAILURE;
   1337        }
   1338    } else {
   1339        nssrv = PR_FAILURE;
   1340    }
   1341 done:
   1342    (void)nssTrust_Destroy(nssTrust);
   1343    return nssrv;
   1344 }
   1345 
   1346 /*
   1347 ** Delete trust objects matching the given slot.
   1348 ** Returns error if a device fails to delete.
   1349 **
   1350 ** This function has the side effect of moving the
   1351 ** surviving entries to the front of the object list
   1352 ** and nullifying the rest.
   1353 */
   1354 static PRStatus
   1355 DeleteCertTrustMatchingSlot(PK11SlotInfo *pk11slot, nssPKIObject *tObject)
   1356 {
   1357    int numNotDestroyed = 0; /* the ones skipped plus the failures */
   1358    int failureCount = 0;    /* actual deletion failures by devices */
   1359    unsigned int index;
   1360 
   1361    nssPKIObject_AddRef(tObject);
   1362    nssPKIObject_Lock(tObject);
   1363    /* Keep going even if a module fails to delete. */
   1364    for (index = 0; index < tObject->numInstances; index++) {
   1365        nssCryptokiObject *instance = tObject->instances[index];
   1366        if (!instance) {
   1367            continue;
   1368        }
   1369 
   1370        /* ReadOnly and not matched treated the same */
   1371        if (PK11_IsReadOnly(instance->token->pk11slot) ||
   1372            pk11slot != instance->token->pk11slot) {
   1373            tObject->instances[numNotDestroyed++] = instance;
   1374            continue;
   1375        }
   1376 
   1377        /* Here we have found a matching one */
   1378        tObject->instances[index] = NULL;
   1379        if (nssToken_DeleteStoredObject(instance) == PR_SUCCESS) {
   1380            nssCryptokiObject_Destroy(instance);
   1381        } else {
   1382            tObject->instances[numNotDestroyed++] = instance;
   1383            failureCount++;
   1384        }
   1385    }
   1386    if (numNotDestroyed == 0) {
   1387        nss_ZFreeIf(tObject->instances);
   1388        tObject->numInstances = 0;
   1389    } else {
   1390        tObject->numInstances = numNotDestroyed;
   1391    }
   1392 
   1393    nssPKIObject_Unlock(tObject);
   1394    nssPKIObject_Destroy(tObject);
   1395 
   1396    return failureCount == 0 ? PR_SUCCESS : PR_FAILURE;
   1397 }
   1398 
   1399 /*
   1400 ** Delete trust objects matching the slot of the given certificate.
   1401 ** Returns an error if any device fails to delete.
   1402 */
   1403 NSS_EXTERN PRStatus
   1404 STAN_DeleteCertTrustMatchingSlot(NSSCertificate *c)
   1405 {
   1406    PRStatus nssrv = PR_SUCCESS;
   1407 
   1408    unsigned int i;
   1409    nssPKIObject *tobject = NULL;
   1410    nssPKIObject *cobject = &c->object;
   1411 
   1412    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
   1413    NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c);
   1414    if (!nssTrust) {
   1415        return PR_FAILURE;
   1416    }
   1417 
   1418    tobject = &nssTrust->object;
   1419 
   1420    /* Iterate through the cert and trust object instances looking for
   1421     * those with matching pk11 slots to delete. Even if some device
   1422     * can't delete we keep going. Keeping a status variable for the
   1423     * loop so that once it's failed the other gets set.
   1424     */
   1425    NSSRWLock_LockRead(td->tokensLock);
   1426    nssPKIObject_AddRef(cobject);
   1427    nssPKIObject_Lock(cobject);
   1428    for (i = 0; i < cobject->numInstances; i++) {
   1429        nssCryptokiObject *cInstance = cobject->instances[i];
   1430        if (cInstance && !PK11_IsReadOnly(cInstance->token->pk11slot)) {
   1431            PRStatus status;
   1432            if (!tobject->numInstances || !tobject->instances)
   1433                continue;
   1434            status = DeleteCertTrustMatchingSlot(cInstance->token->pk11slot, tobject);
   1435            if (status == PR_FAILURE) {
   1436                /* set the outer one but keep going */
   1437                nssrv = PR_FAILURE;
   1438            }
   1439        }
   1440    }
   1441    nssTrust_Destroy(nssTrust);
   1442    nssPKIObject_Unlock(cobject);
   1443    nssPKIObject_Destroy(cobject);
   1444    NSSRWLock_UnlockRead(td->tokensLock);
   1445    return nssrv;
   1446 }
   1447 
   1448 /* CERT_TraversePermCertsForSubject */
   1449 NSS_IMPLEMENT PRStatus
   1450 nssTrustDomain_TraverseCertificatesBySubject(
   1451    NSSTrustDomain *td,
   1452    NSSDER *subject,
   1453    PRStatus (*callback)(NSSCertificate *c, void *arg),
   1454    void *arg)
   1455 {
   1456    PRStatus nssrv = PR_SUCCESS;
   1457    NSSArena *tmpArena;
   1458    NSSCertificate **subjectCerts;
   1459    NSSCertificate *c;
   1460    PRIntn i;
   1461    tmpArena = NSSArena_Create();
   1462    if (!tmpArena) {
   1463        return PR_FAILURE;
   1464    }
   1465    subjectCerts = NSSTrustDomain_FindCertificatesBySubject(td, subject, NULL,
   1466                                                            0, tmpArena);
   1467    if (subjectCerts) {
   1468        for (i = 0, c = subjectCerts[i]; c; i++) {
   1469            nssrv = callback(c, arg);
   1470            if (nssrv != PR_SUCCESS)
   1471                break;
   1472        }
   1473    }
   1474    nssArena_Destroy(tmpArena);
   1475    return nssrv;
   1476 }
   1477 
   1478 /* CERT_TraversePermCertsForNickname */
   1479 NSS_IMPLEMENT PRStatus
   1480 nssTrustDomain_TraverseCertificatesByNickname(
   1481    NSSTrustDomain *td,
   1482    NSSUTF8 *nickname,
   1483    PRStatus (*callback)(NSSCertificate *c, void *arg),
   1484    void *arg)
   1485 {
   1486    PRStatus nssrv = PR_SUCCESS;
   1487    NSSArena *tmpArena;
   1488    NSSCertificate **nickCerts;
   1489    NSSCertificate *c;
   1490    PRIntn i;
   1491    tmpArena = NSSArena_Create();
   1492    if (!tmpArena) {
   1493        return PR_FAILURE;
   1494    }
   1495    nickCerts = NSSTrustDomain_FindCertificatesByNickname(td, nickname, NULL,
   1496                                                          0, tmpArena);
   1497    if (nickCerts) {
   1498        for (i = 0, c = nickCerts[i]; c; i++) {
   1499            nssrv = callback(c, arg);
   1500            if (nssrv != PR_SUCCESS)
   1501                break;
   1502        }
   1503    }
   1504    nssArena_Destroy(tmpArena);
   1505    return nssrv;
   1506 }
   1507 
   1508 static void
   1509 cert_dump_iter(const void *k, void *v, void *a)
   1510 {
   1511    NSSCertificate *c = (NSSCertificate *)k;
   1512    CERTCertificate *cert = STAN_GetCERTCertificate(c);
   1513    printf("[%2d] \"%s\"\n", c->object.refCount, cert->subjectName);
   1514 }
   1515 
   1516 void
   1517 nss_DumpCertificateCacheInfo()
   1518 {
   1519    NSSTrustDomain *td;
   1520    NSSCryptoContext *cc;
   1521    td = STAN_GetDefaultTrustDomain();
   1522    cc = STAN_GetDefaultCryptoContext();
   1523    printf("\n\nCertificates in the cache:\n");
   1524    nssTrustDomain_DumpCacheInfo(td, cert_dump_iter, NULL);
   1525    printf("\n\nCertificates in the temporary store:\n");
   1526    if (cc->certStore) {
   1527        nssCertificateStore_DumpStoreInfo(cc->certStore, cert_dump_iter, NULL);
   1528    }
   1529 }