Simplify ssl_private_key_* state machine points.

The original motivation behind the sign/complete split was to avoid
needlessly hashing the input on each pass through the state machine, but
we're payload-based now and, in all cases, the payload is either cheap
to compute or readily available. (Even the hashing worry was probably
unnecessary.)

Tweak ssl_private_key_{sign,decrypt} to automatically call
ssl_private_key_complete as needed and take advantage of this in the
handshake state machines:

- TLS 1.3 signing now computes the payload each pass. The payload is
  small and we're already allocating a comparable-sized buffer each
  iteration to hold the signature. This shouldn't be a big deal.

- TLS 1.2 decryption code still needs two states due to reading the
  message (fixed in new state machine style), but otherwise it just
  performs cheap idempotent tasks again. The PSK code is reshuffled to
  guarantee the callback is not called twice (though this was impossible
  anyway because we don't support RSA_PSK).

- TLS 1.2 CertificateVerify signing is easy as the transcript is readily
  available. The buffer is released very slightly later, but it
  shouldn't matter.

- TLS 1.2 ServerKeyExchange signing required some reshuffling.
  Assembling the ServerKeyExchange parameters is moved to the previous
  state. The signing payload has some randoms prepended. This is cheap
  enough, but a nuisance in C. Pre-prepend the randoms in
  hs->server_params.

With this change, we are *nearly* rid of the A/B => same function
pattern.

BUG=128

Change-Id: Iec4fe0be7cfc88a6de027ba2760fae70794ea810
Reviewed-on: https://boringssl-review.googlesource.com/17265
Commit-Queue: David Benjamin <davidben@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
This commit is contained in:
David Benjamin 2017-06-17 13:20:59 -04:00 committed by Steven Valdez
parent babcac1c6f
commit 4414874f1f
9 changed files with 231 additions and 297 deletions

View File

@ -310,14 +310,12 @@ OPENSSL_COMPILE_ASSERT(
#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126 | SSL_ST_CONNECT)
#define SSL3_ST_CR_CERT_A (0x130 | SSL_ST_CONNECT)
#define SSL3_ST_CR_KEY_EXCH_A (0x140 | SSL_ST_CONNECT)
#define SSL3_ST_CR_KEY_EXCH_B (0x141 | SSL_ST_CONNECT)
#define SSL3_ST_CR_CERT_REQ_A (0x150 | SSL_ST_CONNECT)
#define SSL3_ST_CR_SRVR_DONE_A (0x160 | SSL_ST_CONNECT)
/* write to server */
#define SSL3_ST_CW_CERT_A (0x170 | SSL_ST_CONNECT)
#define SSL3_ST_CW_KEY_EXCH_A (0x180 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CERT_VRFY_A (0x190 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CERT_VRFY_B (0x191 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CHANGE (0x1A0 | SSL_ST_CONNECT)
#define SSL3_ST_CW_NEXT_PROTO_A (0x200 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CHANNEL_ID_A (0x220 | SSL_ST_CONNECT)
@ -344,7 +342,6 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_ST_SW_SRVR_HELLO_A (0x130 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_CERT_A (0x140 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_KEY_EXCH_A (0x150 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_KEY_EXCH_B (0x151 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_SRVR_DONE_A (0x170 | SSL_ST_ACCEPT)
/* read from client */
#define SSL3_ST_SR_CERT_A (0x180 | SSL_ST_ACCEPT)

View File

@ -346,7 +346,6 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {
break;
case SSL3_ST_CW_CERT_VRFY_A:
case SSL3_ST_CW_CERT_VRFY_B:
if (hs->cert_request && ssl_has_certificate(ssl)) {
ret = ssl3_send_cert_verify(hs);
if (ret <= 0) {
@ -1660,58 +1659,43 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
}
size_t sig_len = max_sig_len;
enum ssl_private_key_result_t sign_result;
if (hs->state == SSL3_ST_CW_CERT_VRFY_A) {
/* The SSL3 construction for CertificateVerify does not decompose into a
* single final digest and signature, and must be special-cased. */
if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
if (ssl->cert->key_method != NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
goto err;
}
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
&digest_len, hs->new_session,
signature_algorithm)) {
goto err;
}
sign_result = ssl_private_key_success;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
if (pctx == NULL ||
!EVP_PKEY_sign_init(pctx) ||
!EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len)) {
EVP_PKEY_CTX_free(pctx);
sign_result = ssl_private_key_failure;
goto err;
}
EVP_PKEY_CTX_free(pctx);
} else {
sign_result = ssl_private_key_sign(
ssl, ptr, &sig_len, max_sig_len, signature_algorithm,
(const uint8_t *)hs->transcript.buffer->data,
hs->transcript.buffer->length);
/* The SSL3 construction for CertificateVerify does not decompose into a
* single final digest and signature, and must be special-cased. */
if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
if (ssl->cert->key_method != NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
goto err;
}
/* The handshake buffer is no longer necessary. */
SSL_TRANSCRIPT_free_buffer(&hs->transcript);
} else {
assert(hs->state == SSL3_ST_CW_CERT_VRFY_B);
sign_result = ssl_private_key_complete(ssl, ptr, &sig_len, max_sig_len);
}
uint8_t digest[EVP_MAX_MD_SIZE];
size_t digest_len;
if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
&digest_len, hs->new_session,
signature_algorithm)) {
goto err;
}
switch (sign_result) {
case ssl_private_key_success:
break;
case ssl_private_key_failure:
goto err;
case ssl_private_key_retry:
ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
hs->state = SSL3_ST_CW_CERT_VRFY_B;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
int ok = pctx != NULL &&
EVP_PKEY_sign_init(pctx) &&
EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len);
EVP_PKEY_CTX_free(pctx);
if (!ok) {
goto err;
}
} else {
switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
signature_algorithm,
(const uint8_t *)hs->transcript.buffer->data,
hs->transcript.buffer->length)) {
case ssl_private_key_success:
break;
case ssl_private_key_failure:
goto err;
case ssl_private_key_retry:
ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
goto err;
}
}
if (!CBB_did_write(&child, sig_len) ||
@ -1719,6 +1703,8 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
goto err;
}
/* The handshake buffer is no longer necessary. */
SSL_TRANSCRIPT_free_buffer(&hs->transcript);
return 1;
err:

View File

@ -186,7 +186,6 @@ static int ssl3_send_server_finished(SSL_HANDSHAKE *hs);
int ssl3_accept(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
uint32_t alg_a;
int ret = -1;
assert(ssl->handshake_func == ssl3_accept);
@ -257,12 +256,7 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
break;
case SSL3_ST_SW_KEY_EXCH_A:
case SSL3_ST_SW_KEY_EXCH_B:
alg_a = hs->new_cipher->algorithm_auth;
/* PSK ciphers send ServerKeyExchange if there is an identity hint. */
if (ssl_cipher_requires_server_key_exchange(hs->new_cipher) ||
((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
if (hs->server_params_len > 0) {
ret = ssl3_send_server_key_exchange(hs);
if (ret <= 0) {
goto end;
@ -1030,50 +1024,48 @@ static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
if (!ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
return 1;
}
int ret = -1;
CBB cbb;
CBB_zero(&cbb);
if (!ssl_has_certificate(ssl)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
return -1;
}
if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
if (!ssl_has_certificate(ssl)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
goto err;
}
if (!ssl3_output_cert_chain(ssl)) {
return -1;
}
if (!ssl3_output_cert_chain(ssl)) {
goto err;
}
if (hs->certificate_status_expected) {
CBB cbb, body, ocsp_response;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_CERTIFICATE_STATUS) ||
!CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) ||
!CBB_add_u24_length_prefixed(&body, &ocsp_response) ||
!CBB_add_bytes(&ocsp_response,
CRYPTO_BUFFER_data(ssl->cert->ocsp_response),
CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) ||
!ssl_add_message_cbb(ssl, &cbb)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
CBB_cleanup(&cbb);
return -1;
if (hs->certificate_status_expected) {
CBB body, ocsp_response;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_CERTIFICATE_STATUS) ||
!CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) ||
!CBB_add_u24_length_prefixed(&body, &ocsp_response) ||
!CBB_add_bytes(&ocsp_response,
CRYPTO_BUFFER_data(ssl->cert->ocsp_response),
CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) ||
!ssl_add_message_cbb(ssl, &cbb)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
goto err;
}
}
}
return 1;
}
/* Assemble ServerKeyExchange parameters if needed. */
uint32_t alg_k = hs->new_cipher->algorithm_mkey;
uint32_t alg_a = hs->new_cipher->algorithm_auth;
if (ssl_cipher_requires_server_key_exchange(hs->new_cipher) ||
((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
CBB cbb, child;
CBB_zero(&cbb);
/* Put together the parameters. */
if (hs->state == SSL3_ST_SW_KEY_EXCH_A) {
uint32_t alg_k = hs->new_cipher->algorithm_mkey;
uint32_t alg_a = hs->new_cipher->algorithm_auth;
/* Pre-allocate enough room to comfortably fit an ECDHE public key. */
if (!CBB_init(&cbb, 128)) {
/* Pre-allocate enough room to comfortably fit an ECDHE public key. Prepend
* the client and server randoms for the signing transcript. */
CBB child;
if (!CBB_init(&cbb, SSL3_RANDOM_SIZE * 2 + 128) ||
!CBB_add_bytes(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
!CBB_add_bytes(&cbb, ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
goto err;
}
@ -1115,11 +1107,22 @@ static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
}
}
/* Assemble the message. */
CBB body;
ret = 1;
err:
CBB_cleanup(&cbb);
return ret;
}
static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
CBB cbb, body, child;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_SERVER_KEY_EXCHANGE) ||
!CBB_add_bytes(&body, hs->server_params, hs->server_params_len)) {
/* |hs->server_params| contains a prefix for signing. */
hs->server_params_len < 2 * SSL3_RANDOM_SIZE ||
!CBB_add_bytes(&body, hs->server_params + 2 * SSL3_RANDOM_SIZE,
hs->server_params_len - 2 * SSL3_RANDOM_SIZE)) {
goto err;
}
@ -1152,36 +1155,9 @@ static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
}
size_t sig_len;
enum ssl_private_key_result_t sign_result;
if (hs->state == SSL3_ST_SW_KEY_EXCH_A) {
CBB transcript;
uint8_t *transcript_data;
size_t transcript_len;
if (!CBB_init(&transcript,
2 * SSL3_RANDOM_SIZE + hs->server_params_len) ||
!CBB_add_bytes(&transcript, ssl->s3->client_random,
SSL3_RANDOM_SIZE) ||
!CBB_add_bytes(&transcript, ssl->s3->server_random,
SSL3_RANDOM_SIZE) ||
!CBB_add_bytes(&transcript, hs->server_params,
hs->server_params_len) ||
!CBB_finish(&transcript, &transcript_data, &transcript_len)) {
CBB_cleanup(&transcript);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len,
signature_algorithm, transcript_data,
transcript_len);
OPENSSL_free(transcript_data);
} else {
assert(hs->state == SSL3_ST_SW_KEY_EXCH_B);
sign_result = ssl_private_key_complete(ssl, ptr, &sig_len, max_sig_len);
}
switch (sign_result) {
switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
signature_algorithm, hs->server_params,
hs->server_params_len)) {
case ssl_private_key_success:
if (!CBB_did_write(&child, sig_len)) {
goto err;
@ -1191,7 +1167,6 @@ static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
goto err;
case ssl_private_key_retry:
ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
hs->state = SSL3_ST_SW_KEY_EXCH_B;
goto err;
}
}
@ -1345,32 +1320,26 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
CBS client_key_exchange;
uint32_t alg_k;
uint32_t alg_a;
uint8_t *premaster_secret = NULL;
size_t premaster_secret_len = 0;
uint8_t *decrypt_buf = NULL;
unsigned psk_len = 0;
uint8_t psk[PSK_MAX_PSK_LEN];
if (hs->state == SSL3_ST_SR_KEY_EXCH_A) {
int ret = ssl->method->ssl_get_message(ssl);
if (ret <= 0) {
return ret;
}
}
if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE) ||
!ssl_hash_current_message(hs)) {
return -1;
}
if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE)) {
return -1;
}
CBS_init(&client_key_exchange, ssl->init_msg, ssl->init_num);
alg_k = hs->new_cipher->algorithm_mkey;
alg_a = hs->new_cipher->algorithm_auth;
uint32_t alg_k = hs->new_cipher->algorithm_mkey;
uint32_t alg_a = hs->new_cipher->algorithm_auth;
/* If using a PSK key exchange, prepare the pre-shared key. */
/* If using a PSK key exchange, parse the PSK identity. */
if (alg_a & SSL_aPSK) {
CBS psk_identity;
@ -1383,12 +1352,6 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
goto err;
}
if (ssl->psk_server_callback == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_SERVER_CB);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN ||
CBS_contains_zero_byte(&psk_identity)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
@ -1401,25 +1364,24 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
/* Look up the key for the identity. */
psk_len = ssl->psk_server_callback(ssl, hs->new_session->psk_identity, psk,
sizeof(psk));
if (psk_len > PSK_MAX_PSK_LEN) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
} else if (psk_len == 0) {
/* PSK related to the given identity not found */
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_PSK_IDENTITY);
goto err;
}
}
/* Depending on the key exchange method, compute |premaster_secret| and
* |premaster_secret_len|. */
if (alg_k & SSL_kRSA) {
CBS encrypted_premaster_secret;
if (ssl->version > SSL3_VERSION) {
if (!CBS_get_u16_length_prefixed(&client_key_exchange,
&encrypted_premaster_secret) ||
CBS_len(&client_key_exchange) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
goto err;
}
} else {
encrypted_premaster_secret = client_key_exchange;
}
/* Allocate a buffer large enough for an RSA decryption. */
const size_t rsa_size = EVP_PKEY_size(hs->local_pubkey);
decrypt_buf = OPENSSL_malloc(rsa_size);
@ -1428,43 +1390,12 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
goto err;
}
enum ssl_private_key_result_t decrypt_result;
/* Decrypt with no padding. PKCS#1 padding will be removed as part of the
* timing-sensitive code below. */
size_t decrypt_len;
if (hs->state == SSL3_ST_SR_KEY_EXCH_A) {
if (!ssl_has_private_key(ssl) ||
EVP_PKEY_id(hs->local_pubkey) != EVP_PKEY_RSA) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_RSA_CERTIFICATE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
goto err;
}
CBS encrypted_premaster_secret;
if (ssl->version > SSL3_VERSION) {
if (!CBS_get_u16_length_prefixed(&client_key_exchange,
&encrypted_premaster_secret) ||
CBS_len(&client_key_exchange) != 0) {
OPENSSL_PUT_ERROR(SSL,
SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
goto err;
}
} else {
encrypted_premaster_secret = client_key_exchange;
}
/* Decrypt with no padding. PKCS#1 padding will be removed as part of the
* timing-sensitive code below. */
decrypt_result = ssl_private_key_decrypt(
ssl, decrypt_buf, &decrypt_len, rsa_size,
CBS_data(&encrypted_premaster_secret),
CBS_len(&encrypted_premaster_secret));
} else {
assert(hs->state == SSL3_ST_SR_KEY_EXCH_B);
/* Complete async decrypt. */
decrypt_result =
ssl_private_key_complete(ssl, decrypt_buf, &decrypt_len, rsa_size);
}
switch (decrypt_result) {
switch (ssl_private_key_decrypt(hs, decrypt_buf, &decrypt_len, rsa_size,
CBS_data(&encrypted_premaster_secret),
CBS_len(&encrypted_premaster_secret))) {
case ssl_private_key_success:
break;
case ssl_private_key_failure:
@ -1547,17 +1478,7 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
/* The key exchange state may now be discarded. */
SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
} else if (alg_k & SSL_kPSK) {
/* For plain PSK, other_secret is a block of 0s with the same length as the
* pre-shared key. */
premaster_secret_len = psk_len;
premaster_secret = OPENSSL_malloc(premaster_secret_len);
if (premaster_secret == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
} else {
} else if (!(alg_k & SSL_kPSK)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_TYPE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
goto err;
@ -1566,10 +1487,42 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
/* For a PSK cipher suite, the actual pre-master secret is combined with the
* pre-shared key. */
if (alg_a & SSL_aPSK) {
if (ssl->psk_server_callback == NULL) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_SERVER_CB);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
/* Look up the key for the identity. */
uint8_t psk[PSK_MAX_PSK_LEN];
unsigned psk_len = ssl->psk_server_callback(
ssl, hs->new_session->psk_identity, psk, sizeof(psk));
if (psk_len > PSK_MAX_PSK_LEN) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
} else if (psk_len == 0) {
/* PSK related to the given identity not found */
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_PSK_IDENTITY);
goto err;
}
if (alg_k & SSL_kPSK) {
/* In plain PSK, other_secret is a block of 0s with the same length as the
* pre-shared key. */
premaster_secret_len = psk_len;
premaster_secret = OPENSSL_malloc(premaster_secret_len);
if (premaster_secret == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
}
CBB new_premaster, child;
uint8_t *new_data;
size_t new_len;
CBB_zero(&new_premaster);
if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) ||
!CBB_add_u16_length_prefixed(&new_premaster, &child) ||
@ -1588,6 +1541,10 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
premaster_secret_len = new_len;
}
if (!ssl_hash_current_message(hs)) {
goto err;
}
/* Compute the master secret */
hs->new_session->master_key_length = tls1_generate_master_secret(
hs, hs->new_session->master_key, premaster_secret, premaster_secret_len);

View File

@ -548,22 +548,20 @@ typedef struct ssl_handshake_st SSL_HANDSHAKE;
* configured and zero otherwise. */
int ssl_has_private_key(const SSL *ssl);
/* ssl_private_key_* call the corresponding function on the
* |SSL_PRIVATE_KEY_METHOD| for |ssl|, if configured. Otherwise, they implement
* the operation with |EVP_PKEY|. */
/* ssl_private_key_* perform the corresponding operation on
* |SSL_PRIVATE_KEY_METHOD|. If there is a custom private key configured, they
* call the corresponding function or |complete| depending on whether there is a
* pending operation. Otherwise, they implement the operation with
* |EVP_PKEY|. */
enum ssl_private_key_result_t ssl_private_key_sign(
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
uint16_t signature_algorithm, const uint8_t *in, size_t in_len);
enum ssl_private_key_result_t ssl_private_key_decrypt(
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
SSL_HANDSHAKE *hs, 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_complete(SSL *ssl, uint8_t *out,
size_t *out_len,
size_t max_out);
/* ssl_private_key_supports_signature_algorithm returns one if |hs|'s private
* key supports |sigalg| and zero otherwise. */
int ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
@ -1023,8 +1021,9 @@ struct ssl_handshake_st {
uint8_t *peer_key;
size_t peer_key_len;
/* server_params, in TLS 1.2, stores the ServerKeyExchange parameters to be
* signed while the signature is being computed. */
/* server_params, in a TLS 1.2 server, stores the ServerKeyExchange
* parameters. It has client and server randoms prepended for signing
* convenience. */
uint8_t *server_params;
size_t server_params_len;
@ -1128,6 +1127,10 @@ struct ssl_handshake_st {
* negotiated in this handshake. */
unsigned extended_master_secret:1;
/* pending_private_key_op is one if there is a pending private key operation
* in progress. */
unsigned pending_private_key_op:1;
/* client_version is the value sent or received in the ClientHello version. */
uint16_t client_version;
@ -1172,8 +1175,12 @@ int tls13_process_certificate_verify(SSL_HANDSHAKE *hs);
int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value);
int tls13_add_certificate(SSL_HANDSHAKE *hs);
enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs,
int is_first_run);
/* tls13_add_certificate_verify adds a TLS 1.3 CertificateVerify message to the
* handshake. If it returns |ssl_private_key_retry|, it should be called again
* to retry when the signing operation is completed. */
enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs);
int tls13_add_finished(SSL_HANDSHAKE *hs);
int tls13_process_new_session_ticket(SSL *ssl);

View File

@ -56,6 +56,7 @@
#include <openssl/ssl.h>
#include <assert.h>
#include <limits.h>
#include <openssl/ec.h>
@ -406,33 +407,43 @@ static int legacy_sign_digest_supported(const SSL_SIGNATURE_ALGORITHM *alg) {
!alg->is_rsa_pss;
}
static enum ssl_private_key_result_t legacy_sign(
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, uint16_t sigalg,
const uint8_t *in, size_t in_len) {
/* TODO(davidben): Remove support for |sign_digest|-only
* |SSL_PRIVATE_KEY_METHOD|s. */
const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
if (alg == NULL || !legacy_sign_digest_supported(alg)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
return ssl_private_key_failure;
}
const EVP_MD *md = alg->digest_func();
uint8_t hash[EVP_MAX_MD_SIZE];
unsigned hash_len;
if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
return ssl_private_key_failure;
}
return ssl->cert->key_method->sign_digest(ssl, out, out_len, max_out, md,
hash, hash_len);
}
enum ssl_private_key_result_t ssl_private_key_sign(
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
uint16_t sigalg, const uint8_t *in, size_t in_len) {
SSL *const ssl = hs->ssl;
if (ssl->cert->key_method != NULL) {
if (ssl->cert->key_method->sign != NULL) {
return ssl->cert->key_method->sign(ssl, out, out_len, max_out, sigalg, in,
in_len);
enum ssl_private_key_result_t ret;
if (hs->pending_private_key_op) {
ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
} else {
ret = (ssl->cert->key_method->sign != NULL
? ssl->cert->key_method->sign
: legacy_sign)(ssl, out, out_len, max_out, sigalg, in, in_len);
}
/* TODO(davidben): Remove support for |sign_digest|-only
* |SSL_PRIVATE_KEY_METHOD|s. */
const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
if (alg == NULL ||
!legacy_sign_digest_supported(alg)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
return ssl_private_key_failure;
}
const EVP_MD *md = alg->digest_func();
uint8_t hash[EVP_MAX_MD_SIZE];
unsigned hash_len;
if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
return ssl_private_key_failure;
}
return ssl->cert->key_method->sign_digest(ssl, out, out_len, max_out, md,
hash, hash_len);
hs->pending_private_key_op = ret == ssl_private_key_retry;
return ret;
}
*out_len = max_out;
@ -456,11 +467,19 @@ int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
}
enum ssl_private_key_result_t ssl_private_key_decrypt(
SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
const uint8_t *in, size_t in_len) {
SSL *const ssl = hs->ssl;
if (ssl->cert->key_method != NULL) {
return ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
in_len);
enum ssl_private_key_result_t ret;
if (hs->pending_private_key_op) {
ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
} else {
ret = ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
in_len);
}
hs->pending_private_key_op = ret == ssl_private_key_retry;
return ret;
}
RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey);
@ -478,13 +497,6 @@ enum ssl_private_key_result_t ssl_private_key_decrypt(
return ssl_private_key_success;
}
enum ssl_private_key_result_t ssl_private_key_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->complete(ssl, out, out_len, max_out);
}
int ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
uint16_t sigalg) {
SSL *const ssl = hs->ssl;

View File

@ -142,9 +142,6 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_CW_CERT_VRFY_A:
return "SSLv3 write certificate verify A";
case SSL3_ST_CW_CERT_VRFY_B:
return "SSLv3 write certificate verify B";
case SSL3_ST_CW_CHANGE:
return "SSLv3 write change cipher spec";
@ -249,9 +246,6 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_CW_CERT_VRFY_A:
return "3WCV_A";
case SSL3_ST_CW_CERT_VRFY_B:
return "3WCV_B";
case SSL3_ST_CW_CHANGE:
return "3WCCS_";
@ -285,9 +279,6 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_SW_KEY_EXCH_A:
return "3WSKEA";
case SSL3_ST_SW_KEY_EXCH_B:
return "3WSKEB";
case SSL3_ST_SW_SRVR_DONE_A:
return "3WSD_A";

View File

@ -533,8 +533,7 @@ err:
return 0;
}
enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs,
int is_first_run) {
enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
enum ssl_private_key_result_t ret = ssl_private_key_failure;
uint8_t *msg = NULL;
@ -564,20 +563,15 @@ enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs,
goto err;
}
enum ssl_private_key_result_t sign_result;
if (is_first_run) {
if (!tls13_get_cert_verify_signature_input(
hs, &msg, &msg_len,
ssl->server ? ssl_cert_verify_server : ssl_cert_verify_client)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
sign_result = ssl_private_key_sign(ssl, sig, &sig_len, max_sig_len,
signature_algorithm, msg, msg_len);
} else {
sign_result = ssl_private_key_complete(ssl, sig, &sig_len, max_sig_len);
if (!tls13_get_cert_verify_signature_input(
hs, &msg, &msg_len,
ssl->server ? ssl_cert_verify_server : ssl_cert_verify_client)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
goto err;
}
enum ssl_private_key_result_t sign_result = ssl_private_key_sign(
hs, sig, &sig_len, max_sig_len, signature_algorithm, msg, msg_len);
if (sign_result != ssl_private_key_success) {
ret = sign_result;
goto err;

View File

@ -41,7 +41,6 @@ enum client_hs_state_t {
state_send_end_of_early_data,
state_send_client_certificate,
state_send_client_certificate_verify,
state_complete_client_certificate_verify,
state_complete_second_flight,
state_done,
};
@ -543,8 +542,7 @@ static enum ssl_hs_wait_t do_send_client_certificate(SSL_HANDSHAKE *hs) {
return ssl_hs_ok;
}
static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs,
int is_first_run) {
static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* Don't send CertificateVerify if there is no certificate. */
if (!ssl_has_certificate(ssl)) {
@ -552,13 +550,13 @@ static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs,
return ssl_hs_ok;
}
switch (tls13_add_certificate_verify(hs, is_first_run)) {
switch (tls13_add_certificate_verify(hs)) {
case ssl_private_key_success:
hs->tls13_state = state_complete_second_flight;
return ssl_hs_ok;
case ssl_private_key_retry:
hs->tls13_state = state_complete_client_certificate_verify;
hs->tls13_state = state_send_client_certificate_verify;
return ssl_hs_private_key_operation;
case ssl_private_key_failure:
@ -649,10 +647,7 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {
ret = do_send_client_certificate(hs);
break;
case state_send_client_certificate_verify:
ret = do_send_client_certificate_verify(hs, 1 /* first run */);
break;
case state_complete_client_certificate_verify:
ret = do_send_client_certificate_verify(hs, 0 /* complete */);
ret = do_send_client_certificate_verify(hs);
break;
case state_complete_second_flight:
ret = do_complete_second_flight(hs);

View File

@ -36,7 +36,6 @@ enum server_hs_state_t {
state_process_second_client_hello,
state_send_server_hello,
state_send_server_certificate_verify,
state_complete_server_certificate_verify,
state_send_server_finished,
state_read_second_client_flight,
state_process_end_of_early_data,
@ -583,15 +582,14 @@ err:
return ssl_hs_error;
}
static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs,
int is_first_run) {
switch (tls13_add_certificate_verify(hs, is_first_run)) {
static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs) {
switch (tls13_add_certificate_verify(hs)) {
case ssl_private_key_success:
hs->tls13_state = state_send_server_finished;
return ssl_hs_ok;
case ssl_private_key_retry:
hs->tls13_state = state_complete_server_certificate_verify;
hs->tls13_state = state_send_server_certificate_verify;
return ssl_hs_private_key_operation;
case ssl_private_key_failure:
@ -802,10 +800,7 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) {
ret = do_send_server_hello(hs);
break;
case state_send_server_certificate_verify:
ret = do_send_server_certificate_verify(hs, 1 /* first run */);
break;
case state_complete_server_certificate_verify:
ret = do_send_server_certificate_verify(hs, 0 /* complete */);
ret = do_send_server_certificate_verify(hs);
break;
case state_send_server_finished:
ret = do_send_server_finished(hs);