tor-browser

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

sslcert.c (30276B)


      1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
      2 /*
      3 * SSL server certificate configuration functions.
      4 *
      5 * This Source Code Form is subject to the terms of the Mozilla Public
      6 * License, v. 2.0. If a copy of the MPL was not distributed with this
      7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      8 
      9 #include "ssl.h"
     10 #include "sslimpl.h"
     11 #include "secoid.h"        /* for SECOID_GetAlgorithmTag */
     12 #include "pk11func.h"      /* for PK11_ReferenceSlot */
     13 #include "nss.h"           /* for NSS_RegisterShutdown */
     14 #include "prinit.h"        /* for PR_CallOnceWithArg */
     15 #include "tls13subcerts.h" /* for tls13_ReadDelegatedCredential */
     16 
     17 /* This global item is used only in servers.  It is is initialized by
     18 * SSL_ConfigSecureServer(), and is used in ssl3_SendCertificateRequest().
     19 */
     20 static struct {
     21    PRCallOnceType setup;
     22    CERTDistNames *names;
     23 } ssl_server_ca_list;
     24 
     25 static SECStatus
     26 ssl_ServerCAListShutdown(void *appData, void *nssData)
     27 {
     28    PORT_Assert(ssl_server_ca_list.names);
     29    if (ssl_server_ca_list.names) {
     30        CERT_FreeDistNames(ssl_server_ca_list.names);
     31    }
     32    PORT_Memset(&ssl_server_ca_list, 0, sizeof(ssl_server_ca_list));
     33    return SECSuccess;
     34 }
     35 
     36 static PRStatus
     37 ssl_SetupCAListOnce(void *arg)
     38 {
     39    CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg;
     40    SECStatus rv = NSS_RegisterShutdown(ssl_ServerCAListShutdown, NULL);
     41    PORT_Assert(SECSuccess == rv);
     42    if (SECSuccess == rv) {
     43        ssl_server_ca_list.names = CERT_GetSSLCACerts(dbHandle);
     44        return PR_SUCCESS;
     45    }
     46    return PR_FAILURE;
     47 }
     48 
     49 SECStatus
     50 ssl_SetupCAList(const sslSocket *ss)
     51 {
     52    if (PR_SUCCESS != PR_CallOnceWithArg(&ssl_server_ca_list.setup,
     53                                         &ssl_SetupCAListOnce,
     54                                         (void *)(ss->dbHandle))) {
     55        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
     56        return SECFailure;
     57    }
     58    return SECSuccess;
     59 }
     60 
     61 SECStatus
     62 ssl_GetCertificateRequestCAs(const sslSocket *ss, unsigned int *calen,
     63                             const SECItem **names, unsigned int *nnames)
     64 {
     65    const SECItem *name;
     66    const CERTDistNames *ca_list;
     67    unsigned int i;
     68 
     69    *calen = 0;
     70    *names = NULL;
     71    *nnames = 0;
     72 
     73    /* ssl3.ca_list is initialized to NULL, and never changed. */
     74    ca_list = ss->ssl3.ca_list;
     75    if (!ca_list) {
     76        if (ssl_SetupCAList(ss) != SECSuccess) {
     77            return SECFailure;
     78        }
     79        ca_list = ssl_server_ca_list.names;
     80    }
     81 
     82    if (ca_list != NULL) {
     83        *names = ca_list->names;
     84        *nnames = ca_list->nnames;
     85    }
     86 
     87    for (i = 0, name = *names; i < *nnames; i++, name++) {
     88        *calen += 2 + name->len;
     89    }
     90    return SECSuccess;
     91 }
     92 
     93 sslServerCert *
     94 ssl_NewServerCert()
     95 {
     96    sslServerCert *sc = PORT_ZNew(sslServerCert);
     97    if (!sc) {
     98        return NULL;
     99    }
    100    sc->authTypes = 0;
    101    sc->namedCurve = NULL;
    102    sc->serverCert = NULL;
    103    sc->serverCertChain = NULL;
    104    sc->certStatusArray = NULL;
    105    sc->signedCertTimestamps.len = 0;
    106    sc->delegCred.len = 0;
    107    sc->delegCredKeyPair = NULL;
    108    return sc;
    109 }
    110 
    111 sslServerCert *
    112 ssl_CopyServerCert(const sslServerCert *oc)
    113 {
    114    sslServerCert *sc;
    115 
    116    sc = ssl_NewServerCert();
    117    if (!sc) {
    118        return NULL;
    119    }
    120 
    121    sc->authTypes = oc->authTypes;
    122    sc->namedCurve = oc->namedCurve;
    123 
    124    if (oc->serverCert && oc->serverCertChain) {
    125        sc->serverCert = CERT_DupCertificate(oc->serverCert);
    126        if (!sc->serverCert)
    127            goto loser;
    128        sc->serverCertChain = CERT_DupCertList(oc->serverCertChain);
    129        if (!sc->serverCertChain)
    130            goto loser;
    131    } else {
    132        sc->serverCert = NULL;
    133        sc->serverCertChain = NULL;
    134    }
    135 
    136    if (oc->serverKeyPair) {
    137        sc->serverKeyPair = ssl_GetKeyPairRef(oc->serverKeyPair);
    138        if (!sc->serverKeyPair)
    139            goto loser;
    140    } else {
    141        sc->serverKeyPair = NULL;
    142    }
    143    sc->serverKeyBits = oc->serverKeyBits;
    144 
    145    if (oc->certStatusArray) {
    146        sc->certStatusArray = SECITEM_DupArray(NULL, oc->certStatusArray);
    147        if (!sc->certStatusArray)
    148            goto loser;
    149    } else {
    150        sc->certStatusArray = NULL;
    151    }
    152 
    153    if (SECITEM_CopyItem(NULL, &sc->signedCertTimestamps,
    154                         &oc->signedCertTimestamps) != SECSuccess) {
    155        goto loser;
    156    }
    157 
    158    if (SECITEM_CopyItem(NULL, &sc->delegCred, &oc->delegCred) != SECSuccess) {
    159        goto loser;
    160    }
    161    if (oc->delegCredKeyPair) {
    162        sc->delegCredKeyPair = ssl_GetKeyPairRef(oc->delegCredKeyPair);
    163    }
    164 
    165    return sc;
    166 loser:
    167    ssl_FreeServerCert(sc);
    168    return NULL;
    169 }
    170 
    171 void
    172 ssl_FreeServerCert(sslServerCert *sc)
    173 {
    174    if (!sc) {
    175        return;
    176    }
    177 
    178    if (sc->serverCert) {
    179        CERT_DestroyCertificate(sc->serverCert);
    180    }
    181    if (sc->serverCertChain) {
    182        CERT_DestroyCertificateList(sc->serverCertChain);
    183    }
    184    if (sc->serverKeyPair) {
    185        ssl_FreeKeyPair(sc->serverKeyPair);
    186    }
    187    if (sc->certStatusArray) {
    188        SECITEM_FreeArray(sc->certStatusArray, PR_TRUE);
    189    }
    190    if (sc->signedCertTimestamps.len) {
    191        SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE);
    192    }
    193    if (sc->delegCred.len) {
    194        SECITEM_FreeItem(&sc->delegCred, PR_FALSE);
    195    }
    196    if (sc->delegCredKeyPair) {
    197        ssl_FreeKeyPair(sc->delegCredKeyPair);
    198    }
    199    PORT_ZFree(sc, sizeof(*sc));
    200 }
    201 
    202 const sslServerCert *
    203 ssl_FindServerCert(const sslSocket *ss, SSLAuthType authType,
    204                   const sslNamedGroupDef *namedCurve)
    205 {
    206    PRCList *cursor;
    207 
    208    /* Bug 1749475: avoid UB while fuzzing session tickets */
    209    if ((unsigned)authType >= ssl_auth_size) {
    210        return NULL;
    211    }
    212 
    213    for (cursor = PR_NEXT_LINK(&ss->serverCerts);
    214         cursor != &ss->serverCerts;
    215         cursor = PR_NEXT_LINK(cursor)) {
    216        sslServerCert *cert = (sslServerCert *)cursor;
    217        if (!SSL_CERT_IS(cert, authType)) {
    218            continue;
    219        }
    220        if (SSL_CERT_IS_EC(cert)) {
    221            /* Note: For deprecated APIs, we need to be able to find and
    222               match a slot with any named curve. */
    223            if (namedCurve && cert->namedCurve != namedCurve) {
    224                continue;
    225            }
    226        }
    227        return cert;
    228    }
    229    return NULL;
    230 }
    231 
    232 static SECStatus
    233 ssl_PopulateServerCert(sslServerCert *sc, CERTCertificate *cert,
    234                       const CERTCertificateList *certChain)
    235 {
    236    if (sc->serverCert) {
    237        CERT_DestroyCertificate(sc->serverCert);
    238    }
    239    if (sc->serverCertChain) {
    240        CERT_DestroyCertificateList(sc->serverCertChain);
    241    }
    242 
    243    if (!cert) {
    244        sc->serverCert = NULL;
    245        sc->serverCertChain = NULL;
    246        return SECSuccess;
    247    }
    248 
    249    sc->serverCert = CERT_DupCertificate(cert);
    250    if (certChain) {
    251        sc->serverCertChain = CERT_DupCertList(certChain);
    252    } else {
    253        sc->serverCertChain =
    254            CERT_CertChainFromCert(sc->serverCert, certUsageSSLServer,
    255                                   PR_TRUE);
    256    }
    257    return sc->serverCertChain ? SECSuccess : SECFailure;
    258 }
    259 
    260 static SECStatus
    261 ssl_PopulateKeyPair(sslServerCert *sc, sslKeyPair *keyPair)
    262 {
    263    if (sc->serverKeyPair) {
    264        ssl_FreeKeyPair(sc->serverKeyPair);
    265        sc->serverKeyPair = NULL;
    266    }
    267    if (keyPair) {
    268        KeyType keyType = SECKEY_GetPublicKeyType(keyPair->pubKey);
    269        PORT_Assert(keyType == SECKEY_GetPrivateKeyType(keyPair->privKey));
    270 
    271        if (keyType == ecKey) {
    272            sc->namedCurve = ssl_ECPubKey2NamedGroup(keyPair->pubKey);
    273            if (!sc->namedCurve) {
    274                /* Unsupported curve. */
    275                PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
    276                return SECFailure;
    277            }
    278        }
    279 
    280        /* Get the size of the cert's public key, and remember it. */
    281        sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey);
    282        if (sc->serverKeyBits == 0 ||
    283            (keyType == rsaKey && sc->serverKeyBits > SSL_MAX_RSA_KEY_BITS)) {
    284            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    285            return SECFailure;
    286        }
    287 
    288        SECKEY_CacheStaticFlags(keyPair->privKey);
    289        sc->serverKeyPair = ssl_GetKeyPairRef(keyPair);
    290 
    291        if (SSL_CERT_IS(sc, ssl_auth_rsa_decrypt)) {
    292            /* This will update the global session ticket key pair with this
    293             * key, if a value hasn't been set already. */
    294            if (ssl_MaybeSetSelfEncryptKeyPair(keyPair) != SECSuccess) {
    295                return SECFailure;
    296            }
    297        }
    298    } else {
    299        sc->serverKeyPair = NULL;
    300        sc->namedCurve = NULL;
    301    }
    302    return SECSuccess;
    303 }
    304 
    305 static SECStatus
    306 ssl_PopulateOCSPResponses(sslServerCert *sc,
    307                          const SECItemArray *stapledOCSPResponses)
    308 {
    309    if (sc->certStatusArray) {
    310        SECITEM_FreeArray(sc->certStatusArray, PR_TRUE);
    311    }
    312    if (stapledOCSPResponses) {
    313        sc->certStatusArray = SECITEM_DupArray(NULL, stapledOCSPResponses);
    314        return sc->certStatusArray ? SECSuccess : SECFailure;
    315    } else {
    316        sc->certStatusArray = NULL;
    317    }
    318    return SECSuccess;
    319 }
    320 
    321 static SECStatus
    322 ssl_PopulateSignedCertTimestamps(sslServerCert *sc,
    323                                 const SECItem *signedCertTimestamps)
    324 {
    325    if (sc->signedCertTimestamps.len) {
    326        SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE);
    327    }
    328    if (signedCertTimestamps && signedCertTimestamps->len) {
    329        return SECITEM_CopyItem(NULL, &sc->signedCertTimestamps,
    330                                signedCertTimestamps);
    331    }
    332    return SECSuccess;
    333 }
    334 
    335 /* Installs the given delegated credential (DC) and DC private key into the
    336 * certificate.
    337 *
    338 * It's the caller's responsibility to ensure that the DC is well-formed and
    339 * that the DC public key matches the DC private key.
    340 */
    341 static SECStatus
    342 ssl_PopulateDelegatedCredential(sslServerCert *sc,
    343                                const SECItem *delegCred,
    344                                const SECKEYPrivateKey *delegCredPrivKey)
    345 {
    346    sslDelegatedCredential *dc = NULL;
    347 
    348    if (sc->delegCred.len) {
    349        SECITEM_FreeItem(&sc->delegCred, PR_FALSE);
    350    }
    351 
    352    if (sc->delegCredKeyPair) {
    353        ssl_FreeKeyPair(sc->delegCredKeyPair);
    354        sc->delegCredKeyPair = NULL;
    355    }
    356 
    357    /* Both the DC and its private are present. */
    358    if (delegCred && delegCredPrivKey) {
    359        SECStatus rv;
    360        SECKEYPublicKey *pub;
    361        SECKEYPrivateKey *priv;
    362 
    363        if (!delegCred->data || delegCred->len == 0) {
    364            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    365            goto loser;
    366        }
    367 
    368        /* Parse the DC. */
    369        rv = tls13_ReadDelegatedCredential(delegCred->data, delegCred->len, &dc);
    370        if (rv != SECSuccess) {
    371            goto loser;
    372        }
    373 
    374        /* Make a copy of the DC. */
    375        rv = SECITEM_CopyItem(NULL, &sc->delegCred, delegCred);
    376        if (rv != SECSuccess) {
    377            goto loser;
    378        }
    379 
    380        /* Make a copy of the DC private key. */
    381        priv = SECKEY_CopyPrivateKey(delegCredPrivKey);
    382        if (!priv) {
    383            goto loser;
    384        }
    385 
    386        /* parse public key from the DC. */
    387        pub = SECKEY_ExtractPublicKey(dc->spki);
    388        if (!pub) {
    389            goto loser;
    390        }
    391 
    392        sc->delegCredKeyPair = ssl_NewKeyPair(priv, pub);
    393 
    394        /* Attempting to configure either the DC or DC private key, but not both. */
    395    } else if (delegCred || delegCredPrivKey) {
    396        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    397        goto loser;
    398    }
    399 
    400    tls13_DestroyDelegatedCredential(dc);
    401    return SECSuccess;
    402 
    403 loser:
    404    tls13_DestroyDelegatedCredential(dc);
    405    return SECFailure;
    406 }
    407 
    408 /* Find any existing certificates that overlap with the new certificate and
    409 * either remove any supported authentication types that overlap with the new
    410 * certificate or - if they have no types left - remove them entirely. */
    411 static void
    412 ssl_ClearMatchingCerts(sslSocket *ss, sslAuthTypeMask authTypes,
    413                       const sslNamedGroupDef *namedCurve)
    414 {
    415    PRCList *cursor = PR_NEXT_LINK(&ss->serverCerts);
    416 
    417    while (cursor != &ss->serverCerts) {
    418        sslServerCert *sc = (sslServerCert *)cursor;
    419        cursor = PR_NEXT_LINK(cursor);
    420        if ((sc->authTypes & authTypes) == 0) {
    421            continue;
    422        }
    423        /* namedCurve will be NULL only for legacy functions. */
    424        if (namedCurve != NULL && sc->namedCurve != namedCurve) {
    425            continue;
    426        }
    427 
    428        sc->authTypes &= ~authTypes;
    429        if (sc->authTypes == 0) {
    430            PR_REMOVE_LINK(&sc->link);
    431            ssl_FreeServerCert(sc);
    432        }
    433    }
    434 }
    435 
    436 static SECStatus
    437 ssl_ConfigCert(sslSocket *ss, sslAuthTypeMask authTypes,
    438               CERTCertificate *cert, sslKeyPair *keyPair,
    439               const SSLExtraServerCertData *data)
    440 {
    441    SECStatus rv;
    442    sslServerCert *sc = NULL;
    443    int error_code = SEC_ERROR_NO_MEMORY;
    444 
    445    PORT_Assert(cert);
    446    PORT_Assert(keyPair);
    447    PORT_Assert(data);
    448    PORT_Assert(authTypes);
    449 
    450    if (!cert || !keyPair || !data || !authTypes) {
    451        error_code = SEC_ERROR_INVALID_ARGS;
    452        goto loser;
    453    }
    454 
    455    sc = ssl_NewServerCert();
    456    if (!sc) {
    457        goto loser;
    458    }
    459 
    460    sc->authTypes = authTypes;
    461    rv = ssl_PopulateServerCert(sc, cert, data->certChain);
    462    if (rv != SECSuccess) {
    463        goto loser;
    464    }
    465    rv = ssl_PopulateKeyPair(sc, keyPair);
    466    if (rv != SECSuccess) {
    467        error_code = PORT_GetError();
    468        goto loser;
    469    }
    470    rv = ssl_PopulateOCSPResponses(sc, data->stapledOCSPResponses);
    471    if (rv != SECSuccess) {
    472        goto loser;
    473    }
    474    rv = ssl_PopulateSignedCertTimestamps(sc, data->signedCertTimestamps);
    475    if (rv != SECSuccess) {
    476        goto loser;
    477    }
    478    rv = ssl_PopulateDelegatedCredential(sc, data->delegCred,
    479                                         data->delegCredPrivKey);
    480    if (rv != SECSuccess) {
    481        error_code = PORT_GetError();
    482        goto loser;
    483    }
    484    ssl_ClearMatchingCerts(ss, sc->authTypes, sc->namedCurve);
    485    PR_APPEND_LINK(&sc->link, &ss->serverCerts);
    486    return SECSuccess;
    487 
    488 loser:
    489    ssl_FreeServerCert(sc);
    490    PORT_SetError(error_code);
    491    return SECFailure;
    492 }
    493 
    494 static SSLAuthType
    495 ssl_GetEcdhAuthType(CERTCertificate *cert)
    496 {
    497    SECOidTag sigTag = SECOID_GetAlgorithmTag(&cert->signature);
    498    switch (sigTag) {
    499        case SEC_OID_PKCS1_RSA_ENCRYPTION:
    500        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
    501        case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
    502        case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
    503        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
    504        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
    505        case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
    506        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
    507        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
    508        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
    509            return ssl_auth_ecdh_rsa;
    510        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
    511        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
    512        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
    513        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
    514        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
    515        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
    516        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
    517            return ssl_auth_ecdh_ecdsa;
    518        default:
    519            return ssl_auth_null;
    520    }
    521 }
    522 
    523 /* This function examines the type of certificate and its key usage and
    524 * chooses which authTypes apply.  For some certificates
    525 * this can mean that multiple authTypes.
    526 *
    527 * If the targetAuthType is not ssl_auth_null, then only that type will be used.
    528 * If that choice is invalid, then this function will fail. */
    529 static sslAuthTypeMask
    530 ssl_GetCertificateAuthTypes(CERTCertificate *cert, SSLAuthType targetAuthType)
    531 {
    532    sslAuthTypeMask authTypes = 0;
    533    SECOidTag tag;
    534 
    535    tag = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
    536    switch (tag) {
    537        case SEC_OID_X500_RSA_ENCRYPTION:
    538        case SEC_OID_PKCS1_RSA_ENCRYPTION:
    539            if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
    540                authTypes |= 1 << ssl_auth_rsa_sign;
    541            }
    542 
    543            if (cert->keyUsage & KU_KEY_ENCIPHERMENT) {
    544                /* If ku_sig=true we configure signature and encryption slots with the
    545                 * same cert. This is bad form, but there are enough dual-usage RSA
    546                 * certs that we can't really break by limiting this to one type. */
    547                authTypes |= 1 << ssl_auth_rsa_decrypt;
    548            }
    549            break;
    550 
    551        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
    552            if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
    553                authTypes |= 1 << ssl_auth_rsa_pss;
    554            }
    555            break;
    556 
    557        case SEC_OID_ANSIX9_DSA_SIGNATURE:
    558            if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
    559                authTypes |= 1 << ssl_auth_dsa;
    560            }
    561            break;
    562 
    563        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
    564            if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
    565                authTypes |= 1 << ssl_auth_ecdsa;
    566            }
    567            /* Again, bad form to have dual usage and we don't prevent it. */
    568            if (cert->keyUsage & KU_KEY_ENCIPHERMENT) {
    569                authTypes |= 1 << ssl_GetEcdhAuthType(cert);
    570            }
    571            break;
    572 
    573        default:
    574            break;
    575    }
    576 
    577    /* Check that we successfully picked an authType */
    578    if (targetAuthType != ssl_auth_null) {
    579        authTypes &= 1 << targetAuthType;
    580    }
    581    return authTypes;
    582 }
    583 
    584 /* This function adopts pubKey and destroys it if things go wrong. */
    585 static sslKeyPair *
    586 ssl_MakeKeyPairForCert(SECKEYPrivateKey *key, CERTCertificate *cert)
    587 {
    588    sslKeyPair *keyPair = NULL;
    589    SECKEYPublicKey *pubKey = NULL;
    590    SECKEYPrivateKey *privKeyCopy = NULL;
    591    PK11SlotInfo *bestSlot;
    592 
    593    pubKey = CERT_ExtractPublicKey(cert);
    594    if (!pubKey) {
    595        PORT_SetError(SEC_ERROR_NO_MEMORY);
    596        return NULL;
    597    }
    598 
    599    if (SECKEY_GetPublicKeyType(pubKey) != SECKEY_GetPrivateKeyType(key)) {
    600        SECKEY_DestroyPublicKey(pubKey);
    601        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    602        return NULL;
    603    }
    604 
    605    if (key->pkcs11Slot) {
    606        bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
    607        if (bestSlot) {
    608            privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
    609            PK11_FreeSlot(bestSlot);
    610        }
    611    }
    612    if (!privKeyCopy) {
    613        CK_MECHANISM_TYPE keyMech = PK11_MapSignKeyType(key->keyType);
    614        /* XXX Maybe should be bestSlotMultiple? */
    615        bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
    616        if (bestSlot) {
    617            privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
    618            PK11_FreeSlot(bestSlot);
    619        }
    620    }
    621    if (!privKeyCopy) {
    622        privKeyCopy = SECKEY_CopyPrivateKey(key);
    623    }
    624    if (privKeyCopy) {
    625        keyPair = ssl_NewKeyPair(privKeyCopy, pubKey);
    626    }
    627    if (!keyPair) {
    628        if (privKeyCopy) {
    629            SECKEY_DestroyPrivateKey(privKeyCopy);
    630        }
    631        SECKEY_DestroyPublicKey(pubKey);
    632        PORT_SetError(SEC_ERROR_NO_MEMORY);
    633    }
    634    return keyPair;
    635 }
    636 
    637 /* Configure a certificate and private key.
    638 *
    639 * This function examines the certificate and key to determine the type (or
    640 * types) of authentication the certificate supports.  As long as certificates
    641 * are different (different authTypes and maybe keys in different ec groups),
    642 * then this function can be called multiple times.
    643 */
    644 SECStatus
    645 SSL_ConfigServerCert(PRFileDesc *fd, CERTCertificate *cert,
    646                     SECKEYPrivateKey *key,
    647                     const SSLExtraServerCertData *data, unsigned int data_len)
    648 {
    649    sslSocket *ss;
    650    sslKeyPair *keyPair;
    651    SECStatus rv;
    652    SSLExtraServerCertData dataCopy = {
    653        ssl_auth_null, NULL, NULL, NULL, NULL, NULL
    654    };
    655    sslAuthTypeMask authTypes;
    656 
    657    ss = ssl_FindSocket(fd);
    658    if (!ss) {
    659        return SECFailure;
    660    }
    661 
    662    if (!cert || !key) {
    663        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    664        return SECFailure;
    665    }
    666 
    667    if (data) {
    668        if (data_len > sizeof(dataCopy)) {
    669            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    670            return SECFailure;
    671        }
    672        PORT_Memcpy(&dataCopy, data, data_len);
    673    }
    674 
    675    authTypes = ssl_GetCertificateAuthTypes(cert, dataCopy.authType);
    676    if (!authTypes) {
    677        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    678        return SECFailure;
    679    }
    680 
    681    keyPair = ssl_MakeKeyPairForCert(key, cert);
    682    if (!keyPair) {
    683        return SECFailure;
    684    }
    685 
    686    rv = ssl_ConfigCert(ss, authTypes, cert, keyPair, &dataCopy);
    687    ssl_FreeKeyPair(keyPair);
    688    if (rv != SECSuccess) {
    689        return SECFailure;
    690    }
    691    return SECSuccess;
    692 }
    693 
    694 /*******************************************************************/
    695 /* Deprecated functions.
    696 *
    697 * The remainder of this file contains deprecated functions for server
    698 * certificate configuration.  These configure certificates incorrectly, but in
    699 * a way that allows old code to continue working without change.  All these
    700 * functions create certificate slots based on SSLKEAType values.  Some values
    701 * of SSLKEAType cause multiple certificates to be configured.
    702 */
    703 
    704 SECStatus
    705 SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
    706                       SECKEYPrivateKey *key, SSLKEAType kea)
    707 {
    708    return SSL_ConfigSecureServerWithCertChain(fd, cert, NULL, key, kea);
    709 }
    710 
    711 /* This implements a limited check that is consistent with the checks performed
    712 * by older versions of NSS.  This is less rigorous than the checks in
    713 * ssl_ConfigCertByUsage(), only checking against the type of key and ignoring
    714 * things like usage. */
    715 static PRBool
    716 ssl_CertSuitableForAuthType(CERTCertificate *cert, sslAuthTypeMask authTypes)
    717 {
    718    SECOidTag tag = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
    719    sslAuthTypeMask mask = 0;
    720    switch (tag) {
    721        case SEC_OID_X500_RSA_ENCRYPTION:
    722        case SEC_OID_PKCS1_RSA_ENCRYPTION:
    723            mask |= 1 << ssl_auth_rsa_decrypt;
    724            mask |= 1 << ssl_auth_rsa_sign;
    725            break;
    726        case SEC_OID_ANSIX9_DSA_SIGNATURE:
    727            mask |= 1 << ssl_auth_dsa;
    728            break;
    729        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
    730            mask |= 1 << ssl_auth_ecdsa;
    731            mask |= 1 << ssl_auth_ecdh_rsa;
    732            mask |= 1 << ssl_auth_ecdh_ecdsa;
    733            break;
    734        default:
    735            break;
    736    }
    737    PORT_Assert(authTypes);
    738    /* Simply test that no inappropriate auth types are set. */
    739    return (authTypes & ~mask) == 0;
    740 }
    741 
    742 /* Lookup a cert for the legacy configuration functions.  An exact match on
    743 * authTypes and ignoring namedCurve will ensure that values configured using
    744 * legacy functions are overwritten by other legacy functions. */
    745 static sslServerCert *
    746 ssl_FindCertWithMask(sslSocket *ss, sslAuthTypeMask authTypes)
    747 {
    748    PRCList *cursor;
    749 
    750    for (cursor = PR_NEXT_LINK(&ss->serverCerts);
    751         cursor != &ss->serverCerts;
    752         cursor = PR_NEXT_LINK(cursor)) {
    753        sslServerCert *cert = (sslServerCert *)cursor;
    754        if (cert->authTypes == authTypes) {
    755            return cert;
    756        }
    757    }
    758    return NULL;
    759 }
    760 
    761 /* This finds an existing server cert in a matching slot that can be reused.
    762 * Failing that, it removes any other certs that might conflict and makes a new
    763 * server cert slot of the right type. */
    764 static sslServerCert *
    765 ssl_FindOrMakeCert(sslSocket *ss, sslAuthTypeMask authTypes)
    766 {
    767    sslServerCert *sc;
    768 
    769    /* Reuse a perfect match.  Note that there is a problem here with use of
    770     * multiple EC certificates that have keys on different curves: these
    771     * deprecated functions will match the first found and overwrite that
    772     * certificate, potentially leaving the other values with a duplicate curve.
    773     * Configuring multiple EC certificates are only possible with the new
    774     * functions, so this is not something that is worth fixing.  */
    775    sc = ssl_FindCertWithMask(ss, authTypes);
    776    if (sc) {
    777        PR_REMOVE_LINK(&sc->link);
    778        return sc;
    779    }
    780 
    781    /* Ignore the namedCurve parameter. Like above, this means that legacy
    782     * functions will clobber values set with the new functions blindly. */
    783    ssl_ClearMatchingCerts(ss, authTypes, NULL);
    784 
    785    sc = ssl_NewServerCert();
    786    if (sc) {
    787        sc->authTypes = authTypes;
    788    }
    789    return sc;
    790 }
    791 
    792 static sslAuthTypeMask
    793 ssl_KeaTypeToAuthTypeMask(SSLKEAType keaType)
    794 {
    795    switch (keaType) {
    796        case ssl_kea_rsa:
    797            return (1 << ssl_auth_rsa_decrypt) |
    798                   (1 << ssl_auth_rsa_sign);
    799 
    800        case ssl_kea_dh:
    801            return 1 << ssl_auth_dsa;
    802 
    803        case ssl_kea_ecdh:
    804            return (1 << ssl_auth_ecdsa) |
    805                   (1 << ssl_auth_ecdh_rsa) |
    806                   (1 << ssl_auth_ecdh_ecdsa);
    807 
    808        default:
    809            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    810    }
    811    return 0;
    812 }
    813 
    814 static SECStatus
    815 ssl_AddCertChain(sslSocket *ss, CERTCertificate *cert,
    816                 const CERTCertificateList *certChainOpt,
    817                 SECKEYPrivateKey *key, sslAuthTypeMask authTypes)
    818 {
    819    sslServerCert *sc;
    820    sslKeyPair *keyPair;
    821    SECStatus rv;
    822    PRErrorCode err = SEC_ERROR_NO_MEMORY;
    823 
    824    if (!ssl_CertSuitableForAuthType(cert, authTypes)) {
    825        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    826        return SECFailure;
    827    }
    828 
    829    sc = ssl_FindOrMakeCert(ss, authTypes);
    830    if (!sc) {
    831        goto loser;
    832    }
    833 
    834    rv = ssl_PopulateServerCert(sc, cert, certChainOpt);
    835    if (rv != SECSuccess) {
    836        goto loser;
    837    }
    838 
    839    keyPair = ssl_MakeKeyPairForCert(key, cert);
    840    if (!keyPair) {
    841        /* Error code is set by ssl_MakeKeyPairForCert */
    842        goto loser;
    843    }
    844    rv = ssl_PopulateKeyPair(sc, keyPair);
    845    ssl_FreeKeyPair(keyPair);
    846    if (rv != SECSuccess) {
    847        err = PORT_GetError();
    848        goto loser;
    849    }
    850 
    851    PR_APPEND_LINK(&sc->link, &ss->serverCerts);
    852    return SECSuccess;
    853 
    854 loser:
    855    ssl_FreeServerCert(sc);
    856    PORT_SetError(err);
    857    return SECFailure;
    858 }
    859 
    860 /* Public deprecated function */
    861 SECStatus
    862 SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
    863                                    const CERTCertificateList *certChainOpt,
    864                                    SECKEYPrivateKey *key, SSLKEAType certType)
    865 {
    866    sslSocket *ss;
    867    sslAuthTypeMask authTypes;
    868 
    869    ss = ssl_FindSocket(fd);
    870    if (!ss) {
    871        return SECFailure;
    872    }
    873 
    874    if (!cert != !key) { /* Configure both, or neither */
    875        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    876        return SECFailure;
    877    }
    878 
    879    authTypes = ssl_KeaTypeToAuthTypeMask(certType);
    880    if (!authTypes) {
    881        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    882        return SECFailure;
    883    }
    884 
    885    if (!cert) {
    886        sslServerCert *sc = ssl_FindCertWithMask(ss, authTypes);
    887        if (sc) {
    888            (void)ssl_PopulateServerCert(sc, NULL, NULL);
    889            (void)ssl_PopulateKeyPair(sc, NULL);
    890            /* Leave the entry linked here because the old API expects that.
    891             * There might be OCSP stapling values or signed certificate
    892             * timestamps still present that will subsequently be used. */
    893        }
    894        return SECSuccess;
    895    }
    896 
    897    return ssl_AddCertChain(ss, cert, certChainOpt, key, authTypes);
    898 }
    899 
    900 /* Public deprecated function */
    901 SECStatus
    902 SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
    903                            SSLKEAType certType)
    904 {
    905    sslSocket *ss;
    906    sslServerCert *sc;
    907    sslAuthTypeMask authTypes;
    908    SECStatus rv;
    909 
    910    ss = ssl_FindSocket(fd);
    911    if (!ss) {
    912        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetStapledOCSPResponses",
    913                 SSL_GETPID(), fd));
    914        return SECFailure;
    915    }
    916 
    917    authTypes = ssl_KeaTypeToAuthTypeMask(certType);
    918    if (!authTypes) {
    919        SSL_DBG(("%d: SSL[%d]: invalid cert type in SSL_SetStapledOCSPResponses",
    920                 SSL_GETPID(), fd));
    921        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    922        return SECFailure;
    923    }
    924 
    925    if (!responses) {
    926        sc = ssl_FindCertWithMask(ss, authTypes);
    927        if (sc) {
    928            (void)ssl_PopulateOCSPResponses(sc, NULL);
    929        }
    930        return SECSuccess;
    931    }
    932 
    933    sc = ssl_FindOrMakeCert(ss, authTypes);
    934    if (!sc) {
    935        return SECFailure;
    936    }
    937 
    938    rv = ssl_PopulateOCSPResponses(sc, responses);
    939    if (rv == SECSuccess) {
    940        PR_APPEND_LINK(&sc->link, &ss->serverCerts);
    941    } else {
    942        ssl_FreeServerCert(sc);
    943    }
    944    return rv;
    945 }
    946 
    947 /* Public deprecated function */
    948 SECStatus
    949 SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts,
    950                            SSLKEAType certType)
    951 {
    952    sslSocket *ss;
    953    sslServerCert *sc;
    954    sslAuthTypeMask authTypes;
    955    SECStatus rv;
    956 
    957    ss = ssl_FindSocket(fd);
    958    if (!ss) {
    959        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSignedCertTimestamps",
    960                 SSL_GETPID(), fd));
    961        return SECFailure;
    962    }
    963 
    964    authTypes = ssl_KeaTypeToAuthTypeMask(certType);
    965    if (!authTypes) {
    966        SSL_DBG(("%d: SSL[%d]: invalid cert type in SSL_SetSignedCertTimestamps",
    967                 SSL_GETPID(), fd));
    968        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    969        return SECFailure;
    970    }
    971 
    972    if (!scts) {
    973        sc = ssl_FindCertWithMask(ss, authTypes);
    974        if (sc) {
    975            (void)ssl_PopulateSignedCertTimestamps(sc, NULL);
    976        }
    977        return SECSuccess;
    978    }
    979 
    980    sc = ssl_FindOrMakeCert(ss, authTypes);
    981    if (!sc) {
    982        return SECFailure;
    983    }
    984 
    985    rv = ssl_PopulateSignedCertTimestamps(sc, scts);
    986    if (rv == SECSuccess) {
    987        PR_APPEND_LINK(&sc->link, &ss->serverCerts);
    988    } else {
    989        ssl_FreeServerCert(sc);
    990    }
    991    return rv;
    992 }
    993 
    994 /* Public deprecated function. */
    995 SSLKEAType
    996 NSS_FindCertKEAType(CERTCertificate *cert)
    997 {
    998    int tag;
    999 
   1000    if (!cert)
   1001        return ssl_kea_null;
   1002 
   1003    tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
   1004    switch (tag) {
   1005        case SEC_OID_X500_RSA_ENCRYPTION:
   1006        case SEC_OID_PKCS1_RSA_ENCRYPTION:
   1007            return ssl_kea_rsa;
   1008        case SEC_OID_ANSIX9_DSA_SIGNATURE: /* hah, signature, not a key? */
   1009        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
   1010            return ssl_kea_dh;
   1011        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
   1012            return ssl_kea_ecdh;
   1013        default:
   1014            return ssl_kea_null;
   1015    }
   1016 }