aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/pubkey
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/pubkey
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/pubkey')
-rw-r--r--src/lib/pubkey/cecpq1/cecpq1.cpp50
-rw-r--r--src/lib/pubkey/cecpq1/cecpq1.h36
-rw-r--r--src/lib/pubkey/cecpq1/info.txt7
-rw-r--r--src/lib/pubkey/curve25519/curve25519.cpp25
-rw-r--r--src/lib/pubkey/curve25519/curve25519.h14
-rw-r--r--src/lib/pubkey/curve25519/donna.cpp3
-rw-r--r--src/lib/pubkey/newhope/newhope.cpp4
-rw-r--r--src/lib/pubkey/newhope/newhope.h31
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,