diff options
author | Jack Lloyd <[email protected]> | 2016-11-16 12:05:34 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-11-17 13:56:25 -0500 |
commit | 74cf1686b727d9b41781df66f3f74d63b9c5cfe2 (patch) | |
tree | c5127473f7676763202cf79837bd4328c903a21d /src/lib/tls | |
parent | 97df0c27b878d77799353ccc9eda9705b1ec1fa4 (diff) |
Add CECPQ1 TLS ciphersuites
Tested against BoringSSL (as client + server) and google.com (as client).
Fix a stupid crashing bug in NewHope's BoringSSL mode.
Remove unneeded error return from curve25519_donna - always returned 0.
Default policy prefers ChaChaPoly1305 over GCM and CECPQ1 over ECDH/DH, which
means the default no-extra-configuration ciphersuite (for Botan client speaking
to Botan server) is a ciphersuite which is both implemented in constant time
on all platforms and (hopefully) provides post quantum security. Good Things.
Diffstat (limited to 'src/lib/tls')
-rw-r--r-- | src/lib/tls/msg_client_kex.cpp | 49 | ||||
-rw-r--r-- | src/lib/tls/msg_server_kex.cpp | 22 | ||||
-rw-r--r-- | src/lib/tls/tls_ciphersuite.cpp | 6 | ||||
-rw-r--r-- | src/lib/tls/tls_messages.h | 18 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.cpp | 3 | ||||
-rw-r--r-- | src/lib/tls/tls_suite_info.cpp | 8 |
6 files changed, 92 insertions, 14 deletions
diff --git a/src/lib/tls/msg_client_kex.cpp b/src/lib/tls/msg_client_kex.cpp index 6dc8295a6..05926ac2d 100644 --- a/src/lib/tls/msg_client_kex.cpp +++ b/src/lib/tls/msg_client_kex.cpp @@ -1,6 +1,6 @@ /* * Client Key Exchange Message -* (C) 2004-2010 Jack Lloyd +* (C) 2004-2010,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -24,6 +24,10 @@ #include <botan/curve25519.h> #endif +#if defined(BOTAN_HAS_CECPQ1) + #include <botan/cecpq1.h> +#endif + #if defined(BOTAN_HAS_SRP6) #include <botan/srp6.h> #endif @@ -55,9 +59,8 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, identity_hint = reader.get_string(2, 0, 65535); } - const std::string psk_identity = creds.psk_identity("tls-client", - hostname, - identity_hint); + const std::string psk_identity = + creds.psk_identity("tls-client", hostname, identity_hint); append_tls_length_value(m_key_material, psk_identity, 2); @@ -78,9 +81,8 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, { std::string identity_hint = reader.get_string(2, 0, 65535); - const std::string psk_identity = creds.psk_identity("tls-client", - hostname, - identity_hint); + const std::string psk_identity = + creds.psk_identity("tls-client", hostname, identity_hint); append_tls_length_value(m_key_material, psk_identity, 2); @@ -154,7 +156,6 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, } const std::vector<byte> ecdh_key = reader.get_range<byte>(1, 1, 255); - std::vector<byte> our_ecdh_public; secure_vector<byte> ecdh_secret; @@ -229,10 +230,25 @@ Client_Key_Exchange::Client_Key_Exchange(Handshake_IO& io, m_pre_master = srp_vals.second.bits_of(); } #endif + +#if defined(BOTAN_HAS_CECPQ1) + else if(kex_algo == "CECPQ1") + { + const std::vector<byte> cecpq1_offer = reader.get_range<byte>(2, 1, 65535); + + if(cecpq1_offer.size() != CECPQ1_OFFER_BYTES) + throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Invalid CECPQ1 key size"); + + std::vector<uint8_t> newhope_accept(CECPQ1_ACCEPT_BYTES); + secure_vector<uint8_t> shared_secret(CECPQ1_SHARED_KEY_BYTES); + CECPQ1_accept(shared_secret.data(), newhope_accept.data(), cecpq1_offer.data(), rng); + append_tls_length_value(m_key_material, newhope_accept, 2); + m_pre_master = shared_secret; + } +#endif else { - throw Internal_Error("Client_Key_Exchange: Unknown kex " + - kex_algo); + throw Internal_Error("Client_Key_Exchange: Unknown kex " + kex_algo); } reader.assert_done(); @@ -359,6 +375,19 @@ Client_Key_Exchange::Client_Key_Exchange(const std::vector<byte>& contents, m_pre_master = srp.step2(BigInt::decode(reader.get_range<byte>(2, 0, 65535))).bits_of(); } #endif +#if defined(BOTAN_HAS_CECPQ1) + else if(kex_algo == "CECPQ1") + { + const CECPQ1_key& cecpq1_offer = state.server_kex()->cecpq1_key(); + + const std::vector<byte> cecpq1_accept = reader.get_range<byte>(2, 0, 65535); + if(cecpq1_accept.size() != CECPQ1_ACCEPT_BYTES) + throw Decoding_Error("Invalid size for CECPQ1 accept message"); + + m_pre_master.resize(CECPQ1_SHARED_KEY_BYTES); + CECPQ1_finish(m_pre_master.data(), cecpq1_offer, cecpq1_accept.data()); + } +#endif else if(kex_algo == "DH" || kex_algo == "DHE_PSK" || kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") { diff --git a/src/lib/tls/msg_server_kex.cpp b/src/lib/tls/msg_server_kex.cpp index 4515ea450..521ef4e20 100644 --- a/src/lib/tls/msg_server_kex.cpp +++ b/src/lib/tls/msg_server_kex.cpp @@ -1,6 +1,6 @@ /* * Server Key Exchange Message -* (C) 2004-2010,2012,2015 Jack Lloyd +* (C) 2004-2010,2012,2015,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -21,6 +21,10 @@ #include <botan/curve25519.h> #endif +#if defined(BOTAN_HAS_CECPQ1) + #include <botan/cecpq1.h> +#endif + #if defined(BOTAN_HAS_SRP6) #include <botan/srp6.h> #endif @@ -139,8 +143,19 @@ Server_Key_Exchange::Server_Key_Exchange(Handshake_IO& io, append_tls_length_value(m_params, BigInt::encode(B), 2); } #endif +#if defined(BOTAN_HAS_CECPQ1) + else if(kex_algo == "CECPQ1") + { + std::vector<uint8_t> cecpq1_offer(CECPQ1_OFFER_BYTES); + m_cecpq1_key.reset(new CECPQ1_key); + CECPQ1_offer(cecpq1_offer.data(), m_cecpq1_key.get(), rng); + append_tls_length_value(m_params, cecpq1_offer, 2); + } +#endif else if(kex_algo != "PSK") + { throw Internal_Error("Server_Key_Exchange: Unknown kex type " + kex_algo); + } if(state.ciphersuite().sig_algo() != "") { @@ -205,6 +220,11 @@ Server_Key_Exchange::Server_Key_Exchange(const std::vector<byte>& buf, reader.get_range<byte>(1, 1, 255); reader.get_range<byte>(2, 1, 65535); } + else if(kex_algo == "CECPQ1") + { + // u16 blob + reader.get_range<byte>(2, 1, 65535); + } else if(kex_algo != "PSK") throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " + kex_algo); diff --git a/src/lib/tls/tls_ciphersuite.cpp b/src/lib/tls/tls_ciphersuite.cpp index aa00334c5..3c29c3c2b 100644 --- a/src/lib/tls/tls_ciphersuite.cpp +++ b/src/lib/tls/tls_ciphersuite.cpp @@ -143,6 +143,12 @@ bool Ciphersuite::is_usable() const return false; #endif } + else if(kex_algo() == "CECPQ1") + { +#if !defined(BOTAN_HAS_CECPQ1) + return false; +#endif + } if(sig_algo() == "DSA") { diff --git a/src/lib/tls/tls_messages.h b/src/lib/tls/tls_messages.h index 1e012a899..5e6962329 100644 --- a/src/lib/tls/tls_messages.h +++ b/src/lib/tls/tls_messages.h @@ -29,6 +29,10 @@ class Credentials_Manager; class SRP6_Server_Session; #endif +#if defined(BOTAN_HAS_CECPQ1) +class CECPQ1_key; +#endif + namespace TLS { class Session; @@ -566,6 +570,15 @@ class Server_Key_Exchange final : public Handshake_Message } #endif +#if defined(BOTAN_HAS_CECPQ1) + // Only valid for CECPQ1 negotiation + const CECPQ1_key& cecpq1_key() const + { + BOTAN_ASSERT_NONNULL(m_cecpq1_key); + return *m_cecpq1_key; + } +#endif + Server_Key_Exchange(Handshake_IO& io, Handshake_State& state, const Policy& policy, @@ -585,6 +598,11 @@ class Server_Key_Exchange final : public Handshake_Message #if defined(BOTAN_HAS_SRP6) std::unique_ptr<SRP6_Server_Session> m_srp_params; #endif + +#if defined(BOTAN_HAS_CECPQ1) + std::unique_ptr<CECPQ1_key> m_cecpq1_key; +#endif + std::unique_ptr<Private_Key> m_kex_key; std::vector<byte> m_params; diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp index c7c285716..1bb0951bb 100644 --- a/src/lib/tls/tls_policy.cpp +++ b/src/lib/tls/tls_policy.cpp @@ -21,9 +21,9 @@ std::vector<std::string> Policy::allowed_ciphers() const return { //"AES-256/OCB(12)", //"AES-128/OCB(12)", + "ChaCha20Poly1305", "AES-256/GCM", "AES-128/GCM", - "ChaCha20Poly1305", "AES-256/CCM", "AES-128/CCM", //"AES-256/CCM(8)", @@ -71,6 +71,7 @@ std::vector<std::string> Policy::allowed_key_exchange_methods() const //"ECDHE_PSK", //"DHE_PSK", //"PSK", + "CECPQ1", "ECDH", "DH", //"RSA", diff --git a/src/lib/tls/tls_suite_info.cpp b/src/lib/tls/tls_suite_info.cpp index 7a2c62d56..cc89934e0 100644 --- a/src/lib/tls/tls_suite_info.cpp +++ b/src/lib/tls/tls_suite_info.cpp @@ -2,8 +2,8 @@ * TLS cipher suite information * * This file was automatically generated from the IANA assignments -* (tls-parameters.txt hash 9546b3c8be1a1202e1d4a07c2a9d7d6394ae4a21) -* by ./src/scripts/tls_suite_info.py on 2016-08-16 +* (tls-parameters.txt hash 67a567fcf1ac67cb8cfc4af96c20c3efb05c1fc1) +* by ./src/scripts/tls_suite_info.py on 2016-11-16 * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -81,6 +81,10 @@ const std::vector<Ciphersuite>& Ciphersuite::all_known_ciphersuites() Ciphersuite(0x00C3, "DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", "DSA", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32, ""), Ciphersuite(0x00C4, "DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", "RSA", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32, ""), Ciphersuite(0x00C5, "DH_anon_WITH_CAMELLIA_256_CBC_SHA256", "", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32, ""), + Ciphersuite(0x16B7, "CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256", "RSA", "CECPQ1", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"), + Ciphersuite(0x16B8, "CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256", "ECDSA", "CECPQ1", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256"), + Ciphersuite(0x16B9, "CECPQ1_RSA_WITH_AES_256_GCM_SHA384", "RSA", "CECPQ1", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"), + Ciphersuite(0x16BA, "CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384", "ECDSA", "CECPQ1", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384"), Ciphersuite(0xC008, "ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "ECDSA", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20, ""), Ciphersuite(0xC009, "ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "ECDSA", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20, ""), Ciphersuite(0xC00A, "ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "ECDSA", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20, ""), |