update master-with-bazel from master branch
This commit is contained in:
@@ -2469,9 +2469,9 @@ OPENSSL_EXPORT int SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, const void *in,
|
||||
// When decrypting a ticket, |encrypt| will be zero. |key_name| will point to a
|
||||
// 16-byte key name and |iv| points to an IV. The length of the IV consumed must
|
||||
// match |EVP_CIPHER_CTX_iv_length| of the cipher selected. In this mode,
|
||||
// |callback| returns -1 to abort the handshake, 0 if decrypting the ticket
|
||||
// failed, and 1 or 2 on success. If it returns 2, the ticket will be renewed.
|
||||
// This may be used to re-key the ticket.
|
||||
// |callback| returns -1 to abort the handshake, 0 if the ticket key was
|
||||
// unrecognized, and 1 or 2 on success. If it returns 2, the ticket will be
|
||||
// renewed. This may be used to re-key the ticket.
|
||||
//
|
||||
// WARNING: |callback| wildly breaks the usual return value convention and is
|
||||
// called in two different modes.
|
||||
|
||||
@@ -101,6 +101,9 @@ bool RetryAsync(SSL *ssl, int ret) {
|
||||
case SSL_ERROR_WANT_CERTIFICATE_VERIFY:
|
||||
test_state->custom_verify_ready = true;
|
||||
return true;
|
||||
case SSL_ERROR_PENDING_TICKET:
|
||||
test_state->async_ticket_decrypt_ready = true;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8574,54 +8574,65 @@ func addExtensionTests() {
|
||||
resumeSession: true,
|
||||
expectResumeRejected: true,
|
||||
})
|
||||
// Test the ticket callback, with and without renewal.
|
||||
testCases = append(testCases, testCase{
|
||||
protocol: protocol,
|
||||
testType: serverTest,
|
||||
name: "TicketCallback-" + suffix,
|
||||
config: Config{
|
||||
MaxVersion: ver.version,
|
||||
},
|
||||
resumeSession: true,
|
||||
flags: []string{"-use-ticket-callback"},
|
||||
})
|
||||
testCases = append(testCases, testCase{
|
||||
protocol: protocol,
|
||||
testType: serverTest,
|
||||
name: "TicketCallback-Renew-" + suffix,
|
||||
config: Config{
|
||||
MaxVersion: ver.version,
|
||||
Bugs: ProtocolBugs{
|
||||
ExpectNewTicket: true,
|
||||
// Test the ticket callbacks.
|
||||
for _, aeadCallback := range []bool{false, true} {
|
||||
flag := "-use-ticket-callback"
|
||||
callbackSuffix := suffix
|
||||
if aeadCallback {
|
||||
flag = "-use-ticket-aead-callback"
|
||||
callbackSuffix += "-AEAD"
|
||||
}
|
||||
testCases = append(testCases, testCase{
|
||||
protocol: protocol,
|
||||
testType: serverTest,
|
||||
name: "TicketCallback-" + callbackSuffix,
|
||||
config: Config{
|
||||
MaxVersion: ver.version,
|
||||
},
|
||||
},
|
||||
flags: []string{"-use-ticket-callback", "-renew-ticket"},
|
||||
resumeSession: true,
|
||||
})
|
||||
resumeSession: true,
|
||||
flags: []string{flag},
|
||||
})
|
||||
// Only the old callback supports renewal.
|
||||
if !aeadCallback {
|
||||
testCases = append(testCases, testCase{
|
||||
protocol: protocol,
|
||||
testType: serverTest,
|
||||
name: "TicketCallback-Renew-" + callbackSuffix,
|
||||
config: Config{
|
||||
MaxVersion: ver.version,
|
||||
Bugs: ProtocolBugs{
|
||||
ExpectNewTicket: true,
|
||||
},
|
||||
},
|
||||
flags: []string{flag, "-renew-ticket"},
|
||||
resumeSession: true,
|
||||
})
|
||||
}
|
||||
|
||||
// Test that the ticket callback is only called once when everything before
|
||||
// it in the ClientHello is asynchronous. This corrupts the ticket so
|
||||
// certificate selection callbacks run.
|
||||
testCases = append(testCases, testCase{
|
||||
protocol: protocol,
|
||||
testType: serverTest,
|
||||
name: "TicketCallback-SingleCall-" + suffix,
|
||||
config: Config{
|
||||
MaxVersion: ver.version,
|
||||
Bugs: ProtocolBugs{
|
||||
FilterTicket: func(in []byte) ([]byte, error) {
|
||||
in[len(in)-1] ^= 1
|
||||
return in, nil
|
||||
// Test that the ticket callback is only called once when everything before
|
||||
// it in the ClientHello is asynchronous. This corrupts the ticket so
|
||||
// certificate selection callbacks run.
|
||||
testCases = append(testCases, testCase{
|
||||
protocol: protocol,
|
||||
testType: serverTest,
|
||||
name: "TicketCallback-SingleCall-" + callbackSuffix,
|
||||
config: Config{
|
||||
MaxVersion: ver.version,
|
||||
Bugs: ProtocolBugs{
|
||||
FilterTicket: func(in []byte) ([]byte, error) {
|
||||
in[len(in)-1] ^= 1
|
||||
return in, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
resumeSession: true,
|
||||
expectResumeRejected: true,
|
||||
flags: []string{
|
||||
"-use-ticket-callback",
|
||||
"-async",
|
||||
},
|
||||
})
|
||||
resumeSession: true,
|
||||
expectResumeRejected: true,
|
||||
flags: []string{
|
||||
flag,
|
||||
"-async",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Resume with various lengths of ticket session id.
|
||||
if ver.version < VersionTLS13 {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/base64.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/hpke.h>
|
||||
@@ -354,7 +355,8 @@ const Flag<TestConfig> *FindFlag(const char *name) {
|
||||
BoolFlag("-implicit-handshake", &TestConfig::implicit_handshake),
|
||||
BoolFlag("-use-early-callback", &TestConfig::use_early_callback),
|
||||
BoolFlag("-fail-early-callback", &TestConfig::fail_early_callback),
|
||||
BoolFlag("-fail-early-callback-ech-rewind", &TestConfig::fail_early_callback_ech_rewind),
|
||||
BoolFlag("-fail-early-callback-ech-rewind",
|
||||
&TestConfig::fail_early_callback_ech_rewind),
|
||||
BoolFlag("-install-ddos-callback", &TestConfig::install_ddos_callback),
|
||||
BoolFlag("-fail-ddos-callback", &TestConfig::fail_ddos_callback),
|
||||
BoolFlag("-fail-cert-callback", &TestConfig::fail_cert_callback),
|
||||
@@ -375,9 +377,10 @@ const Flag<TestConfig> *FindFlag(const char *name) {
|
||||
&TestConfig::expect_reject_early_data),
|
||||
BoolFlag("-expect-no-offer-early-data",
|
||||
&TestConfig::expect_no_offer_early_data),
|
||||
BoolFlag("-expect-no-server-name",
|
||||
&TestConfig::expect_no_server_name),
|
||||
BoolFlag("-expect-no-server-name", &TestConfig::expect_no_server_name),
|
||||
BoolFlag("-use-ticket-callback", &TestConfig::use_ticket_callback),
|
||||
BoolFlag("-use-ticket-aead-callback",
|
||||
&TestConfig::use_ticket_aead_callback),
|
||||
BoolFlag("-renew-ticket", &TestConfig::renew_ticket),
|
||||
BoolFlag("-enable-early-data", &TestConfig::enable_early_data),
|
||||
Base64Flag("-expect-ocsp-response", &TestConfig::expect_ocsp_response),
|
||||
@@ -1214,6 +1217,88 @@ static const SSL_PRIVATE_KEY_METHOD g_async_private_key_method = {
|
||||
AsyncPrivateKeyComplete,
|
||||
};
|
||||
|
||||
static size_t AsyncTicketMaxOverhead(SSL *ssl) {
|
||||
const EVP_AEAD *aead = EVP_aead_aes_128_gcm_siv();
|
||||
return EVP_AEAD_max_overhead(aead) + EVP_AEAD_nonce_length(aead);
|
||||
}
|
||||
|
||||
static int AsyncTicketSeal(SSL *ssl, uint8_t *out, size_t *out_len,
|
||||
size_t max_out_len, const uint8_t *in,
|
||||
size_t in_len) {
|
||||
auto out_span = bssl::MakeSpan(out, max_out_len);
|
||||
// Encrypt the ticket with the all zero key and a random nonce.
|
||||
static const uint8_t kKey[16] = {0};
|
||||
const EVP_AEAD *aead = EVP_aead_aes_128_gcm_siv();
|
||||
size_t nonce_len = EVP_AEAD_nonce_length(aead);
|
||||
if (out_span.size() < nonce_len) {
|
||||
return 0;
|
||||
}
|
||||
auto nonce = out_span.first(nonce_len);
|
||||
out_span = out_span.subspan(nonce_len);
|
||||
RAND_bytes(nonce.data(), nonce.size());
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
size_t len;
|
||||
if (!EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm_siv(), kKey,
|
||||
sizeof(kKey), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
|
||||
!EVP_AEAD_CTX_seal(ctx.get(), out_span.data(), &len, out_span.size(),
|
||||
nonce.data(), nonce.size(), in, in_len,
|
||||
/*ad=*/nullptr, /*ad_len=*/0)) {
|
||||
return 0;
|
||||
}
|
||||
*out_len = nonce.size() + len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ssl_ticket_aead_result_t AsyncTicketOpen(SSL *ssl, uint8_t *out,
|
||||
size_t *out_len,
|
||||
size_t max_out_len,
|
||||
const uint8_t *in,
|
||||
size_t in_len) {
|
||||
auto in_span = bssl::MakeSpan(in, in_len);
|
||||
const TestConfig *test_config = GetTestConfig(ssl);
|
||||
TestState *test_state = GetTestState(ssl);
|
||||
if (test_state->ticket_decrypt_done) {
|
||||
fprintf(stderr, "AsyncTicketOpen called after completion.\n");
|
||||
return ssl_ticket_aead_error;
|
||||
}
|
||||
if (test_config->renew_ticket) {
|
||||
fprintf(stderr, "-renew-ticket not supported with async tickets.\n");
|
||||
return ssl_ticket_aead_error;
|
||||
}
|
||||
if (test_config->async && !test_state->async_ticket_decrypt_ready) {
|
||||
return ssl_ticket_aead_retry;
|
||||
}
|
||||
|
||||
const EVP_AEAD *aead = EVP_aead_aes_128_gcm_siv();
|
||||
size_t nonce_len = EVP_AEAD_nonce_length(aead);
|
||||
if (in_span.size() < nonce_len) {
|
||||
return ssl_ticket_aead_error;
|
||||
}
|
||||
auto nonce = in_span.first(nonce_len);
|
||||
in_span = in_span.subspan(nonce_len);
|
||||
|
||||
static const uint8_t kKey[16] = {0};
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm_siv(), kKey,
|
||||
sizeof(kKey), EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
|
||||
return ssl_ticket_aead_error;
|
||||
}
|
||||
if (!EVP_AEAD_CTX_open(ctx.get(), out, out_len, max_out_len, nonce.data(),
|
||||
nonce.size(), in_span.data(), in_span.size(),
|
||||
/*ad=*/nullptr, /*ad_len=*/0)) {
|
||||
ERR_clear_error();
|
||||
return ssl_ticket_aead_ignore_ticket;
|
||||
}
|
||||
test_state->ticket_decrypt_done = true;
|
||||
return ssl_ticket_aead_success;
|
||||
}
|
||||
|
||||
static const SSL_TICKET_AEAD_METHOD g_async_ticket_aead_method = {
|
||||
AsyncTicketMaxOverhead,
|
||||
AsyncTicketSeal,
|
||||
AsyncTicketOpen,
|
||||
};
|
||||
|
||||
static bssl::UniquePtr<SSL_CREDENTIAL> CredentialFromConfig(
|
||||
const TestConfig &config, const CredentialConfig &cred_config, int number) {
|
||||
bssl::UniquePtr<SSL_CREDENTIAL> cred;
|
||||
@@ -1758,8 +1843,10 @@ bssl::UniquePtr<SSL_CTX> TestConfig::SetupCtx(SSL_CTX *old_ctx) const {
|
||||
SSL_CTX_set_info_callback(ssl_ctx.get(), InfoCallback);
|
||||
SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
|
||||
|
||||
if (use_ticket_callback || handshake_hints) {
|
||||
// If using handshake hints, always enable the ticket callback, so we can
|
||||
if (use_ticket_aead_callback) {
|
||||
SSL_CTX_set_ticket_aead_method(ssl_ctx.get(), &g_async_ticket_aead_method);
|
||||
} else if (use_ticket_callback || handshake_hints) {
|
||||
// If using handshake hints, always enable some ticket callback, so we can
|
||||
// check that hints only mismatch when allowed. The ticket callback also
|
||||
// uses a constant key, which simplifies the test.
|
||||
SSL_CTX_set_tlsext_ticket_key_cb(ssl_ctx.get(), TicketKeyCallback);
|
||||
|
||||
@@ -137,6 +137,7 @@ struct TestConfig {
|
||||
bool expect_no_offer_early_data = false;
|
||||
bool expect_no_server_name = false;
|
||||
bool use_ticket_callback = false;
|
||||
bool use_ticket_aead_callback = false;
|
||||
bool renew_ticket = false;
|
||||
bool enable_early_data = false;
|
||||
std::string ocsp_response;
|
||||
|
||||
@@ -56,6 +56,7 @@ struct TestState {
|
||||
unsigned private_key_retries = 0;
|
||||
bool got_new_session = false;
|
||||
bssl::UniquePtr<SSL_SESSION> new_session;
|
||||
bool async_ticket_decrypt_ready = false;
|
||||
bool ticket_decrypt_done = false;
|
||||
bool alpn_select_done = false;
|
||||
bool early_callback_ready = false;
|
||||
|
||||
Reference in New Issue
Block a user