Commit d7c8d7de authored by Franziskus Kiefer's avatar Franziskus Kiefer

Bug 1399439 - API for external TLS session caches, r=mt

Reviewers: mt, ekr

Bug #: 1399439

Differential Revision: https://phabricator.services.mozilla.com/D284

--HG--
extra : rebase_source : b0bb342c952973b4d1ef6cfff7c4810904a8bbb1
extra : histedit_source : 3edefe0328a634ce2aec862458b8cb483a7a2dbd
parent d2b3c946
......@@ -12,6 +12,7 @@
#include "keyhi.h"
#include "pk11pub.h"
#include "pkcs11uri.h"
#include "sslexp.h"
struct ScopedDelete {
void operator()(CERTCertificate* cert) { CERT_DestroyCertificate(cert); }
......@@ -37,6 +38,9 @@ struct ScopedDelete {
void operator()(PLArenaPool* arena) { PORT_FreeArena(arena, PR_FALSE); }
void operator()(PK11Context* context) { PK11_DestroyContext(context, true); }
void operator()(PK11GenericObject* obj) { PK11_DestroyGenericObject(obj); }
void operator()(SSLResumptionTokenInfo* token) {
SSL_DestroyResumptionTokenInfo(token);
}
};
template <class T>
......@@ -68,6 +72,7 @@ SCOPED(PK11URI);
SCOPED(PLArenaPool);
SCOPED(PK11Context);
SCOPED(PK11GenericObject);
SCOPED(SSLResumptionTokenInfo);
#undef SCOPED
......
......@@ -535,4 +535,27 @@ INSTANTIATE_TEST_CASE_P(Version12Plus, TlsConnectTls12Plus,
::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
TlsConnectTestBase::kTlsV12Plus));
} // namespace nspr_test
INSTANTIATE_TEST_CASE_P(
GenericStream, TlsConnectGenericResumption,
::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
TlsConnectTestBase::kTlsVAll,
::testing::Values(true, false)));
INSTANTIATE_TEST_CASE_P(
GenericDatagram, TlsConnectGenericResumption,
::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
TlsConnectTestBase::kTlsV11Plus,
::testing::Values(true, false)));
INSTANTIATE_TEST_CASE_P(
GenericStream, TlsConnectGenericResumptionToken,
::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,
TlsConnectTestBase::kTlsVAll));
INSTANTIATE_TEST_CASE_P(
GenericDatagram, TlsConnectGenericResumptionToken,
::testing::Combine(TlsConnectTestBase::kTlsVariantsDatagram,
TlsConnectTestBase::kTlsV11Plus));
INSTANTIATE_TEST_CASE_P(GenericDatagram, TlsConnectTls13ResumptionToken,
TlsConnectTestBase::kTlsVariantsAll);
} // namespace nss_test
......@@ -60,7 +60,7 @@ TEST_P(TlsConnectGenericPre13, ConnectResumed) {
Connect();
}
TEST_P(TlsConnectGeneric, ConnectClientCacheDisabled) {
TEST_P(TlsConnectGenericResumption, ConnectClientCacheDisabled) {
ConfigureSessionCache(RESUME_NONE, RESUME_SESSIONID);
Connect();
SendReceive();
......@@ -71,7 +71,7 @@ TEST_P(TlsConnectGeneric, ConnectClientCacheDisabled) {
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectServerCacheDisabled) {
TEST_P(TlsConnectGenericResumption, ConnectServerCacheDisabled) {
ConfigureSessionCache(RESUME_SESSIONID, RESUME_NONE);
Connect();
SendReceive();
......@@ -82,7 +82,7 @@ TEST_P(TlsConnectGeneric, ConnectServerCacheDisabled) {
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectSessionCacheDisabled) {
TEST_P(TlsConnectGenericResumption, ConnectSessionCacheDisabled) {
ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
Connect();
SendReceive();
......@@ -93,7 +93,7 @@ TEST_P(TlsConnectGeneric, ConnectSessionCacheDisabled) {
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectResumeSupportBoth) {
TEST_P(TlsConnectGenericResumption, ConnectResumeSupportBoth) {
// This prefers tickets.
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
Connect();
......@@ -106,7 +106,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeSupportBoth) {
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectResumeClientTicketServerBoth) {
TEST_P(TlsConnectGenericResumption, ConnectResumeClientTicketServerBoth) {
// This causes no resumption because the client needs the
// session cache to resume even with tickets.
ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH);
......@@ -120,7 +120,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientTicketServerBoth) {
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicket) {
TEST_P(TlsConnectGenericResumption, ConnectResumeClientBothTicketServerTicket) {
// This causes a ticket resumption.
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
Connect();
......@@ -133,7 +133,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicket) {
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectResumeClientServerTicketOnly) {
TEST_P(TlsConnectGenericResumption, ConnectResumeClientServerTicketOnly) {
// This causes no resumption because the client needs the
// session cache to resume even with tickets.
ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
......@@ -147,7 +147,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientServerTicketOnly) {
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectResumeClientBothServerNone) {
TEST_P(TlsConnectGenericResumption, ConnectResumeClientBothServerNone) {
ConfigureSessionCache(RESUME_BOTH, RESUME_NONE);
Connect();
SendReceive();
......@@ -159,7 +159,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientBothServerNone) {
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectResumeClientNoneServerBoth) {
TEST_P(TlsConnectGenericResumption, ConnectResumeClientNoneServerBoth) {
ConfigureSessionCache(RESUME_NONE, RESUME_BOTH);
Connect();
SendReceive();
......@@ -202,7 +202,7 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicketForget) {
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectWithExpiredTicketAtClient) {
TEST_P(TlsConnectGenericResumption, ConnectWithExpiredTicketAtClient) {
SSLInt_SetTicketLifetime(1); // one second
// This causes a ticket resumption.
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
......@@ -417,7 +417,7 @@ static uint16_t ChooseAnotherCipher(uint16_t version) {
}
// Test that we don't resume when we can't negotiate the same cipher.
TEST_P(TlsConnectGeneric, TestResumeClientDifferentCipher) {
TEST_P(TlsConnectGenericResumption, TestResumeClientDifferentCipher) {
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
client_->EnableSingleCipher(ChooseOneCipher(version_));
Connect();
......@@ -442,7 +442,7 @@ TEST_P(TlsConnectGeneric, TestResumeClientDifferentCipher) {
}
// Test that we don't resume when we can't negotiate the same cipher.
TEST_P(TlsConnectGeneric, TestResumeServerDifferentCipher) {
TEST_P(TlsConnectGenericResumption, TestResumeServerDifferentCipher) {
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
server_->EnableSingleCipher(ChooseOneCipher(version_));
Connect();
......@@ -845,7 +845,7 @@ TEST_F(TlsConnectTest, TestTls13ResumptionForcedDowngrade) {
server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}
TEST_P(TlsConnectGeneric, ReConnectTicket) {
TEST_P(TlsConnectGenericResumption, ReConnectTicket) {
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
server_->EnableSingleCipher(ChooseOneCipher(version_));
Connect();
......@@ -877,7 +877,7 @@ TEST_P(TlsConnectGenericPre13, ReConnectCache) {
ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256);
}
TEST_P(TlsConnectGeneric, ReConnectAgainTicket) {
TEST_P(TlsConnectGenericResumption, ReConnectAgainTicket) {
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
server_->EnableSingleCipher(ChooseOneCipher(version_));
Connect();
......@@ -902,4 +902,116 @@ TEST_P(TlsConnectGeneric, ReConnectAgainTicket) {
ssl_auth_rsa_sign, ssl_sig_rsa_pss_rsae_sha256);
}
void CheckGetInfoResult(uint32_t alpnSize, uint32_t earlyDataSize,
ScopedCERTCertificate& cert,
ScopedSSLResumptionTokenInfo& token) {
ASSERT_TRUE(cert);
ASSERT_TRUE(token->peerCert);
// Check that the server cert is the correct one.
ASSERT_EQ(cert->derCert.len, token->peerCert->derCert.len);
EXPECT_EQ(0, memcmp(cert->derCert.data, token->peerCert->derCert.data,
cert->derCert.len));
ASSERT_EQ(alpnSize, token->alpnSelectionLen);
EXPECT_EQ(0, memcmp("a", token->alpnSelection, token->alpnSelectionLen));
ASSERT_EQ(earlyDataSize, token->maxEarlyDataSize);
}
TEST_P(TlsConnectGenericResumptionToken, ConnectResumeGetInfo) {
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
Connect();
SendReceive();
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ExpectResumption(RESUME_TICKET);
StartConnect();
ASSERT_TRUE(client_->MaybeSetResumptionToken());
// Get resumption token infos
SSLResumptionTokenInfo tokenInfo = {0};
ScopedSSLResumptionTokenInfo token(&tokenInfo);
client_->GetTokenInfo(token);
ScopedCERTCertificate cert(
PK11_FindCertFromNickname(server_->name().c_str(), nullptr));
CheckGetInfoResult(0, 0, cert, token);
Handshake();
CheckConnected();
SendReceive();
}
TEST_P(TlsConnectGenericResumptionToken, ConnectResumeGetInfoAlpn) {
EnableAlpn();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
Connect();
CheckAlpn("a");
SendReceive();
Reset();
EnableAlpn();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ExpectResumption(RESUME_TICKET);
StartConnect();
ASSERT_TRUE(client_->MaybeSetResumptionToken());
// Get resumption token infos
SSLResumptionTokenInfo tokenInfo = {0};
ScopedSSLResumptionTokenInfo token(&tokenInfo);
client_->GetTokenInfo(token);
ScopedCERTCertificate cert(
PK11_FindCertFromNickname(server_->name().c_str(), nullptr));
CheckGetInfoResult(1, 0, cert, token);
Handshake();
CheckConnected();
CheckAlpn("a");
SendReceive();
}
TEST_P(TlsConnectTls13ResumptionToken, ConnectResumeGetInfoZeroRtt) {
EnableAlpn();
SSLInt_RolloverAntiReplay();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
server_->Set0RttEnabled(true);
Connect();
CheckAlpn("a");
SendReceive();
Reset();
EnableAlpn();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ExpectResumption(RESUME_TICKET);
StartConnect();
server_->Set0RttEnabled(true);
client_->Set0RttEnabled(true);
ASSERT_TRUE(client_->MaybeSetResumptionToken());
// Get resumption token infos
SSLResumptionTokenInfo tokenInfo = {0};
ScopedSSLResumptionTokenInfo token(&tokenInfo);
client_->GetTokenInfo(token);
ScopedCERTCertificate cert(
PK11_FindCertFromNickname(server_->name().c_str(), nullptr));
CheckGetInfoResult(1, 1024, cert, token);
ZeroRttSendReceive(true, true);
Handshake();
ExpectEarlyDataAccepted(true);
CheckConnected();
CheckAlpn("a");
SendReceive();
}
} // namespace nss_test
......@@ -73,7 +73,8 @@ TlsAgent::TlsAgent(const std::string& name, Role role,
handshake_callback_(),
auth_certificate_callback_(),
sni_callback_(),
skip_version_checks_(false) {
skip_version_checks_(false),
resumption_token_() {
memset(&info_, 0, sizeof(info_));
memset(&csinfo_, 0, sizeof(csinfo_));
SECStatus rv = SSL_VersionRangeGetDefault(variant_, &vrange_);
......@@ -207,6 +208,29 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) {
return true;
}
bool TlsAgent::MaybeSetResumptionToken() {
if (!resumption_token_.empty()) {
SECStatus rv = SSL_SetResumptionToken(ssl_fd(), resumption_token_.data(),
resumption_token_.size());
// rv is SECFailure with error set to SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR
// if the resumption token was bad (expired/malformed/etc.).
if (expect_resumption_) {
// Only in case we expect resumption this has to be successful. We might
// not expect resumption due to some reason but the token is totally fine.
EXPECT_EQ(SECSuccess, rv);
}
if (rv != SECSuccess) {
EXPECT_EQ(SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR, PORT_GetError());
resumption_token_.clear();
EXPECT_FALSE(expect_resumption_);
if (expect_resumption_) return false;
}
}
return true;
}
void TlsAgent::SetupClientAuth() {
EXPECT_TRUE(EnsureTlsSetup());
ASSERT_EQ(CLIENT, role_);
......@@ -386,6 +410,26 @@ void TlsAgent::SetVersionRange(uint16_t minver, uint16_t maxver) {
}
}
SECStatus ResumptionTokenCallback(PRFileDesc* fd,
const PRUint8* resumptionToken,
unsigned int len, void* ctx) {
EXPECT_NE(nullptr, resumptionToken);
if (!resumptionToken) {
return SECFailure;
}
std::vector<uint8_t> new_token(resumptionToken, resumptionToken + len);
reinterpret_cast<TlsAgent*>(ctx)->SetResumptionToken(new_token);
return SECSuccess;
}
void TlsAgent::SetResumptionTokenCallback() {
EXPECT_TRUE(EnsureTlsSetup());
SECStatus rv =
SSL_SetResumptionTokenCallback(ssl_fd(), ResumptionTokenCallback, this);
EXPECT_EQ(SECSuccess, rv);
}
void TlsAgent::GetVersionRange(uint16_t* minver, uint16_t* maxver) {
*minver = vrange_.min;
*maxver = vrange_.max;
......
......@@ -165,6 +165,20 @@ class TlsAgent : public PollTarget {
void DisableECDHEServerKeyReuse();
bool GetPeerChainLength(size_t* count);
void CheckCipherSuite(uint16_t cipher_suite);
void SetResumptionTokenCallback();
bool MaybeSetResumptionToken();
void SetResumptionToken(const std::vector<uint8_t>& resumption_token) {
resumption_token_ = resumption_token;
}
const std::vector<uint8_t>& GetResumptionToken() const {
return resumption_token_;
}
void GetTokenInfo(ScopedSSLResumptionTokenInfo& token) {
SECStatus rv = SSL_GetResumptionTokenInfo(
resumption_token_.data(), resumption_token_.size(), token.get(),
sizeof(SSLResumptionTokenInfo));
ASSERT_EQ(SECSuccess, rv);
}
const std::string& name() const { return name_; }
......@@ -393,6 +407,7 @@ class TlsAgent : public PollTarget {
AuthCertificateCallbackFunction auth_certificate_callback_;
SniCallbackFunction sni_callback_;
bool skip_version_checks_;
std::vector<uint8_t> resumption_token_;
};
inline std::ostream& operator<<(std::ostream& stream,
......
......@@ -230,7 +230,9 @@ void TlsConnectTestBase::Reset() {
void TlsConnectTestBase::Reset(const std::string& server_name,
const std::string& client_name) {
auto token = client_->GetResumptionToken();
client_.reset(new TlsAgent(client_name, TlsAgent::CLIENT, variant_));
client_->SetResumptionToken(token);
server_.reset(new TlsAgent(server_name, TlsAgent::SERVER, variant_));
if (skip_version_checks_) {
client_->SkipVersionChecks();
......@@ -290,6 +292,7 @@ void TlsConnectTestBase::EnableExtendedMasterSecret() {
void TlsConnectTestBase::Connect() {
server_->StartConnect(server_model_ ? server_model_->ssl_fd() : nullptr);
client_->StartConnect(client_model_ ? client_model_->ssl_fd() : nullptr);
client_->MaybeSetResumptionToken();
Handshake();
CheckConnected();
}
......@@ -755,6 +758,16 @@ TlsConnectTls12Plus::TlsConnectTls12Plus()
TlsConnectTls13::TlsConnectTls13()
: TlsConnectTestBase(GetParam(), SSL_LIBRARY_VERSION_TLS_1_3) {}
TlsConnectGenericResumption::TlsConnectGenericResumption()
: TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())),
external_cache_(std::get<2>(GetParam())) {}
TlsConnectTls13ResumptionToken::TlsConnectTls13ResumptionToken()
: TlsConnectTestBase(GetParam(), SSL_LIBRARY_VERSION_TLS_1_3) {}
TlsConnectGenericResumptionToken::TlsConnectGenericResumptionToken()
: TlsConnectTestBase(std::get<0>(GetParam()), std::get<1>(GetParam())) {}
void TlsKeyExchangeTest::EnsureKeyShareSetup() {
EnsureTlsSetup();
groups_capture_ =
......
......@@ -55,7 +55,7 @@ class TlsConnectTestBase : public ::testing::Test {
// Clear the server session cache.
void ClearServerCache();
// Make sure TLS is configured for a connection.
void EnsureTlsSetup();
virtual void EnsureTlsSetup();
// Reset and keep the same certificate names
void Reset();
// Reset, and update the certificate names on both peers
......@@ -208,6 +208,50 @@ class TlsConnectGeneric : public TlsConnectTestBase,
TlsConnectGeneric();
};
class TlsConnectGenericResumption
: public TlsConnectTestBase,
public ::testing::WithParamInterface<
std::tuple<SSLProtocolVariant, uint16_t, bool>> {
private:
bool external_cache_;
public:
TlsConnectGenericResumption();
virtual void EnsureTlsSetup() {
TlsConnectTestBase::EnsureTlsSetup();
// Enable external resumption token cache.
if (external_cache_) {
client_->SetResumptionTokenCallback();
}
}
};
class TlsConnectTls13ResumptionToken
: public TlsConnectTestBase,
public ::testing::WithParamInterface<SSLProtocolVariant> {
public:
TlsConnectTls13ResumptionToken();
virtual void EnsureTlsSetup() {
TlsConnectTestBase::EnsureTlsSetup();
client_->SetResumptionTokenCallback();
}
};
class TlsConnectGenericResumptionToken
: public TlsConnectTestBase,
public ::testing::WithParamInterface<
std::tuple<SSLProtocolVariant, uint16_t>> {
public:
TlsConnectGenericResumptionToken();
virtual void EnsureTlsSetup() {
TlsConnectTestBase::EnsureTlsSetup();
client_->SetResumptionTokenCallback();
}
};
// A Pre TLS 1.2 generic test.
class TlsConnectPre12 : public TlsConnectTestBase,
public ::testing::WithParamInterface<
......
......@@ -343,7 +343,7 @@ CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
/* First, see if it is already a temp cert */
c = NSSCryptoContext_FindCertificateByEncodedCertificate(gCC,
&encoding);
if (!c) {
if (!c && handle) {
/* Then, see if it is already a perm cert */
c = NSSTrustDomain_FindCertificateByEncodedCertificate(handle,
&encoding);
......
......@@ -192,75 +192,71 @@ ssl_SelfEncryptUnprotectInt(
const PRUint8 *in, unsigned int inLen,
PRUint8 *out, unsigned int *outLen, unsigned int maxOutLen)
{
unsigned char *encodedKeyName;
unsigned char *iv;
SECItem ivItem = { siBuffer, NULL, 0 };
SECItem inItem = { siBuffer, (unsigned char *)in, inLen };
unsigned char *cipherText;
PRUint32 cipherTextLen;
unsigned char *encodedMac;
unsigned char computedMac[SHA256_LENGTH];
unsigned int computedMacLen;
unsigned int bytesToMac;
SECStatus rv;
sslReader reader = SSL_READER(in, inLen);
rv = ssl3_ConsumeFromItem(&inItem, &encodedKeyName,
SELF_ENCRYPT_KEY_NAME_LEN);
sslReadBuffer encodedKeyNameBuffer = { 0 };
SECStatus rv = sslRead_Read(&reader, SELF_ENCRYPT_KEY_NAME_LEN,
&encodedKeyNameBuffer);
if (rv != SECSuccess) {
return SECFailure;
}
rv = ssl3_ConsumeFromItem(&inItem, &iv, AES_BLOCK_SIZE);
sslReadBuffer ivBuffer = { 0 };
rv = sslRead_Read(&reader, AES_BLOCK_SIZE, &ivBuffer);
if (rv != SECSuccess) {
return SECFailure;
}
rv = ssl3_ConsumeNumberFromItem(&inItem, &cipherTextLen, 2);
PRUint64 cipherTextLen = 0;
rv = sslRead_ReadNumber(&reader, 2, &cipherTextLen);
if (rv != SECSuccess) {
return SECFailure;
}
rv = ssl3_ConsumeFromItem(&inItem, &cipherText, cipherTextLen);
sslReadBuffer cipherTextBuffer = { 0 };
rv = sslRead_Read(&reader, (unsigned int)cipherTextLen, &cipherTextBuffer);
if (rv != SECSuccess) {
return SECFailure;
}
bytesToMac = inItem.data - in;
unsigned int bytesToMac = reader.offset;
rv = ssl3_ConsumeFromItem(&inItem, &encodedMac, SHA256_LENGTH);
sslReadBuffer encodedMacBuffer = { 0 };
rv = sslRead_Read(&reader, SHA256_LENGTH, &encodedMacBuffer);
if (rv != SECSuccess) {
return SECFailure;
}
/* Make sure we're at the end of the block. */
if (inItem.len) {
if (reader.offset != reader.buf.len) {
PORT_SetError(SEC_ERROR_BAD_DATA);
return SECFailure;
}
/* Now that everything is decoded, we can make progress. */
/* 1. Check that we have the right key. */
if (PORT_Memcmp(keyName, encodedKeyName, SELF_ENCRYPT_KEY_NAME_LEN)) {
if (PORT_Memcmp(keyName, encodedKeyNameBuffer.buf, SELF_ENCRYPT_KEY_NAME_LEN)) {
PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT);
return SECFailure;
}
/* 2. Check the MAC */
unsigned char computedMac[SHA256_LENGTH];
unsigned int computedMacLen = 0;
rv = ssl_MacBuffer(macKey, CKM_SHA256_HMAC, in, bytesToMac,
computedMac, &computedMacLen, sizeof(computedMac));
if (rv != SECSuccess) {
return SECFailure;
}
PORT_Assert(computedMacLen == SHA256_LENGTH);
if (NSS_SecureMemcmp(computedMac, encodedMac, computedMacLen) != 0) {
if (NSS_SecureMemcmp(computedMac, encodedMacBuffer.buf, computedMacLen) != 0) {
PORT_SetError(SEC_ERROR_BAD_DATA);
return SECFailure;
}
/* 3. OK, it verifies, now decrypt. */
ivItem.data = iv;
ivItem.len = AES_BLOCK_SIZE;
SECItem ivItem = { siBuffer, (unsigned char *)ivBuffer.buf, AES_BLOCK_SIZE };
rv = PK11_Decrypt(encKey, CKM_AES_CBC_PAD, &ivItem,
out, outLen, maxOutLen, cipherText, cipherTextLen);
out, outLen, maxOutLen, cipherTextBuffer.buf, cipherTextLen);
if (rv != SECSuccess) {
return SECFailure;
}
......
......@@ -852,7 +852,7 @@ ssl3_config_match_init(sslSocket *ss)
* enabled, has a certificate (as needed), has a viable key agreement method, is
* usable with the negotiated TLS version, and is otherwise usable. */
static PRBool
config_match(const ssl3CipherSuiteCfg *suite, int policy,
config_match(const ssl3CipherSuiteCfg *suite, PRUint8 policy,
const SSLVersionRange *vrange, const sslSocket *ss)
{
const ssl3CipherSuiteDef *cipher_def;
......@@ -888,7 +888,7 @@ config_match(const ssl3CipherSuiteCfg *suite, int policy,
/* Return the number of cipher suites that are usable. */
/* called from ssl3_SendClientHello */
static unsigned int
count_cipher_suites(sslSocket *ss, int policy)
count_cipher_suites(sslSocket *ss, PRUint8 policy)
{
unsigned int i, count = 0;
......@@ -2652,9 +2652,7 @@ ssl3_HandleNoCertificate(sslSocket *ss)
(ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) {
PRFileDesc *lower;
if (!ss->opt.noCache) {
ss->sec.uncache(ss->sec.ci.sid);
}
ssl_UncacheSessionID(ss);
SSL3_SendAlert(ss, alert_fatal, bad_certificate);
lower = ss->fd->lower;
......@@ -2716,8 +2714,8 @@ SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
ssl_GetSSL3HandshakeLock(ss);
}
if (level == alert_fatal) {
if (!ss->opt.noCache && ss->sec.ci.sid) {
ss->sec.uncache(ss->sec.ci.sid);
if (ss->sec.ci.sid) {
ssl_UncacheSessionID(ss);
}
}
......@@ -2981,9 +2979,7 @@ ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
}
}
if (level == alert_fatal) {
if (!ss->opt.noCache) {
ss->sec.uncache(ss->sec.ci.sid);
}
ssl_UncacheSessionID(ss);
if ((ss->ssl3.hs.ws == wait_server_hello) &&
(desc == handshake_failure)) {
/* XXX This is a hack. We're assuming that any handshake failure
......@@ -4603,13 +4599,24 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
}
}
/* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup
* handles expired entries and other details.
* XXX If we've been called from ssl_BeginClientHandshake, then
* this lookup is duplicative and wasteful.
*/
sid = (ss->opt.noCache) ? NULL
: ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url);
/* Check if we have a ss->sec.ci.sid.
* Check that it's not expired.
* If we have an sid and it comes from an external cache, we use it. */
if (ss->sec.ci.sid && ss->sec.ci.sid->cached == in_external_cache) {
PORT_Assert(!ss->sec.isServer);
sid = ss->sec.ci.sid;
SSL_TRC(3, ("%d: SSL3[%d]: using external resumption token in ClientHello",
SSL_GETPID(), ss->fd));
} else if (!ss->opt.noCache) {
/* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup
* handles expired entries and other details.
* XXX If we've been called from ssl_BeginClientHandshake, then
* this lookup is duplicative and wasteful.
*/
sid = ssl_LookupSID(&ss->sec.ci.peer, ss->sec.ci.port, ss->peerID, ss->url);
} else {
sid = NULL;
}
/* We can't resume based on a different token. If the sid exists,
* make sure the token that holds the master secret still exists ...
......@@ -4700,7 +4707,7 @@ ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
if (!sidOK) {
SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_not_ok);
ss->sec.uncache(sid);
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
sid = NULL;
}
......@@ -5031,7 +5038,7 @@ ssl3_HandleHelloRequest(sslSocket *ss)
}
if (sid) {
ss->sec.uncache(sid);
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
ss->sec.ci.sid = NULL;
}
......@@ -6606,7 +6613,7 @@ ssl3_HandleServerHelloPart2(sslSocket *ss, const SECItem *sidBytes,
/* throw the old one away */
sid->u.ssl3.keys.resumable = PR_FALSE;
ss->sec.uncache(sid);
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
/* get a new sid */
......@@ -7516,8 +7523,6 @@ ssl3_NewSessionID(sslSocket *ss, PRBool is_server)
sid->u.ssl3.keys.resumable = PR_TRUE;
sid->u.ssl3.policy = SSL_ALLOWED;
sid->u.ssl3.clientWriteKey = NULL;
sid->u.ssl3.serverWriteKey = NULL;
sid->u.ssl3.keys.extendedMasterSecretUsed = PR_FALSE;
if (is_server) {
......@@ -8246,7 +8251,7 @@ ssl3_HandleClientHello(sslSocket *ss, PRUint8 *b, PRUint32 length)
!ss->firstHsDone))) {
SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
ss->sec.uncache(sid);
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
sid = NULL;
}
......@@ -8452,7 +8457,7 @@ cipher_found:
}
if (ss->sec.ci.sid) {
ss->sec.uncache(ss->sec.ci.sid);
ssl_UncacheSessionID(ss);
PORT_Assert(ss->sec.ci.sid != sid); /* should be impossible, but ... */
if (ss->sec.ci.sid != sid) {
ssl_FreeSID(ss->sec.ci.sid);
......@@ -8548,7 +8553,7 @@ cipher_found:
if (sid) { /* we had a sid, but it's no longer valid, free it */
ss->statelessResume = PR_FALSE;
SSL_AtomicIncrementLong(&ssl3stats.hch_sid_cache_not_ok);
ss->sec.uncache(sid);