aboutsummaryrefslogtreecommitdiffstats
path: root/src/modes/aead
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-08-25 18:27:52 +0000
committerlloyd <[email protected]>2013-08-25 18:27:52 +0000
commita2443d682d13032b205d0b6814c3df1a223f77b2 (patch)
treefd5aeb595b9cb77cee74c9e9c6b798a934de0a05 /src/modes/aead
parent8e264435dc3645334098ed47c84bb2ada6a684e3 (diff)
Some OCB cleanups
Diffstat (limited to 'src/modes/aead')
-rw-r--r--src/modes/aead/ocb/ocb.cpp174
-rw-r--r--src/modes/aead/ocb/ocb.h14
2 files changed, 90 insertions, 98 deletions
diff --git a/src/modes/aead/ocb/ocb.cpp b/src/modes/aead/ocb/ocb.cpp
index a18a9c50e..34ea4b9ad 100644
--- a/src/modes/aead/ocb/ocb.cpp
+++ b/src/modes/aead/ocb/ocb.cpp
@@ -13,6 +13,12 @@
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
{
@@ -31,6 +37,22 @@ class L_computer
const secure_vector<byte>& operator()(size_t i) const { return get(i); }
+ const secure_vector<byte>& compute_offsets(secure_vector<byte>& offset,
+ size_t block_index,
+ size_t blocks) const
+ {
+ m_offset_buf.resize(blocks*BS);
+
+ 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[0], BS);
+ }
+
+ return m_offset_buf;
+ }
+
+ private:
const secure_vector<byte>& get(size_t i) const
{
while(m_L.size() <= i)
@@ -39,7 +61,6 @@ class L_computer
return m_L.at(i);
}
- private:
secure_vector<byte> poly_double(const secure_vector<byte>& in) const
{
return CMAC::poly_double(in, 0x87);
@@ -47,65 +68,9 @@ class L_computer
secure_vector<byte> m_L_dollar, m_L_star;
mutable std::vector<secure_vector<byte>> m_L;
+ mutable secure_vector<byte> m_offset_buf;
};
-class Nonce_State
- {
- public:
- Nonce_State(const BlockCipher& cipher) : m_cipher(cipher) {}
-
- secure_vector<byte> update_nonce(const byte nonce[],
- size_t nonce_len);
- private:
- const BlockCipher& m_cipher;
- secure_vector<byte> m_last_nonce;
- secure_vector<byte> m_stretch;
- };
-
-secure_vector<byte>
-Nonce_State::update_nonce(const byte nonce[], size_t nonce_len)
- {
- const size_t BS = 16;
-
- BOTAN_ASSERT(nonce_len < BS, "Nonce is less than 128 bits");
-
- secure_vector<byte> nonce_buf(BS);
-
- copy_mem(&nonce_buf[BS - nonce_len], nonce, nonce_len);
- nonce_buf[BS - nonce_len - 1] = 1;
-
- const byte bottom = nonce_buf[15] & 0x3F;
- nonce_buf[15] &= 0xC0;
-
- const bool need_new_stretch = (m_last_nonce != nonce_buf);
-
- if(need_new_stretch)
- {
- m_last_nonce = nonce_buf;
-
- m_cipher.encrypt(nonce_buf);
-
- for(size_t i = 0; i != 8; ++i)
- nonce_buf.push_back(nonce_buf[i] ^ nonce_buf[i+1]);
-
- m_stretch = nonce_buf;
- }
-
- // now set the offset from stretch and bottom
-
- 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)
- {
- offset[i] = (m_stretch[i+shift_bytes] << shift_bits);
- offset[i] |= (m_stretch[i+shift_bytes+1] >> (8-shift_bits));
- }
-
- return offset;
- }
-
namespace {
/*
@@ -115,8 +80,6 @@ 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);
@@ -158,8 +121,10 @@ secure_vector<byte> ocb_hash(const L_computer& L,
OCB_Mode::OCB_Mode(BlockCipher* cipher, size_t tag_size) :
m_cipher(cipher),
- m_tag_size(tag_size),
- m_ad_hash(BS), m_offset(BS), m_checksum(m_cipher->parallel_bytes())
+ m_checksum(m_cipher->parallel_bytes()),
+ m_offset(BS),
+ m_ad_hash(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 " +
@@ -177,6 +142,7 @@ void OCB_Mode::clear()
{
m_cipher.reset();
m_L.reset();
+
zeroise(m_ad_hash);
zeroise(m_offset);
zeroise(m_checksum);
@@ -194,7 +160,7 @@ std::string OCB_Mode::name() const
size_t OCB_Mode::update_granularity() const
{
- return 8 * m_cipher->parallel_bytes();
+ return m_cipher->parallel_bytes();
}
Key_Length_Specification OCB_Mode::key_spec() const
@@ -206,7 +172,6 @@ void OCB_Mode::key_schedule(const byte key[], size_t length)
{
m_cipher->set_key(key, length);
m_L.reset(new L_computer(*m_cipher));
- m_nonce_state.reset(new Nonce_State(*m_cipher));
}
void OCB_Mode::set_associated_data(const byte ad[], size_t ad_len)
@@ -215,14 +180,56 @@ void OCB_Mode::set_associated_data(const byte ad[], size_t ad_len)
m_ad_hash = ocb_hash(*m_L, *m_cipher, &ad[0], 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");
+
+ secure_vector<byte> nonce_buf(BS);
+
+ copy_mem(&nonce_buf[BS - nonce_len], nonce, nonce_len);
+ nonce_buf[BS - nonce_len - 1] = 1;
+
+ const byte bottom = nonce_buf[15] & 0x3F;
+ nonce_buf[15] &= 0xC0;
+
+ const bool need_new_stretch = (m_last_nonce != nonce_buf);
+
+ if(need_new_stretch)
+ {
+ m_last_nonce = nonce_buf;
+
+ m_cipher->encrypt(nonce_buf);
+
+ for(size_t i = 0; i != 8; ++i)
+ nonce_buf.push_back(nonce_buf[i] ^ nonce_buf[i+1]);
+
+ m_stretch = nonce_buf;
+ }
+
+ // now set the offset from stretch and bottom
+
+ 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)
+ {
+ offset[i] = (m_stretch[i+shift_bytes] << shift_bits);
+ offset[i] |= (m_stretch[i+shift_bytes+1] >> (8-shift_bits));
+ }
+
+ return offset;
+ }
+
secure_vector<byte> OCB_Mode::start(const byte nonce[], size_t nonce_len)
{
if(!valid_nonce_length(nonce_len))
throw Invalid_IV_Length(name(), nonce_len);
- BOTAN_ASSERT(m_nonce_state, "A key was set");
+ BOTAN_ASSERT(m_L, "A key was set");
- m_offset = m_nonce_state->update_nonce(nonce, nonce_len);
+ m_offset = update_nonce(nonce, nonce_len);
zeroise(m_checksum);
m_block_index = 0;
@@ -235,21 +242,12 @@ void OCB_Encryption::encrypt(byte buffer[], size_t blocks)
const size_t par_blocks = m_checksum.size() / BS;
- std::vector<byte> offsets(m_checksum.size());
-
- size_t blocks_left = blocks;
-
- while(blocks_left)
+ while(blocks)
{
- const size_t proc_blocks = std::min(blocks_left, par_blocks);
+ const size_t proc_blocks = std::min(blocks, par_blocks);
const size_t proc_bytes = proc_blocks * BS;
- for(size_t i = 0; i != proc_blocks; ++i)
- { // could be done in parallel
- //xor_buf(&m_offset[0],
- m_offset ^= L(ctz(++m_block_index));
- copy_mem(&offsets[BS*i], &m_offset[0], BS);
- }
+ const auto& offsets = L.compute_offsets(m_offset, m_block_index, proc_blocks);
xor_buf(&m_checksum[0], &buffer[0], proc_bytes);
@@ -258,7 +256,8 @@ void OCB_Encryption::encrypt(byte buffer[], size_t blocks)
xor_buf(&buffer[0], &offsets[0], proc_bytes);
buffer += proc_bytes;
- blocks_left -= proc_blocks;
+ blocks -= proc_blocks;
+ m_block_index += proc_blocks;
}
}
@@ -334,20 +333,12 @@ void OCB_Decryption::decrypt(byte buffer[], size_t blocks)
const size_t par_blocks = par_bytes / BS;
- secure_vector<byte> offsets(par_bytes);
-
- size_t blocks_left = blocks;
-
- while(blocks_left)
+ while(blocks)
{
- const size_t proc_blocks = std::min(blocks_left, par_blocks);
+ const size_t proc_blocks = std::min(blocks, par_blocks);
const size_t proc_bytes = proc_blocks * BS;
- for(size_t i = 0; i != proc_blocks; ++i)
- { // could be done in parallel
- m_offset ^= L(ctz(++m_block_index));
- copy_mem(&offsets[BS*i], &m_offset[0], BS);
- }
+ const auto& offsets = 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);
@@ -356,7 +347,8 @@ void OCB_Decryption::decrypt(byte buffer[], size_t blocks)
xor_buf(&m_checksum[0], &buffer[0], proc_bytes);
buffer += proc_bytes;
- blocks_left -= proc_blocks;
+ blocks -= proc_blocks;
+ m_block_index += proc_blocks;
}
}
diff --git a/src/modes/aead/ocb/ocb.h b/src/modes/aead/ocb/ocb.h
index c61983f44..9eb40e2cf 100644
--- a/src/modes/aead/ocb/ocb.h
+++ b/src/modes/aead/ocb/ocb.h
@@ -16,7 +16,6 @@
namespace Botan {
class L_computer;
-class Nonce_State;
/**
* OCB Mode (base class for OCB_Encryption and OCB_Decryption). Note
@@ -48,8 +47,6 @@ class BOTAN_DLL OCB_Mode : public AEAD_Mode
~OCB_Mode();
protected:
- static const size_t BS = 16; // intrinsic to OCB definition
-
/**
* @param cipher the 128-bit block cipher to use
* @param tag_size is how big the auth tag will be
@@ -62,14 +59,17 @@ class BOTAN_DLL OCB_Mode : public AEAD_Mode
std::unique_ptr<BlockCipher> m_cipher;
std::unique_ptr<L_computer> m_L;
- size_t m_tag_size = 0;
size_t m_block_index = 0;
- secure_vector<byte> m_ad_hash;
- secure_vector<byte> m_offset;
secure_vector<byte> m_checksum;
+ secure_vector<byte> m_offset;
+ secure_vector<byte> m_ad_hash;
private:
- std::unique_ptr<Nonce_State> m_nonce_state;
+ secure_vector<byte> update_nonce(const byte nonce[], size_t nonce_len);
+
+ size_t m_tag_size = 0;
+ secure_vector<byte> m_last_nonce;
+ secure_vector<byte> m_stretch;
};
class BOTAN_DLL OCB_Encryption : public OCB_Mode