diff options
author | Jack Lloyd <[email protected]> | 2016-09-01 13:40:26 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2016-09-01 14:16:38 -0400 |
commit | 507d926da825fbc1d9d74b4517dbab47702c66b9 (patch) | |
tree | 22ac0e4a9c85fb3583d478a41ba1c46aeced5ec3 /src/lib/modes/aead | |
parent | e4656be6a8e601b64c759906bacf543388b3cf22 (diff) |
Cipher_Mode API improvements
The Cipher_Mode::update API is more general than needed to just
support ciphers (this is due to it previously being an API of
Transform which before 8b85b780515 was Cipher_Mode's base class)
Define a less general interface `process` which either processes the
blocks in-place, producing exactly as much output as there was input,
or (SIV/CCM case) saves the entire message for processing in `finish`.
These two uses cover all current or anticipated cipher modes.
Leaves `update` for compatability with existing callers; all that is
needed is an inline function forwarding to `process`.
Removes the return type from `start` - in all cipher implementations,
this always returned an empty vector.
Adds BOTAN_ARG_CHECK macro; right now BOTAN_ASSERT is being used
for argument checking in some places, which is not right at all.
Diffstat (limited to 'src/lib/modes/aead')
-rw-r--r-- | src/lib/modes/aead/ccm/ccm.cpp | 51 | ||||
-rw-r--r-- | src/lib/modes/aead/ccm/ccm.h | 6 | ||||
-rw-r--r-- | src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp | 18 | ||||
-rw-r--r-- | src/lib/modes/aead/chacha20poly1305/chacha20poly1305.h | 6 | ||||
-rw-r--r-- | src/lib/modes/aead/eax/eax.cpp | 20 | ||||
-rw-r--r-- | src/lib/modes/aead/eax/eax.h | 6 | ||||
-rw-r--r-- | src/lib/modes/aead/gcm/gcm.cpp | 63 | ||||
-rw-r--r-- | src/lib/modes/aead/gcm/gcm.h | 6 | ||||
-rw-r--r-- | src/lib/modes/aead/ocb/ocb.cpp | 113 | ||||
-rw-r--r-- | src/lib/modes/aead/ocb/ocb.h | 9 | ||||
-rw-r--r-- | src/lib/modes/aead/siv/siv.cpp | 13 | ||||
-rw-r--r-- | src/lib/modes/aead/siv/siv.h | 4 |
12 files changed, 135 insertions, 180 deletions
diff --git a/src/lib/modes/aead/ccm/ccm.cpp b/src/lib/modes/aead/ccm/ccm.cpp index 1f528769e..d5559bfb5 100644 --- a/src/lib/modes/aead/ccm/ccm.cpp +++ b/src/lib/modes/aead/ccm/ccm.cpp @@ -11,6 +11,9 @@ namespace Botan { +// 128-bit cipher is intrinsic to CCM definition +static const size_t CCM_BS = 16; + /* * CCM_Mode Constructor */ @@ -19,7 +22,7 @@ CCM_Mode::CCM_Mode(BlockCipher* cipher, size_t tag_size, size_t L) : m_L(L), m_cipher(cipher) { - if(m_cipher->block_size() != BS) + if(m_cipher->block_size() != CCM_BS) throw Invalid_Argument(m_cipher->name() + " cannot be used with CCM mode"); if(L < 2 || L > 8) @@ -84,30 +87,24 @@ void CCM_Mode::set_associated_data(const byte ad[], size_t length) m_ad_buf.push_back(get_byte(0, static_cast<u16bit>(length))); m_ad_buf.push_back(get_byte(1, static_cast<u16bit>(length))); m_ad_buf += std::make_pair(ad, length); - while(m_ad_buf.size() % BS) + while(m_ad_buf.size() % CCM_BS) m_ad_buf.push_back(0); // pad with zeros to full block size } } -secure_vector<byte> CCM_Mode::start_raw(const byte nonce[], size_t nonce_len) +void CCM_Mode::start_msg(const byte nonce[], size_t nonce_len) { if(!valid_nonce_length(nonce_len)) throw Invalid_IV_Length(name(), nonce_len); m_nonce.assign(nonce, nonce + nonce_len); m_msg_buf.clear(); - - return secure_vector<byte>(); } -void CCM_Mode::update(secure_vector<byte>& buffer, size_t offset) +size_t CCM_Mode::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz); - buffer.resize(offset); // truncate msg + return 0; // no output until finished } void CCM_Mode::encode_length(size_t len, byte out[]) @@ -131,7 +128,7 @@ void CCM_Mode::inc(secure_vector<byte>& C) secure_vector<byte> CCM_Mode::format_b0(size_t sz) { - secure_vector<byte> B0(BS); + secure_vector<byte> B0(CCM_BS); const byte b_flags = (m_ad_buf.size() ? 64 : 0) + (((tag_size()/2)-1) << 3) + (L()-1); @@ -144,7 +141,7 @@ secure_vector<byte> CCM_Mode::format_b0(size_t sz) secure_vector<byte> CCM_Mode::format_c0() { - secure_vector<byte> C(BS); + secure_vector<byte> C(CCM_BS); const byte a_flags = L()-1; @@ -164,31 +161,31 @@ void CCM_Encryption::finish(secure_vector<byte>& buffer, size_t offset) byte* buf = buffer.data() + offset; const secure_vector<byte>& ad = ad_buf(); - BOTAN_ASSERT(ad.size() % BS == 0, "AD is block size multiple"); + BOTAN_ASSERT(ad.size() % CCM_BS == 0, "AD is block size multiple"); const BlockCipher& E = cipher(); - secure_vector<byte> T(BS); + secure_vector<byte> T(CCM_BS); E.encrypt(format_b0(sz), T); - for(size_t i = 0; i != ad.size(); i += BS) + for(size_t i = 0; i != ad.size(); i += CCM_BS) { - xor_buf(T.data(), &ad[i], BS); + xor_buf(T.data(), &ad[i], CCM_BS); E.encrypt(T); } secure_vector<byte> C = format_c0(); - secure_vector<byte> S0(BS); + secure_vector<byte> S0(CCM_BS); E.encrypt(C, S0); inc(C); - secure_vector<byte> X(BS); + secure_vector<byte> X(CCM_BS); const byte* buf_end = &buf[sz]; while(buf != buf_end) { - const size_t to_proc = std::min<size_t>(BS, buf_end - buf); + const size_t to_proc = std::min<size_t>(CCM_BS, buf_end - buf); xor_buf(T.data(), buf, to_proc); E.encrypt(T); @@ -217,32 +214,32 @@ void CCM_Decryption::finish(secure_vector<byte>& buffer, size_t offset) BOTAN_ASSERT(sz >= tag_size(), "We have the tag"); const secure_vector<byte>& ad = ad_buf(); - BOTAN_ASSERT(ad.size() % BS == 0, "AD is block size multiple"); + BOTAN_ASSERT(ad.size() % CCM_BS == 0, "AD is block size multiple"); const BlockCipher& E = cipher(); - secure_vector<byte> T(BS); + secure_vector<byte> T(CCM_BS); E.encrypt(format_b0(sz - tag_size()), T); - for(size_t i = 0; i != ad.size(); i += BS) + for(size_t i = 0; i != ad.size(); i += CCM_BS) { - xor_buf(T.data(), &ad[i], BS); + xor_buf(T.data(), &ad[i], CCM_BS); E.encrypt(T); } secure_vector<byte> C = format_c0(); - secure_vector<byte> S0(BS); + secure_vector<byte> S0(CCM_BS); E.encrypt(C, S0); inc(C); - secure_vector<byte> X(BS); + secure_vector<byte> X(CCM_BS); const byte* buf_end = &buf[sz - tag_size()]; while(buf != buf_end) { - const size_t to_proc = std::min<size_t>(BS, buf_end - buf); + const size_t to_proc = std::min<size_t>(CCM_BS, buf_end - buf); E.encrypt(C, X); xor_buf(buf, X.data(), to_proc); diff --git a/src/lib/modes/aead/ccm/ccm.h b/src/lib/modes/aead/ccm/ccm.h index 8277a8f93..7484b500a 100644 --- a/src/lib/modes/aead/ccm/ccm.h +++ b/src/lib/modes/aead/ccm/ccm.h @@ -22,7 +22,7 @@ namespace Botan { class BOTAN_DLL CCM_Mode : public AEAD_Mode { public: - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t sz) override; void set_associated_data(const byte ad[], size_t ad_len) override; @@ -41,8 +41,6 @@ class BOTAN_DLL CCM_Mode : public AEAD_Mode size_t tag_size() const override { return m_tag_size; } protected: - const size_t BS = 16; // intrinsic to CCM definition - CCM_Mode(BlockCipher* cipher, size_t tag_size, size_t L); size_t L() const { return m_L; } @@ -60,7 +58,7 @@ class BOTAN_DLL CCM_Mode : public AEAD_Mode secure_vector<byte> format_b0(size_t msg_size); secure_vector<byte> format_c0(); private: - secure_vector<byte> start_raw(const byte nonce[], size_t nonce_len) override; + void start_msg(const byte nonce[], size_t nonce_len) override; void key_schedule(const byte key[], size_t length) override; diff --git a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp index ca4cc15ed..04326dede 100644 --- a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp +++ b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.cpp @@ -50,7 +50,7 @@ void ChaCha20Poly1305_Mode::update_len(size_t len) m_poly1305->update(len8, 8); } -secure_vector<byte> ChaCha20Poly1305_Mode::start_raw(const byte nonce[], size_t nonce_len) +void ChaCha20Poly1305_Mode::start_msg(const byte nonce[], size_t nonce_len) { if(!valid_nonce_length(nonce_len)) throw Invalid_IV_Length(name(), nonce_len); @@ -80,19 +80,14 @@ secure_vector<byte> ChaCha20Poly1305_Mode::start_raw(const byte nonce[], size_t { update_len(m_ad.size()); } - - return secure_vector<byte>(); } -void ChaCha20Poly1305_Encryption::update(secure_vector<byte>& buffer, size_t offset) +size_t ChaCha20Poly1305_Encryption::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - m_chacha->cipher1(buf, sz); m_poly1305->update(buf, sz); // poly1305 of ciphertext m_ctext_len += sz; + return sz; } void ChaCha20Poly1305_Encryption::finish(secure_vector<byte>& buffer, size_t offset) @@ -114,15 +109,12 @@ void ChaCha20Poly1305_Encryption::finish(secure_vector<byte>& buffer, size_t off m_ctext_len = 0; } -void ChaCha20Poly1305_Decryption::update(secure_vector<byte>& buffer, size_t offset) +size_t ChaCha20Poly1305_Decryption::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - m_poly1305->update(buf, sz); // poly1305 of ciphertext m_chacha->cipher1(buf, sz); m_ctext_len += sz; + return sz; } void ChaCha20Poly1305_Decryption::finish(secure_vector<byte>& buffer, size_t offset) diff --git a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.h b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.h index 5aa2dc010..553508854 100644 --- a/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.h +++ b/src/lib/modes/aead/chacha20poly1305/chacha20poly1305.h @@ -50,7 +50,7 @@ class BOTAN_DLL ChaCha20Poly1305_Mode : public AEAD_Mode bool cfrg_version() const { return m_nonce_len == 12; } void update_len(size_t len); private: - secure_vector<byte> start_raw(const byte nonce[], size_t nonce_len) override; + void start_msg(const byte nonce[], size_t nonce_len) override; void key_schedule(const byte key[], size_t length) override; }; @@ -66,7 +66,7 @@ class BOTAN_DLL ChaCha20Poly1305_Encryption final : public ChaCha20Poly1305_Mode size_t minimum_final_size() const override { return 0; } - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t size) override; void finish(secure_vector<byte>& final_block, size_t offset = 0) override; }; @@ -85,7 +85,7 @@ class BOTAN_DLL ChaCha20Poly1305_Decryption final : public ChaCha20Poly1305_Mode size_t minimum_final_size() const override { return tag_size(); } - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t size) override; void finish(secure_vector<byte>& final_block, size_t offset = 0) override; }; diff --git a/src/lib/modes/aead/eax/eax.cpp b/src/lib/modes/aead/eax/eax.cpp index 4b928cd31..f26a1eae3 100644 --- a/src/lib/modes/aead/eax/eax.cpp +++ b/src/lib/modes/aead/eax/eax.cpp @@ -60,7 +60,7 @@ std::string EAX_Mode::name() const size_t EAX_Mode::update_granularity() const { - return 8 * m_cipher->parallel_bytes(); + return 1; } Key_Length_Specification EAX_Mode::key_spec() const @@ -91,7 +91,7 @@ void EAX_Mode::set_associated_data(const byte ad[], size_t length) m_ad_mac = eax_prf(1, block_size(), *m_cmac, ad, length); } -secure_vector<byte> EAX_Mode::start_raw(const byte nonce[], size_t nonce_len) +void EAX_Mode::start_msg(const byte nonce[], size_t nonce_len) { if(!valid_nonce_length(nonce_len)) throw Invalid_IV_Length(name(), nonce_len); @@ -103,18 +103,13 @@ secure_vector<byte> EAX_Mode::start_raw(const byte nonce[], size_t nonce_len) for(size_t i = 0; i != block_size() - 1; ++i) m_cmac->update(0); m_cmac->update(2); - - return secure_vector<byte>(); } -void EAX_Encryption::update(secure_vector<byte>& buffer, size_t offset) +size_t EAX_Encryption::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - m_ctr->cipher(buf, buf, sz); m_cmac->update(buf, sz); + return sz; } void EAX_Encryption::finish(secure_vector<byte>& buffer, size_t offset) @@ -128,14 +123,11 @@ void EAX_Encryption::finish(secure_vector<byte>& buffer, size_t offset) buffer += std::make_pair(data_mac.data(), tag_size()); } -void EAX_Decryption::update(secure_vector<byte>& buffer, size_t offset) +size_t EAX_Decryption::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - m_cmac->update(buf, sz); m_ctr->cipher(buf, buf, sz); + return sz; } void EAX_Decryption::finish(secure_vector<byte>& buffer, size_t offset) diff --git a/src/lib/modes/aead/eax/eax.h b/src/lib/modes/aead/eax/eax.h index e3d942d5e..0dedefe07 100644 --- a/src/lib/modes/aead/eax/eax.h +++ b/src/lib/modes/aead/eax/eax.h @@ -54,7 +54,7 @@ class BOTAN_DLL EAX_Mode : public AEAD_Mode secure_vector<byte> m_nonce_mac; private: - secure_vector<byte> start_raw(const byte nonce[], size_t nonce_len) override; + void start_msg(const byte nonce[], size_t nonce_len) override; void key_schedule(const byte key[], size_t length) override; }; @@ -77,7 +77,7 @@ class BOTAN_DLL EAX_Encryption final : public EAX_Mode size_t minimum_final_size() const override { return 0; } - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t size) override; void finish(secure_vector<byte>& final_block, size_t offset = 0) override; }; @@ -103,7 +103,7 @@ class BOTAN_DLL EAX_Decryption final : public EAX_Mode size_t minimum_final_size() const override { return tag_size(); } - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t size) override; void finish(secure_vector<byte>& final_block, size_t offset = 0) override; }; diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp index e23551cb4..78792b79a 100644 --- a/src/lib/modes/aead/gcm/gcm.cpp +++ b/src/lib/modes/aead/gcm/gcm.cpp @@ -17,6 +17,8 @@ namespace Botan { +static const size_t GCM_BS = 16; + void GHASH::gcm_multiply(secure_vector<byte>& x) const { #if defined(BOTAN_HAS_GCM_CLMUL) @@ -66,15 +68,13 @@ void GHASH::gcm_multiply(secure_vector<byte>& x) const void GHASH::ghash_update(secure_vector<byte>& ghash, const byte input[], size_t length) { - const size_t BS = 16; - /* This assumes if less than block size input then we're just on the final block and should pad with zeros */ while(length) { - const size_t to_proc = std::min(length, BS); + const size_t to_proc = std::min(length, GCM_BS); xor_buf(ghash.data(), input, to_proc); @@ -88,7 +88,7 @@ void GHASH::ghash_update(secure_vector<byte>& ghash, void GHASH::key_schedule(const byte key[], size_t length) { m_H.assign(key, key+length); - m_H_ad.resize(16); + m_H_ad.resize(GCM_BS); m_ad_len = 0; m_text_len = 0; } @@ -109,7 +109,7 @@ void GHASH::set_associated_data(const byte input[], size_t length) void GHASH::update(const byte input[], size_t length) { - BOTAN_ASSERT(m_ghash.size() == 16, "Key was set"); + BOTAN_ASSERT(m_ghash.size() == GCM_BS, "Key was set"); m_text_len += length; @@ -119,7 +119,7 @@ void GHASH::update(const byte input[], size_t length) void GHASH::add_final_block(secure_vector<byte>& hash, size_t ad_len, size_t text_len) { - secure_vector<byte> final_block(16); + secure_vector<byte> final_block(GCM_BS); store_be<u64bit>(final_block.data(), 8*ad_len, 8*text_len); ghash_update(hash, final_block.data(), final_block.size()); } @@ -139,7 +139,7 @@ secure_vector<byte> GHASH::final() secure_vector<byte> GHASH::nonce_hash(const byte nonce[], size_t nonce_len) { BOTAN_ASSERT(m_ghash.size() == 0, "nonce_hash called during wrong time"); - secure_vector<byte> y0(16); + secure_vector<byte> y0(GCM_BS); ghash_update(y0, nonce, nonce_len); add_final_block(y0, 0, nonce_len); @@ -162,15 +162,14 @@ GCM_Mode::GCM_Mode(BlockCipher* cipher, size_t tag_size) : m_tag_size(tag_size), m_cipher_name(cipher->name()) { - if(cipher->block_size() != m_BS) - throw Invalid_Argument("GCM requires a 128 bit cipher so cannot be used with " + - cipher->name()); + if(cipher->block_size() != GCM_BS) + throw Invalid_Argument("Invalid block cipher for GCM"); m_ghash.reset(new GHASH); m_ctr.reset(new CTR_BE(cipher, 4)); // CTR_BE takes ownership of cipher - if(m_tag_size != 8 && m_tag_size != 16) + if(m_tag_size != 8 && m_tag_size != GCM_BS) throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(m_tag_size)); } @@ -187,7 +186,7 @@ std::string GCM_Mode::name() const size_t GCM_Mode::update_granularity() const { - return m_BS; + return GCM_BS; } Key_Length_Specification GCM_Mode::key_spec() const @@ -199,10 +198,10 @@ void GCM_Mode::key_schedule(const byte key[], size_t keylen) { m_ctr->set_key(key, keylen); - const std::vector<byte> zeros(m_BS); + const std::vector<byte> zeros(GCM_BS); m_ctr->set_iv(zeros.data(), zeros.size()); - secure_vector<byte> H(m_BS); + secure_vector<byte> H(GCM_BS); m_ctr->encipher(H); m_ghash->set_key(H); } @@ -212,12 +211,12 @@ void GCM_Mode::set_associated_data(const byte ad[], size_t ad_len) m_ghash->set_associated_data(ad, ad_len); } -secure_vector<byte> GCM_Mode::start_raw(const byte nonce[], size_t nonce_len) +void GCM_Mode::start_msg(const byte nonce[], size_t nonce_len) { if(!valid_nonce_length(nonce_len)) throw Invalid_IV_Length(name(), nonce_len); - secure_vector<byte> y0(m_BS); + secure_vector<byte> y0(GCM_BS); if(nonce_len == 12) { @@ -231,48 +230,48 @@ secure_vector<byte> GCM_Mode::start_raw(const byte nonce[], size_t nonce_len) m_ctr->set_iv(y0.data(), y0.size()); - secure_vector<byte> m_enc_y0(m_BS); + secure_vector<byte> m_enc_y0(GCM_BS); m_ctr->encipher(m_enc_y0); m_ghash->start(m_enc_y0.data(), m_enc_y0.size()); - - return secure_vector<byte>(); } -void GCM_Encryption::update(secure_vector<byte>& buffer, size_t offset) +size_t GCM_Encryption::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - + BOTAN_ARG_CHECK(sz % update_granularity() == 0); m_ctr->cipher(buf, buf, sz); m_ghash->update(buf, sz); + return sz; } void GCM_Encryption::finish(secure_vector<byte>& buffer, size_t offset) { - update(buffer, offset); + BOTAN_ARG_CHECK(offset <= buffer.size()); + const size_t sz = buffer.size() - offset; + byte* buf = buffer.data() + offset; + + m_ctr->cipher(buf, buf, sz); + m_ghash->update(buf, sz); auto mac = m_ghash->final(); buffer += std::make_pair(mac.data(), tag_size()); } -void GCM_Decryption::update(secure_vector<byte>& buffer, size_t offset) +size_t GCM_Decryption::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - + BOTAN_ARG_CHECK(sz % update_granularity() == 0); m_ghash->update(buf, sz); m_ctr->cipher(buf, buf, sz); + return sz; } void GCM_Decryption::finish(secure_vector<byte>& buffer, size_t offset) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + BOTAN_ARG_CHECK(offset <= buffer.size()); const size_t sz = buffer.size() - offset; byte* buf = buffer.data() + offset; - BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input"); + if(sz < tag_size()) + throw Exception("Insufficient input for GCM decryption, tag missing"); const size_t remaining = sz - tag_size(); diff --git a/src/lib/modes/aead/gcm/gcm.h b/src/lib/modes/aead/gcm/gcm.h index ba0d6cad8..0110436b2 100644 --- a/src/lib/modes/aead/gcm/gcm.h +++ b/src/lib/modes/aead/gcm/gcm.h @@ -47,7 +47,7 @@ class BOTAN_DLL GCM_Mode : public AEAD_Mode std::unique_ptr<StreamCipher> m_ctr; std::unique_ptr<GHASH> m_ghash; private: - secure_vector<byte> start_raw(const byte nonce[], size_t nonce_len) override; + void start_msg(const byte nonce[], size_t nonce_len) override; void key_schedule(const byte key[], size_t length) override; }; @@ -70,7 +70,7 @@ class BOTAN_DLL GCM_Encryption final : public GCM_Mode size_t minimum_final_size() const override { return 0; } - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t size) override; void finish(secure_vector<byte>& final_block, size_t offset = 0) override; }; @@ -96,7 +96,7 @@ class BOTAN_DLL GCM_Decryption final : public GCM_Mode size_t minimum_final_size() const override { return tag_size(); } - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t size) override; void finish(secure_vector<byte>& final_block, size_t offset = 0) override; }; diff --git a/src/lib/modes/aead/ocb/ocb.cpp b/src/lib/modes/aead/ocb/ocb.cpp index 77126ec7a..e21749f3b 100644 --- a/src/lib/modes/aead/ocb/ocb.cpp +++ b/src/lib/modes/aead/ocb/ocb.cpp @@ -33,13 +33,12 @@ class L_computer size_t block_index, size_t blocks) const { - const size_t BS = m_L_star.size(); - m_offset_buf.resize(blocks * BS); + m_offset_buf.resize(blocks * 16); for(size_t i = 0; i != blocks; ++i) { // could be done in parallel offset ^= get(ctz(block_index + 1 + i)); - copy_mem(&m_offset_buf[BS*i], offset.data(), BS); + copy_mem(&m_offset_buf[16*i], offset.data(), 16); } return m_offset_buf; @@ -73,15 +72,13 @@ secure_vector<byte> ocb_hash(const L_computer& L, const BlockCipher& cipher, const byte ad[], size_t ad_len) { - const size_t BS = cipher.block_size(); + secure_vector<byte> sum(16); + secure_vector<byte> offset(16); - secure_vector<byte> sum(BS); - secure_vector<byte> offset(BS); + secure_vector<byte> buf(16); - secure_vector<byte> buf(BS); - - const size_t ad_blocks = (ad_len / BS); - const size_t ad_remainder = (ad_len % BS); + const size_t ad_blocks = (ad_len / 16); + const size_t ad_remainder = (ad_len % 16); for(size_t i = 0; i != ad_blocks; ++i) { @@ -89,7 +86,7 @@ secure_vector<byte> ocb_hash(const L_computer& L, offset ^= L(ctz(i+1)); buf = offset; - xor_buf(buf.data(), &ad[BS*i], BS); + xor_buf(buf.data(), &ad[16*i], 16); cipher.encrypt(buf); @@ -101,8 +98,8 @@ secure_vector<byte> ocb_hash(const L_computer& L, offset ^= L.star(); buf = offset; - xor_buf(buf.data(), &ad[BS*ad_blocks], ad_remainder); - buf[ad_len % BS] ^= 0x80; + xor_buf(buf.data(), &ad[16*ad_blocks], ad_remainder); + buf[ad_len % 16] ^= 0x80; cipher.encrypt(buf); @@ -116,19 +113,16 @@ secure_vector<byte> ocb_hash(const L_computer& L, OCB_Mode::OCB_Mode(BlockCipher* cipher, size_t tag_size) : m_cipher(cipher), - m_BS(m_cipher->block_size()), m_checksum(m_cipher->parallel_bytes()), - m_offset(m_BS), - m_ad_hash(m_BS), + m_offset(16), + m_ad_hash(16), m_tag_size(tag_size) { - if(BS() != 16) - throw Invalid_Argument("OCB is not compatible with " + m_cipher->name()); - - if(m_tag_size % 4 != 0 || m_tag_size < 8 || m_tag_size > BS()) - throw Invalid_Argument("OCB cannot produce a " + std::to_string(m_tag_size) + - " byte tag"); + if(m_cipher->block_size() != 16) + throw Invalid_Argument("OCB requires 128 bit cipher"); + if(m_tag_size % 4 != 0 || m_tag_size < 8 || m_tag_size > 16) + throw Invalid_Argument("Invalid OCB tag length"); } OCB_Mode::~OCB_Mode() { /* for unique_ptr destructor */ } @@ -178,16 +172,16 @@ void OCB_Mode::set_associated_data(const byte ad[], size_t ad_len) secure_vector<byte> OCB_Mode::update_nonce(const byte nonce[], size_t nonce_len) { - BOTAN_ASSERT(nonce_len < BS(), "OCB nonce is less than cipher block size"); + BOTAN_ASSERT(nonce_len < 16, "OCB nonce is less than cipher block size"); - secure_vector<byte> nonce_buf(BS()); + secure_vector<byte> nonce_buf(16); - copy_mem(&nonce_buf[BS() - nonce_len], nonce, nonce_len); + copy_mem(&nonce_buf[16 - nonce_len], nonce, nonce_len); nonce_buf[0] = ((tag_size() * 8) % 128) << 1; - nonce_buf[BS() - nonce_len - 1] = 1; + nonce_buf[16 - nonce_len - 1] = 1; - const byte bottom = nonce_buf[BS()-1] & 0x3F; - nonce_buf[BS()-1] &= 0xC0; + const byte bottom = nonce_buf[16-1] & 0x3F; + nonce_buf[16-1] &= 0xC0; const bool need_new_stretch = (m_last_nonce != nonce_buf); @@ -197,7 +191,7 @@ OCB_Mode::update_nonce(const byte nonce[], size_t nonce_len) m_cipher->encrypt(nonce_buf); - for(size_t i = 0; i != BS() / 2; ++i) + for(size_t i = 0; i != 16 / 2; ++i) nonce_buf.push_back(nonce_buf[i] ^ nonce_buf[i+1]); m_stretch = nonce_buf; @@ -208,8 +202,8 @@ OCB_Mode::update_nonce(const byte nonce[], size_t nonce_len) const size_t shift_bytes = bottom / 8; const size_t shift_bits = bottom % 8; - secure_vector<byte> offset(BS()); - for(size_t i = 0; i != BS(); ++i) + secure_vector<byte> offset(16); + for(size_t i = 0; i != 16; ++i) { offset[i] = (m_stretch[i+shift_bytes] << shift_bits); offset[i] |= (m_stretch[i+shift_bytes+1] >> (8-shift_bits)); @@ -218,7 +212,7 @@ OCB_Mode::update_nonce(const byte nonce[], size_t nonce_len) return offset; } -secure_vector<byte> OCB_Mode::start_raw(const byte nonce[], size_t nonce_len) +void OCB_Mode::start_msg(const byte nonce[], size_t nonce_len) { if(!valid_nonce_length(nonce_len)) throw Invalid_IV_Length(name(), nonce_len); @@ -228,18 +222,16 @@ secure_vector<byte> OCB_Mode::start_raw(const byte nonce[], size_t nonce_len) m_offset = update_nonce(nonce, nonce_len); zeroise(m_checksum); m_block_index = 0; - - return secure_vector<byte>(); } void OCB_Encryption::encrypt(byte buffer[], size_t blocks) { - const size_t par_blocks = m_checksum.size() / BS(); + const size_t par_blocks = m_checksum.size() / 16; while(blocks) { const size_t proc_blocks = std::min(blocks, par_blocks); - const size_t proc_bytes = proc_blocks * BS(); + const size_t proc_bytes = proc_blocks * 16; const auto& offsets = m_L->compute_offsets(m_offset, m_block_index, proc_blocks); @@ -255,14 +247,11 @@ void OCB_Encryption::encrypt(byte buffer[], size_t blocks) } } -void OCB_Encryption::update(secure_vector<byte>& buffer, size_t offset) +size_t OCB_Encryption::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - - BOTAN_ASSERT(sz % BS() == 0, "Input length is an even number of blocks"); - encrypt(buf, sz / BS()); + BOTAN_ASSERT(sz % 16 == 0, "Invalid OCB input size"); + encrypt(buf, sz / 16); + return sz; } void OCB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) @@ -273,14 +262,14 @@ void OCB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) if(sz) { - const size_t final_full_blocks = sz / BS(); - const size_t remainder_bytes = sz - (final_full_blocks * BS()); + const size_t final_full_blocks = sz / 16; + const size_t remainder_bytes = sz - (final_full_blocks * 16); encrypt(buf, final_full_blocks); if(remainder_bytes) { - BOTAN_ASSERT(remainder_bytes < BS(), "Only a partial block left"); + BOTAN_ASSERT(remainder_bytes < 16, "Only a partial block left"); byte* remainder = &buf[sz - remainder_bytes]; xor_buf(m_checksum.data(), remainder, remainder_bytes); @@ -288,13 +277,13 @@ void OCB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) m_offset ^= m_L->star(); // Offset_* - secure_vector<byte> zeros(BS()); + secure_vector<byte> zeros(16); m_cipher->encrypt(m_offset, zeros); xor_buf(remainder, zeros.data(), remainder_bytes); } } - secure_vector<byte> checksum(BS()); + secure_vector<byte> checksum(16); // fold checksum for(size_t i = 0; i != m_checksum.size(); ++i) @@ -320,14 +309,14 @@ void OCB_Decryption::decrypt(byte buffer[], size_t blocks) { const size_t par_bytes = m_cipher->parallel_bytes(); - BOTAN_ASSERT(par_bytes % BS() == 0, "Cipher is parallel in full blocks"); + BOTAN_ASSERT(par_bytes % 16 == 0, "Cipher is parallel in full blocks"); - const size_t par_blocks = par_bytes / BS(); + const size_t par_blocks = par_bytes / 16; while(blocks) { const size_t proc_blocks = std::min(blocks, par_blocks); - const size_t proc_bytes = proc_blocks * BS(); + const size_t proc_bytes = proc_blocks * 16; const auto& offsets = m_L->compute_offsets(m_offset, m_block_index, proc_blocks); @@ -343,15 +332,11 @@ void OCB_Decryption::decrypt(byte buffer[], size_t blocks) } } -void OCB_Decryption::update(secure_vector<byte>& buffer, size_t offset) +size_t OCB_Decryption::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - - BOTAN_ASSERT(sz % BS() == 0, "Input length is an even number of blocks"); - - decrypt(buf, sz / BS()); + BOTAN_ASSERT(sz % 16 == 0, "Invalid OCB input size"); + decrypt(buf, sz / 16); + return sz; } void OCB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) @@ -366,20 +351,20 @@ void OCB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) if(remaining) { - const size_t final_full_blocks = remaining / BS(); - const size_t final_bytes = remaining - (final_full_blocks * BS()); + const size_t final_full_blocks = remaining / 16; + const size_t final_bytes = remaining - (final_full_blocks * 16); decrypt(buf, final_full_blocks); if(final_bytes) { - BOTAN_ASSERT(final_bytes < BS(), "Only a partial block left"); + BOTAN_ASSERT(final_bytes < 16, "Only a partial block left"); byte* remainder = &buf[remaining - final_bytes]; m_offset ^= m_L->star(); // Offset_* - secure_vector<byte> pad(BS()); + secure_vector<byte> pad(16); m_cipher->encrypt(m_offset, pad); // P_* xor_buf(remainder, pad.data(), final_bytes); @@ -389,7 +374,7 @@ void OCB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) } } - secure_vector<byte> checksum(BS()); + secure_vector<byte> checksum(16); // fold checksum for(size_t i = 0; i != m_checksum.size(); ++i) diff --git a/src/lib/modes/aead/ocb/ocb.h b/src/lib/modes/aead/ocb/ocb.h index 92edce970..4daa7a81b 100644 --- a/src/lib/modes/aead/ocb/ocb.h +++ b/src/lib/modes/aead/ocb/ocb.h @@ -49,20 +49,17 @@ class BOTAN_DLL OCB_Mode : public AEAD_Mode */ OCB_Mode(BlockCipher* cipher, size_t tag_size); - size_t BS() const { return m_BS; } - // fixme make these private std::unique_ptr<BlockCipher> m_cipher; std::unique_ptr<L_computer> m_L; - size_t m_BS; size_t m_block_index = 0; secure_vector<byte> m_checksum; secure_vector<byte> m_offset; secure_vector<byte> m_ad_hash; private: - secure_vector<byte> start_raw(const byte nonce[], size_t nonce_len) override; + void start_msg(const byte nonce[], size_t nonce_len) override; void key_schedule(const byte key[], size_t length) override; @@ -88,7 +85,7 @@ class BOTAN_DLL OCB_Encryption final : public OCB_Mode size_t minimum_final_size() const override { return 0; } - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t size) override; void finish(secure_vector<byte>& final_block, size_t offset = 0) override; private: @@ -113,7 +110,7 @@ class BOTAN_DLL OCB_Decryption final : public OCB_Mode size_t minimum_final_size() const override { return tag_size(); } - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t size) override; void finish(secure_vector<byte>& final_block, size_t offset = 0) override; private: diff --git a/src/lib/modes/aead/siv/siv.cpp b/src/lib/modes/aead/siv/siv.cpp index a4cb65a94..9e638b659 100644 --- a/src/lib/modes/aead/siv/siv.cpp +++ b/src/lib/modes/aead/siv/siv.cpp @@ -70,7 +70,7 @@ void SIV_Mode::set_associated_data_n(size_t n, const byte ad[], size_t length) m_ad_macs[n] = m_cmac->process(ad, length); } -secure_vector<byte> SIV_Mode::start_raw(const byte nonce[], size_t nonce_len) +void SIV_Mode::start_msg(const byte nonce[], size_t nonce_len) { if(!valid_nonce_length(nonce_len)) throw Invalid_IV_Length(name(), nonce_len); @@ -81,18 +81,13 @@ secure_vector<byte> SIV_Mode::start_raw(const byte nonce[], size_t nonce_len) m_nonce.clear(); m_msg_buf.clear(); - - return secure_vector<byte>(); } -void SIV_Mode::update(secure_vector<byte>& buffer, size_t offset) +size_t SIV_Mode::process(uint8_t buf[], size_t sz) { - BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); - const size_t sz = buffer.size() - offset; - byte* buf = buffer.data() + offset; - + // all output is saved for processing in finish m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz); - buffer.resize(offset); // truncate msg + return 0; } secure_vector<byte> SIV_Mode::S2V(const byte* text, size_t text_len) diff --git a/src/lib/modes/aead/siv/siv.h b/src/lib/modes/aead/siv/siv.h index d3e4c5270..6acfe515a 100644 --- a/src/lib/modes/aead/siv/siv.h +++ b/src/lib/modes/aead/siv/siv.h @@ -21,7 +21,7 @@ namespace Botan { class BOTAN_DLL SIV_Mode : public AEAD_Mode { public: - void update(secure_vector<byte>& blocks, size_t offset = 0) override; + size_t process(uint8_t buf[], size_t size) override; void set_associated_data_n(size_t n, const byte ad[], size_t ad_len); @@ -53,7 +53,7 @@ class BOTAN_DLL SIV_Mode : public AEAD_Mode secure_vector<byte> S2V(const byte text[], size_t text_len); private: - secure_vector<byte> start_raw(const byte nonce[], size_t nonce_len) override; + void start_msg(const byte nonce[], size_t nonce_len) override; void key_schedule(const byte key[], size_t length) override; |