aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-11-16 12:05:34 -0500
committerJack Lloyd <[email protected]>2016-11-17 13:56:25 -0500
commit74cf1686b727d9b41781df66f3f74d63b9c5cfe2 (patch)
treec5127473f7676763202cf79837bd4328c903a21d /src/lib/tls
parent97df0c27b878d77799353ccc9eda9705b1ec1fa4 (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.cpp49
-rw-r--r--src/lib/tls/msg_server_kex.cpp22
-rw-r--r--src/lib/tls/tls_ciphersuite.cpp6
-rw-r--r--src/lib/tls/tls_messages.h18
-rw-r--r--src/lib/tls/tls_policy.cpp3
-rw-r--r--src/lib/tls/tls_suite_info.cpp8
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, ""),