aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/stream
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-10-20 20:12:51 -0400
committerJack Lloyd <[email protected]>2016-10-20 20:12:51 -0400
commit9419f3a8f544e9cfca60d458ba512ed69d4cc22a (patch)
tree9b2e7799e639e94799627f81287afa457ee79b23 /src/lib/stream
parentb64629dfe76cec3f8f4f9f5e19966629e1f895a8 (diff)
parentd9a11e68915b6f4ab0682007a036d2ddc0133d09 (diff)
Merge GH #669 Add SHA-3, SHAKE-128, and BoringSSL-mode NewHope
Diffstat (limited to 'src/lib/stream')
-rw-r--r--src/lib/stream/salsa20/salsa20.cpp2
-rw-r--r--src/lib/stream/shake_cipher/info.txt1
-rw-r--r--src/lib/stream/shake_cipher/shake_cipher.cpp75
-rw-r--r--src/lib/stream/shake_cipher/shake_cipher.h64
-rw-r--r--src/lib/stream/stream_cipher.cpp8
5 files changed, 149 insertions, 1 deletions
diff --git a/src/lib/stream/salsa20/salsa20.cpp b/src/lib/stream/salsa20/salsa20.cpp
index f11fe5e59..0d8942789 100644
--- a/src/lib/stream/salsa20/salsa20.cpp
+++ b/src/lib/stream/salsa20/salsa20.cpp
@@ -163,7 +163,7 @@ void Salsa20::key_schedule(const byte key[], size_t length)
}
/*
-* Return the name of this type
+* Set the Salsa IV
*/
void Salsa20::set_iv(const byte iv[], size_t length)
{
diff --git a/src/lib/stream/shake_cipher/info.txt b/src/lib/stream/shake_cipher/info.txt
new file mode 100644
index 000000000..53e6f5012
--- /dev/null
+++ b/src/lib/stream/shake_cipher/info.txt
@@ -0,0 +1 @@
+define SHAKE_CIPHER 20161018
diff --git a/src/lib/stream/shake_cipher/shake_cipher.cpp b/src/lib/stream/shake_cipher/shake_cipher.cpp
new file mode 100644
index 000000000..5701e7802
--- /dev/null
+++ b/src/lib/stream/shake_cipher/shake_cipher.cpp
@@ -0,0 +1,75 @@
+/*
+* SHAKE-128
+* (C) 2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/shake_cipher.h>
+#include <botan/sha3.h>
+#include <botan/loadstor.h>
+
+namespace Botan {
+
+SHAKE_128::SHAKE_128() :
+ m_state(25),
+ m_buffer((1600 - 256) / 8),
+ m_buf_pos(0)
+ {}
+
+void SHAKE_128::cipher(const byte in[], byte out[], size_t length)
+ {
+ while(length >= m_buffer.size() - m_buf_pos)
+ {
+ xor_buf(out, in, &m_buffer[m_buf_pos], m_buffer.size() - m_buf_pos);
+ length -= (m_buffer.size() - m_buf_pos);
+ in += (m_buffer.size() - m_buf_pos);
+ out += (m_buffer.size() - m_buf_pos);
+
+ SHA_3::permute(m_state.data());
+ copy_out_le(m_buffer.data(), m_buffer.size(), m_state.data());
+
+ m_buf_pos = 0;
+ }
+ xor_buf(out, in, &m_buffer[m_buf_pos], length);
+ m_buf_pos += length;
+ }
+
+void SHAKE_128::key_schedule(const byte key[], size_t length)
+ {
+ zeroise(m_state);
+
+ for(size_t i = 0; i < length/8; ++i)
+ {
+ m_state[i] ^= load_le<uint64_t>(key, i);
+ }
+
+ m_state[length/8] ^= 0x000000000000001F;
+ m_state[20] ^= 0x8000000000000000;
+
+ SHA_3::permute(m_state.data());
+ copy_out_le(m_buffer.data(), m_buffer.size(), m_state.data());
+ }
+
+void SHAKE_128::clear()
+ {
+ zeroise(m_state);
+ zeroise(m_buffer);
+ m_buf_pos = 0;
+ }
+
+void SHAKE_128::set_iv(const byte[], size_t length)
+ {
+ /*
+ * This could be supported in some way (say, by treating iv as
+ * a prefix or suffix of the key).
+ */
+ if(length != 0)
+ throw Invalid_IV_Length(name(), length);
+ }
+
+void SHAKE_128::seek(u64bit)
+ {
+ throw Not_Implemented("SHAKE_128::seek");
+ }
+}
diff --git a/src/lib/stream/shake_cipher/shake_cipher.h b/src/lib/stream/shake_cipher/shake_cipher.h
new file mode 100644
index 000000000..57eda58a4
--- /dev/null
+++ b/src/lib/stream/shake_cipher/shake_cipher.h
@@ -0,0 +1,64 @@
+/*
+* SHAKE-128 as a stream cipher
+* (C) 2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_SHAKE128_CIPHER_H__
+#define BOTAN_SHAKE128_CIPHER_H__
+
+#include <botan/stream_cipher.h>
+#include <botan/secmem.h>
+
+namespace Botan {
+
+/**
+* SHAKE-128 XOF presented as a stream cipher
+*/
+class BOTAN_DLL SHAKE_128 final : public StreamCipher
+ {
+ public:
+ SHAKE_128();
+
+ /**
+ * Produce more XOF output
+ */
+ void cipher(const byte in[], byte out[], size_t length) override;
+
+ /**
+ * Seeking is not supported, this function will throw
+ */
+ void seek(u64bit offset) override;
+
+ /**
+ * IV not supported, this function will throw unless iv_len == 0
+ */
+ void set_iv(const byte iv[], size_t iv_len) override;
+
+ bool valid_iv_length(size_t iv_len) const override { return (iv_len == 0); }
+
+ /**
+ * In principle SHAKE can accept arbitrary length inputs, but this
+ * does not seem required for a stream cipher.
+ */
+ Key_Length_Specification key_spec() const override
+ {
+ return Key_Length_Specification(16, 160, 8);
+ }
+
+ void clear() override;
+ std::string name() const override { return "SHAKE-128"; }
+ StreamCipher* clone() const override { return new SHAKE_128; }
+
+ private:
+ void key_schedule(const byte key[], size_t key_len) override;
+
+ secure_vector<uint64_t> m_state; // internal state
+ secure_vector<byte> m_buffer; // ciphertext buffer
+ size_t m_buf_pos; // position in m_buffer
+ };
+
+}
+
+#endif
diff --git a/src/lib/stream/stream_cipher.cpp b/src/lib/stream/stream_cipher.cpp
index cd6400d8f..7c41722a0 100644
--- a/src/lib/stream/stream_cipher.cpp
+++ b/src/lib/stream/stream_cipher.cpp
@@ -16,6 +16,10 @@
#include <botan/salsa20.h>
#endif
+#if defined(BOTAN_HAS_SHAKE_CIPHER)
+ #include <botan/shake_cipher.h>
+#endif
+
#if defined(BOTAN_HAS_CTR_BE)
#include <botan/ctr.h>
#endif
@@ -52,6 +56,10 @@ BOTAN_REGISTER_T_1LEN(StreamCipher, ChaCha, 20);
BOTAN_REGISTER_T_NOARGS(StreamCipher, Salsa20);
#endif
+#if defined(BOTAN_HAS_SHAKE_CIPHER)
+BOTAN_REGISTER_NAMED_T(StreamCipher, "SHAKE-128", SHAKE_128, make_new_T<SHAKE_128>);
+#endif
+
#if defined(BOTAN_HAS_CTR_BE)
BOTAN_REGISTER_NAMED_T(StreamCipher, "CTR-BE", CTR_BE, CTR_BE::make);
#endif