Update NSS to 3.41

This commit is contained in:
wolfbeast 2018-12-15 01:42:53 +01:00 committed by Roy Tam
commit 5f0986e66f
540 changed files with 49568 additions and 10631 deletions

View file

@ -52,6 +52,7 @@ CPPSRCS = \
tls_hkdf_unittest.cc \
tls_filter.cc \
tls_protect.cc \
tls_esni_unittest.cc \
$(NULL)
INCLUDES += -I$(CORE_DEPTH)/gtests/google_test/gtest/include \

View file

@ -206,4 +206,4 @@ static const uint8_t rsa8193[] = {
0x13, 0x34, 0x9d, 0x34, 0xb8, 0xef, 0x13, 0x3a, 0x20, 0xf5, 0x74, 0x02,
0x70, 0x3b, 0x41, 0x60, 0x1f, 0x5e, 0x76, 0x0a, 0xb1, 0x17, 0xd5, 0xcf,
0x79, 0xef, 0xf7, 0xab, 0xe7, 0xd6, 0x0f, 0xad, 0x85, 0x2c, 0x52, 0x67,
0xb5, 0xa0, 0x4a, 0xfd, 0xaf};
0xb5, 0xa0, 0x4a, 0xfd, 0xaf};

View file

@ -19,7 +19,7 @@ extern "C" {
#include "databuffer.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
namespace nss_test {

View file

@ -16,7 +16,7 @@ extern "C" {
}
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

View file

@ -34,7 +34,7 @@ const static uint8_t kCannedTls13ClientHello[] = {
0xc2, 0xb3, 0xc6, 0x80, 0x72, 0x86, 0x08, 0x86, 0x8f, 0x52, 0xc5, 0xcb,
0xbf, 0x2a, 0xb5, 0x59, 0x64, 0xcc, 0x0c, 0x49, 0x95, 0x36, 0xe4, 0xd9,
0x2f, 0xd4, 0x24, 0x66, 0x71, 0x6f, 0x5d, 0x70, 0xe2, 0xa0, 0xea, 0x26,
0x00, 0x2b, 0x00, 0x03, 0x02, 0x7f, kD13, 0x00, 0x0d, 0x00, 0x20, 0x00,
0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, 0x04, 0x00, 0x0d, 0x00, 0x20, 0x00,
0x1e, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x02, 0x03, 0x08, 0x04, 0x08,
0x05, 0x08, 0x06, 0x04, 0x01, 0x05, 0x01, 0x06, 0x01, 0x02, 0x01, 0x04,
0x02, 0x05, 0x02, 0x06, 0x02, 0x02, 0x02};
@ -64,8 +64,8 @@ TEST_P(TlsAgentTestClient13, CannedHello) {
auto sh = MakeCannedTls13ServerHello();
MakeHandshakeMessage(kTlsHandshakeServerHello, sh.data(), sh.len(),
&server_hello);
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
server_hello.data(), server_hello.len(), &buffer);
MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(),
server_hello.len(), &buffer);
ProcessMessage(buffer, TlsAgent::STATE_CONNECTING);
}
@ -79,8 +79,8 @@ TEST_P(TlsAgentTestClient13, EncryptedExtensionsInClear) {
&encrypted_extensions, 1);
server_hello.Append(encrypted_extensions);
DataBuffer buffer;
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
server_hello.data(), server_hello.len(), &buffer);
MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(),
server_hello.len(), &buffer);
EnsureInit();
ExpectAlert(kTlsAlertUnexpectedMessage);
ProcessMessage(buffer, TlsAgent::STATE_ERROR,
@ -97,11 +97,11 @@ TEST_F(TlsAgentStreamTestClient, EncryptedExtensionsInClearTwoPieces) {
&encrypted_extensions, 1);
server_hello.Append(encrypted_extensions);
DataBuffer buffer;
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
server_hello.data(), kFirstFragmentSize, &buffer);
MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, server_hello.data(),
kFirstFragmentSize, &buffer);
DataBuffer buffer2;
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3,
server_hello.data() + kFirstFragmentSize,
server_hello.len() - kFirstFragmentSize, &buffer2);
@ -129,11 +129,11 @@ TEST_F(TlsAgentDgramTestClient, EncryptedExtensionsInClearTwoPieces) {
&encrypted_extensions, 1);
server_hello_frag2.Append(encrypted_extensions);
DataBuffer buffer;
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3,
server_hello_frag1.data(), server_hello_frag1.len(), &buffer);
DataBuffer buffer2;
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3,
server_hello_frag2.data(), server_hello_frag2.len(), &buffer2, 1);
EnsureInit();
@ -150,7 +150,7 @@ TEST_F(TlsAgentDgramTestClient, AckWithBogusLengthField) {
// Length doesn't match
const uint8_t ackBuf[] = {0x00, 0x08, 0x00};
DataBuffer record;
MakeRecord(variant_, kTlsAckType, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf,
MakeRecord(variant_, ssl_ct_ack, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf,
sizeof(ackBuf), &record, 0);
agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
SSL_LIBRARY_VERSION_TLS_1_3);
@ -164,7 +164,7 @@ TEST_F(TlsAgentDgramTestClient, AckWithNonEvenLength) {
// Length isn't a multiple of 8
const uint8_t ackBuf[] = {0x00, 0x01, 0x00};
DataBuffer record;
MakeRecord(variant_, kTlsAckType, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf,
MakeRecord(variant_, ssl_ct_ack, SSL_LIBRARY_VERSION_TLS_1_2, ackBuf,
sizeof(ackBuf), &record, 0);
agent_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_3,
SSL_LIBRARY_VERSION_TLS_1_3);
@ -196,7 +196,7 @@ TEST_F(TlsAgentStreamTestClient, Set0RttOptionThenRead) {
agent_->StartConnect();
agent_->Set0RttEnabled(true);
DataBuffer buffer;
MakeRecord(kTlsApplicationDataType, SSL_LIBRARY_VERSION_TLS_1_3,
MakeRecord(ssl_ct_application_data, SSL_LIBRARY_VERSION_TLS_1_3,
reinterpret_cast<const uint8_t *>(k0RttData), strlen(k0RttData),
&buffer);
ExpectAlert(kTlsAlertUnexpectedMessage);
@ -214,10 +214,10 @@ TEST_F(TlsAgentStreamTestServer, Set0RttOptionClientHelloThenRead) {
agent_->StartConnect();
agent_->Set0RttEnabled(true);
DataBuffer buffer;
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3,
MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3,
kCannedTls13ClientHello, sizeof(kCannedTls13ClientHello), &buffer);
ProcessMessage(buffer, TlsAgent::STATE_CONNECTING);
MakeRecord(kTlsApplicationDataType, SSL_LIBRARY_VERSION_TLS_1_3,
MakeRecord(ssl_ct_application_data, SSL_LIBRARY_VERSION_TLS_1_3,
reinterpret_cast<const uint8_t *>(k0RttData), strlen(k0RttData),
&buffer);
ExpectAlert(kTlsAlertBadRecordMac);

View file

@ -15,7 +15,7 @@ extern "C" {
}
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@ -37,6 +37,50 @@ TEST_P(TlsConnectGeneric, ServerAuthRsaChain) {
EXPECT_EQ(2UL, chain_length);
}
TEST_P(TlsConnectTls12Plus, ServerAuthRsaPss) {
static const SSLSignatureScheme kSignatureSchemePss[] = {
ssl_sig_rsa_pss_pss_sha256};
Reset(TlsAgent::kServerRsaPss);
client_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
server_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
Connect();
CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss,
ssl_sig_rsa_pss_pss_sha256);
}
// PSS doesn't work with TLS 1.0 or 1.1 because we can't signal it.
TEST_P(TlsConnectPre12, ServerAuthRsaPssFails) {
static const SSLSignatureScheme kSignatureSchemePss[] = {
ssl_sig_rsa_pss_pss_sha256};
Reset(TlsAgent::kServerRsaPss);
client_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
server_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
server_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
}
// Check that a PSS certificate with no parameters works.
TEST_P(TlsConnectTls12Plus, ServerAuthRsaPssNoParameters) {
static const SSLSignatureScheme kSignatureSchemePss[] = {
ssl_sig_rsa_pss_pss_sha256};
Reset("rsa_pss_noparam");
client_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
server_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
Connect();
CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_pss,
ssl_sig_rsa_pss_pss_sha256);
}
TEST_P(TlsConnectGeneric, ServerAuthRsaPssChain) {
Reset("rsa_pss_chain");
Connect();
@ -55,6 +99,76 @@ TEST_P(TlsConnectGeneric, ServerAuthRsaCARsaPssChain) {
EXPECT_EQ(2UL, chain_length);
}
TEST_P(TlsConnectGeneric, ServerAuthRejected) {
EnsureTlsSetup();
client_->SetAuthCertificateCallback(
[](TlsAgent*, PRBool, PRBool) -> SECStatus { return SECFailure; });
ConnectExpectAlert(client_, kTlsAlertBadCertificate);
client_->CheckErrorCode(SSL_ERROR_BAD_CERTIFICATE);
server_->CheckErrorCode(SSL_ERROR_BAD_CERT_ALERT);
EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state());
}
struct AuthCompleteArgs : public PollTarget {
AuthCompleteArgs(const std::shared_ptr<TlsAgent>& a, PRErrorCode c)
: agent(a), code(c) {}
std::shared_ptr<TlsAgent> agent;
PRErrorCode code;
};
static void CallAuthComplete(PollTarget* target, Event event) {
EXPECT_EQ(TIMER_EVENT, event);
auto args = reinterpret_cast<AuthCompleteArgs*>(target);
std::cerr << args->agent->role_str() << ": call SSL_AuthCertificateComplete "
<< (args->code ? PR_ErrorToName(args->code) : "no error")
<< std::endl;
EXPECT_EQ(SECSuccess,
SSL_AuthCertificateComplete(args->agent->ssl_fd(), args->code));
args->agent->Handshake(); // Make the TlsAgent aware of the error.
delete args;
}
// Install an AuthCertificateCallback that blocks when called. Then
// SSL_AuthCertificateComplete is called on a very short timer. This allows any
// processing that might follow the callback to complete.
static void SetDeferredAuthCertificateCallback(std::shared_ptr<TlsAgent> agent,
PRErrorCode code) {
auto args = new AuthCompleteArgs(agent, code);
agent->SetAuthCertificateCallback(
[args](TlsAgent*, PRBool, PRBool) -> SECStatus {
// This can't be 0 or we race the message from the client to the server,
// and tests assume that we lose that race.
std::shared_ptr<Poller::Timer> timer_handle;
Poller::Instance()->SetTimer(1U, args, CallAuthComplete, &timer_handle);
return SECWouldBlock;
});
}
TEST_P(TlsConnectTls13, ServerAuthRejectAsync) {
SetDeferredAuthCertificateCallback(client_, SEC_ERROR_REVOKED_CERTIFICATE);
ConnectExpectAlert(client_, kTlsAlertCertificateRevoked);
// We only detect the error here when we attempt to handshake, so all the
// client learns is that the handshake has already failed.
client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILED);
server_->CheckErrorCode(SSL_ERROR_REVOKED_CERT_ALERT);
}
// In TLS 1.2 and earlier, this will result in the client sending its Finished
// before learning that the server certificate is bad. That means that the
// server will believe that the handshake is complete.
TEST_P(TlsConnectGenericPre13, ServerAuthRejectAsync) {
SetDeferredAuthCertificateCallback(client_, SEC_ERROR_EXPIRED_CERTIFICATE);
client_->ExpectSendAlert(kTlsAlertCertificateExpired);
server_->ExpectReceiveAlert(kTlsAlertCertificateExpired);
ConnectExpectFailOneSide(TlsAgent::CLIENT);
client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILED);
// The server might not receive the alert that the client sends, which would
// cause the test to fail when it cleans up. Reset expectations.
server_->ExpectReceiveAlert(kTlsAlertCloseNotify, kTlsAlertWarning);
}
TEST_P(TlsConnectGeneric, ClientAuth) {
client_->SetupClientAuth();
server_->RequestClientAuth(true);
@ -153,6 +267,81 @@ TEST_P(TlsConnectTls12, ClientAuthBigRsaCheckSigAlg) {
2048);
}
// Replaces the signature scheme in a CertificateVerify message.
class TlsReplaceSignatureSchemeFilter : public TlsHandshakeFilter {
public:
TlsReplaceSignatureSchemeFilter(const std::shared_ptr<TlsAgent>& a,
SSLSignatureScheme scheme)
: TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}),
scheme_(scheme) {
EnableDecryption();
}
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) {
*output = input;
output->Write(0, scheme_, 2);
return CHANGE;
}
private:
SSLSignatureScheme scheme_;
};
// Check if CertificateVerify signed with rsa_pss_rsae_* is properly
// rejected when the certificate is RSA-PSS.
//
// This only works under TLS 1.2, because PSS doesn't work with TLS
// 1.0 or TLS 1.1 and the TLS 1.3 1-RTT handshake is partially
// successful at the client side.
TEST_P(TlsConnectTls12, ClientAuthInconsistentRsaeSignatureScheme) {
static const SSLSignatureScheme kSignatureSchemePss[] = {
ssl_sig_rsa_pss_pss_sha256, ssl_sig_rsa_pss_rsae_sha256};
Reset(TlsAgent::kServerRsa, "rsa_pss");
client_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
server_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
client_->SetupClientAuth();
server_->RequestClientAuth(true);
EnsureTlsSetup();
MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(client_,
ssl_sig_rsa_pss_rsae_sha256);
ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
}
// Check if CertificateVerify signed with rsa_pss_pss_* is properly
// rejected when the certificate is RSA.
//
// This only works under TLS 1.2, because PSS doesn't work with TLS
// 1.0 or TLS 1.1 and the TLS 1.3 1-RTT handshake is partially
// successful at the client side.
TEST_P(TlsConnectTls12, ClientAuthInconsistentPssSignatureScheme) {
static const SSLSignatureScheme kSignatureSchemePss[] = {
ssl_sig_rsa_pss_rsae_sha256, ssl_sig_rsa_pss_pss_sha256};
Reset(TlsAgent::kServerRsa, "rsa");
client_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
server_->SetSignatureSchemes(kSignatureSchemePss,
PR_ARRAY_SIZE(kSignatureSchemePss));
client_->SetupClientAuth();
server_->RequestClientAuth(true);
EnsureTlsSetup();
MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(client_,
ssl_sig_rsa_pss_pss_sha256);
ConnectExpectAlert(server_, kTlsAlertIllegalParameter);
}
class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter {
public:
TlsZeroCertificateRequestSigAlgsFilter(const std::shared_ptr<TlsAgent>& a)
@ -197,9 +386,9 @@ class TlsZeroCertificateRequestSigAlgsFilter : public TlsHandshakeFilter {
}
};
// Check that we fall back to SHA-1 when the server doesn't provide any
// Check that we send an alert when the server doesn't provide any
// supported_signature_algorithms in the CertificateRequest message.
TEST_P(TlsConnectTls12, ClientAuthNoSigAlgsFallback) {
TEST_P(TlsConnectTls12, ClientAuthNoSigAlgs) {
EnsureTlsSetup();
MakeTlsFilter<TlsZeroCertificateRequestSigAlgsFilter>(server_);
auto capture_cert_verify = MakeTlsFilter<TlsHandshakeRecorder>(
@ -207,24 +396,19 @@ TEST_P(TlsConnectTls12, ClientAuthNoSigAlgsFallback) {
client_->SetupClientAuth();
server_->RequestClientAuth(true);
ConnectExpectAlert(server_, kTlsAlertDecryptError);
ConnectExpectAlert(client_, kTlsAlertHandshakeFailure);
// We're expecting a bad signature here because we tampered with a handshake
// message (CertReq). Previously, without the SHA-1 fallback, we would've
// seen a malformed record alert.
server_->CheckErrorCode(SEC_ERROR_BAD_SIGNATURE);
client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
CheckSigScheme(capture_cert_verify, 0, server_, ssl_sig_rsa_pkcs1_sha1, 1024);
server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT);
client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
}
static const SSLSignatureScheme SignatureSchemeEcdsaSha384[] = {
static const SSLSignatureScheme kSignatureSchemeEcdsaSha384[] = {
ssl_sig_ecdsa_secp384r1_sha384};
static const SSLSignatureScheme SignatureSchemeEcdsaSha256[] = {
static const SSLSignatureScheme kSignatureSchemeEcdsaSha256[] = {
ssl_sig_ecdsa_secp256r1_sha256};
static const SSLSignatureScheme SignatureSchemeRsaSha384[] = {
static const SSLSignatureScheme kSignatureSchemeRsaSha384[] = {
ssl_sig_rsa_pkcs1_sha384};
static const SSLSignatureScheme SignatureSchemeRsaSha256[] = {
static const SSLSignatureScheme kSignatureSchemeRsaSha256[] = {
ssl_sig_rsa_pkcs1_sha256};
static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) {
@ -241,10 +425,10 @@ static SSLNamedGroup NamedGroupForEcdsa384(uint16_t version) {
// for TLS 1.1 and 1.0, where they should be ignored.
TEST_P(TlsConnectGeneric, SignatureAlgorithmServerAuth) {
Reset(TlsAgent::kServerEcdsa384);
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
Connect();
CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa,
ssl_sig_ecdsa_secp384r1_sha384);
@ -273,8 +457,8 @@ TEST_P(TlsConnectGeneric, SignatureAlgorithmClientOnly) {
// Defaults on the client include the provided option.
TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) {
Reset(TlsAgent::kServerEcdsa384);
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
Connect();
CheckKeys(ssl_kea_ecdh, NamedGroupForEcdsa384(version_), ssl_auth_ecdsa,
ssl_sig_ecdsa_secp384r1_sha384);
@ -283,16 +467,16 @@ TEST_P(TlsConnectGeneric, SignatureAlgorithmServerOnly) {
// In TLS 1.2, curve and hash aren't bound together.
TEST_P(TlsConnectTls12, SignatureSchemeCurveMismatch) {
Reset(TlsAgent::kServerEcdsa256);
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
Connect();
}
// In TLS 1.3, curve and hash are coupled.
TEST_P(TlsConnectTls13, SignatureSchemeCurveMismatch) {
Reset(TlsAgent::kServerEcdsa256);
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
@ -301,16 +485,16 @@ TEST_P(TlsConnectTls13, SignatureSchemeCurveMismatch) {
// Configuring a P-256 cert with only SHA-384 signatures is OK in TLS 1.2.
TEST_P(TlsConnectTls12, SignatureSchemeBadConfig) {
Reset(TlsAgent::kServerEcdsa256); // P-256 cert can't be used.
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
Connect();
}
// A P-256 certificate in TLS 1.3 needs a SHA-256 signature scheme.
TEST_P(TlsConnectTls13, SignatureSchemeBadConfig) {
Reset(TlsAgent::kServerEcdsa256); // P-256 cert can't be used.
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
@ -319,10 +503,10 @@ TEST_P(TlsConnectTls13, SignatureSchemeBadConfig) {
// Where there is no overlap on signature schemes, we still connect successfully
// if we aren't going to use a signature.
TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) {
client_->SetSignatureSchemes(SignatureSchemeRsaSha384,
PR_ARRAY_SIZE(SignatureSchemeRsaSha384));
server_->SetSignatureSchemes(SignatureSchemeRsaSha256,
PR_ARRAY_SIZE(SignatureSchemeRsaSha256));
client_->SetSignatureSchemes(kSignatureSchemeRsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeRsaSha384));
server_->SetSignatureSchemes(kSignatureSchemeRsaSha256,
PR_ARRAY_SIZE(kSignatureSchemeRsaSha256));
EnableOnlyStaticRsaCiphers();
Connect();
CheckKeys(ssl_kea_rsa, ssl_auth_rsa_decrypt);
@ -330,10 +514,10 @@ TEST_P(TlsConnectGenericPre13, SignatureAlgorithmNoOverlapStaticRsa) {
TEST_P(TlsConnectTls12Plus, SignatureAlgorithmNoOverlapEcdsa) {
Reset(TlsAgent::kServerEcdsa256);
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha256,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha256));
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha256,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha256));
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
@ -342,10 +526,10 @@ TEST_P(TlsConnectTls12Plus, SignatureAlgorithmNoOverlapEcdsa) {
// Pre 1.2, a mismatch on signature algorithms shouldn't affect anything.
TEST_P(TlsConnectPre12, SignatureAlgorithmNoOverlapEcdsa) {
Reset(TlsAgent::kServerEcdsa256);
client_->SetSignatureSchemes(SignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha384));
server_->SetSignatureSchemes(SignatureSchemeEcdsaSha256,
PR_ARRAY_SIZE(SignatureSchemeEcdsaSha256));
client_->SetSignatureSchemes(kSignatureSchemeEcdsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha384));
server_->SetSignatureSchemes(kSignatureSchemeEcdsaSha256,
PR_ARRAY_SIZE(kSignatureSchemeEcdsaSha256));
Connect();
}
@ -366,29 +550,6 @@ TEST_P(TlsConnectTls12, SignatureAlgorithmDrop) {
server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}
// Replaces the signature scheme in a TLS 1.3 CertificateVerify message.
class TlsReplaceSignatureSchemeFilter : public TlsHandshakeFilter {
public:
TlsReplaceSignatureSchemeFilter(const std::shared_ptr<TlsAgent>& a,
SSLSignatureScheme scheme)
: TlsHandshakeFilter(a, {kTlsHandshakeCertificateVerify}),
scheme_(scheme) {
EnableDecryption();
}
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) {
*output = input;
output->Write(0, scheme_, 2);
return CHANGE;
}
private:
SSLSignatureScheme scheme_;
};
TEST_P(TlsConnectTls13, UnsupportedSignatureSchemeAlert) {
EnsureTlsSetup();
MakeTlsFilter<TlsReplaceSignatureSchemeFilter>(server_, ssl_sig_none);
@ -411,8 +572,8 @@ TEST_P(TlsConnectTls13, InconsistentSignatureSchemeAlert) {
}
TEST_P(TlsConnectTls12Plus, RequestClientAuthWithSha384) {
server_->SetSignatureSchemes(SignatureSchemeRsaSha384,
PR_ARRAY_SIZE(SignatureSchemeRsaSha384));
server_->SetSignatureSchemes(kSignatureSchemeRsaSha384,
PR_ARRAY_SIZE(kSignatureSchemeRsaSha384));
server_->RequestClientAuth(false);
Connect();
}
@ -438,7 +599,7 @@ class BeforeFinished : public TlsRecordFilter {
switch (state_) {
case BEFORE_CCS:
// Awaken when we see the CCS.
if (header.content_type() == kTlsChangeCipherSpecType) {
if (header.content_type() == ssl_ct_change_cipher_spec) {
before_ccs_();
// Write the CCS out as a separate write, so that we can make
@ -455,7 +616,7 @@ class BeforeFinished : public TlsRecordFilter {
break;
case AFTER_CCS:
EXPECT_EQ(kTlsHandshakeType, header.content_type());
EXPECT_EQ(ssl_ct_handshake, header.content_type());
// This could check that data contains a Finished message, but it's
// encrypted, so that's too much extra work.
@ -552,25 +713,11 @@ TEST_F(TlsConnectDatagram13, AuthCompleteBeforeFinished) {
Connect();
}
static void TriggerAuthComplete(PollTarget* target, Event event) {
std::cerr << "client: call SSL_AuthCertificateComplete" << std::endl;
EXPECT_EQ(TIMER_EVENT, event);
TlsAgent* client = static_cast<TlsAgent*>(target);
EXPECT_EQ(SECSuccess, SSL_AuthCertificateComplete(client->ssl_fd(), 0));
}
// This test uses a simple AuthCertificateCallback. Due to the way that the
// entire server flight is processed, the call to SSL_AuthCertificateComplete
// will trigger after the Finished message is processed.
TEST_F(TlsConnectDatagram13, AuthCompleteAfterFinished) {
client_->SetAuthCertificateCallback(
[this](TlsAgent*, PRBool, PRBool) -> SECStatus {
std::shared_ptr<Poller::Timer> timer_handle;
// This is really just to unroll the stack.
Poller::Instance()->SetTimer(1U, client_.get(), TriggerAuthComplete,
&timer_handle);
return SECWouldBlock;
});
SetDeferredAuthCertificateCallback(client_, 0); // 0 = success.
Connect();
}
@ -754,15 +901,15 @@ TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1SignAndKEX) {
PRFileDesc* ssl_fd = agent_->ssl_fd();
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt));
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign));
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
// Configuring for only rsa_sign, rsa_pss, or rsa_decrypt should work.
// Configuring for only rsa_sign or rsa_decrypt should work.
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
&ServerCertDataRsaPkcs1Decrypt));
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
&ServerCertDataRsaPkcs1Sign));
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
&ServerCertDataRsaPss));
EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsa, false,
&ServerCertDataRsaPss));
}
// Test RSA cert with usage=[signature].
@ -772,17 +919,17 @@ TEST_F(TlsAgentStreamTestServer, ConfigureCertRsaPkcs1Sign) {
PRFileDesc* ssl_fd = agent_->ssl_fd();
EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_decrypt));
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_sign));
EXPECT_TRUE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
EXPECT_FALSE(SSLInt_HasCertWithAuthType(ssl_fd, ssl_auth_rsa_pss));
// Configuring for only rsa_decrypt should fail.
EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
&ServerCertDataRsaPkcs1Decrypt));
// Configuring for only rsa_sign or rsa_pss should work.
// Configuring for only rsa_sign should work.
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
&ServerCertDataRsaPkcs1Sign));
EXPECT_TRUE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
&ServerCertDataRsaPss));
EXPECT_FALSE(agent_->ConfigServerCert(TlsAgent::kServerRsaSign, false,
&ServerCertDataRsaPss));
}
// Test RSA cert with usage=[encipherment].

View file

@ -84,6 +84,18 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
Reset(TlsAgent::kRsa2048);
auth_type_ = ssl_auth_rsa_sign;
break;
case ssl_sig_rsa_pss_pss_sha256:
Reset(TlsAgent::kServerRsaPss);
auth_type_ = ssl_auth_rsa_pss;
break;
case ssl_sig_rsa_pss_pss_sha384:
Reset("rsa_pss384");
auth_type_ = ssl_auth_rsa_pss;
break;
case ssl_sig_rsa_pss_pss_sha512:
Reset("rsa_pss512");
auth_type_ = ssl_auth_rsa_pss;
break;
case ssl_sig_ecdsa_secp256r1_sha256:
Reset(TlsAgent::kServerEcdsa256);
auth_type_ = ssl_auth_ecdsa;
@ -270,7 +282,7 @@ TEST_P(TlsCipherSuiteTest, ReadLimit) {
} else {
epoch = 0;
}
TlsAgentTestBase::MakeRecord(variant_, kTlsApplicationDataType, version_,
TlsAgentTestBase::MakeRecord(variant_, ssl_ct_application_data, version_,
payload, sizeof(payload), &record,
(epoch << 48) | record_limit());
client_->SendDirect(record);
@ -310,14 +322,13 @@ static const auto kDummyNamedGroupParams = ::testing::Values(ssl_grp_none);
static const auto kDummySignatureSchemesParams =
::testing::Values(ssl_sig_none);
#ifndef NSS_DISABLE_TLS_1_3
static SSLSignatureScheme kSignatureSchemesParamsArr[] = {
ssl_sig_rsa_pkcs1_sha256, ssl_sig_rsa_pkcs1_sha384,
ssl_sig_rsa_pkcs1_sha512, ssl_sig_ecdsa_secp256r1_sha256,
ssl_sig_ecdsa_secp384r1_sha384, ssl_sig_rsa_pss_rsae_sha256,
ssl_sig_rsa_pss_rsae_sha384, ssl_sig_rsa_pss_rsae_sha512,
};
#endif
ssl_sig_rsa_pss_pss_sha256, ssl_sig_rsa_pss_pss_sha384,
ssl_sig_rsa_pss_pss_sha512};
INSTANTIATE_CIPHER_TEST_P(RC4, Stream, V10ToV12, kDummyNamedGroupParams,
kDummySignatureSchemesParams,
@ -372,6 +383,14 @@ INSTANTIATE_CIPHER_TEST_P(
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
INSTANTIATE_CIPHER_TEST_P(
TLS12SigSchemes, All, V12, ::testing::ValuesIn(kFasterDHEGroups),
::testing::ValuesIn(kSignatureSchemesParamsArr),
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, TLS_RSA_WITH_AES_256_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,
TLS_DHE_DSS_WITH_AES_256_CBC_SHA256);
#ifndef NSS_DISABLE_TLS_1_3
INSTANTIATE_CIPHER_TEST_P(TLS13, All, V13,
::testing::ValuesIn(kFasterDHEGroups),

View file

@ -132,7 +132,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionEmptyWriterServer) {
// Sending extensions that the client doesn't expect leads to extensions
// appearing even if the client didn't send one, or in the wrong messages.
client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
}
@ -350,7 +350,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionUnsolicitedServer) {
auto capture = MakeTlsFilter<TlsExtensionCapture>(server_, extension_code);
client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_TRUE(capture->captured());
@ -401,7 +401,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionClientReject) {
EXPECT_EQ(SECSuccess, rv);
client_->ExpectSendAlert(kTlsAlertHandshakeFailure);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
}
@ -451,7 +451,7 @@ TEST_F(TlsConnectStreamTls13, CustomExtensionClientRejectAlert) {
EXPECT_EQ(SECSuccess, rv);
client_->ExpectSendAlert(kCustomAlert);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
}

View file

@ -17,7 +17,7 @@ extern "C" {
}
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

View file

@ -13,7 +13,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@ -643,4 +643,43 @@ TEST_P(TlsConnectGenericPre13, InvalidDERSignatureFfdhe) {
client_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}
// Replace SignatureAndHashAlgorithm of a SKE.
class DHEServerKEXSigAlgReplacer : public TlsHandshakeFilter {
public:
DHEServerKEXSigAlgReplacer(const std::shared_ptr<TlsAgent>& server,
SSLSignatureScheme sig_scheme)
: TlsHandshakeFilter(server, {kTlsHandshakeServerKeyExchange}),
sig_scheme_(sig_scheme) {}
protected:
virtual PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) {
*output = input;
uint32_t len;
uint32_t idx = 0;
EXPECT_TRUE(output->Read(idx, 2, &len));
idx += 2 + len;
EXPECT_TRUE(output->Read(idx, 2, &len));
idx += 2 + len;
EXPECT_TRUE(output->Read(idx, 2, &len));
idx += 2 + len;
output->Write(idx, sig_scheme_, 2);
return CHANGE;
}
private:
SSLSignatureScheme sig_scheme_;
};
TEST_P(TlsConnectTls12, ConnectInconsistentSigAlgDHE) {
EnableOnlyDheCiphers();
MakeTlsFilter<DHEServerKEXSigAlgReplacer>(server_,
ssl_sig_ecdsa_secp256r1_sha256);
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
}
} // namespace nss_test

View file

@ -14,7 +14,7 @@ extern "C" {
}
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@ -123,7 +123,7 @@ class TlsDropDatagram13 : public TlsConnectDatagram13,
void Init(const std::shared_ptr<TlsAgent>& agent) {
records_ = std::make_shared<TlsRecordRecorder>(agent);
ack_ = std::make_shared<TlsRecordRecorder>(agent, content_ack);
ack_ = std::make_shared<TlsRecordRecorder>(agent, ssl_ct_ack);
ack_->EnableDecryption();
drop_ = std::make_shared<SelectiveRecordDropFilter>(agent, 0, false);
chain_ = std::make_shared<ChainedPacketFilter>(
@ -670,7 +670,7 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderAppWithHandshakeKey) {
ASSERT_NE(nullptr, spec.get());
ASSERT_EQ(2, spec->epoch());
ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0x0002000000000002,
kTlsApplicationDataType,
ssl_ct_application_data,
DataBuffer(buf, sizeof(buf))));
// Now have the server consume the bogus message.
@ -696,7 +696,7 @@ TEST_P(TlsDropDatagram13, SendOutOfOrderHsNonsenseWithHandshakeKey) {
ASSERT_NE(nullptr, spec.get());
ASSERT_EQ(2, spec->epoch());
ASSERT_TRUE(client_->SendEncryptedRecord(spec, 0x0002000000000002,
kTlsHandshakeType,
ssl_ct_handshake,
DataBuffer(buf, sizeof(buf))));
server_->Handshake();
EXPECT_EQ(2UL, server_filters_.ack_->count());
@ -899,7 +899,7 @@ class TlsReplaceFirstRecordWithJunk : public TlsRecordFilter {
}
replaced_ = true;
TlsRecordHeader out_header(header.variant(), header.version(),
kTlsApplicationDataType,
ssl_ct_application_data,
header.sequence_number());
static const uint8_t junk[] = {1, 2, 3, 4};

View file

@ -17,7 +17,7 @@ extern "C" {
}
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

View file

@ -10,7 +10,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

View file

@ -9,6 +9,9 @@
#include "sslerr.h"
#include "sslproto.h"
// This is only to get DTLS_1_3_DRAFT_VERSION
#include "ssl3prot.h"
#include <memory>
#include "tls_connect.h"
@ -41,28 +44,6 @@ class TlsExtensionTruncator : public TlsExtensionFilter {
size_t length_;
};
class TlsExtensionDamager : public TlsExtensionFilter {
public:
TlsExtensionDamager(const std::shared_ptr<TlsAgent>& a, uint16_t extension,
size_t index)
: TlsExtensionFilter(a), extension_(extension), index_(index) {}
virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
const DataBuffer& input,
DataBuffer* output) {
if (extension_type != extension_) {
return KEEP;
}
*output = input;
output->data()[index_] += 73; // Increment selected for maximum damage
return CHANGE;
}
private:
uint16_t extension_;
size_t index_;
};
class TlsExtensionAppender : public TlsHandshakeFilter {
public:
TlsExtensionAppender(const std::shared_ptr<TlsAgent>& a,
@ -454,6 +435,25 @@ TEST_P(TlsExtensionTest12Plus, SignatureAlgorithmsOddLength) {
client_, ssl_signature_algorithms_xtn, extension));
}
TEST_F(TlsExtensionTest13Stream, SignatureAlgorithmsPrecedingGarbage) {
// 31 unknown signature algorithms followed by sha-256, rsa
const uint8_t val[] = {
0x00, 0x40, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x04, 0x01};
DataBuffer extension(val, sizeof(val));
MakeTlsFilter<TlsExtensionReplacer>(client_, ssl_signature_algorithms_xtn,
extension);
client_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
ConnectExpectFail();
client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}
TEST_P(TlsExtensionTestGeneric, NoSupportedGroups) {
ClientHelloErrorTest(
std::make_shared<TlsExtensionDropper>(client_, ssl_supported_groups_xtn),
@ -563,10 +563,10 @@ TEST_F(TlsExtensionTest13Stream, DropServerKeyShare) {
EnsureTlsSetup();
MakeTlsFilter<TlsExtensionDropper>(server_, ssl_tls13_key_share_xtn);
client_->ExpectSendAlert(kTlsAlertMissingExtension);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code());
EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) {
@ -583,13 +583,12 @@ TEST_F(TlsExtensionTest13Stream, WrongServerKeyShare) {
EnsureTlsSetup();
MakeTlsFilter<TlsExtensionReplacer>(server_, ssl_tls13_key_share_xtn, buf);
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_RX_MALFORMED_KEY_SHARE, client_->error_code());
EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
// TODO(ekr@rtfm.com): This is the wrong error code. See bug 1307269.
TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) {
const uint16_t wrong_group = 0xffff;
@ -603,11 +602,11 @@ TEST_F(TlsExtensionTest13Stream, UnknownServerKeyShare) {
DataBuffer buf(key_share, sizeof(key_share));
EnsureTlsSetup();
MakeTlsFilter<TlsExtensionReplacer>(server_, ssl_tls13_key_share_xtn, buf);
client_->ExpectSendAlert(kTlsAlertMissingExtension);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_MISSING_KEY_SHARE, client_->error_code());
EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
EXPECT_EQ(SSL_ERROR_RX_MALFORMED_KEY_SHARE, client_->error_code());
EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) {
@ -616,10 +615,10 @@ TEST_F(TlsExtensionTest13Stream, AddServerSignatureAlgorithmsOnResumption) {
MakeTlsFilter<TlsExtensionInjector>(server_, ssl_signature_algorithms_xtn,
empty);
client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_EXTENSION_DISALLOWED_FOR_VERSION, client_->error_code());
EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
struct PskIdentity {
@ -912,23 +911,32 @@ TEST_P(TlsExtensionTest13, RemoveTls13FromVersionListServerV12) {
// 3. Server supports 1.2 and 1.3, client supports 1.2 and 1.3
// but advertises 1.2 (because we changed things).
TEST_P(TlsExtensionTest13, RemoveTls13FromVersionListBothV12) {
client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
#ifndef TLS_1_3_DRAFT_VERSION
ExpectAlert(server_, kTlsAlertIllegalParameter);
#else
ExpectAlert(server_, kTlsAlertDecryptError);
// The downgrade check is disabled in DTLS 1.3, so all that happens when we
// tamper with the supported versions is that the Finished check fails.
#ifdef DTLS_1_3_DRAFT_VERSION
if (variant_ == ssl_variant_datagram) {
ExpectAlert(server_, kTlsAlertDecryptError);
} else
#endif
{
ExpectAlert(client_, kTlsAlertIllegalParameter);
}
ConnectWithReplacementVersionList(SSL_LIBRARY_VERSION_TLS_1_2);
#ifndef TLS_1_3_DRAFT_VERSION
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
#else
client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
#ifdef DTLS_1_3_DRAFT_VERSION
if (variant_ == ssl_variant_datagram) {
client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
} else
#endif
{
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
}
TEST_P(TlsExtensionTest13, HrrThenRemoveSignatureAlgorithms) {
@ -1017,7 +1025,7 @@ class TlsBogusExtensionTest13 : public TlsBogusExtensionTest {
client_->ExpectSendAlert(alert);
client_->Handshake();
if (variant_ == ssl_variant_stream) {
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
}
server_->Handshake();
}

View file

@ -10,7 +10,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@ -106,8 +106,8 @@ class RecordFragmenter : public PacketFilter {
}
// Just rewrite the sequence number (CCS only).
if (header.content_type() != kTlsHandshakeType) {
EXPECT_EQ(kTlsChangeCipherSpecType, header.content_type());
if (header.content_type() != ssl_ct_handshake) {
EXPECT_EQ(ssl_ct_change_cipher_spec, header.content_type());
WriteRecord(header, record);
continue;
}

View file

@ -33,7 +33,7 @@ class TlsApplicationDataRecorder : public TlsRecordFilter {
virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& input,
DataBuffer* output) {
if (header.content_type() == kTlsApplicationDataType) {
if (header.content_type() == ssl_ct_application_data) {
buffer_.Append(input);
}

View file

@ -15,6 +15,7 @@ class GatherV2ClientHelloTest : public TlsConnectTestBase {
void ConnectExpectMalformedClientHello(const DataBuffer &data) {
EnsureTlsSetup();
server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_TRUE);
server_->ExpectSendAlert(kTlsAlertIllegalParameter);
client_->SendDirect(data);
server_->StartConnect();

View file

@ -51,6 +51,7 @@
'tls_connect.cc',
'tls_filter.cc',
'tls_hkdf_unittest.cc',
'tls_esni_unittest.cc',
'tls_protect.cc'
],
'dependencies': [

View file

@ -9,11 +9,11 @@
#include "sslerr.h"
#include "sslproto.h"
// This is internal, just to get TLS_1_3_DRAFT_VERSION.
// This is internal, just to get DTLS_1_3_DRAFT_VERSION.
#include "ssl3prot.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@ -76,7 +76,7 @@ class CorrectMessageSeqAfterHrrFilter : public TlsRecordFilter {
PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& record, size_t* offset,
DataBuffer* output) {
if (filtered_packets() > 0 || header.content_type() != content_handshake) {
if (filtered_packets() > 0 || header.content_type() != ssl_ct_handshake) {
return KEEP;
}
@ -718,6 +718,86 @@ TEST_F(TlsConnectStreamTls13, RetryStatelessDamageSecondClientHello) {
client_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}
// Stream because SSL_SendSessionTicket only supports that.
TEST_F(TlsConnectStreamTls13, SecondClientHelloSendSameTicket) {
// This simulates the scenario described at:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1481271#c7
//
// Here two connections are interleaved. Tickets are issued on one
// connection. A HelloRetryRequest is triggered on the second connection,
// meaning that there are two ClientHellos. We need to check that both
// ClientHellos have the same ticket, even if a new ticket is issued on the
// other connection in the meantime.
//
// Connection 1: <handshake>
// Connection 1: S->C: NST=X
// Connection 2: C->S: CH [PSK_ID=X]
// Connection 1: S->C: NST=Y
// Connection 2: S->C: HRR
// Connection 2: C->S: CH [PSK_ID=Y]
// Connection 1, send a ticket after handshake is complete.
ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
Connect();
// Set this token so that RetryHelloWithToken() will check that this
// is the token that it receives in the HelloRetryRequest callback.
EXPECT_EQ(SECSuccess,
SSL_SendSessionTicket(server_->ssl_fd(), kApplicationToken,
sizeof(kApplicationToken)));
SendReceive(50);
// Connection 2, trigger HRR.
auto client2 =
std::make_shared<TlsAgent>(client_->name(), TlsAgent::CLIENT, variant_);
auto server2 =
std::make_shared<TlsAgent>(server_->name(), TlsAgent::SERVER, variant_);
client2->SetPeer(server2);
server2->SetPeer(client2);
client_.swap(client2);
server_.swap(server2);
ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
client_->StartConnect();
server_->StartConnect();
size_t cb_called = 0;
EXPECT_EQ(SECSuccess,
SSL_HelloRetryRequestCallback(server_->ssl_fd(),
RetryHelloWithToken, &cb_called));
client_->Handshake(); // Send ClientHello.
server_->Handshake(); // Process ClientHello, send HelloRetryRequest.
EXPECT_EQ(1U, cb_called) << "callback should be called once here";
// Connection 1, send another ticket.
client_.swap(client2);
server_.swap(server2);
// If the client uses this token, RetryHelloWithToken() will fail the test.
const uint8_t kAnotherApplicationToken[] = {0x92, 0x44, 0x01};
EXPECT_EQ(SECSuccess,
SSL_SendSessionTicket(server_->ssl_fd(), kAnotherApplicationToken,
sizeof(kAnotherApplicationToken)));
SendReceive(60);
// Connection 2, continue the handshake.
// The client should use kApplicationToken, not kAnotherApplicationToken.
client_.swap(client2);
server_.swap(server2);
client_->Handshake();
server_->Handshake();
EXPECT_EQ(2U, cb_called) << "callback should be called twice here";
}
// Read the cipher suite from the HRR and disable it on the identified agent.
static void DisableSuiteFromHrr(
std::shared_ptr<TlsAgent>& agent,
@ -844,10 +924,10 @@ TEST_F(TlsConnectStreamTls13, RetryWithDifferentCipherSuite) {
TLS_CHACHA20_POLY1305_SHA256);
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
EXPECT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
EXPECT_EQ(SSL_ERROR_BAD_MAC_READ, server_->error_code());
EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
// This tests that the second attempt at sending a ClientHello (after receiving
@ -1007,14 +1087,17 @@ class HelloRetryRequestAgentTest : public TlsAgentTestClient {
// Now the supported version.
i = hrr_data.Write(i, ssl_tls13_supported_versions_xtn, 2);
i = hrr_data.Write(i, 2, 2);
i = hrr_data.Write(i, 0x7f00 | TLS_1_3_DRAFT_VERSION, 2);
i = hrr_data.Write(i, (variant_ == ssl_variant_datagram)
? (0x7f00 | DTLS_1_3_DRAFT_VERSION)
: SSL_LIBRARY_VERSION_TLS_1_3,
2);
if (len) {
hrr_data.Write(i, body, len);
}
DataBuffer hrr;
MakeHandshakeMessage(kTlsHandshakeServerHello, hrr_data.data(),
hrr_data.len(), &hrr, seq_num);
MakeRecord(kTlsHandshakeType, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(),
MakeRecord(ssl_ct_handshake, SSL_LIBRARY_VERSION_TLS_1_3, hrr.data(),
hrr.len(), hrr_record, seq_num);
}

View file

@ -15,7 +15,7 @@ extern "C" {
}
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

View file

@ -18,7 +18,7 @@ extern "C" {
}
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@ -65,7 +65,7 @@ class TlsAlertRecorder : public TlsRecordFilter {
if (level_ != 255) { // Already captured.
return KEEP;
}
if (header.content_type() != kTlsAlertType) {
if (header.content_type() != ssl_ct_alert) {
return KEEP;
}
@ -130,7 +130,7 @@ TEST_P(TlsConnectTls13, CaptureAlertClient) {
client_->Handshake();
if (variant_ == ssl_variant_stream) {
// DTLS just drops the alert it can't decrypt.
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
}
server_->Handshake();
EXPECT_EQ(kTlsAlertFatal, alert_recorder->level());
@ -320,6 +320,53 @@ TEST_F(TlsConnectStreamTls13, DropRecordClient) {
SendReceive();
}
// Check that a server can use 0.5 RTT if client authentication isn't enabled.
TEST_P(TlsConnectTls13, WriteBeforeClientFinished) {
EnsureTlsSetup();
StartConnect();
client_->Handshake(); // ClientHello
server_->Handshake(); // ServerHello
server_->SendData(10);
client_->ReadBytes(10); // Client should emit the Finished as a side-effect.
server_->Handshake(); // Server consumes the Finished.
CheckConnected();
}
// We don't allow 0.5 RTT if client authentication is requested.
TEST_P(TlsConnectTls13, WriteBeforeClientFinishedClientAuth) {
client_->SetupClientAuth();
server_->RequestClientAuth(false);
StartConnect();
client_->Handshake(); // ClientHello
server_->Handshake(); // ServerHello
static const uint8_t data[] = {1, 2, 3};
EXPECT_GT(0, PR_Write(server_->ssl_fd(), data, sizeof(data)));
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
Handshake();
CheckConnected();
SendReceive();
}
// 0.5 RTT should fail with client authentication required.
TEST_P(TlsConnectTls13, WriteBeforeClientFinishedClientAuthRequired) {
client_->SetupClientAuth();
server_->RequestClientAuth(true);
StartConnect();
client_->Handshake(); // ClientHello
server_->Handshake(); // ServerHello
static const uint8_t data[] = {1, 2, 3};
EXPECT_GT(0, PR_Write(server_->ssl_fd(), data, sizeof(data)));
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
Handshake();
CheckConnected();
SendReceive();
}
// The next two tests takes advantage of the fact that we
// automatically read the first 1024 bytes, so if
// we provide 1200 bytes, they overrun the read buffer
@ -426,13 +473,15 @@ class TlsPreCCSHeaderInjector : public TlsRecordFilter {
virtual PacketFilter::Action FilterRecord(
const TlsRecordHeader& record_header, const DataBuffer& input,
size_t* offset, DataBuffer* output) override {
if (record_header.content_type() != kTlsChangeCipherSpecType) return KEEP;
if (record_header.content_type() != ssl_ct_change_cipher_spec) {
return KEEP;
}
std::cerr << "Injecting Finished header before CCS\n";
const uint8_t hhdr[] = {kTlsHandshakeFinished, 0x00, 0x00, 0x0c};
DataBuffer hhdr_buf(hhdr, sizeof(hhdr));
TlsRecordHeader nhdr(record_header.variant(), record_header.version(),
kTlsHandshakeType, 0);
ssl_ct_handshake, 0);
*offset = nhdr.Write(output, *offset, hhdr_buf);
*offset = record_header.Write(output, *offset, input);
return CHANGE;
@ -477,6 +526,26 @@ TEST_P(TlsConnectTls13, AlertWrongLevel) {
client_->WaitForErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT, 2000);
}
TEST_P(TlsConnectTls13, UnknownRecord) {
static const uint8_t kUknownRecord[] = {
0xff, SSL_LIBRARY_VERSION_TLS_1_2 >> 8,
SSL_LIBRARY_VERSION_TLS_1_2 & 0xff, 0, 0};
Connect();
if (variant_ == ssl_variant_stream) {
// DTLS just drops the record with an invalid type.
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
}
client_->SendDirect(DataBuffer(kUknownRecord, sizeof(kUknownRecord)));
server_->ExpectReadWriteError();
server_->ReadBytes();
if (variant_ == ssl_variant_stream) {
EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
} else {
EXPECT_EQ(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, server_->error_code());
}
}
TEST_F(TlsConnectStreamTls13, Tls13FailedWriteSecondFlight) {
EnsureTlsSetup();
StartConnect();
@ -539,6 +608,126 @@ TEST_F(TlsConnectTest, OneNRecordSplitting) {
EXPECT_EQ(ExpectedCbcLen(20), records->record(2).buffer.len());
}
// We can't test for randomness easily here, but we can test that we don't
// produce a zero value, or produce the same value twice. There are 5 values
// here: two ClientHello.random, two ServerHello.random, and one zero value.
// Matrix them and fail if any are the same.
TEST_P(TlsConnectGeneric, CheckRandoms) {
ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
static const size_t random_len = 32;
uint8_t crandom1[random_len], srandom1[random_len];
uint8_t z[random_len] = {0};
auto ch = MakeTlsFilter<TlsHandshakeRecorder>(client_, ssl_hs_client_hello);
auto sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
Connect();
ASSERT_TRUE(ch->buffer().len() > (random_len + 2));
ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
memcpy(crandom1, ch->buffer().data() + 2, random_len);
memcpy(srandom1, sh->buffer().data() + 2, random_len);
EXPECT_NE(0, memcmp(crandom1, srandom1, random_len));
EXPECT_NE(0, memcmp(crandom1, z, random_len));
EXPECT_NE(0, memcmp(srandom1, z, random_len));
Reset();
ch = MakeTlsFilter<TlsHandshakeRecorder>(client_, ssl_hs_client_hello);
sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
Connect();
ASSERT_TRUE(ch->buffer().len() > (random_len + 2));
ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
const uint8_t* crandom2 = ch->buffer().data() + 2;
const uint8_t* srandom2 = sh->buffer().data() + 2;
EXPECT_NE(0, memcmp(crandom2, srandom2, random_len));
EXPECT_NE(0, memcmp(crandom2, z, random_len));
EXPECT_NE(0, memcmp(srandom2, z, random_len));
EXPECT_NE(0, memcmp(crandom1, crandom2, random_len));
EXPECT_NE(0, memcmp(crandom1, srandom2, random_len));
EXPECT_NE(0, memcmp(srandom1, crandom2, random_len));
EXPECT_NE(0, memcmp(srandom1, srandom2, random_len));
}
void FailOnCloseNotify(const PRFileDesc* fd, void* arg, const SSLAlert* alert) {
ADD_FAILURE() << "received alert " << alert->description;
}
void CheckCloseNotify(const PRFileDesc* fd, void* arg, const SSLAlert* alert) {
*reinterpret_cast<bool*>(arg) = true;
EXPECT_EQ(close_notify, alert->description);
EXPECT_EQ(alert_warning, alert->level);
}
TEST_P(TlsConnectGeneric, ShutdownOneSide) {
Connect();
// Setup to check alerts.
EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(server_->ssl_fd(),
FailOnCloseNotify, nullptr));
EXPECT_EQ(SECSuccess, SSL_AlertReceivedCallback(client_->ssl_fd(),
FailOnCloseNotify, nullptr));
bool client_sent = false;
EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(client_->ssl_fd(),
CheckCloseNotify, &client_sent));
bool server_received = false;
EXPECT_EQ(SECSuccess,
SSL_AlertReceivedCallback(server_->ssl_fd(), CheckCloseNotify,
&server_received));
EXPECT_EQ(PR_SUCCESS, PR_Shutdown(client_->ssl_fd(), PR_SHUTDOWN_SEND));
// Make sure that the server reads out the close_notify.
uint8_t buf[10];
EXPECT_EQ(0, PR_Read(server_->ssl_fd(), buf, sizeof(buf)));
// Reading and writing should still work in the one open direction.
EXPECT_TRUE(client_sent);
EXPECT_TRUE(server_received);
server_->SendData(10, 10);
client_->ReadBytes(10);
// Now close the other side and do the same checks.
bool server_sent = false;
EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(server_->ssl_fd(),
CheckCloseNotify, &server_sent));
bool client_received = false;
EXPECT_EQ(SECSuccess,
SSL_AlertReceivedCallback(client_->ssl_fd(), CheckCloseNotify,
&client_received));
EXPECT_EQ(PR_SUCCESS, PR_Shutdown(server_->ssl_fd(), PR_SHUTDOWN_SEND));
EXPECT_EQ(0, PR_Read(client_->ssl_fd(), buf, sizeof(buf)));
EXPECT_TRUE(server_sent);
EXPECT_TRUE(client_received);
}
TEST_P(TlsConnectGeneric, ShutdownOneSideThenCloseTcp) {
Connect();
bool client_sent = false;
EXPECT_EQ(SECSuccess, SSL_AlertSentCallback(client_->ssl_fd(),
CheckCloseNotify, &client_sent));
bool server_received = false;
EXPECT_EQ(SECSuccess,
SSL_AlertReceivedCallback(server_->ssl_fd(), CheckCloseNotify,
&server_received));
EXPECT_EQ(PR_SUCCESS, PR_Shutdown(client_->ssl_fd(), PR_SHUTDOWN_SEND));
// Make sure that the server reads out the close_notify.
uint8_t buf[10];
EXPECT_EQ(0, PR_Read(server_->ssl_fd(), buf, sizeof(buf)));
// Now simulate the underlying connection closing.
client_->adapter()->Reset();
// Now close the other side and see that things don't explode.
EXPECT_EQ(PR_SUCCESS, PR_Shutdown(server_->ssl_fd(), PR_SHUTDOWN_SEND));
EXPECT_GT(0, PR_Read(client_->ssl_fd(), buf, sizeof(buf)));
EXPECT_EQ(PR_NOT_CONNECTED_ERROR, PR_GetError());
}
INSTANTIATE_TEST_CASE_P(
GenericStream, TlsConnectGeneric,
::testing::Combine(TlsConnectTestBase::kTlsVariantsStream,

View file

@ -111,7 +111,7 @@ class RecordReplacer : public TlsRecordFilter {
PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& data,
DataBuffer* changed) override {
EXPECT_EQ(kTlsApplicationDataType, header.content_type());
EXPECT_EQ(ssl_ct_application_data, header.content_type());
changed->Allocate(size_);
for (size_t i = 0; i < size_; ++i) {

View file

@ -10,7 +10,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@ -34,7 +34,7 @@ class TlsRecordMaximum : public TlsRecordFilter {
DataBuffer* output) override {
std::cerr << "max: " << record << std::endl;
// Ignore unprotected packets.
if (header.content_type() != kTlsApplicationDataType) {
if (header.content_type() != ssl_ct_application_data) {
return KEEP;
}
@ -187,7 +187,7 @@ class TlsRecordExpander : public TlsRecordFilter {
virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& data,
DataBuffer* changed) {
if (header.content_type() != kTlsApplicationDataType) {
if (header.content_type() != ssl_ct_application_data) {
return KEEP;
}
changed->Allocate(data.len() + expansion_);
@ -252,7 +252,7 @@ class TlsRecordPadder : public TlsRecordFilter {
PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& record, size_t* offset,
DataBuffer* output) override {
if (header.content_type() != kTlsApplicationDataType) {
if (header.content_type() != ssl_ct_application_data) {
return KEEP;
}
@ -262,7 +262,7 @@ class TlsRecordPadder : public TlsRecordFilter {
return KEEP;
}
if (inner_content_type != kTlsApplicationDataType) {
if (inner_content_type != ssl_ct_application_data) {
return KEEP;
}

View file

@ -18,7 +18,8 @@ extern "C" {
}
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "scoped_ptrs_ssl.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@ -171,23 +172,145 @@ TEST_P(TlsConnectGenericResumption, ConnectResumeClientNoneServerBoth) {
SendReceive();
}
TEST_P(TlsConnectGenericPre13, ConnectResumeWithHigherVersion) {
TEST_P(TlsConnectGenericPre13, ResumeWithHigherVersionTls13) {
uint16_t lower_version = version_;
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
Connect();
SendReceive();
CheckKeys();
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
EnsureTlsSetup();
auto psk_ext = std::make_shared<TlsExtensionCapture>(
client_, ssl_tls13_pre_shared_key_xtn);
auto ticket_ext =
std::make_shared<TlsExtensionCapture>(client_, ssl_session_ticket_xtn);
client_->SetFilter(std::make_shared<ChainedPacketFilter>(
ChainedPacketFilterInit({psk_ext, ticket_ext})));
SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3);
client_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
ExpectResumption(RESUME_NONE);
Connect();
// The client shouldn't have sent a PSK, though it will send a ticket.
EXPECT_FALSE(psk_ext->captured());
EXPECT_TRUE(ticket_ext->captured());
}
class CaptureSessionId : public TlsHandshakeFilter {
public:
CaptureSessionId(const std::shared_ptr<TlsAgent>& a)
: TlsHandshakeFilter(
a, {kTlsHandshakeClientHello, kTlsHandshakeServerHello}),
sid_() {}
const DataBuffer& sid() const { return sid_; }
protected:
PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
const DataBuffer& input,
DataBuffer* output) override {
// The session_id is in the same place in both Hello messages:
size_t offset = 2 + 32; // Version(2) + Random(32)
uint32_t len = 0;
EXPECT_TRUE(input.Read(offset, 1, &len));
offset++;
if (input.len() < offset + len) {
ADD_FAILURE() << "session_id overflows the Hello message";
return KEEP;
}
sid_.Assign(input.data() + offset, len);
return KEEP;
}
private:
DataBuffer sid_;
};
// Attempting to resume from TLS 1.2 when 1.3 is possible should not result in
// resumption, though it will appear to be TLS 1.3 compatibility mode if the
// server uses a session ID.
TEST_P(TlsConnectGenericPre13, ResumeWithHigherVersionTls13SessionId) {
uint16_t lower_version = version_;
ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_1);
SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_1);
auto original_sid = MakeTlsFilter<CaptureSessionId>(server_);
Connect();
CheckKeys();
EXPECT_EQ(32U, original_sid->sid().len());
// The client should now attempt to resume with the session ID from the last
// connection. This looks like compatibility mode, we just want to ensure
// that we get TLS 1.3 rather than 1.2 (and no resumption).
Reset();
auto client_sid = MakeTlsFilter<CaptureSessionId>(client_);
auto server_sid = MakeTlsFilter<CaptureSessionId>(server_);
ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3);
client_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
ExpectResumption(RESUME_NONE);
Connect();
SendReceive();
EXPECT_EQ(client_sid->sid(), original_sid->sid());
if (variant_ == ssl_variant_stream) {
EXPECT_EQ(client_sid->sid(), server_sid->sid());
} else {
// DTLS servers don't echo the session ID.
EXPECT_EQ(0U, server_sid->sid().len());
}
}
TEST_P(TlsConnectPre12, ResumeWithHigherVersionTls12) {
uint16_t lower_version = version_;
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
Connect();
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
EnsureTlsSetup();
SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_2);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_2);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_2);
SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_3);
client_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(lower_version, SSL_LIBRARY_VERSION_TLS_1_3);
ExpectResumption(RESUME_NONE);
Connect();
}
TEST_P(TlsConnectGenericPre13, ResumeWithLowerVersionFromTls13) {
uint16_t original_version = version_;
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
Connect();
SendReceive();
CheckKeys();
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ConfigureVersion(original_version);
ExpectResumption(RESUME_NONE);
Connect();
SendReceive();
}
TEST_P(TlsConnectPre12, ResumeWithLowerVersionFromTls12) {
uint16_t original_version = version_;
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_2);
Connect();
SendReceive();
CheckKeys();
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ConfigureVersion(original_version);
ExpectResumption(RESUME_NONE);
Connect();
SendReceive();
}
TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicketForget) {
// This causes a ticket resumption.
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
@ -276,8 +399,13 @@ TEST_P(TlsConnectGeneric, ConnectResumeCorruptTicket) {
ASSERT_NE(nullptr, hmac_key);
SSLInt_SetSelfEncryptMacKey(hmac_key);
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
ConnectExpectAlert(server_, illegal_parameter);
server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
ExpectResumption(RESUME_NONE);
Connect();
} else {
ConnectExpectAlert(server_, illegal_parameter);
server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}
}
// This callback switches out the "server" cert used on the server with
@ -394,6 +522,64 @@ TEST_P(TlsConnectTls13, TestTls13ResumeDifferentGroup) {
ssl_sig_rsa_pss_rsae_sha256);
}
// Verify that TLS 1.3 server doesn't request certificate in the main
// handshake, after resumption.
TEST_P(TlsConnectTls13, TestTls13ResumeNoCertificateRequest) {
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
client_->SetupClientAuth();
server_->RequestClientAuth(true);
Connect();
SendReceive(); // Need to read so that we absorb the session ticket.
ScopedCERTCertificate cert1(SSL_LocalCertificate(client_->ssl_fd()));
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
ExpectResumption(RESUME_TICKET);
server_->RequestClientAuth(false);
auto cr_capture =
MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_certificate_request);
cr_capture->EnableDecryption();
Connect();
SendReceive();
EXPECT_EQ(0U, cr_capture->buffer().len()) << "expect nothing captured yet";
// Sanity check whether the client certificate matches the one
// decrypted from ticket.
ScopedCERTCertificate cert2(SSL_PeerCertificate(server_->ssl_fd()));
EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
}
// Here we test that 0.5 RTT is available at the server when resuming, even if
// configured to request a client certificate. The resumed handshake relies on
// the authentication from the original handshake, so no certificate is
// requested this time around. The server can write before the handshake
// completes because the PSK binder is sufficient authentication for the client.
TEST_P(TlsConnectTls13, WriteBeforeHandshakeCompleteOnResumption) {
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
client_->SetupClientAuth();
server_->RequestClientAuth(true);
Connect();
SendReceive(); // Absorb the session ticket.
ScopedCERTCertificate cert1(SSL_LocalCertificate(client_->ssl_fd()));
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
ExpectResumption(RESUME_TICKET);
server_->RequestClientAuth(false);
StartConnect();
client_->Handshake(); // ClientHello
server_->Handshake(); // ServerHello
server_->SendData(10);
client_->ReadBytes(10); // Client should emit the Finished as a side-effect.
server_->Handshake(); // Server consumes the Finished.
CheckConnected();
// Check whether the client certificate matches the one from the ticket.
ScopedCERTCertificate cert2(SSL_PeerCertificate(server_->ssl_fd()));
EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
}
// We need to enable different cipher suites at different times in the following
// tests. Those cipher suites need to be suited to the version.
static uint16_t ChooseOneCipher(uint16_t version) {
@ -467,7 +653,7 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) {
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
} else {
ExpectAlert(client_, kTlsAlertHandshakeFailure);
}
@ -476,7 +662,7 @@ TEST_P(TlsConnectStream, TestResumptionOverrideCipher) {
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
// The reason this test is stream only: the server is unable to decrypt
// the alert that the client sends, see bug 1304603.
server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE);
} else {
server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT);
}
@ -760,6 +946,36 @@ TEST_F(TlsConnectDatagram13, SendSessionTicketDtls) {
EXPECT_EQ(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, PORT_GetError());
}
TEST_F(TlsConnectStreamTls13, ExternalResumptionUseSecondTicket) {
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
struct ResumptionTicketState {
std::vector<uint8_t> ticket;
size_t invoked = 0;
} ticket_state;
auto cb = [](PRFileDesc* fd, const PRUint8* ticket, unsigned int ticket_len,
void* arg) -> SECStatus {
auto state = reinterpret_cast<ResumptionTicketState*>(arg);
state->ticket.assign(ticket, ticket + ticket_len);
state->invoked++;
return SECSuccess;
};
SSL_SetResumptionTokenCallback(client_->ssl_fd(), cb, &ticket_state);
Connect();
EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), nullptr, 0));
SendReceive();
EXPECT_EQ(2U, ticket_state.invoked);
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
client_->SetResumptionToken(ticket_state.ticket);
ExpectResumption(RESUME_TICKET);
Connect();
SendReceive();
}
TEST_F(TlsConnectTest, TestTls13ResumptionDowngrade) {
ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
@ -830,10 +1046,10 @@ TEST_F(TlsConnectTest, TestTls13ResumptionForcedDowngrade) {
// client expects to receive an unencrypted TLS 1.2 Certificate message.
// The server can't decrypt the alert.
client_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
server_->ExpectSendAlert(kTlsAlertBadRecordMac); // Server can't read
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage); // Server can't read
ConnectExpectFail();
client_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA);
server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE);
}
TEST_P(TlsConnectGenericResumption, ReConnectTicket) {
@ -908,6 +1124,36 @@ void CheckGetInfoResult(uint32_t alpnSize, uint32_t earlyDataSize,
EXPECT_EQ(0, memcmp("a", token->alpnSelection, token->alpnSelectionLen));
ASSERT_EQ(earlyDataSize, token->maxEarlyDataSize);
ASSERT_LT(ssl_TimeUsec(), token->expirationTime);
}
// The client should generate a new, randomized session_id
// when resuming using an external token.
TEST_P(TlsConnectGenericResumptionToken, CheckSessionId) {
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
auto original_sid = MakeTlsFilter<CaptureSessionId>(client_);
Connect();
SendReceive();
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ExpectResumption(RESUME_TICKET);
StartConnect();
ASSERT_TRUE(client_->MaybeSetResumptionToken());
auto resumed_sid = MakeTlsFilter<CaptureSessionId>(client_);
Handshake();
CheckConnected();
SendReceive();
if (version_ < SSL_LIBRARY_VERSION_TLS_1_3) {
EXPECT_NE(resumed_sid->sid(), original_sid->sid());
EXPECT_EQ(32U, resumed_sid->sid().len());
} else {
EXPECT_EQ(0U, resumed_sid->sid().len());
}
}
TEST_P(TlsConnectGenericResumptionToken, ConnectResumeGetInfo) {
@ -1026,4 +1272,34 @@ TEST_P(TlsConnectGenericResumption, ConnectResumeClientAuth) {
SendReceive();
}
TEST_F(TlsConnectStreamTls13, ExternalTokenAfterHrr) {
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
Connect();
SendReceive();
Reset();
ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
ExpectResumption(RESUME_TICKET);
static const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1,
ssl_grp_ec_secp521r1};
server_->ConfigNamedGroups(groups);
StartConnect();
ASSERT_TRUE(client_->MaybeSetResumptionToken());
client_->Handshake(); // Send ClientHello.
server_->Handshake(); // Process ClientHello, send HelloRetryRequest.
auto& token = client_->GetResumptionToken();
SECStatus rv =
SSL_SetResumptionToken(client_->ssl_fd(), token.data(), token.size());
ASSERT_EQ(SECFailure, rv);
ASSERT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
Handshake();
CheckConnected();
SendReceive();
}
} // namespace nss_test

View file

@ -32,7 +32,7 @@ class TlsHandshakeSkipFilter : public TlsRecordFilter {
virtual PacketFilter::Action FilterRecord(
const TlsRecordHeader& record_header, const DataBuffer& input,
DataBuffer* output) {
if (record_header.content_type() != kTlsHandshakeType) {
if (record_header.content_type() != ssl_ct_handshake) {
return KEEP;
}

View file

@ -17,7 +17,7 @@ extern "C" {
}
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

View file

@ -82,7 +82,7 @@ class Tls13CompatTest : public TlsConnectStreamTls13 {
// Only the second record can be a CCS.
bool expected_match = expected && (i == 1);
EXPECT_EQ(expected_match,
kTlsChangeCipherSpecType ==
ssl_ct_change_cipher_spec ==
records_->record(i).header.content_type());
}
}
@ -299,15 +299,15 @@ TEST_F(TlsConnectTest, TLS13NonCompatModeSessionID) {
MakeTlsFilter<TlsSessionIDInjectFilter>(server_);
client_->ExpectSendAlert(kTlsAlertIllegalParameter);
server_->ExpectSendAlert(kTlsAlertBadRecordMac);
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
ConnectExpectFail();
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE);
}
static const uint8_t kCannedCcs[] = {
kTlsChangeCipherSpecType,
ssl_ct_change_cipher_spec,
SSL_LIBRARY_VERSION_TLS_1_2 >> 8,
SSL_LIBRARY_VERSION_TLS_1_2 & 0xff,
0,
@ -362,6 +362,19 @@ TEST_F(TlsConnectStreamTls13, ChangeCipherSpecBeforeClientHello12) {
client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
}
TEST_F(TlsConnectStreamTls13, ChangeCipherSpecAfterFinished13) {
EnsureTlsSetup();
ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
Connect();
SendReceive(10);
// Client sends CCS after the handshake.
client_->SendDirect(DataBuffer(kCannedCcs, sizeof(kCannedCcs)));
server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
server_->ExpectReadWriteError();
server_->ReadBytes();
EXPECT_EQ(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE, server_->error_code());
}
TEST_F(TlsConnectDatagram13, CompatModeDtlsClient) {
EnsureTlsSetup();
client_->SetOption(SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE);
@ -370,14 +383,14 @@ TEST_F(TlsConnectDatagram13, CompatModeDtlsClient) {
Connect();
ASSERT_EQ(2U, client_records->count()); // CH, Fin
EXPECT_EQ(kTlsHandshakeType, client_records->record(0).header.content_type());
EXPECT_EQ(kTlsApplicationDataType,
EXPECT_EQ(ssl_ct_handshake, client_records->record(0).header.content_type());
EXPECT_EQ(ssl_ct_application_data,
client_records->record(1).header.content_type());
ASSERT_EQ(6U, server_records->count()); // SH, EE, CT, CV, Fin, Ack
EXPECT_EQ(kTlsHandshakeType, server_records->record(0).header.content_type());
EXPECT_EQ(ssl_ct_handshake, server_records->record(0).header.content_type());
for (size_t i = 1; i < server_records->count(); ++i) {
EXPECT_EQ(kTlsApplicationDataType,
EXPECT_EQ(ssl_ct_application_data,
server_records->record(i).header.content_type());
}
}
@ -422,12 +435,12 @@ TEST_F(TlsConnectDatagram13, CompatModeDtlsServer) {
client_->Handshake();
ASSERT_EQ(1U, client_records->count());
EXPECT_EQ(kTlsHandshakeType, client_records->record(0).header.content_type());
EXPECT_EQ(ssl_ct_handshake, client_records->record(0).header.content_type());
ASSERT_EQ(5U, server_records->count()); // SH, EE, CT, CV, Fin
EXPECT_EQ(kTlsHandshakeType, server_records->record(0).header.content_type());
EXPECT_EQ(ssl_ct_handshake, server_records->record(0).header.content_type());
for (size_t i = 1; i < server_records->count(); ++i) {
EXPECT_EQ(kTlsApplicationDataType,
EXPECT_EQ(ssl_ct_application_data,
server_records->record(i).header.content_type());
}

View file

@ -151,6 +151,7 @@ class SSLv2ClientHelloTestF : public TlsConnectTestBase {
void SetUp() override {
TlsConnectTestBase::SetUp();
filter_ = MakeTlsFilter<SSLv2ClientHelloFilter>(client_, version_);
server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_TRUE);
}
void SetExpectedVersion(uint16_t version) {
@ -197,6 +198,27 @@ TEST_P(SSLv2ClientHelloTest, Connect) {
Connect();
}
TEST_P(SSLv2ClientHelloTest, ConnectDisabled) {
server_->SetOption(SSL_ENABLE_V2_COMPATIBLE_HELLO, PR_FALSE);
SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
StartConnect();
client_->Handshake(); // Send the modified ClientHello.
server_->Handshake(); // Read some.
// The problem here is that the v2 ClientHello puts the version where the v3
// ClientHello puts a version number. So the version number (0x0301+) appears
// to be a length and server blocks waiting for that much data.
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
// This is usually what happens with v2-compatible: the server hangs.
// But to be certain, feed in more data to see if an error comes out.
uint8_t zeros[SSL_LIBRARY_VERSION_TLS_1_2] = {0};
client_->SendDirect(DataBuffer(zeros, sizeof(zeros)));
ExpectAlert(server_, kTlsAlertIllegalParameter);
server_->Handshake();
client_->Handshake();
}
// Sending a v2 ClientHello after a no-op v3 record must fail.
TEST_P(SSLv2ClientHelloTest, ConnectAfterEmptyV3Record) {
DataBuffer buffer;
@ -328,6 +350,30 @@ TEST_P(SSLv2ClientHelloTest, RequireSafeRenegotiationWithSCSV) {
Connect();
}
TEST_P(SSLv2ClientHelloTest, CheckServerRandom) {
ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
SetAvailableCipherSuite(TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
static const size_t random_len = 32;
uint8_t srandom1[random_len];
uint8_t z[random_len] = {0};
auto sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
Connect();
ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
memcpy(srandom1, sh->buffer().data() + 2, random_len);
EXPECT_NE(0, memcmp(srandom1, z, random_len));
Reset();
sh = MakeTlsFilter<TlsHandshakeRecorder>(server_, ssl_hs_server_hello);
Connect();
ASSERT_TRUE(sh->buffer().len() > (random_len + 2));
const uint8_t* srandom2 = sh->buffer().data() + 2;
EXPECT_NE(0, memcmp(srandom2, z, random_len));
EXPECT_NE(0, memcmp(srandom1, srandom2, random_len));
}
// Connect to the server with TLS 1.1, signalling that this is a fallback from
// a higher version. As the server doesn't support anything higher than TLS 1.1
// it must accept the connection.

View file

@ -11,7 +11,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"
@ -48,7 +48,6 @@ TEST_P(TlsConnectGeneric, ServerNegotiateTls12) {
SSL_LIBRARY_VERSION_TLS_1_2);
Connect();
}
#ifndef TLS_1_3_DRAFT_VERSION
// Test the ServerRandom version hack from
// [draft-ietf-tls-tls13-11 Section 6.3.1.1].
@ -56,71 +55,116 @@ TEST_P(TlsConnectGeneric, ServerNegotiateTls12) {
// two validate that we can also detect fallback using the
// SSL_SetDowngradeCheckVersion() API.
TEST_F(TlsConnectTest, TestDowngradeDetectionToTls11) {
client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
MakeTlsFilter<TlsClientHelloVersionSetter>(client_,
SSL_LIBRARY_VERSION_TLS_1_1);
ConnectExpectFail();
ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
/* Attempt to negotiate the bogus DTLS 1.1 version. */
// Attempt to negotiate the bogus DTLS 1.1 version.
TEST_F(DtlsConnectTest, TestDtlsVersion11) {
MakeTlsFilter<TlsClientHelloVersionSetter>(client_, ((~0x0101) & 0xffff));
ConnectExpectFail();
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
// It's kind of surprising that SSL_ERROR_NO_CYPHER_OVERLAP is
// what is returned here, but this is deliberate in ssl3_HandleAlert().
EXPECT_EQ(SSL_ERROR_NO_CYPHER_OVERLAP, client_->error_code());
EXPECT_EQ(SSL_ERROR_UNSUPPORTED_VERSION, server_->error_code());
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
}
// Disabled as long as we have draft version.
TEST_F(TlsConnectTest, TestDowngradeDetectionToTls12) {
EnsureTlsSetup();
MakeTlsFilter<TlsClientHelloVersionSetter>(client_,
SSL_LIBRARY_VERSION_TLS_1_2);
client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
MakeTlsFilter<TlsExtensionDropper>(client_, ssl_tls13_supported_versions_xtn);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
ConnectExpectFail();
ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
// Disabling downgrade checks will be caught when the Finished MAC check fails.
TEST_F(TlsConnectTest, TestDisableDowngradeDetection) {
client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_FALSE);
MakeTlsFilter<TlsExtensionDropper>(client_, ssl_tls13_supported_versions_xtn);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
ConnectExpectAlert(server_, kTlsAlertDecryptError);
client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}
// TLS 1.1 clients do not check the random values, so we should
// instead get a handshake failure alert from the server.
TEST_F(TlsConnectTest, TestDowngradeDetectionToTls10) {
// Setting the option here has no effect.
client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
MakeTlsFilter<TlsClientHelloVersionSetter>(client_,
SSL_LIBRARY_VERSION_TLS_1_0);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_1);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_0,
SSL_LIBRARY_VERSION_TLS_1_2);
ConnectExpectFail();
ASSERT_EQ(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE, server_->error_code());
ASSERT_EQ(SSL_ERROR_DECRYPT_ERROR_ALERT, client_->error_code());
ConnectExpectAlert(server_, kTlsAlertDecryptError);
server_->CheckErrorCode(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
client_->CheckErrorCode(SSL_ERROR_DECRYPT_ERROR_ALERT);
}
TEST_F(TlsConnectTest, TestFallbackFromTls12) {
EnsureTlsSetup();
client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_2);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_1);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_2);
ConnectExpectFail();
ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
static SECStatus AllowFalseStart(PRFileDesc* fd, void* arg,
PRBool* can_false_start) {
bool* false_start_attempted = reinterpret_cast<bool*>(arg);
*false_start_attempted = true;
*can_false_start = PR_TRUE;
return SECSuccess;
}
// If we disable the downgrade check, the sentinel is still generated, and we
// disable false start instead.
TEST_F(TlsConnectTest, DisableFalseStartOnFallback) {
// Don't call client_->EnableFalseStart(), because that sets the client up for
// success, and we want false start to fail.
client_->SetOption(SSL_ENABLE_FALSE_START, PR_TRUE);
bool false_start_attempted = false;
EXPECT_EQ(SECSuccess,
SSL_SetCanFalseStartCallback(client_->ssl_fd(), AllowFalseStart,
&false_start_attempted));
client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_3);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_2);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
Connect();
EXPECT_FALSE(false_start_attempted);
}
TEST_F(TlsConnectTest, TestFallbackFromTls13) {
EnsureTlsSetup();
client_->SetOption(SSL_ENABLE_HELLO_DOWNGRADE_CHECK, PR_TRUE);
client_->SetDowngradeCheckVersion(SSL_LIBRARY_VERSION_TLS_1_3);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_2);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
SSL_LIBRARY_VERSION_TLS_1_3);
ConnectExpectFail();
ASSERT_EQ(SSL_ERROR_RX_MALFORMED_SERVER_HELLO, client_->error_code());
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
}
#endif
TEST_P(TlsConnectGeneric, TestFallbackSCSVVersionMatch) {
client_->SetOption(SSL_ENABLE_FALLBACK_SCSV, PR_TRUE);
@ -132,6 +176,7 @@ TEST_P(TlsConnectGenericPre13, TestFallbackSCSVVersionMismatch) {
server_->SetVersionRange(version_, version_ + 1);
ConnectExpectAlert(server_, kTlsAlertInappropriateFallback);
client_->CheckErrorCode(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT);
server_->CheckErrorCode(SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT);
}
// The TLS v1.3 spec section C.4 states that 'Implementations MUST NOT send or
@ -158,7 +203,7 @@ TEST_P(TlsConnectGeneric, AlertBeforeServerHello) {
static const uint8_t kWarningAlert[] = {kTlsAlertWarning,
kTlsAlertUnrecognizedName};
DataBuffer alert;
TlsAgentTestBase::MakeRecord(variant_, kTlsAlertType,
TlsAgentTestBase::MakeRecord(variant_, ssl_ct_alert,
SSL_LIBRARY_VERSION_TLS_1_0, kWarningAlert,
PR_ARRAY_SIZE(kWarningAlert), &alert);
client_->adapter()->PacketReceived(alert);

View file

@ -12,7 +12,7 @@
#include "sslproto.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "tls_connect.h"
#include "tls_filter.h"
#include "tls_parser.h"

View file

@ -31,6 +31,20 @@ ScopedPRFileDesc DummyPrSocket::CreateFD() {
return DummyIOLayerMethods::CreateFD(test_fd_identity, this);
}
void DummyPrSocket::Reset() {
auto p = peer_.lock();
peer_.reset();
if (p) {
p->peer_.reset();
p->Reset();
}
while (!input_.empty()) {
input_.pop();
}
filter_ = nullptr;
write_error_ = 0;
}
void DummyPrSocket::PacketReceived(const DataBuffer &packet) {
input_.push(Packet(packet));
}
@ -42,6 +56,12 @@ int32_t DummyPrSocket::Read(PRFileDesc *f, void *data, int32_t len) {
return -1;
}
auto dst = peer_.lock();
if (!dst) {
PR_SetError(PR_NOT_CONNECTED_ERROR, 0);
return -1;
}
if (input_.empty()) {
LOGV("Read --> wouldblock " << len);
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
@ -74,6 +94,12 @@ int32_t DummyPrSocket::Recv(PRFileDesc *f, void *buf, int32_t buflen,
return Read(f, buf, buflen);
}
auto dst = peer_.lock();
if (!dst) {
PR_SetError(PR_NOT_CONNECTED_ERROR, 0);
return -1;
}
if (input_.empty()) {
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
return -1;
@ -101,7 +127,7 @@ int32_t DummyPrSocket::Write(PRFileDesc *f, const void *buf, int32_t length) {
auto dst = peer_.lock();
if (!dst) {
PR_SetError(PR_IO_ERROR, 0);
PR_SetError(PR_NOT_CONNECTED_ERROR, 0);
return -1;
}

View file

@ -17,7 +17,7 @@
#include "databuffer.h"
#include "dummy_io.h"
#include "prio.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "sslt.h"
namespace nss_test {

View file

@ -15,6 +15,9 @@
#include "tls_filter.h"
#include "tls_parser.h"
// This is an internal header, used to get DTLS_1_3_DRAFT_VERSION.
#include "ssl3prot.h"
extern "C" {
// This is not something that should make you happy.
#include "libssl_internals.h"
@ -23,7 +26,7 @@ extern "C" {
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
extern std::string g_working_dir_path;
@ -53,7 +56,7 @@ static const uint8_t kCannedTls13ServerHello[] = {
0x00, 0x1d, 0x00, 0x20, 0xc2, 0xcf, 0x23, 0x17, 0x64, 0x23, 0x03,
0xf0, 0xfb, 0x45, 0x98, 0x26, 0xd1, 0x65, 0x24, 0xa1, 0x6c, 0xa9,
0x80, 0x8f, 0x2c, 0xac, 0x0a, 0xea, 0x53, 0x3a, 0xcb, 0xe3, 0x08,
0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x7f, kD13};
0x84, 0xae, 0x19, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04};
TlsAgent::TlsAgent(const std::string& nm, Role rl, SSLProtocolVariant var)
: name_(nm),
@ -226,6 +229,7 @@ bool TlsAgent::EnsureTlsSetup(PRFileDesc* modelSocket) {
bool TlsAgent::MaybeSetResumptionToken() {
if (!resumption_token_.empty()) {
LOG("setting external resumption token");
SECStatus rv = SSL_SetResumptionToken(ssl_fd(), resumption_token_.data(),
resumption_token_.size());
@ -583,6 +587,7 @@ void TlsAgent::CheckAuthType(SSLAuthType auth,
// switch statement because default label is different.
switch (auth) {
case ssl_auth_rsa_sign:
case ssl_auth_rsa_pss:
EXPECT_EQ(ssl_auth_rsa_decrypt, csinfo_.authAlgorithm)
<< "authAlgorithm for RSA is always decrypt";
break;
@ -934,8 +939,8 @@ void TlsAgent::SendRecordDirect(const TlsRecord& record) {
SendDirect(buf);
}
static bool ErrorIsNonFatal(PRErrorCode code) {
return code == PR_WOULD_BLOCK_ERROR || code == SSL_ERROR_RX_SHORT_DTLS_READ;
static bool ErrorIsFatal(PRErrorCode code) {
return code != PR_WOULD_BLOCK_ERROR && code != SSL_ERROR_RX_SHORT_DTLS_READ;
}
void TlsAgent::SendData(size_t bytes, size_t blocksize) {
@ -975,7 +980,7 @@ bool TlsAgent::SendEncryptedRecord(const std::shared_ptr<TlsCipherSpec>& spec,
LOGV("Encrypting " << buf.len() << " bytes");
// Ensure that we are doing TLS 1.3.
EXPECT_GE(expected_version_, SSL_LIBRARY_VERSION_TLS_1_3);
TlsRecordHeader header(variant_, expected_version_, kTlsApplicationDataType,
TlsRecordHeader header(variant_, expected_version_, ssl_ct_application_data,
seq);
DataBuffer padded = buf;
padded.Write(padded.len(), ct, 1);
@ -994,28 +999,39 @@ bool TlsAgent::SendEncryptedRecord(const std::shared_ptr<TlsCipherSpec>& spec,
void TlsAgent::ReadBytes(size_t amount) {
uint8_t block[16384];
int32_t rv = PR_Read(ssl_fd(), block, (std::min)(amount, sizeof(block)));
LOGV("ReadBytes " << rv);
int32_t err;
size_t remaining = amount;
while (remaining > 0) {
int32_t rv = PR_Read(ssl_fd(), block, (std::min)(amount, sizeof(block)));
LOGV("ReadBytes " << rv);
if (rv >= 0) {
size_t count = static_cast<size_t>(rv);
for (size_t i = 0; i < count; ++i) {
ASSERT_EQ(recv_ctr_ & 0xff, block[i]);
recv_ctr_++;
}
} else {
err = PR_GetError();
LOG("Read error " << PORT_ErrorToName(err) << ": "
<< PORT_ErrorToString(err));
if (err != PR_WOULD_BLOCK_ERROR && expect_readwrite_error_) {
error_code_ = err;
expect_readwrite_error_ = false;
if (rv > 0) {
size_t count = static_cast<size_t>(rv);
for (size_t i = 0; i < count; ++i) {
ASSERT_EQ(recv_ctr_ & 0xff, block[i]);
recv_ctr_++;
}
remaining -= rv;
} else {
PRErrorCode err = 0;
if (rv < 0) {
err = PR_GetError();
LOG("Read error " << PORT_ErrorToName(err) << ": "
<< PORT_ErrorToString(err));
if (err != PR_WOULD_BLOCK_ERROR && expect_readwrite_error_) {
error_code_ = err;
expect_readwrite_error_ = false;
}
}
if (err != 0 && ErrorIsFatal(err)) {
// If we hit a fatal error, we're done.
remaining = 0;
}
break;
}
}
// If closed, then don't bother waiting around.
if (rv > 0 || (rv < 0 && ErrorIsNonFatal(err))) {
if (remaining) {
LOGV("Re-arming");
Poller::Instance()->Wait(READABLE_EVENT, adapter_, this,
&TlsAgent::ReadableCallback);
@ -1104,7 +1120,7 @@ void TlsAgentTestBase::MakeRecord(SSLProtocolVariant variant, uint8_t type,
if (variant == ssl_variant_stream) {
index = out->Write(index, version, 2);
} else if (version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
type == kTlsApplicationDataType) {
type == ssl_ct_application_data) {
uint32_t epoch = (sequence_number >> 48) & 0x3;
uint32_t seqno = sequence_number & ((1ULL << 30) - 1);
index = out->Write(index, (epoch << 30) | seqno, 4);
@ -1157,10 +1173,10 @@ void TlsAgentTestBase::MakeTrivialHandshakeRecord(uint8_t hs_type,
size_t hs_len,
DataBuffer* out) {
size_t index = 0;
index = out->Write(index, kTlsHandshakeType, 1); // Content Type
index = out->Write(index, 3, 1); // Version high
index = out->Write(index, 1, 1); // Version low
index = out->Write(index, 4 + hs_len, 2); // Length
index = out->Write(index, ssl_ct_handshake, 1); // Content Type
index = out->Write(index, 3, 1); // Version high
index = out->Write(index, 1, 1); // Version low
index = out->Write(index, 4 + hs_len, 2); // Length
index = out->Write(index, hs_type, 1); // Handshake record type.
index = out->Write(index, hs_len, 3); // Handshake length
@ -1173,6 +1189,11 @@ DataBuffer TlsAgentTestBase::MakeCannedTls13ServerHello() {
DataBuffer sh(kCannedTls13ServerHello, sizeof(kCannedTls13ServerHello));
if (variant_ == ssl_variant_datagram) {
sh.Write(0, SSL_LIBRARY_VERSION_DTLS_1_2_WIRE, 2);
// The version should be at the end.
uint32_t v;
EXPECT_TRUE(sh.Read(sh.len() - 2, 2, &v));
EXPECT_EQ(static_cast<uint32_t>(SSL_LIBRARY_VERSION_TLS_1_3), v);
sh.Write(sh.len() - 2, 0x7f00 | DTLS_1_3_DRAFT_VERSION, 2);
}
return sh;
}

View file

@ -10,9 +10,6 @@
#include "prio.h"
#include "ssl.h"
// This is an internal header, used to get TLS_1_3_DRAFT_VERSION.
#include "ssl3prot.h"
#include <functional>
#include <iostream>
@ -20,7 +17,8 @@
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "scoped_ptrs_ssl.h"
extern bool g_ssl_gtest_verbose;
@ -60,8 +58,6 @@ typedef std::function<int32_t(TlsAgent* agent, const SECItem* srvNameArr,
PRUint32 srvNameArrSize)>
SniCallbackFunction;
static const uint8_t kD13 = TLS_1_3_DRAFT_VERSION;
class TlsAgent : public PollTarget {
public:
enum Role { CLIENT, SERVER };

View file

@ -14,7 +14,7 @@ extern "C" {
#include "databuffer.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
#include "sslproto.h"
extern std::string g_working_dir_path;
@ -559,13 +559,15 @@ void TlsConnectTestBase::CheckResumption(SessionResumptionMode expected) {
EXPECT_EQ(stateless_count, stats->hsh_sid_stateless_resumes);
if (expected != RESUME_NONE) {
if (client_->version() < SSL_LIBRARY_VERSION_TLS_1_3) {
if (client_->version() < SSL_LIBRARY_VERSION_TLS_1_3 &&
client_->GetResumptionToken().size() == 0) {
// Check that the last two session ids match.
ASSERT_EQ(1U + expected_resumptions_, session_ids_.size());
EXPECT_EQ(session_ids_[session_ids_.size() - 1],
session_ids_[session_ids_.size() - 2]);
} else {
// TLS 1.3 only uses tickets.
// We've either chosen TLS 1.3 or are using an external resumption token,
// both of which only use tickets.
EXPECT_TRUE(expected & RESUME_TICKET);
}
}

View file

@ -0,0 +1,470 @@
/* -*- 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 <ctime>
#include "secerr.h"
#include "ssl.h"
#include "gtest_utils.h"
#include "tls_agent.h"
#include "tls_connect.h"
namespace nss_test {
static const char* kDummySni("dummy.invalid");
std::vector<uint16_t> kDefaultSuites = {TLS_AES_256_GCM_SHA384,
TLS_AES_128_GCM_SHA256};
std::vector<uint16_t> kChaChaSuite = {TLS_CHACHA20_POLY1305_SHA256};
std::vector<uint16_t> kBogusSuites = {0};
std::vector<uint16_t> kTls12Suites = {
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256};
static void NamedGroup2ECParams(SSLNamedGroup group, SECItem* params) {
auto groupDef = ssl_LookupNamedGroup(group);
ASSERT_NE(nullptr, groupDef);
auto oidData = SECOID_FindOIDByTag(groupDef->oidTag);
ASSERT_NE(nullptr, oidData);
ASSERT_NE(nullptr,
SECITEM_AllocItem(nullptr, params, (2 + oidData->oid.len)));
/*
* params->data needs to contain the ASN encoding of an object ID (OID)
* representing the named curve. The actual OID is in
* oidData->oid.data so we simply prepend 0x06 and OID length
*/
params->data[0] = SEC_ASN1_OBJECT_ID;
params->data[1] = oidData->oid.len;
memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
}
/* Checksum is a 4-byte array. */
static void UpdateEsniKeysChecksum(DataBuffer* buf) {
SECStatus rv;
PRUint8 sha256[32];
/* Stomp the checksum. */
PORT_Memset(buf->data() + 2, 0, 4);
rv = PK11_HashBuf(ssl3_HashTypeToOID(ssl_hash_sha256), sha256, buf->data(),
buf->len());
ASSERT_EQ(SECSuccess, rv);
buf->Write(2, sha256, 4);
}
static void GenerateEsniKey(time_t windowStart, SSLNamedGroup group,
std::vector<uint16_t>& cipher_suites,
DataBuffer* record,
ScopedSECKEYPublicKey* pubKey = nullptr,
ScopedSECKEYPrivateKey* privKey = nullptr) {
SECKEYECParams ecParams = {siBuffer, NULL, 0};
NamedGroup2ECParams(group, &ecParams);
SECKEYPublicKey* pub = nullptr;
SECKEYPrivateKey* priv = SECKEY_CreateECPrivateKey(&ecParams, &pub, nullptr);
ASSERT_NE(nullptr, priv);
SECITEM_FreeItem(&ecParams, PR_FALSE);
PRUint8 encoded[1024];
unsigned int encoded_len;
SECStatus rv = SSL_EncodeESNIKeys(
&cipher_suites[0], cipher_suites.size(), group, pub, 100, windowStart,
windowStart + 10, encoded, &encoded_len, sizeof(encoded));
ASSERT_EQ(SECSuccess, rv);
ASSERT_GT(encoded_len, 0U);
if (pubKey) {
pubKey->reset(pub);
} else {
SECKEY_DestroyPublicKey(pub);
}
if (privKey) {
privKey->reset(priv);
} else {
SECKEY_DestroyPrivateKey(priv);
}
record->Truncate(0);
record->Write(0, encoded, encoded_len);
}
static void SetupEsni(const std::shared_ptr<TlsAgent>& client,
const std::shared_ptr<TlsAgent>& server,
SSLNamedGroup group = ssl_grp_ec_curve25519) {
ScopedSECKEYPublicKey pub;
ScopedSECKEYPrivateKey priv;
DataBuffer record;
GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
&pub, &priv);
SECStatus rv = SSL_SetESNIKeyPair(server->ssl_fd(), priv.get(), record.data(),
record.len());
ASSERT_EQ(SECSuccess, rv);
rv = SSL_EnableESNI(client->ssl_fd(), record.data(), record.len(), kDummySni);
ASSERT_EQ(SECSuccess, rv);
}
static void CheckSniExtension(const DataBuffer& data) {
TlsParser parser(data.data(), data.len());
uint32_t tmp;
ASSERT_TRUE(parser.Read(&tmp, 2));
ASSERT_EQ(parser.remaining(), tmp);
ASSERT_TRUE(parser.Read(&tmp, 1));
ASSERT_EQ(0U, tmp); /* sni_nametype_hostname */
DataBuffer name;
ASSERT_TRUE(parser.ReadVariable(&name, 2));
ASSERT_EQ(0U, parser.remaining());
DataBuffer expected(reinterpret_cast<const uint8_t*>(kDummySni),
strlen(kDummySni));
ASSERT_EQ(expected, name);
}
static void ClientInstallEsni(std::shared_ptr<TlsAgent>& agent,
const DataBuffer& record, PRErrorCode err = 0) {
SECStatus rv =
SSL_EnableESNI(agent->ssl_fd(), record.data(), record.len(), kDummySni);
if (err == 0) {
ASSERT_EQ(SECSuccess, rv);
} else {
ASSERT_EQ(SECFailure, rv);
ASSERT_EQ(err, PORT_GetError());
}
}
TEST_P(TlsAgentTestClient13, EsniInstall) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
ClientInstallEsni(agent_, record);
}
// The next set of tests fail at setup time.
TEST_P(TlsAgentTestClient13, EsniInvalidHash) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
record.data()[2]++;
ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS);
}
TEST_P(TlsAgentTestClient13, EsniInvalidVersion) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
record.Write(0, 0xffff, 2);
ClientInstallEsni(agent_, record, SSL_ERROR_UNSUPPORTED_VERSION);
}
TEST_P(TlsAgentTestClient13, EsniShort) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
record.Truncate(record.len() - 1);
UpdateEsniKeysChecksum(&record);
ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS);
}
TEST_P(TlsAgentTestClient13, EsniLong) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
record.Write(record.len(), 1, 1);
UpdateEsniKeysChecksum(&record);
ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS);
}
TEST_P(TlsAgentTestClient13, EsniExtensionMismatch) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
record.Write(record.len() - 1, 1, 1);
UpdateEsniKeysChecksum(&record);
ClientInstallEsni(agent_, record, SSL_ERROR_RX_MALFORMED_ESNI_KEYS);
}
// The following tests fail by ignoring the Esni block.
TEST_P(TlsAgentTestClient13, EsniUnknownGroup) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
record.Write(8, 0xffff, 2); // Fake group
UpdateEsniKeysChecksum(&record);
ClientInstallEsni(agent_, record, 0);
auto filter =
MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
agent_->Handshake();
ASSERT_EQ(TlsAgent::STATE_CONNECTING, agent_->state());
ASSERT_TRUE(!filter->captured());
}
TEST_P(TlsAgentTestClient13, EsniUnknownCS) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kBogusSuites, &record);
ClientInstallEsni(agent_, record, 0);
auto filter =
MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
agent_->Handshake();
ASSERT_EQ(TlsAgent::STATE_CONNECTING, agent_->state());
ASSERT_TRUE(!filter->captured());
}
TEST_P(TlsAgentTestClient13, EsniInvalidCS) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kTls12Suites, &record);
UpdateEsniKeysChecksum(&record);
ClientInstallEsni(agent_, record, 0);
auto filter =
MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
agent_->Handshake();
ASSERT_EQ(TlsAgent::STATE_CONNECTING, agent_->state());
ASSERT_TRUE(!filter->captured());
}
TEST_P(TlsAgentTestClient13, EsniNotReady) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0) + 1000, ssl_grp_ec_curve25519, kDefaultSuites,
&record);
ClientInstallEsni(agent_, record, 0);
auto filter =
MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
agent_->Handshake();
ASSERT_TRUE(!filter->captured());
}
TEST_P(TlsAgentTestClient13, EsniExpired) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0) - 1000, ssl_grp_ec_curve25519, kDefaultSuites,
&record);
ClientInstallEsni(agent_, record, 0);
auto filter =
MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
agent_->Handshake();
ASSERT_TRUE(!filter->captured());
}
TEST_P(TlsAgentTestClient13, NoSniSoNoEsni) {
EnsureInit();
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
SSL_SetURL(agent_->ssl_fd(), "");
ClientInstallEsni(agent_, record, 0);
auto filter =
MakeTlsFilter<TlsExtensionCapture>(agent_, ssl_tls13_encrypted_sni_xtn);
agent_->Handshake();
ASSERT_TRUE(!filter->captured());
}
static int32_t SniCallback(TlsAgent* agent, const SECItem* srvNameAddr,
PRUint32 srvNameArrSize) {
EXPECT_EQ(1U, srvNameArrSize);
SECItem expected = {
siBuffer, reinterpret_cast<unsigned char*>(const_cast<char*>("server")),
6};
EXPECT_TRUE(!SECITEM_CompareItem(&expected, &srvNameAddr[0]));
return SECSuccess;
}
TEST_P(TlsConnectTls13, ConnectEsni) {
EnsureTlsSetup();
SetupEsni(client_, server_);
auto cFilterSni =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
auto cFilterEsni =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_tls13_encrypted_sni_xtn);
client_->SetFilter(std::make_shared<ChainedPacketFilter>(
ChainedPacketFilterInit({cFilterSni, cFilterEsni})));
auto sfilter =
MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn);
sfilter->EnableDecryption();
server_->SetSniCallback(SniCallback);
Connect();
CheckSniExtension(cFilterSni->extension());
ASSERT_TRUE(cFilterEsni->captured());
// Check that our most preferred suite got chosen.
uint32_t suite;
ASSERT_TRUE(cFilterEsni->extension().Read(0, 2, &suite));
ASSERT_EQ(TLS_AES_128_GCM_SHA256, static_cast<PRUint16>(suite));
ASSERT_TRUE(!sfilter->captured());
}
TEST_P(TlsConnectTls13, ConnectEsniHrr) {
EnsureTlsSetup();
const std::vector<SSLNamedGroup> groups = {ssl_grp_ec_secp384r1};
server_->ConfigNamedGroups(groups);
SetupEsni(client_, server_);
auto hrr_capture = MakeTlsFilter<TlsHandshakeRecorder>(
server_, kTlsHandshakeHelloRetryRequest);
auto filter =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
auto cfilter =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
server_->SetSniCallback(SniCallback);
Connect();
CheckSniExtension(cfilter->extension());
EXPECT_NE(0UL, hrr_capture->buffer().len());
}
TEST_P(TlsConnectTls13, ConnectEsniNoDummy) {
EnsureTlsSetup();
ScopedSECKEYPublicKey pub;
ScopedSECKEYPrivateKey priv;
DataBuffer record;
GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
&pub, &priv);
SECStatus rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(),
record.data(), record.len());
ASSERT_EQ(SECSuccess, rv);
rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), "");
ASSERT_EQ(SECSuccess, rv);
auto cfilter =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
auto sfilter =
MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn);
server_->SetSniCallback(SniCallback);
Connect();
ASSERT_TRUE(!cfilter->captured());
ASSERT_TRUE(!sfilter->captured());
}
TEST_P(TlsConnectTls13, ConnectEsniNullDummy) {
EnsureTlsSetup();
ScopedSECKEYPublicKey pub;
ScopedSECKEYPrivateKey priv;
DataBuffer record;
GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
&pub, &priv);
SECStatus rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(),
record.data(), record.len());
ASSERT_EQ(SECSuccess, rv);
rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), nullptr);
ASSERT_EQ(SECSuccess, rv);
auto cfilter =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
auto sfilter =
MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn);
server_->SetSniCallback(SniCallback);
Connect();
ASSERT_TRUE(!cfilter->captured());
ASSERT_TRUE(!sfilter->captured());
}
/* Tell the client that it supports AES but the server that it supports ChaCha
*/
TEST_P(TlsConnectTls13, ConnectEsniCSMismatch) {
EnsureTlsSetup();
ScopedSECKEYPublicKey pub;
ScopedSECKEYPrivateKey priv;
DataBuffer record;
GenerateEsniKey(time(nullptr), ssl_grp_ec_curve25519, kDefaultSuites, &record,
&pub, &priv);
PRUint8 encoded[1024];
unsigned int encoded_len;
SECStatus rv = SSL_EncodeESNIKeys(
&kChaChaSuite[0], kChaChaSuite.size(), ssl_grp_ec_curve25519, pub.get(),
100, time(0), time(0) + 10, encoded, &encoded_len, sizeof(encoded));
rv = SSL_SetESNIKeyPair(server_->ssl_fd(), priv.get(), encoded, encoded_len);
ASSERT_EQ(SECSuccess, rv);
rv = SSL_EnableESNI(client_->ssl_fd(), record.data(), record.len(), "");
ASSERT_EQ(SECSuccess, rv);
ConnectExpectAlert(server_, illegal_parameter);
server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}
TEST_P(TlsConnectTls13, ConnectEsniP256) {
EnsureTlsSetup();
SetupEsni(client_, server_, ssl_grp_ec_secp256r1);
auto cfilter =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_server_name_xtn);
auto sfilter =
MakeTlsFilter<TlsExtensionCapture>(server_, ssl_server_name_xtn);
server_->SetSniCallback(SniCallback);
Connect();
CheckSniExtension(cfilter->extension());
ASSERT_TRUE(!sfilter->captured());
}
TEST_P(TlsConnectTls13, ConnectMismatchedEsniKeys) {
EnsureTlsSetup();
SetupEsni(client_, server_);
// Now install a new set of keys on the client, so we have a mismatch.
DataBuffer record;
GenerateEsniKey(time(0), ssl_grp_ec_curve25519, kDefaultSuites, &record);
ClientInstallEsni(client_, record, 0);
ConnectExpectAlert(server_, illegal_parameter);
server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}
TEST_P(TlsConnectTls13, ConnectDamagedEsniExtensionCH) {
EnsureTlsSetup();
SetupEsni(client_, server_);
auto filter = MakeTlsFilter<TlsExtensionDamager>(
client_, ssl_tls13_encrypted_sni_xtn, 50); // in the ciphertext
ConnectExpectAlert(server_, illegal_parameter);
server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}
TEST_P(TlsConnectTls13, ConnectRemoveEsniExtensionEE) {
EnsureTlsSetup();
SetupEsni(client_, server_);
auto filter =
MakeTlsFilter<TlsExtensionDropper>(server_, ssl_tls13_encrypted_sni_xtn);
filter->EnableDecryption();
ConnectExpectAlert(client_, missing_extension);
client_->CheckErrorCode(SSL_ERROR_MISSING_ESNI_EXTENSION);
}
TEST_P(TlsConnectTls13, ConnectShortEsniExtensionEE) {
EnsureTlsSetup();
SetupEsni(client_, server_);
DataBuffer shortNonce;
auto filter = MakeTlsFilter<TlsExtensionReplacer>(
server_, ssl_tls13_encrypted_sni_xtn, shortNonce);
filter->EnableDecryption();
ConnectExpectAlert(client_, illegal_parameter);
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_ESNI_EXTENSION);
}
TEST_P(TlsConnectTls13, ConnectBogusEsniExtensionEE) {
EnsureTlsSetup();
SetupEsni(client_, server_);
const uint8_t bogusNonceBuf[16] = {0};
DataBuffer bogusNonce(bogusNonceBuf, sizeof(bogusNonceBuf));
auto filter = MakeTlsFilter<TlsExtensionReplacer>(
server_, ssl_tls13_encrypted_sni_xtn, bogusNonce);
filter->EnableDecryption();
ConnectExpectAlert(client_, illegal_parameter);
client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_ESNI_EXTENSION);
}
// ESNI is a commitment to doing TLS 1.3 or above.
// The TLS 1.2 server ignores ESNI and processes the dummy SNI.
// The client then aborts when it sees the server did TLS 1.2.
TEST_P(TlsConnectTls13, EsniButTLS12Server) {
EnsureTlsSetup();
SetupEsni(client_, server_);
client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_3);
server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
SSL_LIBRARY_VERSION_TLS_1_2);
ConnectExpectAlert(client_, kTlsAlertProtocolVersion);
client_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_VERSION);
server_->CheckErrorCode(SSL_ERROR_PROTOCOL_VERSION_ALERT);
ASSERT_FALSE(SSLInt_ExtensionNegotiated(server_->ssl_fd(),
ssl_tls13_encrypted_sni_xtn));
}
}

View file

@ -131,7 +131,7 @@ PacketFilter::Action TlsRecordFilter::Filter(const DataBuffer& input,
// spec to another active cipher spec (KeyUpdate for instance) AND writes
// are consolidated across that change, this code could use the wrong
// sequence numbers when re-encrypting records with the old keys.
if (header.content_type() == kTlsApplicationDataType) {
if (header.content_type() == ssl_ct_application_data) {
in_sequence_number_ =
(std::max)(in_sequence_number_, header.sequence_number() + 1);
}
@ -194,7 +194,7 @@ PacketFilter::Action TlsRecordFilter::FilterRecord(
uint64_t seq_num;
if (header.is_dtls() || !cipher_spec_ ||
header.content_type() != kTlsApplicationDataType) {
header.content_type() != ssl_ct_application_data) {
seq_num = header.sequence_number();
} else {
seq_num = out_sequence_number_++;
@ -277,7 +277,7 @@ bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser,
#ifndef UNSAFE_FUZZER_MODE
// Deal with the 7 octet header.
if (content_type_ == kTlsApplicationDataType) {
if (content_type_ == ssl_ct_application_data) {
uint32_t tmp;
if (!parser->Read(&tmp, 4)) {
return false;
@ -298,7 +298,7 @@ bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser,
}
// Need to use the low 5 bits of the first octet too.
tmp |= (content_type_ & 0x1f) << 8;
content_type_ = kTlsApplicationDataType;
content_type_ = ssl_ct_application_data;
sequence_number_ = ParseSequenceNumber(seqno, tmp, 12, 1);
if (!parser->ReadFromMark(&header_, parser->consumed() - mark, mark)) {
@ -308,9 +308,9 @@ bool TlsRecordHeader::Parse(bool is_dtls13, uint64_t seqno, TlsParser* parser,
}
// The full 13 octet header can only be used for a few types.
EXPECT_TRUE(content_type_ == kTlsAlertType ||
content_type_ == kTlsHandshakeType ||
content_type_ == kTlsAckType);
EXPECT_TRUE(content_type_ == ssl_ct_alert ||
content_type_ == ssl_ct_handshake ||
content_type_ == ssl_ct_ack);
#endif
}
@ -347,7 +347,7 @@ size_t TlsRecordHeader::WriteHeader(DataBuffer* buffer, size_t offset,
size_t body_len) const {
offset = buffer->Write(offset, content_type_, 1);
if (is_dtls() && version_ >= SSL_LIBRARY_VERSION_TLS_1_3 &&
content_type() == kTlsApplicationDataType) {
content_type() == ssl_ct_application_data) {
// application_data records in TLS 1.3 have a different header format.
// Always use the long header here for simplicity.
uint32_t e = (sequence_number_ >> 48) & 0x3;
@ -377,7 +377,7 @@ bool TlsRecordFilter::Unprotect(const TlsRecordHeader& header,
const DataBuffer& ciphertext,
uint8_t* inner_content_type,
DataBuffer* plaintext) {
if (!cipher_spec_ || header.content_type() != kTlsApplicationDataType) {
if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) {
*inner_content_type = header.content_type();
*plaintext = ciphertext;
return true;
@ -411,7 +411,7 @@ bool TlsRecordFilter::Protect(const TlsRecordHeader& header,
uint8_t inner_content_type,
const DataBuffer& plaintext,
DataBuffer* ciphertext, size_t padding) {
if (!cipher_spec_ || header.content_type() != kTlsApplicationDataType) {
if (!cipher_spec_ || header.content_type() != ssl_ct_application_data) {
*ciphertext = plaintext;
return true;
}
@ -453,8 +453,7 @@ PacketFilter::Action TlsHandshakeFilter::FilterRecord(
const TlsRecordHeader& record_header, const DataBuffer& input,
DataBuffer* output) {
// Check that the first byte is as requested.
if ((record_header.content_type() != kTlsHandshakeType) &&
(record_header.content_type() != kTlsAltHandshakeType)) {
if (record_header.content_type() != ssl_ct_handshake) {
return KEEP;
}
@ -879,6 +878,17 @@ PacketFilter::Action TlsExtensionDropper::FilterExtension(
return KEEP;
}
PacketFilter::Action TlsExtensionDamager::FilterExtension(
uint16_t extension_type, const DataBuffer& input, DataBuffer* output) {
if (extension_type != extension_) {
return KEEP;
}
*output = input;
output->data()[index_] += 73; // Increment selected for maximum damage
return CHANGE;
}
PacketFilter::Action TlsExtensionInjector::FilterHandshake(
const HandshakeHeader& header, const DataBuffer& input,
DataBuffer* output) {

View file

@ -172,20 +172,19 @@ inline std::ostream& operator<<(std::ostream& stream,
hdr.WriteStream(stream);
stream << ' ';
switch (hdr.content_type()) {
case kTlsChangeCipherSpecType:
case ssl_ct_change_cipher_spec:
stream << "CCS";
break;
case kTlsAlertType:
case ssl_ct_alert:
stream << "Alert";
break;
case kTlsHandshakeType:
case kTlsAltHandshakeType:
case ssl_ct_handshake:
stream << "Handshake";
break;
case kTlsApplicationDataType:
case ssl_ct_application_data:
stream << "Data";
break;
case kTlsAckType:
case ssl_ct_ack:
stream << "ACK";
break;
default:
@ -301,7 +300,7 @@ class TlsRecordRecorder : public TlsRecordFilter {
TlsRecordRecorder(const std::shared_ptr<TlsAgent>& a)
: TlsRecordFilter(a),
filter_(false),
ct_(content_handshake), // dummy (<optional> is C++14)
ct_(ssl_ct_handshake), // dummy (<optional> is C++14)
records_() {}
virtual PacketFilter::Action FilterRecord(const TlsRecordHeader& header,
const DataBuffer& input,
@ -466,6 +465,20 @@ class TlsExtensionInjector : public TlsHandshakeFilter {
const DataBuffer data_;
};
class TlsExtensionDamager : public TlsExtensionFilter {
public:
TlsExtensionDamager(const std::shared_ptr<TlsAgent>& a, uint16_t extension,
size_t index)
: TlsExtensionFilter(a), extension_(extension), index_(index) {}
virtual PacketFilter::Action FilterExtension(uint16_t extension_type,
const DataBuffer& input,
DataBuffer* output);
private:
uint16_t extension_;
size_t index_;
};
typedef std::function<void(void)> VoidFunction;
class AfterRecordN : public TlsRecordFilter {

View file

@ -11,7 +11,7 @@
#include "databuffer.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "nss_scoped_ptrs.h"
namespace nss_test {
@ -60,9 +60,11 @@ const std::string kHashName[] = {"None", "MD5", "SHA-1", "SHA-224",
"SHA-256", "SHA-384", "SHA-512"};
static void ImportKey(ScopedPK11SymKey* to, const DataBuffer& key,
PK11SlotInfo* slot) {
SSLHashType hash_type, PK11SlotInfo* slot) {
ASSERT_LT(hash_type, sizeof(kHashLength));
ASSERT_LE(kHashLength[hash_type], key.len());
SECItem key_item = {siBuffer, const_cast<uint8_t*>(key.data()),
static_cast<unsigned int>(key.len())};
static_cast<unsigned int>(kHashLength[hash_type])};
PK11SymKey* inner =
PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, PK11_OriginUnwrap,
@ -106,8 +108,8 @@ class TlsHkdfTest : public ::testing::Test,
}
void SetUp() {
ImportKey(&k1_, kKey1, slot_.get());
ImportKey(&k2_, kKey2, slot_.get());
ImportKey(&k1_, kKey1, hash_type_, slot_.get());
ImportKey(&k2_, kKey2, hash_type_, slot_.get());
}
void VerifyKey(const ScopedPK11SymKey& key, const DataBuffer& expected) {
@ -183,9 +185,9 @@ TEST_P(TlsHkdfTest, HkdfKey1Only) {
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0x11, 0x87, 0x38, 0x28, 0xa9, 0x19, 0x78, 0x11, 0x33, 0x91, 0x24,
0xb5, 0x8a, 0x1b, 0xb0, 0x9f, 0x7f, 0x0d, 0x8d, 0xbb, 0x10, 0xf4,
0x9c, 0x54, 0xbd, 0x1f, 0xd8, 0x85, 0xcd, 0x15, 0x30, 0x33},
{0x41, 0x6c, 0x53, 0x92, 0xb9, 0xf3, 0x6d, 0xf1, 0x88, 0xe9, 0x0e,
0xb1, 0x4d, 0x17, 0xbf, 0x0d, 0xa1, 0x90, 0xbf, 0xdb, 0x7f, 0x1f,
0x49, 0x56, 0xe6, 0xe5, 0x66, 0xa5, 0x69, 0xc8, 0xb1, 0x5c},
{0x51, 0xb1, 0xd5, 0xb4, 0x59, 0x79, 0x79, 0x08, 0x4a, 0x15, 0xb2, 0xdb,
0x84, 0xd3, 0xd6, 0xbc, 0xfc, 0x93, 0x45, 0xd9, 0xdc, 0x74, 0xda, 0x1a,
0x57, 0xc2, 0x76, 0x9f, 0x3f, 0x83, 0x45, 0x2f, 0xf6, 0xf3, 0x56, 0x1f,
@ -201,11 +203,9 @@ TEST_P(TlsHkdfTest, HkdfKey2Only) {
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{
0x2f, 0x5f, 0x78, 0xd0, 0xa4, 0xc4, 0x36, 0xee, 0x6c, 0x8a, 0x4e,
0xf9, 0xd0, 0x43, 0x81, 0x02, 0x13, 0xfd, 0x47, 0x83, 0x63, 0x3a,
0xd2, 0xe1, 0x40, 0x6d, 0x2d, 0x98, 0x00, 0xfd, 0xc1, 0x87,
},
{0x16, 0xaf, 0x00, 0x54, 0x3a, 0x56, 0xc8, 0x26, 0xa2, 0xa7, 0xfc,
0xb6, 0x34, 0x66, 0x8a, 0xfd, 0x36, 0xdc, 0x8e, 0xce, 0xc4, 0xd2,
0x6c, 0x7a, 0xdc, 0xe3, 0x70, 0x36, 0x3d, 0x60, 0xfa, 0x0b},
{0x7b, 0x40, 0xf9, 0xef, 0x91, 0xff, 0xc9, 0xd1, 0x29, 0x24, 0x5c, 0xbf,
0xf8, 0x82, 0x76, 0x68, 0xae, 0x4b, 0x63, 0xe8, 0x03, 0xdd, 0x39, 0xa8,
0xd4, 0x6a, 0xf6, 0xe5, 0xec, 0xea, 0xf8, 0x7d, 0x91, 0x71, 0x81, 0xf1,
@ -221,11 +221,9 @@ TEST_P(TlsHkdfTest, HkdfKey1Key2) {
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{
0x79, 0x53, 0xb8, 0xdd, 0x6b, 0x98, 0xce, 0x00, 0xb7, 0xdc, 0xe8,
0x03, 0x70, 0x8c, 0xe3, 0xac, 0x06, 0x8b, 0x22, 0xfd, 0x0e, 0x34,
0x48, 0xe6, 0xe5, 0xe0, 0x8a, 0xd6, 0x16, 0x18, 0xe5, 0x48,
},
{0xa5, 0x68, 0x02, 0x5a, 0x95, 0xc9, 0x7f, 0x55, 0x38, 0xbc, 0xf7,
0x97, 0xcc, 0x0f, 0xd5, 0xf6, 0xa8, 0x8d, 0x15, 0xbc, 0x0e, 0x85,
0x74, 0x70, 0x3c, 0xa3, 0x65, 0xbd, 0x76, 0xcf, 0x9f, 0xd3},
{0x01, 0x93, 0xc0, 0x07, 0x3f, 0x6a, 0x83, 0x0e, 0x2e, 0x4f, 0xb2, 0x58,
0xe4, 0x00, 0x08, 0x5c, 0x68, 0x9c, 0x37, 0x32, 0x00, 0x37, 0xff, 0xc3,
0x1c, 0x5b, 0x98, 0x0b, 0x02, 0x92, 0x3f, 0xfd, 0x73, 0x5a, 0x6f, 0x2a,
@ -241,9 +239,9 @@ TEST_P(TlsHkdfTest, HkdfExpandLabel) {
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0xc6, 0xdd, 0x6e, 0xc4, 0x76, 0xb8, 0x55, 0xf2, 0xa4, 0xfc, 0x59,
0x04, 0xa4, 0x90, 0xdc, 0xa7, 0xa7, 0x0d, 0x94, 0x8f, 0xc2, 0xdc,
0x15, 0x6d, 0x48, 0x93, 0x9d, 0x05, 0xbb, 0x9a, 0xbc, 0xc1},
{0x3e, 0x4e, 0x6e, 0xd0, 0xbc, 0xc4, 0xf4, 0xff, 0xf0, 0xf5, 0x69,
0xd0, 0x6c, 0x1e, 0x0e, 0x10, 0x32, 0xaa, 0xd7, 0xa3, 0xef, 0xf6,
0xa8, 0x65, 0x8e, 0xbe, 0xee, 0xc7, 0x1f, 0x01, 0x6d, 0x3c},
{0x41, 0xea, 0x77, 0x09, 0x8c, 0x90, 0x04, 0x10, 0xec, 0xbc, 0x37, 0xd8,
0x5b, 0x54, 0xcd, 0x7b, 0x08, 0x15, 0x13, 0x20, 0xed, 0x1e, 0x3f, 0x54,
0x74, 0xf7, 0x8b, 0x06, 0x38, 0x28, 0x06, 0x37, 0x75, 0x23, 0xa2, 0xb7,