Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Bug 1325035 - Streamline session ticket key wrapping, r=ttaubert
Differential Revision: https://nss-review.dev.mozaws.net/D127

--HG--
extra : rebase_source : 8efefb1f37dd327397d259c342e60223bd9bed9b
extra : amend_source : bdae9423ae41ed762c18718715425646a5ad0ec2
extra : histedit_source : 2d211aa721bc82eae4a1fb1895e1b2529899c3ae%2C640dfe56df26288f8ba8608dd24d277396d839bb
  • Loading branch information
martinthomson committed Jan 25, 2017
1 parent b41c93d commit a3d3f69
Show file tree
Hide file tree
Showing 16 changed files with 1,008 additions and 924 deletions.
7 changes: 2 additions & 5 deletions gtests/ssl_gtest/libssl_internals.c
Expand Up @@ -62,10 +62,7 @@ PRBool SSLInt_ExtensionNegotiated(PRFileDesc *fd, PRUint16 ext) {
return (PRBool)(ss && ssl3_ExtensionNegotiated(ss, ext));
}

void SSLInt_ClearSessionTicketKey() {
ssl3_SessionTicketShutdown(NULL, NULL);
NSS_UnregisterShutdown(ssl3_SessionTicketShutdown, NULL);
}
void SSLInt_ClearSessionTicketKey() { ssl_ResetSessionTicketKeys(); }

SECStatus SSLInt_SetMTU(PRFileDesc *fd, PRUint16 mtu) {
sslSocket *ss = ssl_FindSocket(fd);
Expand Down Expand Up @@ -209,7 +206,7 @@ PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType) {
return PR_FALSE;
}

return (PRBool)(!!ssl_FindServerCertByAuthType(ss, authType));
return (PRBool)(!!ssl_FindServerCert(ss, authType, NULL));
}

PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type) {
Expand Down
29 changes: 19 additions & 10 deletions gtests/ssl_gtest/ssl_cert_ext_unittest.cc
Expand Up @@ -62,10 +62,22 @@ static const uint8_t kSctValue[] = {0x01, 0x23, 0x45, 0x67, 0x89};
static const SECItem kSctItem = {siBuffer, const_cast<uint8_t*>(kSctValue),
sizeof(kSctValue)};
static const DataBuffer kSctBuffer(kSctValue, sizeof(kSctValue));
static const SSLExtraServerCertData kExtraSctData = {ssl_auth_null, nullptr,
nullptr, &kSctItem};

// Test timestamps extraction during a successful handshake.
TEST_P(TlsConnectGeneric, SignedCertificateTimestampsHandshake) {
TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsLegacy) {
EnsureTlsSetup();

// We have to use the legacy API consistently here for configuring certs.
// Also, this doesn't work in TLS 1.3 because this only configures the SCT for
// RSA decrypt and PKCS#1 signing, not PSS.
ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey priv;
ASSERT_TRUE(TlsAgent::LoadCertificate(TlsAgent::kServerRsa, &cert, &priv));
EXPECT_EQ(SECSuccess, SSL_ConfigSecureServerWithCertChain(
server_->ssl_fd(), cert.get(), nullptr, priv.get(),
ssl_kea_rsa));
EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(),
&kSctItem, ssl_kea_rsa));
EXPECT_EQ(SECSuccess,
Expand All @@ -78,13 +90,10 @@ TEST_P(TlsConnectGeneric, SignedCertificateTimestampsHandshake) {
timestamps_extractor.assertTimestamps(kSctBuffer);
}

TEST_P(TlsConnectGeneric, SignedCertificateTimestampsConfig) {
static const SSLExtraServerCertData kExtraData = {ssl_auth_rsa_sign, nullptr,
nullptr, &kSctItem};

TEST_P(TlsConnectGeneric, SignedCertificateTimestampsSuccess) {
EnsureTlsSetup();
EXPECT_TRUE(
server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraData));
server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraSctData));
EXPECT_EQ(SECSuccess,
SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
PR_TRUE));
Expand All @@ -99,8 +108,8 @@ TEST_P(TlsConnectGeneric, SignedCertificateTimestampsConfig) {
// when the client / the server / both have not enabled the feature.
TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveClient) {
EnsureTlsSetup();
EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(),
&kSctItem, ssl_kea_rsa));
EXPECT_TRUE(
server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraSctData));
SignedCertificateTimestampsExtractor timestamps_extractor(client_);

Connect();
Expand Down Expand Up @@ -141,8 +150,8 @@ static const SECItem kOcspItems[] = {
{siBuffer, const_cast<uint8_t*>(kOcspValue2), sizeof(kOcspValue2)}};
static const SECItemArray kOcspResponses = {const_cast<SECItem*>(kOcspItems),
PR_ARRAY_SIZE(kOcspItems)};
const static SSLExtraServerCertData kOcspExtraData = {
ssl_auth_rsa_sign, nullptr, &kOcspResponses, nullptr};
const static SSLExtraServerCertData kOcspExtraData = {ssl_auth_null, nullptr,
&kOcspResponses, nullptr};

TEST_P(TlsConnectGeneric, NoOcsp) {
EnsureTlsSetup();
Expand Down
20 changes: 13 additions & 7 deletions gtests/ssl_gtest/ssl_ciphersuite_unittest.cc
Expand Up @@ -128,16 +128,22 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
Connect();
SendReceive();

// Check that we used the right cipher suite.
// Check that we used the right cipher suite, auth type and kea type.
uint16_t actual;
EXPECT_TRUE(client_->cipher_suite(&actual) && actual == cipher_suite_);
EXPECT_TRUE(server_->cipher_suite(&actual) && actual == cipher_suite_);
EXPECT_TRUE(client_->cipher_suite(&actual));
EXPECT_EQ(cipher_suite_, actual);
EXPECT_TRUE(server_->cipher_suite(&actual));
EXPECT_EQ(cipher_suite_, actual);
SSLAuthType auth;
EXPECT_TRUE(client_->auth_type(&auth) && auth == auth_type_);
EXPECT_TRUE(server_->auth_type(&auth) && auth == auth_type_);
EXPECT_TRUE(client_->auth_type(&auth));
EXPECT_EQ(auth_type_, auth);
EXPECT_TRUE(server_->auth_type(&auth));
EXPECT_EQ(auth_type_, auth);
SSLKEAType kea;
EXPECT_TRUE(client_->kea_type(&kea) && kea == kea_type_);
EXPECT_TRUE(server_->kea_type(&kea) && kea == kea_type_);
EXPECT_TRUE(client_->kea_type(&kea));
EXPECT_EQ(kea_type_, kea);
EXPECT_TRUE(server_->kea_type(&kea));
EXPECT_EQ(kea_type_, kea);
}

// Get the expected limit on the number of records that can be sent for the
Expand Down
61 changes: 33 additions & 28 deletions gtests/ssl_gtest/tls_agent.cc
Expand Up @@ -102,23 +102,35 @@ void TlsAgent::SetState(State state) {
state_ = state;
}

/*static*/ bool TlsAgent::LoadCertificate(const std::string& name,
ScopedCERTCertificate* cert,
ScopedSECKEYPrivateKey* priv) {
cert->reset(PK11_FindCertFromNickname(name.c_str(), nullptr));
EXPECT_NE(nullptr, cert->get());
if (!cert->get()) return false;

priv->reset(PK11_FindKeyByAnyCert(cert->get(), nullptr));
EXPECT_NE(nullptr, priv->get());
if (!priv->get()) return false;

return true;
}

bool TlsAgent::ConfigServerCert(const std::string& name, bool updateKeyBits,
const SSLExtraServerCertData* serverCertData) {
ScopedCERTCertificate cert(PK11_FindCertFromNickname(name.c_str(), nullptr));
EXPECT_NE(nullptr, cert.get());
if (!cert.get()) return false;
ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey priv;
if (!TlsAgent::LoadCertificate(name, &cert, &priv)) {
return false;
}

ScopedSECKEYPublicKey pub(CERT_ExtractPublicKey(cert.get()));
EXPECT_NE(nullptr, pub.get());
if (!pub.get()) return false;
if (updateKeyBits) {
ScopedSECKEYPublicKey pub(CERT_ExtractPublicKey(cert.get()));
EXPECT_NE(nullptr, pub.get());
if (!pub.get()) return false;
server_key_bits_ = SECKEY_PublicKeyStrengthInBits(pub.get());
}

ScopedSECKEYPrivateKey priv(PK11_FindKeyByAnyCert(cert.get(), nullptr));
EXPECT_NE(nullptr, priv.get());
if (!priv.get()) return false;

SECStatus rv =
SSL_ConfigSecureServer(ssl_fd_, nullptr, nullptr, ssl_kea_null);
EXPECT_EQ(SECFailure, rv);
Expand Down Expand Up @@ -181,30 +193,23 @@ void TlsAgent::SetupClientAuth() {
reinterpret_cast<void*>(this)));
}

bool TlsAgent::GetClientAuthCredentials(CERTCertificate** cert,
SECKEYPrivateKey** priv) const {
*cert = PK11_FindCertFromNickname(name_.c_str(), nullptr);
EXPECT_NE(nullptr, *cert);
if (!*cert) return false;

*priv = PK11_FindKeyByAnyCert(*cert, nullptr);
EXPECT_NE(nullptr, *priv);
if (!*priv) return false; // Leak cert.

return true;
}

SECStatus TlsAgent::GetClientAuthDataHook(void* self, PRFileDesc* fd,
CERTDistNames* caNames,
CERTCertificate** cert,
SECKEYPrivateKey** privKey) {
CERTCertificate** clientCert,
SECKEYPrivateKey** clientKey) {
TlsAgent* agent = reinterpret_cast<TlsAgent*>(self);
ScopedCERTCertificate peerCert(SSL_PeerCertificate(agent->ssl_fd()));
EXPECT_TRUE(peerCert) << "Client should be able to see the server cert";
if (agent->GetClientAuthCredentials(cert, privKey)) {
return SECSuccess;

ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey priv;
if (!TlsAgent::LoadCertificate(agent->name(), &cert, &priv)) {
return SECFailure;
}
return SECFailure;

*clientCert = cert.release();
*clientKey = priv.release();
return SECSuccess;
}

bool TlsAgent::GetPeerChainLength(size_t* count) {
Expand Down
6 changes: 4 additions & 2 deletions gtests/ssl_gtest/tls_agent.h
Expand Up @@ -18,6 +18,7 @@

#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "scoped_ptrs.h"

extern bool g_ssl_gtest_verbose;

Expand Down Expand Up @@ -115,15 +116,16 @@ class TlsAgent : public PollTarget {
void PrepareForRenegotiate();
// Prepares for renegotiation, then actually triggers it.
void StartRenegotiate();
static bool LoadCertificate(const std::string& name,
ScopedCERTCertificate* cert,
ScopedSECKEYPrivateKey* priv);
bool ConfigServerCert(const std::string& name, bool updateKeyBits = false,
const SSLExtraServerCertData* serverCertData = nullptr);
bool ConfigServerCertWithChain(const std::string& name);
bool EnsureTlsSetup(PRFileDesc* modelSocket = nullptr);

void SetupClientAuth();
void RequestClientAuth(bool requireAuth);
bool GetClientAuthCredentials(CERTCertificate** cert,
SECKEYPrivateKey** priv) const;

void ConfigureSessionCache(SessionResumptionMode mode);
void SetSessionTicketsEnabled(bool en);
Expand Down
23 changes: 19 additions & 4 deletions gtests/ssl_gtest/tls_connect.cc
Expand Up @@ -13,6 +13,7 @@ extern "C" {

#include "databuffer.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "sslproto.h"

extern std::string g_working_dir_path;
Expand Down Expand Up @@ -345,6 +346,13 @@ void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type,
scheme = ssl_sig_none;
break;
case ssl_auth_rsa_sign:
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_2) {
scheme = ssl_sig_rsa_pss_sha256;
} else {
scheme = ssl_sig_rsa_pkcs1_sha256;
}
break;
case ssl_auth_rsa_pss:
scheme = ssl_sig_rsa_pss_sha256;
break;
case ssl_auth_ecdsa:
Expand Down Expand Up @@ -390,6 +398,7 @@ void TlsConnectTestBase::ConnectExpectFailOneSide(TlsAgent::Role failing_side) {
}

void TlsConnectTestBase::ConfigureVersion(uint16_t version) {
version_ = version;
client_->SetVersionRange(version, version);
server_->SetVersionRange(version, version);
}
Expand Down Expand Up @@ -440,10 +449,16 @@ void TlsConnectTestBase::ConfigureSessionCache(SessionResumptionMode client,
client_->ConfigureSessionCache(client);
server_->ConfigureSessionCache(server);
if ((server & RESUME_TICKET) != 0) {
// This is an abomination. NSS encrypts session tickets with the server's
// RSA public key. That means we need the server to have an RSA certificate
// even if it won't be used for the connection.
server_->ConfigServerCert(TlsAgent::kServerRsaDecrypt);
ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey privKey;
ASSERT_TRUE(TlsAgent::LoadCertificate(TlsAgent::kServerRsaDecrypt, &cert,
&privKey));

ScopedSECKEYPublicKey pubKey(CERT_ExtractPublicKey(cert.get()));
ASSERT_TRUE(pubKey);

EXPECT_EQ(SECSuccess,
SSL_SetSessionTicketKeyPair(pubKey.get(), privKey.get()));
}
}

Expand Down
6 changes: 6 additions & 0 deletions lib/ssl/ssl.def
Expand Up @@ -221,3 +221,9 @@ SSL_SignatureSchemePrefGet;
;+ local:
;+*;
;+};
;+NSS_3.30 { # NSS 3.30 release
;+ global:
SSL_SetSessionTicketKeyPair;
;+ local:
;+*;
;+};
13 changes: 13 additions & 0 deletions lib/ssl/ssl.h
Expand Up @@ -913,6 +913,19 @@ SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
const CERTCertificateList *certChainOpt,
SECKEYPrivateKey *key, SSLKEAType kea);

/*
** SSL_SetSessionTicketKeyPair configures an asymmetric key pair for use in
** wrapping session ticket keys, used by the server. This function currently
** only accepts an RSA public/private key pair.
**
** Prior to the existence of this function, NSS used an RSA private key
** associated with a configured certificate to perform session ticket
** encryption. If this function isn't used, the keys provided with a configured
** RSA certificate are used for wrapping session ticket keys.
*/
SSL_IMPORT SECStatus
SSL_SetSessionTicketKeyPair(SECKEYPublicKey *pubKey, SECKEYPrivateKey *privKey);

/*
** Configure a secure server's session-id cache. Define the maximum number
** of entries in the cache, the longevity of the entires, and the directory
Expand Down

0 comments on commit a3d3f69

Please sign in to comment.