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