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.cpp4
-rw-r--r--src/lib/stream/ctr/ctr.h2
-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.cpp4
-rw-r--r--src/lib/stream/rc4/rc4.h2
-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.h6
11 files changed, 59 insertions, 4 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 f5301c099..43609ba2d 100644
--- a/src/lib/stream/ctr/ctr.cpp
+++ b/src/lib/stream/ctr/ctr.cpp
@@ -125,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 003297b92..5d5556254 100644
--- a/src/lib/stream/ctr/ctr.h
+++ b/src/lib/stream/ctr/ctr.h
@@ -46,6 +46,8 @@ class BOTAN_DLL CTR_BE final : public StreamCipher
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();
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..a4dea9e2b 100644
--- a/src/lib/stream/rc4/rc4.cpp
+++ b/src/lib/stream/rc4/rc4.cpp
@@ -113,4 +113,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..88798fae6 100644
--- a/src/lib/stream/rc4/rc4.h
+++ b/src/lib/stream/rc4/rc4.h
@@ -39,6 +39,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.h b/src/lib/stream/stream_cipher.h
index bff1fd1a6..56bd2d5d9 100644
--- a/src/lib/stream/stream_cipher.h
+++ b/src/lib/stream/stream_cipher.h
@@ -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();
};