diff options
Diffstat (limited to 'src/lib/stream')
-rw-r--r-- | src/lib/stream/chacha/chacha.cpp | 28 | ||||
-rw-r--r-- | src/lib/stream/chacha/chacha.h | 4 | ||||
-rw-r--r-- | src/lib/stream/ctr/ctr.cpp | 21 | ||||
-rw-r--r-- | src/lib/stream/ctr/ctr.h | 5 | ||||
-rw-r--r-- | src/lib/stream/ofb/ofb.cpp | 5 | ||||
-rw-r--r-- | src/lib/stream/ofb/ofb.h | 2 | ||||
-rw-r--r-- | src/lib/stream/rc4/rc4.cpp | 10 | ||||
-rw-r--r-- | src/lib/stream/rc4/rc4.h | 4 | ||||
-rw-r--r-- | src/lib/stream/salsa20/salsa20.cpp | 4 | ||||
-rw-r--r-- | src/lib/stream/salsa20/salsa20.h | 2 | ||||
-rw-r--r-- | src/lib/stream/stream_cipher.cpp | 6 | ||||
-rw-r--r-- | src/lib/stream/stream_cipher.h | 8 |
12 files changed, 86 insertions, 13 deletions
diff --git a/src/lib/stream/chacha/chacha.cpp b/src/lib/stream/chacha/chacha.cpp index ac81fd70d..40da93029 100644 --- a/src/lib/stream/chacha/chacha.cpp +++ b/src/lib/stream/chacha/chacha.cpp @@ -12,8 +12,8 @@ namespace Botan { 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"); + if(m_rounds != 8 && m_rounds != 12 && m_rounds != 20) + throw Invalid_Argument("ChaCha only supports 8, 12 or 20 rounds"); } namespace { @@ -67,7 +67,6 @@ void chacha(byte output[64], const u32bit input[16], size_t rounds) store_le(x14 + input[14], output + 4 * 14); store_le(x15 + input[15], output + 4 * 15); } - } /* @@ -173,4 +172,27 @@ std::string ChaCha::name() const return "ChaCha(" + std::to_string(m_rounds) + ")"; } +void ChaCha::seek(u64bit offset) + { + if (m_state.size() == 0 && m_buffer.size() == 0) + { + throw Invalid_State("You have to setup the stream cipher (key and iv)"); + } + + m_position = offset % m_buffer.size(); + + u64bit counter = offset / m_buffer.size(); + + byte out[8]; + + store_le(counter, out); + + m_state[12] = load_le<u32bit>(out, 0); + m_state[13] += load_le<u32bit>(out, 1); + + chacha(m_buffer.data(), m_state.data(), m_rounds); + + ++m_state[12]; + m_state[13] += (m_state[12] == 0); + } } diff --git a/src/lib/stream/chacha/chacha.h b/src/lib/stream/chacha/chacha.h index ba93d6260..f8f42e41d 100644 --- a/src/lib/stream/chacha/chacha.h +++ b/src/lib/stream/chacha/chacha.h @@ -21,7 +21,7 @@ class BOTAN_DLL ChaCha final : public StreamCipher StreamCipher* clone() const override { return new ChaCha(m_rounds); } /** - * Currently only 12 or 20 rounds are supported, all others + * Currently only 8, 12 or 20 rounds are supported, all others * will throw an exception */ ChaCha(size_t rounds); @@ -42,6 +42,8 @@ class BOTAN_DLL ChaCha final : public StreamCipher std::string name() const override; + void seek(u64bit offset) override; + private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/lib/stream/ctr/ctr.cpp b/src/lib/stream/ctr/ctr.cpp index 88c7a8d8e..43609ba2d 100644 --- a/src/lib/stream/ctr/ctr.cpp +++ b/src/lib/stream/ctr/ctr.cpp @@ -23,10 +23,23 @@ CTR_BE::CTR_BE(BlockCipher* ciph) : m_cipher(ciph), m_counter(m_cipher->parallel_bytes()), m_pad(m_counter.size()), + m_ctr_size(m_cipher->block_size()), m_pad_pos(0) { } +CTR_BE::CTR_BE(BlockCipher* cipher, size_t ctr_size) : + m_cipher(cipher), + m_counter(m_cipher->parallel_bytes()), + m_pad(m_counter.size()), + m_ctr_size(ctr_size), + m_pad_pos(0) + { + //BOTAN_CHECK_ARG(m_ctr_size > 0 && m_ctr_size <= cipher->block_size(), "Invalid CTR size"); + if(m_ctr_size == 0 || m_ctr_size > m_cipher->block_size()) + throw Invalid_Argument("Invalid CTR-BE counter size"); + } + void CTR_BE::clear() { m_cipher->clear(); @@ -79,7 +92,7 @@ void CTR_BE::set_iv(const byte iv[], size_t iv_len) { buffer_insert(m_counter, i*bs, &m_counter[(i-1)*bs], bs); - for(size_t j = 0; j != bs; ++j) + for(size_t j = 0; j != m_ctr_size; ++j) if(++m_counter[i*bs + (bs - 1 - j)]) break; } @@ -99,7 +112,7 @@ void CTR_BE::increment_counter() for(size_t i = 0; i != n_wide; ++i) { uint16_t carry = static_cast<uint16_t>(n_wide); - for(size_t j = 0; carry && j != bs; ++j) + for(size_t j = 0; carry && j != m_ctr_size; ++j) { const size_t off = i*bs + (bs-1-j); const uint16_t cnt = static_cast<uint16_t>(m_counter[off]) + carry; @@ -112,4 +125,8 @@ void CTR_BE::increment_counter() m_pad_pos = 0; } +void CTR_BE::seek(u64bit) + { + throw Not_Implemented("CTR_BE::seek"); + } } diff --git a/src/lib/stream/ctr/ctr.h b/src/lib/stream/ctr/ctr.h index 8e931605c..5d5556254 100644 --- a/src/lib/stream/ctr/ctr.h +++ b/src/lib/stream/ctr/ctr.h @@ -44,12 +44,17 @@ class BOTAN_DLL CTR_BE final : public StreamCipher * @param cipher the underlying block cipher to use */ explicit CTR_BE(BlockCipher* cipher); + + CTR_BE(BlockCipher* cipher, size_t ctr_size); + + void seek(u64bit offset) override; private: void key_schedule(const byte key[], size_t key_len) override; void increment_counter(); std::unique_ptr<BlockCipher> m_cipher; secure_vector<byte> m_counter, m_pad; + size_t m_ctr_size; size_t m_pad_pos; }; diff --git a/src/lib/stream/ofb/ofb.cpp b/src/lib/stream/ofb/ofb.cpp index e8cb463db..3337a0c14 100644 --- a/src/lib/stream/ofb/ofb.cpp +++ b/src/lib/stream/ofb/ofb.cpp @@ -73,4 +73,9 @@ void OFB::set_iv(const byte iv[], size_t iv_len) m_buf_pos = 0; } + +void OFB::seek(u64bit) + { + throw Exception("OFB does not support seeking"); + } } diff --git a/src/lib/stream/ofb/ofb.h b/src/lib/stream/ofb/ofb.h index fecd47d9d..127a06578 100644 --- a/src/lib/stream/ofb/ofb.h +++ b/src/lib/stream/ofb/ofb.h @@ -44,6 +44,8 @@ class BOTAN_DLL OFB final : public StreamCipher * @param cipher the underlying block cipher to use */ explicit OFB(BlockCipher* cipher); + + void seek(u64bit offset) override; private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/lib/stream/rc4/rc4.cpp b/src/lib/stream/rc4/rc4.cpp index 895f38091..e5ea2e2b8 100644 --- a/src/lib/stream/rc4/rc4.cpp +++ b/src/lib/stream/rc4/rc4.cpp @@ -6,6 +6,7 @@ */ #include <botan/rc4.h> +#include <botan/exceptn.h> namespace Botan { @@ -35,6 +36,11 @@ void RC4::cipher(const byte in[], byte out[], size_t length) m_position += length; } +void RC4::set_iv(const byte*, size_t) + { + throw Exception("RC4 does not support an IV"); + } + /* * Generate cipher stream */ @@ -113,4 +119,8 @@ void RC4::clear() */ RC4::RC4(size_t s) : m_SKIP(s) {} +void RC4::seek(u64bit) + { + throw Exception("RC4 does not support seeking"); + } } diff --git a/src/lib/stream/rc4/rc4.h b/src/lib/stream/rc4/rc4.h index f166a2772..82dd6097b 100644 --- a/src/lib/stream/rc4/rc4.h +++ b/src/lib/stream/rc4/rc4.h @@ -21,6 +21,8 @@ class BOTAN_DLL RC4 final : public StreamCipher public: void cipher(const byte in[], byte out[], size_t length) override; + void set_iv(const byte iv[], size_t iv_len) override; + void clear() override; std::string name() const override; @@ -39,6 +41,8 @@ class BOTAN_DLL RC4 final : public StreamCipher explicit RC4(size_t skip = 0); ~RC4() { clear(); } + + void seek(u64bit offset) override; private: void key_schedule(const byte[], size_t) override; void generate(); diff --git a/src/lib/stream/salsa20/salsa20.cpp b/src/lib/stream/salsa20/salsa20.cpp index 1d3fe3d28..f11fe5e59 100644 --- a/src/lib/stream/salsa20/salsa20.cpp +++ b/src/lib/stream/salsa20/salsa20.cpp @@ -227,4 +227,8 @@ void Salsa20::clear() m_position = 0; } +void Salsa20::seek(u64bit) + { + throw Not_Implemented("Salsa20::seek"); + } } diff --git a/src/lib/stream/salsa20/salsa20.h b/src/lib/stream/salsa20/salsa20.h index 7e75470da..8256ea4db 100644 --- a/src/lib/stream/salsa20/salsa20.h +++ b/src/lib/stream/salsa20/salsa20.h @@ -33,6 +33,8 @@ class BOTAN_DLL Salsa20 final : public StreamCipher void clear() override; std::string name() const override; StreamCipher* clone() const override { return new Salsa20; } + + void seek(u64bit offset) override; private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/lib/stream/stream_cipher.cpp b/src/lib/stream/stream_cipher.cpp index 6f98df1fb..cd6400d8f 100644 --- a/src/lib/stream/stream_cipher.cpp +++ b/src/lib/stream/stream_cipher.cpp @@ -44,12 +44,6 @@ std::vector<std::string> StreamCipher::providers(const std::string& algo_spec) StreamCipher::StreamCipher() {} StreamCipher::~StreamCipher() {} -void StreamCipher::set_iv(const byte[], size_t iv_len) - { - if(!valid_iv_length(iv_len)) - throw Invalid_IV_Length(name(), iv_len); - } - #if defined(BOTAN_HAS_CHACHA) BOTAN_REGISTER_T_1LEN(StreamCipher, ChaCha, 20); #endif diff --git a/src/lib/stream/stream_cipher.h b/src/lib/stream/stream_cipher.h index bff1fd1a6..e08bee0ce 100644 --- a/src/lib/stream/stream_cipher.h +++ b/src/lib/stream/stream_cipher.h @@ -67,7 +67,7 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm * @param iv the initialization vector * @param iv_len the length of the IV in bytes */ - virtual void set_iv(const byte[], size_t iv_len); + virtual void set_iv(const byte[], size_t iv_len) = 0; /** * @param iv_len the length of the IV in bytes @@ -80,6 +80,12 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm */ virtual StreamCipher* clone() const = 0; + /** + * Set the offset and the state used later to generate the keystream + * @param offset the offset where we begin to generate the keystream + */ + virtual void seek(u64bit offset) = 0; + StreamCipher(); virtual ~StreamCipher(); }; |