Coverage Report

Created: 2018-09-25 14:53

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