Change-Id: I6df623f3e9bc88acc52043f16b34649b7af67663 Reviewed-on: https://boringssl-review.googlesource.com/5531 Reviewed-by: Adam Langley <alangley@gmail.com>kris/onging/CECPQ3_patch15
@@ -966,7 +966,37 @@ typedef struct ssl_private_key_method_st { | |||
* it is an error to call |sign_complete| if there is no pending |sign| | |||
* operation in progress on |ssl|. */ | |||
enum ssl_private_key_result_t (*sign_complete)(SSL *ssl, uint8_t *out, | |||
size_t *out_len, size_t max_out); | |||
size_t *out_len, | |||
size_t max_out); | |||
/* decrypt decrypts |in_len| bytes of encrypted data from |in|. On success it | |||
* returns |ssl_private_key_success|, writes at most |max_out| bytes of | |||
* decrypted data to |out| and sets |*out_len| to the actual number of bytes | |||
* written. On failure it returns |ssl_private_key_failure|. If the operation | |||
* has not completed, it returns |ssl_private_key_retry|. The caller should | |||
* arrange for the high-level operation on |ssl| to be retried when the | |||
* operation is completed, which will result in a call to |decrypt_complete|. | |||
* This function only works with RSA keys and should perform a raw RSA | |||
* decryption operation with no padding. | |||
* | |||
* It is an error to call |decrypt| while another private key operation is in | |||
* progress on |ssl|. */ | |||
enum ssl_private_key_result_t (*decrypt)(SSL *ssl, uint8_t *out, | |||
size_t *out_len, size_t max_out, | |||
const uint8_t *in, size_t in_len); | |||
/* decrypt_complete completes a pending |decrypt| operation. If the operation | |||
* has completed, it returns |ssl_private_key_success| and writes the result | |||
* to |out| as in |decrypt|. Otherwise, it returns |ssl_private_key_failure| | |||
* on failure and |ssl_private_key_retry| if the operation is still in | |||
* progress. | |||
* | |||
* |decrypt_complete| may be called arbitrarily many times before completion, | |||
* but it is an error to call |decrypt_complete| if there is no pending | |||
* |decrypt| operation in progress on |ssl|. */ | |||
enum ssl_private_key_result_t (*decrypt_complete)(SSL *ssl, uint8_t *out, | |||
size_t *out_len, | |||
size_t max_out); | |||
} SSL_PRIVATE_KEY_METHOD; | |||
/* SSL_set_private_key_method configures a custom private key on |ssl|. | |||
@@ -382,6 +382,7 @@ OPENSSL_COMPILE_ASSERT( | |||
#define SSL3_ST_SR_CERT_B (0x181 | SSL_ST_ACCEPT) | |||
#define SSL3_ST_SR_KEY_EXCH_A (0x190 | SSL_ST_ACCEPT) | |||
#define SSL3_ST_SR_KEY_EXCH_B (0x191 | SSL_ST_ACCEPT) | |||
#define SSL3_ST_SR_KEY_EXCH_C (0x192 | SSL_ST_ACCEPT) | |||
#define SSL3_ST_SR_CERT_VRFY_A (0x1A0 | SSL_ST_ACCEPT) | |||
#define SSL3_ST_SR_CERT_VRFY_B (0x1A1 | SSL_ST_ACCEPT) | |||
#define SSL3_ST_SR_CHANGE (0x1B0 | SSL_ST_ACCEPT) | |||
@@ -330,6 +330,7 @@ int dtls1_accept(SSL *s) { | |||
case SSL3_ST_SR_KEY_EXCH_A: | |||
case SSL3_ST_SR_KEY_EXCH_B: | |||
case SSL3_ST_SR_KEY_EXCH_C: | |||
ret = ssl3_get_client_key_exchange(s); | |||
if (ret <= 0) { | |||
goto end; | |||
@@ -464,6 +464,13 @@ enum ssl_private_key_result_t ssl_private_key_sign( | |||
enum ssl_private_key_result_t ssl_private_key_sign_complete( | |||
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out); | |||
enum ssl_private_key_result_t ssl_private_key_decrypt( | |||
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, | |||
const uint8_t *in, size_t in_len); | |||
enum ssl_private_key_result_t ssl_private_key_decrypt_complete( | |||
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out); | |||
/* Custom extensions */ | |||
@@ -399,6 +399,7 @@ int ssl3_accept(SSL *s) { | |||
case SSL3_ST_SR_KEY_EXCH_A: | |||
case SSL3_ST_SR_KEY_EXCH_B: | |||
case SSL3_ST_SR_KEY_EXCH_C: | |||
ret = ssl3_get_client_key_exchange(s); | |||
if (ret <= 0) { | |||
goto end; | |||
@@ -1586,16 +1587,13 @@ uint64_t OPENSSL_get_d5_bug_use_count(void) { | |||
} | |||
int ssl3_get_client_key_exchange(SSL *s) { | |||
int al, ok; | |||
long n; | |||
int al; | |||
CBS client_key_exchange; | |||
uint32_t alg_k; | |||
uint32_t alg_a; | |||
uint8_t *premaster_secret = NULL; | |||
size_t premaster_secret_len = 0; | |||
RSA *rsa = NULL; | |||
uint8_t *decrypt_buf = NULL; | |||
EVP_PKEY *pkey = NULL; | |||
BIGNUM *pub = NULL; | |||
DH *dh_srvr; | |||
@@ -1606,17 +1604,18 @@ int ssl3_get_client_key_exchange(SSL *s) { | |||
unsigned int psk_len = 0; | |||
uint8_t psk[PSK_MAX_PSK_LEN]; | |||
n = s->method->ssl_get_message(s, SSL3_ST_SR_KEY_EXCH_A, | |||
SSL3_ST_SR_KEY_EXCH_B, | |||
SSL3_MT_CLIENT_KEY_EXCHANGE, 2048, /* ??? */ | |||
ssl_hash_message, &ok); | |||
if (!ok) { | |||
return n; | |||
if (s->state == SSL3_ST_SR_KEY_EXCH_A || | |||
s->state == SSL3_ST_SR_KEY_EXCH_B) { | |||
int ok; | |||
const long n = s->method->ssl_get_message( | |||
s, SSL3_ST_SR_KEY_EXCH_A, SSL3_ST_SR_KEY_EXCH_B, | |||
SSL3_MT_CLIENT_KEY_EXCHANGE, 2048 /* ??? */, ssl_hash_message, &ok); | |||
if (!ok) { | |||
return n; | |||
} | |||
} | |||
CBS_init(&client_key_exchange, s->init_msg, n); | |||
CBS_init(&client_key_exchange, s->init_msg, s->init_num); | |||
alg_k = s->s3->tmp.new_cipher->algorithm_mkey; | |||
alg_a = s->s3->tmp.new_cipher->algorithm_auth; | |||
@@ -1673,72 +1672,82 @@ int ssl3_get_client_key_exchange(SSL *s) { | |||
CBS encrypted_premaster_secret; | |||
uint8_t rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH]; | |||
uint8_t good; | |||
size_t rsa_size, decrypt_len, premaster_index, j; | |||
size_t decrypt_len, premaster_index, j; | |||
const size_t rsa_size = ssl_private_key_max_signature_len(s); | |||
pkey = s->cert->privatekey; | |||
if (pkey == NULL || pkey->type != EVP_PKEY_RSA || pkey->pkey.rsa == NULL) { | |||
al = SSL_AD_HANDSHAKE_FAILURE; | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_RSA_CERTIFICATE); | |||
goto f_err; | |||
/* Allocate a buffer large enough for an RSA decryption. */ | |||
decrypt_buf = OPENSSL_malloc(rsa_size); | |||
if (decrypt_buf == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); | |||
goto err; | |||
} | |||
rsa = pkey->pkey.rsa; | |||
/* TLS and [incidentally] DTLS{0xFEFF} */ | |||
if (s->version > SSL3_VERSION) { | |||
CBS copy = client_key_exchange; | |||
if (!CBS_get_u16_length_prefixed(&client_key_exchange, | |||
&encrypted_premaster_secret) || | |||
CBS_len(&client_key_exchange) != 0) { | |||
if (!(s->options & SSL_OP_TLS_D5_BUG)) { | |||
al = SSL_AD_DECODE_ERROR; | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); | |||
goto f_err; | |||
} else { | |||
CRYPTO_STATIC_MUTEX_lock_write(&g_d5_bug_lock); | |||
g_d5_bug_use_count++; | |||
CRYPTO_STATIC_MUTEX_unlock(&g_d5_bug_lock); | |||
encrypted_premaster_secret = copy; | |||
enum ssl_private_key_result_t decrypt_result; | |||
if (s->state == SSL3_ST_SR_KEY_EXCH_B) { | |||
if (!ssl_has_private_key(s) || ssl_private_key_type(s) != EVP_PKEY_RSA) { | |||
al = SSL_AD_HANDSHAKE_FAILURE; | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_RSA_CERTIFICATE); | |||
goto f_err; | |||
} | |||
/* TLS and [incidentally] DTLS{0xFEFF} */ | |||
if (s->version > SSL3_VERSION) { | |||
CBS copy = client_key_exchange; | |||
if (!CBS_get_u16_length_prefixed(&client_key_exchange, | |||
&encrypted_premaster_secret) || | |||
CBS_len(&client_key_exchange) != 0) { | |||
if (!(s->options & SSL_OP_TLS_D5_BUG)) { | |||
al = SSL_AD_DECODE_ERROR; | |||
OPENSSL_PUT_ERROR(SSL, | |||
SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG); | |||
goto f_err; | |||
} else { | |||
CRYPTO_STATIC_MUTEX_lock_write(&g_d5_bug_lock); | |||
g_d5_bug_use_count++; | |||
CRYPTO_STATIC_MUTEX_unlock(&g_d5_bug_lock); | |||
encrypted_premaster_secret = copy; | |||
} | |||
} | |||
} else { | |||
encrypted_premaster_secret = client_key_exchange; | |||
} | |||
} else { | |||
encrypted_premaster_secret = client_key_exchange; | |||
} | |||
/* Reject overly short RSA keys because we want to be sure that the buffer | |||
* size makes it safe to iterate over the entire size of a premaster secret | |||
* (SSL_MAX_MASTER_KEY_LENGTH). The actual expected size is larger due to | |||
* RSA padding, but the bound is sufficient to be safe. */ | |||
rsa_size = RSA_size(rsa); | |||
if (rsa_size < SSL_MAX_MASTER_KEY_LENGTH) { | |||
al = SSL_AD_DECRYPT_ERROR; | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED); | |||
goto f_err; | |||
} | |||
/* Reject overly short RSA keys because we want to be sure that the buffer | |||
* size makes it safe to iterate over the entire size of a premaster | |||
* secret (SSL_MAX_MASTER_KEY_LENGTH). The actual expected size is larger | |||
* due to RSA padding, but the bound is sufficient to be safe. */ | |||
if (rsa_size < SSL_MAX_MASTER_KEY_LENGTH) { | |||
al = SSL_AD_DECRYPT_ERROR; | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED); | |||
goto f_err; | |||
} | |||
/* We must not leak whether a decryption failure occurs because of | |||
* Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, | |||
* section 7.4.7.1). The code follows that advice of the TLS RFC and | |||
* generates a random premaster secret for the case that the decrypt fails. | |||
* See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */ | |||
if (!RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret))) { | |||
goto err; | |||
/* Decrypt with no padding. PKCS#1 padding will be removed as part of the | |||
* timing-sensitive code below. */ | |||
decrypt_result = ssl_private_key_decrypt( | |||
s, decrypt_buf, &decrypt_len, rsa_size, | |||
CBS_data(&encrypted_premaster_secret), | |||
CBS_len(&encrypted_premaster_secret)); | |||
} else { | |||
assert(s->state == SSL3_ST_SR_KEY_EXCH_C); | |||
/* Complete async decrypt. */ | |||
decrypt_result = ssl_private_key_decrypt_complete( | |||
s, decrypt_buf, &decrypt_len, rsa_size); | |||
} | |||
/* Allocate a buffer large enough for an RSA decryption. */ | |||
decrypt_buf = OPENSSL_malloc(rsa_size); | |||
if (decrypt_buf == NULL) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE); | |||
goto err; | |||
switch (decrypt_result) { | |||
case ssl_private_key_success: | |||
s->rwstate = SSL_NOTHING; | |||
break; | |||
case ssl_private_key_failure: | |||
s->rwstate = SSL_NOTHING; | |||
goto err; | |||
case ssl_private_key_retry: | |||
s->rwstate = SSL_PRIVATE_KEY_OPERATION; | |||
s->state = SSL3_ST_SR_KEY_EXCH_C; | |||
goto err; | |||
} | |||
/* Decrypt with no padding. PKCS#1 padding will be removed as part of the | |||
* timing-sensitive code below. */ | |||
if (!RSA_decrypt(rsa, &decrypt_len, decrypt_buf, rsa_size, | |||
CBS_data(&encrypted_premaster_secret), | |||
CBS_len(&encrypted_premaster_secret), RSA_NO_PADDING)) { | |||
goto err; | |||
} | |||
if (decrypt_len != rsa_size) { | |||
/* This should never happen, but do a check so we do not read | |||
* uninitialized memory. */ | |||
@@ -1782,6 +1791,15 @@ int ssl3_get_client_key_exchange(SSL *s) { | |||
good &= constant_time_eq_8(premaster_secret[1], | |||
(unsigned)(s->client_version & 0xff)); | |||
/* We must not leak whether a decryption failure occurs because of | |||
* Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246, | |||
* section 7.4.7.1). The code follows that advice of the TLS RFC and | |||
* generates a random premaster secret for the case that the decrypt | |||
* fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1 */ | |||
if (!RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret))) { | |||
goto err; | |||
} | |||
/* Now copy rand_premaster_secret over premaster_secret using | |||
* decrypt_good_mask. */ | |||
for (j = 0; j < sizeof(rand_premaster_secret); j++) { | |||
@@ -376,3 +376,33 @@ enum ssl_private_key_result_t ssl_private_key_sign_complete( | |||
/* Only custom keys may be asynchronous. */ | |||
return ssl->cert->key_method->sign_complete(ssl, out, out_len, max_out); | |||
} | |||
enum ssl_private_key_result_t ssl_private_key_decrypt( | |||
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, | |||
const uint8_t *in, size_t in_len) { | |||
if (ssl->cert->key_method != NULL) { | |||
return ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in, | |||
in_len); | |||
} | |||
if (ssl_private_key_type(ssl) != EVP_PKEY_RSA) { | |||
/* Decrypt operations are only supported for RSA keys. */ | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
return ssl_private_key_failure; | |||
} | |||
enum ssl_private_key_result_t ret = ssl_private_key_failure; | |||
RSA *rsa = ssl->cert->privatekey->pkey.rsa; | |||
/* Decrypt with no padding. PKCS#1 padding will be removed as part | |||
* of the timing-sensitive code by the caller. */ | |||
if (RSA_decrypt(rsa, out_len, out, max_out, in, in_len, RSA_NO_PADDING)) { | |||
ret = ssl_private_key_success; | |||
} | |||
return ret; | |||
} | |||
enum ssl_private_key_result_t ssl_private_key_decrypt_complete( | |||
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) { | |||
/* Only custom keys may be asynchronous. */ | |||
return ssl->cert->key_method->decrypt_complete(ssl, out, out_len, max_out); | |||
} |
@@ -97,10 +97,10 @@ struct TestState { | |||
bool handshake_done = false; | |||
// private_key is the underlying private key used when testing custom keys. | |||
ScopedEVP_PKEY private_key; | |||
std::vector<uint8_t> signature; | |||
// signature_retries is the number of times an asynchronous sign operation has | |||
// been retried. | |||
unsigned signature_retries = 0; | |||
std::vector<uint8_t> private_key_result; | |||
// private_key_retries is the number of times an asynchronous private key | |||
// operation has been retried. | |||
unsigned private_key_retries = 0; | |||
bool got_new_session = false; | |||
}; | |||
@@ -153,7 +153,7 @@ static ssl_private_key_result_t AsyncPrivateKeySign( | |||
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, | |||
const EVP_MD *md, const uint8_t *in, size_t in_len) { | |||
TestState *test_state = GetTestState(ssl); | |||
if (!test_state->signature.empty()) { | |||
if (!test_state->private_key_result.empty()) { | |||
fprintf(stderr, "AsyncPrivateKeySign called with operation pending.\n"); | |||
abort(); | |||
} | |||
@@ -171,42 +171,103 @@ static ssl_private_key_result_t AsyncPrivateKeySign( | |||
!EVP_PKEY_sign(ctx.get(), nullptr, &len, in, in_len)) { | |||
return ssl_private_key_failure; | |||
} | |||
test_state->signature.resize(len); | |||
if (!EVP_PKEY_sign(ctx.get(), bssl::vector_data(&test_state->signature), &len, | |||
in, in_len)) { | |||
test_state->private_key_result.resize(len); | |||
if (!EVP_PKEY_sign(ctx.get(), bssl::vector_data( | |||
&test_state->private_key_result), &len, in, in_len)) { | |||
return ssl_private_key_failure; | |||
} | |||
test_state->signature.resize(len); | |||
test_state->private_key_result.resize(len); | |||
// The signature will be released asynchronously in |AsyncPrivateKeySignComplete|. | |||
// The signature will be released asynchronously in | |||
// |AsyncPrivateKeySignComplete|. | |||
return ssl_private_key_retry; | |||
} | |||
static ssl_private_key_result_t AsyncPrivateKeySignComplete( | |||
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) { | |||
TestState *test_state = GetTestState(ssl); | |||
if (test_state->signature.empty()) { | |||
if (test_state->private_key_result.empty()) { | |||
fprintf(stderr, | |||
"AsyncPrivateKeySignComplete called without operation pending.\n"); | |||
abort(); | |||
} | |||
if (test_state->signature_retries < 2) { | |||
if (test_state->private_key_retries < 2) { | |||
// Only return the signature on the second attempt, to test both incomplete | |||
// |sign| and |sign_complete|. | |||
return ssl_private_key_retry; | |||
} | |||
if (max_out < test_state->signature.size()) { | |||
if (max_out < test_state->private_key_result.size()) { | |||
fprintf(stderr, "Output buffer too small.\n"); | |||
return ssl_private_key_failure; | |||
} | |||
memcpy(out, bssl::vector_data(&test_state->signature), | |||
test_state->signature.size()); | |||
*out_len = test_state->signature.size(); | |||
memcpy(out, bssl::vector_data(&test_state->private_key_result), | |||
test_state->private_key_result.size()); | |||
*out_len = test_state->private_key_result.size(); | |||
test_state->signature.clear(); | |||
test_state->signature_retries = 0; | |||
test_state->private_key_result.clear(); | |||
test_state->private_key_retries = 0; | |||
return ssl_private_key_success; | |||
} | |||
static ssl_private_key_result_t AsyncPrivateKeyDecrypt( | |||
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, | |||
const uint8_t *in, size_t in_len) { | |||
TestState *test_state = GetTestState(ssl); | |||
if (!test_state->private_key_result.empty()) { | |||
fprintf(stderr, | |||
"AsyncPrivateKeyDecrypt called with operation pending.\n"); | |||
abort(); | |||
} | |||
EVP_PKEY *pkey = test_state->private_key.get(); | |||
if (pkey->type != EVP_PKEY_RSA || pkey->pkey.rsa == NULL) { | |||
fprintf(stderr, | |||
"AsyncPrivateKeyDecrypt called with incorrect key type.\n"); | |||
abort(); | |||
} | |||
RSA *rsa = pkey->pkey.rsa; | |||
test_state->private_key_result.resize(RSA_size(rsa)); | |||
if (!RSA_decrypt(rsa, out_len, | |||
bssl::vector_data(&test_state->private_key_result), | |||
RSA_size(rsa), in, in_len, RSA_NO_PADDING)) { | |||
return ssl_private_key_failure; | |||
} | |||
test_state->private_key_result.resize(*out_len); | |||
// The decryption will be released asynchronously in | |||
// |AsyncPrivateKeyDecryptComplete|. | |||
return ssl_private_key_retry; | |||
} | |||
static ssl_private_key_result_t AsyncPrivateKeyDecryptComplete( | |||
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) { | |||
TestState *test_state = GetTestState(ssl); | |||
if (test_state->private_key_result.empty()) { | |||
fprintf(stderr, | |||
"AsyncPrivateKeyDecryptComplete called without operation " | |||
"pending.\n"); | |||
abort(); | |||
} | |||
if (test_state->private_key_retries < 2) { | |||
// Only return the decryption on the second attempt, to test both incomplete | |||
// |decrypt| and |decrypt_complete|. | |||
return ssl_private_key_retry; | |||
} | |||
if (max_out < test_state->private_key_result.size()) { | |||
fprintf(stderr, "Output buffer too small.\n"); | |||
return ssl_private_key_failure; | |||
} | |||
memcpy(out, bssl::vector_data(&test_state->private_key_result), | |||
test_state->private_key_result.size()); | |||
*out_len = test_state->private_key_result.size(); | |||
test_state->private_key_result.clear(); | |||
test_state->private_key_retries = 0; | |||
return ssl_private_key_success; | |||
} | |||
@@ -215,6 +276,8 @@ static const SSL_PRIVATE_KEY_METHOD g_async_private_key_method = { | |||
AsyncPrivateKeyMaxSignatureLen, | |||
AsyncPrivateKeySign, | |||
AsyncPrivateKeySignComplete, | |||
AsyncPrivateKeyDecrypt, | |||
AsyncPrivateKeyDecryptComplete | |||
}; | |||
template<typename T> | |||
@@ -250,7 +313,7 @@ static bool InstallCertificate(SSL *ssl) { | |||
} | |||
if (!config->key_file.empty()) { | |||
if (config->use_async_private_key) { | |||
if (config->async) { | |||
test_state->private_key = LoadPrivateKey(config->key_file.c_str()); | |||
if (!test_state->private_key) { | |||
return false; | |||
@@ -789,7 +852,7 @@ static bool RetryAsync(SSL *ssl, int ret) { | |||
// The handshake will resume without a second call to the early callback. | |||
return InstallCertificate(ssl); | |||
case SSL_ERROR_WANT_PRIVATE_KEY_OPERATION: | |||
test_state->signature_retries++; | |||
test_state->private_key_retries++; | |||
return true; | |||
default: | |||
return false; | |||
@@ -2585,7 +2585,7 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) | |||
// TLS client auth. | |||
tests = append(tests, testCase{ | |||
testType: clientTest, | |||
name: "ClientAuth-Client", | |||
name: "ClientAuth-RSA-Client", | |||
config: Config{ | |||
ClientAuth: RequireAnyClientCert, | |||
}, | |||
@@ -2594,35 +2594,50 @@ func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) | |||
"-key-file", path.Join(*resourceDir, rsaKeyFile), | |||
}, | |||
}) | |||
tests = append(tests, testCase{ | |||
testType: clientTest, | |||
name: "ClientAuth-ECDSA-Client", | |||
config: Config{ | |||
ClientAuth: RequireAnyClientCert, | |||
}, | |||
flags: []string{ | |||
"-cert-file", path.Join(*resourceDir, ecdsaCertificateFile), | |||
"-key-file", path.Join(*resourceDir, ecdsaKeyFile), | |||
}, | |||
}) | |||
if async { | |||
// Test async keys against each key exchange. | |||
tests = append(tests, testCase{ | |||
testType: clientTest, | |||
name: "ClientAuth-Client-AsyncKey", | |||
testType: serverTest, | |||
name: "Basic-Server-RSA", | |||
config: Config{ | |||
ClientAuth: RequireAnyClientCert, | |||
CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256}, | |||
}, | |||
flags: []string{ | |||
"-cert-file", path.Join(*resourceDir, rsaCertificateFile), | |||
"-key-file", path.Join(*resourceDir, rsaKeyFile), | |||
"-use-async-private-key", | |||
}, | |||
}) | |||
tests = append(tests, testCase{ | |||
testType: serverTest, | |||
name: "Basic-Server-RSAAsyncKey", | |||
name: "Basic-Server-ECDHE-RSA", | |||
config: Config{ | |||
CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}, | |||
}, | |||
flags: []string{ | |||
"-cert-file", path.Join(*resourceDir, rsaCertificateFile), | |||
"-key-file", path.Join(*resourceDir, rsaKeyFile), | |||
"-use-async-private-key", | |||
}, | |||
}) | |||
tests = append(tests, testCase{ | |||
testType: serverTest, | |||
name: "Basic-Server-ECDSAAsyncKey", | |||
name: "Basic-Server-ECDHE-ECDSA", | |||
config: Config{ | |||
CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}, | |||
}, | |||
flags: []string{ | |||
"-cert-file", path.Join(*resourceDir, ecdsaCertificateFile), | |||
"-key-file", path.Join(*resourceDir, ecdsaKeyFile), | |||
"-use-async-private-key", | |||
}, | |||
}) | |||
} | |||
@@ -78,7 +78,6 @@ const Flag<bool> kBoolFlags[] = { | |||
{ "-use-export-context", &TestConfig::use_export_context }, | |||
{ "-no-legacy-server-connect", &TestConfig::no_legacy_server_connect }, | |||
{ "-tls-unique", &TestConfig::tls_unique }, | |||
{ "-use-async-private-key", &TestConfig::use_async_private_key }, | |||
{ "-expect-ticket-renewal", &TestConfig::expect_ticket_renewal }, | |||
{ "-expect-no-session", &TestConfig::expect_no_session }, | |||
{ "-use-ticket-callback", &TestConfig::use_ticket_callback }, | |||
@@ -79,7 +79,6 @@ struct TestConfig { | |||
bool use_export_context = false; | |||
bool no_legacy_server_connect = false; | |||
bool tls_unique = false; | |||
bool use_async_private_key = false; | |||
bool expect_ticket_renewal = false; | |||
bool expect_no_session = false; | |||
bool use_ticket_callback = false; | |||