in ssl/handshake_server.cc [1406:1617]
static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
SSLMessage msg;
if (!ssl->method->get_message(ssl, &msg)) {
return ssl_hs_read_message;
}
if (!ssl_check_message_type(ssl, msg, SSL3_MT_CLIENT_KEY_EXCHANGE)) {
return ssl_hs_error;
}
CBS client_key_exchange = msg.body;
uint32_t alg_k = hs->new_cipher->algorithm_mkey;
uint32_t alg_a = hs->new_cipher->algorithm_auth;
// If using a PSK key exchange, parse the PSK identity.
if (alg_a & SSL_aPSK) {
CBS psk_identity;
// If using PSK, the ClientKeyExchange contains a psk_identity. If PSK,
// then this is the only field in the message.
if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) ||
((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
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);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
return ssl_hs_error;
}
char *raw = nullptr;
if (!CBS_strdup(&psk_identity, &raw)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
hs->new_session->psk_identity.reset(raw);
}
// Depending on the key exchange method, compute |premaster_secret|.
Array<uint8_t> premaster_secret;
if (alg_k & SSL_kRSA) {
CBS encrypted_premaster_secret;
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);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
// Allocate a buffer large enough for an RSA decryption.
Array<uint8_t> decrypt_buf;
if (!decrypt_buf.Init(EVP_PKEY_size(hs->local_pubkey.get()))) {
return ssl_hs_error;
}
// Decrypt with no padding. PKCS#1 padding will be removed as part of the
// timing-sensitive code below.
size_t decrypt_len;
switch (ssl_private_key_decrypt(hs, decrypt_buf.data(), &decrypt_len,
decrypt_buf.size(),
encrypted_premaster_secret)) {
case ssl_private_key_success:
break;
case ssl_private_key_failure:
return ssl_hs_error;
case ssl_private_key_retry:
return ssl_hs_private_key_operation;
}
if (decrypt_len != decrypt_buf.size()) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
return ssl_hs_error;
}
CONSTTIME_SECRET(decrypt_buf.data(), decrypt_len);
// Prepare a random premaster, to be used on invalid padding. See RFC 5246,
// section 7.4.7.1.
if (!premaster_secret.Init(SSL_MAX_MASTER_KEY_LENGTH) ||
!RAND_bytes(premaster_secret.data(), premaster_secret.size())) {
return ssl_hs_error;
}
// The smallest padded premaster is 11 bytes of overhead. Small keys are
// publicly invalid.
if (decrypt_len < 11 + premaster_secret.size()) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
return ssl_hs_error;
}
// Check the padding. See RFC 3447, section 7.2.2.
size_t padding_len = decrypt_len - premaster_secret.size();
uint8_t good = constant_time_eq_int_8(decrypt_buf[0], 0) &
constant_time_eq_int_8(decrypt_buf[1], 2);
for (size_t i = 2; i < padding_len - 1; i++) {
good &= ~constant_time_is_zero_8(decrypt_buf[i]);
}
good &= constant_time_is_zero_8(decrypt_buf[padding_len - 1]);
// The premaster secret must begin with |client_version|. This too must be
// checked in constant time (http://eprint.iacr.org/2003/052/).
good &= constant_time_eq_8(decrypt_buf[padding_len],
(unsigned)(hs->client_version >> 8));
good &= constant_time_eq_8(decrypt_buf[padding_len + 1],
(unsigned)(hs->client_version & 0xff));
// Select, in constant time, either the decrypted premaster or the random
// premaster based on |good|.
for (size_t i = 0; i < premaster_secret.size(); i++) {
premaster_secret[i] = constant_time_select_8(
good, decrypt_buf[padding_len + i], premaster_secret[i]);
}
} else if (alg_k & SSL_kECDHE) {
// Parse the ClientKeyExchange.
CBS peer_key;
if (!CBS_get_u8_length_prefixed(&client_key_exchange, &peer_key) ||
CBS_len(&client_key_exchange) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
// Compute the premaster.
uint8_t alert = SSL_AD_DECODE_ERROR;
if (!hs->key_shares[0]->Finish(&premaster_secret, &alert, peer_key) ||
// Save peer's public key for observation with |SSL_get_peer_tmp_key|.
!ssl->s3->peer_key.CopyFrom(peer_key)) {
ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
// The key exchange state may now be discarded.
hs->key_shares[0].reset();
hs->key_shares[1].reset();
} else if (!(alg_k & SSL_kPSK)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
return ssl_hs_error;
}
// For a PSK cipher suite, the actual pre-master secret is combined with the
// pre-shared key.
if (alg_a & SSL_aPSK) {
if (hs->config->psk_server_callback == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
// Look up the key for the identity.
uint8_t psk[PSK_MAX_PSK_LEN];
unsigned psk_len = hs->config->psk_server_callback(
ssl, hs->new_session->psk_identity.get(), psk, sizeof(psk));
if (psk_len > PSK_MAX_PSK_LEN) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
} else if (psk_len == 0) {
// PSK related to the given identity not found.
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_PSK_IDENTITY);
return ssl_hs_error;
}
if (alg_k & SSL_kPSK) {
// In plain PSK, other_secret is a block of 0s with the same length as the
// pre-shared key.
if (!premaster_secret.Init(psk_len)) {
return ssl_hs_error;
}
OPENSSL_memset(premaster_secret.data(), 0, premaster_secret.size());
}
ScopedCBB new_premaster;
CBB child;
if (!CBB_init(new_premaster.get(),
2 + psk_len + 2 + premaster_secret.size()) ||
!CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
!CBB_add_bytes(&child, premaster_secret.data(),
premaster_secret.size()) ||
!CBB_add_u16_length_prefixed(new_premaster.get(), &child) ||
!CBB_add_bytes(&child, psk, psk_len) ||
!CBBFinishArray(new_premaster.get(), &premaster_secret)) {
return ssl_hs_error;
}
}
if (!ssl_hash_message(hs, msg)) {
return ssl_hs_error;
}
// Compute the master secret.
hs->new_session->secret_length = tls1_generate_master_secret(
hs, hs->new_session->secret, premaster_secret);
if (hs->new_session->secret_length == 0) {
return ssl_hs_error;
}
hs->new_session->extended_master_secret = hs->extended_master_secret;
CONSTTIME_DECLASSIFY(hs->new_session->secret, hs->new_session->secret_length);
hs->can_release_private_key = true;
ssl->method->next_message(ssl);
hs->state = state12_read_client_certificate_verify;
return ssl_hs_ok;
}