Coverage Report

Created: 2025-07-11 07:06

/src/nss/lib/ssl/sslcert.c
Line
Count
Source (jump to first uncovered line)
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
4
{
28
4
    PORT_Assert(ssl_server_ca_list.names);
29
4
    if (ssl_server_ca_list.names) {
30
4
        CERT_FreeDistNames(ssl_server_ca_list.names);
31
4
    }
32
4
    PORT_Memset(&ssl_server_ca_list, 0, sizeof(ssl_server_ca_list));
33
4
    return SECSuccess;
34
4
}
35
36
static PRStatus
37
ssl_SetupCAListOnce(void *arg)
38
4
{
39
4
    CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg;
40
4
    SECStatus rv = NSS_RegisterShutdown(ssl_ServerCAListShutdown, NULL);
41
4
    PORT_Assert(SECSuccess == rv);
42
4
    if (SECSuccess == rv) {
43
4
        ssl_server_ca_list.names = CERT_GetSSLCACerts(dbHandle);
44
4
        return PR_SUCCESS;
45
4
    }
46
0
    return PR_FAILURE;
47
4
}
48
49
SECStatus
50
ssl_SetupCAList(const sslSocket *ss)
51
24.1k
{
52
24.1k
    if (PR_SUCCESS != PR_CallOnceWithArg(&ssl_server_ca_list.setup,
53
24.1k
                                         &ssl_SetupCAListOnce,
54
24.1k
                                         (void *)(ss->dbHandle))) {
55
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
56
0
        return SECFailure;
57
0
    }
58
24.1k
    return SECSuccess;
59
24.1k
}
60
61
SECStatus
62
ssl_GetCertificateRequestCAs(const sslSocket *ss, unsigned int *calen,
63
                             const SECItem **names, unsigned int *nnames)
64
24.1k
{
65
24.1k
    const SECItem *name;
66
24.1k
    const CERTDistNames *ca_list;
67
24.1k
    unsigned int i;
68
69
24.1k
    *calen = 0;
70
24.1k
    *names = NULL;
71
24.1k
    *nnames = 0;
72
73
    /* ssl3.ca_list is initialized to NULL, and never changed. */
74
24.1k
    ca_list = ss->ssl3.ca_list;
75
24.1k
    if (!ca_list) {
76
24.1k
        if (ssl_SetupCAList(ss) != SECSuccess) {
77
0
            return SECFailure;
78
0
        }
79
24.1k
        ca_list = ssl_server_ca_list.names;
80
24.1k
    }
81
82
24.1k
    if (ca_list != NULL) {
83
24.1k
        *names = ca_list->names;
84
24.1k
        *nnames = ca_list->nnames;
85
24.1k
    }
86
87
24.1k
    for (i = 0, name = *names; i < *nnames; i++, name++) {
88
0
        *calen += 2 + name->len;
89
0
    }
90
24.1k
    return SECSuccess;
91
24.1k
}
92
93
sslServerCert *
94
ssl_NewServerCert()
95
62.1k
{
96
62.1k
    sslServerCert *sc = PORT_ZNew(sslServerCert);
97
62.1k
    if (!sc) {
98
0
        return NULL;
99
0
    }
100
62.1k
    sc->authTypes = 0;
101
62.1k
    sc->namedCurve = NULL;
102
62.1k
    sc->serverCert = NULL;
103
62.1k
    sc->serverCertChain = NULL;
104
62.1k
    sc->certStatusArray = NULL;
105
62.1k
    sc->signedCertTimestamps.len = 0;
106
62.1k
    sc->delegCred.len = 0;
107
62.1k
    sc->delegCredKeyPair = NULL;
108
62.1k
    return sc;
109
62.1k
}
110
111
sslServerCert *
112
ssl_CopyServerCert(const sslServerCert *oc)
113
62.1k
{
114
62.1k
    sslServerCert *sc;
115
116
62.1k
    sc = ssl_NewServerCert();
117
62.1k
    if (!sc) {
118
0
        return NULL;
119
0
    }
120
121
62.1k
    sc->authTypes = oc->authTypes;
122
62.1k
    sc->namedCurve = oc->namedCurve;
123
124
62.1k
    if (oc->serverCert && oc->serverCertChain) {
125
62.1k
        sc->serverCert = CERT_DupCertificate(oc->serverCert);
126
62.1k
        if (!sc->serverCert)
127
0
            goto loser;
128
62.1k
        sc->serverCertChain = CERT_DupCertList(oc->serverCertChain);
129
62.1k
        if (!sc->serverCertChain)
130
0
            goto loser;
131
62.1k
    } else {
132
0
        sc->serverCert = NULL;
133
0
        sc->serverCertChain = NULL;
134
0
    }
135
136
62.1k
    if (oc->serverKeyPair) {
137
62.1k
        sc->serverKeyPair = ssl_GetKeyPairRef(oc->serverKeyPair);
138
62.1k
        if (!sc->serverKeyPair)
139
0
            goto loser;
140
62.1k
    } else {
141
0
        sc->serverKeyPair = NULL;
142
0
    }
143
62.1k
    sc->serverKeyBits = oc->serverKeyBits;
144
145
62.1k
    if (oc->certStatusArray) {
146
0
        sc->certStatusArray = SECITEM_DupArray(NULL, oc->certStatusArray);
147
0
        if (!sc->certStatusArray)
148
0
            goto loser;
149
62.1k
    } else {
150
62.1k
        sc->certStatusArray = NULL;
151
62.1k
    }
152
153
62.1k
    if (SECITEM_CopyItem(NULL, &sc->signedCertTimestamps,
154
62.1k
                         &oc->signedCertTimestamps) != SECSuccess) {
155
0
        goto loser;
156
0
    }
157
158
62.1k
    if (SECITEM_CopyItem(NULL, &sc->delegCred, &oc->delegCred) != SECSuccess) {
159
0
        goto loser;
160
0
    }
161
62.1k
    if (oc->delegCredKeyPair) {
162
0
        sc->delegCredKeyPair = ssl_GetKeyPairRef(oc->delegCredKeyPair);
163
0
    }
164
165
62.1k
    return sc;
166
0
loser:
167
0
    ssl_FreeServerCert(sc);
168
0
    return NULL;
169
62.1k
}
170
171
void
172
ssl_FreeServerCert(sslServerCert *sc)
173
62.1k
{
174
62.1k
    if (!sc) {
175
0
        return;
176
0
    }
177
178
62.1k
    if (sc->serverCert) {
179
62.1k
        CERT_DestroyCertificate(sc->serverCert);
180
62.1k
    }
181
62.1k
    if (sc->serverCertChain) {
182
62.1k
        CERT_DestroyCertificateList(sc->serverCertChain);
183
62.1k
    }
184
62.1k
    if (sc->serverKeyPair) {
185
62.1k
        ssl_FreeKeyPair(sc->serverKeyPair);
186
62.1k
    }
187
62.1k
    if (sc->certStatusArray) {
188
0
        SECITEM_FreeArray(sc->certStatusArray, PR_TRUE);
189
0
    }
190
62.1k
    if (sc->signedCertTimestamps.len) {
191
0
        SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE);
192
0
    }
193
62.1k
    if (sc->delegCred.len) {
194
0
        SECITEM_FreeItem(&sc->delegCred, PR_FALSE);
195
0
    }
196
62.1k
    if (sc->delegCredKeyPair) {
197
0
        ssl_FreeKeyPair(sc->delegCredKeyPair);
198
0
    }
199
62.1k
    PORT_ZFree(sc, sizeof(*sc));
200
62.1k
}
201
202
const sslServerCert *
203
ssl_FindServerCert(const sslSocket *ss, SSLAuthType authType,
204
                   const sslNamedGroupDef *namedCurve)
205
6
{
206
6
    PRCList *cursor;
207
208
    /* Bug 1749475: avoid UB while fuzzing session tickets */
209
6
    if ((unsigned)authType >= ssl_auth_size) {
210
1
        return NULL;
211
1
    }
212
213
5
    for (cursor = PR_NEXT_LINK(&ss->serverCerts);
214
11
         cursor != &ss->serverCerts;
215
9
         cursor = PR_NEXT_LINK(cursor)) {
216
9
        sslServerCert *cert = (sslServerCert *)cursor;
217
9
        if (!SSL_CERT_IS(cert, authType)) {
218
5
            continue;
219
5
        }
220
4
        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
2
            if (namedCurve && cert->namedCurve != namedCurve) {
224
1
                continue;
225
1
            }
226
2
        }
227
3
        return cert;
228
4
    }
229
2
    return NULL;
230
5
}
231
232
static SECStatus
233
ssl_PopulateServerCert(sslServerCert *sc, CERTCertificate *cert,
234
                       const CERTCertificateList *certChain)
235
8
{
236
8
    if (sc->serverCert) {
237
0
        CERT_DestroyCertificate(sc->serverCert);
238
0
    }
239
8
    if (sc->serverCertChain) {
240
0
        CERT_DestroyCertificateList(sc->serverCertChain);
241
0
    }
242
243
8
    if (!cert) {
244
0
        sc->serverCert = NULL;
245
0
        sc->serverCertChain = NULL;
246
0
        return SECSuccess;
247
0
    }
248
249
8
    sc->serverCert = CERT_DupCertificate(cert);
250
8
    if (certChain) {
251
0
        sc->serverCertChain = CERT_DupCertList(certChain);
252
8
    } else {
253
8
        sc->serverCertChain =
254
8
            CERT_CertChainFromCert(sc->serverCert, certUsageSSLServer,
255
8
                                   PR_TRUE);
256
8
    }
257
8
    return sc->serverCertChain ? SECSuccess : SECFailure;
258
8
}
259
260
static SECStatus
261
ssl_PopulateKeyPair(sslServerCert *sc, sslKeyPair *keyPair)
262
8
{
263
8
    if (sc->serverKeyPair) {
264
0
        ssl_FreeKeyPair(sc->serverKeyPair);
265
0
        sc->serverKeyPair = NULL;
266
0
    }
267
8
    if (keyPair) {
268
8
        KeyType keyType = SECKEY_GetPublicKeyType(keyPair->pubKey);
269
8
        PORT_Assert(keyType == SECKEY_GetPrivateKeyType(keyPair->privKey));
270
271
8
        if (keyType == ecKey) {
272
4
            sc->namedCurve = ssl_ECPubKey2NamedGroup(keyPair->pubKey);
273
4
            if (!sc->namedCurve) {
274
                /* Unsupported curve. */
275
0
                PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
276
0
                return SECFailure;
277
0
            }
278
4
        }
279
280
        /* Get the size of the cert's public key, and remember it. */
281
8
        sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey);
282
8
        if (sc->serverKeyBits == 0 ||
283
8
            (keyType == rsaKey && sc->serverKeyBits > SSL_MAX_RSA_KEY_BITS)) {
284
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
285
0
            return SECFailure;
286
0
        }
287
288
8
        SECKEY_CacheStaticFlags(keyPair->privKey);
289
8
        sc->serverKeyPair = ssl_GetKeyPairRef(keyPair);
290
291
8
        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
4
            if (ssl_MaybeSetSelfEncryptKeyPair(keyPair) != SECSuccess) {
295
0
                return SECFailure;
296
0
            }
297
4
        }
298
8
    } else {
299
0
        sc->serverKeyPair = NULL;
300
0
        sc->namedCurve = NULL;
301
0
    }
302
8
    return SECSuccess;
303
8
}
304
305
static SECStatus
306
ssl_PopulateOCSPResponses(sslServerCert *sc,
307
                          const SECItemArray *stapledOCSPResponses)
308
8
{
309
8
    if (sc->certStatusArray) {
310
0
        SECITEM_FreeArray(sc->certStatusArray, PR_TRUE);
311
0
    }
312
8
    if (stapledOCSPResponses) {
313
0
        sc->certStatusArray = SECITEM_DupArray(NULL, stapledOCSPResponses);
314
0
        return sc->certStatusArray ? SECSuccess : SECFailure;
315
8
    } else {
316
8
        sc->certStatusArray = NULL;
317
8
    }
318
8
    return SECSuccess;
319
8
}
320
321
static SECStatus
322
ssl_PopulateSignedCertTimestamps(sslServerCert *sc,
323
                                 const SECItem *signedCertTimestamps)
324
8
{
325
8
    if (sc->signedCertTimestamps.len) {
326
0
        SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE);
327
0
    }
328
8
    if (signedCertTimestamps && signedCertTimestamps->len) {
329
0
        return SECITEM_CopyItem(NULL, &sc->signedCertTimestamps,
330
0
                                signedCertTimestamps);
331
0
    }
332
8
    return SECSuccess;
333
8
}
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
8
{
346
8
    sslDelegatedCredential *dc = NULL;
347
348
8
    if (sc->delegCred.len) {
349
0
        SECITEM_FreeItem(&sc->delegCred, PR_FALSE);
350
0
    }
351
352
8
    if (sc->delegCredKeyPair) {
353
0
        ssl_FreeKeyPair(sc->delegCredKeyPair);
354
0
        sc->delegCredKeyPair = NULL;
355
0
    }
356
357
    /* Both the DC and its private are present. */
358
8
    if (delegCred && delegCredPrivKey) {
359
0
        SECStatus rv;
360
0
        SECKEYPublicKey *pub;
361
0
        SECKEYPrivateKey *priv;
362
363
0
        if (!delegCred->data || delegCred->len == 0) {
364
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
365
0
            goto loser;
366
0
        }
367
368
        /* Parse the DC. */
369
0
        rv = tls13_ReadDelegatedCredential(delegCred->data, delegCred->len, &dc);
370
0
        if (rv != SECSuccess) {
371
0
            goto loser;
372
0
        }
373
374
        /* Make a copy of the DC. */
375
0
        rv = SECITEM_CopyItem(NULL, &sc->delegCred, delegCred);
376
0
        if (rv != SECSuccess) {
377
0
            goto loser;
378
0
        }
379
380
        /* Make a copy of the DC private key. */
381
0
        priv = SECKEY_CopyPrivateKey(delegCredPrivKey);
382
0
        if (!priv) {
383
0
            goto loser;
384
0
        }
385
386
        /* parse public key from the DC. */
387
0
        pub = SECKEY_ExtractPublicKey(dc->spki);
388
0
        if (!pub) {
389
0
            goto loser;
390
0
        }
391
392
0
        sc->delegCredKeyPair = ssl_NewKeyPair(priv, pub);
393
394
        /* Attempting to configure either the DC or DC private key, but not both. */
395
8
    } else if (delegCred || delegCredPrivKey) {
396
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
397
0
        goto loser;
398
0
    }
399
400
8
    tls13_DestroyDelegatedCredential(dc);
401
8
    return SECSuccess;
402
403
0
loser:
404
0
    tls13_DestroyDelegatedCredential(dc);
405
0
    return SECFailure;
406
8
}
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
8
{
415
8
    PRCList *cursor = PR_NEXT_LINK(&ss->serverCerts);
416
417
12
    while (cursor != &ss->serverCerts) {
418
4
        sslServerCert *sc = (sslServerCert *)cursor;
419
4
        cursor = PR_NEXT_LINK(cursor);
420
4
        if ((sc->authTypes & authTypes) == 0) {
421
4
            continue;
422
4
        }
423
        /* namedCurve will be NULL only for legacy functions. */
424
0
        if (namedCurve != NULL && sc->namedCurve != namedCurve) {
425
0
            continue;
426
0
        }
427
428
0
        sc->authTypes &= ~authTypes;
429
0
        if (sc->authTypes == 0) {
430
0
            PR_REMOVE_LINK(&sc->link);
431
0
            ssl_FreeServerCert(sc);
432
0
        }
433
0
    }
434
8
}
435
436
static SECStatus
437
ssl_ConfigCert(sslSocket *ss, sslAuthTypeMask authTypes,
438
               CERTCertificate *cert, sslKeyPair *keyPair,
439
               const SSLExtraServerCertData *data)
440
8
{
441
8
    SECStatus rv;
442
8
    sslServerCert *sc = NULL;
443
8
    int error_code = SEC_ERROR_NO_MEMORY;
444
445
8
    PORT_Assert(cert);
446
8
    PORT_Assert(keyPair);
447
8
    PORT_Assert(data);
448
8
    PORT_Assert(authTypes);
449
450
8
    if (!cert || !keyPair || !data || !authTypes) {
451
0
        error_code = SEC_ERROR_INVALID_ARGS;
452
0
        goto loser;
453
0
    }
454
455
8
    sc = ssl_NewServerCert();
456
8
    if (!sc) {
457
0
        goto loser;
458
0
    }
459
460
8
    sc->authTypes = authTypes;
461
8
    rv = ssl_PopulateServerCert(sc, cert, data->certChain);
462
8
    if (rv != SECSuccess) {
463
0
        goto loser;
464
0
    }
465
8
    rv = ssl_PopulateKeyPair(sc, keyPair);
466
8
    if (rv != SECSuccess) {
467
0
        error_code = PORT_GetError();
468
0
        goto loser;
469
0
    }
470
8
    rv = ssl_PopulateOCSPResponses(sc, data->stapledOCSPResponses);
471
8
    if (rv != SECSuccess) {
472
0
        goto loser;
473
0
    }
474
8
    rv = ssl_PopulateSignedCertTimestamps(sc, data->signedCertTimestamps);
475
8
    if (rv != SECSuccess) {
476
0
        goto loser;
477
0
    }
478
8
    rv = ssl_PopulateDelegatedCredential(sc, data->delegCred,
479
8
                                         data->delegCredPrivKey);
480
8
    if (rv != SECSuccess) {
481
0
        error_code = PORT_GetError();
482
0
        goto loser;
483
0
    }
484
8
    ssl_ClearMatchingCerts(ss, sc->authTypes, sc->namedCurve);
485
8
    PR_APPEND_LINK(&sc->link, &ss->serverCerts);
486
8
    return SECSuccess;
487
488
0
loser:
489
0
    ssl_FreeServerCert(sc);
490
0
    PORT_SetError(error_code);
491
0
    return SECFailure;
492
8
}
493
494
static SSLAuthType
495
ssl_GetEcdhAuthType(CERTCertificate *cert)
496
4
{
497
4
    SECOidTag sigTag = SECOID_GetAlgorithmTag(&cert->signature);
498
4
    switch (sigTag) {
499
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
500
0
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
501
0
        case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
502
0
        case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
503
0
        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
504
0
        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
505
0
        case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
506
0
        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
507
0
        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
508
0
        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
509
0
            return ssl_auth_ecdh_rsa;
510
4
        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
511
4
        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
512
4
        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
513
4
        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
514
4
        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
515
4
        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
516
4
        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
517
4
            return ssl_auth_ecdh_ecdsa;
518
0
        default:
519
0
            return ssl_auth_null;
520
4
    }
521
4
}
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
8
{
532
8
    sslAuthTypeMask authTypes = 0;
533
8
    SECOidTag tag;
534
535
8
    tag = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
536
8
    switch (tag) {
537
0
        case SEC_OID_X500_RSA_ENCRYPTION:
538
4
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
539
4
            if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
540
4
                authTypes |= 1 << ssl_auth_rsa_sign;
541
4
            }
542
543
4
            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
4
                authTypes |= 1 << ssl_auth_rsa_decrypt;
548
4
            }
549
4
            break;
550
551
0
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
552
0
            if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
553
0
                authTypes |= 1 << ssl_auth_rsa_pss;
554
0
            }
555
0
            break;
556
557
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
558
0
            if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
559
0
                authTypes |= 1 << ssl_auth_dsa;
560
0
            }
561
0
            break;
562
563
4
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
564
4
            if (cert->keyUsage & KU_DIGITAL_SIGNATURE) {
565
4
                authTypes |= 1 << ssl_auth_ecdsa;
566
4
            }
567
            /* Again, bad form to have dual usage and we don't prevent it. */
568
4
            if (cert->keyUsage & KU_KEY_ENCIPHERMENT) {
569
4
                authTypes |= 1 << ssl_GetEcdhAuthType(cert);
570
4
            }
571
4
            break;
572
573
0
        default:
574
0
            break;
575
8
    }
576
577
    /* Check that we successfully picked an authType */
578
8
    if (targetAuthType != ssl_auth_null) {
579
0
        authTypes &= 1 << targetAuthType;
580
0
    }
581
8
    return authTypes;
582
8
}
583
584
/* This function adopts pubKey and destroys it if things go wrong. */
585
static sslKeyPair *
586
ssl_MakeKeyPairForCert(SECKEYPrivateKey *key, CERTCertificate *cert)
587
8
{
588
8
    sslKeyPair *keyPair = NULL;
589
8
    SECKEYPublicKey *pubKey = NULL;
590
8
    SECKEYPrivateKey *privKeyCopy = NULL;
591
8
    PK11SlotInfo *bestSlot;
592
593
8
    pubKey = CERT_ExtractPublicKey(cert);
594
8
    if (!pubKey) {
595
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
596
0
        return NULL;
597
0
    }
598
599
8
    if (SECKEY_GetPublicKeyType(pubKey) != SECKEY_GetPrivateKeyType(key)) {
600
0
        SECKEY_DestroyPublicKey(pubKey);
601
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
602
0
        return NULL;
603
0
    }
604
605
8
    if (key->pkcs11Slot) {
606
8
        bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
607
8
        if (bestSlot) {
608
8
            privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
609
8
            PK11_FreeSlot(bestSlot);
610
8
        }
611
8
    }
612
8
    if (!privKeyCopy) {
613
0
        CK_MECHANISM_TYPE keyMech = PK11_MapSignKeyType(key->keyType);
614
        /* XXX Maybe should be bestSlotMultiple? */
615
0
        bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
616
0
        if (bestSlot) {
617
0
            privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
618
0
            PK11_FreeSlot(bestSlot);
619
0
        }
620
0
    }
621
8
    if (!privKeyCopy) {
622
0
        privKeyCopy = SECKEY_CopyPrivateKey(key);
623
0
    }
624
8
    if (privKeyCopy) {
625
8
        keyPair = ssl_NewKeyPair(privKeyCopy, pubKey);
626
8
    }
627
8
    if (!keyPair) {
628
0
        if (privKeyCopy) {
629
0
            SECKEY_DestroyPrivateKey(privKeyCopy);
630
0
        }
631
0
        SECKEY_DestroyPublicKey(pubKey);
632
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
633
0
    }
634
8
    return keyPair;
635
8
}
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
8
{
649
8
    sslSocket *ss;
650
8
    sslKeyPair *keyPair;
651
8
    SECStatus rv;
652
8
    SSLExtraServerCertData dataCopy = {
653
8
        ssl_auth_null, NULL, NULL, NULL, NULL, NULL
654
8
    };
655
8
    sslAuthTypeMask authTypes;
656
657
8
    ss = ssl_FindSocket(fd);
658
8
    if (!ss) {
659
0
        return SECFailure;
660
0
    }
661
662
8
    if (!cert || !key) {
663
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
664
0
        return SECFailure;
665
0
    }
666
667
8
    if (data) {
668
0
        if (data_len > sizeof(dataCopy)) {
669
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
670
0
            return SECFailure;
671
0
        }
672
0
        PORT_Memcpy(&dataCopy, data, data_len);
673
0
    }
674
675
8
    authTypes = ssl_GetCertificateAuthTypes(cert, dataCopy.authType);
676
8
    if (!authTypes) {
677
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
678
0
        return SECFailure;
679
0
    }
680
681
8
    keyPair = ssl_MakeKeyPairForCert(key, cert);
682
8
    if (!keyPair) {
683
0
        return SECFailure;
684
0
    }
685
686
8
    rv = ssl_ConfigCert(ss, authTypes, cert, keyPair, &dataCopy);
687
8
    ssl_FreeKeyPair(keyPair);
688
8
    if (rv != SECSuccess) {
689
0
        return SECFailure;
690
0
    }
691
8
    return SECSuccess;
692
8
}
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
0
{
708
0
    return SSL_ConfigSecureServerWithCertChain(fd, cert, NULL, key, kea);
709
0
}
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
0
{
718
0
    SECOidTag tag = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
719
0
    sslAuthTypeMask mask = 0;
720
0
    switch (tag) {
721
0
        case SEC_OID_X500_RSA_ENCRYPTION:
722
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
723
0
            mask |= 1 << ssl_auth_rsa_decrypt;
724
0
            mask |= 1 << ssl_auth_rsa_sign;
725
0
            break;
726
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
727
0
            mask |= 1 << ssl_auth_dsa;
728
0
            break;
729
0
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
730
0
            mask |= 1 << ssl_auth_ecdsa;
731
0
            mask |= 1 << ssl_auth_ecdh_rsa;
732
0
            mask |= 1 << ssl_auth_ecdh_ecdsa;
733
0
            break;
734
0
        default:
735
0
            break;
736
0
    }
737
0
    PORT_Assert(authTypes);
738
    /* Simply test that no inappropriate auth types are set. */
739
0
    return (authTypes & ~mask) == 0;
740
0
}
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
0
{
748
0
    PRCList *cursor;
749
750
0
    for (cursor = PR_NEXT_LINK(&ss->serverCerts);
751
0
         cursor != &ss->serverCerts;
752
0
         cursor = PR_NEXT_LINK(cursor)) {
753
0
        sslServerCert *cert = (sslServerCert *)cursor;
754
0
        if (cert->authTypes == authTypes) {
755
0
            return cert;
756
0
        }
757
0
    }
758
0
    return NULL;
759
0
}
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
0
{
767
0
    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
0
    sc = ssl_FindCertWithMask(ss, authTypes);
776
0
    if (sc) {
777
0
        PR_REMOVE_LINK(&sc->link);
778
0
        return sc;
779
0
    }
780
781
    /* Ignore the namedCurve parameter. Like above, this means that legacy
782
     * functions will clobber values set with the new functions blindly. */
783
0
    ssl_ClearMatchingCerts(ss, authTypes, NULL);
784
785
0
    sc = ssl_NewServerCert();
786
0
    if (sc) {
787
0
        sc->authTypes = authTypes;
788
0
    }
789
0
    return sc;
790
0
}
791
792
static sslAuthTypeMask
793
ssl_KeaTypeToAuthTypeMask(SSLKEAType keaType)
794
0
{
795
0
    switch (keaType) {
796
0
        case ssl_kea_rsa:
797
0
            return (1 << ssl_auth_rsa_decrypt) |
798
0
                   (1 << ssl_auth_rsa_sign);
799
800
0
        case ssl_kea_dh:
801
0
            return 1 << ssl_auth_dsa;
802
803
0
        case ssl_kea_ecdh:
804
0
            return (1 << ssl_auth_ecdsa) |
805
0
                   (1 << ssl_auth_ecdh_rsa) |
806
0
                   (1 << ssl_auth_ecdh_ecdsa);
807
808
0
        default:
809
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
810
0
    }
811
0
    return 0;
812
0
}
813
814
static SECStatus
815
ssl_AddCertChain(sslSocket *ss, CERTCertificate *cert,
816
                 const CERTCertificateList *certChainOpt,
817
                 SECKEYPrivateKey *key, sslAuthTypeMask authTypes)
818
0
{
819
0
    sslServerCert *sc;
820
0
    sslKeyPair *keyPair;
821
0
    SECStatus rv;
822
0
    PRErrorCode err = SEC_ERROR_NO_MEMORY;
823
824
0
    if (!ssl_CertSuitableForAuthType(cert, authTypes)) {
825
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
826
0
        return SECFailure;
827
0
    }
828
829
0
    sc = ssl_FindOrMakeCert(ss, authTypes);
830
0
    if (!sc) {
831
0
        goto loser;
832
0
    }
833
834
0
    rv = ssl_PopulateServerCert(sc, cert, certChainOpt);
835
0
    if (rv != SECSuccess) {
836
0
        goto loser;
837
0
    }
838
839
0
    keyPair = ssl_MakeKeyPairForCert(key, cert);
840
0
    if (!keyPair) {
841
        /* Error code is set by ssl_MakeKeyPairForCert */
842
0
        goto loser;
843
0
    }
844
0
    rv = ssl_PopulateKeyPair(sc, keyPair);
845
0
    ssl_FreeKeyPair(keyPair);
846
0
    if (rv != SECSuccess) {
847
0
        err = PORT_GetError();
848
0
        goto loser;
849
0
    }
850
851
0
    PR_APPEND_LINK(&sc->link, &ss->serverCerts);
852
0
    return SECSuccess;
853
854
0
loser:
855
0
    ssl_FreeServerCert(sc);
856
0
    PORT_SetError(err);
857
0
    return SECFailure;
858
0
}
859
860
/* Public deprecated function */
861
SECStatus
862
SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
863
                                    const CERTCertificateList *certChainOpt,
864
                                    SECKEYPrivateKey *key, SSLKEAType certType)
865
0
{
866
0
    sslSocket *ss;
867
0
    sslAuthTypeMask authTypes;
868
869
0
    ss = ssl_FindSocket(fd);
870
0
    if (!ss) {
871
0
        return SECFailure;
872
0
    }
873
874
0
    if (!cert != !key) { /* Configure both, or neither */
875
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
876
0
        return SECFailure;
877
0
    }
878
879
0
    authTypes = ssl_KeaTypeToAuthTypeMask(certType);
880
0
    if (!authTypes) {
881
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
882
0
        return SECFailure;
883
0
    }
884
885
0
    if (!cert) {
886
0
        sslServerCert *sc = ssl_FindCertWithMask(ss, authTypes);
887
0
        if (sc) {
888
0
            (void)ssl_PopulateServerCert(sc, NULL, NULL);
889
0
            (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
0
        }
894
0
        return SECSuccess;
895
0
    }
896
897
0
    return ssl_AddCertChain(ss, cert, certChainOpt, key, authTypes);
898
0
}
899
900
/* Public deprecated function */
901
SECStatus
902
SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses,
903
                            SSLKEAType certType)
904
0
{
905
0
    sslSocket *ss;
906
0
    sslServerCert *sc;
907
0
    sslAuthTypeMask authTypes;
908
0
    SECStatus rv;
909
910
0
    ss = ssl_FindSocket(fd);
911
0
    if (!ss) {
912
0
        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetStapledOCSPResponses",
913
0
                 SSL_GETPID(), fd));
914
0
        return SECFailure;
915
0
    }
916
917
0
    authTypes = ssl_KeaTypeToAuthTypeMask(certType);
918
0
    if (!authTypes) {
919
0
        SSL_DBG(("%d: SSL[%d]: invalid cert type in SSL_SetStapledOCSPResponses",
920
0
                 SSL_GETPID(), fd));
921
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
922
0
        return SECFailure;
923
0
    }
924
925
0
    if (!responses) {
926
0
        sc = ssl_FindCertWithMask(ss, authTypes);
927
0
        if (sc) {
928
0
            (void)ssl_PopulateOCSPResponses(sc, NULL);
929
0
        }
930
0
        return SECSuccess;
931
0
    }
932
933
0
    sc = ssl_FindOrMakeCert(ss, authTypes);
934
0
    if (!sc) {
935
0
        return SECFailure;
936
0
    }
937
938
0
    rv = ssl_PopulateOCSPResponses(sc, responses);
939
0
    if (rv == SECSuccess) {
940
0
        PR_APPEND_LINK(&sc->link, &ss->serverCerts);
941
0
    } else {
942
0
        ssl_FreeServerCert(sc);
943
0
    }
944
0
    return rv;
945
0
}
946
947
/* Public deprecated function */
948
SECStatus
949
SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts,
950
                            SSLKEAType certType)
951
0
{
952
0
    sslSocket *ss;
953
0
    sslServerCert *sc;
954
0
    sslAuthTypeMask authTypes;
955
0
    SECStatus rv;
956
957
0
    ss = ssl_FindSocket(fd);
958
0
    if (!ss) {
959
0
        SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSignedCertTimestamps",
960
0
                 SSL_GETPID(), fd));
961
0
        return SECFailure;
962
0
    }
963
964
0
    authTypes = ssl_KeaTypeToAuthTypeMask(certType);
965
0
    if (!authTypes) {
966
0
        SSL_DBG(("%d: SSL[%d]: invalid cert type in SSL_SetSignedCertTimestamps",
967
0
                 SSL_GETPID(), fd));
968
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
969
0
        return SECFailure;
970
0
    }
971
972
0
    if (!scts) {
973
0
        sc = ssl_FindCertWithMask(ss, authTypes);
974
0
        if (sc) {
975
0
            (void)ssl_PopulateSignedCertTimestamps(sc, NULL);
976
0
        }
977
0
        return SECSuccess;
978
0
    }
979
980
0
    sc = ssl_FindOrMakeCert(ss, authTypes);
981
0
    if (!sc) {
982
0
        return SECFailure;
983
0
    }
984
985
0
    rv = ssl_PopulateSignedCertTimestamps(sc, scts);
986
0
    if (rv == SECSuccess) {
987
0
        PR_APPEND_LINK(&sc->link, &ss->serverCerts);
988
0
    } else {
989
0
        ssl_FreeServerCert(sc);
990
0
    }
991
0
    return rv;
992
0
}
993
994
/* Public deprecated function. */
995
SSLKEAType
996
NSS_FindCertKEAType(CERTCertificate *cert)
997
0
{
998
0
    int tag;
999
1000
0
    if (!cert)
1001
0
        return ssl_kea_null;
1002
1003
0
    tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
1004
0
    switch (tag) {
1005
0
        case SEC_OID_X500_RSA_ENCRYPTION:
1006
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
1007
0
            return ssl_kea_rsa;
1008
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE: /* hah, signature, not a key? */
1009
0
        case SEC_OID_X942_DIFFIE_HELMAN_KEY:
1010
0
            return ssl_kea_dh;
1011
0
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
1012
0
            return ssl_kea_ecdh;
1013
0
        default:
1014
0
            return ssl_kea_null;
1015
0
    }
1016
0
}