diff options
-rw-r--r-- | doc/todo.rst | 1 | ||||
-rw-r--r-- | src/lib/stream/chacha/chacha.cpp | 25 | ||||
-rw-r--r-- | src/lib/stream/chacha/chacha.h | 15 | ||||
-rw-r--r-- | src/lib/stream/stream_cipher.cpp | 2 | ||||
-rw-r--r-- | src/tests/data/stream/chacha.vec | 17 |
5 files changed, 49 insertions, 11 deletions
diff --git a/doc/todo.rst b/doc/todo.rst index 437501c02..52ee5c4a2 100644 --- a/doc/todo.rst +++ b/doc/todo.rst @@ -73,7 +73,6 @@ Symmetric Algorithms, Hashes, ... * Serpent using AVX2 * Serpent using SSSE3 pshufb for sboxes * ChaCha20 using SSE2 or AVX2 -* Modify ChaCha to support 12 or 20 rounds * scrypt * Argon2 (draft-irtf-cfrg-argon2) * bcrypt PBKDF diff --git a/src/lib/stream/chacha/chacha.cpp b/src/lib/stream/chacha/chacha.cpp index 0a32c720b..ac81fd70d 100644 --- a/src/lib/stream/chacha/chacha.cpp +++ b/src/lib/stream/chacha/chacha.cpp @@ -10,8 +10,18 @@ namespace Botan { -void ChaCha::chacha(byte output[64], const u32bit input[16]) +ChaCha::ChaCha(size_t rounds) : m_rounds(rounds) { + if(m_rounds != 12 && m_rounds != 20) + throw Invalid_Argument("ChaCha only supports 12 or 20 rounds"); + } + +namespace { + +void chacha(byte output[64], const u32bit input[16], size_t rounds) + { + BOTAN_ASSERT(rounds % 2 == 0, "Valid rounds"); + u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3], x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7], x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11], @@ -25,7 +35,7 @@ void ChaCha::chacha(byte output[64], const u32bit input[16]) c += d; b ^= c; b = rotate_left(b, 7); \ } while(0) - for(size_t i = 0; i != 10; ++i) + for(size_t i = 0; i != rounds / 2; ++i) { CHACHA_QUARTER_ROUND(x00, x04, x08, x12); CHACHA_QUARTER_ROUND(x01, x05, x09, x13); @@ -58,6 +68,8 @@ void ChaCha::chacha(byte output[64], const u32bit input[16]) store_le(x15 + input[15], output + 4 * 15); } +} + /* * Combine cipher stream with message */ @@ -69,7 +81,7 @@ void ChaCha::cipher(const byte in[], byte out[], size_t length) length -= (m_buffer.size() - m_position); in += (m_buffer.size() - m_position); out += (m_buffer.size() - m_position); - chacha(m_buffer.data(), m_state.data()); + chacha(m_buffer.data(), m_state.data(), m_rounds); ++m_state[12]; m_state[13] += (m_state[12] == 0); @@ -142,7 +154,7 @@ void ChaCha::set_iv(const byte iv[], size_t length) m_state[15] = load_le<u32bit>(iv, 2); } - chacha(m_buffer.data(), m_state.data()); + chacha(m_buffer.data(), m_state.data(), m_rounds); ++m_state[12]; m_state[13] += (m_state[12] == 0); @@ -156,4 +168,9 @@ void ChaCha::clear() m_position = 0; } +std::string ChaCha::name() const + { + return "ChaCha(" + std::to_string(m_rounds) + ")"; + } + } diff --git a/src/lib/stream/chacha/chacha.h b/src/lib/stream/chacha/chacha.h index 92f8ef035..ba93d6260 100644 --- a/src/lib/stream/chacha/chacha.h +++ b/src/lib/stream/chacha/chacha.h @@ -18,6 +18,14 @@ namespace Botan { class BOTAN_DLL ChaCha final : public StreamCipher { public: + StreamCipher* clone() const override { return new ChaCha(m_rounds); } + + /** + * Currently only 12 or 20 rounds are supported, all others + * will throw an exception + */ + ChaCha(size_t rounds); + void cipher(const byte in[], byte out[], size_t length) override; void set_iv(const byte iv[], size_t iv_len) override; @@ -31,14 +39,13 @@ class BOTAN_DLL ChaCha final : public StreamCipher } void clear() override; - std::string name() const override { return "ChaCha"; } - StreamCipher* clone() const override { return new ChaCha; } - protected: - virtual void chacha(byte output[64], const u32bit input[16]); + std::string name() const override; + private: void key_schedule(const byte key[], size_t key_len) override; + size_t m_rounds; secure_vector<u32bit> m_state; secure_vector<byte> m_buffer; size_t m_position = 0; diff --git a/src/lib/stream/stream_cipher.cpp b/src/lib/stream/stream_cipher.cpp index 03ef5e329..6f98df1fb 100644 --- a/src/lib/stream/stream_cipher.cpp +++ b/src/lib/stream/stream_cipher.cpp @@ -51,7 +51,7 @@ void StreamCipher::set_iv(const byte[], size_t iv_len) } #if defined(BOTAN_HAS_CHACHA) -BOTAN_REGISTER_T_NOARGS(StreamCipher, ChaCha); +BOTAN_REGISTER_T_1LEN(StreamCipher, ChaCha, 20); #endif #if defined(BOTAN_HAS_SALSA20) diff --git a/src/tests/data/stream/chacha.vec b/src/tests/data/stream/chacha.vec index e4386cbd5..1c3c18c7c 100644 --- a/src/tests/data/stream/chacha.vec +++ b/src/tests/data/stream/chacha.vec @@ -1,5 +1,20 @@ -[ChaCha] +[ChaCha(12)] + +# ChaCha(12) test vectors from +# https://github.com/Yawning/sphincs256/blob/master/chacha/chacha_test.go + +Key = 80000000000000000000000000000000 +Nonce = 0000000000000000 +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 36CF0D56E9F7FBF287BC5460D95FBA94AA6CBF17D74E7C784DDCF7E0E882DDAE3B5A58243EF32B79A04575A8E2C2B73DC64A52AA15B9F88305A8F0CA0B5A1A25 + +Key = 0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C +Nonce = 288FF65DC42B92F9 +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 49FD8FBF19EDCF3A198F5226AA480B97D9F16BA71A693C4ECB90C276094585DFA4FA259E1EC34DE444C92879BFE7F641EEAC480168DC8969A9C033151B1E9229 + +[ChaCha(20)] Key = 00000000000000000000000000000000 Nonce = 0000000000000000 In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |