aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/stream
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/stream')
-rw-r--r--src/lib/stream/chacha/chacha.cpp28
-rw-r--r--src/lib/stream/chacha/chacha.h4
-rw-r--r--src/lib/stream/ctr/ctr.cpp21
-rw-r--r--src/lib/stream/ctr/ctr.h5
-rw-r--r--src/lib/stream/ofb/ofb.cpp5
-rw-r--r--src/lib/stream/ofb/ofb.h2
-rw-r--r--src/lib/stream/rc4/rc4.cpp10
-rw-r--r--src/lib/stream/rc4/rc4.h4
-rw-r--r--src/lib/stream/salsa20/salsa20.cpp4
-rw-r--r--src/lib/stream/salsa20/salsa20.h2
-rw-r--r--src/lib/stream/stream_cipher.cpp6
-rw-r--r--src/lib/stream/stream_cipher.h8
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();
};