aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls/msg_client_kex.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-02-28 02:43:57 -0500
committerJack Lloyd <[email protected]>2016-03-20 09:38:17 -0400
commitada363473a9491a3b07e3bb6fa2b5fd9f12aec98 (patch)
tree0dc7eefb24c3d9983e45dd6e2e7f0876179c8c11 /src/lib/tls/msg_client_kex.cpp
parentf70a9de37d22282d8cca465632efd0044ab9008c (diff)
Add PK_Decryptor::decrypt_or_random
Performs content checks on the value (expected length, expected bytes) and in constant time returns either the decrypted value or a random value.
Diffstat (limited to 'src/lib/tls/msg_client_kex.cpp')
-rw-r--r--src/lib/tls/msg_client_kex.cpp52
1 files changed, 22 insertions, 30 deletions
diff --git a/src/lib/tls/msg_client_kex.cpp b/src/lib/tls/msg_client_kex.cpp
index d7689df45..77e9795f4 100644
--- a/src/lib/tls/msg_client_kex.cpp
+++ b/src/lib/tls/msg_client_kex.cpp
@@ -270,41 +270,33 @@ Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents,
if(!dynamic_cast<const RSA_PrivateKey*>(server_rsa_kex_key))
throw Internal_Error("Expected RSA key but got " + server_rsa_kex_key->algo_name());
+ TLS_Data_Reader reader("ClientKeyExchange", contents);
+ const std::vector<byte> encrypted_pre_master = reader.get_range<byte>(2, 0, 65535);
+
PK_Decryptor_EME decryptor(*server_rsa_kex_key, "PKCS1v15");
- Protocol_Version client_version = state.client_hello()->version();
+ const byte client_major = state.client_hello()->version().major_version();
+ const byte client_minor = state.client_hello()->version().minor_version();
/*
- * This is used as the pre-master if RSA decryption fails.
- * Otherwise we can be used as an oracle. See Bleichenbacher
- * "Chosen Ciphertext Attacks against Protocols Based on RSA
- * Encryption Standard PKCS #1", Crypto 98
- *
- * Create it here instead if in the catch clause as otherwise we
- * expose a timing channel WRT the generation of the fake value.
- * Some timing channel likely remains due to exception handling
- * and the like.
+ * PK_Decryptor::decrypt_or_random will return a random value if
+ * either the length does not match the expected value or if the
+ * version number embedded in the PMS does not match the one sent
+ * in the client hello.
*/
- secure_vector<byte> fake_pre_master = rng.random_vec(48);
- fake_pre_master[0] = client_version.major_version();
- fake_pre_master[1] = client_version.minor_version();
-
- try
- {
- TLS_Data_Reader reader("ClientKeyExchange", contents);
- m_pre_master = decryptor.decrypt(reader.get_range<byte>(2, 0, 65535));
-
- if(m_pre_master.size() != 48 ||
- client_version.major_version() != m_pre_master[0] ||
- client_version.minor_version() != m_pre_master[1])
- {
- throw Decoding_Error("Client_Key_Exchange: Secret corrupted");
- }
- }
- catch(...)
- {
- m_pre_master = fake_pre_master;
- }
+ const size_t expected_plaintext_size = 48;
+ const size_t expected_content_size = 2;
+ const byte expected_content_bytes[expected_content_size] = { client_major, client_minor };
+ const byte expected_content_pos[expected_content_size] = { 0, 1 };
+
+ m_pre_master =
+ decryptor.decrypt_or_random(encrypted_pre_master.data(),
+ encrypted_pre_master.size(),
+ expected_plaintext_size,
+ rng,
+ expected_content_bytes,
+ expected_content_pos,
+ expected_content_size);
}
else
{