diff options
-rw-r--r-- | src/lib/stream/chacha/chacha.cpp | 5 | ||||
-rw-r--r-- | src/lib/stream/ctr/ctr.cpp | 2 | ||||
-rw-r--r-- | src/lib/stream/ofb/ofb.cpp | 2 | ||||
-rw-r--r-- | src/lib/stream/rc4/rc4.cpp | 2 | ||||
-rw-r--r-- | src/lib/stream/salsa20/info.txt | 2 | ||||
-rw-r--r-- | src/lib/stream/salsa20/salsa20.cpp | 19 | ||||
-rw-r--r-- | src/tests/data/stream/salsa20.vec | 24 | ||||
-rw-r--r-- | src/tests/test_stream.cpp | 14 |
8 files changed, 61 insertions, 9 deletions
diff --git a/src/lib/stream/chacha/chacha.cpp b/src/lib/stream/chacha/chacha.cpp index 52e5eaaf4..0f1e082cf 100644 --- a/src/lib/stream/chacha/chacha.cpp +++ b/src/lib/stream/chacha/chacha.cpp @@ -222,10 +222,7 @@ std::string ChaCha::name() const void ChaCha::seek(uint64_t offset) { - if (m_state.size() == 0 && m_buffer.size() == 0) - { - throw Invalid_State("You have to setup the stream cipher (key and iv)"); - } + verify_key_set(m_state.empty() == false); // Find the block offset uint64_t counter = offset / 64; diff --git a/src/lib/stream/ctr/ctr.cpp b/src/lib/stream/ctr/ctr.cpp index 463119caf..21e62fb4b 100644 --- a/src/lib/stream/ctr/ctr.cpp +++ b/src/lib/stream/ctr/ctr.cpp @@ -174,6 +174,8 @@ void CTR_BE::add_counter(const uint64_t counter) void CTR_BE::seek(uint64_t offset) { + verify_key_set(m_iv.empty() == false); + const uint64_t base_counter = m_ctr_blocks * (offset / m_counter.size()); zeroise(m_counter); diff --git a/src/lib/stream/ofb/ofb.cpp b/src/lib/stream/ofb/ofb.cpp index 5a2d63dd4..75b7048aa 100644 --- a/src/lib/stream/ofb/ofb.cpp +++ b/src/lib/stream/ofb/ofb.cpp @@ -66,6 +66,6 @@ void OFB::set_iv(const uint8_t iv[], size_t iv_len) void OFB::seek(uint64_t) { - throw Exception("OFB does not support seeking"); + throw Not_Implemented("OFB does not support seeking"); } } diff --git a/src/lib/stream/rc4/rc4.cpp b/src/lib/stream/rc4/rc4.cpp index 60565d445..cce09d183 100644 --- a/src/lib/stream/rc4/rc4.cpp +++ b/src/lib/stream/rc4/rc4.cpp @@ -115,6 +115,6 @@ RC4::RC4(size_t s) : m_SKIP(s) {} void RC4::seek(uint64_t) { - throw Exception("RC4 does not support seeking"); + throw Not_Implemented("RC4 does not support seeking"); } } diff --git a/src/lib/stream/salsa20/info.txt b/src/lib/stream/salsa20/info.txt index 3c7fed8fe..8e9bfa568 100644 --- a/src/lib/stream/salsa20/info.txt +++ b/src/lib/stream/salsa20/info.txt @@ -1,3 +1,3 @@ <defines> -SALSA20 -> 20131128 +SALSA20 -> 20171114 </defines> diff --git a/src/lib/stream/salsa20/salsa20.cpp b/src/lib/stream/salsa20/salsa20.cpp index 3f93cee94..ce22adcb7 100644 --- a/src/lib/stream/salsa20/salsa20.cpp +++ b/src/lib/stream/salsa20/salsa20.cpp @@ -234,8 +234,23 @@ void Salsa20::clear() m_position = 0; } -void Salsa20::seek(uint64_t) +void Salsa20::seek(uint64_t offset) { - throw Not_Implemented("Salsa20::seek"); + verify_key_set(m_state.empty() == false); + + // Find the block offset + const uint64_t counter = offset / 64; + uint8_t counter8[8]; + store_le(counter, counter8); + + m_state[8] = load_le<uint32_t>(counter8, 0); + m_state[9] += load_le<uint32_t>(counter8, 1); + + salsa20(m_buffer.data(), m_state.data()); + + ++m_state[8]; + m_state[9] += (m_state[8] == 0); + + m_position = offset % 64; } } diff --git a/src/tests/data/stream/salsa20.vec b/src/tests/data/stream/salsa20.vec index afe111266..e8276bf32 100644 --- a/src/tests/data/stream/salsa20.vec +++ b/src/tests/data/stream/salsa20.vec @@ -30,3 +30,27 @@ Key = 3070F0DB09C523507D36404DAC79038A393E9F0E3CF5F870B16D2A06DA68DCD3 In = F4EA120B47D15466ADE07DF0F2FF508759D9CB1035CEEAB43920E9094FA50B868673B07173557D4B994B1E9D35078C1C7369DF6B6ADB2EC0E6BFD280FEA8AC31DB44BEB0C2A4DDC6198957BD0592E3E587D304863B893FF8EEE0EFC70CED5D712651C3E9DD1A0DE0480FD8CCCBAE4C50DCCBACB83DCDC3E2CEF7DBC645F0AF468163FB0E015EF48AD74694DFBCE2DB8430A6E91645FD16ADBB72E21A0FBAEDF5ECFF829CEA9CBC22F82902748AA52DA5CE903D9F2BDE77EFEF5FA3970C720E89F25DD05157247BF0DE2D2129C3F856238D4FAD Nonce = 4AFE87BF79EB938D786BA54C26FD6D7E62261EEAE8B62202 Out = 46F396F0D2D54189968BF56B5B2F35588C3AD851E00FAC6507598F3EA0193A586C00B18677811CC305B0261D9AEBBB9C0485A5800C940AA4F09C4FBDEDE12553824C429C7954E0B8DAD889203D292517B98A64E8D7A37C1364EB0934751323D9B9F8498F50D729E977FB742880222F22AC5D7BFEBE6905A4C344D82027398A70C334635792DEB0F20B83861B05E731F5627AEE17DF20413C79957556E66A970085E9AD40A73D9A964381584976C6F111619A916FBB5F5D305DF862D5A56BAC9FF9B436F31C85F34FF890B5AD3299EDA2B8642D + +Key = 000102030405060708090A0B0C0D0E0F +Nonce = 0000000000000000 +Seek = 3 +Out = F7BA2B20F76802410C688688895AD8C1BD4EA6C9B140FB9B90E21049BF583F527970EBC1 + +Key = 0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C +Nonce = 288FF65DC42B92F9 +Out = 5E5E71F90199340304ABB22A37B6625BF883FB89CE3B21F54A10B81066EF87DA30B77699AA7379DA595C77DD59542DA208E5954F89E40EB7AA80A84A6176663F + +Key = 0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C +Nonce = 288FF65DC42B92F9 +Seek = 65472 +Out = 2DA2174BD150A1DFEC1796E921E9D6E24ECF0209BCBEA4F98370FCE629056F64917283436E2D3F45556225307D5CC5A565325D8993B37F1654195C240BF75B16 + +Key = 0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C +Nonce = 288FF65DC42B92F9 +Seek = 65473 +Out = A2174BD150A1DFEC1796E921E9D6E24ECF0209BCBEA4F98370FCE629056F64917283436E2D3F45556225307D5CC5A565325D8993B37F1654195C240BF75B16ABF39A + +Key = 0F62B5085BAE0154A7FA4DA0F34699EC3F92E5388BDE3184D72A7DD02376C91C +Nonce = 288FF65DC42B92F9 +Seek = 65479 +Out = DFEC1796E921E9D6E24ECF0209BCBEA4F98370FCE629056F64917283436E2D3F45556225307D5CC5A565325D8993B37F1654195C240BF75B16ABF39A210EEE89598B7133377056C2FE diff --git a/src/tests/test_stream.cpp b/src/tests/test_stream.cpp index c430c0cf3..ab9de228b 100644 --- a/src/tests/test_stream.cpp +++ b/src/tests/test_stream.cpp @@ -68,6 +68,20 @@ class Stream_Cipher_Tests final : public Text_Based_Test result.test_success("Trying to encrypt with no key set fails"); } + try + { + cipher->seek(0); + result.test_failure("Was able to seek without a key being set"); + } + catch(Botan::Invalid_State&) + { + result.test_success("Trying to seek with no key set fails"); + } + catch(Botan::Not_Implemented&) + { + result.test_success("Trying to seek failed because not implemented"); + } + cipher->set_key(key); if(nonce.size()) |