Skip to content

Commit

Permalink
Bug 1291181 - status_request extension is an extension in TLS 1.3, r=ekr
Browse files Browse the repository at this point in the history
--HG--
extra : rebase_source : dc0c9d3eba1267ae8ccc23a7ad6b8c2d74aeac1a
  • Loading branch information
martinthomson committed Aug 15, 2016
1 parent 43069c5 commit a12063d
Show file tree
Hide file tree
Showing 10 changed files with 319 additions and 199 deletions.
1 change: 1 addition & 0 deletions external_tests/ssl_gtest/manifest.mn
Expand Up @@ -15,6 +15,7 @@ CPPSRCS = \
ssl_0rtt_unittest.cc \
ssl_agent_unittest.cc \
ssl_auth_unittest.cc \
ssl_cert_ext_unittest.cc \
ssl_ciphersuite_unittest.cc \
ssl_damage_unittest.cc \
ssl_dhe_unittest.cc \
Expand Down
6 changes: 3 additions & 3 deletions external_tests/ssl_gtest/ssl_auth_unittest.cc
Expand Up @@ -364,7 +364,7 @@ class BeforeFinished13 : public PacketFilter {
// processed by the client, SSL_AuthCertificateComplete() is called.
TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) {
client_->SetAuthCertificateCallback(
[](TlsAgent&, PRBool, PRBool) -> SECStatus { return SECWouldBlock; });
[](TlsAgent*, PRBool, PRBool) -> SECStatus { return SECWouldBlock; });
server_->SetPacketFilter(new BeforeFinished13(client_, server_, [this]() {
EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client_->ssl_fd(), 0));
}));
Expand All @@ -383,7 +383,7 @@ static void TriggerAuthComplete(PollTarget* target, Event event) {
// will trigger after the Finished message is processed.
TEST_F(TlsConnectDatagram13, AuthCompleteAfterFinished) {
client_->SetAuthCertificateCallback(
[this](TlsAgent&, PRBool, PRBool) -> SECStatus {
[this](TlsAgent*, PRBool, PRBool) -> SECStatus {
Poller::Timer* timer_handle;
// This is really just to unroll the stack.
Poller::Instance()->SetTimer(1U, client_, TriggerAuthComplete,
Expand Down Expand Up @@ -411,7 +411,7 @@ TEST_P(TlsConnectGenericPre13, ClientWriteBetweenCCSAndFinishedWithFalseStart) {
TEST_P(TlsConnectGenericPre13, AuthCompleteBeforeFinishedWithFalseStart) {
client_->EnableFalseStart();
client_->SetAuthCertificateCallback(
[](TlsAgent&, PRBool, PRBool) -> SECStatus { return SECWouldBlock; });
[](TlsAgent*, PRBool, PRBool) -> SECStatus { return SECWouldBlock; });
server_->SetPacketFilter(new BeforeFinished(
client_, server_,
[]() {
Expand Down
198 changes: 198 additions & 0 deletions external_tests/ssl_gtest/ssl_cert_ext_unittest.cc
@@ -0,0 +1,198 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 "sslerr.h"
#include "sslproto.h"

#include <memory>

#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

namespace nss_test {

// Tests for Certificate Transparency (RFC 6962)
// These don't work with TLS 1.3: see bug 1252745.

// Helper class - stores signed certificate timestamps as provided
// by the relevant callbacks on the client.
class SignedCertificateTimestampsExtractor {
public:
SignedCertificateTimestampsExtractor(TlsAgent* client) {
client->SetAuthCertificateCallback(
[&](TlsAgent* agent, bool checksig, bool isServer) -> SECStatus {
const SECItem* scts = SSL_PeerSignedCertTimestamps(agent->ssl_fd());
EXPECT_TRUE(scts);
if (!scts) {
return SECFailure;
}
auth_timestamps_.reset(new DataBuffer(scts->data, scts->len));
return SECSuccess;
});
client->SetHandshakeCallback([&](TlsAgent* agent) {
const SECItem* scts = SSL_PeerSignedCertTimestamps(agent->ssl_fd());
ASSERT_TRUE(scts);
handshake_timestamps_.reset(new DataBuffer(scts->data, scts->len));
});
}

void assertTimestamps(const DataBuffer& timestamps) {
EXPECT_TRUE(auth_timestamps_);
EXPECT_EQ(timestamps, *auth_timestamps_);

EXPECT_TRUE(handshake_timestamps_);
EXPECT_EQ(timestamps, *handshake_timestamps_);
}

private:
std::unique_ptr<DataBuffer> auth_timestamps_;
std::unique_ptr<DataBuffer> handshake_timestamps_;
};

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));

// Test timestamps extraction during a successful handshake.
TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsHandshake) {
EnsureTlsSetup();
EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(),
&kSctItem, ssl_kea_rsa));
EXPECT_EQ(SECSuccess,
SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
PR_TRUE));
SignedCertificateTimestampsExtractor timestamps_extractor(client_);

Connect();

timestamps_extractor.assertTimestamps(kSctBuffer);
const SECItem* c_timestamps = SSL_PeerSignedCertTimestamps(client_->ssl_fd());
EXPECT_EQ(SECEqual, SECITEM_CompareItem(&kSctItem, c_timestamps));
}

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

EnsureTlsSetup();
EXPECT_TRUE(
server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraData));
EXPECT_EQ(SECSuccess,
SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
PR_TRUE));
SignedCertificateTimestampsExtractor timestamps_extractor(client_);

Connect();

timestamps_extractor.assertTimestamps(kSctBuffer);
const SECItem* c_timestamps = SSL_PeerSignedCertTimestamps(client_->ssl_fd());
EXPECT_EQ(SECEqual, SECITEM_CompareItem(&kSctItem, c_timestamps));
}

// Test SSL_PeerSignedCertTimestamps returning zero-length SECItem
// when the client / the server / both have not enabled the feature.
TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsInactiveClient) {
EnsureTlsSetup();
EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(),
&kSctItem, ssl_kea_rsa));
SignedCertificateTimestampsExtractor timestamps_extractor(client_);

Connect();
timestamps_extractor.assertTimestamps(DataBuffer());
}

TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsInactiveServer) {
EnsureTlsSetup();
EXPECT_EQ(SECSuccess,
SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
PR_TRUE));
SignedCertificateTimestampsExtractor timestamps_extractor(client_);

Connect();
timestamps_extractor.assertTimestamps(DataBuffer());
}

TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsInactiveBoth) {
EnsureTlsSetup();
SignedCertificateTimestampsExtractor timestamps_extractor(client_);

Connect();
timestamps_extractor.assertTimestamps(DataBuffer());
}

// Check that the given agent doesn't have an OCSP response for its peer.
static SECStatus CheckNoOCSP(TlsAgent* agent, bool checksig, bool isServer) {
const SECItemArray* ocsp = SSL_PeerStapledOCSPResponses(agent->ssl_fd());
EXPECT_TRUE(ocsp);
EXPECT_EQ(0U, ocsp->len);
return SECSuccess;
}

static const uint8_t kOcspValue1[] = {1, 2, 3, 4, 5, 6};
static const uint8_t kOcspValue2[] = {7, 8, 9};
static const SECItem kOcspItems[] = {
{siBuffer, const_cast<uint8_t*>(kOcspValue1), sizeof(kOcspValue1)},
{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};

TEST_P(TlsConnectGeneric, NoOcsp) {
EnsureTlsSetup();
client_->SetAuthCertificateCallback(CheckNoOCSP);
Connect();
}

// The client doesn't get OCSP stapling unless it asks.
TEST_P(TlsConnectGeneric, OcspNotRequested) {
EnsureTlsSetup();
client_->SetAuthCertificateCallback(CheckNoOCSP);
EXPECT_TRUE(
server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kOcspExtraData));
Connect();
}

// Even if the client asks, the server has nothing unless it is configured.
TEST_P(TlsConnectGeneric, OcspNotProvided) {
EnsureTlsSetup();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_OCSP_STAPLING, PR_TRUE));
client_->SetAuthCertificateCallback(CheckNoOCSP);
Connect();
}

TEST_P(TlsConnectGeneric, OcspSuccess) {
EnsureTlsSetup();
EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
SSL_ENABLE_OCSP_STAPLING, PR_TRUE));
auto capture_ocsp = new TlsExtensionCapture(ssl_cert_status_xtn);
server_->SetPacketFilter(capture_ocsp);

// The value should be available during the AuthCertificateCallback
client_->SetAuthCertificateCallback([](TlsAgent* agent, bool checksig,
bool isServer) -> SECStatus {
const SECItemArray* ocsp = SSL_PeerStapledOCSPResponses(agent->ssl_fd());
if (!ocsp) {
return SECFailure;
}
EXPECT_EQ(1U, ocsp->len) << "We only provide the first item";
EXPECT_EQ(0, SECITEM_CompareItem(&kOcspItems[0], &ocsp->items[0]));
return SECSuccess;
});
EXPECT_TRUE(
server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kOcspExtraData));

Connect();
// In TLS 1.3, the server doesn't provide a visible ServerHello extension.
// For earlier versions, the extension is just empty.
EXPECT_EQ(0U, capture_ocsp->extension().len());
}

} // namespace nspr_test
107 changes: 0 additions & 107 deletions external_tests/ssl_gtest/ssl_extension_unittest.cc
Expand Up @@ -519,113 +519,6 @@ TEST_P(TlsExtensionTest12, SignatureAlgorithmConfiguration) {
}
}

/*
* Tests for Certificate Transparency (RFC 6962)
* These don't work with TLS 1.3: see bug 1252745.
*/

// Helper class - stores signed certificate timestamps as provided
// by the relevant callbacks on the client.
class SignedCertificateTimestampsExtractor {
public:
SignedCertificateTimestampsExtractor(TlsAgent& client) {
client.SetAuthCertificateCallback(
[&](TlsAgent& agent, PRBool checksig, PRBool isServer) -> SECStatus {
const SECItem* scts = SSL_PeerSignedCertTimestamps(agent.ssl_fd());
EXPECT_TRUE(scts);
if (!scts) {
return SECFailure;
}
auth_timestamps_.reset(new DataBuffer(scts->data, scts->len));
return SECSuccess;
});
client.SetHandshakeCallback([&](TlsAgent& agent) {
const SECItem* scts = SSL_PeerSignedCertTimestamps(agent.ssl_fd());
ASSERT_TRUE(scts);
handshake_timestamps_.reset(new DataBuffer(scts->data, scts->len));
});
}

void assertTimestamps(const DataBuffer& timestamps) {
EXPECT_TRUE(auth_timestamps_);
EXPECT_EQ(timestamps, *auth_timestamps_);

EXPECT_TRUE(handshake_timestamps_);
EXPECT_EQ(timestamps, *handshake_timestamps_);
}

private:
std::unique_ptr<DataBuffer> auth_timestamps_;
std::unique_ptr<DataBuffer> handshake_timestamps_;
};

// Test timestamps extraction during a successful handshake.
TEST_P(TlsExtensionTestPre13, SignedCertificateTimestampsHandshake) {
uint8_t val[] = {0x01, 0x23, 0x45, 0x67, 0x89};
const SECItem si_timestamps = {siBuffer, val, sizeof(val)};
const DataBuffer timestamps(val, sizeof(val));

server_->StartConnect();
ASSERT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(
server_->ssl_fd(), &si_timestamps, ssl_kea_rsa));

client_->StartConnect();
ASSERT_EQ(SECSuccess,
SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
PR_TRUE));

SignedCertificateTimestampsExtractor timestamps_extractor(*client_);
Handshake();
CheckConnected();
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
timestamps_extractor.assertTimestamps(timestamps);
}
const SECItem* c_timestamps = SSL_PeerSignedCertTimestamps(client_->ssl_fd());
ASSERT_EQ(SECEqual, SECITEM_CompareItem(&si_timestamps, c_timestamps));
}

// Test SSL_PeerSignedCertTimestamps returning zero-length SECItem
// when the client / the server / both have not enabled the feature.
TEST_P(TlsExtensionTestPre13, SignedCertificateTimestampsInactiveClient) {
uint8_t val[] = {0x01, 0x23, 0x45, 0x67, 0x89};
const SECItem si_timestamps = {siBuffer, val, sizeof(val)};

server_->StartConnect();
ASSERT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(
server_->ssl_fd(), &si_timestamps, ssl_kea_rsa));

client_->StartConnect();

SignedCertificateTimestampsExtractor timestamps_extractor(*client_);
Handshake();
CheckConnected();
timestamps_extractor.assertTimestamps(DataBuffer());
}

TEST_P(TlsExtensionTestPre13, SignedCertificateTimestampsInactiveServer) {
server_->StartConnect();

client_->StartConnect();
ASSERT_EQ(SECSuccess,
SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
PR_TRUE));

SignedCertificateTimestampsExtractor timestamps_extractor(*client_);
Handshake();
CheckConnected();
timestamps_extractor.assertTimestamps(DataBuffer());
}

TEST_P(TlsExtensionTestPre13, SignedCertificateTimestampsInactiveBoth) {
server_->StartConnect();
client_->StartConnect();

SignedCertificateTimestampsExtractor timestamps_extractor(*client_);
Handshake();
CheckConnected();
timestamps_extractor.assertTimestamps(DataBuffer());
}

// Temporary test to verify that we choke on an empty ClientKeyShare.
// This test will fail when we implement HelloRetryRequest.
TEST_P(TlsExtensionTest13, EmptyClientKeyShare) {
Expand Down
4 changes: 2 additions & 2 deletions external_tests/ssl_gtest/ssl_resumption_unittest.cc
Expand Up @@ -206,9 +206,9 @@ TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicketForget) {

// This callback switches out the "server" cert used on the server with
// the "client" certificate, which should be the same type.
static int32_t SwitchCertificates(TlsAgent& agent, const SECItem* srvNameArr,
static int32_t SwitchCertificates(TlsAgent* agent, const SECItem* srvNameArr,
uint32_t srvNameArrSize) {
bool ok = agent.ConfigServerCert("client");
bool ok = agent->ConfigServerCert("client");
if (!ok) return SSL_SNI_SEND_ALERT;

return 0; // first config
Expand Down

0 comments on commit a12063d

Please sign in to comment.