Skip to content

Commit

Permalink
Bug 944175 - Implement Certificate Transparency [part 3, tests]. r=ekr
Browse files Browse the repository at this point in the history
  • Loading branch information
sergei-ndivi committed Dec 8, 2015
1 parent 417367e commit de6321c
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 3 deletions.
20 changes: 18 additions & 2 deletions external_tests/ssl_gtest/databuffer.h
Expand Up @@ -51,9 +51,16 @@ class DataBuffer {
void Assign(const DataBuffer& other) {
Assign(other.data(), other.len());
}

void Assign(const uint8_t* data, size_t len) {
Allocate(len);
memcpy(static_cast<void *>(data_), static_cast<const void *>(data), len);
if (data) {
Allocate(len);
memcpy(static_cast<void *>(data_), static_cast<const void *>(data), len);
} else {
assert(len == 0);
data_ = nullptr;
len_ = 0;
}
}

// Write will do a new allocation and expand the size of the buffer if needed.
Expand Down Expand Up @@ -166,6 +173,15 @@ inline std::ostream& operator<<(std::ostream& stream, const DataBuffer& buf) {
return stream;
}

inline bool operator==(const DataBuffer& a, const DataBuffer& b) {
return (a.empty() && b.empty()) ||
(a.len() == b.len() && 0 == memcmp(a.data(), b.data(), a.len()));
}

inline bool operator!=(const DataBuffer& a, const DataBuffer& b) {
return !(a == b);
}

} // namespace nss_test

#endif
104 changes: 104 additions & 0 deletions external_tests/ssl_gtest/ssl_extension_unittest.cc
Expand Up @@ -609,6 +609,110 @@ TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmConfiguration) {
}
}

/*
* Tests for Certificate Transparency (RFC 6962)
*/

// 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) {
const SECItem *scts = SSL_PeerSignedCertTimestamps(agent.ssl_fd());
ASSERT_TRUE(scts);
auth_timestamps_.reset(new DataBuffer(scts->data, scts->len));
}
);
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) {
ASSERT_TRUE(auth_timestamps_);
ASSERT_EQ(timestamps, *auth_timestamps_);

ASSERT_TRUE(handshake_timestamps_);
ASSERT_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(TlsExtensionTestGeneric, 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, server_->kea()));

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(timestamps);
}

// Test SSL_PeerSignedCertTimestamps returning zero-length SECItem
// when the client / the server / both have not enabled the feature.
TEST_P(TlsExtensionTestGeneric, 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, server_->kea()));

client_->StartConnect();

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

TEST_P(TlsExtensionTestGeneric, 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(TlsExtensionTestGeneric, SignedCertificateTimestampsInactiveBoth) {
server_->StartConnect();
client_->StartConnect();

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


INSTANTIATE_TEST_CASE_P(ExtensionTls10, TlsExtensionTestGeneric,
::testing::Combine(
TlsConnectTestBase::kTlsModesStream,
Expand Down
4 changes: 3 additions & 1 deletion external_tests/ssl_gtest/tls_agent.cc
Expand Up @@ -40,7 +40,9 @@ TlsAgent::TlsAgent(const std::string& name, Role role, Mode mode, SSLKEAType kea
error_code_(0),
send_ctr_(0),
recv_ctr_(0),
expected_read_error_(false) {
expected_read_error_(false),
handshake_callback_(),
auth_certificate_callback_() {

memset(&info_, 0, sizeof(info_));
memset(&csinfo_, 0, sizeof(csinfo_));
Expand Down
35 changes: 35 additions & 0 deletions external_tests/ssl_gtest/tls_agent.h
Expand Up @@ -11,6 +11,7 @@
#include "ssl.h"

#include <iostream>
#include <functional>

#include "test_io.h"

Expand All @@ -28,6 +29,16 @@ enum SessionResumptionMode {
RESUME_BOTH = RESUME_SESSIONID | RESUME_TICKET
};

class TlsAgent;

typedef
std::function<void(TlsAgent& agent, PRBool checksig, PRBool isServer)>
AuthCertificateCallbackFunction;

typedef
std::function<void(TlsAgent& agent)>
HandshakeCallbackFunction;

class TlsAgent : public PollTarget {
public:
enum Role { CLIENT, SERVER };
Expand Down Expand Up @@ -94,8 +105,12 @@ class TlsAgent : public PollTarget {
void CheckExtendedMasterSecret(bool expected);
void DisableRollbackDetection();

Role role() const { return role_; }

State state() const { return state_; }

SSLKEAType kea() const { return kea_; }

const char* state_str() const { return state_str(state()); }

const char* state_str(State state) const { return states[state]; }
Expand Down Expand Up @@ -131,6 +146,15 @@ class TlsAgent : public PollTarget {
size_t received_bytes() const { return recv_ctr_; }
int32_t error_code() const { return error_code_; }

void SetHandshakeCallback(HandshakeCallbackFunction handshake_callback) {
handshake_callback_ = handshake_callback;
}

void SetAuthCertificateCallback(
AuthCertificateCallbackFunction auth_certificate_callback) {
auth_certificate_callback_ = auth_certificate_callback;
}

private:
const static char* states[];

Expand All @@ -148,6 +172,9 @@ class TlsAgent : public PollTarget {
TlsAgent* agent = reinterpret_cast<TlsAgent*>(arg);
agent->CheckPreliminaryInfo();
agent->auth_certificate_hook_called_ = true;
if (agent->auth_certificate_callback_) {
agent->auth_certificate_callback_(*agent, checksig, isServer);
}
return SECSuccess;
}

Expand All @@ -157,6 +184,9 @@ class TlsAgent : public PollTarget {
TlsAgent* agent = reinterpret_cast<TlsAgent*>(arg);
EXPECT_TRUE(agent->expect_client_auth_);
EXPECT_TRUE(isServer);
if (agent->auth_certificate_callback_) {
agent->auth_certificate_callback_(*agent, checksig, isServer);
}
return SECSuccess;
}

Expand Down Expand Up @@ -208,6 +238,9 @@ class TlsAgent : public PollTarget {
TlsAgent* agent = reinterpret_cast<TlsAgent*>(arg);
agent->CheckPreliminaryInfo();
agent->handshake_callback_called_ = true;
if (agent->handshake_callback_) {
agent->handshake_callback_(*agent);
}
}

void CheckCallbacks() const;
Expand Down Expand Up @@ -237,6 +270,8 @@ class TlsAgent : public PollTarget {
size_t send_ctr_;
size_t recv_ctr_;
bool expected_read_error_;
HandshakeCallbackFunction handshake_callback_;
AuthCertificateCallbackFunction auth_certificate_callback_;
};

class TlsAgentTestBase : public ::testing::Test {
Expand Down

0 comments on commit de6321c

Please sign in to comment.