tor-browser

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

stanpcertdb.c (37554B)


      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 #include "prtime.h"
      6 
      7 #include "cert.h"
      8 #include "certi.h"
      9 #include "certdb.h"
     10 #include "secitem.h"
     11 #include "secder.h"
     12 
     13 /* Call to PK11_FreeSlot below */
     14 
     15 #include "secasn1.h"
     16 #include "secerr.h"
     17 #include "nssilock.h"
     18 #include "prmon.h"
     19 #include "base64.h"
     20 #include "sechash.h"
     21 #include "plhash.h"
     22 #include "pk11func.h" /* sigh */
     23 
     24 #include "nsspki.h"
     25 #include "pki.h"
     26 #include "pkim.h"
     27 #include "pki3hack.h"
     28 #include "ckhelper.h"
     29 #include "base.h"
     30 #include "pkistore.h"
     31 #include "dev3hack.h"
     32 #include "dev.h"
     33 #include "secmodi.h"
     34 
     35 extern void CERT_MaybeLockCertTempPerm(const CERTCertificate *cert);
     36 extern void CERT_MaybeUnlockCertTempPerm(const CERTCertificate *cert);
     37 
     38 PRBool
     39 SEC_CertNicknameConflict(const char *nickname, const SECItem *derSubject,
     40                         CERTCertDBHandle *handle)
     41 {
     42    CERTCertificate *cert;
     43    PRBool conflict = PR_FALSE;
     44 
     45    cert = CERT_FindCertByNickname(handle, nickname);
     46 
     47    if (!cert) {
     48        return conflict;
     49    }
     50 
     51    conflict = !SECITEM_ItemsAreEqual(derSubject, &cert->derSubject);
     52    CERT_DestroyCertificate(cert);
     53    return conflict;
     54 }
     55 
     56 SECStatus
     57 SEC_DeletePermCertificate(CERTCertificate *cert)
     58 {
     59    PRStatus nssrv;
     60    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
     61    NSSCertificate *c = STAN_GetNSSCertificate(cert);
     62    CERTCertTrust *certTrust;
     63 
     64    if (c == NULL) {
     65        /* error code is set */
     66        return SECFailure;
     67    }
     68 
     69    certTrust = nssTrust_GetCERTCertTrustForCert(c, cert);
     70    if (certTrust) {
     71        NSSTrust *nssTrust = nssTrustDomain_FindTrustForCertificate(td, c);
     72        if (nssTrust) {
     73            nssrv = STAN_DeleteCertTrustMatchingSlot(c);
     74            if (nssrv != PR_SUCCESS) {
     75                CERT_MapStanError();
     76            }
     77            /* This call always returns PR_SUCCESS! */
     78            (void)nssTrust_Destroy(nssTrust);
     79        }
     80    }
     81 
     82    /* get rid of the token instances */
     83    nssrv = NSSCertificate_DeleteStoredObject(c, NULL);
     84 
     85    /* get rid of the cache entry */
     86    nssTrustDomain_LockCertCache(td);
     87    nssTrustDomain_RemoveCertFromCacheLOCKED(td, c);
     88    nssTrustDomain_UnlockCertCache(td);
     89 
     90    return (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
     91 }
     92 
     93 SECStatus
     94 CERT_GetCertTrust(const CERTCertificate *cert, CERTCertTrust *trust)
     95 {
     96    SECStatus rv;
     97    CERT_LockCertTrust(cert);
     98    if (!cert || cert->trust == NULL) {
     99        rv = SECFailure;
    100    } else {
    101        *trust = *cert->trust;
    102        rv = SECSuccess;
    103    }
    104    CERT_UnlockCertTrust(cert);
    105    return (rv);
    106 }
    107 
    108 extern const NSSError NSS_ERROR_NO_ERROR;
    109 extern const NSSError NSS_ERROR_INTERNAL_ERROR;
    110 extern const NSSError NSS_ERROR_NO_MEMORY;
    111 extern const NSSError NSS_ERROR_INVALID_POINTER;
    112 extern const NSSError NSS_ERROR_INVALID_ARENA;
    113 extern const NSSError NSS_ERROR_INVALID_ARENA_MARK;
    114 extern const NSSError NSS_ERROR_DUPLICATE_POINTER;
    115 extern const NSSError NSS_ERROR_POINTER_NOT_REGISTERED;
    116 extern const NSSError NSS_ERROR_TRACKER_NOT_EMPTY;
    117 extern const NSSError NSS_ERROR_TRACKER_NOT_INITIALIZED;
    118 extern const NSSError NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD;
    119 extern const NSSError NSS_ERROR_VALUE_TOO_LARGE;
    120 extern const NSSError NSS_ERROR_UNSUPPORTED_TYPE;
    121 extern const NSSError NSS_ERROR_BUFFER_TOO_SHORT;
    122 extern const NSSError NSS_ERROR_INVALID_ATOB_CONTEXT;
    123 extern const NSSError NSS_ERROR_INVALID_BASE64;
    124 extern const NSSError NSS_ERROR_INVALID_BTOA_CONTEXT;
    125 extern const NSSError NSS_ERROR_INVALID_ITEM;
    126 extern const NSSError NSS_ERROR_INVALID_STRING;
    127 extern const NSSError NSS_ERROR_INVALID_ASN1ENCODER;
    128 extern const NSSError NSS_ERROR_INVALID_ASN1DECODER;
    129 extern const NSSError NSS_ERROR_INVALID_BER;
    130 extern const NSSError NSS_ERROR_INVALID_ATAV;
    131 extern const NSSError NSS_ERROR_INVALID_ARGUMENT;
    132 extern const NSSError NSS_ERROR_INVALID_UTF8;
    133 extern const NSSError NSS_ERROR_INVALID_NSSOID;
    134 extern const NSSError NSS_ERROR_UNKNOWN_ATTRIBUTE;
    135 extern const NSSError NSS_ERROR_NOT_FOUND;
    136 extern const NSSError NSS_ERROR_INVALID_PASSWORD;
    137 extern const NSSError NSS_ERROR_USER_CANCELED;
    138 extern const NSSError NSS_ERROR_MAXIMUM_FOUND;
    139 extern const NSSError NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND;
    140 extern const NSSError NSS_ERROR_CERTIFICATE_IN_CACHE;
    141 extern const NSSError NSS_ERROR_HASH_COLLISION;
    142 extern const NSSError NSS_ERROR_DEVICE_ERROR;
    143 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
    144 extern const NSSError NSS_ERROR_BUSY;
    145 extern const NSSError NSS_ERROR_ALREADY_INITIALIZED;
    146 extern const NSSError NSS_ERROR_PKCS11;
    147 
    148 /* Look at the stan error stack and map it to NSS 3 errors */
    149 #define STAN_MAP_ERROR(x, y) \
    150    else if (error == (x)) { secError = y; }
    151 
    152 /*
    153 * map Stan errors into NSS errors
    154 * This function examines the stan error stack and automatically sets
    155 * PORT_SetError(); to the appropriate SEC_ERROR value.
    156 */
    157 void
    158 CERT_MapStanError()
    159 {
    160    PRInt32 *errorStack;
    161    NSSError error, prevError;
    162    int secError;
    163    int i;
    164 
    165    errorStack = NSS_GetErrorStack();
    166    if (errorStack == 0) {
    167        PORT_SetError(0);
    168        return;
    169    }
    170    error = prevError = CKR_GENERAL_ERROR;
    171    /* get the 'top 2' error codes from the stack */
    172    for (i = 0; errorStack[i]; i++) {
    173        prevError = error;
    174        error = errorStack[i];
    175    }
    176    if (error == NSS_ERROR_PKCS11) {
    177        /* map it */
    178        secError = PK11_MapError(prevError);
    179    }
    180    STAN_MAP_ERROR(NSS_ERROR_NO_ERROR, 0)
    181    STAN_MAP_ERROR(NSS_ERROR_NO_MEMORY, SEC_ERROR_NO_MEMORY)
    182    STAN_MAP_ERROR(NSS_ERROR_INVALID_BASE64, SEC_ERROR_BAD_DATA)
    183    STAN_MAP_ERROR(NSS_ERROR_INVALID_BER, SEC_ERROR_BAD_DER)
    184    STAN_MAP_ERROR(NSS_ERROR_INVALID_ATAV, SEC_ERROR_INVALID_AVA)
    185    STAN_MAP_ERROR(NSS_ERROR_INVALID_PASSWORD, SEC_ERROR_BAD_PASSWORD)
    186    STAN_MAP_ERROR(NSS_ERROR_BUSY, SEC_ERROR_BUSY)
    187    STAN_MAP_ERROR(NSS_ERROR_DEVICE_ERROR, SEC_ERROR_IO)
    188    STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_ISSUER_NOT_FOUND,
    189                   SEC_ERROR_UNKNOWN_ISSUER)
    190    STAN_MAP_ERROR(NSS_ERROR_INVALID_CERTIFICATE, SEC_ERROR_CERT_NOT_VALID)
    191    STAN_MAP_ERROR(NSS_ERROR_INVALID_UTF8, SEC_ERROR_BAD_DATA)
    192    STAN_MAP_ERROR(NSS_ERROR_INVALID_NSSOID, SEC_ERROR_BAD_DATA)
    193 
    194    /* these are library failure for lack of a better error code */
    195    STAN_MAP_ERROR(NSS_ERROR_NOT_FOUND, SEC_ERROR_LIBRARY_FAILURE)
    196    STAN_MAP_ERROR(NSS_ERROR_CERTIFICATE_IN_CACHE, SEC_ERROR_LIBRARY_FAILURE)
    197    STAN_MAP_ERROR(NSS_ERROR_MAXIMUM_FOUND, SEC_ERROR_LIBRARY_FAILURE)
    198    STAN_MAP_ERROR(NSS_ERROR_USER_CANCELED, SEC_ERROR_LIBRARY_FAILURE)
    199    STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE)
    200    STAN_MAP_ERROR(NSS_ERROR_ALREADY_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE)
    201    STAN_MAP_ERROR(NSS_ERROR_ARENA_MARKED_BY_ANOTHER_THREAD,
    202                   SEC_ERROR_LIBRARY_FAILURE)
    203    STAN_MAP_ERROR(NSS_ERROR_HASH_COLLISION, SEC_ERROR_LIBRARY_FAILURE)
    204 
    205    STAN_MAP_ERROR(NSS_ERROR_INTERNAL_ERROR, SEC_ERROR_LIBRARY_FAILURE)
    206 
    207    /* these are all invalid arguments */
    208    STAN_MAP_ERROR(NSS_ERROR_INVALID_ARGUMENT, SEC_ERROR_INVALID_ARGS)
    209    STAN_MAP_ERROR(NSS_ERROR_INVALID_POINTER, SEC_ERROR_INVALID_ARGS)
    210    STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA, SEC_ERROR_INVALID_ARGS)
    211    STAN_MAP_ERROR(NSS_ERROR_INVALID_ARENA_MARK, SEC_ERROR_INVALID_ARGS)
    212    STAN_MAP_ERROR(NSS_ERROR_DUPLICATE_POINTER, SEC_ERROR_INVALID_ARGS)
    213    STAN_MAP_ERROR(NSS_ERROR_POINTER_NOT_REGISTERED, SEC_ERROR_INVALID_ARGS)
    214    STAN_MAP_ERROR(NSS_ERROR_TRACKER_NOT_EMPTY, SEC_ERROR_INVALID_ARGS)
    215    STAN_MAP_ERROR(NSS_ERROR_VALUE_TOO_LARGE, SEC_ERROR_INVALID_ARGS)
    216    STAN_MAP_ERROR(NSS_ERROR_UNSUPPORTED_TYPE, SEC_ERROR_INVALID_ARGS)
    217    STAN_MAP_ERROR(NSS_ERROR_BUFFER_TOO_SHORT, SEC_ERROR_INVALID_ARGS)
    218    STAN_MAP_ERROR(NSS_ERROR_INVALID_ATOB_CONTEXT, SEC_ERROR_INVALID_ARGS)
    219    STAN_MAP_ERROR(NSS_ERROR_INVALID_BTOA_CONTEXT, SEC_ERROR_INVALID_ARGS)
    220    STAN_MAP_ERROR(NSS_ERROR_INVALID_ITEM, SEC_ERROR_INVALID_ARGS)
    221    STAN_MAP_ERROR(NSS_ERROR_INVALID_STRING, SEC_ERROR_INVALID_ARGS)
    222    STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1ENCODER, SEC_ERROR_INVALID_ARGS)
    223    STAN_MAP_ERROR(NSS_ERROR_INVALID_ASN1DECODER, SEC_ERROR_INVALID_ARGS)
    224    STAN_MAP_ERROR(NSS_ERROR_UNKNOWN_ATTRIBUTE, SEC_ERROR_INVALID_ARGS)
    225    else { secError = SEC_ERROR_LIBRARY_FAILURE; }
    226    PORT_SetError(secError);
    227 }
    228 
    229 SECStatus
    230 CERT_ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert,
    231                     CERTCertTrust *trust)
    232 {
    233    SECStatus rv = SECSuccess;
    234    PRStatus ret;
    235 
    236    ret = STAN_ChangeCertTrust(cert, trust);
    237    if (ret != PR_SUCCESS) {
    238        rv = SECFailure;
    239        CERT_MapStanError();
    240    }
    241    return rv;
    242 }
    243 
    244 extern const NSSError NSS_ERROR_INVALID_CERTIFICATE;
    245 
    246 SECStatus
    247 __CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
    248                         CERTCertTrust *trust)
    249 {
    250    NSSUTF8 *stanNick;
    251    PK11SlotInfo *slot;
    252    NSSToken *internal;
    253    NSSCryptoContext *context;
    254    nssCryptokiObject *permInstance;
    255    NSSCertificate *c = STAN_GetNSSCertificate(cert);
    256    nssCertificateStoreTrace lockTrace = { NULL, NULL, PR_FALSE, PR_FALSE };
    257    nssCertificateStoreTrace unlockTrace = { NULL, NULL, PR_FALSE, PR_FALSE };
    258    SECStatus rv;
    259    PRStatus ret;
    260 
    261    if (c == NULL) {
    262        CERT_MapStanError();
    263        return SECFailure;
    264    }
    265 
    266    context = c->object.cryptoContext;
    267    if (!context) {
    268        PORT_SetError(SEC_ERROR_ADDING_CERT);
    269        return SECFailure; /* wasn't a temp cert */
    270    }
    271    stanNick = nssCertificate_GetNickname(c, NULL);
    272    if (stanNick && nickname && strcmp(nickname, stanNick) != 0) {
    273        /* different: take the new nickname */
    274        cert->nickname = NULL;
    275        nss_ZFreeIf(stanNick);
    276        stanNick = NULL;
    277    }
    278    if (!stanNick && nickname) {
    279        /* Either there was no nickname yet, or we have a new nickname */
    280        stanNick = nssUTF8_Duplicate((NSSUTF8 *)nickname, NULL);
    281    } /* else: old stanNick is identical to new nickname */
    282    /* Delete the temp instance */
    283    nssCertificateStore_Lock(context->certStore, &lockTrace);
    284    nssCertificateStore_RemoveCertLOCKED(context->certStore, c);
    285    nssCertificateStore_Unlock(context->certStore, &lockTrace, &unlockTrace);
    286    c->object.cryptoContext = NULL;
    287 
    288    /* if the id has not been set explicitly yet, create one from the public
    289     * key. */
    290    if (c->id.data == NULL) {
    291        SECItem *keyID = pk11_mkcertKeyID(cert);
    292        if (keyID) {
    293            nssItem_Create(c->object.arena, &c->id, keyID->len, keyID->data);
    294            SECITEM_FreeItem(keyID, PR_TRUE);
    295        }
    296        /* if any of these failed, continue with our null c->id */
    297    }
    298 
    299    /* Import the perm instance onto the internal token */
    300    slot = PK11_GetInternalKeySlot();
    301    internal = PK11Slot_GetNSSToken(slot);
    302    if (!internal) {
    303        PK11_FreeSlot(slot);
    304        PORT_SetError(SEC_ERROR_NO_TOKEN);
    305        return SECFailure;
    306    }
    307    permInstance = nssToken_ImportCertificate(
    308        internal, NULL, NSSCertificateType_PKIX, &c->id, stanNick, &c->encoding,
    309        &c->issuer, &c->subject, &c->serial, cert->emailAddr, PR_TRUE);
    310    (void)nssToken_Destroy(internal);
    311    nss_ZFreeIf(stanNick);
    312    stanNick = NULL;
    313    PK11_FreeSlot(slot);
    314    if (!permInstance) {
    315        if (NSS_GetError() == NSS_ERROR_INVALID_CERTIFICATE) {
    316            PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL);
    317        }
    318        return SECFailure;
    319    }
    320    nssPKIObject_AddInstance(&c->object, permInstance);
    321    nssTrustDomain_AddCertsToCache(STAN_GetDefaultTrustDomain(), &c, 1);
    322    /* reset the CERTCertificate fields */
    323    CERT_LockCertTempPerm(cert);
    324    cert->nssCertificate = NULL;
    325    CERT_UnlockCertTempPerm(cert);
    326    cert = STAN_GetCERTCertificateOrRelease(c); /* should return same pointer */
    327    if (!cert) {
    328        CERT_MapStanError();
    329        return SECFailure;
    330    }
    331    CERT_LockCertTempPerm(cert);
    332    cert->istemp = PR_FALSE;
    333    cert->isperm = PR_TRUE;
    334    CERT_UnlockCertTempPerm(cert);
    335    if (!trust) {
    336        return SECSuccess;
    337    }
    338    ret = STAN_ChangeCertTrust(cert, trust);
    339    rv = SECSuccess;
    340    if (ret != PR_SUCCESS) {
    341        rv = SECFailure;
    342        CERT_MapStanError();
    343    }
    344    return rv;
    345 }
    346 
    347 SECStatus
    348 CERT_AddTempCertToPerm(CERTCertificate *cert, char *nickname,
    349                       CERTCertTrust *trust)
    350 {
    351    return __CERT_AddTempCertToPerm(cert, nickname, trust);
    352 }
    353 
    354 CERTCertificate *
    355 CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
    356                        char *nickname, PRBool isperm, PRBool copyDER)
    357 {
    358    NSSCertificate *c;
    359    CERTCertificate *cc;
    360    NSSCertificate *tempCert = NULL;
    361    nssPKIObject *pkio;
    362    NSSCryptoContext *gCC = STAN_GetDefaultCryptoContext();
    363    NSSTrustDomain *gTD = STAN_GetDefaultTrustDomain();
    364    if (!isperm) {
    365        NSSDER encoding;
    366        NSSITEM_FROM_SECITEM(&encoding, derCert);
    367        /* First, see if it is already a temp cert */
    368        c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC,
    369                                                                 &encoding);
    370        if (!c && handle) {
    371            /* Then, see if it is already a perm cert */
    372            c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle,
    373                                                                   &encoding);
    374        }
    375        if (c) {
    376            /* actually, that search ends up going by issuer/serial,
    377             * so it is still possible to return a cert with the same
    378             * issuer/serial but a different encoding, and we're
    379             * going to reject that
    380             */
    381            if (!nssItem_Equal(&c->encoding, &encoding, NULL)) {
    382                nssCertificate_Destroy(c);
    383                PORT_SetError(SEC_ERROR_REUSED_ISSUER_AND_SERIAL);
    384                cc = NULL;
    385            } else {
    386                cc = STAN_GetCERTCertificateOrRelease(c);
    387                if (cc == NULL) {
    388                    CERT_MapStanError();
    389                }
    390            }
    391            return cc;
    392        }
    393    }
    394    pkio = nssPKIObject_Create(NULL, NULL, gTD, gCC, nssPKIMonitor);
    395    if (!pkio) {
    396        CERT_MapStanError();
    397        return NULL;
    398    }
    399    c = nss_ZNEW(pkio->arena, NSSCertificate);
    400    if (!c) {
    401        CERT_MapStanError();
    402        nssPKIObject_Destroy(pkio);
    403        return NULL;
    404    }
    405    c->object = *pkio;
    406    if (copyDER) {
    407        nssItem_Create(c->object.arena, &c->encoding, derCert->len,
    408                       derCert->data);
    409    } else {
    410        NSSITEM_FROM_SECITEM(&c->encoding, derCert);
    411    }
    412    /* Forces a decoding of the cert in order to obtain the parts used
    413     * below
    414     */
    415    /* 'c' is not adopted here, if we fail loser frees what has been
    416     * allocated so far for 'c' */
    417    cc = STAN_GetCERTCertificate(c);
    418    if (!cc) {
    419        CERT_MapStanError();
    420        goto loser;
    421    }
    422    nssItem_Create(c->object.arena, &c->issuer, cc->derIssuer.len,
    423                   cc->derIssuer.data);
    424    nssItem_Create(c->object.arena, &c->subject, cc->derSubject.len,
    425                   cc->derSubject.data);
    426    /* CERTCertificate stores serial numbers decoded.  I need the DER
    427     * here.  sigh.
    428     */
    429    SECItem derSerial = { 0 };
    430    CERT_SerialNumberFromDERCert(&cc->derCert, &derSerial);
    431    if (!derSerial.data)
    432        goto loser;
    433    nssItem_Create(c->object.arena, &c->serial, derSerial.len,
    434                   derSerial.data);
    435    PORT_Free(derSerial.data);
    436 
    437    if (nickname) {
    438        c->object.tempName =
    439            nssUTF8_Create(c->object.arena, nssStringType_UTF8String,
    440                           (NSSUTF8 *)nickname, PORT_Strlen(nickname));
    441    }
    442    if (cc->emailAddr && cc->emailAddr[0]) {
    443        c->email = nssUTF8_Create(
    444            c->object.arena, nssStringType_PrintableString,
    445            (NSSUTF8 *)cc->emailAddr, PORT_Strlen(cc->emailAddr));
    446    }
    447 
    448    tempCert = NSSCryptoContext_FindOrImportCertificate(gCC, c);
    449    if (!tempCert) {
    450        CERT_MapStanError();
    451        goto loser;
    452    }
    453    /* destroy our copy */
    454    NSSCertificate_Destroy(c);
    455    /* and use the stored entry */
    456    c = tempCert;
    457    cc = STAN_GetCERTCertificateOrRelease(c);
    458    if (!cc) {
    459        /* STAN_GetCERTCertificateOrRelease destroys c on failure. */
    460        CERT_MapStanError();
    461        return NULL;
    462    }
    463 
    464    CERT_LockCertTempPerm(cc);
    465    cc->istemp = PR_TRUE;
    466    cc->isperm = PR_FALSE;
    467    CERT_UnlockCertTempPerm(cc);
    468    return cc;
    469 loser:
    470    /* Perhaps this should be nssCertificate_Destroy(c) */
    471    nssPKIObject_Destroy(&c->object);
    472    return NULL;
    473 }
    474 
    475 /* This symbol is exported for backward compatibility. */
    476 CERTCertificate *
    477 __CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
    478                          char *nickname, PRBool isperm, PRBool copyDER)
    479 {
    480    return CERT_NewTempCertificate(handle, derCert, nickname, isperm, copyDER);
    481 }
    482 
    483 static CERTCertificate *
    484 common_FindCertByIssuerAndSN(CERTCertDBHandle *handle,
    485                             CERTIssuerAndSN *issuerAndSN,
    486                             void *wincx)
    487 {
    488    PK11SlotInfo *slot;
    489    CERTCertificate *cert;
    490 
    491    cert = PK11_FindCertByIssuerAndSN(&slot, issuerAndSN, wincx);
    492    if (cert && slot) {
    493        PK11_FreeSlot(slot);
    494    }
    495 
    496    return cert;
    497 }
    498 
    499 /* maybe all the wincx's should be some const for internal token login? */
    500 CERTCertificate *
    501 CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle,
    502                           CERTIssuerAndSN *issuerAndSN)
    503 {
    504    return common_FindCertByIssuerAndSN(handle, issuerAndSN, NULL);
    505 }
    506 
    507 /* maybe all the wincx's should be some const for internal token login? */
    508 CERTCertificate *
    509 CERT_FindCertByIssuerAndSNCX(CERTCertDBHandle *handle,
    510                             CERTIssuerAndSN *issuerAndSN,
    511                             void *wincx)
    512 {
    513    return common_FindCertByIssuerAndSN(handle, issuerAndSN, wincx);
    514 }
    515 
    516 static NSSCertificate *
    517 get_best_temp_or_perm(NSSCertificate *ct, NSSCertificate *cp)
    518 {
    519    NSSUsage usage;
    520    NSSCertificate *arr[3];
    521    if (!ct) {
    522        return nssCertificate_AddRef(cp);
    523    } else if (!cp) {
    524        return nssCertificate_AddRef(ct);
    525    }
    526    arr[0] = ct;
    527    arr[1] = cp;
    528    arr[2] = NULL;
    529    usage.anyUsage = PR_TRUE;
    530    return nssCertificateArray_FindBestCertificate(arr, NULL, &usage, NULL);
    531 }
    532 
    533 CERTCertificate *
    534 CERT_FindCertByName(CERTCertDBHandle *handle, SECItem *name)
    535 {
    536    NSSCertificate *cp, *ct, *c;
    537    NSSDER subject;
    538    NSSUsage usage;
    539    NSSCryptoContext *cc;
    540    NSSITEM_FROM_SECITEM(&subject, name);
    541    usage.anyUsage = PR_TRUE;
    542    cc = STAN_GetDefaultCryptoContext();
    543    ct = NSSCryptoContext_FindBestCertificateBySubject(cc, &subject, NULL,
    544                                                       &usage, NULL);
    545    cp = NSSTrustDomain_FindBestCertificateBySubject(handle, &subject, NULL,
    546                                                     &usage, NULL);
    547    c = get_best_temp_or_perm(ct, cp);
    548    if (ct) {
    549        CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
    550    }
    551    if (cp) {
    552        CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(cp));
    553    }
    554    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
    555 }
    556 
    557 CERTCertificate *
    558 CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID)
    559 {
    560    CERTCertList *list;
    561    CERTCertificate *cert = NULL;
    562    CERTCertListNode *node;
    563 
    564    list = CERT_CreateSubjectCertList(NULL, handle, name, 0, PR_FALSE);
    565    if (list == NULL)
    566        return NULL;
    567 
    568    node = CERT_LIST_HEAD(list);
    569    while (!CERT_LIST_END(node, list)) {
    570        if (node->cert &&
    571            SECITEM_ItemsAreEqual(&node->cert->subjectKeyID, keyID)) {
    572            cert = CERT_DupCertificate(node->cert);
    573            goto done;
    574        }
    575        node = CERT_LIST_NEXT(node);
    576    }
    577    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
    578 
    579 done:
    580    CERT_DestroyCertList(list);
    581    return cert;
    582 }
    583 
    584 CERTCertificate *
    585 CERT_FindCertByNickname(CERTCertDBHandle *handle, const char *nickname)
    586 {
    587    NSSCryptoContext *cc;
    588    NSSCertificate *c, *ct;
    589    CERTCertificate *cert;
    590    NSSUsage usage;
    591    usage.anyUsage = PR_TRUE;
    592    cc = STAN_GetDefaultCryptoContext();
    593    ct = NSSCryptoContext_FindBestCertificateByNickname(cc, nickname, NULL,
    594                                                        &usage, NULL);
    595    cert = PK11_FindCertFromNickname(nickname, NULL);
    596    c = NULL;
    597    if (cert) {
    598        c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
    599        CERT_DestroyCertificate(cert);
    600        if (ct) {
    601            CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
    602        }
    603    } else {
    604        c = ct;
    605    }
    606    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
    607 }
    608 
    609 CERTCertificate *
    610 CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert)
    611 {
    612    NSSCryptoContext *cc;
    613    NSSCertificate *c;
    614    NSSDER encoding;
    615    NSSITEM_FROM_SECITEM(&encoding, derCert);
    616    cc = STAN_GetDefaultCryptoContext();
    617    c = NSSCryptoContext_FindCertificateByEncodedCertificate(cc, &encoding);
    618    if (!c) {
    619        c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle,
    620                                                               &encoding);
    621        if (!c)
    622            return NULL;
    623    }
    624    return STAN_GetCERTCertificateOrRelease(c);
    625 }
    626 
    627 static CERTCertificate *
    628 common_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
    629                                             const char *name, PRBool anyUsage,
    630                                             SECCertUsage lookingForUsage,
    631                                             void *wincx)
    632 {
    633    NSSCryptoContext *cc;
    634    NSSCertificate *c, *ct;
    635    CERTCertificate *cert = NULL;
    636    NSSUsage usage;
    637    CERTCertList *certlist;
    638 
    639    if (NULL == name) {
    640        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    641        return NULL;
    642    }
    643 
    644    usage.anyUsage = anyUsage;
    645 
    646    if (!anyUsage) {
    647        usage.nss3lookingForCA = PR_FALSE;
    648        usage.nss3usage = lookingForUsage;
    649    }
    650 
    651    cc = STAN_GetDefaultCryptoContext();
    652    ct = NSSCryptoContext_FindBestCertificateByNickname(cc, name, NULL, &usage,
    653                                                        NULL);
    654    if (!ct && PORT_Strchr(name, '@') != NULL) {
    655        char *lowercaseName = CERT_FixupEmailAddr(name);
    656        if (lowercaseName) {
    657            ct = NSSCryptoContext_FindBestCertificateByEmail(
    658                cc, lowercaseName, NULL, &usage, NULL);
    659            PORT_Free(lowercaseName);
    660        }
    661    }
    662 
    663    if (anyUsage) {
    664        cert = PK11_FindCertFromNickname(name, wincx);
    665    } else {
    666        if (ct) {
    667            /* Does ct really have the required usage? */
    668            nssDecodedCert *dc;
    669            dc = nssCertificate_GetDecoding(ct);
    670            if (!dc->matchUsage(dc, &usage)) {
    671                CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
    672                ct = NULL;
    673            }
    674        }
    675 
    676        certlist = PK11_FindCertsFromNickname(name, wincx);
    677        if (certlist) {
    678            SECStatus rv =
    679                CERT_FilterCertListByUsage(certlist, lookingForUsage, PR_FALSE);
    680            if (SECSuccess == rv && !CERT_LIST_EMPTY(certlist)) {
    681                cert = CERT_DupCertificate(CERT_LIST_HEAD(certlist)->cert);
    682            }
    683            CERT_DestroyCertList(certlist);
    684        }
    685    }
    686 
    687    if (cert) {
    688        c = get_best_temp_or_perm(ct, STAN_GetNSSCertificate(cert));
    689        CERT_DestroyCertificate(cert);
    690        if (ct) {
    691            CERT_DestroyCertificate(STAN_GetCERTCertificateOrRelease(ct));
    692        }
    693    } else {
    694        c = ct;
    695    }
    696    return c ? STAN_GetCERTCertificateOrRelease(c) : NULL;
    697 }
    698 
    699 CERTCertificate *
    700 CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, const char *name)
    701 {
    702    return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_TRUE,
    703                                                        0, NULL);
    704 }
    705 
    706 CERTCertificate *
    707 CERT_FindCertByNicknameOrEmailAddrCX(CERTCertDBHandle *handle, const char *name,
    708                                     void *wincx)
    709 {
    710    return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_TRUE,
    711                                                        0, wincx);
    712 }
    713 
    714 CERTCertificate *
    715 CERT_FindCertByNicknameOrEmailAddrForUsage(CERTCertDBHandle *handle,
    716                                           const char *name,
    717                                           SECCertUsage lookingForUsage)
    718 {
    719    return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_FALSE,
    720                                                        lookingForUsage, NULL);
    721 }
    722 
    723 CERTCertificate *
    724 CERT_FindCertByNicknameOrEmailAddrForUsageCX(CERTCertDBHandle *handle,
    725                                             const char *name,
    726                                             SECCertUsage lookingForUsage,
    727                                             void *wincx)
    728 {
    729    return common_FindCertByNicknameOrEmailAddrForUsage(handle, name, PR_FALSE,
    730                                                        lookingForUsage, wincx);
    731 }
    732 
    733 static void
    734 add_to_subject_list(CERTCertList *certList, CERTCertificate *cert,
    735                    PRBool validOnly, PRTime sorttime)
    736 {
    737    SECStatus secrv;
    738    if (!validOnly ||
    739        CERT_CheckCertValidTimes(cert, sorttime, PR_FALSE) ==
    740            secCertTimeValid) {
    741        secrv = CERT_AddCertToListSorted(certList, cert, CERT_SortCBValidity,
    742                                         (void *)&sorttime);
    743        if (secrv != SECSuccess) {
    744            CERT_DestroyCertificate(cert);
    745        }
    746    } else {
    747        CERT_DestroyCertificate(cert);
    748    }
    749 }
    750 
    751 CERTCertList *
    752 CERT_CreateSubjectCertList(CERTCertList *certList, CERTCertDBHandle *handle,
    753                           const SECItem *name, PRTime sorttime,
    754                           PRBool validOnly)
    755 {
    756    NSSCryptoContext *cc;
    757    NSSCertificate **tSubjectCerts, **pSubjectCerts;
    758    NSSCertificate **ci;
    759    CERTCertificate *cert;
    760    NSSDER subject;
    761    PRBool myList = PR_FALSE;
    762    cc = STAN_GetDefaultCryptoContext();
    763    NSSITEM_FROM_SECITEM(&subject, name);
    764    /* Collect both temp and perm certs for the subject */
    765    tSubjectCerts =
    766        NSSCryptoContext_FindCertificatesBySubject(cc, &subject, NULL, 0, NULL);
    767    pSubjectCerts = NSSTrustDomain_FindCertificatesBySubject(handle, &subject,
    768                                                             NULL, 0, NULL);
    769    if (!tSubjectCerts && !pSubjectCerts) {
    770        return NULL;
    771    }
    772    if (certList == NULL) {
    773        certList = CERT_NewCertList();
    774        myList = PR_TRUE;
    775        if (!certList)
    776            goto loser;
    777    }
    778    /* Iterate over the matching temp certs.  Add them to the list */
    779    ci = tSubjectCerts;
    780    while (ci && *ci) {
    781        cert = STAN_GetCERTCertificateOrRelease(*ci);
    782        /* *ci may be invalid at this point, don't reference it again */
    783        if (cert) {
    784            /* NOTE: add_to_subject_list adopts the incoming cert. */
    785            add_to_subject_list(certList, cert, validOnly, sorttime);
    786        }
    787        ci++;
    788    }
    789    /* Iterate over the matching perm certs.  Add them to the list */
    790    ci = pSubjectCerts;
    791    while (ci && *ci) {
    792        cert = STAN_GetCERTCertificateOrRelease(*ci);
    793        /* *ci may be invalid at this point, don't reference it again */
    794        if (cert) {
    795            /* NOTE: add_to_subject_list adopts the incoming cert. */
    796            add_to_subject_list(certList, cert, validOnly, sorttime);
    797        }
    798        ci++;
    799    }
    800    /* all the references have been adopted or freed at this point, just
    801     * free the arrays now */
    802    nss_ZFreeIf(tSubjectCerts);
    803    nss_ZFreeIf(pSubjectCerts);
    804    return certList;
    805 loser:
    806    /* need to free the references in tSubjectCerts and pSubjectCerts! */
    807    nssCertificateArray_Destroy(tSubjectCerts);
    808    nssCertificateArray_Destroy(pSubjectCerts);
    809    if (myList && certList != NULL) {
    810        CERT_DestroyCertList(certList);
    811    }
    812    return NULL;
    813 }
    814 
    815 void
    816 CERT_DestroyCertificate(CERTCertificate *cert)
    817 {
    818    if (cert) {
    819        /* don't use STAN_GetNSSCertificate because we don't want to
    820         * go to the trouble of translating the CERTCertificate into
    821         * an NSSCertificate just to destroy it.  If it hasn't been done
    822         * yet, don't do it at all
    823         *
    824         * cert->nssCertificate contains its own locks and refcount, but as it
    825         * may be NULL, the pointer itself must be guarded by some other lock.
    826         * Rather than creating a new global lock for only this purpose, share
    827         * an existing global lock that happens to be taken near the write in
    828         * fill_CERTCertificateFields(). The longer-term goal is to refactor
    829         * all these global locks to be certificate-scoped. */
    830        CERT_MaybeLockCertTempPerm(cert);
    831        NSSCertificate *tmp = cert->nssCertificate;
    832        CERT_MaybeUnlockCertTempPerm(cert);
    833        if (tmp) {
    834            /* delete the NSSCertificate */
    835            NSSCertificate_Destroy(tmp);
    836        } else if (cert->arena) {
    837            PORT_FreeArena(cert->arena, PR_FALSE);
    838        }
    839    }
    840    return;
    841 }
    842 
    843 int
    844 CERT_GetDBContentVersion(CERTCertDBHandle *handle)
    845 {
    846    /* should read the DB content version from the pkcs #11 device */
    847    return 0;
    848 }
    849 
    850 SECStatus
    851 certdb_SaveSingleProfile(CERTCertificate *cert, const char *emailAddr,
    852                         SECItem *emailProfile, SECItem *profileTime)
    853 {
    854    PRTime oldtime;
    855    PRTime newtime;
    856    SECStatus rv = SECFailure;
    857    PRBool saveit;
    858    SECItem oldprof, oldproftime;
    859    SECItem *oldProfile = NULL;
    860    SECItem *oldProfileTime = NULL;
    861    PK11SlotInfo *slot = NULL;
    862    NSSCertificate *c;
    863    NSSCryptoContext *cc;
    864    nssSMIMEProfile *stanProfile = NULL;
    865    PRBool freeOldProfile = PR_FALSE;
    866 
    867    c = STAN_GetNSSCertificate(cert);
    868    if (!c)
    869        return SECFailure;
    870    cc = c->object.cryptoContext;
    871    if (cc != NULL) {
    872        stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
    873        if (stanProfile) {
    874            PORT_Assert(stanProfile->profileData);
    875            SECITEM_FROM_NSSITEM(&oldprof, stanProfile->profileData);
    876            oldProfile = &oldprof;
    877            SECITEM_FROM_NSSITEM(&oldproftime, stanProfile->profileTime);
    878            oldProfileTime = &oldproftime;
    879        }
    880    } else {
    881        oldProfile = PK11_FindSMimeProfile(&slot, (char *)emailAddr,
    882                                           &cert->derSubject, &oldProfileTime);
    883        freeOldProfile = PR_TRUE;
    884    }
    885 
    886    saveit = PR_FALSE;
    887 
    888    /* both profileTime and emailProfile have to exist or not exist */
    889    if (emailProfile == NULL) {
    890        profileTime = NULL;
    891    } else if (profileTime == NULL) {
    892        emailProfile = NULL;
    893    }
    894 
    895    if (oldProfileTime == NULL) {
    896        saveit = PR_TRUE;
    897    } else {
    898        /* there was already a profile for this email addr */
    899        if (profileTime) {
    900            /* we have an old and new profile - save whichever is more recent*/
    901            if (oldProfileTime->len == 0) {
    902                /* always replace if old entry doesn't have a time */
    903                oldtime = LL_MININT;
    904            } else {
    905                rv = DER_UTCTimeToTime(&oldtime, oldProfileTime);
    906                if (rv != SECSuccess) {
    907                    goto loser;
    908                }
    909            }
    910 
    911            rv = DER_UTCTimeToTime(&newtime, profileTime);
    912            if (rv != SECSuccess) {
    913                goto loser;
    914            }
    915 
    916            if (LL_CMP(newtime, >, oldtime)) {
    917                /* this is a newer profile, save it and cert */
    918                saveit = PR_TRUE;
    919            }
    920        } else {
    921            saveit = PR_TRUE;
    922        }
    923    }
    924 
    925    if (saveit) {
    926        if (cc) {
    927            if (stanProfile && profileTime && emailProfile) {
    928                /* stanProfile is already stored in the crypto context,
    929                 * overwrite the data
    930                 */
    931                NSSArena *arena = stanProfile->object.arena;
    932                stanProfile->profileTime = nssItem_Create(
    933                    arena, NULL, profileTime->len, profileTime->data);
    934                stanProfile->profileData = nssItem_Create(
    935                    arena, NULL, emailProfile->len, emailProfile->data);
    936            } else if (profileTime && emailProfile) {
    937                PRStatus nssrv;
    938                NSSItem profTime, profData;
    939                NSSITEM_FROM_SECITEM(&profTime, profileTime);
    940                NSSITEM_FROM_SECITEM(&profData, emailProfile);
    941                stanProfile = nssSMIMEProfile_Create(c, &profTime, &profData);
    942                if (!stanProfile)
    943                    goto loser;
    944                nssrv = nssCryptoContext_ImportSMIMEProfile(cc, stanProfile);
    945                rv = (nssrv == PR_SUCCESS) ? SECSuccess : SECFailure;
    946            }
    947        } else {
    948            rv = PK11_SaveSMimeProfile(slot, (char *)emailAddr,
    949                                       &cert->derSubject, emailProfile,
    950                                       profileTime);
    951        }
    952    } else {
    953        rv = SECSuccess;
    954    }
    955 
    956 loser:
    957    if (oldProfile && freeOldProfile) {
    958        SECITEM_FreeItem(oldProfile, PR_TRUE);
    959    }
    960    if (oldProfileTime && freeOldProfile) {
    961        SECITEM_FreeItem(oldProfileTime, PR_TRUE);
    962    }
    963    if (stanProfile) {
    964        nssSMIMEProfile_Destroy(stanProfile);
    965    }
    966    if (slot) {
    967        PK11_FreeSlot(slot);
    968    }
    969 
    970    return (rv);
    971 }
    972 
    973 /*
    974 *
    975 * Manage S/MIME profiles
    976 *
    977 */
    978 
    979 SECStatus
    980 CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile,
    981                      SECItem *profileTime)
    982 {
    983    const char *emailAddr;
    984    SECStatus rv;
    985    PRBool isperm = PR_FALSE;
    986 
    987    if (!cert) {
    988        return SECFailure;
    989    }
    990 
    991    if (cert->slot && !PK11_IsInternal(cert->slot)) {
    992        /* this cert comes from an external source, we need to add it
    993        to the cert db before creating an S/MIME profile */
    994        PK11SlotInfo *internalslot = PK11_GetInternalKeySlot();
    995        if (!internalslot) {
    996            return SECFailure;
    997        }
    998        rv = PK11_ImportCert(internalslot, cert, CK_INVALID_HANDLE, NULL,
    999                             PR_FALSE);
   1000 
   1001        PK11_FreeSlot(internalslot);
   1002        if (rv != SECSuccess) {
   1003            return SECFailure;
   1004        }
   1005    }
   1006 
   1007    rv = CERT_GetCertIsPerm(cert, &isperm);
   1008    if (rv != SECSuccess) {
   1009        return SECFailure;
   1010    }
   1011    if (cert->slot && isperm && CERT_IsUserCert(cert) &&
   1012        (!emailProfile || !emailProfile->len)) {
   1013        /* Don't clobber emailProfile for user certs. */
   1014        return SECSuccess;
   1015    }
   1016 
   1017    for (emailAddr = CERT_GetFirstEmailAddress(cert); emailAddr != NULL;
   1018         emailAddr = CERT_GetNextEmailAddress(cert, emailAddr)) {
   1019        rv = certdb_SaveSingleProfile(cert, emailAddr, emailProfile,
   1020                                      profileTime);
   1021        if (rv != SECSuccess) {
   1022            return SECFailure;
   1023        }
   1024    }
   1025    return SECSuccess;
   1026 }
   1027 
   1028 SECItem *
   1029 CERT_FindSMimeProfile(CERTCertificate *cert)
   1030 {
   1031    PK11SlotInfo *slot = NULL;
   1032    NSSCertificate *c;
   1033    NSSCryptoContext *cc;
   1034    SECItem *rvItem = NULL;
   1035 
   1036    if (!cert || !cert->emailAddr || !cert->emailAddr[0]) {
   1037        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1038        return NULL;
   1039    }
   1040    c = STAN_GetNSSCertificate(cert);
   1041    if (!c)
   1042        return NULL;
   1043    cc = c->object.cryptoContext;
   1044    if (cc != NULL) {
   1045        nssSMIMEProfile *stanProfile;
   1046        stanProfile = nssCryptoContext_FindSMIMEProfileForCertificate(cc, c);
   1047        if (stanProfile) {
   1048            rvItem =
   1049                SECITEM_AllocItem(NULL, NULL, stanProfile->profileData->size);
   1050            if (rvItem) {
   1051                rvItem->data = stanProfile->profileData->data;
   1052            }
   1053            nssSMIMEProfile_Destroy(stanProfile);
   1054        }
   1055        return rvItem;
   1056    }
   1057    rvItem =
   1058        PK11_FindSMimeProfile(&slot, cert->emailAddr, &cert->derSubject, NULL);
   1059    if (slot) {
   1060        PK11_FreeSlot(slot);
   1061    }
   1062    return rvItem;
   1063 }
   1064 
   1065 SECStatus
   1066 CERT_GetCertIsPerm(const CERTCertificate *cert, PRBool *isperm)
   1067 {
   1068    if (cert == NULL) {
   1069        return SECFailure;
   1070    }
   1071 
   1072    CERT_LockCertTempPerm(cert);
   1073    *isperm = cert->isperm;
   1074    CERT_UnlockCertTempPerm(cert);
   1075    return SECSuccess;
   1076 }
   1077 
   1078 SECStatus
   1079 CERT_GetCertIsTemp(const CERTCertificate *cert, PRBool *istemp)
   1080 {
   1081    if (cert == NULL) {
   1082        return SECFailure;
   1083    }
   1084 
   1085    CERT_LockCertTempPerm(cert);
   1086    *istemp = cert->istemp;
   1087    CERT_UnlockCertTempPerm(cert);
   1088    return SECSuccess;
   1089 }
   1090 
   1091 /*
   1092 * deprecated functions that are now just stubs.
   1093 */
   1094 /*
   1095 * Close the database
   1096 */
   1097 void
   1098 __CERT_ClosePermCertDB(CERTCertDBHandle *handle)
   1099 {
   1100    PORT_Assert("CERT_ClosePermCertDB is Deprecated" == NULL);
   1101    return;
   1102 }
   1103 
   1104 SECStatus
   1105 CERT_OpenCertDBFilename(CERTCertDBHandle *handle, char *certdbname,
   1106                        PRBool readOnly)
   1107 {
   1108    PORT_Assert("CERT_OpenCertDBFilename is Deprecated" == NULL);
   1109    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
   1110    return SECFailure;
   1111 }
   1112 
   1113 SECItem *
   1114 SECKEY_HashPassword(char *pw, SECItem *salt)
   1115 {
   1116    PORT_Assert("SECKEY_HashPassword is Deprecated" == NULL);
   1117    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
   1118    return NULL;
   1119 }
   1120 
   1121 SECStatus
   1122 __CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle,
   1123                                   SECItem *derSubject, void *cb, void *cbarg)
   1124 {
   1125    PORT_Assert("CERT_TraversePermCertsForSubject is Deprecated" == NULL);
   1126    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
   1127    return SECFailure;
   1128 }
   1129 
   1130 SECStatus
   1131 __CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname,
   1132                                    void *cb, void *cbarg)
   1133 {
   1134    PORT_Assert("CERT_TraversePermCertsForNickname is Deprecated" == NULL);
   1135    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
   1136    return SECFailure;
   1137 }