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/pubkey | |
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/pubkey')
-rw-r--r-- | src/lib/pubkey/cecpq1/cecpq1.cpp | 50 | ||||
-rw-r--r-- | src/lib/pubkey/cecpq1/cecpq1.h | 36 | ||||
-rw-r--r-- | src/lib/pubkey/cecpq1/info.txt | 7 | ||||
-rw-r--r-- | src/lib/pubkey/curve25519/curve25519.cpp | 25 | ||||
-rw-r--r-- | src/lib/pubkey/curve25519/curve25519.h | 14 | ||||
-rw-r--r-- | src/lib/pubkey/curve25519/donna.cpp | 3 | ||||
-rw-r--r-- | src/lib/pubkey/newhope/newhope.cpp | 4 | ||||
-rw-r--r-- | src/lib/pubkey/newhope/newhope.h | 31 |
8 files changed, 143 insertions, 27 deletions
diff --git a/src/lib/pubkey/cecpq1/cecpq1.cpp b/src/lib/pubkey/cecpq1/cecpq1.cpp new file mode 100644 index 000000000..d5b6ae702 --- /dev/null +++ b/src/lib/pubkey/cecpq1/cecpq1.cpp @@ -0,0 +1,50 @@ +/* +* CECPQ1 (x25519 + NewHope) +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/cecpq1.h> +#include <botan/newhope.h> +#include <botan/curve25519.h> + +namespace Botan { + +void CECPQ1_offer(uint8_t send[CECPQ1_OFFER_BYTES], + CECPQ1_key* offer_key_output, + RandomNumberGenerator& rng) + { + offer_key_output->m_x25519 = rng.random_vec(32); + curve25519_basepoint(send, offer_key_output->m_x25519.data()); + + newhope_keygen(send + 32, &offer_key_output->m_newhope, + rng, Newhope_Mode::BoringSSL); + } + +void CECPQ1_accept(uint8_t shared_key[CECPQ1_SHARED_KEY_BYTES], + uint8_t send[CECPQ1_ACCEPT_BYTES], + const uint8_t received[CECPQ1_OFFER_BYTES], + RandomNumberGenerator& rng) + { + secure_vector<byte> x25519_key = rng.random_vec(32); + + curve25519_basepoint(send, x25519_key.data()); + + curve25519_donna(shared_key, x25519_key.data(), received); + + newhope_sharedb(shared_key + 32, send + 32, received + 32, + rng, Newhope_Mode::BoringSSL); + } + +void CECPQ1_finish(uint8_t shared_key[CECPQ1_SHARED_KEY_BYTES], + const CECPQ1_key& offer_key, + const uint8_t received[CECPQ1_ACCEPT_BYTES]) + { + curve25519_donna(shared_key, offer_key.m_x25519.data(), received); + + newhope_shareda(shared_key + 32, &offer_key.m_newhope, received + 32, + Newhope_Mode::BoringSSL); + } + +} diff --git a/src/lib/pubkey/cecpq1/cecpq1.h b/src/lib/pubkey/cecpq1/cecpq1.h new file mode 100644 index 000000000..0bda0dd02 --- /dev/null +++ b/src/lib/pubkey/cecpq1/cecpq1.h @@ -0,0 +1,36 @@ +/* +* CECPQ1 (x25519 + NewHope) +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_CECPQ1_H__ +#define BOTAN_CECPQ1_H__ + +#include <botan/secmem.h> +#include <botan/newhope.h> + +namespace Botan { + +struct CECPQ1_key { + secure_vector<uint8_t> m_x25519; + newhope_poly m_newhope; +}; + +void BOTAN_DLL CECPQ1_offer(uint8_t* offer_message, + CECPQ1_key* offer_key_output, + RandomNumberGenerator& rng); + +void BOTAN_DLL CECPQ1_accept(uint8_t* shared_key, + uint8_t* accept_message, + const uint8_t* offer_message, + RandomNumberGenerator& rng); + +void BOTAN_DLL CECPQ1_finish(uint8_t* shared_key, + const CECPQ1_key& offer_key, + const uint8_t* accept_message); + +} + +#endif diff --git a/src/lib/pubkey/cecpq1/info.txt b/src/lib/pubkey/cecpq1/info.txt new file mode 100644 index 000000000..614ba3962 --- /dev/null +++ b/src/lib/pubkey/cecpq1/info.txt @@ -0,0 +1,7 @@ +define CECPQ1 20161116 + +<requires> +newhope +curve25519 +</requires> + diff --git a/src/lib/pubkey/curve25519/curve25519.cpp b/src/lib/pubkey/curve25519/curve25519.cpp index 216d02600..dd97e1f1d 100644 --- a/src/lib/pubkey/curve25519/curve25519.cpp +++ b/src/lib/pubkey/curve25519/curve25519.cpp @@ -12,6 +12,12 @@ namespace Botan { +void curve25519_basepoint(uint8_t mypublic[32], const uint8_t secret[32]) + { + const byte basepoint[32] = { 9 }; + curve25519_donna(mypublic, secret, basepoint); + } + namespace { void size_check(size_t size, const char* thing) @@ -24,17 +30,7 @@ secure_vector<byte> curve25519(const secure_vector<byte>& secret, const byte pubval[32]) { secure_vector<byte> out(32); - const int rc = curve25519_donna(out.data(), secret.data(), pubval); - BOTAN_ASSERT_EQUAL(rc, 0, "Return value of curve25519_donna is ok"); - return out; - } - -std::vector<byte> curve25519_basepoint(const secure_vector<byte>& secret) - { - const byte basepoint[32] = { 9 }; - std::vector<byte> out(32); - const int rc = curve25519_donna(out.data(), secret.data(), basepoint); - BOTAN_ASSERT_EQUAL(rc, 0, "Return value of curve25519_donna is ok"); + curve25519_donna(out.data(), secret.data(), pubval); return out; } @@ -74,7 +70,8 @@ std::vector<byte> Curve25519_PublicKey::x509_subject_public_key() const Curve25519_PrivateKey::Curve25519_PrivateKey(RandomNumberGenerator& rng) { m_private = rng.random_vec(32); - m_public = curve25519_basepoint(m_private); + m_public.resize(32); + curve25519_basepoint(m_public.data(), m_private.data()); } Curve25519_PrivateKey::Curve25519_PrivateKey(const AlgorithmIdentifier&, @@ -103,7 +100,9 @@ secure_vector<byte> Curve25519_PrivateKey::pkcs8_private_key() const bool Curve25519_PrivateKey::check_key(RandomNumberGenerator&, bool) const { - return curve25519_basepoint(m_private) == m_public; + std::vector<uint8_t> public_point(32); + curve25519_basepoint(public_point.data(), m_private.data()); + return public_point == m_public; } secure_vector<byte> Curve25519_PrivateKey::agree(const byte w[], size_t w_len) const diff --git a/src/lib/pubkey/curve25519/curve25519.h b/src/lib/pubkey/curve25519/curve25519.h index 938bc42d4..40d9d81da 100644 --- a/src/lib/pubkey/curve25519/curve25519.h +++ b/src/lib/pubkey/curve25519/curve25519.h @@ -103,9 +103,17 @@ class BOTAN_DLL Curve25519_PrivateKey : public Curve25519_PublicKey, * The types above are just wrappers for curve25519_donna, plus defining * encodings for public and private keys. */ -int BOTAN_DLL curve25519_donna(uint8_t mypublic[32], - const uint8_t secret[32], - const uint8_t basepoint[32]); +void BOTAN_DLL curve25519_donna(uint8_t mypublic[32], + const uint8_t secret[32], + const uint8_t basepoint[32]); + +/** +* Exponentiate by the x25519 base point +* @param mypublic output value +* @param secret random scalar +*/ +void BOTAN_DLL curve25519_basepoint(uint8_t mypublic[32], + const uint8_t secret[32]); } diff --git a/src/lib/pubkey/curve25519/donna.cpp b/src/lib/pubkey/curve25519/donna.cpp index 86b92b0bf..22400015f 100644 --- a/src/lib/pubkey/curve25519/donna.cpp +++ b/src/lib/pubkey/curve25519/donna.cpp @@ -433,7 +433,7 @@ crecip(felem out, const felem z) { /* 2^255 - 21 */ fmul(out, t0, a); } -int +void curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { CT::poison(secret, 32); @@ -457,7 +457,6 @@ curve25519_donna(u8 *mypublic, const u8 *secret, const u8 *basepoint) { CT::unpoison(secret, 32); CT::unpoison(basepoint, 32); CT::unpoison(mypublic, 32); - return 0; } } diff --git a/src/lib/pubkey/newhope/newhope.cpp b/src/lib/pubkey/newhope/newhope.cpp index 356fd416e..77194207e 100644 --- a/src/lib/pubkey/newhope/newhope.cpp +++ b/src/lib/pubkey/newhope/newhope.cpp @@ -666,13 +666,13 @@ void gen_a(poly *a, const uint8_t *seed, Newhope_Mode mode) if(mode == Newhope_Mode::BoringSSL) { - xof = StreamCipher::create("CTR(AES-128)"); + xof = StreamCipher::create_or_throw("CTR-BE(AES-128)"); xof->set_key(seed, 16); xof->set_iv(seed + 16, 16); } else { - xof = StreamCipher::create("SHAKE-128"); + xof = StreamCipher::create_or_throw("SHAKE-128"); xof->set_key(seed, NEWHOPE_SEED_BYTES); } diff --git a/src/lib/pubkey/newhope/newhope.h b/src/lib/pubkey/newhope/newhope.h index 667f1c4cf..df18bc586 100644 --- a/src/lib/pubkey/newhope/newhope.h +++ b/src/lib/pubkey/newhope/newhope.h @@ -21,36 +21,53 @@ namespace Botan { * Currently pubkey.h does not support a 2-phase KEM scheme of * the sort NEWHOPE exports. */ -#define NEWHOPE_SENDABYTES 1824 -#define NEWHOPE_SENDBBYTES 2048 -typedef struct { - uint16_t coeffs[1024]; -} newhope_poly; +// TODO: change to just a secure_vector +class newhope_poly + { + public: + uint16_t coeffs[1024]; + ~newhope_poly() { secure_scrub_memory(coeffs, sizeof(coeffs)); } + }; + +enum Newhope_Params { + NEWHOPE_SENDABYTES = 1824, + NEWHOPE_SENDBBYTES = 2048, + + NEWHOPE_OFFER_BYTES = 1824, + NEWHOPE_ACCEPT_BYTES = 2048, + NEWHOPE_SHARED_KEY_BYTES = 32, + + CECPQ1_OFFER_BYTES = NEWHOPE_OFFER_BYTES + 32, + CECPQ1_ACCEPT_BYTES = NEWHOPE_ACCEPT_BYTES + 32, + CECPQ1_SHARED_KEY_BYTES = NEWHOPE_SHARED_KEY_BYTES + 32 +}; /** * This chooses the XOF + hash for NewHope - * The official NewHope specification and reference implementation use * SHA-3 and SHAKE-128. BoringSSL instead uses SHA-256 and AES-128 in -* CTR mode. +* CTR mode. CECPQ1 (x25519+NewHope) always uses BoringSSL's mode */ enum class Newhope_Mode { SHA3, BoringSSL }; +// offer void BOTAN_DLL newhope_keygen(uint8_t *send, newhope_poly *sk, RandomNumberGenerator& rng, Newhope_Mode = Newhope_Mode::SHA3); +// accept void BOTAN_DLL newhope_sharedb(uint8_t *sharedkey, uint8_t *send, const uint8_t *received, RandomNumberGenerator& rng, Newhope_Mode mode = Newhope_Mode::SHA3); +// finish void BOTAN_DLL newhope_shareda(uint8_t *sharedkey, const newhope_poly *ska, const uint8_t *received, |