diff options
-rw-r--r-- | src/aead/aead.h | 16 | ||||
-rw-r--r-- | src/aead/eax/eax.cpp | 45 | ||||
-rw-r--r-- | src/aead/eax/eax.h | 8 | ||||
-rw-r--r-- | src/aead/gcm/gcm.cpp | 45 | ||||
-rw-r--r-- | src/aead/gcm/gcm.h | 8 | ||||
-rw-r--r-- | src/aead/ocb/ocb.cpp | 54 | ||||
-rw-r--r-- | src/aead/ocb/ocb.h | 8 |
7 files changed, 117 insertions, 67 deletions
diff --git a/src/aead/aead.h b/src/aead/aead.h index 736de85e1..e0e07e8ab 100644 --- a/src/aead/aead.h +++ b/src/aead/aead.h @@ -34,6 +34,11 @@ class AEAD_Mode : public SymmetricAlgorithm virtual size_t minimum_final_size() const = 0; /** + * @return Random nonce appropriate for passing to start + */ + //virtual secure_vector<byte> nonce(RandomNumberGenerator& rng) const = 0; + + /** * Set associated data that is not included in the ciphertext but * that should be authenticated. Must be called after set_key * and before end_msg. @@ -47,6 +52,12 @@ class AEAD_Mode : public SymmetricAlgorithm */ virtual void set_associated_data(const byte ad[], size_t ad_len) = 0; + template<typename Alloc> + void set_associated_data_vec(const std::vector<byte, Alloc>& ad) + { + set_associated_data(&ad[0], ad.size()); + } + virtual bool valid_nonce_length(size_t) const = 0; /** @@ -68,7 +79,7 @@ class AEAD_Mode : public SymmetricAlgorithm * update_granularity() byte blocks. * @param blocks in/out paramter which will possibly be resized */ - virtual void update(secure_vector<byte>& blocks) = 0; + virtual void update(secure_vector<byte>& blocks, size_t offset = 0) = 0; /** * Complete processing of a message. For decryption, may throw an exception @@ -76,8 +87,9 @@ class AEAD_Mode : public SymmetricAlgorithm * * @param final_block in/out parameter which must be at least * minimum_final_size() bytes, and will be set to any final output + * @param offset an offset into final_block to begin processing */ - virtual void finish(secure_vector<byte>& final_block) = 0; + virtual void finish(secure_vector<byte>& final_block, size_t offset = 0) = 0; virtual ~AEAD_Mode() {} }; diff --git a/src/aead/eax/eax.cpp b/src/aead/eax/eax.cpp index 725a473f4..c6aaa9e85 100644 --- a/src/aead/eax/eax.cpp +++ b/src/aead/eax/eax.cpp @@ -108,15 +108,19 @@ secure_vector<byte> EAX_Mode::start(const byte nonce[], size_t nonce_len) return secure_vector<byte>(); } -void EAX_Encryption::update(secure_vector<byte>& buffer) +void EAX_Encryption::update(secure_vector<byte>& buffer, size_t offset) { - m_ctr->cipher(&buffer[0], &buffer[0], buffer.size()); - m_cmac->update(&buffer[0], buffer.size()); + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + m_ctr->cipher(buf, buf, sz); + m_cmac->update(buf, sz); } -void EAX_Encryption::finish(secure_vector<byte>& buffer) +void EAX_Encryption::finish(secure_vector<byte>& buffer, size_t offset) { - update(buffer); + update(buffer, offset); secure_vector<byte> data_mac = m_cmac->final(); xor_buf(data_mac, m_nonce_mac, data_mac.size()); @@ -125,26 +129,33 @@ void EAX_Encryption::finish(secure_vector<byte>& buffer) buffer += std::make_pair(&data_mac[0], tag_size()); } -void EAX_Decryption::update(secure_vector<byte>& buffer) +void EAX_Decryption::update(secure_vector<byte>& buffer, size_t offset) { - m_cmac->update(&buffer[0], buffer.size()); - m_ctr->cipher(&buffer[0], &buffer[0], buffer.size()); + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + m_cmac->update(buf, sz); + m_ctr->cipher(buf, buf, sz); } -void EAX_Decryption::finish(secure_vector<byte>& buffer) +void EAX_Decryption::finish(secure_vector<byte>& buffer, size_t offset) { - BOTAN_ASSERT(buffer.size() >= tag_size(), - "Have the tag as part of final input"); + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input"); - const size_t remaining = buffer.size() - tag_size(); + const size_t remaining = sz - tag_size(); - if(remaining) // handle any remaining input + if(remaining) { - m_cmac->update(&buffer[0], remaining); - m_ctr->cipher(&buffer[0], &buffer[0], remaining); + m_cmac->update(buf, remaining); + m_ctr->cipher(buf, buf, remaining); } - const byte* included_tag = &buffer[remaining]; + const byte* included_tag = &buf[remaining]; secure_vector<byte> mac = m_cmac->final(); mac ^= m_nonce_mac; @@ -153,7 +164,7 @@ void EAX_Decryption::finish(secure_vector<byte>& buffer) if(!same_mem(&mac[0], included_tag, tag_size())) throw Integrity_Failure("EAX tag check failed"); - buffer.resize(remaining); + buffer.resize(offset + remaining); } } diff --git a/src/aead/eax/eax.h b/src/aead/eax/eax.h index f3562f755..6720bdca4 100644 --- a/src/aead/eax/eax.h +++ b/src/aead/eax/eax.h @@ -75,9 +75,9 @@ class BOTAN_DLL EAX_Encryption : public EAX_Mode size_t minimum_final_size() const override { return 0; } - void update(secure_vector<byte>& blocks) override; + void update(secure_vector<byte>& blocks, size_t offset) override; - void finish(secure_vector<byte>& final_block) override; + void finish(secure_vector<byte>& final_block, size_t offset) override; }; /** @@ -95,9 +95,9 @@ class BOTAN_DLL EAX_Decryption : public EAX_Mode size_t minimum_final_size() const override { return tag_size(); } - void update(secure_vector<byte>& blocks) override; + void update(secure_vector<byte>& blocks, size_t offset) override; - void finish(secure_vector<byte>& final_block) override; + void finish(secure_vector<byte>& final_block, size_t offset) override; }; } diff --git a/src/aead/gcm/gcm.cpp b/src/aead/gcm/gcm.cpp index a5ccee927..665fc4472 100644 --- a/src/aead/gcm/gcm.cpp +++ b/src/aead/gcm/gcm.cpp @@ -182,16 +182,20 @@ secure_vector<byte> GCM_Mode::start(const byte nonce[], size_t nonce_len) return secure_vector<byte>(); } -void GCM_Encryption::update(secure_vector<byte>& buffer) +void GCM_Encryption::update(secure_vector<byte>& buffer, size_t offset) { - m_ctr->cipher(&buffer[0], &buffer[0], buffer.size()); - ghash_update(m_H, m_mac, &buffer[0], buffer.size()); - m_text_len += buffer.size(); + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + m_ctr->cipher(buf, buf, sz); + ghash_update(m_H, m_mac, buf, sz); + m_text_len += sz; } -void GCM_Encryption::finish(secure_vector<byte>& buffer) +void GCM_Encryption::finish(secure_vector<byte>& buffer, size_t offset) { - update(buffer); + update(buffer, offset); ghash_finalize(m_H, m_mac, m_ad_len, m_text_len); @@ -200,25 +204,32 @@ void GCM_Encryption::finish(secure_vector<byte>& buffer) buffer += std::make_pair(&m_mac[0], tag_size()); } -void GCM_Decryption::update(secure_vector<byte>& buffer) +void GCM_Decryption::update(secure_vector<byte>& buffer, size_t offset) { - ghash_update(m_H, m_mac, &buffer[0], buffer.size()); - m_ctr->cipher(&buffer[0], &buffer[0], buffer.size()); - m_text_len += buffer.size(); + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + ghash_update(m_H, m_mac, buf, sz); + m_ctr->cipher(buf, buf, sz); + m_text_len += sz; } -void GCM_Decryption::finish(secure_vector<byte>& buffer) +void GCM_Decryption::finish(secure_vector<byte>& buffer, size_t offset) { - BOTAN_ASSERT(buffer.size() >= tag_size(), - "Have the tag as part of final input"); + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input"); - const size_t remaining = buffer.size() - tag_size(); + const size_t remaining = sz - tag_size(); // handle any final input before the tag if(remaining) { - ghash_update(m_H, m_mac, &buffer[0], remaining); - m_ctr->cipher(&buffer[0], &buffer[0], remaining); + ghash_update(m_H, m_mac, buf, remaining); + m_ctr->cipher(buf, buf, remaining); m_text_len += remaining; } @@ -231,7 +242,7 @@ void GCM_Decryption::finish(secure_vector<byte>& buffer) if(!same_mem(&m_mac[0], included_tag, tag_size())) throw Integrity_Failure("GCM tag check failed"); - buffer.resize(remaining); + buffer.resize(offset + remaining); } } diff --git a/src/aead/gcm/gcm.h b/src/aead/gcm/gcm.h index cf7d94ced..bc7eaae20 100644 --- a/src/aead/gcm/gcm.h +++ b/src/aead/gcm/gcm.h @@ -70,9 +70,9 @@ class BOTAN_DLL GCM_Encryption : public GCM_Mode size_t minimum_final_size() const override { return 0; } - void update(secure_vector<byte>& blocks) override; + void update(secure_vector<byte>& blocks, size_t offset) override; - void finish(secure_vector<byte>& final_block) override; + void finish(secure_vector<byte>& final_block, size_t offset) override; }; /** @@ -90,9 +90,9 @@ class BOTAN_DLL GCM_Decryption : public GCM_Mode size_t minimum_final_size() const override { return tag_size(); } - void update(secure_vector<byte>& blocks) override; + void update(secure_vector<byte>& blocks, size_t offset) override; - void finish(secure_vector<byte>& final_block) override; + void finish(secure_vector<byte>& final_block, size_t offset) override; }; } diff --git a/src/aead/ocb/ocb.cpp b/src/aead/ocb/ocb.cpp index ec5835d79..4cbd8bde8 100644 --- a/src/aead/ocb/ocb.cpp +++ b/src/aead/ocb/ocb.cpp @@ -272,26 +272,34 @@ void OCB_Encryption::encrypt(byte buffer[], size_t blocks) m_checksum[i % BS] ^= csum_accum[i]; } -void OCB_Encryption::update(secure_vector<byte>& buffer) +void OCB_Encryption::update(secure_vector<byte>& buffer, size_t offset) { - BOTAN_ASSERT(buffer.size() % BS == 0, "Input length is an even number of blocks"); + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; - encrypt(&buffer[0], buffer.size() / BS); + BOTAN_ASSERT(sz % BS == 0, "Input length is an even number of blocks"); + + encrypt(buf, sz / BS); } -void OCB_Encryption::finish(secure_vector<byte>& buffer) +void OCB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) { - if(!buffer.empty()) + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + if(sz) { - const size_t final_full_blocks = buffer.size() / BS; - const size_t remainder_bytes = buffer.size() - (final_full_blocks * BS); + const size_t final_full_blocks = sz / BS; + const size_t remainder_bytes = sz - (final_full_blocks * BS); - encrypt(&buffer[0], final_full_blocks); + encrypt(buf, final_full_blocks); if(remainder_bytes) { BOTAN_ASSERT(remainder_bytes < BS, "Only a partial block left"); - byte* remainder = &buffer[buffer.size() - remainder_bytes]; + byte* remainder = &buf[sz - remainder_bytes]; xor_buf(&m_checksum[0], &remainder[0], remainder_bytes); m_checksum[remainder_bytes] ^= 0x80; @@ -363,31 +371,39 @@ void OCB_Decryption::decrypt(byte buffer[], size_t blocks) m_checksum[i % BS] ^= csum_accum[i]; } -void OCB_Decryption::update(secure_vector<byte>& buffer) +void OCB_Decryption::update(secure_vector<byte>& buffer, size_t offset) { - BOTAN_ASSERT(buffer.size() % BS == 0, "Input length is an even number of blocks"); + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; - decrypt(&buffer[0], buffer.size() / BS); + BOTAN_ASSERT(sz % BS == 0, "Input length is an even number of blocks"); + + decrypt(buf, sz / BS); } -void OCB_Decryption::finish(secure_vector<byte>& buffer) +void OCB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) { - BOTAN_ASSERT(buffer.size() >= tag_size(), "We have the tag"); + BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane"); + const size_t sz = buffer.size() - offset; + byte* buf = &buffer[offset]; + + BOTAN_ASSERT(sz >= tag_size(), "We have the tag"); - const size_t remaining = buffer.size() - tag_size(); + const size_t remaining = sz - tag_size(); if(remaining) { const size_t final_full_blocks = remaining / BS; const size_t final_bytes = remaining - (final_full_blocks * BS); - decrypt(&buffer[0], final_full_blocks); + decrypt(&buf[0], final_full_blocks); if(final_bytes) { BOTAN_ASSERT(final_bytes < BS, "Only a partial block left"); - byte* remainder = &buffer[remaining - final_bytes]; + byte* remainder = &buf[remaining - final_bytes]; m_offset ^= m_L->star(); // Offset_* @@ -416,13 +432,13 @@ void OCB_Decryption::finish(secure_vector<byte>& buffer) m_block_index = 0; // compare mac - const byte* included_tag = &buffer[remaining]; + const byte* included_tag = &buf[remaining]; if(!same_mem(&mac[0], included_tag, tag_size())) throw Integrity_Failure("OCB tag check failed"); // remove tag from end of message - buffer.resize(remaining); + buffer.resize(remaining + offset); } } diff --git a/src/aead/ocb/ocb.h b/src/aead/ocb/ocb.h index 9d10c2656..d50710a79 100644 --- a/src/aead/ocb/ocb.h +++ b/src/aead/ocb/ocb.h @@ -84,9 +84,9 @@ class BOTAN_DLL OCB_Encryption : public OCB_Mode size_t minimum_final_size() const override { return 0; } - void update(secure_vector<byte>& blocks) override; + void update(secure_vector<byte>& blocks, size_t offset) override; - void finish(secure_vector<byte>& final_block) override; + void finish(secure_vector<byte>& final_block, size_t offset) override; private: void encrypt(byte input[], size_t blocks); }; @@ -103,9 +103,9 @@ class BOTAN_DLL OCB_Decryption : public OCB_Mode size_t minimum_final_size() const override { return tag_size(); } - void update(secure_vector<byte>& blocks) override; + void update(secure_vector<byte>& blocks, size_t offset) override; - void finish(secure_vector<byte>& final_block) override; + void finish(secure_vector<byte>& final_block, size_t offset) override; private: void decrypt(byte input[], size_t blocks); }; |