summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKai Engert <kaie@kuix.de>2016-04-06 18:07:39 +0200
committerKai Engert <kaie@kuix.de>2016-04-06 18:07:39 +0200
commite4b2a164b2414542c430611ce4e0fe52c3b76d6b (patch)
tree5b0625068f774be7a1dfd937881050d8d48bc355
parent85ef0c4c1b77fae164df8ba8853b7adc6b5e17ba (diff)
downloadnss-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.c5
-rw-r--r--external_tests/ssl_gtest/ssl_loopback_unittest.cc67
-rw-r--r--external_tests/ssl_gtest/tls_agent.cc44
-rw-r--r--external_tests/ssl_gtest/tls_agent.h3
-rw-r--r--external_tests/ssl_gtest/tls_connect.cc30
-rw-r--r--external_tests/ssl_gtest/tls_connect.h4
-rw-r--r--lib/ssl/SSLerrs.h2
-rw-r--r--lib/ssl/manifest.mn1
-rw-r--r--lib/ssl/ssl.def1
-rw-r--r--lib/ssl/ssl.h69
-rw-r--r--lib/ssl/ssl3con.c555
-rw-r--r--lib/ssl/ssl3ecc.c139
-rw-r--r--lib/ssl/ssl3ext.c123
-rw-r--r--lib/ssl/sslcert.c877
-rw-r--r--lib/ssl/sslcert.h59
-rw-r--r--lib/ssl/sslcon.c2
-rw-r--r--lib/ssl/sslimpl.h155
-rw-r--r--lib/ssl/sslinfo.c202
-rw-r--r--lib/ssl/sslsecur.c254
-rw-r--r--lib/ssl/sslsnce.c67
-rw-r--r--lib/ssl/sslsock.c189
-rw-r--r--lib/ssl/sslt.h45
-rw-r--r--lib/ssl/tls13con.c138
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;