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