diff options
author | Kai Engert <kaie@kuix.de> | 2016-04-06 18:07:39 +0200 |
---|---|---|
committer | Kai Engert <kaie@kuix.de> | 2016-04-06 18:07:39 +0200 |
commit | e4b2a164b2414542c430611ce4e0fe52c3b76d6b (patch) | |
tree | 5b0625068f774be7a1dfd937881050d8d48bc355 | |
parent | 85ef0c4c1b77fae164df8ba8853b7adc6b5e17ba (diff) | |
download | nss-hg-e4b2a164b2414542c430611ce4e0fe52c3b76d6b.tar.gz |
Backed out changeset 72ae99c547be, part 3/3, bug 1237514, for causing test failures in Firefox tests
-rw-r--r-- | external_tests/ssl_gtest/libssl_internals.c | 5 | ||||
-rw-r--r-- | external_tests/ssl_gtest/ssl_loopback_unittest.cc | 67 | ||||
-rw-r--r-- | external_tests/ssl_gtest/tls_agent.cc | 44 | ||||
-rw-r--r-- | external_tests/ssl_gtest/tls_agent.h | 3 | ||||
-rw-r--r-- | external_tests/ssl_gtest/tls_connect.cc | 30 | ||||
-rw-r--r-- | external_tests/ssl_gtest/tls_connect.h | 4 | ||||
-rw-r--r-- | lib/ssl/SSLerrs.h | 2 | ||||
-rw-r--r-- | lib/ssl/manifest.mn | 1 | ||||
-rw-r--r-- | lib/ssl/ssl.def | 1 | ||||
-rw-r--r-- | lib/ssl/ssl.h | 69 | ||||
-rw-r--r-- | lib/ssl/ssl3con.c | 555 | ||||
-rw-r--r-- | lib/ssl/ssl3ecc.c | 139 | ||||
-rw-r--r-- | lib/ssl/ssl3ext.c | 123 | ||||
-rw-r--r-- | lib/ssl/sslcert.c | 877 | ||||
-rw-r--r-- | lib/ssl/sslcert.h | 59 | ||||
-rw-r--r-- | lib/ssl/sslcon.c | 2 | ||||
-rw-r--r-- | lib/ssl/sslimpl.h | 155 | ||||
-rw-r--r-- | lib/ssl/sslinfo.c | 202 | ||||
-rw-r--r-- | lib/ssl/sslsecur.c | 254 | ||||
-rw-r--r-- | lib/ssl/sslsnce.c | 67 | ||||
-rw-r--r-- | lib/ssl/sslsock.c | 189 | ||||
-rw-r--r-- | lib/ssl/sslt.h | 45 | ||||
-rw-r--r-- | lib/ssl/tls13con.c | 138 |
23 files changed, 1089 insertions, 1942 deletions
diff --git a/external_tests/ssl_gtest/libssl_internals.c b/external_tests/ssl_gtest/libssl_internals.c index c0693b199..48d4412f8 100644 --- a/external_tests/ssl_gtest/libssl_internals.c +++ b/external_tests/ssl_gtest/libssl_internals.c @@ -29,12 +29,11 @@ PRUint32 SSLInt_DetermineKEABits(PRUint16 serverKeyBits, SSLAuthType authAlgorithm) { // For ECDSA authentication we expect a curve for key exchange with the // same strength as the one used for the certificate's signature. - if (authAlgorithm == ssl_auth_ecdsa || authAlgorithm == ssl_auth_ecdh) { + if (authAlgorithm == ssl_auth_ecdsa) { return serverKeyBits; } - PORT_Assert(authAlgorithm == ssl_auth_rsa_decrypt || - authAlgorithm == ssl_auth_rsa_sign); + PORT_Assert(authAlgorithm == ssl_auth_rsa); PRUint32 minKeaBits; #ifdef NSS_ECC_MORE_THAN_SUITE_B // P-192 is the smallest curve we want to use. diff --git a/external_tests/ssl_gtest/ssl_loopback_unittest.cc b/external_tests/ssl_gtest/ssl_loopback_unittest.cc index 410be517d..db246d89a 100644 --- a/external_tests/ssl_gtest/ssl_loopback_unittest.cc +++ b/external_tests/ssl_gtest/ssl_loopback_unittest.cc @@ -108,14 +108,35 @@ class TlsServerKeyExchangeEcdhe { DataBuffer public_key_; }; -class TlsChaCha20Poly1305Test : public TlsConnectTls12 {}; +class TlsChaCha20Poly1305Test : public TlsConnectTls12 { + public: + void ConnectSendReceive(PRUint32 cipher_suite) + { + // Disable all ciphers. + client_->DisableCiphersByKeyExchange(ssl_kea_rsa); + client_->DisableCiphersByKeyExchange(ssl_kea_dh); + client_->DisableCiphersByKeyExchange(ssl_kea_ecdh); + + // Re-enable ChaCha20/Poly1305. + SECStatus rv = SSL_CipherPrefSet(client_->ssl_fd(), cipher_suite, PR_TRUE); + EXPECT_EQ(SECSuccess, rv); + + Connect(); + SendReceive(); + + // Check that we used the right cipher suite. + int16_t actual, expected = static_cast<int16_t>(cipher_suite); + EXPECT_TRUE(client_->cipher_suite(&actual) && actual == expected); + EXPECT_TRUE(server_->cipher_suite(&actual) && actual == expected); + } +}; TEST_P(TlsConnectGeneric, SetupOnly) {} TEST_P(TlsConnectGeneric, Connect) { SetExpectedVersion(std::get<1>(GetParam())); Connect(); - CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + CheckKeys(ssl_kea_ecdh, ssl_auth_rsa); } TEST_P(TlsConnectGeneric, ConnectEcdsa) { @@ -125,22 +146,6 @@ TEST_P(TlsConnectGeneric, ConnectEcdsa) { CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa); } -TEST_P(TlsConnectGenericPre13, ConnectEcdh) { - SetExpectedVersion(std::get<1>(GetParam())); - // ECDH_ cipher suites can use an ECDSA cert (NSS doesn't care that we - // shouldn't, which this shamelessly exploits). - ResetEcdsa(); - DisableDheAndEcdheCiphers(); - EnableSomeEcdhCiphers(); - - Connect(); - CheckKeys(ssl_kea_ecdh, ssl_auth_ecdh); -} - -TEST_P(TlsConnectStreamPre13, ConnectRC4) { - ConnectWithCipherSuite(TLS_RSA_WITH_RC4_128_SHA); -} - TEST_P(TlsConnectGenericPre13, ConnectFalseStart) { client_->EnableFalseStart(); Connect(); @@ -306,7 +311,7 @@ TEST_P(TlsConnectGeneric, ClientAuth) { client_->SetupClientAuth(); server_->RequestClientAuth(true); Connect(); - CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + CheckKeys(ssl_kea_ecdh, ssl_auth_rsa); } // In TLS 1.3, the client sends its cert rejection on the @@ -322,7 +327,7 @@ TEST_P(TlsConnectStream, DISABLED_ClientAuthRequiredRejected) { TEST_P(TlsConnectGeneric, ClientAuthRequestedRejected) { server_->RequestClientAuth(false); Connect(); - CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + CheckKeys(ssl_kea_ecdh, ssl_auth_rsa); } @@ -391,13 +396,13 @@ TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) { PR_ARRAY_SIZE(SignatureRsaSha256)); DisableDheAndEcdheCiphers(); Connect(); - CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt); + CheckKeys(ssl_kea_rsa, ssl_auth_rsa); } TEST_P(TlsConnectGenericPre13, ConnectStaticRSA) { DisableDheAndEcdheCiphers(); Connect(); - CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt); + CheckKeys(ssl_kea_rsa, ssl_auth_rsa); } // Signature algorithms governs both verification and generation of signatures. @@ -532,7 +537,7 @@ TEST_P(TlsConnectStreamPre13, ConnectAndServerRenegotiate) { TEST_P(TlsConnectGenericPre13, ConnectDhe) { DisableEcdheCiphers(); Connect(); - CheckKeys(ssl_kea_dh, ssl_auth_rsa_sign); + CheckKeys(ssl_kea_dh, ssl_auth_rsa); } // Test that a totally bogus EPMS is handled correctly. @@ -578,7 +583,7 @@ TEST_P(TlsConnectGenericPre13, ConnectStaticRSABogusPMSVersionIgnore) { TEST_P(TlsConnectGeneric, ConnectEcdhe) { Connect(); - CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + CheckKeys(ssl_kea_ecdh, ssl_auth_rsa); } // Prior to TLS 1.3, we were not fully ephemeral; though 1.3 fixes that @@ -587,7 +592,7 @@ TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceReuseKey) { new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange); server_->SetPacketFilter(i1); Connect(); - CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + CheckKeys(ssl_kea_ecdh, ssl_auth_rsa); TlsServerKeyExchangeEcdhe dhe1; EXPECT_TRUE(dhe1.Parse(i1->buffer())); @@ -598,7 +603,7 @@ TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceReuseKey) { server_->SetPacketFilter(i2); ConfigureSessionCache(RESUME_NONE, RESUME_NONE); Connect(); - CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + CheckKeys(ssl_kea_ecdh, ssl_auth_rsa); TlsServerKeyExchangeEcdhe dhe2; EXPECT_TRUE(dhe2.Parse(i2->buffer())); @@ -619,7 +624,7 @@ TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceNewKey) { new TlsInspectorRecordHandshakeMessage(kTlsHandshakeServerKeyExchange); server_->SetPacketFilter(i1); Connect(); - CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + CheckKeys(ssl_kea_ecdh, ssl_auth_rsa); TlsServerKeyExchangeEcdhe dhe1; EXPECT_TRUE(dhe1.Parse(i1->buffer())); @@ -633,7 +638,7 @@ TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceNewKey) { server_->SetPacketFilter(i2); ConfigureSessionCache(RESUME_NONE, RESUME_NONE); Connect(); - CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign); + CheckKeys(ssl_kea_ecdh, ssl_auth_rsa); TlsServerKeyExchangeEcdhe dhe2; EXPECT_TRUE(dhe2.Parse(i2->buffer())); @@ -650,16 +655,16 @@ TEST_P(TlsConnectGeneric, ConnectSendReceive) { } TEST_P(TlsChaCha20Poly1305Test, SendReceiveChaCha20Poly1305DheRsa) { - ConnectWithCipherSuite(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256); + ConnectSendReceive(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256); } TEST_P(TlsChaCha20Poly1305Test, SendReceiveChaCha20Poly1305EcdheRsa) { - ConnectWithCipherSuite(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256); + ConnectSendReceive(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256); } TEST_P(TlsChaCha20Poly1305Test, SendReceiveChaCha20Poly1305EcdheEcdsa) { ResetEcdsa(); - ConnectWithCipherSuite(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256); + ConnectSendReceive(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256); } // The next two tests takes advantage of the fact that we diff --git a/external_tests/ssl_gtest/tls_agent.cc b/external_tests/ssl_gtest/tls_agent.cc index 5139f51d1..c0af1ebb5 100644 --- a/external_tests/ssl_gtest/tls_agent.cc +++ b/external_tests/ssl_gtest/tls_agent.cc @@ -106,9 +106,7 @@ bool TlsAgent::EnsureTlsSetup() { EXPECT_NE(nullptr, priv); if (!priv) return false; // Leak cert. - SECStatus rv = SSL_ConfigSecureServer(ssl_fd_, nullptr, nullptr, kt_null); - EXPECT_EQ(SECFailure, rv); - rv = SSL_ConfigSecureServer(ssl_fd_, cert, priv, kea_); + SECStatus rv = SSL_ConfigSecureServer(ssl_fd_, cert, priv, kea_); EXPECT_EQ(SECSuccess, rv); if (rv != SECSuccess) return false; // Leak cert and key. @@ -215,23 +213,6 @@ void TlsAgent::DisableCiphersByKeyExchange(SSLKEAType kea) { } } -void TlsAgent::EnableCiphersByAuthType(SSLAuthType authType) { - EXPECT_TRUE(EnsureTlsSetup()); - - for (size_t i = 0; i < SSL_NumImplementedCiphers; ++i) { - SSLCipherSuiteInfo csinfo; - - SECStatus rv = SSL_GetCipherSuiteInfo(SSL_ImplementedCiphers[i], - &csinfo, sizeof(csinfo)); - ASSERT_EQ(SECSuccess, rv); - - bool enable = csinfo.authType == authType; - rv = SSL_CipherPrefSet(ssl_fd_, SSL_ImplementedCiphers[i], enable); - EXPECT_EQ(SECSuccess, rv); - } -} - - void TlsAgent::SetSessionTicketsEnabled(bool en) { EXPECT_TRUE(EnsureTlsSetup()); @@ -321,7 +302,7 @@ void TlsAgent::CheckKEAType(SSLKEAType type) const { EXPECT_EQ(type, csinfo_.keaType); PRUint32 ecKEAKeyBits = SSLInt_DetermineKEABits(server_key_bits_, - csinfo_.authType); + csinfo_.authAlgorithm); switch (type) { case ssl_kea_ecdh: @@ -340,33 +321,14 @@ void TlsAgent::CheckKEAType(SSLKEAType type) const { void TlsAgent::CheckAuthType(SSLAuthType type) const { EXPECT_EQ(STATE_CONNECTED, state_); - EXPECT_EQ(type, csinfo_.authType); + EXPECT_EQ(type, csinfo_.authAlgorithm); EXPECT_EQ(server_key_bits_, info_.authKeyBits); - - // Do some extra checks based on type. switch (type) { case ssl_auth_ecdsa: // extra check for P-256 EXPECT_EQ(256U, info_.authKeyBits); break; - default: - break; - } - - // Check authAlgorithm, which is the old value for authType. This is a second switch - // statement because default label is different. - switch (type) { - case ssl_auth_rsa_sign: - EXPECT_EQ(ssl_auth_rsa_decrypt, csinfo_.authAlgorithm) - << "authAlgorithm for RSA is always decrypt"; - break; - case ssl_auth_ecdh: - EXPECT_TRUE(csinfo_.authAlgorithm != ssl_auth_ecdh) - << "ECDH suites were originally wonky"; - break; default: - EXPECT_EQ(type, csinfo_.authAlgorithm) - << "authAlgorithm is (usually) the same as authType"; break; } } diff --git a/external_tests/ssl_gtest/tls_agent.h b/external_tests/ssl_gtest/tls_agent.h index b31d6cca4..1c824d6e6 100644 --- a/external_tests/ssl_gtest/tls_agent.h +++ b/external_tests/ssl_gtest/tls_agent.h @@ -74,7 +74,6 @@ class TlsAgent : public PollTarget { // Prepares for renegotiation, then actually triggers it. void StartRenegotiate(); void DisableCiphersByKeyExchange(SSLKEAType kea); - void EnableCiphersByAuthType(SSLAuthType authType); bool EnsureTlsSetup(); void SetupClientAuth(); @@ -139,7 +138,7 @@ class TlsAgent : public PollTarget { return info_.protocolVersion; } - bool cipher_suite(uint16_t* cipher_suite) const { + bool cipher_suite(int16_t* cipher_suite) const { if (state_ != STATE_CONNECTED) return false; *cipher_suite = info_.cipherSuite; diff --git a/external_tests/ssl_gtest/tls_connect.cc b/external_tests/ssl_gtest/tls_connect.cc index 942cddc29..38e90e550 100644 --- a/external_tests/ssl_gtest/tls_connect.cc +++ b/external_tests/ssl_gtest/tls_connect.cc @@ -219,29 +219,6 @@ void TlsConnectTestBase::Connect() { CheckConnected(); } -void TlsConnectTestBase::ConnectWithCipherSuite(uint16_t cipher_suite) -{ - // Disable all ciphers. - client_->DisableCiphersByKeyExchange(ssl_kea_rsa); - client_->DisableCiphersByKeyExchange(ssl_kea_dh); - client_->DisableCiphersByKeyExchange(ssl_kea_ecdh); - - // Re-enable this specific cipher suite - SECStatus rv = SSL_CipherPrefSet(client_->ssl_fd(), cipher_suite, PR_TRUE); - EXPECT_EQ(SECSuccess, rv); - - Connect(); - SendReceive(); - - // Check that we used the right cipher suite. - uint16_t actual; - EXPECT_TRUE(client_->cipher_suite(&actual)); - EXPECT_EQ(cipher_suite, actual); - EXPECT_TRUE(server_->cipher_suite(&actual)); - EXPECT_EQ(cipher_suite, actual); -} - - void TlsConnectTestBase::CheckConnected() { // Check the version is as expected EXPECT_EQ(client_->version(), server_->version()); @@ -252,7 +229,7 @@ void TlsConnectTestBase::CheckConnected() { EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state()); EXPECT_EQ(TlsAgent::STATE_CONNECTED, server_->state()); - uint16_t cipher_suite1, cipher_suite2; + int16_t cipher_suite1, cipher_suite2; bool ret = client_->cipher_suite(&cipher_suite1); EXPECT_TRUE(ret); ret = server_->cipher_suite(&cipher_suite2); @@ -314,11 +291,6 @@ void TlsConnectTestBase::DisableDheAndEcdheCiphers() { DisableEcdheCiphers(); } -void TlsConnectTestBase::EnableSomeEcdhCiphers() { - client_->EnableCiphersByAuthType(ssl_auth_ecdh); - server_->EnableCiphersByAuthType(ssl_auth_ecdh); -} - void TlsConnectTestBase::ConfigureSessionCache(SessionResumptionMode client, SessionResumptionMode server) { client_->ConfigureSessionCache(client); diff --git a/external_tests/ssl_gtest/tls_connect.h b/external_tests/ssl_gtest/tls_connect.h index 70b6c9ba9..ab9a5dc8b 100644 --- a/external_tests/ssl_gtest/tls_connect.h +++ b/external_tests/ssl_gtest/tls_connect.h @@ -66,8 +66,7 @@ class TlsConnectTestBase : public ::testing::Test { void CheckConnected(); // Connect and expect it to fail. void ConnectExpectFail(); - void ConnectWithCipherSuite(uint16_t cipher_suite); - void CheckKeys(SSLKEAType akeyType, SSLAuthType authType) const; + void CheckKeys(SSLKEAType keyType, SSLAuthType authType) const; void SetExpectedVersion(uint16_t version); // Expect resumption of a particular type. @@ -75,7 +74,6 @@ class TlsConnectTestBase : public ::testing::Test { void DisableDheAndEcdheCiphers(); void DisableDheCiphers(); void DisableEcdheCiphers(); - void EnableSomeEcdhCiphers(); void EnableExtendedMasterSecret(); void ConfigureSessionCache(SessionResumptionMode client, SessionResumptionMode server); diff --git a/lib/ssl/SSLerrs.h b/lib/ssl/SSLerrs.h index 7da916b62..6ae620b61 100644 --- a/lib/ssl/SSLerrs.h +++ b/lib/ssl/SSLerrs.h @@ -290,7 +290,7 @@ ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE, (SSL_ERROR_BASE + 87), "Received incorrect handshakes hash values from peer.") ER3(SSL_ERROR_CERT_KEA_MISMATCH, (SSL_ERROR_BASE + 88), - "The certificate provided cannot be used with the selected authentication type.") + "The certificate provided cannot be used with the selected key exchange algorithm.") ER3(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA, (SSL_ERROR_BASE + 89), "No certificate authority is trusted for SSL client authentication.") diff --git a/lib/ssl/manifest.mn b/lib/ssl/manifest.mn index 267a69dc5..4c466488d 100644 --- a/lib/ssl/manifest.mn +++ b/lib/ssl/manifest.mn @@ -45,7 +45,6 @@ CSRCS = \ ssl3ecc.c \ tls13con.c \ tls13hkdf.c \ - sslcert.c \ $(NULL) LIBRARY_NAME = ssl diff --git a/lib/ssl/ssl.def b/lib/ssl/ssl.def index 26840c497..a05cb6071 100644 --- a/lib/ssl/ssl.def +++ b/lib/ssl/ssl.def @@ -196,7 +196,6 @@ SSL_SetSignedCertTimestamps; ;+}; ;+NSS_3.23 { # NSS 3.23 release ;+ global: -SSL_ConfigServerCert; SSL_SetDowngradeCheckVersion; ;+ local: ;+*; diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h index 2c9a8e0ea..30555e32a 100644 --- a/lib/ssl/ssl.h +++ b/lib/ssl/ssl.h @@ -596,8 +596,6 @@ SSL_IMPORT const SECItem *SSL_PeerSignedCertTimestamps(PRFileDesc *fd); * handshake message. Parameter |responses| is for the server certificate of * the key exchange type |kea|. * The function will duplicate the responses array. - * - * Deprecated: see SSL_ConfigSecureServer for details. */ SSL_IMPORT SECStatus SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses, @@ -610,8 +608,6 @@ SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses, * is for the server certificate of the key exchange type |kea|. * The function will duplicate the provided data item. To clear previously * set data for a given key exchange type |kea|, pass NULL to |scts|. - * - * Deprecated: see SSL_ConfigSecureServer for details. */ SSL_IMPORT SECStatus SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts, @@ -768,72 +764,14 @@ SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, ** Configure SSL socket for running a secure server. Needs the ** certificate for the server and the servers private key. The arguments ** are copied. -** -** This method should be used in preference to SSL_ConfigSecureServer, -** SSL_ConfigSecureServerWithCertChain, SSL_SetStapledOCSPResponses, and -** SSL_SetSignedCertTimestamps. -** -** The authentication method is determined from the certificate and private key -** based on how libssl authenticates peers. Primarily, this uses the value of -** the SSLAuthType enum and is derived from the type of public key in the -** certificate. For example, different RSA certificates might be saved for -** signing (ssl_auth_rsa_sign) and key encipherment -** (ssl_auth_rsa_decrypt). Unique to RSA, the same certificate can be used for -** both usages. Additional information about the authentication method is also -** used: EC keys with different curves are separately stored. -** -** Only one certificate is stored for each authentication method. -** -** The optional |data| argument contains additional information about the -** certificate: -** -** - |authType| (with a value other than ssl_auth_null) limits the -** authentication method; this is primarily useful in limiting the use of an -** RSA certificate to one particular key usage (either signing or key -** encipherment) when its key usages indicate support for both. -** -** - |certChain| provides an explicit certificate chain, rather than relying on -** NSS functions for finding a certificate chain. -** -** - |stapledOCSPResponses| provides a response for OCSP stapling. -** -** - |signedCertTimestamps| provides a value for the -** signed_certificate_timestamp extension used in certificate transparency. -** -** The |data_len| argument provides the length of the data. This should be set -** to |sizeof(data)|. -** -** This function allows an application to provide certificates with narrow key -** usages attached to them. For instance, RSA keys can be provided that are -** limited to signing or decryption only. Multiple EC certificates with keys on -** different named curves can be provided. -** -** Unlike SSL_ConfigSecureServer(WithCertChain), this function does not accept -** NULL for the |cert| and |key| arguments. It will replace certificates that -** have the same type, but it cannot be used to remove certificates that have -** already been configured. -*/ -SSL_IMPORT SECStatus SSL_ConfigServerCert( - PRFileDesc *fd, CERTCertificate *cert, SECKEYPrivateKey *key, - const SSLExtraServerCertData *data, unsigned int data_len); - -/* -** Deprecated variant of SSL_ConfigServerCert. -** -** This uses values from the SSLKEAType to identify the type of |key| that the -** |cert| contains. This is incorrect, since key exchange and authentication -** are separated in some cipher suites (in particular, ECDHE_RSA_* suites). -** -** Providing a |kea| parameter of ssl_kea_ecdh (or kt_ecdh) is interpreted as -** providing both ECDH and ECDSA certificates. */ SSL_IMPORT SECStatus SSL_ConfigSecureServer( PRFileDesc *fd, CERTCertificate *cert, SECKEYPrivateKey *key, SSLKEAType kea); /* -** Deprecated variant of SSL_ConfigSecureServerCert. The |data| argument to -** SSL_ConfigSecureServerCert can be used to pass a certificate chain. +** Allows SSL socket configuration with caller-supplied certificate chain. +** If certChainOpt is NULL, tries to find one. */ SSL_IMPORT SECStatus SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert, @@ -1065,8 +1003,7 @@ SSL_IMPORT SECStatus SSL_GetSRTPCipher(PRFileDesc *fd, SSL_IMPORT SECStatus NSS_CmpCertChainWCANames(CERTCertificate *cert, CERTDistNames *caNames); -/* Deprecated. This reports a misleading value for certificates that might - * be used for signing rather than key exchange. +/* * Returns key exchange type of the keys in an SSL server certificate. */ SSL_IMPORT SSLKEAType NSS_FindCertKEAType(CERTCertificate *cert); diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c index 3871eab89..28fc85bb4 100644 --- a/lib/ssl/ssl3con.c +++ b/lib/ssl/ssl3con.c @@ -309,30 +309,29 @@ static const ssl3BulkCipherDef bulk_cipher_defs[] = { static const ssl3KEADef kea_defs[] = { /* indexed by SSL3KeyExchangeAlgorithm */ - /* kea exchKeyType signKeyType authKeyType, is_limited limit tls_keygen ephemeral oid */ - {kea_null, ssl_kea_null, ssl_sign_null, ssl_auth_null, PR_FALSE, 0, PR_FALSE, PR_FALSE, 0}, - {kea_rsa, ssl_kea_rsa, ssl_sign_null, ssl_auth_rsa_decrypt, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA}, - /* note: export suites abuse RSA, but these will be removed soon */ - {kea_rsa_export, ssl_kea_rsa, ssl_sign_rsa, ssl_auth_rsa_sign, PR_TRUE, 512, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT}, - {kea_rsa_export_1024,ssl_kea_rsa, ssl_sign_rsa, ssl_auth_rsa_sign, PR_TRUE, 1024, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT}, - {kea_dh_dss, ssl_kea_dh, ssl_sign_dsa, ssl_auth_dsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS}, - {kea_dh_dss_export, ssl_kea_dh, ssl_sign_dsa, ssl_auth_dsa, PR_TRUE, 512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS_EXPORT}, - {kea_dh_rsa, ssl_kea_dh, ssl_sign_rsa, ssl_auth_rsa_sign, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA}, - {kea_dh_rsa_export, ssl_kea_dh, ssl_sign_rsa, ssl_auth_rsa_sign, PR_TRUE, 512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA_EXPORT}, - {kea_dhe_dss, ssl_kea_dh, ssl_sign_dsa, ssl_auth_dsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_DSS}, - {kea_dhe_dss_export, ssl_kea_dh, ssl_sign_dsa, ssl_auth_dsa, PR_TRUE, 512, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_DSS_EXPORT}, - {kea_dhe_rsa, ssl_kea_dh, ssl_sign_rsa, ssl_auth_rsa_sign, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_RSA}, - {kea_dhe_rsa_export, ssl_kea_dh, ssl_sign_rsa, ssl_auth_rsa_sign, PR_TRUE, 512, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_RSA_EXPORT}, - {kea_dh_anon, ssl_kea_dh, ssl_sign_null, ssl_auth_null, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DH_ANON}, - {kea_dh_anon_export, ssl_kea_dh, ssl_sign_null, ssl_auth_null, PR_TRUE, 512, PR_FALSE, PR_TRUE, SEC_OID_TLS_DH_ANON_EXPORT}, - {kea_rsa_fips, ssl_kea_rsa, ssl_sign_rsa, ssl_auth_rsa_decrypt, PR_FALSE, 0, PR_TRUE, PR_FALSE, SEC_OID_TLS_RSA}, + /* kea exchKeyType signKeyType is_limited limit tls_keygen ephemeral oid */ + {kea_null, kt_null, ssl_sign_null, PR_FALSE, 0, PR_FALSE, PR_FALSE, 0}, + {kea_rsa, kt_rsa, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA}, + {kea_rsa_export, kt_rsa, ssl_sign_rsa, PR_TRUE, 512, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT}, + {kea_rsa_export_1024,kt_rsa, ssl_sign_rsa, PR_TRUE, 1024, PR_FALSE, PR_FALSE, SEC_OID_TLS_RSA_EXPORT}, + {kea_dh_dss, kt_dh, ssl_sign_dsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS}, + {kea_dh_dss_export, kt_dh, ssl_sign_dsa, PR_TRUE, 512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_DSS_EXPORT}, + {kea_dh_rsa, kt_dh, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA}, + {kea_dh_rsa_export, kt_dh, ssl_sign_rsa, PR_TRUE, 512, PR_FALSE, PR_FALSE, SEC_OID_TLS_DH_RSA_EXPORT}, + {kea_dhe_dss, kt_dh, ssl_sign_dsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_DSS}, + {kea_dhe_dss_export, kt_dh, ssl_sign_dsa, PR_TRUE, 512, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_DSS_EXPORT}, + {kea_dhe_rsa, kt_dh, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_RSA}, + {kea_dhe_rsa_export, kt_dh, ssl_sign_rsa, PR_TRUE, 512, PR_FALSE, PR_TRUE, SEC_OID_TLS_DHE_RSA_EXPORT}, + {kea_dh_anon, kt_dh, ssl_sign_null, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_DH_ANON}, + {kea_dh_anon_export, kt_dh, ssl_sign_null, PR_TRUE, 512, PR_FALSE, PR_TRUE, SEC_OID_TLS_DH_ANON_EXPORT}, + {kea_rsa_fips, kt_rsa, ssl_sign_rsa, PR_FALSE, 0, PR_TRUE, PR_FALSE, SEC_OID_TLS_RSA}, #ifndef NSS_DISABLE_ECC - {kea_ecdh_ecdsa, ssl_kea_ecdh, ssl_sign_null, ssl_auth_ecdh, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_ECDSA}, - {kea_ecdhe_ecdsa, ssl_kea_ecdh, ssl_sign_ecdsa, ssl_auth_ecdsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDHE_ECDSA}, - {kea_ecdh_rsa, ssl_kea_ecdh, ssl_sign_null, ssl_auth_ecdh, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_RSA}, - {kea_ecdhe_rsa, ssl_kea_ecdh, ssl_sign_rsa, ssl_auth_rsa_sign, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDHE_RSA}, - {kea_ecdh_anon, ssl_kea_ecdh, ssl_sign_null, ssl_auth_null, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDH_ANON}, - {kea_ecdhe_psk, ssl_kea_ecdh_psk, ssl_sign_null, ssl_auth_psk, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDHE_PSK} + {kea_ecdh_ecdsa, kt_ecdh, ssl_sign_ecdsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_ECDSA}, + {kea_ecdhe_ecdsa, kt_ecdh, ssl_sign_ecdsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDHE_ECDSA}, + {kea_ecdh_rsa, kt_ecdh, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_FALSE, SEC_OID_TLS_ECDH_RSA}, + {kea_ecdhe_rsa, kt_ecdh, ssl_sign_rsa, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDHE_RSA}, + {kea_ecdh_anon, kt_ecdh, ssl_sign_null, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDH_ANON}, + {kea_ecdhe_psk, kt_ecdh, ssl_sign_psk, PR_FALSE, 0, PR_FALSE, PR_TRUE, SEC_OID_TLS_ECDHE_PSK} #endif /* NSS_DISABLE_ECC */ }; @@ -480,28 +479,13 @@ static const ssl3CipherSuiteDef cipher_suite_defs[] = }; /* clang-format on */ -static const CK_MECHANISM_TYPE auth_alg_defs[] = { - 0x80000000L, /* ssl_auth_null */ - CKM_RSA_PKCS, /* ssl_auth_rsa_decrypt */ - CKM_DSA, /* ? _SHA1 */ /* ssl_auth_dsa */ - 0x80000000L, /* ssl_auth_kea (unused) */ - CKM_ECDSA, /* ssl_auth_ecdsa */ - CKM_ECDH1_DERIVE, /* ssl_auth_ecdh */ - CKM_RSA_PKCS, /* ssl_auth_rsa_sign */ - CKM_RSA_PKCS_PSS, /* ssl_auth_rsa_pss */ - CKM_NSS_HKDF_SHA256 /* ssl_auth_psk (just check for HKDF) */ -}; -PR_STATIC_ASSERT(PR_ARRAY_SIZE(auth_alg_defs) == ssl_auth_size); - static const CK_MECHANISM_TYPE kea_alg_defs[] = { - 0x80000000L, /* ssl_kea_null */ - CKM_RSA_PKCS, /* ssl_kea_rsa */ - CKM_DH_PKCS_DERIVE, /* ssl_kea_dh */ - 0x80000000L, /* ssl_kea_fortezza (unused) */ - CKM_ECDH1_DERIVE, /* ssl_kea_ecdh */ - CKM_ECDH1_DERIVE /* ssl_kea_ecdh_psk */ + 0x80000000L, + CKM_RSA_PKCS, + CKM_DH_PKCS_DERIVE, + CKM_KEA_KEY_DERIVE, + CKM_ECDH1_DERIVE }; -PR_STATIC_ASSERT(PR_ARRAY_SIZE(kea_alg_defs) == ssl_kea_size); typedef struct SSLCipher2MechStr { SSLCipherAlgorithm calg; @@ -822,27 +806,6 @@ ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, ssl3CipherSuiteCfg *suites) return NULL; } -static PRBool -ssl3_HasCert(sslSocket *ss, SSLAuthType authType) -{ - PRCList *cursor; - if (authType == ssl_auth_null) { - return PR_TRUE; - } - for (cursor = PR_NEXT_LINK(&ss->serverCerts); - cursor != &ss->serverCerts; - cursor = PR_NEXT_LINK(cursor)) { - sslServerCert *cert = (sslServerCert*)cursor; - if (cert->certType.authType == authType && - cert->serverKeyPair && - cert->serverKeyPair->privKey && - cert->serverCertChain) { - return PR_TRUE; - } - } - return PR_FALSE; -} - /* Initialize the suite->isPresent value for config_match * Returns count of enabled ciphers supported by extant tokens, * regardless of policy or user preference. @@ -855,12 +818,12 @@ ssl3_config_match_init(sslSocket *ss) const ssl3CipherSuiteDef *cipher_def; SSLCipherAlgorithm cipher_alg; CK_MECHANISM_TYPE cipher_mech; - SSLAuthType authType; - SSLKEAType keaType; + SSL3KEAType exchKeyType; int i; int numPresent = 0; int numEnabled = 0; PRBool isServer; + sslServerCerts *svrAuth; PORT_Assert(ss); if (!ss) { @@ -886,34 +849,50 @@ ssl3_config_match_init(sslSocket *ss) } cipher_alg = bulk_cipher_defs[cipher_def->bulk_cipher_alg].calg; cipher_mech = ssl3_Alg2Mech(cipher_alg); - - /* Mark the suites that are backed by real tokens, certs and keys */ - suite->isPresent = PR_TRUE; - - authType = kea_defs[cipher_def->key_exchange_alg].authKeyType; - if (authType != ssl_auth_null) { - if (isServer && !ssl3_HasCert(ss, authType)) { - suite->isPresent = PR_FALSE; - } - if (!PK11_TokenExists(auth_alg_defs[authType])) { - suite->isPresent = PR_FALSE; - } - } - - keaType = kea_defs[cipher_def->key_exchange_alg].exchKeyType; - if (keaType != ssl_kea_null && - !PK11_TokenExists(kea_alg_defs[keaType])) { - suite->isPresent = PR_FALSE; - } - - if (cipher_alg != calg_null && - !PK11_TokenExists(cipher_mech)) { - suite->isPresent = PR_FALSE; + exchKeyType = + kea_defs[cipher_def->key_exchange_alg].exchKeyType; +#ifdef NSS_DISABLE_ECC + svrAuth = ss->serverCerts + exchKeyType; +#else + /* XXX SSLKEAType isn't really a good choice for + * indexing certificates. It doesn't work for + * (EC)DHE-* ciphers. Here we use a hack to ensure + * that the server uses an RSA cert for (EC)DHE-RSA. + */ + switch (cipher_def->key_exchange_alg) { + case kea_dhe_dss: + svrAuth = ss->serverCerts + ssl_kea_dh; + break; + case kea_ecdhe_rsa: + case kea_dhe_rsa: + svrAuth = ss->serverCerts + kt_rsa; + break; + case kea_ecdh_ecdsa: + case kea_ecdh_rsa: + /* + * XXX We ought to have different indices for + * ECDSA- and RSA-signed EC certificates so + * we could support both key exchange mechanisms + * simultaneously. For now, both of them use + * whatever is in the certificate slot for kt_ecdh + */ + case kea_dhe_dss_export: + case kea_dhe_rsa_export: + default: + svrAuth = ss->serverCerts + exchKeyType; + break; } +#endif /* NSS_DISABLE_ECC */ - if (suite->isPresent) { + /* Mark the suites that are backed by real tokens, certs and keys */ + suite->isPresent = (PRBool)(((exchKeyType == kt_null) || + ((!isServer || + (svrAuth->serverKeyPair && svrAuth->SERVERKEY && + svrAuth->serverCertChain)) && + PK11_TokenExists(kea_alg_defs[exchKeyType]))) && + ((cipher_alg == calg_null) || PK11_TokenExists(cipher_mech))); + if (suite->isPresent) ++numPresent; - } } } PORT_Assert(numPresent > 0 || numEnabled == 0); @@ -957,8 +936,8 @@ config_match(ssl3CipherSuiteCfg *suite, int policy, PRBool enabled, return PR_FALSE; /* We only allow PSK for TLS 1.3 and only if there is resumption. */ - if (kea_defs[cipher_def->key_exchange_alg].authKeyType == - ssl_auth_psk) { + if (kea_defs[cipher_def->key_exchange_alg].signKeyType == + ssl_sign_psk) { return tls13_AllowPskCipher(ss, cipher_def); } @@ -3928,8 +3907,8 @@ ssl3_ComputeMasterSecretInt(sslSocket *ss, PK11SymKey *pms, * which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size * data into a 48-byte value, and does not expect to return the version. */ - PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_dh) || - (ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_ecdh)); + PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) || + (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh)); CK_MECHANISM_TYPE master_derive; CK_MECHANISM_TYPE key_derive; SECItem params; @@ -4005,9 +3984,9 @@ tls_ComputeExtendedMasterSecretInt(sslSocket *ss, PK11SymKey *pms, */ /* * TODO(ekr@rtfm.com): Verify that the slot can handle this key expansion - * mode. Bug 1198298 */ - PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_dh) || - (ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_ecdh)); + * mode. Bug 1198298 */ + PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == kt_dh) || + (ss->ssl3.hs.kea_def->exchKeyType == kt_ecdh)); CK_MECHANISM_TYPE master_derive; CK_MECHANISM_TYPE key_derive; SECItem params; @@ -5918,7 +5897,7 @@ static PK11SymKey * ssl_UnwrapSymWrappingKey( SSLWrappedSymWrappingKey *pWswk, SECKEYPrivateKey *svrPrivKey, - SSLAuthType authType, + SSL3KEAType exchKeyType, CK_MECHANISM_TYPE masterWrapMech, void *pwArg) { @@ -5932,9 +5911,9 @@ ssl_UnwrapSymWrappingKey( /* found the wrapping key on disk. */ PORT_Assert(pWswk->symWrapMechanism == masterWrapMech); - PORT_Assert(pWswk->authType == authType); + PORT_Assert(pWswk->exchKeyType == exchKeyType); if (pWswk->symWrapMechanism != masterWrapMech || - pWswk->authType != authType) { + pWswk->exchKeyType != exchKeyType) { goto loser; } wrappedKey.type = siBuffer; @@ -5942,20 +5921,18 @@ ssl_UnwrapSymWrappingKey( wrappedKey.len = pWswk->wrappedSymKeyLen; PORT_Assert(wrappedKey.len <= sizeof pWswk->wrappedSymmetricWrappingkey); - switch (authType) { + switch (exchKeyType) { - case ssl_auth_rsa_decrypt: - case ssl_auth_rsa_sign: /* bad: see Bug 1248320 */ + case kt_rsa: unwrappedWrappingKey = - PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey, - masterWrapMech, CKA_UNWRAP, 0); + PK11_PubUnwrapSymKey(svrPrivKey, &wrappedKey, + masterWrapMech, CKA_UNWRAP, 0); break; #ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: + case kt_ecdh: /* - * For ssl_auth_ecd*, we first create an EC public key based on + * For kt_ecdh, we first create an EC public key based on * data stored with the wrappedSymmetricWrappingkey. Next, * we do an ECDH computation involving this public key and * the SSL server's (long-term) EC private key. The resulting @@ -6014,14 +5991,14 @@ loser: return unwrappedWrappingKey; } -/* Each process sharing the server session ID cache has its own array of SymKey - * pointers for the symmetric wrapping keys that are used to wrap the master - * secrets. There is one key for each authentication type. These Symkeys +/* Each process sharing the server session ID cache has its own array of + * SymKey pointers for the symmetric wrapping keys that are used to wrap + * the master secrets. There is one key for each KEA type. These Symkeys * correspond to the wrapped SymKeys kept in the server session cache. */ typedef struct { - PK11SymKey *symWrapKey[ssl_auth_size]; + PK11SymKey *symWrapKey[kt_kea_size]; } ssl3SymWrapKey; static PZLock *symWrapKeysLock = NULL; @@ -6049,7 +6026,7 @@ SSL3_ShutdownServerCache(void) PZ_Lock(symWrapKeysLock); /* get rid of all symWrapKeys */ for (i = 0; i < SSL_NUM_WRAP_MECHS; ++i) { - for (j = 0; j < ssl_auth_size; ++j) { + for (j = 0; j < kt_kea_size; ++j) { PK11SymKey **pSymWrapKey; pSymWrapKey = &symWrapKeys[i].symWrapKey[j]; if (*pSymWrapKey) { @@ -6075,19 +6052,14 @@ ssl_InitSymWrapKeysLock(void) * If that fails, look for one on disk. * If that fails, generate a new one, put the new one on disk, * Put the new key in the in-memory array. - * - * Note that this function performs some fairly inadvisable functions with - * certificate private keys. ECDSA keys are used with ECDH; similarly, RSA - * signing keys are used to encrypt. Bug 1248320. */ PK11SymKey * ssl3_GetWrappingKey(sslSocket *ss, PK11SlotInfo *masterSecretSlot, - const sslServerCert *serverCert, + SSL3KEAType exchKeyType, CK_MECHANISM_TYPE masterWrapMech, void *pwArg) { - SSLAuthType authType; SECKEYPrivateKey *svrPrivKey; SECKEYPublicKey *svrPubKey = NULL; PK11SymKey *unwrappedWrappingKey = NULL; @@ -6105,25 +6077,18 @@ ssl3_GetWrappingKey(sslSocket *ss, ECCWrappedKeyInfo *ecWrapped; #endif /* NSS_DISABLE_ECC */ - PORT_Assert(serverCert); - PORT_Assert(serverCert->serverKeyPair); - PORT_Assert(serverCert->serverKeyPair->privKey); - PORT_Assert(serverCert->serverKeyPair->pubKey); - if (!serverCert || !serverCert->serverKeyPair || - !serverCert->serverKeyPair->privKey || - !serverCert->serverKeyPair->pubKey) { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; /* hmm */ + svrPrivKey = ss->serverCerts[exchKeyType].SERVERKEY; + PORT_Assert(svrPrivKey != NULL); + if (!svrPrivKey) { + return NULL; /* why are we here?!? */ } - authType = serverCert->certType.authType; - svrPrivKey = serverCert->serverKeyPair->privKey; symWrapMechIndex = ssl_FindIndexByWrapMechanism(masterWrapMech); PORT_Assert(symWrapMechIndex >= 0); if (symWrapMechIndex < 0) return NULL; /* invalid masterWrapMech. */ - pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[authType]; + pSymWrapKey = &symWrapKeys[symWrapMechIndex].symWrapKey[exchKeyType]; ssl_InitSessionCacheLocks(PR_TRUE); @@ -6142,10 +6107,10 @@ ssl3_GetWrappingKey(sslSocket *ss, /* Try to get wrapped SymWrapping key out of the (disk) cache. */ /* Following call fills in wswk on success. */ - if (ssl_GetWrappingKey(symWrapMechIndex, authType, &wswk)) { + if (ssl_GetWrappingKey(symWrapMechIndex, exchKeyType, &wswk)) { /* found the wrapped sym wrapping key on disk. */ unwrappedWrappingKey = - ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, authType, + ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType, masterWrapMech, pwArg); if (unwrappedWrappingKey) { goto install; @@ -6170,7 +6135,13 @@ ssl3_GetWrappingKey(sslSocket *ss, */ PORT_Memset(&wswk, 0, sizeof wswk); /* eliminate UMRs. */ - svrPubKey = serverCert->serverKeyPair->pubKey; + if (ss->serverCerts[exchKeyType].serverKeyPair) { + svrPubKey = ss->serverCerts[exchKeyType].serverKeyPair->pubKey; + } + if (svrPubKey == NULL) { + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + goto loser; + } wrappedKey.type = siBuffer; wrappedKey.len = SECKEY_PublicKeyStrength(svrPubKey); wrappedKey.data = wswk.wrappedSymmetricWrappingkey; @@ -6180,17 +6151,15 @@ ssl3_GetWrappingKey(sslSocket *ss, goto loser; /* wrap symmetric wrapping key in server's public key. */ - switch (authType) { - case ssl_auth_rsa_decrypt: - case ssl_auth_rsa_sign: /* bad: see Bug 1248320 */ + switch (exchKeyType) { + case kt_rsa: asymWrapMechanism = CKM_RSA_PKCS; rv = PK11_PubWrapSymKey(asymWrapMechanism, svrPubKey, unwrappedWrappingKey, &wrappedKey); break; #ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: + case kt_ecdh: /* * We generate an ephemeral EC key pair. Perform an ECDH * computation involving this ephemeral EC public key and @@ -6295,7 +6264,7 @@ ssl3_GetWrappingKey(sslSocket *ss, wswk.symWrapMechanism = masterWrapMech; wswk.symWrapMechIndex = symWrapMechIndex; wswk.asymWrapMechanism = asymWrapMechanism; - wswk.authType = authType; + wswk.exchKeyType = exchKeyType; wswk.wrappedSymKeyLen = wrappedKey.len; /* put it on disk. */ @@ -6311,7 +6280,7 @@ ssl3_GetWrappingKey(sslSocket *ss, PK11_FreeSymKey(unwrappedWrappingKey); unwrappedWrappingKey = - ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, authType, + ssl_UnwrapSymWrappingKey(&wswk, svrPrivKey, exchKeyType, masterWrapMech, pwArg); } @@ -6586,16 +6555,16 @@ ssl3_SendClientKeyExchange(sslSocket *ss) ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(serverKey); switch (ss->ssl3.hs.kea_def->exchKeyType) { - case ssl_kea_rsa: + case kt_rsa: rv = sendRSAClientKeyExchange(ss, serverKey); break; - case ssl_kea_dh: + case kt_dh: rv = sendDHClientKeyExchange(ss, serverKey); break; #ifndef NSS_DISABLE_ECC - case ssl_kea_ecdh: + case kt_ecdh: rv = ssl3_SendECDHClientKeyExchange(ss, serverKey); break; #endif /* NSS_DISABLE_ECC */ @@ -7058,7 +7027,7 @@ ssl3_HandleServerHelloPart2(sslSocket *ss, const SECItem *sidBytes, goto alert_loser; } - ss->sec.authType = sid->authType; + ss->sec.authAlgorithm = sid->authAlgorithm; ss->sec.authKeyBits = sid->authKeyBits; ss->sec.keaType = sid->keaType; ss->sec.keaKeyBits = sid->keaKeyBits; @@ -7204,8 +7173,8 @@ ssl3_HandleServerHelloPart2(sslSocket *ss, const SECItem *sidBytes, } ss->ssl3.hs.isResuming = PR_FALSE; - if (ss->ssl3.hs.kea_def->authKeyType != ssl_auth_null) { - /* All current cipher suites other than those with ssl_auth_null (i.e., + if (ss->ssl3.hs.kea_def->signKeyType != ssl_sign_null) { + /* All current cipher suites other than those with ssl_sign_null (i.e., * (EC)DH_anon_* suites) require a certificate, so use that signal. */ ss->ssl3.hs.ws = wait_server_cert; } else { @@ -7259,7 +7228,8 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) isTLS12 = (PRBool)(ss->ssl3.prSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); switch (ss->ssl3.hs.kea_def->exchKeyType) { - case ssl_kea_rsa: { + + case kt_rsa: { SECItem modulus = { siBuffer, NULL, 0 }; SECItem exponent = { siBuffer, NULL, 0 }; @@ -7295,7 +7265,8 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } if (length != 0) { if (isTLS) - desc = decode_error; + desc = + decode_error; goto alert_loser; /* malformed. */ } @@ -7351,7 +7322,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) return SECSuccess; } - case ssl_kea_dh: { + case kt_dh: { SECItem dh_p = { siBuffer, NULL, 0 }; SECItem dh_g = { siBuffer, NULL, 0 }; SECItem dh_Ys = { siBuffer, NULL, 0 }; @@ -7407,7 +7378,8 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } if (length != 0) { if (isTLS) - desc = decode_error; + desc = + decode_error; goto alert_loser; /* malformed. */ } @@ -7470,7 +7442,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) } #ifndef NSS_DISABLE_ECC - case ssl_kea_ecdh: + case kt_ecdh: rv = ssl3_HandleECDHServerKeyExchange(ss, b, length); return rv; #endif /* NSS_DISABLE_ECC */ @@ -8244,26 +8216,15 @@ ssl3_SendServerHelloSequence(sslSocket *ss) kea_def = ss->ssl3.hs.kea_def; ss->ssl3.hs.usedStepDownKey = PR_FALSE; - if (kea_def->is_limited) { + if (kea_def->is_limited && kea_def->exchKeyType == kt_rsa) { /* see if we can legally use the key in the cert. */ - unsigned int keyBits; - const sslServerCert *cert; + unsigned int keyLen; /* bytes */ - /* Note that all ciphers that are limited use a SSLAuthType of - * ssl_auth_rsa_sign. This isn't even remotely correct, but these keys - * need to do either signing or decryption on demand. */ - PORT_Assert(kea_def->authKeyType == ssl_auth_rsa_sign); + keyLen = PK11_GetPrivateModulusLen( + ss->serverCerts[kea_def->exchKeyType].SERVERKEY); - cert = ssl_FindServerCertByAuthType(ss, ssl_auth_rsa_sign); - if (!cert || !cert->serverKeyPair || !cert->serverKeyPair->pubKey) { - PORT_SetError(SSL_ERROR_NO_CERTIFICATE); - return SECFailure; - } - - keyBits = SECKEY_PublicKeyStrengthInBits(cert->serverKeyPair->pubKey); - PORT_Assert(keyBits); - - if (keyBits <= kea_def->key_size_limit) { + if (keyLen > 0 && + keyLen * BPB <= kea_def->key_size_limit) { /* XXX AND cert is not signing only!! */ /* just fall through and use it. */ } else if (ss->stepDownKeyPair != NULL) { @@ -8305,14 +8266,19 @@ ssl3_SendServerHelloSequence(sslSocket *ss) static const PRUint8 emptyRIext[5] = { 0xff, 0x01, 0x00, 0x01, 0x00 }; static PRBool -ssl3_KEASupportsTickets(const ssl3KEADef *kea_def) -{ - if (kea_def->signKeyType == ssl_sign_dsa) { - /* TODO: Fix session tickets for DSS. The server code rejects the - * session ticket received from the client. Bug 1174677 */ - return PR_FALSE; - } - return PR_TRUE; +ssl3_KEAAllowsSessionTicket(SSL3KeyExchangeAlgorithm kea) +{ + switch (kea) { + case kea_dhe_dss: + case kea_dhe_dss_export: + case kea_dh_dss_export: + case kea_dh_dss: + /* TODO: Fix session tickets for DSS. The server code rejects the + * session ticket received from the client. Bug 1174677 */ + return PR_FALSE; + default: + return PR_TRUE; + }; } /* Select a cipher suite. @@ -8526,45 +8492,6 @@ alert_loser: return SECFailure; } -SECStatus -ssl3_SelectServerCert(sslSocket *ss) -{ - const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def; - PRCList *cursor; - - /* This picks the first certificate that has: - * a) the right authentication method, and - * b) the right named curve (EC only) - * - * We might want to do some sort of ranking here later. For now, it's all - * based on what order they are configured in. */ - for (cursor = PR_NEXT_LINK(&ss->serverCerts); - cursor != &ss->serverCerts; - cursor = PR_NEXT_LINK(cursor)) { - sslServerCert *cert = (sslServerCert*)cursor; - if (cert->certType.authType != kea_def->authKeyType) { - continue; - } -#ifndef NSS_DISABLE_ECC - if ((cert->certType.authType == ssl_auth_ecdh || - cert->certType.authType == ssl_auth_ecdsa) && - !SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, - cert->certType.u.namedCurve)) { - continue; - } -#endif - - /* Found one. */ - ss->sec.serverCert = cert; - ss->sec.authType = cert->certType.authType; - ss->sec.authKeyBits = cert->serverKeyBits; - return SECSuccess; - } - - PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); - return SECFailure; -} - /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete * ssl3 Client Hello message. * Caller must hold Handshake and RecvBuf locks. @@ -9030,8 +8957,8 @@ static SECStatus ssl3_HandleClientHelloPart2(sslSocket *ss, } if (canOfferSessionTicket) - canOfferSessionTicket = - ssl3_KEASupportsTickets(ss->ssl3.hs.kea_def); + canOfferSessionTicket = ssl3_KEAAllowsSessionTicket( + ss->ssl3.hs.suite_def->key_exchange_alg); if (canOfferSessionTicket) { ssl3_RegisterServerHelloExtensionSender(ss, @@ -9068,7 +8995,6 @@ compression_found: do { ssl3CipherSpec *pwSpec; SECItem wrappedMS; /* wrapped key */ - const sslServerCert *serverCert; if (sid->version != ss->version || sid->u.ssl3.cipherSuite != ss->ssl3.hs.cipher_suite || @@ -9076,14 +9002,6 @@ compression_found: break; /* not an error */ } - serverCert = ssl_FindServerCert(ss, &sid->certType); - if (!serverCert) { - /* A compatible certificate must not have been configured. It - * might not be the same certificate, but we only find that out - * when the ticket fails to decrypt. */ - break; - } - /* [draft-ietf-tls-session-hash-06; Section 5.3] * o If the original session did not use the "extended_master_secret" * extension but the new ClientHello contains the extension, then the @@ -9134,7 +9052,7 @@ compression_found: } #endif - wrapKey = ssl3_GetWrappingKey(ss, NULL, serverCert, + wrapKey = ssl3_GetWrappingKey(ss, NULL, sid->u.ssl3.exchKeyType, sid->u.ssl3.masterWrapMech, ss->pkcs11PinArg); if (!wrapKey) { @@ -9143,7 +9061,8 @@ compression_found: } if (ss->version > SSL_LIBRARY_VERSION_3_0) { /* isTLS */ - keyFlags = CKF_SIGN | CKF_VERIFY; + keyFlags = + CKF_SIGN | CKF_VERIFY; } wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret; @@ -9197,18 +9116,18 @@ compression_found: SSL_AtomicIncrementLong(&ssl3stats.hch_sid_stateless_resumes); ss->ssl3.hs.isResuming = PR_TRUE; - ss->sec.authType = sid->authType; + ss->sec.authAlgorithm = sid->authAlgorithm; ss->sec.authKeyBits = sid->authKeyBits; ss->sec.keaType = sid->keaType; ss->sec.keaKeyBits = sid->keaKeyBits; /* server sids don't remember the server cert we previously sent, - ** but they do remember the slot we originally used, so we + ** but they do remember the kea type we originally used, so we ** can locate it again, provided that the current ssl socket ** has had its server certs configured the same as the previous one. */ - ss->sec.serverCert = serverCert; - ss->sec.localCert = CERT_DupCertificate(serverCert->serverCert); + ss->sec.localCert = + CERT_DupCertificate(ss->serverCerts[sid->keaType].serverCert); /* Copy cached name in to pending spec */ if (sid != NULL && @@ -9297,13 +9216,6 @@ compression_found: goto loser; } - rv = ssl3_SelectServerCert(ss); - if (rv != SECSuccess) { - errCode = PORT_GetError(); - desc = handshake_failure; - goto alert_loser; - } - sid = ssl3_NewSessionID(ss, PR_TRUE); if (sid == NULL) { errCode = PORT_GetError(); @@ -9537,13 +9449,6 @@ suite_found: ss->ssl3.hs.compression = ssl_compression_null; - rv = ssl3_SelectServerCert(ss); - if (rv != SECSuccess) { - errCode = PORT_GetError(); - desc = handshake_failure; - goto alert_loser; - } - /* we don't even search for a cache hit here. It's just a miss. */ SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_misses); sid = ssl3_NewSessionID(ss, PR_TRUE); @@ -9724,7 +9629,7 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss) ssl3KeyPair *keyPair = NULL; SECKEYPublicKey *pubKey = NULL; /* Ephemeral DH key */ SECKEYPrivateKey *privKey = NULL; /* Ephemeral DH key */ - SECKEYPrivateKey *certPrivateKey; + int certIndex = -1; if (kea_def->kea != kea_dhe_dss && kea_def->kea != kea_dhe_rsa) { /* TODO: Support DH_anon. It might be sufficient to drop the signature. @@ -9777,9 +9682,16 @@ ssl3_SendDHServerKeyExchange(sslSocket *ss) goto loser; } + /* It has been suggested to test kea_def->signKeyType instead, and to use + * ssl_auth_* instead. Investigate what to do. See bug 102794. */ + if (kea_def->kea == kea_dhe_rsa) + certIndex = ssl_kea_rsa; + else + certIndex = ssl_kea_dh; + isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); - certPrivateKey = ss->sec.serverCert->serverKeyPair->privKey; - rv = ssl3_SignHashes(&hashes, certPrivateKey, &signed_hash, isTLS); + rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY, + &signed_hash, isTLS); if (rv != SECSuccess) { goto loser; /* ssl3_SignHashes has set err. */ } @@ -9927,7 +9839,7 @@ ssl3_SendServerKeyExchange(sslSocket *ss) } switch (kea_def->exchKeyType) { - case ssl_kea_rsa: + case kt_rsa: /* Perform SSL Step-Down here. */ sdPub = ss->stepDownKeyPair->pubKey; PORT_Assert(sdPub != NULL); @@ -9947,7 +9859,7 @@ ssl3_SendServerKeyExchange(sslSocket *ss) } isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); - rv = ssl3_SignHashes(&hashes, ss->sec.serverCert->serverKeyPair->privKey, + rv = ssl3_SignHashes(&hashes, ss->serverCerts[kt_rsa].SERVERKEY, &signed_hash, isTLS); if (rv != SECSuccess) { goto loser; /* ssl3_SignHashes has set err. */ @@ -9958,8 +9870,8 @@ ssl3_SendServerKeyExchange(sslSocket *ss) goto loser; } length = 2 + sdPub->u.rsa.modulus.len + - 2 + sdPub->u.rsa.publicExponent.len + - 2 + signed_hash.len; + 2 + sdPub->u.rsa.publicExponent.len + + 2 + signed_hash.len; if (ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2) { length += 2; @@ -10004,13 +9916,13 @@ ssl3_SendServerKeyExchange(sslSocket *ss) } #ifndef NSS_DISABLE_ECC - case ssl_kea_ecdh: { + case kt_ecdh: { rv = ssl3_SendECDHServerKeyExchange(ss, &sigAndHash); return rv; } #endif /* NSS_DISABLE_ECC */ - case ssl_kea_null: + case kt_null: default: PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); break; @@ -10627,10 +10539,11 @@ ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) if (ss->ssl3.hs.usedStepDownKey) { PORT_Assert(kea_def->is_limited /* XXX OR cert is signing only */ - && kea_def->authKeyType == ssl_auth_rsa_sign - && ss->stepDownKeyPair != NULL); + && + kea_def->exchKeyType == kt_rsa && + ss->stepDownKeyPair != NULL); if (!kea_def->is_limited || - kea_def->authKeyType != ssl_auth_rsa_sign || + kea_def->exchKeyType != kt_rsa || ss->stepDownKeyPair == NULL) { /* shouldn't happen, don't use step down if it does */ goto skip; @@ -10639,27 +10552,38 @@ ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB; } else skip: - if (kea_def->ephemeral) { - if (kea_def->exchKeyType == ssl_kea_dh && ss->dheKeyPair) { + if (kea_def->kea == kea_dhe_dss || + kea_def->kea == kea_dhe_rsa) { + if (ss->dheKeyPair) { serverKeyPair = ss->dheKeyPair; if (serverKeyPair->pubKey) { ss->sec.keaKeyBits = SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey); } } + } else #ifndef NSS_DISABLE_ECC - else if (kea_def->exchKeyType == ssl_kea_ecdh && - ss->ephemeralECDHKeyPair) { + /* XXX Using SSLKEAType to index server certifiates + * does not work for (EC)DHE ciphers. Until we have + * an indexing mechanism general enough for all key + * exchange algorithms, we'll need to deal with each + * one seprately. + */ + if ((kea_def->kea == kea_ecdhe_rsa) || + (kea_def->kea == kea_ecdhe_ecdsa)) { + if (ss->ephemeralECDHKeyPair != NULL) { serverKeyPair = ss->ephemeralECDHKeyPair; if (serverKeyPair->pubKey) { ss->sec.keaKeyBits = - SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey); + SECKEY_PublicKeyStrengthInBits(serverKeyPair->pubKey); } } + } else #endif - } else { - serverKeyPair = ss->sec.serverCert->serverKeyPair; - ss->sec.keaKeyBits = ss->sec.serverCert->serverKeyBits; + { + sslServerCerts *sc = ss->serverCerts + kea_def->exchKeyType; + serverKeyPair = sc->serverKeyPair; + ss->sec.keaKeyBits = sc->serverKeyBits; } if (serverKeyPair) { @@ -10675,7 +10599,7 @@ ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ss->sec.keaType = kea_def->exchKeyType; switch (kea_def->exchKeyType) { - case ssl_kea_rsa: + case kt_rsa: rv = ssl3_HandleRSAClientKeyExchange(ss, b, length, serverKey); if (rv != SECSuccess) { SEND_ALERT @@ -10700,7 +10624,13 @@ ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) break; #ifndef NSS_DISABLE_ECC - case ssl_kea_ecdh: + case kt_ecdh: + /* XXX We really ought to be able to store multiple + * EC certs (a requirement if we wish to support both + * ECDH-RSA and ECDH-ECDSA key exchanges concurrently). + * When we make that change, we'll need an index other + * than kt_ecdh to pick the right EC certificate. + */ if (serverKeyPair) { serverPubKey = serverKeyPair->pubKey; } @@ -10887,6 +10817,7 @@ ssl3_SendCertificate(sslSocket *ss) CERTCertificateList *certChain; int certChainLen = 0; int i; + SSL3KEAType certIndex; #ifdef NISCC_TEST SECItem fakeCert; int ndex = -1; @@ -10903,11 +10834,27 @@ ssl3_SendCertificate(sslSocket *ss) if (ss->sec.localCert) CERT_DestroyCertificate(ss->sec.localCert); if (ss->sec.isServer) { - /* A server certificate is selected in ssl3_HandleClientHello. */ - PORT_Assert(ss->sec.serverCert); - - certChain = ss->sec.serverCert->serverCertChain; - ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert); + sslServerCerts *sc = NULL; + + /* XXX SSLKEAType isn't really a good choice for + * indexing certificates (it breaks when we deal + * with (EC)DHE-* cipher suites. This hack ensures + * the RSA cert is picked for (EC)DHE-RSA. + * Revisit this when we add server side support + * for ECDHE-ECDSA or client-side authentication + * using EC certificates. + */ + if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) || + (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) { + certIndex = kt_rsa; + } else { + certIndex = ss->ssl3.hs.kea_def->exchKeyType; + } + sc = ss->serverCerts + certIndex; + certChain = sc->serverCertChain; + ss->sec.authKeyBits = sc->serverKeyBits; + ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType; + ss->sec.localCert = CERT_DupCertificate(sc->serverCert); } else { certChain = ss->ssl3.clientCertChain; ss->sec.localCert = CERT_DupCertificate(ss->ssl3.clientCertificate); @@ -10994,7 +10941,7 @@ ssl3_SendCertificateStatus(sslSocket *ss) SECStatus rv; int len = 0; SECItemArray *statusToSend = NULL; - const sslServerCert *serverCert; + SSL3KEAType certIndex; SSL_TRC(3, ("%d: SSL3[%d]: send certificate status handshake", SSL_GETPID(), ss->fd)); @@ -11007,9 +10954,14 @@ ssl3_SendCertificateStatus(sslSocket *ss) return SECSuccess; /* Use certStatus based on the cert being used. */ - serverCert = ss->sec.serverCert; - if (serverCert->certStatusArray && serverCert->certStatusArray->len) { - statusToSend = serverCert->certStatusArray; + if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) || + (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) { + certIndex = kt_rsa; + } else { + certIndex = ss->ssl3.hs.kea_def->exchKeyType; + } + if (ss->certStatusArray[certIndex] && ss->certStatusArray[certIndex]->len) { + statusToSend = ss->certStatusArray[certIndex]; } if (!statusToSend) return SECSuccess; @@ -11366,7 +11318,7 @@ ssl3_AuthCertificate(sslSocket *ss) /* set the server authentication type and size from the value ** in the cert. */ SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(cert); - ss->sec.authType = ss->ssl3.hs.kea_def->authKeyType; + ss->sec.authAlgorithm = ss->ssl3.hs.kea_def->signKeyType; ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType; if (pubKey) { KeyType pubKeyType; @@ -11831,7 +11783,7 @@ fail: */ SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid, - ssl3CipherSpec *spec, SSLAuthType authType) + ssl3CipherSpec *spec, SSL3KEAType effectiveExchKeyType) { PK11SymKey *wrappingKey = NULL; PK11SlotInfo *symKeySlot; @@ -11839,7 +11791,6 @@ ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid, SECStatus rv = SECFailure; PRBool isServer = ss->sec.isServer; CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; - symKeySlot = PK11_GetSlotFromKey(spec->master_secret); if (!isServer) { int wrapKeyIndex; @@ -11885,7 +11836,7 @@ ssl3_CacheWrappedMasterSecret(sslSocket *ss, sslSessionID *sid, mechanism = PK11_GetBestWrapMechanism(symKeySlot); if (mechanism != CKM_INVALID_MECHANISM) { wrappingKey = - ssl3_GetWrappingKey(ss, symKeySlot, ss->sec.serverCert, + ssl3_GetWrappingKey(ss, symKeySlot, effectiveExchKeyType, mechanism, pwArg); if (wrappingKey) { mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */ @@ -11922,6 +11873,7 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, SECStatus rv = SECSuccess; PRBool isServer = ss->sec.isServer; PRBool isTLS; + SSL3KEAType effectiveExchKeyType; PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); @@ -11998,7 +11950,7 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, */ if (isServer && !ss->ssl3.hs.isResuming && ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) && - ssl3_KEASupportsTickets(ss->ssl3.hs.kea_def)) { + ssl3_KEAAllowsSessionTicket(ss->ssl3.hs.suite_def->key_exchange_alg)) { /* RFC 5077 Section 3.3: "In the case of a full handshake, the * server MUST verify the client's Finished message before sending * the ticket." Presumably, this also means that the client's @@ -12046,8 +11998,15 @@ xmit_loser: return rv; } + if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa || + ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) { + effectiveExchKeyType = kt_rsa; + } else { + effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType; + } + if (sid->cached == never_cached && !ss->opt.noCache && ss->sec.cache) { - rv = ssl3_FillInCachedSID(ss, sid); + rv = ssl3_FillInCachedSID(ss, sid, effectiveExchKeyType); /* If the wrap failed, we don't cache the sid. * The connection continues normally however. @@ -12071,7 +12030,8 @@ xmit_loser: } SECStatus -ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid) +ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid, + SSL3KEAType effectiveExchKeyType) { SECStatus rv; @@ -12084,8 +12044,9 @@ ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid) #ifndef NSS_DISABLE_ECC sid->u.ssl3.negotiatedECCurves = ss->ssl3.hs.negotiatedECCurves; #endif + sid->u.ssl3.exchKeyType = effectiveExchKeyType; sid->version = ss->version; - sid->authType = ss->sec.authType; + sid->authAlgorithm = ss->sec.authAlgorithm; sid->authKeyBits = ss->sec.authKeyBits; sid->keaType = ss->sec.keaType; sid->keaKeyBits = ss->sec.keaKeyBits; @@ -12107,7 +12068,7 @@ ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid) } else { rv = ssl3_CacheWrappedMasterSecret(ss, ss->sec.ci.sid, ss->ssl3.crSpec, - ss->ssl3.hs.kea_def->authKeyType); + effectiveExchKeyType); sid->u.ssl3.keys.msIsWrapped = PR_TRUE; } ssl_ReleaseSpecReadLock(ss); /*************************************/ @@ -12171,7 +12132,7 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, SSL3Opaque *b, PRUint32 length) { SECStatus rv = SECSuccess; SSL3HandshakeType type = ss->ssl3.hs.msg_type; - SSL3Hashes hashes; /* computed hashes are put here. */ + SSL3Hashes hashes; /* computed hashes are put here. */ SSL3Hashes *hashesPtr = NULL; /* Set when hashes are computed */ PRUint8 hdr[4]; PRUint8 dtlsData[8]; @@ -12541,7 +12502,7 @@ ssl3_HandleHandshake(sslSocket *ss, sslBuffer *origBuf) } /* end loop */ origBuf->len = 0; /* So ssl3_GatherAppDataRecord will keep looping. */ - buf->buf = NULL; /* not a leak. */ + buf->buf = NULL; /* not a leak. */ return SECSuccess; } @@ -13355,21 +13316,15 @@ ssl3_CreateRSAStepDownKeys(sslSocket *ss) { SECStatus rv = SECSuccess; SECKEYPrivateKey *privKey; /* RSA step down key */ - SECKEYPublicKey *pubKey; /* RSA step down key */ - const sslServerCert *cert; - unsigned int len; + SECKEYPublicKey *pubKey; /* RSA step down key */ if (ss->stepDownKeyPair) ssl3_FreeKeyPair(ss->stepDownKeyPair); ss->stepDownKeyPair = NULL; #ifndef HACKED_EXPORT_SERVER - cert = ssl_FindServerCertByAuthType(ss, ssl_auth_rsa_decrypt); - if (!cert) { - return SECFailure; - } - len = PK11_GetPrivateModulusLen(cert->serverKeyPair->privKey); /* Sigh, should have a get key strength call for private keys */ - if (len > EXPORT_RSA_KEY_LENGTH) { + if (PK11_GetPrivateModulusLen(ss->serverCerts[kt_rsa].SERVERKEY) > + EXPORT_RSA_KEY_LENGTH) { /* need to ask for the key size in bits */ privKey = SECKEY_CreateRSAPrivateKey(EXPORT_RSA_KEY_LENGTH * BPB, &pubKey, NULL); @@ -13600,7 +13555,7 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache) if (sid && flushCache) { if (ss->sec.uncache) ss->sec.uncache(sid); /* remove it from whichever cache it's in. */ - ssl_FreeSID(sid); /* dec ref count and free if zero. */ + ssl_FreeSID(sid); /* dec ref count and free if zero. */ ss->sec.ci.sid = NULL; } diff --git a/lib/ssl/ssl3ecc.c b/lib/ssl/ssl3ecc.c index 36996afb5..c8e9d06b5 100644 --- a/lib/ssl/ssl3ecc.c +++ b/lib/ssl/ssl3ecc.c @@ -40,6 +40,15 @@ (x)->ulValueLen = (l); #endif +#define SSL_GET_SERVER_PUBLIC_KEY(sock, type) \ + (ss->serverCerts[type].serverKeyPair ? ss->serverCerts[type].serverKeyPair->pubKey \ + : NULL) + +#define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \ + ((curveName > ec_noName) && \ + (curveName < ec_pastLastName) && \ + ((1UL << curveName) & curvemsk) != 0) + static SECStatus ssl3_CreateECDHEphemeralKeys(sslSocket *ss, ECName ec_curve); #define supportedCurve(x) (((x) > ec_noName) && ((x) < ec_pastLastName)) @@ -575,39 +584,38 @@ ssl3_GetCurveWithECKeyStrength(PRUint32 curvemsk, int requiredECCbits) ECName ssl3_GetCurveNameForServerSocket(sslSocket *ss) { + SECKEYPublicKey *svrPublicKey = NULL; ECName ec_curve = ec_noName; int signatureKeyStrength = 521; int requiredECCbits = ss->sec.secretKeyBits * 2; - PORT_Assert(ss->sec.serverCert); - if (!ss->sec.serverCert || - !ss->sec.serverCert->serverKeyPair || - !ss->sec.serverCert->serverKeyPair->pubKey) { - PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); - return ec_noName; - } - - if (ss->sec.serverCert->certType.authType == ssl_auth_ecdsa || - ss->sec.serverCert->certType.authType == ssl_auth_ecdh) { - ec_curve = ss->sec.serverCert->certType.u.namedCurve; - /* We won't select a certificate unless the named curve has been - * negotiated (or supported_curves was absent), double check that. */ - PORT_Assert(SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, - ec_curve)); - if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, - ec_curve)) { + if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa) { + svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_ecdh); + if (svrPublicKey) + ec_curve = ssl3_PubKey2ECName(svrPublicKey); + if (!SSL_IS_CURVE_NEGOTIATED(ss->ssl3.hs.negotiatedECCurves, ec_curve)) { + PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); return ec_noName; } signatureKeyStrength = curve2bits[ec_curve]; } else { /* RSA is our signing cert */ - unsigned int serverKeyStrengthInBits; - const sslServerCert *cert = ss->sec.serverCert; - PORT_Assert(cert->certType.authType == ssl_auth_rsa_sign || - cert->certType.authType == ssl_auth_rsa_decrypt); + int serverKeyStrengthInBits; + + svrPublicKey = SSL_GET_SERVER_PUBLIC_KEY(ss, kt_rsa); + if (!svrPublicKey) { + PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP); + return ec_noName; + } + + /* currently strength in bytes */ + serverKeyStrengthInBits = svrPublicKey->u.rsa.modulus.len; + if (svrPublicKey->u.rsa.modulus.data[0] == 0) { + serverKeyStrengthInBits--; + } + /* convert to strength in bits */ + serverKeyStrengthInBits *= BPB; - serverKeyStrengthInBits - = SECKEY_PublicKeyStrengthInBits(cert->serverKeyPair->pubKey); signatureKeyStrength = SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits); } @@ -896,6 +904,7 @@ ssl3_SendECDHServerKeyExchange( sslSocket *ss, const SSLSignatureAndHashAlg *sigAndHash) { + const ssl3KEADef *kea_def = ss->ssl3.hs.kea_def; SECStatus rv = SECFailure; int length; PRBool isTLS, isTLS12; @@ -906,7 +915,7 @@ ssl3_SendECDHServerKeyExchange( SECItem ec_params = { siBuffer, NULL, 0 }; unsigned char paramBuf[3]; ECName curve; - ssl3KeyPair *keyPair; + SSL3KEAType certIndex; /* Generate ephemeral ECDH key pair and send the public key */ curve = ssl3_GetCurveNameForServerSocket(ss); @@ -956,8 +965,17 @@ ssl3_SendECDHServerKeyExchange( isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0); isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2); - keyPair = ss->sec.serverCert->serverKeyPair; - rv = ssl3_SignHashes(&hashes, keyPair->privKey, &signed_hash, isTLS); + /* XXX SSLKEAType isn't really a good choice for + * indexing certificates but that's all we have + * for now. + */ + if (kea_def->kea == kea_ecdhe_rsa) + certIndex = kt_rsa; + else /* kea_def->kea == kea_ecdhe_ecdsa */ + certIndex = kt_ecdh; + + rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].SERVERKEY, + &signed_hash, isTLS); if (rv != SECSuccess) { goto loser; /* ssl3_SignHashes has set err. */ } @@ -1112,28 +1130,23 @@ ssl3_DisableECCSuites(sslSocket *ss, const ssl3CipherSuite *suite) /* Look at the server certs configured on this socket, and disable any * ECC cipher suites that are not supported by those certs. - * - * libssl generally supports multiple ECDH certificates. However, - * this function will only filter based on the first of those certificates. */ void ssl3_FilterECCipherSuitesByServerCerts(sslSocket *ss) { - sslServerCert *ecdhCert; + CERTCertificate *svrCert; - if (!ssl_FindServerCertByAuthType(ss, ssl_auth_rsa_sign)) { + svrCert = ss->serverCerts[kt_rsa].serverCert; + if (!svrCert) { ssl3_DisableECCSuites(ss, ecdhe_rsa_suites); } - if (!ssl_FindServerCertByAuthType(ss, ssl_auth_ecdsa)) { - ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites); - } - - ecdhCert = ssl_FindServerCertByAuthType(ss, ssl_auth_ecdh); - if (!ecdhCert || !ecdhCert->serverCert) { + svrCert = ss->serverCerts[kt_ecdh].serverCert; + if (!svrCert) { ssl3_DisableECCSuites(ss, ecdh_suites); + ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites); } else { - SECOidTag sigTag = SECOID_GetAlgorithmTag(&ecdhCert->serverCert->signature); + SECOidTag sigTag = SECOID_GetAlgorithmTag(&svrCert->signature); switch (sigTag) { case SEC_OID_PKCS1_RSA_ENCRYPTION: @@ -1390,6 +1403,24 @@ ssl3_HandleSupportedPointFormatsXtn(sslSocket *ss, PRUint16 ex_type, return SECSuccess; } +#define SSL3_GET_SERVER_PUBLICKEY(sock, type) \ + (ss->serverCerts[type].serverKeyPair ? ss->serverCerts[type].serverKeyPair->pubKey \ + : NULL) + +/* Extract the TLS curve name for the public key in our EC server cert. */ +ECName +ssl3_GetSvrCertCurveName(sslSocket *ss) +{ + SECKEYPublicKey *srvPublicKey; + ECName ec_curve = ec_noName; + + srvPublicKey = SSL3_GET_SERVER_PUBLICKEY(ss, kt_ecdh); + if (srvPublicKey) { + ec_curve = ssl3_PubKey2ECName(srvPublicKey); + } + return ec_curve; +} + /* Ensure that the curve in our server cert is one of the ones supported * by the remote client, and disable all ECC cipher suites if not. */ @@ -1399,9 +1430,7 @@ ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) PRInt32 list_len; PRUint32 peerCurves = 0; PRUint32 mutualCurves = 0; - PRCList *cursor; - PRBool foundECDH = PR_FALSE; - PRBool foundECDSA = PR_FALSE; + PRUint16 svrCertCurveName; if (!data->data || data->len < 4) { (void)ssl3_DecodeError(ss); @@ -1433,31 +1462,19 @@ ssl3_HandleSupportedCurvesXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) return SECSuccess; } - /* if we don't have a cert with one of these curves, + /* if our ECC cert doesn't use one of these supported curves, * disable ECC cipher suites that require an ECC cert. */ - for (cursor = PR_NEXT_LINK(&ss->serverCerts); - cursor != &ss->serverCerts; - cursor = PR_NEXT_LINK(cursor)) { - sslServerCert *cert = (sslServerCert*)cursor; - if (cert->certType.authType == ssl_auth_ecdh - && (mutualCurves & (1U << cert->certType.u.namedCurve))) { - foundECDH = PR_TRUE; - } - if (cert->certType.authType == ssl_auth_ecdsa - && (mutualCurves & (1U << cert->certType.u.namedCurve))) { - foundECDSA = PR_TRUE; - } + svrCertCurveName = ssl3_GetSvrCertCurveName(ss); + if (svrCertCurveName != ec_noName && + (mutualCurves & (1U << svrCertCurveName)) != 0) { + return SECSuccess; } /* Our EC cert doesn't contain a mutually supported curve. - * Disable the affected cipher suites. + * Disable all ECC cipher suites that require an EC cert */ - if (!foundECDH) { - ssl3_DisableECCSuites(ss, ecdh_suites); - } - if (!foundECDSA) { - ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites); - } + ssl3_DisableECCSuites(ss, ecdh_ecdsa_suites); + ssl3_DisableECCSuites(ss, ecdhe_ecdsa_suites); return SECSuccess; } diff --git a/lib/ssl/ssl3ext.c b/lib/ssl/ssl3ext.c index 6e84a06ca..07d114ee4 100644 --- a/lib/ssl/ssl3ext.c +++ b/lib/ssl/ssl3ext.c @@ -190,20 +190,9 @@ ssl3_GenerateSessionTicketKeysPKCS11(void *data) { SECStatus rv; sslSocket *ss = (sslSocket *)data; - sslServerCertType certType; - const sslServerCert *sc; - SECKEYPrivateKey *svrPrivKey; - SECKEYPublicKey *svrPubKey; - - certType.authType = ssl_auth_rsa_decrypt; - sc = ssl_FindServerCert(ss, &certType); - if (!sc || !sc->serverKeyPair) { - SSL_DBG(("%d: SSL[%d]: No ssl_auth_rsa_decrypt cert and key pair", - SSL_GETPID(), ss->fd)); - goto loser; - } - svrPrivKey = sc->serverKeyPair->privKey; - svrPubKey = sc->serverKeyPair->pubKey; + SECKEYPrivateKey *svrPrivKey = ss->serverCerts[kt_rsa].SERVERKEY; + SECKEYPublicKey *svrPubKey = ss->serverCerts[kt_rsa].serverKeyPair->pubKey; + if (svrPrivKey == NULL || svrPubKey == NULL) { SSL_DBG(("%d: SSL[%d]: Pub or priv key(s) is NULL.", SSL_GETPID(), ss->fd)); @@ -337,10 +326,6 @@ static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = { * These static tables are for the formatting of client hello extensions. * The server's table of hello senders is dynamic, in the socket struct, * and sender functions are registered there. - * NB: the order of these extensions can have an impact on compatibility. Some - * servers (e.g. Tomcat) will terminate the connection if the last extension in - * the client hello is empty (for example, the extended master secret - * extension, if it were listed last). See bug 1243641. */ static const ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { @@ -1040,11 +1025,22 @@ ssl3_ServerSendStatusRequestXtn( PRUint32 maxBytes) { PRInt32 extension_length; - const sslServerCert *serverCert = ss->sec.serverCert; + SSLKEAType effectiveExchKeyType; SECStatus rv; - if (!serverCert->certStatusArray || - !serverCert->certStatusArray->len) { + /* ssl3_SendCertificateStatus (which sents the certificate status data) + * uses the exact same logic to select the server certificate + * and determine if we have the status for that certificate. */ + + if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa || + ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) { + effectiveExchKeyType = ssl_kea_rsa; + } else { + effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType; + } + + if (!ss->certStatusArray[effectiveExchKeyType] || + !ss->certStatusArray[effectiveExchKeyType]->len) { return 0; } @@ -1139,6 +1135,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss) PRBool ms_is_wrapped; unsigned char wrapped_ms[SSL3_MASTER_SECRET_LENGTH]; SECItem ms_item = { 0, NULL, 0 }; + SSL3KEAType effectiveExchKeyType = ssl_kea_null; PRUint32 padding_length; PRUint32 message_length; PRUint32 cert_length = 0; @@ -1213,8 +1210,15 @@ ssl3_SendNewSessionTicket(sslSocket *ss) sslSessionID sid; PORT_Memset(&sid, 0, sizeof(sslSessionID)); + if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa || + ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) { + effectiveExchKeyType = kt_rsa; + } else { + effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType; + } + rv = ssl3_CacheWrappedMasterSecret(ss, &sid, spec, - ss->ssl3.hs.kea_def->authKeyType); + effectiveExchKeyType); if (rv == SECSuccess) { if (sid.u.ssl3.keys.wrapped_master_secret_len > sizeof(wrapped_ms)) goto loser; @@ -1241,8 +1245,8 @@ ssl3_SendNewSessionTicket(sslSocket *ss) + sizeof(ssl3CipherSuite) /* ciphersuite */ + 1 /* compression */ + 10 /* cipher spec parameters */ - + 1 /* certType arguments */ + 1 /* SessionTicket.ms_is_wrapped */ + + 1 /* effectiveExchKeyType */ + 4 /* msWrapMech */ + 2 /* master_secret.length */ + ms_item.len /* master_secret */ @@ -1295,7 +1299,7 @@ ssl3_SendNewSessionTicket(sslSocket *ss) goto loser; /* cipher spec parameters */ - rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authType, 1); + rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authAlgorithm, 1); if (rv != SECSuccess) goto loser; rv = ssl3_AppendNumberToItem(&plaintext, ss->sec.authKeyBits, 4); @@ -1308,28 +1312,13 @@ ssl3_SendNewSessionTicket(sslSocket *ss) if (rv != SECSuccess) goto loser; - /* certificate slot */ - PORT_Assert(ss->sec.serverCert->certType.authType == ss->sec.authType); - switch (ss->sec.authType) { -#ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: - /* Too many curves and we will need two bytes here. */ - PORT_Assert(ec_pastLastName < 256); - rv = ssl3_AppendNumberToItem(&plaintext, - ss->sec.serverCert->certType.u.namedCurve, 1); - break; -#endif - default: - rv = ssl3_AppendNumberToItem(&plaintext, 0, 1); - break; - } - if (rv != SECSuccess) goto loser; - /* master_secret */ rv = ssl3_AppendNumberToItem(&plaintext, ms_is_wrapped, 1); if (rv != SECSuccess) goto loser; + rv = ssl3_AppendNumberToItem(&plaintext, effectiveExchKeyType, 1); + if (rv != SECSuccess) + goto loser; rv = ssl3_AppendNumberToItem(&plaintext, msWrapMech, 4); if (rv != SECSuccess) goto loser; @@ -1420,7 +1409,6 @@ ssl3_SendNewSessionTicket(sslSocket *ss) } else #endif { - PORT_Assert(aes_key_pkcs11); aes_ctx_pkcs11 = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, aes_key_pkcs11, &ivItem); if (!aes_ctx_pkcs11) @@ -1442,8 +1430,6 @@ ssl3_SendNewSessionTicket(sslSocket *ss) /* Compute MAC. */ #ifndef NO_PKCS11_BYPASS if (ss->opt.bypassPKCS11) { - PORT_Assert(mac_key); - hmac_ctx = (HMACContext *)hmac_ctx_buf; hashObj = HASH_GetRawHashObject(HASH_AlgSHA256); if (HMAC_Init(hmac_ctx, hashObj, mac_key, @@ -1461,7 +1447,6 @@ ssl3_SendNewSessionTicket(sslSocket *ss) #endif { SECItem macParam; - PORT_Assert(mac_key_pkcs11); macParam.data = NULL; macParam.len = 0; hmac_ctx_pkcs11 = PK11_CreateContextBySymKey(macMech, @@ -1802,7 +1787,7 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data) temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; - parsed_session_ticket->authType = (SSLAuthType)temp; + parsed_session_ticket->authAlgorithm = (SSLSignType)temp; temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); if (temp < 0) goto no_ticket; @@ -1816,27 +1801,16 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data) goto no_ticket; parsed_session_ticket->keaKeyBits = (PRUint32)temp; - /* Read certificate slot */ - parsed_session_ticket->certType.authType = parsed_session_ticket->authType; + /* Read wrapped master_secret. */ temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; - switch (parsed_session_ticket->authType) { -#ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: - parsed_session_ticket->certType.u.namedCurve = (ECName)temp; - break; -#endif - default: - break; - } + parsed_session_ticket->ms_is_wrapped = (PRBool)temp; - /* Read wrapped master_secret. */ temp = ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len); if (temp < 0) goto no_ticket; - parsed_session_ticket->ms_is_wrapped = (PRBool)temp; + parsed_session_ticket->exchKeyType = (SSL3KEAType)temp; temp = ssl3_ConsumeHandshakeNumber(ss, 4, &buffer, &buffer_len); if (temp < 0) @@ -1933,18 +1907,15 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data) sid->version = parsed_session_ticket->ssl_version; sid->u.ssl3.cipherSuite = parsed_session_ticket->cipher_suite; sid->u.ssl3.compression = parsed_session_ticket->compression_method; - sid->authType = parsed_session_ticket->authType; + sid->authAlgorithm = parsed_session_ticket->authAlgorithm; sid->authKeyBits = parsed_session_ticket->authKeyBits; sid->keaType = parsed_session_ticket->keaType; sid->keaKeyBits = parsed_session_ticket->keaKeyBits; - memcpy(&sid->certType, &parsed_session_ticket->certType, - sizeof(sslServerCertType)); - - if (SECITEM_CopyItem(NULL, &sid->u.ssl3.locked.sessionTicket.ticket, - &extension_data) != SECSuccess) - goto no_ticket; + if (SECITEM_CopyItem(NULL, &sid->u.ssl3.locked.sessionTicket.ticket, + &extension_data) != SECSuccess) + goto no_ticket; - /* Copy master secret. */ + /* Copy master secret. */ #ifndef NO_PKCS11_BYPASS if (ss->opt.bypassPKCS11 && parsed_session_ticket->ms_is_wrapped) @@ -1958,6 +1929,7 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data) parsed_session_ticket->ms_length); sid->u.ssl3.keys.wrapped_master_secret_len = parsed_session_ticket->ms_length; + sid->u.ssl3.exchKeyType = parsed_session_ticket->exchKeyType; sid->u.ssl3.masterWrapMech = parsed_session_ticket->msWrapMech; sid->u.ssl3.keys.msIsWrapped = parsed_session_ticket->ms_is_wrapped; @@ -2989,7 +2961,17 @@ ssl3_ServerSendSignedCertTimestampXtn(sslSocket *ss, PRUint32 maxBytes) { PRInt32 extension_length; - const SECItem *scts = &ss->sec.serverCert->signedCertTimestamps; + SSLKEAType effectiveExchKeyType; + const SECItem *scts; + + if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa || + ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) { + effectiveExchKeyType = ssl_kea_rsa; + } else { + effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType; + } + + scts = &ss->signedCertTimestamps[effectiveExchKeyType]; if (!scts->len) { /* No timestamps to send */ @@ -3258,7 +3240,6 @@ tls13_ServerSendKeyShareXtn(sslSocket *ss, PRBool append, switch (ss->ssl3.hs.kea_def->exchKeyType) { #ifndef NSS_DISABLE_ECC case ssl_kea_ecdh: - case ssl_kea_ecdh_psk: PORT_Assert(ss->ephemeralECDHKeyPair); break; #endif diff --git a/lib/ssl/sslcert.c b/lib/ssl/sslcert.c deleted file mode 100644 index c4d869592..000000000 --- a/lib/ssl/sslcert.c +++ /dev/null @@ -1,877 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * SSL server certificate configuration functions. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ssl.h" -#include "sslimpl.h" -#include "secoid.h" /* for SECOID_GetAlgorithmTag */ -#include "pk11func.h" /* for PK11_ReferenceSlot */ -#include "nss.h" /* for NSS_RegisterShutdown */ -#include "prinit.h" /* for PR_CallOnceWithArg */ - -static const PRCallOnceType pristineCallOnce; -static PRCallOnceType setupServerCAListOnce; - -static SECStatus -serverCAListShutdown(void *appData, void *nssData) -{ - PORT_Assert(ssl3_server_ca_list); - if (ssl3_server_ca_list) { - CERT_FreeDistNames(ssl3_server_ca_list); - ssl3_server_ca_list = NULL; - } - setupServerCAListOnce = pristineCallOnce; - return SECSuccess; -} - -static PRStatus -serverCAListSetup(void *arg) -{ - CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg; - SECStatus rv = NSS_RegisterShutdown(serverCAListShutdown, NULL); - PORT_Assert(SECSuccess == rv); - if (SECSuccess == rv) { - ssl3_server_ca_list = CERT_GetSSLCACerts(dbHandle); - return PR_SUCCESS; - } - return PR_FAILURE; -} - -sslServerCert * -ssl_NewServerCert(const sslServerCertType *certType) -{ - sslServerCert *sc = PORT_ZNew(sslServerCert); - if (!sc) { - return NULL; - } - memcpy(&sc->certType, certType, sizeof(sc->certType)); - sc->serverCert = NULL; - sc->serverCertChain = NULL; - sc->certStatusArray = NULL; - sc->signedCertTimestamps.len = 0; - return sc; -} - -void -ssl_FreeServerCert(sslServerCert *sc) -{ - if (!sc) { - return; - } - - if (sc->serverCert) { - CERT_DestroyCertificate(sc->serverCert); - } - if (sc->serverCertChain) { - CERT_DestroyCertificateList(sc->serverCertChain); - } - if (sc->serverKeyPair) { - ssl3_FreeKeyPair(sc->serverKeyPair); - } - if (sc->certStatusArray) { - SECITEM_FreeArray(sc->certStatusArray, PR_TRUE); - } - if (sc->signedCertTimestamps.len) { - SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE); - } - PORT_ZFree(sc, sizeof(*sc)); -} - -sslServerCert * -ssl_FindServerCert(const sslSocket *ss, - const sslServerCertType *certType) -{ - PRCList *cursor; - - for (cursor = PR_NEXT_LINK(&ss->serverCerts); - cursor != &ss->serverCerts; - cursor = PR_NEXT_LINK(cursor)) { - sslServerCert *cert = (sslServerCert *)cursor; - if (cert->certType.authType == certType->authType) { - switch (cert->certType.authType) { -#ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: - /* Note: For deprecated APIs, we need to be able to find and - match a slot with any named curve. */ - if (certType->u.namedCurve == ec_noName || - cert->certType.u.namedCurve == certType->u.namedCurve) { - return cert; - } - break; -#endif - default: - return cert; - } - } - } - return NULL; -} - -sslServerCert * -ssl_FindServerCertByAuthType(const sslSocket *ss, SSLAuthType authType) -{ - sslServerCertType certType; - certType.authType = authType; - switch (authType) { -#ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: - /* Setting the named curve to ec_noName ensures that all EC certificates - * are matched when searching for this slot. */ - certType.u.namedCurve = ec_noName; - break; -#endif - default: - break; - } - return ssl_FindServerCert(ss, &certType); -} - -SECStatus -ssl_OneTimeCertSetup(sslSocket *ss, const sslServerCert *sc) -{ - /* Generate a step-down RSA key. */ - if (sc->certType.authType == ssl_auth_rsa_sign && sc->serverKeyBits > 512 && - !ss->opt.noStepDown && !ss->stepDownKeyPair) { - if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) { - return SECFailure; - } - } - - /* DH parameters are only needed for DHE_RSA_* and DHE_DSS_* suites. Make - * sure that they are properly setup here. */ - if (sc->certType.authType == ssl_auth_rsa_sign || - sc->certType.authType == ssl_auth_rsa_decrypt || - sc->certType.authType == ssl_auth_dsa) { - if (ssl3_SelectDHParams(ss) != SECSuccess) { - return SECFailure; - } - } - - if (PR_SUCCESS != PR_CallOnceWithArg(&setupServerCAListOnce, - &serverCAListSetup, - (void *)(ss->dbHandle))) { - return SECFailure; - } - return SECSuccess; -} - -static SECStatus -ssl_PopulateServerCert(sslServerCert *sc, CERTCertificate *cert, - const CERTCertificateList *certChain) -{ - if (sc->serverCert) { - CERT_DestroyCertificate(sc->serverCert); - } - if (sc->serverCertChain) { - CERT_DestroyCertificateList(sc->serverCertChain); - } - - if (!cert) { - sc->serverCert = NULL; - sc->serverCertChain = NULL; - return SECSuccess; - } - - sc->serverCert = CERT_DupCertificate(cert); - if (certChain) { - sc->serverCertChain = CERT_DupCertList(certChain); - } else { - sc->serverCertChain = - CERT_CertChainFromCert(sc->serverCert, certUsageSSLServer, - PR_TRUE); - } - return sc->serverCertChain ? SECSuccess : SECFailure; -} - -static SECStatus -ssl_PopulateKeyPair(sslServerCert *sc, ssl3KeyPair *keyPair) -{ - /* Copy over the key pair. */ - if (sc->serverKeyPair) { - ssl3_FreeKeyPair(sc->serverKeyPair); - } - if (keyPair) { - /* Get the size of the cert's public key, and remember it. */ - sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey); - if (sc->serverKeyBits == 0) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); /* zero bits! */ - return SECFailure; - } - - SECKEY_CacheStaticFlags(keyPair->privKey); - sc->serverKeyPair = ssl3_GetKeyPairRef(keyPair); - } else { - sc->serverKeyPair = NULL; - } - return SECSuccess; -} - -static SECStatus -ssl_PopulateOCSPResponses(sslServerCert *sc, - const SECItemArray *stapledOCSPResponses) -{ - if (sc->certStatusArray) { - SECITEM_FreeArray(sc->certStatusArray, PR_TRUE); - } - if (stapledOCSPResponses) { - sc->certStatusArray = SECITEM_DupArray(NULL, stapledOCSPResponses); - return sc->certStatusArray ? SECSuccess : SECFailure; - } else { - sc->certStatusArray = NULL; - } - return SECSuccess; -} - -static SECStatus -ssl_PopulateSignedCertTimestamps(sslServerCert *sc, - const SECItem *signedCertTimestamps) -{ - if (sc->signedCertTimestamps.len) { - SECITEM_FreeItem(&sc->signedCertTimestamps, PR_FALSE); - } - if (signedCertTimestamps) { - return SECITEM_CopyItem(NULL, &sc->signedCertTimestamps, - signedCertTimestamps); - } - return SECSuccess; -} - -static SECStatus -ssl_ConfigCert(sslSocket *ss, CERTCertificate *cert, - ssl3KeyPair *keyPair, const SSLExtraServerCertData *data) -{ - sslServerCert *oldsc; - sslServerCert *sc; - sslServerCertType certType; - SECStatus rv; - int error_code = SEC_ERROR_NO_MEMORY; - - PORT_Assert(cert); - PORT_Assert(keyPair); - PORT_Assert(data); - PORT_Assert(data->authType != ssl_auth_null); - - /* Determine which slot this falls into. A value for SSLAuthType is already - * set in |*data|, we just need to work out any extra information. */ - certType.authType = data->authType; - switch (data->authType) { -#ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: - certType.u.namedCurve = ssl3_PubKey2ECName(keyPair->pubKey); - break; -#endif - default: - break; - } - - /* Delete any existing certificate that matches this one, since we can only - * use one certificate of a given type. */ - oldsc = ssl_FindServerCert(ss, &certType); - if (oldsc) { - PR_REMOVE_LINK(&oldsc->link); - ssl_FreeServerCert(oldsc); - } - sc = ssl_NewServerCert(&certType); - if (!sc) { - goto loser; - } - - rv = ssl_PopulateServerCert(sc, cert, data->certChain); - if (rv != SECSuccess) { - goto loser; - } - rv = ssl_PopulateKeyPair(sc, keyPair); - if (rv != SECSuccess) { - goto loser; - } - rv = ssl_PopulateOCSPResponses(sc, data->stapledOCSPResponses); - if (rv != SECSuccess) { - goto loser; - } - rv = ssl_PopulateSignedCertTimestamps(sc, data->signedCertTimestamps); - if (rv != SECSuccess) { - goto loser; - } - PR_APPEND_LINK(&sc->link, &ss->serverCerts); - - /* This one-time setupdepends on having the certificate in place. */ - rv = ssl_OneTimeCertSetup(ss, sc); - if (rv != SECSuccess) { - PR_REMOVE_LINK(&sc->link); - error_code = PORT_GetError(); - goto loser; - } - return SECSuccess; - -loser: - if (sc) { - ssl_FreeServerCert(sc); - } - /* This is the only way any of the calls above can fail, except the one time - * setup, which doesn't land here. */ - PORT_SetError(error_code); - return SECFailure; -} - -/* This function examines the type of certificate and its key usage and - * configures a certificate based on that information. For RSA certificates - * only, this can mean that two certificates are configured. - * - * If the optional data argument is non-NULL and contains an authType value - * other than ssl_auth_null, then only that slot will be used. If that choice - * is invalid, then this will fail. */ -static SECStatus -ssl_ConfigCertByUsage(sslSocket *ss, CERTCertificate *cert, - ssl3KeyPair *keyPair, const SSLExtraServerCertData *data) -{ - SECStatus rv = SECFailure; - SSLExtraServerCertData arg = { - ssl_auth_null, NULL, NULL, NULL - }; - SECOidTag tag; - - if (data) { - /* Take a (shallow) copy so that we can play with it */ - memcpy(&arg, data, sizeof(arg)); - } - tag = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm); - switch (tag) { - case SEC_OID_X500_RSA_ENCRYPTION: - case SEC_OID_PKCS1_RSA_ENCRYPTION: - if (cert->keyUsage & KU_DIGITAL_SIGNATURE) { - if ((cert->keyUsage & KU_KEY_ENCIPHERMENT) && - arg.authType == ssl_auth_null) { - /* Two usages is bad form, but there are enough dual-usage RSA - * certs that we can't really break by limiting this to one. - * Configure both slots only if no explicit slot was set. */ - arg.authType = ssl_auth_rsa_decrypt; - rv = ssl_ConfigCert(ss, cert, keyPair, &arg); - if (rv != SECSuccess) { - return rv; - } - } - - arg.authType = ssl_auth_rsa_sign; - } else if (cert->keyUsage & KU_KEY_ENCIPHERMENT) { - arg.authType = ssl_auth_rsa_decrypt; - } - break; - - case SEC_OID_PKCS1_RSA_PSS_SIGNATURE: - if (cert->keyUsage & KU_DIGITAL_SIGNATURE) { - arg.authType = ssl_auth_rsa_pss; - } - break; - - case SEC_OID_ANSIX9_DSA_SIGNATURE: - if (cert->keyUsage & KU_DIGITAL_SIGNATURE) { - arg.authType = ssl_auth_dsa; - } - break; - -#ifndef NSS_DISABLE_ECC - case SEC_OID_ANSIX962_EC_PUBLIC_KEY: - /* Yes, this means that you can't do both ECDSA and ECDH, but that is a - * bad practice, and ECDH isn't used that much (if at all). */ - if (cert->keyUsage & KU_DIGITAL_SIGNATURE) { - arg.authType = ssl_auth_ecdsa; - } else if (cert->keyUsage & KU_KEY_AGREEMENT) { - arg.authType = ssl_auth_ecdh; - } - break; -#endif /* NSS_DISABLE_ECC */ - - default: - return SECFailure; - } - - /* Setting data->authType explicitly limits the usage. */ - if ((!data || data->authType == ssl_auth_null) && - arg.authType != ssl_auth_null) { - rv = ssl_ConfigCert(ss, cert, keyPair, &arg); - } - return rv; -} - -/* This function adopts pubKey and destroys it if things go wrong. */ -static ssl3KeyPair * -ssl_MakeKeyPairForCert(SECKEYPrivateKey *key, SECKEYPublicKey *pubKey) -{ - ssl3KeyPair *keyPair = NULL; - SECKEYPrivateKey *privKeyCopy = NULL; - PK11SlotInfo *bestSlot; - - if (key->pkcs11Slot) { - bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); - if (bestSlot) { - privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); - PK11_FreeSlot(bestSlot); - } - } - if (!privKeyCopy) { - CK_MECHANISM_TYPE keyMech = PK11_MapSignKeyType(key->keyType); - /* XXX Maybe should be bestSlotMultiple? */ - bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); - if (bestSlot) { - privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); - PK11_FreeSlot(bestSlot); - } - } - if (!privKeyCopy) { - privKeyCopy = SECKEY_CopyPrivateKey(key); - } - if (privKeyCopy) { - keyPair = ssl3_NewKeyPair(privKeyCopy, pubKey); - } - if (!keyPair) { - if (privKeyCopy) { - SECKEY_DestroyPrivateKey(privKeyCopy); - } - /* We adopted the public key, so we're responsible. */ - if (pubKey) { - SECKEY_DestroyPublicKey(pubKey); - } - } - return keyPair; -} - -/* Configure a certificate and private key. - * - * This function examines the certificate and key to determine which slot (or - * slots) to place the information in. As long as certificates are different - * (based on having different values of sslServerCertType), then this function - * can be called multiple times and the certificates will all be remembered. - */ -SECStatus -SSL_ConfigServerCert(PRFileDesc *fd, CERTCertificate *cert, - SECKEYPrivateKey *key, - const SSLExtraServerCertData *data, unsigned int data_len) -{ - sslSocket *ss; - SECKEYPublicKey *pubKey; - ssl3KeyPair *keyPair; - - ss = ssl_FindSocket(fd); - if (!ss) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - if (!cert || !key) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - if (data_len < sizeof(SSLExtraServerCertData)) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - pubKey = CERT_ExtractPublicKey(cert); - if (!pubKey) { - return SECFailure; - } - - keyPair = ssl_MakeKeyPairForCert(key, pubKey); - if (!keyPair) { - /* pubKey is adopted by ssl_MakeKeyPairForCert() */ - return SECFailure; - } - - return ssl_ConfigCertByUsage(ss, cert, keyPair, data); -} - -/*******************************************************************/ -/* Deprecated functions. - * - * The remainder of this file contains deprecated functions for server - * certificate configuration. These configure certificates incorrectly, but in - * a way that allows old code to continue working without change. All these - * functions create certificate slots based on SSLKEAType values. Some values - * of SSLKEAType cause multiple certificates to be configured. - */ - -SECStatus -SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert, - SECKEYPrivateKey *key, SSLKEAType kea) -{ - return SSL_ConfigSecureServerWithCertChain(fd, cert, NULL, key, kea); -} - -/* This implements a limited check that is consistent with the checks performed - * by older versions of NSS. This is less rigorous than the checks in - * ssl_ConfigCertByUsage(), only checking against the type of key and ignoring - * things like usage. */ -static PRBool -ssl_CertSuitableForAuthType(CERTCertificate *cert, SSLAuthType authType) -{ - SECOidTag tag = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm); - switch (authType) { - case ssl_auth_rsa_decrypt: - case ssl_auth_rsa_sign: - return tag == SEC_OID_X500_RSA_ENCRYPTION || - tag == SEC_OID_PKCS1_RSA_ENCRYPTION; - case ssl_auth_dsa: - return tag == SEC_OID_ANSIX9_DSA_SIGNATURE; - case ssl_auth_ecdsa: - case ssl_auth_ecdh: -#ifndef NSS_DISABLE_ECC - return tag == SEC_OID_ANSIX962_EC_PUBLIC_KEY; -#endif /* NSS_DISABLE_ECC */ - case ssl_auth_null: - case ssl_auth_kea: - case ssl_auth_rsa_pss: /* not supported with deprecated APIs */ - return PR_FALSE; - default: - PORT_Assert(0); - return PR_FALSE; - } -} - -/* This finds an existing server cert slot and unlinks it. */ -static sslServerCert * -ssl_FindOrMakeCertType(sslSocket *ss, SSLAuthType authType) -{ - sslServerCert *sc; - sslServerCertType certType; - - certType.authType = authType; - switch (authType) { -#ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: - /* Setting the named curve to ec_noName ensures that all EC certificates - * are matched when searching for this slot. */ - certType.u.namedCurve = ec_noName; - break; -#endif - default: - break; - } - sc = ssl_FindServerCert(ss, &certType); - if (sc) { - PR_REMOVE_LINK(&sc->link); - return sc; - } - - return ssl_NewServerCert(&certType); -} - -static void -ssl_RemoveCertAndKeyByAuthType(sslSocket *ss, SSLAuthType authType) -{ - sslServerCert *sc; - - sc = ssl_FindServerCertByAuthType(ss, authType); - if (sc) { - (void)ssl_PopulateServerCert(sc, NULL, NULL); - (void)ssl_PopulateKeyPair(sc, NULL); - /* Leave the entry linked here because the old API expects that. There - * might be OCSP stapling values or signed certificate timestamps still - * present that will subsequently be used. */ - /* For ECC certificates, also leave the namedCurve parameter on the slot - * unchanged; the value will be updated when a key is added. */ - } -} - -static SECStatus -ssl_AddCertAndKeyByAuthType(sslSocket *ss, SSLAuthType authType, - CERTCertificate *cert, - const CERTCertificateList *certChainOpt, - ssl3KeyPair *keyPair) -{ - sslServerCert *sc; - SECStatus rv; - - if (!ssl_CertSuitableForAuthType(cert, authType)) { - return SECFailure; - } - - sc = ssl_FindOrMakeCertType(ss, authType); - if (!sc) { - return SECFailure; - } - rv = ssl_PopulateKeyPair(sc, keyPair); - if (rv != SECSuccess) { - return SECFailure; - } - /* Now that we have a key pair, update the details of the slot. Many of the - * legacy functions create a slot with a namedCurve of ec_noName, which - * makes the slot unusable; this corrects that. */ - switch (sc->certType.authType) { -#ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: - sc->certType.u.namedCurve = ssl3_PubKey2ECName(keyPair->pubKey); - break; -#endif - default: - break; - } - rv = ssl_PopulateServerCert(sc, cert, certChainOpt); - if (rv == SECSuccess) { - PR_APPEND_LINK(&sc->link, &ss->serverCerts); - rv = ssl_OneTimeCertSetup(ss, sc); - } else { - ssl_FreeServerCert(sc); - } - return rv; -} - -static SECStatus -ssl_AddCertsByKEA(sslSocket *ss, CERTCertificate *cert, - const CERTCertificateList *certChainOpt, - SECKEYPrivateKey *key, SSLKEAType certType) -{ - SECKEYPublicKey *pubKey; - ssl3KeyPair *keyPair; - SECStatus rv; - - pubKey = CERT_ExtractPublicKey(cert); - if (!pubKey) { - return SECFailure; - } - - keyPair = ssl_MakeKeyPairForCert(key, pubKey); - if (!keyPair) { - /* Note: pubKey is adopted or freed by ssl_MakeKeyPairForCert() - * depending on whether it succeeds or not. */ - return SECFailure; - } - - switch (certType) { - case ssl_kea_rsa: - rv = ssl_AddCertAndKeyByAuthType(ss, ssl_auth_rsa_decrypt, - cert, certChainOpt, keyPair); - if (rv != SECSuccess) { - return SECFailure; - } - return ssl_AddCertAndKeyByAuthType(ss, ssl_auth_rsa_sign, - cert, certChainOpt, keyPair); - - case ssl_kea_dh: - return ssl_AddCertAndKeyByAuthType(ss, ssl_auth_dsa, - cert, certChainOpt, keyPair); - -#ifndef NSS_DISABLE_ECC - case ssl_kea_ecdh: - rv = ssl_AddCertAndKeyByAuthType(ss, ssl_auth_ecdsa, - cert, certChainOpt, keyPair); - if (rv != SECSuccess) { - return SECFailure; - } - return ssl_AddCertAndKeyByAuthType(ss, ssl_auth_ecdh, - cert, certChainOpt, keyPair); -#endif - - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } -} - -/* Public deprecated function */ -SECStatus -SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert, - const CERTCertificateList *certChainOpt, - SECKEYPrivateKey *key, SSLKEAType certType) -{ - sslSocket *ss; - - ss = ssl_FindSocket(fd); - if (!ss) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - if (!cert != !key) { /* Configure both, or neither */ - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - if (!cert) { - switch (certType) { - case ssl_kea_rsa: - ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_rsa_decrypt); - ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_rsa_sign); - break; - - case ssl_kea_dh: - ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_dsa); - break; - -#ifndef NSS_DISABLE_ECC - case ssl_kea_ecdh: - ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_ecdsa); - ssl_RemoveCertAndKeyByAuthType(ss, ssl_auth_ecdh); - break; -#endif - - default: - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - return SECSuccess; - } - - return ssl_AddCertsByKEA(ss, cert, certChainOpt, key, certType); -} - -static SECStatus -ssl_SetOCSPResponsesInSlot(sslSocket *ss, SSLAuthType authType, - const SECItemArray *responses) -{ - sslServerCert *sc; - SECStatus rv; - - sc = ssl_FindOrMakeCertType(ss, authType); - if (!sc) { - return SECFailure; - } - rv = ssl_PopulateOCSPResponses(sc, responses); - if (rv == SECSuccess) { - PR_APPEND_LINK(&sc->link, &ss->serverCerts); - } else { - ssl_FreeServerCert(sc); - } - return rv; -} - -/* Public deprecated function */ -SECStatus -SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses, - SSLKEAType certType) -{ - sslSocket *ss; - SECStatus rv; - - ss = ssl_FindSocket(fd); - if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetStapledOCSPResponses", - SSL_GETPID(), fd)); - return SECFailure; - } - - switch (certType) { - case ssl_kea_rsa: - rv = ssl_SetOCSPResponsesInSlot(ss, ssl_auth_rsa_decrypt, responses); - if (rv != SECSuccess) { - return SECFailure; - } - return ssl_SetOCSPResponsesInSlot(ss, ssl_auth_rsa_sign, responses); - - case ssl_kea_dh: - return ssl_SetOCSPResponsesInSlot(ss, ssl_auth_dsa, responses); - -#ifndef NSS_DISABLE_ECC - case ssl_kea_ecdh: - rv = ssl_SetOCSPResponsesInSlot(ss, ssl_auth_ecdsa, responses); - if (rv != SECSuccess) { - return SECFailure; - } - return ssl_SetOCSPResponsesInSlot(ss, ssl_auth_ecdh, responses); -#endif - - default: - SSL_DBG(("%d: SSL[%d]: invalid cert type in SSL_SetStapledOCSPResponses", - SSL_GETPID(), fd)); - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } -} - -static SECStatus -ssl_SetSignedTimestampsInSlot(sslSocket *ss, SSLAuthType authType, - const SECItem *scts) -{ - sslServerCert *sc; - SECStatus rv; - - sc = ssl_FindOrMakeCertType(ss, authType); - if (!sc) { - return SECFailure; - } - rv = ssl_PopulateSignedCertTimestamps(sc, scts); - if (rv == SECSuccess) { - PR_APPEND_LINK(&sc->link, &ss->serverCerts); - } else { - ssl_FreeServerCert(sc); - } - return rv; -} - -/* Public deprecated function */ -SECStatus -SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts, - SSLKEAType certType) -{ - sslSocket *ss; - SECStatus rv; - - ss = ssl_FindSocket(fd); - if (!ss) { - SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSignedCertTimestamps", - SSL_GETPID(), fd)); - return SECFailure; - } - - switch (certType) { - case ssl_kea_rsa: - rv = ssl_SetSignedTimestampsInSlot(ss, ssl_auth_rsa_decrypt, scts); - if (rv != SECSuccess) { - return SECFailure; - } - return ssl_SetSignedTimestampsInSlot(ss, ssl_auth_rsa_sign, scts); - - case ssl_kea_dh: - return ssl_SetSignedTimestampsInSlot(ss, ssl_auth_dsa, scts); - -#ifndef NSS_DISABLE_ECC - case ssl_kea_ecdh: - rv = ssl_SetSignedTimestampsInSlot(ss, ssl_auth_ecdsa, scts); - if (rv != SECSuccess) { - return SECFailure; - } - return ssl_SetSignedTimestampsInSlot(ss, ssl_auth_ecdh, scts); -#endif - - default: - SSL_DBG(("%d: SSL[%d]: invalid cert type in SSL_SetSignedCertTimestamps", - SSL_GETPID(), fd)); - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } -} - -/* Public deprecated function. */ -SSLKEAType -NSS_FindCertKEAType(CERTCertificate *cert) -{ - int tag; - - if (!cert) - return ssl_kea_null; - - tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm)); - switch (tag) { - case SEC_OID_X500_RSA_ENCRYPTION: - case SEC_OID_PKCS1_RSA_ENCRYPTION: - return ssl_kea_rsa; - case SEC_OID_ANSIX9_DSA_SIGNATURE: /* hah, signature, not a key? */ - case SEC_OID_X942_DIFFIE_HELMAN_KEY: - return ssl_kea_dh; -#ifndef NSS_DISABLE_ECC - case SEC_OID_ANSIX962_EC_PUBLIC_KEY: - return ssl_kea_ecdh; -#endif /* NSS_DISABLE_ECC */ - default: - return ssl_kea_null; - } -} diff --git a/lib/ssl/sslcert.h b/lib/ssl/sslcert.h deleted file mode 100644 index 95171e0cb..000000000 --- a/lib/ssl/sslcert.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is PRIVATE to SSL. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef __sslcert_h_ -#define __sslcert_h_ - -#include "cert.h" -#include "secitem.h" -#include "keyhi.h" - -/* The following struct identifies a single slot into which a certificate can be -** loaded. The authType field determines the basic slot, then additional -** parameters further narrow the slot. -** -** An EC key (ssl_auth_ecdh or ssl_auth_ecdsa) is assigned to a slot -** based on the named curve of the key. -*/ -typedef struct sslServerCertTypeStr { - SSLAuthType authType; - union { -#ifndef NSS_DISABLE_ECC - /* for ssl_auth_ecdh and ssl_auth_ecdsa: */ - ECName namedCurve; -#endif - } u; -} sslServerCertType; - -typedef struct sslServerCertStr { - PRCList link; /* The linked list link */ - - sslServerCertType certType; /* The certificate slot this occupies */ - - /* Configuration state for server sockets */ - CERTCertificate *serverCert; - CERTCertificateList *serverCertChain; - ssl3KeyPair *serverKeyPair; - unsigned int serverKeyBits; - /* Each certificate needs its own status. */ - SECItemArray *certStatusArray; - /* Serialized signed certificate timestamps to be sent to the client - ** in a TLS extension (server only). Each certificate needs its own - ** timestamps item. - */ - SECItem signedCertTimestamps; -} sslServerCert; - -extern sslServerCert *ssl_NewServerCert(const sslServerCertType *slot); -extern sslServerCert *ssl_FindServerCert(const sslSocket *ss, - const sslServerCertType *slot); -extern sslServerCert *ssl_FindServerCertByAuthType(const sslSocket *ss, - SSLAuthType authType); -extern void ssl_FreeServerCert(sslServerCert *sc); - -#endif /* __sslcert_h_ */ diff --git a/lib/ssl/sslcon.c b/lib/ssl/sslcon.c index 0c48c8f1f..c4c1a4c3e 100644 --- a/lib/ssl/sslcon.c +++ b/lib/ssl/sslcon.c @@ -1,5 +1,5 @@ /* - * Basic SSL handshake functions. + * SSL v2 handshake functions, and functions common to SSL2 and SSL3. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h index 6e783fb55..d456eba48 100644 --- a/lib/ssl/sslimpl.h +++ b/lib/ssl/sslimpl.h @@ -36,6 +36,7 @@ ** it was necessary to prepend ssl_ to the names. ** These #defines preserve compatibility with the old code here in libssl. */ +typedef SSLKEAType SSL3KEAType; typedef SSLMACAlgorithm SSL3MACAlgorithm; #define calg_null ssl_calg_null @@ -151,45 +152,6 @@ typedef enum { SSLAppOpRead = 0, /* Time to wait in FINISHED state for retransmissions. */ #define DTLS_RETRANSMIT_FINISHED_MS 30000 -#ifndef NSS_DISABLE_ECC -/* Types and names of elliptic curves used in TLS */ -typedef enum { - ec_type_explicitPrime = 1, - ec_type_explicitChar2Curve = 2, - ec_type_named -} ECType; - -typedef enum { - ec_noName = 0, - ec_sect163k1 = 1, - ec_sect163r1 = 2, - ec_sect163r2 = 3, - ec_sect193r1 = 4, - ec_sect193r2 = 5, - ec_sect233k1 = 6, - ec_sect233r1 = 7, - ec_sect239k1 = 8, - ec_sect283k1 = 9, - ec_sect283r1 = 10, - ec_sect409k1 = 11, - ec_sect409r1 = 12, - ec_sect571k1 = 13, - ec_sect571r1 = 14, - ec_secp160k1 = 15, - ec_secp160r1 = 16, - ec_secp160r2 = 17, - ec_secp192k1 = 18, - ec_secp192r1 = 19, - ec_secp224k1 = 20, - ec_secp224r1 = 21, - ec_secp256k1 = 22, - ec_secp256r1 = 23, - ec_secp384r1 = 24, - ec_secp521r1 = 25, - ec_pastLastName -} ECName; -#endif /* ndef NSS_DISABLE_ECC */ - typedef struct sslBufferStr sslBuffer; typedef struct sslConnectInfoStr sslConnectInfo; typedef struct sslGatherStr sslGather; @@ -370,6 +332,16 @@ typedef enum { sslHandshakingUndetermined = 0, sslHandshakingAsServer } sslHandshakingType; +typedef struct sslServerCertsStr { + /* Configuration state for server sockets */ + CERTCertificate *serverCert; + CERTCertificateList *serverCertChain; + ssl3KeyPair *serverKeyPair; + unsigned int serverKeyBits; +} sslServerCerts; + +#define SERVERKEY serverKeyPair->privKey + #define SSL_LOCK_RANK_SPEC 255 #define SSL_LOCK_RANK_GLOBAL NSS_RWLOCK_RANK_NONE @@ -605,8 +577,6 @@ typedef enum { never_cached, invalid_cache /* no longer in any cache. */ } Cached; -#include "sslcert.h" - struct sslSessionIDStr { /* The global cache lock must be held when accessing these members when the * sid is in any cache. @@ -624,7 +594,6 @@ struct sslSessionIDStr { SECItemArray peerCertStatus; /* client only */ const char *peerID; /* client only */ const char *urlSvrName; /* client only */ - sslServerCertType certType; CERTCertificate *localCert; PRIPv6Addr addr; @@ -635,7 +604,7 @@ struct sslSessionIDStr { PRUint32 creationTime; /* seconds since Jan 1, 1970 */ PRUint32 expirationTime; /* seconds since Jan 1, 1970 */ - SSLAuthType authType; + SSLSignType authAlgorithm; PRUint32 authKeyBits; SSLKEAType keaType; PRUint32 keaKeyBits; @@ -652,6 +621,9 @@ struct sslSessionIDStr { ssl3SidKeys keys; CK_MECHANISM_TYPE masterWrapMech; /* mechanism used to wrap master secret */ + SSL3KEAType exchKeyType; + /* key type used in exchange algorithm, + * and to wrap the sym wrapping key. */ #ifndef NSS_DISABLE_ECC PRUint32 negotiatedECCurves; #endif /* NSS_DISABLE_ECC */ @@ -724,15 +696,9 @@ typedef struct ssl3CipherSuiteDefStr { ** There are tables of these, all const. */ typedef struct { - /* An identifier for this struct. */ SSL3KeyExchangeAlgorithm kea; - /* The type of key exchange used by the cipher suite. */ - SSLKEAType exchKeyType; - /* If the cipher suite uses a signature, the type of signature. */ + SSL3KEAType exchKeyType; SSLSignType signKeyType; - /* In most cases, cipher suites depend on their signature type for - * authentication, ECDH certificates being the exception. */ - SSLAuthType authKeyType; /* For export cipher suites: * is_limited identifies a suite as having a limit on the key size. * key_size_limit provides the corresponding limit. */ @@ -1083,7 +1049,7 @@ typedef struct SSLWrappedSymWrappingKeyStr { CK_MECHANISM_TYPE asymWrapMechanism; /* mechanism used to wrap the SymmetricWrappingKey using * server's public and/or private keys. */ - SSLAuthType authType; /* type of keys used to wrap SymWrapKey*/ + SSL3KEAType exchKeyType; /* type of keys used to wrap SymWrapKey*/ PRInt32 symWrapMechIndex; PRUint16 wrappedSymKeyLen; } SSLWrappedSymWrappingKey; @@ -1093,15 +1059,16 @@ typedef struct SessionTicketStr { SSL3ProtocolVersion ssl_version; ssl3CipherSuite cipher_suite; SSLCompressionMethod compression_method; - SSLAuthType authType; + SSLSignType authAlgorithm; PRUint32 authKeyBits; SSLKEAType keaType; PRUint32 keaKeyBits; - sslServerCertType certType; /* - * msWrapMech contains a meaningful value only if ms_is_wrapped is true. + * exchKeyType and msWrapMech contain meaningful values only if + * ms_is_wrapped is true. */ PRUint8 ms_is_wrapped; + SSLKEAType exchKeyType; /* XXX(wtc): same as keaType above? */ CK_MECHANISM_TYPE msWrapMech; PRUint16 ms_length; SSL3Opaque master_secret[48]; @@ -1153,12 +1120,10 @@ struct sslSecurityInfoStr { CERTCertificate *peerCert; SECKEYPublicKey *peerKey; - SSLAuthType authType; + SSLSignType authAlgorithm; PRUint32 authKeyBits; SSLKEAType keaType; PRUint32 keaKeyBits; - /* The selected certificate (for servers only). */ - const sslServerCert *serverCert; /* ** Procs used for SID cache (nonce) management. @@ -1283,8 +1248,15 @@ struct sslSocketStr { sslBuffer pendingBuf; /*xmitBufLock*/ /* Configuration state for server sockets */ - /* One server cert and key for each authentication type. */ - PRCList /* <sslServerCert> */ serverCerts; + /* server cert and key for each KEA type */ + sslServerCerts serverCerts[kt_kea_size]; + /* each cert needs its own status */ + SECItemArray *certStatusArray[kt_kea_size]; + /* Serialized signed certificate timestamps to be sent to the client + ** in a TLS extension (server only). Each certificate needs its own + ** timestamps item. + */ + SECItem signedCertTimestamps[kt_kea_size]; ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED]; ssl3KeyPair *ephemeralECDHKeyPair; /* for ECDHE-* handshake */ @@ -1651,11 +1623,6 @@ extern SECStatus ssl3_DisableECCSuites(sslSocket *ss, const ssl3CipherSuite *suite); extern PRUint32 ssl3_GetSupportedECCurveMask(sslSocket *ss); -#define SSL_IS_CURVE_NEGOTIATED(curvemsk, curveName) \ - ((curveName > ec_noName) && \ - (curveName < ec_pastLastName) && \ - ((1UL << curveName) & curvemsk) != 0) - /* Macro for finding a curve equivalent in strength to RSA key's */ /* clang-format off */ #define SSL_RSASTRENGTH_TO_ECSTRENGTH(s) \ @@ -1666,6 +1633,41 @@ extern PRUint32 ssl3_GetSupportedECCurveMask(sslSocket *ss); : 521 ) ) ) ) /* clang-format on */ +/* Types and names of elliptic curves used in TLS */ +typedef enum { ec_type_explicitPrime = 1, + ec_type_explicitChar2Curve = 2, + ec_type_named +} ECType; + +typedef enum { ec_noName = 0, + ec_sect163k1 = 1, + ec_sect163r1 = 2, + ec_sect163r2 = 3, + ec_sect193r1 = 4, + ec_sect193r2 = 5, + ec_sect233k1 = 6, + ec_sect233r1 = 7, + ec_sect239k1 = 8, + ec_sect283k1 = 9, + ec_sect283r1 = 10, + ec_sect409k1 = 11, + ec_sect409r1 = 12, + ec_sect571k1 = 13, + ec_sect571r1 = 14, + ec_secp160k1 = 15, + ec_secp160r1 = 16, + ec_secp160r2 = 17, + ec_secp192k1 = 18, + ec_secp192r1 = 19, + ec_secp224k1 = 20, + ec_secp224r1 = 21, + ec_secp256k1 = 22, + ec_secp256r1 = 23, + ec_secp384r1 = 24, + ec_secp521r1 = 25, + ec_pastLastName +} ECName; + extern SECStatus ssl3_ECName2Params(PLArenaPool *arena, ECName curve, SECKEYECParams *params); ECName ssl3_PubKey2ECName(SECKEYPublicKey *pubKey); @@ -1753,9 +1755,9 @@ extern SECStatus ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, extern SECStatus ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert, SECItem *buf, PRBool isTLS, void *pwArg); -extern SECStatus ssl3_CacheWrappedMasterSecret( - sslSocket *ss, sslSessionID *sid, - ssl3CipherSpec *spec, SSLAuthType authType); +extern SECStatus ssl3_CacheWrappedMasterSecret(sslSocket *ss, + sslSessionID *sid, ssl3CipherSpec *spec, + SSL3KEAType effectiveExchKeyType); /* Functions that handle ClientHello and ServerHello extensions. */ extern SECStatus ssl3_HandleServerNameXtn(sslSocket *ss, @@ -1782,6 +1784,14 @@ extern PRInt32 ssl3_SendSessionTicketXtn(sslSocket *ss, PRBool append, extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes); +/* Assigns new cert, cert chain and keys to ss->serverCerts + * struct. If certChain is NULL, tries to find one. Aborts if + * fails to do so. If cert and keyPair are NULL - unconfigures + * sslSocket of kea type.*/ +extern SECStatus ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert, + const CERTCertificateList *certChain, + ssl3KeyPair *keyPair, SSLKEAType kea); + #ifndef NSS_DISABLE_ECC extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss, PRBool append, PRUint32 maxBytes); @@ -1809,7 +1819,7 @@ extern SECStatus ssl3_SessionTicketShutdown(void *appData, void *nssData); /* Tell clients to consider tickets valid for this long. */ #define TLS_EX_SESS_TICKET_LIFETIME_HINT (2 * 24 * 60 * 60) /* 2 days */ -#define TLS_EX_SESS_TICKET_VERSION (0x0102) +#define TLS_EX_SESS_TICKET_VERSION (0x0101) extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char *data, unsigned int length); @@ -1834,7 +1844,8 @@ extern void ssl3_FreeKeyPair(ssl3KeyPair *keyPair); /* calls for accessing wrapping keys across processes. */ extern PRBool -ssl_GetWrappingKey(PRInt32 symWrapMechIndex, SSLAuthType authType, +ssl_GetWrappingKey(PRInt32 symWrapMechIndex, + SSL3KEAType exchKeyType, SSLWrappedSymWrappingKey *wswk); /* The caller passes in the new value it wants @@ -1938,16 +1949,16 @@ PK11SymKey *tls13_ComputeECDHSharedKey(sslSocket *ss, SECStatus ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags); PK11SymKey *ssl3_GetWrappingKey(sslSocket *ss, PK11SlotInfo *masterSecretSlot, - const sslServerCert *serverCert, + SSL3KEAType exchKeyType, CK_MECHANISM_TYPE masterWrapMech, void *pwArg); PRInt32 tls13_ServerSendPreSharedKeyXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes); PRBool ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type); -SECStatus ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid); +SECStatus ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid, + SSL3KEAType effectiveExchKeyType); const ssl3CipherSuiteDef *ssl_LookupCipherSuiteDef(ssl3CipherSuite suite); -SECStatus ssl3_SelectServerCert(sslSocket *ss); /* Pull in TLS 1.3 functions */ #include "tls13con.h" diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c index dc88d371c..6a8fec144 100644 --- a/lib/ssl/sslinfo.c +++ b/lib/ssl/sslinfo.c @@ -134,37 +134,22 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd, return SECSuccess; } -/* name */ -#define CS_(x) x, #x -#define CS(x) CS_(TLS_##x) +#define CS(x) x, #x +#define CK(x) x | 0xff00, #x -/* legacy values for authAlgorithm */ #define S_DSA "DSA", ssl_auth_dsa -/* S_RSA is incorrect for signature-based suites */ -/* ECDH suites incorrectly report S_RSA or S_ECDSA */ -#define S_RSA "RSA", ssl_auth_rsa_decrypt +#define S_RSA "RSA", ssl_auth_rsa +#define S_KEA "KEA", ssl_auth_kea #define S_ECDSA "ECDSA", ssl_auth_ecdsa #define S_PSK "PSK", ssl_auth_psk -/* real authentication algorithm */ -#define A_DSA ssl_auth_dsa -#define A_RSAD ssl_auth_rsa_decrypt -#define A_RSAS ssl_auth_rsa_sign -#define A_ECDSA ssl_auth_ecdsa -#define A_ECDH ssl_auth_ecdh -/* Report ssl_auth_null for export suites that can't decide between - * ssl_auth_rsa_sign and ssl_auth_rsa_decrypt. */ -#define A_EXP ssl_auth_null - -/* key exchange */ -#define K_DHE "DHE", ssl_kea_dh -#define K_RSA "RSA", ssl_kea_rsa -#define K_KEA "KEA", ssl_kea_kea -#define K_ECDH "ECDH", ssl_kea_ecdh -#define K_ECDHE "ECDHE", ssl_kea_ecdh -#define K_ECDHE_PSK "ECDHE-PSK", ssl_kea_ecdh_psk - -/* record protection cipher */ +#define K_DHE "DHE", kt_dh +#define K_RSA "RSA", kt_rsa +#define K_KEA "KEA", kt_kea +#define K_ECDH "ECDH", kt_ecdh +#define K_ECDHE "ECDHE", kt_ecdh +#define K_ECDHE_PSK "ECDHE-PSK", kt_ecdh + #define C_SEED "SEED", calg_seed #define C_CAMELLIA "CAMELLIA", calg_camellia #define C_AES "AES", calg_aes @@ -177,7 +162,6 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd, #define C_AESGCM "AES-GCM", calg_aes_gcm #define C_CHACHA20 "CHACHA20POLY1305", calg_chacha20 -/* "block cipher" sizes */ #define B_256 256, 256, 256 #define B_128 128, 128, 128 #define B_3DES 192, 156, 112 @@ -187,104 +171,98 @@ SSL_GetPreliminaryChannelInfo(PRFileDesc *fd, #define B_40 128, 40, 40 #define B_0 0, 0, 0 -/* "mac algorithm" and size */ #define M_AEAD_128 "AEAD", ssl_mac_aead, 128 #define M_SHA256 "SHA256", ssl_hmac_sha256, 256 #define M_SHA "SHA1", ssl_mac_sha, 160 #define M_MD5 "MD5", ssl_mac_md5, 128 #define M_NULL "NULL", ssl_mac_null, 0 -/* flags */ -#define F_FIPS_STD 1, 0, 0, 0 -#define F_FIPS_NSTD 1, 0, 1, 0 -#define F_NFIPS_STD 0, 0, 0, 0 -#define F_NFIPS_NSTD 0, 0, 1, 0 /* i.e., trash */ -#define F_EXPORT 0, 1, 0, 0 /* i.e., trash */ - +/* clang-format off */ static const SSLCipherSuiteInfo suiteInfo[] = { /* <------ Cipher suite --------------------> <auth> <KEA> <bulk cipher> <MAC> <FIPS> */ - { 0, CS(RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAD }, - { 0, CS(DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_DHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS }, - - { 0, CS(DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_DSA }, - { 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_DSA }, - { 0, CS(DHE_DSS_WITH_AES_256_CBC_SHA256), S_DSA, K_DHE, C_AES, B_256, M_SHA256, F_FIPS_STD, A_DSA }, - { 0, CS(RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, F_NFIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, F_FIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAD }, - - { 0, CS(DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_DSA }, - { 0, CS(DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_DSA }, - { 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_AES_128_GCM_SHA256), S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_DSA }, - { 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_DSA }, - { 0, CS(DHE_DSS_WITH_AES_128_CBC_SHA256), S_DSA, K_DHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_DSA }, - { 0, CS(RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED, B_128, M_SHA, F_FIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, F_NFIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, F_NFIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAD }, - { 0, CS(RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAD }, - - { 0, CS(DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_DSA }, - { 0, CS_(SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES, B_3DES, M_SHA, F_FIPS_NSTD, A_RSAD }, - { 0, CS(RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAD }, - - { 0, CS(DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_DSA }, - { 0, CS_(SSL_RSA_FIPS_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_NFIPS_NSTD, A_RSAD }, - { 0, CS(RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_NFIPS_STD, A_RSAD }, - - { 0, CS(RSA_EXPORT1024_WITH_RC4_56_SHA), S_RSA, K_RSA, C_RC4, B_56, M_SHA, F_EXPORT, A_EXP }, - { 0, CS(RSA_EXPORT1024_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, F_EXPORT, A_EXP }, - { 0, CS(RSA_EXPORT_WITH_RC4_40_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, F_EXPORT, A_EXP }, - { 0, CS(RSA_EXPORT_WITH_RC2_CBC_40_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, F_EXPORT, A_EXP }, - { 0, CS(RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL, B_0, M_SHA256, F_EXPORT, A_RSAD }, - { 0, CS(RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL, B_0, M_SHA, F_EXPORT, A_RSAD }, - { 0, CS(RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL, B_0, M_MD5, F_EXPORT, A_RSAD }, + {0,CS(TLS_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_RSA, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 }, + {0,CS(TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_DHE, C_CHACHA20, B_256, M_AEAD_128, 0, 0, 0 }, + + {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_256, M_SHA, 0, 0, 0 }, + {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0 }, + {0,CS(TLS_DHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA), S_DSA, K_DHE, C_AES, B_256, M_SHA, 1, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256), S_DSA, K_DHE, C_AES, B_256, M_SHA256, 1, 0, 0 }, + {0,CS(TLS_RSA_WITH_CAMELLIA_256_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_256, M_SHA, 0, 0, 0 }, + {0,CS(TLS_RSA_WITH_AES_256_CBC_SHA256), S_RSA, K_RSA, C_AES, B_256, M_SHA256, 1, 0, 0 }, + {0,CS(TLS_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_RSA, C_AES, B_256, M_SHA, 1, 0, 0 }, + + {0,CS(TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA), S_DSA, K_DHE, C_CAMELLIA, B_128, M_SHA, 0, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_RC4_128_SHA), S_DSA, K_DHE, C_RC4, B_128, M_SHA, 0, 0, 0 }, + {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0 }, + {0,CS(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 }, + {0,CS(TLS_DHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256), S_DSA, K_DHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA), S_DSA, K_DHE, C_AES, B_128, M_SHA, 1, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256), S_DSA, K_DHE, C_AES, B_128, M_SHA256, 1, 0, 0 }, + {0,CS(TLS_RSA_WITH_SEED_CBC_SHA), S_RSA, K_RSA, C_SEED,B_128, M_SHA, 1, 0, 0 }, + {0,CS(TLS_RSA_WITH_CAMELLIA_128_CBC_SHA), S_RSA, K_RSA, C_CAMELLIA, B_128, M_SHA, 0, 0, 0 }, + {0,CS(TLS_RSA_WITH_RC4_128_SHA), S_RSA, K_RSA, C_RC4, B_128, M_SHA, 0, 0, 0 }, + {0,CS(TLS_RSA_WITH_RC4_128_MD5), S_RSA, K_RSA, C_RC4, B_128, M_MD5, 0, 0, 0 }, + {0,CS(TLS_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_RSA, C_AES, B_128, M_SHA256, 1, 0, 0 }, + {0,CS(TLS_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_RSA, C_AES, B_128, M_SHA, 1, 0, 0 }, + + {0,CS(TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA), S_DSA, K_DHE, C_3DES,B_3DES,M_SHA, 1, 0, 0 }, + {0,CS(SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 1 }, + {0,CS(TLS_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_RSA, C_3DES,B_3DES,M_SHA, 1, 0, 0 }, + + {0,CS(TLS_DHE_RSA_WITH_DES_CBC_SHA), S_RSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0 }, + {0,CS(TLS_DHE_DSS_WITH_DES_CBC_SHA), S_DSA, K_DHE, C_DES, B_DES, M_SHA, 0, 0, 0 }, + {0,CS(SSL_RSA_FIPS_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 1 }, + {0,CS(TLS_RSA_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 0, 0 }, + + {0,CS(TLS_RSA_EXPORT1024_WITH_RC4_56_SHA), S_RSA, K_RSA, C_RC4, B_56, M_SHA, 0, 1, 0 }, + {0,CS(TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA), S_RSA, K_RSA, C_DES, B_DES, M_SHA, 0, 1, 0 }, + {0,CS(TLS_RSA_EXPORT_WITH_RC4_40_MD5), S_RSA, K_RSA, C_RC4, B_40, M_MD5, 0, 1, 0 }, + {0,CS(TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5), S_RSA, K_RSA, C_RC2, B_40, M_MD5, 0, 1, 0 }, + {0,CS(TLS_RSA_WITH_NULL_SHA256), S_RSA, K_RSA, C_NULL,B_0, M_SHA256, 0, 1, 0 }, + {0,CS(TLS_RSA_WITH_NULL_SHA), S_RSA, K_RSA, C_NULL,B_0, M_SHA, 0, 1, 0 }, + {0,CS(TLS_RSA_WITH_NULL_MD5), S_RSA, K_RSA, C_NULL,B_0, M_MD5, 0, 1, 0 }, #ifndef NSS_DISABLE_ECC /* ECC cipher suites */ - { 0, CS(ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_PSK_WITH_AES_128_GCM_SHA256), S_PSK, K_ECDHE_PSK, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 }, - - { 0, CS(ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH }, - { 0, CS(ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH }, - { 0, CS(ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH }, - { 0, CS(ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH }, - { 0, CS(ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH }, - - { 0, CS(ECDHE_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDSA }, - { 0, CS(ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), S_ECDSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_ECDSA }, - - { 0, CS(ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_ECDH }, - { 0, CS(ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_ECDH }, - { 0, CS(ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_ECDH }, - { 0, CS(ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, F_FIPS_STD, A_ECDH }, - { 0, CS(ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, F_FIPS_STD, A_ECDH }, - - { 0, CS(ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, F_NFIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_256, M_SHA, F_FIPS_STD, A_RSAS }, - { 0, CS(ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, F_NFIPS_STD, A_RSAS }, + {0,CS(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), S_RSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 }, + {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), S_ECDSA, K_ECDHE, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 }, + {0,CS(TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256), S_PSK, K_ECDHE_PSK, C_AESGCM, B_128, M_AEAD_128, 1, 0, 0 }, + + {0,CS(TLS_ECDH_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0 }, + {0,CS(TLS_ECDH_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0 }, + {0,CS(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0 }, + + {0,CS(TLS_ECDHE_ECDSA_WITH_NULL_SHA), S_ECDSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0 }, + {0,CS(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA), S_ECDSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0 }, + {0,CS(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), S_ECDSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), S_ECDSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0 }, + {0,CS(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA), S_ECDSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), S_ECDSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, 0, 0, 0 }, + + {0,CS(TLS_ECDH_RSA_WITH_NULL_SHA), S_RSA, K_ECDH, C_NULL, B_0, M_SHA, 0, 0, 0 }, + {0,CS(TLS_ECDH_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDH, C_RC4, B_128, M_SHA, 0, 0, 0 }, + {0,CS(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDH, C_3DES, B_3DES, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDH, C_AES, B_128, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDH, C_AES, B_256, M_SHA, 1, 0, 0 }, + + {0,CS(TLS_ECDHE_RSA_WITH_NULL_SHA), S_RSA, K_ECDHE, C_NULL, B_0, M_SHA, 0, 0, 0 }, + {0,CS(TLS_ECDHE_RSA_WITH_RC4_128_SHA), S_RSA, K_ECDHE, C_RC4, B_128, M_SHA, 0, 0, 0 }, + {0,CS(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), S_RSA, K_ECDHE, C_3DES, B_3DES, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_128, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256), S_RSA, K_ECDHE, C_AES, B_128, M_SHA256, 1, 0, 0 }, + {0,CS(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), S_RSA, K_ECDHE, C_AES, B_256, M_SHA, 1, 0, 0 }, + {0,CS(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), S_RSA, K_ECDHE, C_CHACHA20, B_256, M_AEAD_128, 0, 0, 0 }, #endif /* NSS_DISABLE_ECC */ }; +/* clang-format on */ #define NUM_SUITEINFOS ((sizeof suiteInfo) / (sizeof suiteInfo[0])) diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c index 6c26c7e87..a3383f64e 100644 --- a/lib/ssl/sslsecur.c +++ b/lib/ssl/sslsecur.c @@ -623,6 +623,260 @@ done: /************************************************************************/ +/* +** Return SSLKEAType derived from cert's Public Key algorithm info. +*/ +SSLKEAType +NSS_FindCertKEAType(CERTCertificate *cert) +{ + SSLKEAType keaType = kt_null; + int tag; + + if (!cert) + goto loser; + + tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm)); + + switch (tag) { + case SEC_OID_X500_RSA_ENCRYPTION: + case SEC_OID_PKCS1_RSA_ENCRYPTION: + keaType = kt_rsa; + break; + case SEC_OID_ANSIX9_DSA_SIGNATURE: /* hah, signature, not a key? */ + case SEC_OID_X942_DIFFIE_HELMAN_KEY: + keaType = kt_dh; + break; +#ifndef NSS_DISABLE_ECC + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + keaType = kt_ecdh; + break; +#endif /* NSS_DISABLE_ECC */ + default: + keaType = kt_null; + } + +loser: + + return keaType; +} + +static const PRCallOnceType pristineCallOnce; +static PRCallOnceType setupServerCAListOnce; + +static SECStatus +serverCAListShutdown(void *appData, void *nssData) +{ + PORT_Assert(ssl3_server_ca_list); + if (ssl3_server_ca_list) { + CERT_FreeDistNames(ssl3_server_ca_list); + ssl3_server_ca_list = NULL; + } + setupServerCAListOnce = pristineCallOnce; + return SECSuccess; +} + +static PRStatus +serverCAListSetup(void *arg) +{ + CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg; + SECStatus rv = NSS_RegisterShutdown(serverCAListShutdown, NULL); + PORT_Assert(SECSuccess == rv); + if (SECSuccess == rv) { + ssl3_server_ca_list = CERT_GetSSLCACerts(dbHandle); + return PR_SUCCESS; + } + return PR_FAILURE; +} + +SECStatus +ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert, + const CERTCertificateList *certChain, + ssl3KeyPair *keyPair, SSLKEAType kea) +{ + CERTCertificateList *localCertChain = NULL; + sslServerCerts *sc = ss->serverCerts + kea; + + /* load the server certificate */ + if (sc->serverCert != NULL) { + CERT_DestroyCertificate(sc->serverCert); + sc->serverCert = NULL; + sc->serverKeyBits = 0; + } + /* load the server cert chain */ + if (sc->serverCertChain != NULL) { + CERT_DestroyCertificateList(sc->serverCertChain); + sc->serverCertChain = NULL; + } + if (cert) { + sc->serverCert = CERT_DupCertificate(cert); + /* get the size of the cert's public key, and remember it */ + sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey); + if (!certChain) { + localCertChain = + CERT_CertChainFromCert(sc->serverCert, certUsageSSLServer, + PR_TRUE); + if (!localCertChain) + goto loser; + } + sc->serverCertChain = (certChain) ? CERT_DupCertList(certChain) : + localCertChain; + if (!sc->serverCertChain) { + goto loser; + } + localCertChain = NULL; /* consumed */ + } + + /* get keyPair */ + if (sc->serverKeyPair != NULL) { + ssl3_FreeKeyPair(sc->serverKeyPair); + sc->serverKeyPair = NULL; + } + if (keyPair) { + SECKEY_CacheStaticFlags(keyPair->privKey); + sc->serverKeyPair = ssl3_GetKeyPairRef(keyPair); + } + if (kea == kt_rsa && cert && sc->serverKeyBits > 512 && + !ss->opt.noStepDown && !ss->stepDownKeyPair) { + if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) { + goto loser; + } + } + if (kea == ssl_kea_dh || kea == ssl_kea_rsa) { + if (ssl3_SelectDHParams(ss) != SECSuccess) { + goto loser; + } + } + return SECSuccess; + +loser: + if (localCertChain) { + CERT_DestroyCertificateList(localCertChain); + } + if (sc->serverCert != NULL) { + CERT_DestroyCertificate(sc->serverCert); + sc->serverCert = NULL; + } + if (sc->serverCertChain != NULL) { + CERT_DestroyCertificateList(sc->serverCertChain); + sc->serverCertChain = NULL; + } + if (sc->serverKeyPair != NULL) { + ssl3_FreeKeyPair(sc->serverKeyPair); + sc->serverKeyPair = NULL; + } + return SECFailure; +} + +/* XXX need to protect the data that gets changed here.!! */ + +SECStatus +SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert, + SECKEYPrivateKey *key, SSL3KEAType kea) +{ + + return SSL_ConfigSecureServerWithCertChain(fd, cert, NULL, key, kea); +} + +SECStatus +SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert, + const CERTCertificateList *certChainOpt, + SECKEYPrivateKey *key, SSL3KEAType kea) +{ + sslSocket *ss; + SECKEYPublicKey *pubKey = NULL; + ssl3KeyPair *keyPair = NULL; + SECStatus rv = SECFailure; + + ss = ssl_FindSocket(fd); + if (!ss) { + return SECFailure; + } + + /* Both key and cert must have a value or be NULL */ + /* Passing a value of NULL will turn off key exchange algorithms that were + * previously turned on */ + if (!cert != !key) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + + /* make sure the key exchange is recognized */ + if ((kea >= kt_kea_size) || (kea < kt_null)) { + PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); + return SECFailure; + } + + if (kea != NSS_FindCertKEAType(cert)) { + PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH); + return SECFailure; + } + + if (cert) { + /* get the size of the cert's public key, and remember it */ + pubKey = CERT_ExtractPublicKey(cert); + if (!pubKey) + return SECFailure; + } + + if (key) { + SECKEYPrivateKey *keyCopy = NULL; + CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM; + + if (key->pkcs11Slot) { + PK11SlotInfo *bestSlot; + bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); + if (bestSlot) { + keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); + PK11_FreeSlot(bestSlot); + } + } + if (keyCopy == NULL) + keyMech = PK11_MapSignKeyType(key->keyType); + if (keyMech != CKM_INVALID_MECHANISM) { + PK11SlotInfo *bestSlot; + /* XXX Maybe should be bestSlotMultiple? */ + bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); + if (bestSlot) { + keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); + PK11_FreeSlot(bestSlot); + } + } + if (keyCopy == NULL) + keyCopy = SECKEY_CopyPrivateKey(key); + if (keyCopy == NULL) + goto loser; + keyPair = ssl3_NewKeyPair(keyCopy, pubKey); + if (keyPair == NULL) { + SECKEY_DestroyPrivateKey(keyCopy); + goto loser; + } + pubKey = NULL; /* adopted by serverKeyPair */ + } + if (ssl_ConfigSecureServer(ss, cert, certChainOpt, + keyPair, kea) == SECFailure) { + goto loser; + } + + /* Only do this once because it's global. */ + if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce, + &serverCAListSetup, + (void *)(ss->dbHandle))) { + rv = SECSuccess; + } + +loser: + if (keyPair) { + ssl3_FreeKeyPair(keyPair); + } + if (pubKey) { + SECKEY_DestroyPublicKey(pubKey); + pubKey = NULL; + } + return rv; +} + +/************************************************************************/ + SECStatus ssl_CreateSecurityInfo(sslSocket *ss) { diff --git a/lib/ssl/sslsnce.c b/lib/ssl/sslsnce.c index 4de31867e..81c85328a 100644 --- a/lib/ssl/sslsnce.c +++ b/lib/ssl/sslsnce.c @@ -33,7 +33,7 @@ * sidCacheSet sidCacheSets[ numSIDCacheSets ]; * sidCacheEntry sidCacheData[ numSIDCacheEntries]; * certCacheEntry certCacheData[numCertCacheEntries]; - * SSLWrappedSymWrappingKey keyCacheData[ssl_auth_size][SSL_NUM_WRAP_MECHS]; + * SSLWrappedSymWrappingKey keyCacheData[kt_kea_size][SSL_NUM_WRAP_MECHS]; * PRUint8 keyNameSuffix[SESS_TICKET_KEY_VAR_NAME_LEN] * encKeyCacheEntry ticketEncKey; // Wrapped in non-bypass mode * encKeyCacheEntry ticketMacKey; // Wrapped in non-bypass mode @@ -98,7 +98,7 @@ struct sidCacheEntryStr { /* 1 */ PRUint8 valid; /* 1 */ PRUint8 sessionIDLength; /* 32 */ PRUint8 sessionID[SSL3_SESSIONID_BYTES]; - /* 2 */ PRUint16 authType; + /* 2 */ PRUint16 authAlgorithm; /* 2 */ PRUint16 authKeyBits; /* 2 */ PRUint16 keaType; /* 2 */ PRUint16 keaKeyBits; @@ -112,11 +112,11 @@ struct { /* 54 */ ssl3SidKeys keys; /* keys, wrapped as needed. */ /* 4 */ PRUint32 masterWrapMech; + /* 4 */ SSL3KEAType exchKeyType; /* 4 */ PRInt32 certIndex; /* 4 */ PRInt32 srvNameIndex; /* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */ - /* 2 */ PRUint16 certTypeArgs; -/*104 */} ssl3; +/*108 */} ssl3; /* force sizeof(sidCacheEntry) to be a multiple of cache line size */ struct { @@ -436,7 +436,7 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from) to->creationTime = from->creationTime; to->lastAccessTime = from->lastAccessTime; to->expirationTime = from->expirationTime; - to->authType = from->authType; + to->authAlgorithm = from->authAlgorithm; to->authKeyBits = from->authKeyBits; to->keaType = from->keaType; to->keaKeyBits = from->keaKeyBits; @@ -445,23 +445,12 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from) to->u.ssl3.compression = (PRUint16)from->u.ssl3.compression; to->u.ssl3.keys = from->u.ssl3.keys; to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech; + to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType; to->sessionIDLength = from->u.ssl3.sessionIDLength; to->u.ssl3.certIndex = -1; to->u.ssl3.srvNameIndex = -1; PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID, to->sessionIDLength); - to->u.ssl3.certTypeArgs = 0U; - switch(from->authType) { -#ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: - to->u.ssl3.certTypeArgs = (PRUint16)from->certType.u.namedCurve; - break; -#endif - default: - break; - } - SSL_TRC(8, ("%d: SSL3: ConvertSID: time=%d addr=0x%08x%08x%08x%08x " "cipherSuite=%d", @@ -492,6 +481,7 @@ ConvertToSID(sidCacheEntry *from, to->u.ssl3.compression = (SSLCompressionMethod)from->u.ssl3.compression; to->u.ssl3.keys = from->u.ssl3.keys; to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech; + to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType; if (from->u.ssl3.srvNameIndex != -1 && psnce) { SECItem name; SECStatus rv; @@ -536,17 +526,6 @@ ConvertToSID(sidCacheEntry *from, if (to->peerCert == NULL) goto loser; } - to->certType.authType = from->authType; - switch (from->authType) { -#ifndef NSS_DISABLE_ECC - case ssl_auth_ecdsa: - case ssl_auth_ecdh: - to->certType.u.namedCurve = (ECName)from->u.ssl3.certTypeArgs; - break; -#endif - default: - break; - } to->version = from->version; to->creationTime = from->creationTime; @@ -555,7 +534,7 @@ ConvertToSID(sidCacheEntry *from, to->cached = in_server_cache; to->addr = from->addr; to->references = 1; - to->authType = from->authType; + to->authAlgorithm = from->authAlgorithm; to->authKeyBits = from->authKeyBits; to->keaType = from->keaType; to->keaKeyBits = from->keaKeyBits; @@ -993,7 +972,7 @@ InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries, cache->certCacheSize = (char *)cache->keyCacheData - (char *)cache->certCacheData; - cache->numKeyCacheEntries = ssl_auth_size * SSL_NUM_WRAP_MECHS; + cache->numKeyCacheEntries = kt_kea_size * SSL_NUM_WRAP_MECHS; ptr = (ptrdiff_t)(cache->keyCacheData + cache->numKeyCacheEntries); ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT); @@ -1625,12 +1604,12 @@ StopLockPoller(cacheDesc *cache) */ static PRBool getSvrWrappingKey(PRInt32 symWrapMechIndex, - SSLAuthType authType, + SSL3KEAType exchKeyType, SSLWrappedSymWrappingKey *wswk, cacheDesc *cache, PRUint32 lockTime) { - PRUint32 ndx = (authType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex; + PRUint32 ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex; SSLWrappedSymWrappingKey *pwswk = cache->keyCacheData + ndx; PRUint32 now = 0; PRBool rv = PR_FALSE; @@ -1645,7 +1624,7 @@ getSvrWrappingKey(PRInt32 symWrapMechIndex, return rv; } } - if (pwswk->authType == authType && + if (pwswk->exchKeyType == exchKeyType && pwswk->symWrapMechIndex == symWrapMechIndex && pwswk->wrappedSymKeyLen != 0) { *wswk = *pwswk; @@ -1659,16 +1638,16 @@ getSvrWrappingKey(PRInt32 symWrapMechIndex, PRBool ssl_GetWrappingKey(PRInt32 symWrapMechIndex, - SSLAuthType authType, + SSL3KEAType exchKeyType, SSLWrappedSymWrappingKey *wswk) { PRBool rv; - PORT_Assert( (unsigned)authType < ssl_auth_size); - PORT_Assert( (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS); - if ((unsigned)authType < ssl_auth_size && + PORT_Assert((unsigned)exchKeyType < kt_kea_size); + PORT_Assert((unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS); + if ((unsigned)exchKeyType < kt_kea_size && (unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS) { - rv = getSvrWrappingKey(symWrapMechIndex, authType, wswk, + rv = getSvrWrappingKey(symWrapMechIndex, exchKeyType, wswk, &globalCache, 0); } else { rv = PR_FALSE; @@ -1949,7 +1928,7 @@ ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk) { cacheDesc *cache = &globalCache; PRBool rv = PR_FALSE; - SSLAuthType authType = wswk->authType; + SSL3KEAType exchKeyType = wswk->exchKeyType; /* type of keys used to wrap SymWrapKey*/ PRInt32 symWrapMechIndex = wswk->symWrapMechIndex; PRUint32 ndx; @@ -1961,20 +1940,20 @@ ssl_SetWrappingKey(SSLWrappedSymWrappingKey *wswk) return 0; } - PORT_Assert((unsigned)authType < ssl_auth_size); - if ((unsigned)authType >= ssl_auth_size) + PORT_Assert((unsigned)exchKeyType < kt_kea_size); + if ((unsigned)exchKeyType >= kt_kea_size) return 0; PORT_Assert((unsigned)symWrapMechIndex < SSL_NUM_WRAP_MECHS); if ((unsigned)symWrapMechIndex >= SSL_NUM_WRAP_MECHS) return 0; - ndx = (authType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex; + ndx = (exchKeyType * SSL_NUM_WRAP_MECHS) + symWrapMechIndex; PORT_Memset(&myWswk, 0, sizeof myWswk); /* eliminate UMRs. */ now = LockSidCacheLock(cache->keyCacheLock, now); if (now) { - rv = getSvrWrappingKey(wswk->symWrapMechIndex, wswk->authType, + rv = getSvrWrappingKey(wswk->symWrapMechIndex, wswk->exchKeyType, &myWswk, cache, now); if (rv) { /* we found it on disk, copy it out to the caller. */ @@ -2024,7 +2003,7 @@ SSL_InheritMPServerSIDCache(const char *envString) PRBool ssl_GetWrappingKey(PRInt32 symWrapMechIndex, - SSLAuthType authType, + SSL3KEAType exchKeyType, SSLWrappedSymWrappingKey *wswk) { PRBool rv = PR_FALSE; diff --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c index 72ea901b3..6ad8e5d97 100644 --- a/lib/ssl/sslsock.c +++ b/lib/ssl/sslsock.c @@ -212,7 +212,6 @@ ssl_DupSocket(sslSocket *os) { sslSocket *ss; SECStatus rv; - sslServerCert *sc = NULL; ss = ssl_NewSocket((PRBool)(!os->opt.noLocks), os->protocolVariant); if (ss) { @@ -255,13 +254,14 @@ ssl_DupSocket(sslSocket *os) } if (ss->opt.useSecurity) { - PRCList *cursor; - for (cursor = PR_NEXT_LINK(&os->serverCerts); - cursor != &os->serverCerts; - cursor = PR_NEXT_LINK(cursor)) { - sslServerCert *oc = (sslServerCert*)cursor; - sc = ssl_NewServerCert(&oc->certType); + /* This int should be SSLKEAType, but CC on Irix complains, + * during the for loop. + */ + int i; + sslServerCerts *oc = os->serverCerts; + sslServerCerts *sc = ss->serverCerts; + for (i = kt_null; i < kt_kea_size; i++, oc++, sc++) { if (oc->serverCert && oc->serverCertChain) { sc->serverCert = CERT_DupCertificate(oc->serverCert); sc->serverCertChain = CERT_DupCertList(oc->serverCertChain); @@ -271,26 +271,16 @@ ssl_DupSocket(sslSocket *os) sc->serverCert = NULL; sc->serverCertChain = NULL; } - sc->serverKeyPair = oc->serverKeyPair ? - ssl3_GetKeyPairRef(oc->serverKeyPair) : NULL; + sc->serverKeyPair = oc->serverKeyPair ? ssl3_GetKeyPairRef(oc->serverKeyPair) + : NULL; if (oc->serverKeyPair && !sc->serverKeyPair) goto loser; sc->serverKeyBits = oc->serverKeyBits; - sc->certStatusArray = !oc->certStatusArray ? NULL : - SECITEM_DupArray(NULL, oc->certStatusArray); - if (SECITEM_CopyItem(NULL, &sc->signedCertTimestamps, - &oc->signedCertTimestamps) != SECSuccess) - goto loser; - PR_APPEND_LINK(&sc->link, &ss->serverCerts); + ss->certStatusArray[i] = !os->certStatusArray[i] ? NULL : SECITEM_DupArray(NULL, os->certStatusArray[i]); } - sc = NULL; - - ss->stepDownKeyPair = !os->stepDownKeyPair ? NULL : - ssl3_GetKeyPairRef(os->stepDownKeyPair); - ss->ephemeralECDHKeyPair = !os->ephemeralECDHKeyPair ? NULL : - ssl3_GetKeyPairRef(os->ephemeralECDHKeyPair); - ss->dheKeyPair = !os->dheKeyPair ? NULL : - ssl3_GetKeyPairRef(os->dheKeyPair); + ss->stepDownKeyPair = !os->stepDownKeyPair ? NULL : ssl3_GetKeyPairRef(os->stepDownKeyPair); + ss->ephemeralECDHKeyPair = !os->ephemeralECDHKeyPair ? NULL : ssl3_GetKeyPairRef(os->ephemeralECDHKeyPair); + ss->dheKeyPair = !os->dheKeyPair ? NULL : ssl3_GetKeyPairRef(os->dheKeyPair); ss->dheParams = os->dheParams; /* @@ -322,7 +312,6 @@ ssl_DupSocket(sslSocket *os) loser: ssl_FreeSocket(ss); - ssl_FreeServerCert(sc); return NULL; } @@ -365,7 +354,10 @@ ssl_DestroyLocks(sslSocket *ss) static void ssl_DestroySocketContents(sslSocket *ss) { - PRCList *cursor; + /* "i" should be of type SSLKEAType, but CC on IRIX complains during + * the for loop. + */ + int i; /* Free up socket */ ssl_DestroySecurityInfo(&ss->sec); @@ -381,11 +373,22 @@ ssl_DestroySocketContents(sslSocket *ss) if (ss->url != NULL) PORT_Free((void *)ss->url); /* CONST */ - /* Clean up server certificates and sundries. */ - while (!PR_CLIST_IS_EMPTY(&ss->serverCerts)) { - cursor = PR_LIST_TAIL(&ss->serverCerts); - PR_REMOVE_LINK(cursor); - ssl_FreeServerCert((sslServerCert *)cursor); + /* Clean up server configuration */ + for (i = kt_null; i < kt_kea_size; i++) { + sslServerCerts *sc = ss->serverCerts + i; + if (sc->serverCert != NULL) + CERT_DestroyCertificate(sc->serverCert); + if (sc->serverCertChain != NULL) + CERT_DestroyCertificateList(sc->serverCertChain); + if (sc->serverKeyPair != NULL) + ssl3_FreeKeyPair(sc->serverKeyPair); + if (ss->certStatusArray[i] != NULL) { + SECITEM_FreeArray(ss->certStatusArray[i], PR_TRUE); + ss->certStatusArray[i] = NULL; + } + if (ss->signedCertTimestamps[i].data) { + SECITEM_FreeItem(&ss->signedCertTimestamps[i], PR_FALSE); + } } if (ss->stepDownKeyPair) { ssl3_FreeKeyPair(ss->stepDownKeyPair); @@ -1896,8 +1899,9 @@ PRFileDesc * SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) { sslSocket *sm = NULL, *ss = NULL; - PRCList *cursor; - sslServerCert *sc = NULL; + int i; + sslServerCerts *mc = NULL; + sslServerCerts *sc = NULL; if (model == NULL) { PR_SetError(SEC_ERROR_INVALID_ARGS, 0); @@ -1932,44 +1936,52 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } - while (!PR_CLIST_IS_EMPTY(&ss->serverCerts)) { - cursor = PR_LIST_TAIL(&ss->serverCerts); - PR_REMOVE_LINK(cursor); - ssl_FreeServerCert((sslServerCert *)cursor); - } - for (cursor = PR_NEXT_LINK(&sm->serverCerts); - cursor != &sm->serverCerts; - cursor = PR_NEXT_LINK(cursor)) { - sslServerCert *mc = (sslServerCert*)cursor; - - sc = ssl_NewServerCert(&mc->certType); + /* This int should be SSLKEAType, but CC on Irix complains, + * during the for loop. + */ + for (i = kt_null; i < kt_kea_size; i++) { + mc = &(sm->serverCerts[i]); + sc = &(ss->serverCerts[i]); if (mc->serverCert && mc->serverCertChain) { - sc->serverCert = CERT_DupCertificate(mc->serverCert); + if (sc->serverCert) { + CERT_DestroyCertificate(sc->serverCert); + } + sc->serverCert = CERT_DupCertificate(mc->serverCert); + if (sc->serverCertChain) { + CERT_DestroyCertificateList(sc->serverCertChain); + } sc->serverCertChain = CERT_DupCertList(mc->serverCertChain); if (!sc->serverCertChain) goto loser; - if (mc->certStatusArray) { - sc->certStatusArray = SECITEM_DupArray(NULL, mc->certStatusArray); - if (!sc->certStatusArray) + if (sm->certStatusArray[i]) { + if (ss->certStatusArray[i]) { + SECITEM_FreeArray(ss->certStatusArray[i], PR_TRUE); + ss->certStatusArray[i] = NULL; + } + ss->certStatusArray[i] = SECITEM_DupArray(NULL, sm->certStatusArray[i]); + if (!ss->certStatusArray[i]) goto loser; } - if (mc->signedCertTimestamps.data) { + if (sm->signedCertTimestamps[i].data) { + if (ss->signedCertTimestamps[i].data) { + SECITEM_FreeItem(&ss->signedCertTimestamps[i], PR_FALSE); + } if (SECITEM_CopyItem(NULL, - &sc->signedCertTimestamps, - &mc->signedCertTimestamps) != + &ss->signedCertTimestamps[i], + &sm->signedCertTimestamps[i]) != SECSuccess) { goto loser; } } } if (mc->serverKeyPair) { + if (sc->serverKeyPair) { + ssl3_FreeKeyPair(sc->serverKeyPair); + } sc->serverKeyPair = ssl3_GetKeyPairRef(mc->serverKeyPair); sc->serverKeyBits = mc->serverKeyBits; } - PR_APPEND_LINK(&sc->link, &ss->serverCerts); } - sc = NULL; - if (sm->stepDownKeyPair) { if (ss->stepDownKeyPair) { ssl3_FreeKeyPair(ss->stepDownKeyPair); @@ -2018,7 +2030,6 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd) ss->pkcs11PinArg = sm->pkcs11PinArg; return fd; loser: - ssl_FreeServerCert(sc); return NULL; } @@ -2674,6 +2685,64 @@ ssl_GetSockName(PRFileDesc *fd, PRNetAddr *name) } SECStatus +SSL_SetStapledOCSPResponses(PRFileDesc *fd, const SECItemArray *responses, + SSLKEAType kea) +{ + sslSocket *ss; + + ss = ssl_FindSocket(fd); + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetStapledOCSPResponses", + SSL_GETPID(), fd)); + return SECFailure; + } + + if (kea <= 0 || kea >= kt_kea_size) { + SSL_DBG(("%d: SSL[%d]: invalid key type in SSL_SetStapledOCSPResponses", + SSL_GETPID(), fd)); + return SECFailure; + } + + if (ss->certStatusArray[kea]) { + SECITEM_FreeArray(ss->certStatusArray[kea], PR_TRUE); + ss->certStatusArray[kea] = NULL; + } + if (responses) { + ss->certStatusArray[kea] = SECITEM_DupArray(NULL, responses); + } + return (ss->certStatusArray[kea] || !responses) ? SECSuccess : SECFailure; +} + +SECStatus +SSL_SetSignedCertTimestamps(PRFileDesc *fd, const SECItem *scts, SSLKEAType kea) +{ + sslSocket *ss; + + ss = ssl_FindSocket(fd); + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetSignedCertTimestamps", + SSL_GETPID(), fd)); + return SECFailure; + } + + if (kea <= 0 || kea >= kt_kea_size) { + SSL_DBG(("%d: SSL[%d]: invalid key type in SSL_SetSignedCertTimestamps", + SSL_GETPID(), fd)); + return SECFailure; + } + + if (ss->signedCertTimestamps[kea].data) { + SECITEM_FreeItem(&ss->signedCertTimestamps[kea], PR_FALSE); + } + + if (!scts) { + return SECSuccess; + } + + return SECITEM_CopyItem(NULL, &ss->signedCertTimestamps[kea], scts); +} + +SECStatus SSL_SetSockPeerID(PRFileDesc *fd, const char *peerID) { sslSocket *ss; @@ -3364,9 +3433,10 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant) /* Make a new socket and get it ready */ ss = (sslSocket *)PORT_ZAlloc(sizeof(sslSocket)); if (ss) { - /* This should be of type SSLAuthType, but CC on IRIX + /* This should be of type SSLKEAType, but CC on IRIX * complains during the for loop. */ + int i; SECStatus status; ss->opt = ssl_defaults; @@ -3381,7 +3451,14 @@ ssl_NewSocket(PRBool makeLocks, SSLProtocolVariant protocolVariant) ss->cTimeout = PR_INTERVAL_NO_TIMEOUT; ss->url = NULL; - PR_INIT_CLIST(&ss->serverCerts); + for (i = kt_null; i < kt_kea_size; i++) { + sslServerCerts *sc = ss->serverCerts + i; + sc->serverCert = NULL; + sc->serverCertChain = NULL; + sc->serverKeyPair = NULL; + sc->serverKeyBits = 0; + ss->certStatusArray[i] = NULL; + } ss->stepDownKeyPair = NULL; ss->dheParams = NULL; diff --git a/lib/ssl/sslt.h b/lib/ssl/sslt.h index cb7883739..098ce88e5 100644 --- a/lib/ssl/sslt.h +++ b/lib/ssl/sslt.h @@ -10,8 +10,6 @@ #define __sslt_h_ #include "prtypes.h" -#include "secitem.h" -#include "certt.h" typedef struct SSL3StatisticsStr { /* statistics from ssl3_SendClientHello (sch) */ @@ -43,7 +41,6 @@ typedef enum { ssl_kea_dh = 2, ssl_kea_fortezza = 3, /* deprecated, now unused */ ssl_kea_ecdh = 4, - ssl_kea_ecdh_psk = 5, ssl_kea_size /* number of ssl_kea_ algorithms */ } SSLKEAType; @@ -65,7 +62,8 @@ typedef enum { ssl_sign_null = 0, /* "anonymous" in TLS */ ssl_sign_rsa = 1, ssl_sign_dsa = 2, - ssl_sign_ecdsa = 3 + ssl_sign_ecdsa = 3, + ssl_sign_psk = 4 } SSLSignType; /* Values of this enum match the HashAlgorithm enum from @@ -87,26 +85,15 @@ typedef struct SSLSignatureAndHashAlgStr { SSLSignType sigAlg; } SSLSignatureAndHashAlg; -/* -** SSLAuthType describes the type of key that is used to authenticate a -** connection. That is, the type of key in the end-entity certificate. -*/ typedef enum { ssl_auth_null = 0, - ssl_auth_rsa_decrypt = 1, /* static RSA */ + ssl_auth_rsa = 1, ssl_auth_dsa = 2, - ssl_auth_kea = 3, /* unused */ + ssl_auth_kea = 3, ssl_auth_ecdsa = 4, - ssl_auth_ecdh = 5, - ssl_auth_rsa_sign = 6, /* RSA PKCS#1.5 signing */ - ssl_auth_rsa_pss = 7, - ssl_auth_psk = 8, - ssl_auth_size /* number of authentication types */ + ssl_auth_psk = 5 /* Used for both PSK and (EC)DHE-PSK */ } SSLAuthType; -/* This is defined for backward compatibility reasons */ -#define ssl_auth_rsa ssl_auth_rsa_sign - typedef enum { ssl_calg_null = 0, ssl_calg_rc4 = 1, @@ -137,22 +124,6 @@ typedef enum { ssl_compression_deflate = 1 /* RFC 3749 */ } SSLCompressionMethod; -typedef struct SSLExtraServerCertDataStr { - /* When this struct is passed to SSL_ConfigServerCert, and authType is set - * to a value other than ssl_auth_null, this limits the use of the key to - * the type defined; otherwise, the certificate is configured for all - * compatible types. */ - SSLAuthType authType; - /* The remainder of the certificate chain. */ - const CERTCertificateList *certChain; - /* A set of one or more stapled OCSP responses for the certificate. This is - * used to generate the OCSP stapling answer provided by the server. */ - const SECItemArray *stapledOCSPResponses; - /* A serialized sign_certificate_timestamp extension, used to answer - * requests from clients for this data. */ - const SECItem *signedCertTimestamps; -} SSLExtraServerCertData; - typedef struct SSLChannelInfoStr { /* |length| is obsolete. On return, SSL_GetChannelInfo sets |length| to the * smaller of the |len| argument and the length of the struct. The caller @@ -218,7 +189,7 @@ typedef struct SSLCipherSuiteInfoStr { /* server authentication info */ const char* authAlgorithmName; - SSLAuthType authAlgorithm; /* deprecated, use |authType| */ + SSLAuthType authAlgorithm; /* key exchange algorithm info */ const char* keaTypeName; @@ -244,10 +215,6 @@ typedef struct SSLCipherSuiteInfoStr { PRUintn nonStandard : 1; PRUintn reservedBits : 29; - /* This reports the correct authentication type for the cipher suite, use - * this instead of |authAlgorithm|. */ - SSLAuthType authType; - } SSLCipherSuiteInfo; typedef enum { diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c index 0548503b6..af6efa6a5 100644 --- a/lib/ssl/tls13con.c +++ b/lib/ssl/tls13con.c @@ -357,11 +357,8 @@ tls13_RecoverWrappedSharedSecret(sslSocket *ss, sslSessionID *sid) /* If we are the server, we compute the wrapping key, but if we * are the client, it's coordinates are stored with the ticket. */ if (ss->sec.isServer) { - const sslServerCert *serverCert; - - serverCert = ssl_FindServerCert(ss, &sid->certType); - PORT_Assert(serverCert); - wrapKey = ssl3_GetWrappingKey(ss, NULL, serverCert, + wrapKey = ssl3_GetWrappingKey(ss, NULL, + sid->u.ssl3.exchKeyType, sid->u.ssl3.masterWrapMech, ss->pkcs11PinArg); } else { @@ -411,10 +408,10 @@ tls13_RestoreCipherInfo(sslSocket *ss, sslSessionID *sid) * TODO(ekr@rtfm.com): Make a version with the "true" values. * Bug 1256137. */ - ss->sec.authType = sid->authType; - ss->sec.authKeyBits = sid->authKeyBits; - ss->sec.keaType = sid->keaType; - ss->sec.keaKeyBits = sid->keaKeyBits; + ss->sec.authAlgorithm = sid->authAlgorithm; + ss->sec.authKeyBits = sid->authKeyBits; + ss->sec.keaType = sid->keaType; + ss->sec.keaKeyBits = sid->keaKeyBits; ss->ssl3.hs.origCipherSuite = sid->u.ssl3.cipherSuite; } @@ -460,25 +457,6 @@ tls13_AllowPskCipher(const sslSocket *ss, const ssl3CipherSuiteDef *cipher_def) return PR_TRUE; } -/* Check whether resumption-PSK is allowed. */ -static PRBool -tls13_CanResume(sslSocket *ss, const sslSessionID *sid) -{ - if (sid->version != ss->version) { - return PR_FALSE; - } - - /* Server sids don't remember the server cert we previously sent, but they - * do remember the type of certificate we originally used, so we can locate - * it again, provided that the current ssl socket has had its server certs - * configured the same as the previous one. */ - if (!ssl_FindServerCert(ss, &sid->certType)) { - return PR_FALSE; - } - - return PR_TRUE; -} - /* Called from ssl3_HandleClientHello after we have parsed the * ClientHello and are sure that we are going to do TLS 1.3 * or fail. */ @@ -496,14 +474,25 @@ tls13_HandleClientHelloPart2(sslSocket *ss, FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error); return SECFailure; } - if (sid != NULL && !tls13_CanResume(ss, sid)) { - /* Destroy SID if it is present an unusable. */ - SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_not_ok); - if (ss->sec.uncache) - ss->sec.uncache(sid); - ssl_FreeSID(sid); - sid = NULL; - ss->statelessResume = PR_FALSE; + /* Sanity check whether resumption-PSK is allowed. */ + if (sid != NULL) { + PRBool resumeOK = PR_FALSE; + + do { + if (sid->version != ss->version) { + break; + } + resumeOK = PR_TRUE; + } while(0); + + if (!resumeOK) { + SSL_AtomicIncrementLong(& ssl3stats->hch_sid_cache_not_ok); + if (ss->sec.uncache) + ss->sec.uncache(sid); + ssl_FreeSID(sid); + sid = NULL; + ss->statelessResume = PR_FALSE; + } } #ifndef PARANOID @@ -521,7 +510,8 @@ tls13_HandleClientHelloPart2(sslSocket *ss, goto loser; } - if (ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) { + /* TODO(ekr@rtfm.com): Update this when we have pure PSK. */ + if (ss->ssl3.hs.suite_def->key_exchange_alg != kea_ecdhe_psk) { /* TODO(ekr@rtfm.com): Free resumeSID. */ ss->statelessResume = PR_FALSE; } @@ -535,15 +525,20 @@ tls13_HandleClientHelloPart2(sslSocket *ss, goto loser; } - SSL_AtomicIncrementLong(&ssl3stats->hch_sid_cache_hits); - SSL_AtomicIncrementLong(&ssl3stats->hch_sid_stateless_resumes); + SSL_AtomicIncrementLong(& ssl3stats->hch_sid_cache_hits); + SSL_AtomicIncrementLong(& ssl3stats->hch_sid_stateless_resumes); ss->ssl3.hs.isResuming = PR_TRUE; tls13_RestoreCipherInfo(ss, sid); - ss->sec.serverCert = ssl_FindServerCert(ss, &sid->certType); - PORT_Assert(ss->sec.serverCert); - ss->sec.localCert = CERT_DupCertificate(ss->sec.serverCert->serverCert); + /* server sids don't remember the server cert we previously sent, + ** but they do remember the kea type we originally used, so we + ** can locate it again, provided that the current ssl socket + ** has had its server certs configured the same as the previous one. + */ + ss->sec.localCert = + CERT_DupCertificate(ss->serverCerts[sid->keaType].serverCert); + if (sid->peerCert != NULL) { ss->sec.peerCert = CERT_DupCertificate(sid->peerCert); } @@ -586,22 +581,6 @@ tls13_HandleClientHelloPart2(sslSocket *ss, } } -<<<<<<< dest -======= - if (!ss->statelessResume) { - rv = ssl3_SelectServerCert(ss); - if (rv != SECSuccess) { - goto loser; - } - } - - rv = ssl3_SetupPendingCipherSpec(ss); - if (rv != SECSuccess) { - FATAL_ERROR(ss, PORT_GetError(), internal_error); - goto loser; - } - ->>>>>>> source /* If this is TLS 1.3 we are expecting a ClientKeyShare * extension. Missing/absent extension cause failure * below. */ @@ -656,7 +635,6 @@ tls13_HandleClientKeyShare(sslSocket *ss) switch (ss->ssl3.hs.kea_def->exchKeyType) { #ifndef NSS_DISABLE_ECC case ssl_kea_ecdh: - case ssl_kea_ecdh_psk: expectedGroup = ssl3_GetCurveNameForServerSocket(ss); if (!expectedGroup) { FATAL_ERROR(ss, SSL_ERROR_NO_CYPHER_OVERLAP, @@ -882,7 +860,7 @@ tls13_InitializeHandshakeEncryption(sslSocket *ss) SECStatus rv; PORT_Assert(!!ss->ssl3.hs.xSS == - (ss->ssl3.hs.kea_def->authKeyType == ssl_auth_psk)); + (ss->ssl3.hs.kea_def->signKeyType == ssl_sign_psk)); if (!ss->ssl3.hs.xSS) { ss->ssl3.hs.xSS = PK11_ReferenceSymKey(ss->ssl3.hs.xES); if (!ss->ssl3.hs.xSS) { @@ -909,7 +887,7 @@ SECStatus tls13_SendServerHelloSequence(sslSocket *ss) { SECStatus rv; - SECKEYPrivateKey *svrPrivKey; + SSL3KEAType certIndex; SSL_TRC(3, ("%d: TLS13[%d]: begin send server_hello sequence", SSL_GETPID(), ss->fd)); @@ -938,7 +916,7 @@ tls13_SendServerHelloSequence(sslSocket *ss) return SECFailure; /* error code is set. */ } } - if (ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) { + if (ss->ssl3.hs.kea_def->signKeyType != ssl_sign_psk) { rv = ssl3_SendCertificate(ss); if (rv != SECSuccess) { return SECFailure; /* error code is set. */ @@ -948,13 +926,22 @@ tls13_SendServerHelloSequence(sslSocket *ss) return SECFailure; /* error code is set. */ } - svrPrivKey = ss->sec.serverCert->serverKeyPair->privKey; - rv = ssl3_SendCertificateVerify(ss, svrPrivKey); + /* This was copied from: ssl3_SendCertificate. + * TODO(ekr@rtfm.com): Verify that this selection logic is correct. + * Bug 1237514. + */ + if ((ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) || + (ss->ssl3.hs.kea_def->kea == kea_dhe_rsa)) { + certIndex = kt_rsa; + } else { + certIndex = ss->ssl3.hs.kea_def->exchKeyType; + } + rv = ssl3_SendCertificateVerify(ss, + ss->serverCerts[certIndex].SERVERKEY); if (rv != SECSuccess) { return rv; /* err code is set. */ } } - /* Compute the rest of the secrets except for the resumption * and exporter secret. */ rv = tls13_ComputeSecrets1(ss); @@ -999,7 +986,7 @@ tls13_HandleServerHelloPart2(sslSocket *ss) if (isPSK) { PRBool cacheOK = PR_FALSE; do { - if (ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) { + if (ss->ssl3.hs.kea_def->signKeyType != ssl_sign_psk) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, illegal_parameter); break; @@ -1025,7 +1012,7 @@ tls13_HandleServerHelloPart2(sslSocket *ss) SSL_AtomicIncrementLong(&ssl3stats->hsh_sid_stateless_resumes); } else { /* No PSK negotiated.*/ - if (ss->ssl3.hs.kea_def->authKeyType == ssl_auth_psk) { + if (ss->ssl3.hs.kea_def->signKeyType == ssl_sign_psk) { FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, illegal_parameter); return SECFailure; @@ -1096,7 +1083,6 @@ tls13_HandleServerKeyShare(sslSocket *ss) switch (ss->ssl3.hs.kea_def->exchKeyType) { #ifndef NSS_DISABLE_ECC case ssl_kea_ecdh: - case ssl_kea_ecdh_psk: expectedGroup = ssl3_PubKey2ECName(ss->ephemeralECDHKeyPair->pubKey); break; #endif /* NSS_DISABLE_ECC */ @@ -1912,7 +1898,7 @@ tls13_HandleEncryptedExtensions(sslSocket *ss, SSL3Opaque *b, PRUint32 length) PORT_Assert(!ss->sec.isServer); - if (ss->ssl3.hs.kea_def->authKeyType == ssl_auth_psk) { + if (ss->ssl3.hs.kea_def->signKeyType == ssl_sign_psk) { /* Compute the rest of the secrets except for the resumption * and exporter secret. */ rv = tls13_ComputeSecrets1(ss); @@ -2237,7 +2223,7 @@ tls13_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length, } ssl_GetXmitBufLock(ss); if (ss->opt.enableSessionTickets && - ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) { + ss->ssl3.hs.kea_def->signKeyType != ssl_sign_psk) { /* TODO(ekr@rtfm.com): Add support for new tickets in PSK. */ rv = ssl3_SendNewSessionTicket(ss); if (rv != SECSuccess) { @@ -2408,7 +2394,8 @@ tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) * server side supports it. Bug 1257047. */ if (!ss->opt.noCache && ss->sec.cache && - ss->ssl3.hs.kea_def->authKeyType != ssl_auth_psk) { + ss->ssl3.hs.kea_def->signKeyType != ssl_sign_psk) { + SSL3KEAType effectiveExchKeyType; /* Uncache so that we replace. */ (*ss->sec.uncache)(ss->sec.ci.sid); @@ -2425,7 +2412,14 @@ tls13_HandleNewSessionTicket(sslSocket *ss, SSL3Opaque *b, PRUint32 length) ssl3_SetSIDSessionTicket(ss->sec.ci.sid, &ticket); PORT_Assert(!ticket.ticket.data); - rv = ssl3_FillInCachedSID(ss, ss->sec.ci.sid); + if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa || + ss->ssl3.hs.kea_def->kea == kea_dhe_rsa) { + effectiveExchKeyType = kt_rsa; + } else { + effectiveExchKeyType = ss->ssl3.hs.kea_def->exchKeyType; + } + + rv = ssl3_FillInCachedSID(ss, ss->sec.ci.sid, effectiveExchKeyType); if (rv != SECSuccess) return SECFailure; |