tor-browser

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

trustdomain.c (35606B)


      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 #ifndef DEV_H
      6 #include "dev.h"
      7 #endif /* DEV_H */
      8 
      9 #ifndef PKIM_H
     10 #include "pkim.h"
     11 #endif /* PKIM_H */
     12 
     13 #include "cert.h"
     14 #include "dev3hack.h"
     15 #include "pki3hack.h"
     16 #include "pk11pub.h"
     17 #include "nssrwlk.h"
     18 #include "pk11priv.h"
     19 
     20 #define NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE 32
     21 
     22 extern const NSSError NSS_ERROR_NOT_FOUND;
     23 
     24 typedef PRUint32 nssUpdateLevel;
     25 
     26 NSS_IMPLEMENT NSSTrustDomain *
     27 NSSTrustDomain_Create(
     28    NSSUTF8 *moduleOpt,
     29    NSSUTF8 *uriOpt,
     30    NSSUTF8 *opaqueOpt,
     31    void *reserved)
     32 {
     33    NSSArena *arena;
     34    NSSTrustDomain *rvTD;
     35    arena = NSSArena_Create();
     36    if (!arena) {
     37        return (NSSTrustDomain *)NULL;
     38    }
     39    rvTD = nss_ZNEW(arena, NSSTrustDomain);
     40    if (!rvTD) {
     41        goto loser;
     42    }
     43    /* protect the token list and the token iterator */
     44    rvTD->tokensLock = NSSRWLock_New(100, "tokens");
     45    if (!rvTD->tokensLock) {
     46        goto loser;
     47    }
     48    nssTrustDomain_InitializeCache(rvTD, NSSTRUSTDOMAIN_DEFAULT_CACHE_SIZE);
     49    rvTD->arena = arena;
     50    rvTD->refCount = 1;
     51    rvTD->statusConfig = NULL;
     52    return rvTD;
     53 loser:
     54    if (rvTD && rvTD->tokensLock) {
     55        NSSRWLock_Destroy(rvTD->tokensLock);
     56    }
     57    nssArena_Destroy(arena);
     58    return (NSSTrustDomain *)NULL;
     59 }
     60 
     61 static void
     62 token_destructor(void *t)
     63 {
     64    NSSToken *tok = (NSSToken *)t;
     65    /* Remove the token list's reference to the token */
     66    (void)nssToken_Destroy(tok);
     67 
     68    /* Signal that the slot should not give out any more references to the
     69     * token. The token might still have a positive refcount after this call.
     70     * The token has a reference to the slot, so the slot will not be destroyed
     71     * until after the token's refcount drops to 0. */
     72    PK11Slot_SetNSSToken(tok->pk11slot, NULL);
     73 }
     74 
     75 NSS_IMPLEMENT PRStatus
     76 NSSTrustDomain_Destroy(
     77    NSSTrustDomain *td)
     78 {
     79    PRStatus status = PR_SUCCESS;
     80    if (--td->refCount == 0) {
     81        /* Destroy each token in the list of tokens */
     82        if (td->tokens) {
     83            nssListIterator_Destroy(td->tokens);
     84            td->tokens = NULL;
     85        }
     86        if (td->tokenList) {
     87            nssList_Clear(td->tokenList, token_destructor);
     88            nssList_Destroy(td->tokenList);
     89            td->tokenList = NULL;
     90        }
     91        NSSRWLock_Destroy(td->tokensLock);
     92        td->tokensLock = NULL;
     93        status = nssTrustDomain_DestroyCache(td);
     94        if (status == PR_FAILURE) {
     95            return status;
     96        }
     97        if (td->statusConfig) {
     98            td->statusConfig->statusDestroy(td->statusConfig);
     99            td->statusConfig = NULL;
    100        }
    101        /* Destroy the trust domain */
    102        nssArena_Destroy(td->arena);
    103    }
    104    return status;
    105 }
    106 
    107 /* XXX uses tokens until slot list is in place */
    108 static NSSSlot **
    109 nssTrustDomain_GetActiveSlots(
    110    NSSTrustDomain *td,
    111    nssUpdateLevel *updateLevel)
    112 {
    113    PRUint32 count;
    114    NSSSlot **slots = NULL;
    115    NSSToken **tp, **tokens;
    116    *updateLevel = 1;
    117    if (!td->tokenList) {
    118        return NULL;
    119    }
    120    NSSRWLock_LockRead(td->tokensLock);
    121    count = nssList_Count(td->tokenList);
    122    tokens = nss_ZNEWARRAY(NULL, NSSToken *, count + 1);
    123    if (!tokens) {
    124        NSSRWLock_UnlockRead(td->tokensLock);
    125        return NULL;
    126    }
    127    slots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1);
    128    if (!slots) {
    129        NSSRWLock_UnlockRead(td->tokensLock);
    130        nss_ZFreeIf(tokens);
    131        return NULL;
    132    }
    133    nssList_GetArray(td->tokenList, (void **)tokens, count);
    134    count = 0;
    135    for (tp = tokens; *tp; tp++) {
    136        NSSSlot *slot = nssToken_GetSlot(*tp);
    137        if (!PK11_IsDisabled(slot->pk11slot)) {
    138            slots[count++] = slot;
    139        } else {
    140            nssSlot_Destroy(slot);
    141        }
    142    }
    143    NSSRWLock_UnlockRead(td->tokensLock);
    144    nss_ZFreeIf(tokens);
    145    if (!count) {
    146        nss_ZFreeIf(slots);
    147        slots = NULL;
    148    }
    149    return slots;
    150 }
    151 
    152 /* XXX */
    153 static nssSession *
    154 nssTrustDomain_GetSessionForToken(
    155    NSSTrustDomain *td,
    156    NSSToken *token)
    157 {
    158    return nssToken_GetDefaultSession(token);
    159 }
    160 
    161 NSS_IMPLEMENT PRStatus
    162 NSSTrustDomain_SetDefaultCallback(
    163    NSSTrustDomain *td,
    164    NSSCallback *newCallback,
    165    NSSCallback **oldCallbackOpt)
    166 {
    167    if (oldCallbackOpt) {
    168        *oldCallbackOpt = td->defaultCallback;
    169    }
    170    td->defaultCallback = newCallback;
    171    return PR_SUCCESS;
    172 }
    173 
    174 NSS_IMPLEMENT NSSCallback *
    175 nssTrustDomain_GetDefaultCallback(
    176    NSSTrustDomain *td,
    177    PRStatus *statusOpt)
    178 {
    179    if (statusOpt) {
    180        *statusOpt = PR_SUCCESS;
    181    }
    182    return td->defaultCallback;
    183 }
    184 
    185 NSS_IMPLEMENT NSSCallback *
    186 NSSTrustDomain_GetDefaultCallback(
    187    NSSTrustDomain *td,
    188    PRStatus *statusOpt)
    189 {
    190    return nssTrustDomain_GetDefaultCallback(td, statusOpt);
    191 }
    192 
    193 NSS_IMPLEMENT PRStatus
    194 NSSTrustDomain_LoadModule(
    195    NSSTrustDomain *td,
    196    NSSUTF8 *moduleOpt,
    197    NSSUTF8 *uriOpt,
    198    NSSUTF8 *opaqueOpt,
    199    void *reserved)
    200 {
    201    return PR_FAILURE;
    202 }
    203 
    204 NSS_IMPLEMENT PRStatus
    205 NSSTrustDomain_DisableToken(
    206    NSSTrustDomain *td,
    207    NSSToken *token,
    208    NSSError why)
    209 {
    210    nss_SetError(NSS_ERROR_NOT_FOUND);
    211    return PR_FAILURE;
    212 }
    213 
    214 NSS_IMPLEMENT PRStatus
    215 NSSTrustDomain_EnableToken(
    216    NSSTrustDomain *td,
    217    NSSToken *token)
    218 {
    219    nss_SetError(NSS_ERROR_NOT_FOUND);
    220    return PR_FAILURE;
    221 }
    222 
    223 NSS_IMPLEMENT PRStatus
    224 NSSTrustDomain_IsTokenEnabled(
    225    NSSTrustDomain *td,
    226    NSSToken *token,
    227    NSSError *whyOpt)
    228 {
    229    nss_SetError(NSS_ERROR_NOT_FOUND);
    230    return PR_FAILURE;
    231 }
    232 
    233 NSS_IMPLEMENT NSSSlot *
    234 NSSTrustDomain_FindSlotByName(
    235    NSSTrustDomain *td,
    236    NSSUTF8 *slotName)
    237 {
    238    nss_SetError(NSS_ERROR_NOT_FOUND);
    239    return NULL;
    240 }
    241 
    242 NSS_IMPLEMENT NSSToken **
    243 NSSTrustDomain_FindTokensByURI(
    244    NSSTrustDomain *td,
    245    PK11URI *uri)
    246 {
    247    NSSToken *tok = NULL;
    248    PK11SlotInfo *slotinfo;
    249    NSSToken **tokens;
    250    int count, i = 0;
    251 
    252    NSSRWLock_LockRead(td->tokensLock);
    253    count = nssList_Count(td->tokenList);
    254    tokens = nss_ZNEWARRAY(NULL, NSSToken *, count + 1);
    255    if (!tokens) {
    256        return NULL;
    257    }
    258    for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
    259         tok != (NSSToken *)NULL;
    260         tok = (NSSToken *)nssListIterator_Next(td->tokens)) {
    261        if (nssToken_IsPresent(tok)) {
    262            slotinfo = tok->pk11slot;
    263            if (pk11_MatchUriTokenInfo(slotinfo, uri))
    264                tokens[i++] = nssToken_AddRef(tok);
    265        }
    266    }
    267    tokens[i] = NULL;
    268    nssListIterator_Finish(td->tokens);
    269    NSSRWLock_UnlockRead(td->tokensLock);
    270    return tokens;
    271 }
    272 
    273 NSS_IMPLEMENT NSSToken *
    274 NSSTrustDomain_FindTokenByName(
    275    NSSTrustDomain *td,
    276    NSSUTF8 *tokenName)
    277 {
    278    PRStatus nssrv;
    279    NSSUTF8 *myName;
    280    NSSToken *tok = NULL;
    281    NSSRWLock_LockRead(td->tokensLock);
    282    for (tok = (NSSToken *)nssListIterator_Start(td->tokens);
    283         tok != (NSSToken *)NULL;
    284         tok = (NSSToken *)nssListIterator_Next(td->tokens)) {
    285        if (nssToken_IsPresent(tok)) {
    286            myName = nssToken_GetName(tok);
    287            if (nssUTF8_Equal(tokenName, myName, &nssrv)) {
    288                tok = nssToken_AddRef(tok);
    289                break;
    290            }
    291        }
    292    }
    293    nssListIterator_Finish(td->tokens);
    294    NSSRWLock_UnlockRead(td->tokensLock);
    295    return tok;
    296 }
    297 
    298 NSS_IMPLEMENT NSSToken *
    299 NSSTrustDomain_FindTokenBySlotName(
    300    NSSTrustDomain *td,
    301    NSSUTF8 *slotName)
    302 {
    303    nss_SetError(NSS_ERROR_NOT_FOUND);
    304    return NULL;
    305 }
    306 
    307 NSS_IMPLEMENT NSSToken *
    308 NSSTrustDomain_FindTokenForAlgorithm(
    309    NSSTrustDomain *td,
    310    NSSOID *algorithm)
    311 {
    312    nss_SetError(NSS_ERROR_NOT_FOUND);
    313    return NULL;
    314 }
    315 
    316 NSS_IMPLEMENT NSSToken *
    317 NSSTrustDomain_FindBestTokenForAlgorithms(
    318    NSSTrustDomain *td,
    319    NSSOID *algorithms[],   /* may be null-terminated */
    320    PRUint32 nAlgorithmsOpt /* limits the array if nonzero */
    321 )
    322 {
    323    nss_SetError(NSS_ERROR_NOT_FOUND);
    324    return NULL;
    325 }
    326 
    327 NSS_IMPLEMENT PRStatus
    328 NSSTrustDomain_Login(
    329    NSSTrustDomain *td,
    330    NSSCallback *uhhOpt)
    331 {
    332    nss_SetError(NSS_ERROR_NOT_FOUND);
    333    return PR_FAILURE;
    334 }
    335 
    336 NSS_IMPLEMENT PRStatus
    337 NSSTrustDomain_Logout(NSSTrustDomain *td)
    338 {
    339    nss_SetError(NSS_ERROR_NOT_FOUND);
    340    return PR_FAILURE;
    341 }
    342 
    343 NSS_IMPLEMENT NSSCertificate *
    344 NSSTrustDomain_ImportCertificate(
    345    NSSTrustDomain *td,
    346    NSSCertificate *c)
    347 {
    348    nss_SetError(NSS_ERROR_NOT_FOUND);
    349    return NULL;
    350 }
    351 
    352 NSS_IMPLEMENT NSSCertificate *
    353 NSSTrustDomain_ImportPKIXCertificate(
    354    NSSTrustDomain *td,
    355    /* declared as a struct until these "data types" are defined */
    356    struct NSSPKIXCertificateStr *pc)
    357 {
    358    nss_SetError(NSS_ERROR_NOT_FOUND);
    359    return NULL;
    360 }
    361 
    362 NSS_IMPLEMENT NSSCertificate *
    363 NSSTrustDomain_ImportEncodedCertificate(
    364    NSSTrustDomain *td,
    365    NSSBER *ber)
    366 {
    367    nss_SetError(NSS_ERROR_NOT_FOUND);
    368    return NULL;
    369 }
    370 
    371 NSS_IMPLEMENT NSSCertificate **
    372 NSSTrustDomain_ImportEncodedCertificateChain(
    373    NSSTrustDomain *td,
    374    NSSBER *ber,
    375    NSSCertificate *rvOpt[],
    376    PRUint32 maximumOpt, /* 0 for no max */
    377    NSSArena *arenaOpt)
    378 {
    379    nss_SetError(NSS_ERROR_NOT_FOUND);
    380    return NULL;
    381 }
    382 
    383 NSS_IMPLEMENT NSSPrivateKey *
    384 NSSTrustDomain_ImportEncodedPrivateKey(
    385    NSSTrustDomain *td,
    386    NSSBER *ber,
    387    NSSItem *passwordOpt, /* NULL will cause a callback */
    388    NSSCallback *uhhOpt,
    389    NSSToken *destination)
    390 {
    391    nss_SetError(NSS_ERROR_NOT_FOUND);
    392    return NULL;
    393 }
    394 
    395 NSS_IMPLEMENT NSSPublicKey *
    396 NSSTrustDomain_ImportEncodedPublicKey(
    397    NSSTrustDomain *td,
    398    NSSBER *ber)
    399 {
    400    nss_SetError(NSS_ERROR_NOT_FOUND);
    401    return NULL;
    402 }
    403 
    404 static NSSCertificate **
    405 get_certs_from_list(nssList *list)
    406 {
    407    PRUint32 count = nssList_Count(list);
    408    NSSCertificate **certs = NULL;
    409    if (count > 0) {
    410        certs = nss_ZNEWARRAY(NULL, NSSCertificate *, count + 1);
    411        if (certs) {
    412            nssList_GetArray(list, (void **)certs, count);
    413        }
    414    }
    415    return certs;
    416 }
    417 
    418 NSS_IMPLEMENT NSSCertificate **
    419 nssTrustDomain_FindCertificatesByNickname(
    420    NSSTrustDomain *td,
    421    const NSSUTF8 *name,
    422    NSSCertificate *rvOpt[],
    423    PRUint32 maximumOpt, /* 0 for no max */
    424    NSSArena *arenaOpt)
    425 {
    426    NSSToken *token = NULL;
    427    NSSSlot **slots = NULL;
    428    NSSSlot **slotp;
    429    NSSCertificate **rvCerts = NULL;
    430    nssPKIObjectCollection *collection = NULL;
    431    nssUpdateLevel updateLevel;
    432    nssList *nameList;
    433    PRUint32 numRemaining = maximumOpt;
    434    PRUint32 collectionCount = 0;
    435    PRUint32 errors = 0;
    436 
    437    /* First, grab from the cache */
    438    nameList = nssList_Create(NULL, PR_FALSE);
    439    if (!nameList) {
    440        return NULL;
    441    }
    442    (void)nssTrustDomain_GetCertsForNicknameFromCache(td, name, nameList);
    443    rvCerts = get_certs_from_list(nameList);
    444    /* initialize the collection of token certificates with the set of
    445     * cached certs (if any).
    446     */
    447    collection = nssCertificateCollection_Create(td, rvCerts);
    448    nssCertificateArray_Destroy(rvCerts);
    449    nssList_Destroy(nameList);
    450    if (!collection) {
    451        return (NSSCertificate **)NULL;
    452    }
    453    /* obtain the current set of active slots in the trust domain */
    454    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
    455    if (!slots) {
    456        goto loser;
    457    }
    458    /* iterate over the slots */
    459    for (slotp = slots; *slotp; slotp++) {
    460        token = nssSlot_GetToken(*slotp);
    461        if (token) {
    462            nssSession *session;
    463            nssCryptokiObject **instances = NULL;
    464            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
    465            PRStatus status = PR_FAILURE;
    466 
    467            session = nssTrustDomain_GetSessionForToken(td, token);
    468            if (session) {
    469                instances = nssToken_FindCertificatesByNickname(token,
    470                                                                session,
    471                                                                name,
    472                                                                tokenOnly,
    473                                                                numRemaining,
    474                                                                &status);
    475            }
    476            (void)nssToken_Destroy(token);
    477            if (status != PR_SUCCESS) {
    478                errors++;
    479                continue;
    480            }
    481            if (instances) {
    482                status = nssPKIObjectCollection_AddInstances(collection,
    483                                                             instances, 0);
    484                nss_ZFreeIf(instances);
    485                if (status != PR_SUCCESS) {
    486                    errors++;
    487                    continue;
    488                }
    489                collectionCount = nssPKIObjectCollection_Count(collection);
    490                if (maximumOpt > 0) {
    491                    if (collectionCount >= maximumOpt)
    492                        break;
    493                    numRemaining = maximumOpt - collectionCount;
    494                }
    495            }
    496        }
    497    }
    498    if (!collectionCount && errors)
    499        goto loser;
    500    /* Grab the certs collected in the search. */
    501    rvCerts = nssPKIObjectCollection_GetCertificates(collection,
    502                                                     rvOpt, maximumOpt,
    503                                                     arenaOpt);
    504    /* clean up */
    505    nssPKIObjectCollection_Destroy(collection);
    506    nssSlotArray_Destroy(slots);
    507    return rvCerts;
    508 loser:
    509    if (slots) {
    510        nssSlotArray_Destroy(slots);
    511    }
    512    if (collection) {
    513        nssPKIObjectCollection_Destroy(collection);
    514    }
    515    return (NSSCertificate **)NULL;
    516 }
    517 
    518 NSS_IMPLEMENT NSSCertificate **
    519 NSSTrustDomain_FindCertificatesByNickname(
    520    NSSTrustDomain *td,
    521    NSSUTF8 *name,
    522    NSSCertificate *rvOpt[],
    523    PRUint32 maximumOpt, /* 0 for no max */
    524    NSSArena *arenaOpt)
    525 {
    526    return nssTrustDomain_FindCertificatesByNickname(td,
    527                                                     name,
    528                                                     rvOpt,
    529                                                     maximumOpt,
    530                                                     arenaOpt);
    531 }
    532 
    533 NSS_IMPLEMENT NSSCertificate *
    534 nssTrustDomain_FindBestCertificateByNickname(
    535    NSSTrustDomain *td,
    536    const NSSUTF8 *name,
    537    NSSTime *timeOpt,
    538    NSSUsage *usage,
    539    NSSPolicies *policiesOpt)
    540 {
    541    NSSCertificate **nicknameCerts;
    542    NSSCertificate *rvCert = NULL;
    543    nicknameCerts = nssTrustDomain_FindCertificatesByNickname(td, name,
    544                                                              NULL,
    545                                                              0,
    546                                                              NULL);
    547    if (nicknameCerts) {
    548        rvCert = nssCertificateArray_FindBestCertificate(nicknameCerts,
    549                                                         timeOpt,
    550                                                         usage,
    551                                                         policiesOpt);
    552        nssCertificateArray_Destroy(nicknameCerts);
    553    }
    554    return rvCert;
    555 }
    556 
    557 NSS_IMPLEMENT NSSCertificate *
    558 NSSTrustDomain_FindBestCertificateByNickname(
    559    NSSTrustDomain *td,
    560    const NSSUTF8 *name,
    561    NSSTime *timeOpt,
    562    NSSUsage *usage,
    563    NSSPolicies *policiesOpt)
    564 {
    565    return nssTrustDomain_FindBestCertificateByNickname(td,
    566                                                        name,
    567                                                        timeOpt,
    568                                                        usage,
    569                                                        policiesOpt);
    570 }
    571 
    572 NSS_IMPLEMENT NSSCertificate **
    573 nssTrustDomain_FindCertificatesBySubject(
    574    NSSTrustDomain *td,
    575    NSSDER *subject,
    576    NSSCertificate *rvOpt[],
    577    PRUint32 maximumOpt, /* 0 for no max */
    578    NSSArena *arenaOpt)
    579 {
    580    NSSToken *token = NULL;
    581    NSSSlot **slots = NULL;
    582    NSSSlot **slotp;
    583    NSSCertificate **rvCerts = NULL;
    584    nssPKIObjectCollection *collection = NULL;
    585    nssUpdateLevel updateLevel;
    586    nssList *subjectList;
    587    PRUint32 numRemaining = maximumOpt;
    588    PRUint32 collectionCount = 0;
    589    PRUint32 errors = 0;
    590 
    591    /* look in cache */
    592    subjectList = nssList_Create(NULL, PR_FALSE);
    593    if (!subjectList) {
    594        return NULL;
    595    }
    596    (void)nssTrustDomain_GetCertsForSubjectFromCache(td, subject, subjectList);
    597    rvCerts = get_certs_from_list(subjectList);
    598    collection = nssCertificateCollection_Create(td, rvCerts);
    599    nssCertificateArray_Destroy(rvCerts);
    600    nssList_Destroy(subjectList);
    601    if (!collection) {
    602        return (NSSCertificate **)NULL;
    603    }
    604    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
    605    if (!slots) {
    606        goto loser;
    607    }
    608    for (slotp = slots; *slotp; slotp++) {
    609        token = nssSlot_GetToken(*slotp);
    610        if (token) {
    611            nssSession *session;
    612            nssCryptokiObject **instances = NULL;
    613            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
    614            PRStatus status = PR_FAILURE;
    615 
    616            session = nssTrustDomain_GetSessionForToken(td, token);
    617            if (session) {
    618                instances = nssToken_FindCertificatesBySubject(token,
    619                                                               session,
    620                                                               subject,
    621                                                               tokenOnly,
    622                                                               numRemaining,
    623                                                               &status);
    624            }
    625            (void)nssToken_Destroy(token);
    626            if (status != PR_SUCCESS) {
    627                errors++;
    628                continue;
    629            }
    630            if (instances) {
    631                status = nssPKIObjectCollection_AddInstances(collection,
    632                                                             instances, 0);
    633                nss_ZFreeIf(instances);
    634                if (status != PR_SUCCESS) {
    635                    errors++;
    636                    continue;
    637                }
    638                collectionCount = nssPKIObjectCollection_Count(collection);
    639                if (maximumOpt > 0) {
    640                    if (collectionCount >= maximumOpt)
    641                        break;
    642                    numRemaining = maximumOpt - collectionCount;
    643                }
    644            }
    645        }
    646    }
    647    if (!collectionCount && errors)
    648        goto loser;
    649    rvCerts = nssPKIObjectCollection_GetCertificates(collection,
    650                                                     rvOpt, maximumOpt,
    651                                                     arenaOpt);
    652    nssPKIObjectCollection_Destroy(collection);
    653    nssSlotArray_Destroy(slots);
    654    return rvCerts;
    655 loser:
    656    if (slots) {
    657        nssSlotArray_Destroy(slots);
    658    }
    659    if (collection) {
    660        nssPKIObjectCollection_Destroy(collection);
    661    }
    662    return (NSSCertificate **)NULL;
    663 }
    664 
    665 NSS_IMPLEMENT NSSCertificate **
    666 NSSTrustDomain_FindCertificatesBySubject(
    667    NSSTrustDomain *td,
    668    NSSDER *subject,
    669    NSSCertificate *rvOpt[],
    670    PRUint32 maximumOpt,
    671    NSSArena *arenaOpt)
    672 {
    673    return nssTrustDomain_FindCertificatesBySubject(td,
    674                                                    subject,
    675                                                    rvOpt,
    676                                                    maximumOpt,
    677                                                    arenaOpt);
    678 }
    679 
    680 NSS_IMPLEMENT NSSCertificate *
    681 nssTrustDomain_FindBestCertificateBySubject(
    682    NSSTrustDomain *td,
    683    NSSDER *subject,
    684    NSSTime *timeOpt,
    685    NSSUsage *usage,
    686    NSSPolicies *policiesOpt)
    687 {
    688    NSSCertificate **subjectCerts;
    689    NSSCertificate *rvCert = NULL;
    690    subjectCerts = nssTrustDomain_FindCertificatesBySubject(td, subject,
    691                                                            NULL,
    692                                                            0,
    693                                                            NULL);
    694    if (subjectCerts) {
    695        rvCert = nssCertificateArray_FindBestCertificate(subjectCerts,
    696                                                         timeOpt,
    697                                                         usage,
    698                                                         policiesOpt);
    699        nssCertificateArray_Destroy(subjectCerts);
    700    }
    701    return rvCert;
    702 }
    703 
    704 NSS_IMPLEMENT NSSCertificate *
    705 NSSTrustDomain_FindBestCertificateBySubject(
    706    NSSTrustDomain *td,
    707    NSSDER *subject,
    708    NSSTime *timeOpt,
    709    NSSUsage *usage,
    710    NSSPolicies *policiesOpt)
    711 {
    712    return nssTrustDomain_FindBestCertificateBySubject(td,
    713                                                       subject,
    714                                                       timeOpt,
    715                                                       usage,
    716                                                       policiesOpt);
    717 }
    718 
    719 NSS_IMPLEMENT NSSCertificate *
    720 NSSTrustDomain_FindBestCertificateByNameComponents(
    721    NSSTrustDomain *td,
    722    NSSUTF8 *nameComponents,
    723    NSSTime *timeOpt,
    724    NSSUsage *usage,
    725    NSSPolicies *policiesOpt)
    726 {
    727    nss_SetError(NSS_ERROR_NOT_FOUND);
    728    return NULL;
    729 }
    730 
    731 NSS_IMPLEMENT NSSCertificate **
    732 NSSTrustDomain_FindCertificatesByNameComponents(
    733    NSSTrustDomain *td,
    734    NSSUTF8 *nameComponents,
    735    NSSCertificate *rvOpt[],
    736    PRUint32 maximumOpt, /* 0 for no max */
    737    NSSArena *arenaOpt)
    738 {
    739    nss_SetError(NSS_ERROR_NOT_FOUND);
    740    return NULL;
    741 }
    742 
    743 /* This returns at most a single certificate, so it can stop the loop
    744 * when one is found.
    745 */
    746 NSS_IMPLEMENT NSSCertificate *
    747 nssTrustDomain_FindCertificateByIssuerAndSerialNumber(
    748    NSSTrustDomain *td,
    749    NSSDER *issuer,
    750    NSSDER *serial)
    751 {
    752    NSSSlot **slots = NULL;
    753    NSSSlot **slotp;
    754    NSSCertificate *rvCert = NULL;
    755    nssPKIObjectCollection *collection = NULL;
    756    nssUpdateLevel updateLevel;
    757 
    758    /* see if this search is already cached */
    759    rvCert = nssTrustDomain_GetCertForIssuerAndSNFromCache(td,
    760                                                           issuer,
    761                                                           serial);
    762    if (rvCert) {
    763        return rvCert;
    764    }
    765    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
    766    if (slots) {
    767        for (slotp = slots; *slotp; slotp++) {
    768            NSSToken *token = nssSlot_GetToken(*slotp);
    769            nssSession *session;
    770            nssCryptokiObject *instance;
    771            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
    772            PRStatus status = PR_FAILURE;
    773 
    774            if (!token)
    775                continue;
    776            session = nssTrustDomain_GetSessionForToken(td, token);
    777            if (session) {
    778                instance = nssToken_FindCertificateByIssuerAndSerialNumber(
    779                    token,
    780                    session,
    781                    issuer,
    782                    serial,
    783                    tokenOnly,
    784                    &status);
    785            }
    786            (void)nssToken_Destroy(token);
    787            if (status != PR_SUCCESS) {
    788                continue;
    789            }
    790            if (instance) {
    791                if (!collection) {
    792                    collection = nssCertificateCollection_Create(td, NULL);
    793                    if (!collection) {
    794                        break; /* don't keep looping if out if memory */
    795                    }
    796                }
    797                status = nssPKIObjectCollection_AddInstances(collection,
    798                                                             &instance, 1);
    799                if (status == PR_SUCCESS) {
    800                    (void)nssPKIObjectCollection_GetCertificates(
    801                        collection, &rvCert, 1, NULL);
    802                }
    803                if (rvCert) {
    804                    break; /* found one cert, all done */
    805                }
    806            }
    807        }
    808    }
    809    if (collection) {
    810        nssPKIObjectCollection_Destroy(collection);
    811    }
    812    if (slots) {
    813        nssSlotArray_Destroy(slots);
    814    }
    815    return rvCert;
    816 }
    817 
    818 NSS_IMPLEMENT NSSCertificate *
    819 NSSTrustDomain_FindCertificateByIssuerAndSerialNumber(
    820    NSSTrustDomain *td,
    821    NSSDER *issuer,
    822    NSSDER *serial)
    823 {
    824    return nssTrustDomain_FindCertificateByIssuerAndSerialNumber(td,
    825                                                                 issuer,
    826                                                                 serial);
    827 }
    828 
    829 NSS_IMPLEMENT NSSCertificate *
    830 nssTrustDomain_FindCertificateByEncodedCertificate(
    831    NSSTrustDomain *td,
    832    NSSBER *ber)
    833 {
    834    PRStatus status;
    835    NSSCertificate *rvCert = NULL;
    836    NSSDER issuer = { 0 };
    837    NSSDER serial = { 0 };
    838    /* XXX this is not generic...  will any cert crack into issuer/serial? */
    839    status = nssPKIX509_GetIssuerAndSerialFromDER(ber, &issuer, &serial);
    840    if (status != PR_SUCCESS) {
    841        return NULL;
    842    }
    843    rvCert = nssTrustDomain_FindCertificateByIssuerAndSerialNumber(td,
    844                                                                   &issuer,
    845                                                                   &serial);
    846    PORT_Free(issuer.data);
    847    PORT_Free(serial.data);
    848    return rvCert;
    849 }
    850 
    851 NSS_IMPLEMENT NSSCertificate *
    852 NSSTrustDomain_FindCertificateByEncodedCertificate(
    853    NSSTrustDomain *td,
    854    NSSBER *ber)
    855 {
    856    return nssTrustDomain_FindCertificateByEncodedCertificate(td, ber);
    857 }
    858 
    859 NSS_IMPLEMENT NSSCertificate *
    860 NSSTrustDomain_FindBestCertificateByEmail(
    861    NSSTrustDomain *td,
    862    NSSASCII7 *email,
    863    NSSTime *timeOpt,
    864    NSSUsage *usage,
    865    NSSPolicies *policiesOpt)
    866 {
    867    return 0;
    868 }
    869 
    870 NSS_IMPLEMENT NSSCertificate **
    871 NSSTrustDomain_FindCertificatesByEmail(
    872    NSSTrustDomain *td,
    873    NSSASCII7 *email,
    874    NSSCertificate *rvOpt[],
    875    PRUint32 maximumOpt, /* 0 for no max */
    876    NSSArena *arenaOpt)
    877 {
    878    nss_SetError(NSS_ERROR_NOT_FOUND);
    879    return NULL;
    880 }
    881 
    882 NSS_IMPLEMENT NSSCertificate *
    883 NSSTrustDomain_FindCertificateByOCSPHash(
    884    NSSTrustDomain *td,
    885    NSSItem *hash)
    886 {
    887    nss_SetError(NSS_ERROR_NOT_FOUND);
    888    return NULL;
    889 }
    890 
    891 NSS_IMPLEMENT NSSCertificate *
    892 NSSTrustDomain_FindBestUserCertificate(
    893    NSSTrustDomain *td,
    894    NSSTime *timeOpt,
    895    NSSUsage *usage,
    896    NSSPolicies *policiesOpt)
    897 {
    898    nss_SetError(NSS_ERROR_NOT_FOUND);
    899    return NULL;
    900 }
    901 
    902 NSS_IMPLEMENT NSSCertificate **
    903 NSSTrustDomain_FindUserCertificates(
    904    NSSTrustDomain *td,
    905    NSSTime *timeOpt,
    906    NSSUsage *usageOpt,
    907    NSSPolicies *policiesOpt,
    908    NSSCertificate **rvOpt,
    909    PRUint32 rvLimit, /* zero for no limit */
    910    NSSArena *arenaOpt)
    911 {
    912    nss_SetError(NSS_ERROR_NOT_FOUND);
    913    return NULL;
    914 }
    915 
    916 NSS_IMPLEMENT NSSCertificate *
    917 NSSTrustDomain_FindBestUserCertificateForSSLClientAuth(
    918    NSSTrustDomain *td,
    919    NSSUTF8 *sslHostOpt,
    920    NSSDER *rootCAsOpt[],   /* null pointer for none */
    921    PRUint32 rootCAsMaxOpt, /* zero means list is null-terminated */
    922    NSSAlgorithmAndParameters *apOpt,
    923    NSSPolicies *policiesOpt)
    924 {
    925    nss_SetError(NSS_ERROR_NOT_FOUND);
    926    return NULL;
    927 }
    928 
    929 NSS_IMPLEMENT NSSCertificate **
    930 NSSTrustDomain_FindUserCertificatesForSSLClientAuth(
    931    NSSTrustDomain *td,
    932    NSSUTF8 *sslHostOpt,
    933    NSSDER *rootCAsOpt[],   /* null pointer for none */
    934    PRUint32 rootCAsMaxOpt, /* zero means list is null-terminated */
    935    NSSAlgorithmAndParameters *apOpt,
    936    NSSPolicies *policiesOpt,
    937    NSSCertificate **rvOpt,
    938    PRUint32 rvLimit, /* zero for no limit */
    939    NSSArena *arenaOpt)
    940 {
    941    nss_SetError(NSS_ERROR_NOT_FOUND);
    942    return NULL;
    943 }
    944 
    945 NSS_IMPLEMENT NSSCertificate *
    946 NSSTrustDomain_FindBestUserCertificateForEmailSigning(
    947    NSSTrustDomain *td,
    948    NSSASCII7 *signerOpt,
    949    NSSASCII7 *recipientOpt,
    950    /* anything more here? */
    951    NSSAlgorithmAndParameters *apOpt,
    952    NSSPolicies *policiesOpt)
    953 {
    954    nss_SetError(NSS_ERROR_NOT_FOUND);
    955    return NULL;
    956 }
    957 
    958 NSS_IMPLEMENT NSSCertificate **
    959 NSSTrustDomain_FindUserCertificatesForEmailSigning(
    960    NSSTrustDomain *td,
    961    NSSASCII7 *signerOpt,
    962    NSSASCII7 *recipientOpt,
    963    /* anything more here? */
    964    NSSAlgorithmAndParameters *apOpt,
    965    NSSPolicies *policiesOpt,
    966    NSSCertificate **rvOpt,
    967    PRUint32 rvLimit, /* zero for no limit */
    968    NSSArena *arenaOpt)
    969 {
    970    nss_SetError(NSS_ERROR_NOT_FOUND);
    971    return NULL;
    972 }
    973 
    974 static PRStatus
    975 collector(nssCryptokiObject *instance, void *arg)
    976 {
    977    nssPKIObjectCollection *collection = (nssPKIObjectCollection *)arg;
    978    return nssPKIObjectCollection_AddInstanceAsObject(collection, instance);
    979 }
    980 
    981 NSS_IMPLEMENT PRStatus *
    982 NSSTrustDomain_TraverseCertificates(
    983    NSSTrustDomain *td,
    984    PRStatus (*callback)(NSSCertificate *c, void *arg),
    985    void *arg)
    986 {
    987    NSSToken *token = NULL;
    988    NSSSlot **slots = NULL;
    989    NSSSlot **slotp;
    990    nssPKIObjectCollection *collection = NULL;
    991    nssPKIObjectCallback pkiCallback;
    992    nssUpdateLevel updateLevel;
    993    NSSCertificate **cached = NULL;
    994    nssList *certList;
    995 
    996    certList = nssList_Create(NULL, PR_FALSE);
    997    if (!certList)
    998        return NULL;
    999    (void)nssTrustDomain_GetCertsFromCache(td, certList);
   1000    cached = get_certs_from_list(certList);
   1001    collection = nssCertificateCollection_Create(td, cached);
   1002    nssCertificateArray_Destroy(cached);
   1003    nssList_Destroy(certList);
   1004    if (!collection) {
   1005        return (PRStatus *)NULL;
   1006    }
   1007    /* obtain the current set of active slots in the trust domain */
   1008    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
   1009    if (!slots) {
   1010        goto loser;
   1011    }
   1012    /* iterate over the slots */
   1013    for (slotp = slots; *slotp; slotp++) {
   1014        /* get the token for the slot, if present */
   1015        token = nssSlot_GetToken(*slotp);
   1016        if (token) {
   1017            nssSession *session;
   1018            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
   1019            /* get a session for the token */
   1020            session = nssTrustDomain_GetSessionForToken(td, token);
   1021            if (session) {
   1022                /* perform the traversal */
   1023                (void)nssToken_TraverseCertificates(token,
   1024                                                    session,
   1025                                                    tokenOnly,
   1026                                                    collector,
   1027                                                    collection);
   1028            }
   1029            (void)nssToken_Destroy(token);
   1030        }
   1031    }
   1032 
   1033    /* Traverse the collection */
   1034    pkiCallback.func.cert = callback;
   1035    pkiCallback.arg = arg;
   1036    (void)nssPKIObjectCollection_Traverse(collection, &pkiCallback);
   1037 loser:
   1038    if (slots) {
   1039        nssSlotArray_Destroy(slots);
   1040    }
   1041    if (collection) {
   1042        nssPKIObjectCollection_Destroy(collection);
   1043    }
   1044    return NULL;
   1045 }
   1046 
   1047 NSS_IMPLEMENT NSSTrust *
   1048 nssTrustDomain_FindTrustForCertificate(
   1049    NSSTrustDomain *td,
   1050    NSSCertificate *c)
   1051 {
   1052    NSSSlot **slots;
   1053    NSSSlot **slotp;
   1054    nssCryptokiObject *to = NULL;
   1055    nssPKIObject *pkio = NULL;
   1056    NSSTrust *rvt = NULL;
   1057    nssUpdateLevel updateLevel;
   1058    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
   1059    if (!slots) {
   1060        return (NSSTrust *)NULL;
   1061    }
   1062    for (slotp = slots; *slotp; slotp++) {
   1063        NSSToken *token = nssSlot_GetToken(*slotp);
   1064 
   1065        if (token) {
   1066            to = nssToken_FindTrustForCertificate(token, NULL,
   1067                                                  &c->encoding,
   1068                                                  &c->issuer,
   1069                                                  &c->serial,
   1070                                                  nssTokenSearchType_TokenOnly);
   1071            if (to) {
   1072                PRStatus status;
   1073                if (!pkio) {
   1074                    pkio = nssPKIObject_Create(NULL, to, td, NULL, nssPKILock);
   1075                    status = pkio ? PR_SUCCESS : PR_FAILURE;
   1076                } else {
   1077                    status = nssPKIObject_AddInstance(pkio, to);
   1078                }
   1079                if (status != PR_SUCCESS) {
   1080                    nssCryptokiObject_Destroy(to);
   1081                }
   1082            }
   1083            (void)nssToken_Destroy(token);
   1084        }
   1085    }
   1086    if (pkio) {
   1087        rvt = nssTrust_Create(pkio, &c->encoding);
   1088        if (rvt) {
   1089            pkio = NULL; /* rvt object now owns the pkio reference */
   1090        }
   1091    }
   1092    nssSlotArray_Destroy(slots);
   1093    if (pkio) {
   1094        nssPKIObject_Destroy(pkio);
   1095    }
   1096    return rvt;
   1097 }
   1098 
   1099 NSS_IMPLEMENT NSSCRL **
   1100 nssTrustDomain_FindCRLsBySubject(
   1101    NSSTrustDomain *td,
   1102    NSSDER *subject)
   1103 {
   1104    NSSSlot **slots;
   1105    NSSSlot **slotp;
   1106    NSSToken *token;
   1107    nssUpdateLevel updateLevel;
   1108    nssPKIObjectCollection *collection;
   1109    NSSCRL **rvCRLs = NULL;
   1110    collection = nssCRLCollection_Create(td, NULL);
   1111    if (!collection) {
   1112        return (NSSCRL **)NULL;
   1113    }
   1114    slots = nssTrustDomain_GetActiveSlots(td, &updateLevel);
   1115    if (!slots) {
   1116        goto loser;
   1117    }
   1118    for (slotp = slots; *slotp; slotp++) {
   1119        token = nssSlot_GetToken(*slotp);
   1120        if (token) {
   1121            PRStatus status = PR_FAILURE;
   1122            nssSession *session;
   1123            nssCryptokiObject **instances = NULL;
   1124            nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
   1125 
   1126            /* get a session for the token */
   1127            session = nssTrustDomain_GetSessionForToken(td, token);
   1128            if (session) {
   1129                /* perform the traversal */
   1130                instances = nssToken_FindCRLsBySubject(token, session, subject,
   1131                                                       tokenOnly, 0, &status);
   1132            }
   1133            (void)nssToken_Destroy(token);
   1134            if (status == PR_SUCCESS) {
   1135                /* add the found CRL's to the collection */
   1136                status = nssPKIObjectCollection_AddInstances(collection,
   1137                                                             instances, 0);
   1138            }
   1139            nss_ZFreeIf(instances);
   1140        }
   1141    }
   1142    rvCRLs = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL);
   1143 loser:
   1144    nssPKIObjectCollection_Destroy(collection);
   1145    nssSlotArray_Destroy(slots);
   1146    return rvCRLs;
   1147 }
   1148 
   1149 NSS_IMPLEMENT PRStatus
   1150 NSSTrustDomain_GenerateKeyPair(
   1151    NSSTrustDomain *td,
   1152    NSSAlgorithmAndParameters *ap,
   1153    NSSPrivateKey **pvkOpt,
   1154    NSSPublicKey **pbkOpt,
   1155    PRBool privateKeyIsSensitive,
   1156    NSSToken *destination,
   1157    NSSCallback *uhhOpt)
   1158 {
   1159    nss_SetError(NSS_ERROR_NOT_FOUND);
   1160    return PR_FAILURE;
   1161 }
   1162 
   1163 NSS_IMPLEMENT NSSSymmetricKey *
   1164 NSSTrustDomain_GenerateSymmetricKey(
   1165    NSSTrustDomain *td,
   1166    NSSAlgorithmAndParameters *ap,
   1167    PRUint32 keysize,
   1168    NSSToken *destination,
   1169    NSSCallback *uhhOpt)
   1170 {
   1171    nss_SetError(NSS_ERROR_NOT_FOUND);
   1172    return NULL;
   1173 }
   1174 
   1175 NSS_IMPLEMENT NSSSymmetricKey *
   1176 NSSTrustDomain_GenerateSymmetricKeyFromPassword(
   1177    NSSTrustDomain *td,
   1178    NSSAlgorithmAndParameters *ap,
   1179    NSSUTF8 *passwordOpt, /* if null, prompt */
   1180    NSSToken *destinationOpt,
   1181    NSSCallback *uhhOpt)
   1182 {
   1183    nss_SetError(NSS_ERROR_NOT_FOUND);
   1184    return NULL;
   1185 }
   1186 
   1187 NSS_IMPLEMENT NSSSymmetricKey *
   1188 NSSTrustDomain_FindSymmetricKeyByAlgorithmAndKeyID(
   1189    NSSTrustDomain *td,
   1190    NSSOID *algorithm,
   1191    NSSItem *keyID,
   1192    NSSCallback *uhhOpt)
   1193 {
   1194    nss_SetError(NSS_ERROR_NOT_FOUND);
   1195    return NULL;
   1196 }
   1197 
   1198 NSS_IMPLEMENT NSSCryptoContext *
   1199 nssTrustDomain_CreateCryptoContext(
   1200    NSSTrustDomain *td,
   1201    NSSCallback *uhhOpt)
   1202 {
   1203    return nssCryptoContext_Create(td, uhhOpt);
   1204 }
   1205 
   1206 NSS_IMPLEMENT NSSCryptoContext *
   1207 NSSTrustDomain_CreateCryptoContext(
   1208    NSSTrustDomain *td,
   1209    NSSCallback *uhhOpt)
   1210 {
   1211    return nssTrustDomain_CreateCryptoContext(td, uhhOpt);
   1212 }
   1213 
   1214 NSS_IMPLEMENT NSSCryptoContext *
   1215 NSSTrustDomain_CreateCryptoContextForAlgorithm(
   1216    NSSTrustDomain *td,
   1217    NSSOID *algorithm)
   1218 {
   1219    nss_SetError(NSS_ERROR_NOT_FOUND);
   1220    return NULL;
   1221 }
   1222 
   1223 NSS_IMPLEMENT NSSCryptoContext *
   1224 NSSTrustDomain_CreateCryptoContextForAlgorithmAndParameters(
   1225    NSSTrustDomain *td,
   1226    NSSAlgorithmAndParameters *ap)
   1227 {
   1228    nss_SetError(NSS_ERROR_NOT_FOUND);
   1229    return NULL;
   1230 }