Add tests for the padding extension.
This sort of test is more suitable for ssl_test than runner. This should stress all the various cases around padding. Use tickets rather than hostnames to inflate the ClientHello because there's a fairly tight maximum hostname length. Change-Id: Ibd43aaa7acb9bf5fa00a9d2548d2101e5bb147d3 Reviewed-on: https://boringssl-review.googlesource.com/5480 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
2399485e0b
commit
422fe08672
109
ssl/ssl_test.cc
109
ssl/ssl_test.cc
@ -549,6 +549,112 @@ static bool TestCipherGetRFCName(void) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// CreateSessionWithTicket returns a sample |SSL_SESSION| with the ticket
|
||||
// replaced for one of length |ticket_len| or nullptr on failure.
|
||||
static ScopedSSL_SESSION CreateSessionWithTicket(size_t ticket_len) {
|
||||
std::vector<uint8_t> der;
|
||||
if (!DecodeBase64(&der, kOpenSSLSession)) {
|
||||
return nullptr;
|
||||
}
|
||||
ScopedSSL_SESSION session(SSL_SESSION_from_bytes(bssl::vector_data(&der),
|
||||
der.size()));
|
||||
if (!session) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Swap out the ticket for a garbage one.
|
||||
OPENSSL_free(session->tlsext_tick);
|
||||
session->tlsext_tick = reinterpret_cast<uint8_t*>(OPENSSL_malloc(ticket_len));
|
||||
if (session->tlsext_tick == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
memset(session->tlsext_tick, 'a', ticket_len);
|
||||
session->tlsext_ticklen = ticket_len;
|
||||
return session;
|
||||
}
|
||||
|
||||
// GetClientHelloLen creates a client SSL connection with a ticket of length
|
||||
// |ticket_len| and records the ClientHello. It returns the length of the
|
||||
// ClientHello, not including the record header, on success and zero on error.
|
||||
static size_t GetClientHelloLen(size_t ticket_len) {
|
||||
ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
|
||||
ScopedSSL_SESSION session = CreateSessionWithTicket(ticket_len);
|
||||
if (!ctx || !session) {
|
||||
return 0;
|
||||
}
|
||||
ScopedSSL ssl(SSL_new(ctx.get()));
|
||||
ScopedBIO bio(BIO_new(BIO_s_mem()));
|
||||
if (!ssl || !bio || !SSL_set_session(ssl.get(), session.get())) {
|
||||
return 0;
|
||||
}
|
||||
// Do not configure a reading BIO, but record what's written to a memory BIO.
|
||||
SSL_set_bio(ssl.get(), nullptr /* rbio */, BIO_up_ref(bio.get()));
|
||||
int ret = SSL_connect(ssl.get());
|
||||
if (ret > 0) {
|
||||
// SSL_connect should fail without a BIO to write to.
|
||||
return 0;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
const uint8_t *unused;
|
||||
size_t client_hello_len;
|
||||
if (!BIO_mem_contents(bio.get(), &unused, &client_hello_len) ||
|
||||
client_hello_len <= SSL3_RT_HEADER_LENGTH) {
|
||||
return 0;
|
||||
}
|
||||
return client_hello_len - SSL3_RT_HEADER_LENGTH;
|
||||
}
|
||||
|
||||
struct PaddingTest {
|
||||
size_t input_len, padded_len;
|
||||
};
|
||||
|
||||
static const PaddingTest kPaddingTests[] = {
|
||||
// ClientHellos of length below 0x100 do not require padding.
|
||||
{0xfe, 0xfe},
|
||||
{0xff, 0xff},
|
||||
// ClientHellos of length 0x100 through 0x1fb are padded up to 0x200.
|
||||
{0x100, 0x200},
|
||||
{0x123, 0x200},
|
||||
{0x1fb, 0x200},
|
||||
// ClientHellos of length 0x1fc through 0x1ff get padded beyond 0x200. The
|
||||
// padding extension takes a minimum of four bytes plus one required content
|
||||
// byte. (To work around yet more server bugs, we avoid empty final
|
||||
// extensions.)
|
||||
{0x1fc, 0x201},
|
||||
{0x1fd, 0x202},
|
||||
{0x1fe, 0x203},
|
||||
{0x1ff, 0x204},
|
||||
// Finally, larger ClientHellos need no padding.
|
||||
{0x200, 0x200},
|
||||
{0x201, 0x201},
|
||||
};
|
||||
|
||||
static bool TestPaddingExtension() {
|
||||
// Sample a baseline length.
|
||||
size_t base_len = GetClientHelloLen(1);
|
||||
if (base_len == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const PaddingTest &test : kPaddingTests) {
|
||||
if (base_len > test.input_len) {
|
||||
fprintf(stderr, "Baseline ClientHello too long.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t padded_len = GetClientHelloLen(1 + test.input_len - base_len);
|
||||
if (padded_len != test.padded_len) {
|
||||
fprintf(stderr, "%u-byte ClientHello padded to %u bytes, not %u.\n",
|
||||
static_cast<unsigned>(test.input_len),
|
||||
static_cast<unsigned>(padded_len),
|
||||
static_cast<unsigned>(test.padded_len));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
SSL_library_init();
|
||||
|
||||
@ -566,7 +672,8 @@ int main(void) {
|
||||
!TestDefaultVersion(0, &DTLS_method) ||
|
||||
!TestDefaultVersion(DTLS1_VERSION, &DTLSv1_method) ||
|
||||
!TestDefaultVersion(DTLS1_2_VERSION, &DTLSv1_2_method) ||
|
||||
!TestCipherGetRFCName()) {
|
||||
!TestCipherGetRFCName() ||
|
||||
!TestPaddingExtension()) {
|
||||
ERR_print_errors_fp(stderr);
|
||||
return 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user