diff options
-rw-r--r-- | src/lib/modes/aead/ocb/ocb.cpp | 90 | ||||
-rw-r--r-- | src/lib/modes/aead/ocb/ocb.h | 7 | ||||
-rw-r--r-- | src/tests/data/aead/ocb.vec | 104 | ||||
-rw-r--r-- | src/tests/test_ocb.cpp | 4 |
4 files changed, 152 insertions, 53 deletions
diff --git a/src/lib/modes/aead/ocb/ocb.cpp b/src/lib/modes/aead/ocb/ocb.cpp index 8bb45f217..f3aa8e06c 100644 --- a/src/lib/modes/aead/ocb/ocb.cpp +++ b/src/lib/modes/aead/ocb/ocb.cpp @@ -13,12 +13,6 @@ namespace Botan { -namespace { - -const size_t BS = 16; // intrinsic to OCB definition - -} - // Has to be in Botan namespace so unique_ptr can reference it class L_computer { @@ -41,7 +35,8 @@ class L_computer size_t block_index, size_t blocks) const { - m_offset_buf.resize(blocks*BS); + const size_t BS = m_L_star.size(); + m_offset_buf.resize(blocks * BS); for(size_t i = 0; i != blocks; ++i) { // could be done in parallel @@ -80,6 +75,8 @@ 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(BS); secure_vector<byte> offset(BS); @@ -121,16 +118,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(BS), - m_ad_hash(BS), + m_offset(m_BS), + m_ad_hash(m_BS), m_tag_size(tag_size) { - if(m_cipher->block_size() != BS) - throw std::invalid_argument("OCB requires a 128 bit cipher so cannot be used with " + - m_cipher->name()); + if(BS() != 16) + throw std::invalid_argument("OCB is not compatible with " + m_cipher->name()); - if(m_tag_size != 8 && m_tag_size != 12 && m_tag_size != 16) + if(m_tag_size % 4 != 0 || m_tag_size < 8 || m_tag_size > BS()) throw std::invalid_argument("OCB cannot produce a " + std::to_string(m_tag_size) + " byte tag"); @@ -150,7 +147,7 @@ void OCB_Mode::clear() bool OCB_Mode::valid_nonce_length(size_t length) const { - return (length > 0 && length < 16); + return (length > 0 && length < m_cipher->block_size()); } std::string OCB_Mode::name() const @@ -183,16 +180,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, "Nonce is less than 128 bits"); + BOTAN_ASSERT(nonce_len < BS(), "OCB nonce is less than cipher block size"); - secure_vector<byte> nonce_buf(BS); + secure_vector<byte> nonce_buf(BS()); - copy_mem(&nonce_buf[BS - nonce_len], nonce, nonce_len); + copy_mem(&nonce_buf[BS() - nonce_len], nonce, nonce_len); nonce_buf[0] = ((tag_size() * 8) % 128) << 1; - nonce_buf[BS - nonce_len - 1] = 1; + nonce_buf[BS() - nonce_len - 1] = 1; - const byte bottom = nonce_buf[15] & 0x3F; - nonce_buf[15] &= 0xC0; + const byte bottom = nonce_buf[BS()-1] & 0x3F; + nonce_buf[BS()-1] &= 0xC0; const bool need_new_stretch = (m_last_nonce != nonce_buf); @@ -202,7 +199,7 @@ OCB_Mode::update_nonce(const byte nonce[], size_t nonce_len) m_cipher->encrypt(nonce_buf); - for(size_t i = 0; i != 8; ++i) + for(size_t i = 0; i != BS() / 2; ++i) nonce_buf.push_back(nonce_buf[i] ^ nonce_buf[i+1]); m_stretch = nonce_buf; @@ -213,8 +210,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(BS()); + for(size_t i = 0; i != BS(); ++i) { offset[i] = (m_stretch[i+shift_bytes] << shift_bits); offset[i] |= (m_stretch[i+shift_bytes+1] >> (8-shift_bits)); @@ -239,16 +236,14 @@ secure_vector<byte> OCB_Mode::start_raw(const byte nonce[], size_t nonce_len) void OCB_Encryption::encrypt(byte buffer[], size_t blocks) { - const L_computer& L = *m_L; // convenient name - - const size_t par_blocks = m_checksum.size() / BS; + const size_t par_blocks = m_checksum.size() / BS(); 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 * BS(); - const auto& offsets = L.compute_offsets(m_offset, m_block_index, proc_blocks); + const auto& offsets = m_L->compute_offsets(m_offset, m_block_index, proc_blocks); xor_buf(&m_checksum[0], &buffer[0], proc_bytes); @@ -268,9 +263,8 @@ void OCB_Encryption::update(secure_vector<byte>& buffer, size_t offset) const size_t sz = buffer.size() - offset; byte* buf = &buffer[offset]; - BOTAN_ASSERT(sz % BS == 0, "Input length is an even number of blocks"); - - encrypt(buf, sz / 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, size_t offset) @@ -281,14 +275,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 / BS(); + const size_t remainder_bytes = sz - (final_full_blocks * BS()); encrypt(buf, final_full_blocks); if(remainder_bytes) { - BOTAN_ASSERT(remainder_bytes < BS, "Only a partial block left"); + BOTAN_ASSERT(remainder_bytes < BS(), "Only a partial block left"); byte* remainder = &buf[sz - remainder_bytes]; xor_buf(&m_checksum[0], &remainder[0], remainder_bytes); @@ -296,13 +290,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(BS()); m_cipher->encrypt(m_offset, zeros); xor_buf(&remainder[0], &zeros[0], remainder_bytes); } } - secure_vector<byte> checksum(BS); + secure_vector<byte> checksum(BS()); // fold checksum for(size_t i = 0; i != m_checksum.size(); ++i) @@ -326,20 +320,18 @@ void OCB_Encryption::finish(secure_vector<byte>& buffer, size_t offset) void OCB_Decryption::decrypt(byte buffer[], size_t blocks) { - const L_computer& L = *m_L; // convenient name - 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 % BS() == 0, "Cipher is parallel in full blocks"); - const size_t par_blocks = par_bytes / BS; + const size_t par_blocks = par_bytes / BS(); 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 * BS(); - const auto& offsets = L.compute_offsets(m_offset, m_block_index, proc_blocks); + const auto& offsets = m_L->compute_offsets(m_offset, m_block_index, proc_blocks); xor_buf(&buffer[0], &offsets[0], proc_bytes); m_cipher->decrypt_n(&buffer[0], &buffer[0], proc_blocks); @@ -359,9 +351,9 @@ void OCB_Decryption::update(secure_vector<byte>& buffer, size_t offset) const size_t sz = buffer.size() - offset; byte* buf = &buffer[offset]; - BOTAN_ASSERT(sz % BS == 0, "Input length is an even number of blocks"); + BOTAN_ASSERT(sz % BS() == 0, "Input length is an even number of blocks"); - decrypt(buf, sz / BS); + decrypt(buf, sz / BS()); } void OCB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) @@ -376,20 +368,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 / BS(); + const size_t final_bytes = remaining - (final_full_blocks * BS()); decrypt(&buf[0], final_full_blocks); if(final_bytes) { - BOTAN_ASSERT(final_bytes < BS, "Only a partial block left"); + BOTAN_ASSERT(final_bytes < BS(), "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(BS()); m_cipher->encrypt(m_offset, pad); // P_* xor_buf(&remainder[0], &pad[0], final_bytes); @@ -399,7 +391,7 @@ void OCB_Decryption::finish(secure_vector<byte>& buffer, size_t offset) } } - secure_vector<byte> checksum(BS); + secure_vector<byte> checksum(BS()); // 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 a7293ffcb..02ea0b0a1 100644 --- a/src/lib/modes/aead/ocb/ocb.h +++ b/src/lib/modes/aead/ocb/ocb.h @@ -1,6 +1,6 @@ /* * OCB Mode -* (C) 2013 Jack Lloyd +* (C) 2013,2014 Jack Lloyd * * Distributed under the terms of the Botan license */ @@ -50,12 +50,13 @@ class BOTAN_DLL OCB_Mode : public AEAD_Mode */ OCB_Mode(BlockCipher* cipher, size_t tag_size); - void key_schedule(const byte key[], size_t length) override; + 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; @@ -64,6 +65,8 @@ class BOTAN_DLL OCB_Mode : public AEAD_Mode private: secure_vector<byte> start_raw(const byte nonce[], size_t nonce_len) override; + void key_schedule(const byte key[], size_t length) override; + secure_vector<byte> update_nonce(const byte nonce[], size_t nonce_len); size_t m_tag_size = 0; diff --git a/src/tests/data/aead/ocb.vec b/src/tests/data/aead/ocb.vec index 63f3143d2..b8220d6bf 100644 --- a/src/tests/data/aead/ocb.vec +++ b/src/tests/data/aead/ocb.vec @@ -46,3 +46,107 @@ Nonce = 000102030405060708090A0B Key = 000102030405060708090A0B0C0D0E0F Out = BEA5E8798DBE7110031C144DA0B26122CEAAB9B05DF771A657149D53773463CB68C65778B058A635659C623211DEEA0DE30D2C381879F4C8 +# From RFC 7253 + +Nonce = BBAA99887766554433221100 +Key = 000102030405060708090A0B0C0D0E0F +AD = +In = +Out = 785407BFFFC8AD9EDCC5520AC9111EE6 + +Nonce = BBAA99887766554433221101 +Key = 000102030405060708090A0B0C0D0E0F +AD = 0001020304050607 +In = 0001020304050607 +Out = 6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009 + +Nonce = BBAA99887766554433221102 +Key = 000102030405060708090A0B0C0D0E0F +AD = 0001020304050607 +In = +Out = 81017F8203F081277152FADE694A0A00 + +Nonce = BBAA99887766554433221103 +Key = 000102030405060708090A0B0C0D0E0F +AD = +In = 0001020304050607 +Out = 45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9 + +Nonce = BBAA99887766554433221104 +Key = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F +In = 000102030405060708090A0B0C0D0E0F +Out = 571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358 + +Nonce = BBAA99887766554433221105 +Key = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F +In = +Out = 8CF761B6902EF764462AD86498CA6B97 + +Nonce = BBAA99887766554433221106 +Key = 000102030405060708090A0B0C0D0E0F +AD = +In = 000102030405060708090A0B0C0D0E0F +Out = 5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D + +Nonce = BBAA99887766554433221107 +Key = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +In = 000102030405060708090A0B0C0D0E0F1011121314151617 +Out = 1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F + +Nonce = BBAA99887766554433221108 +Key = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F1011121314151617 +In = +Out = 6DC225A071FC1B9F7C69F93B0F1E10DE + +Nonce = BBAA99887766554433221109 +Key = 000102030405060708090A0B0C0D0E0F +AD = +In = 000102030405060708090A0B0C0D0E0F1011121314151617 +Out = 221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF + +Nonce = BBAA9988776655443322110A +Key = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +In = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Out = BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240 + +Nonce = BBAA9988776655443322110B +Key = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +In = +Out = FE80690BEE8A485D11F32965BC9D2A32 + +Nonce = BBAA9988776655443322110C +Key = 000102030405060708090A0B0C0D0E0F +AD = +In = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Out = 2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF + +Nonce = BBAA9988776655443322110D +Key = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627 +In = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627 +Out = D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60 + +Nonce = BBAA9988776655443322110E +Key = 000102030405060708090A0B0C0D0E0F +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627 +In = +Out = C5CD9D1850C141E358649994EE701B68 + +Nonce = BBAA9988776655443322110F +Key = 000102030405060708090A0B0C0D0E0F +AD = +In = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627 +Out = 4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479 + +[AES-128/OCB(12)] +Key = 0F0E0D0C0B0A09080706050403020100 +Nonce = BBAA9988776655443322110D +AD = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627 +In = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627 +Out = 1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA diff --git a/src/tests/test_ocb.cpp b/src/tests/test_ocb.cpp index 17cbf4bb1..1c83c8933 100644 --- a/src/tests/test_ocb.cpp +++ b/src/tests/test_ocb.cpp @@ -2,7 +2,7 @@ #include "tests.h" #include <iostream> -#if defined(BOTAN_HAS_OCB) +#if defined(BOTAN_HAS_AEAD_OCB) #include <botan/ocb.h> #include <botan/hex.h> #include <botan/sha2_32.h> @@ -134,7 +134,7 @@ size_t test_ocb() { size_t fails = 0; -#if defined(BOTAN_HAS_OCB) +#if defined(BOTAN_HAS_AEAD_OCB) fails += test_ocb_long(128, "B2B41CBF9B05037DA7F16C24A35C1C94"); fails += test_ocb_long(96, "1A4F0654277709A5BDA0D380"); fails += test_ocb_long(64, "B7ECE9D381FE437F"); |