aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/filters/modes/ocb/ocb.cpp100
-rw-r--r--src/filters/modes/ocb/ocb.h5
2 files changed, 64 insertions, 41 deletions
diff --git a/src/filters/modes/ocb/ocb.cpp b/src/filters/modes/ocb/ocb.cpp
index 20cf8b37c..86057cec6 100644
--- a/src/filters/modes/ocb/ocb.cpp
+++ b/src/filters/modes/ocb/ocb.cpp
@@ -35,7 +35,6 @@ operator^=(std::vector<T, Alloc>& out,
using namespace ShouldNotBeHere;
-
// Has to be in Botan namespace so unique_ptr can reference it
class L_computer
{
@@ -60,7 +59,7 @@ class L_computer
L_computer::L_computer(const BlockCipher& cipher)
{
- m_L_star.resize(16);
+ m_L_star.resize(cipher.block_size());
cipher.encrypt(m_L_star);
m_L_dollar = poly_double(star());
m_L.push_back(poly_double(dollar()));
@@ -74,6 +73,19 @@ const secure_vector<byte>& L_computer::operator()(size_t i) const
return m_L.at(i);
}
+#if 0
+class Nonce_State
+ {
+ public:
+ secure_vector<byte> update_nonce(const byte nonce[], size_t nonce_len);
+
+ bool fresh_nonce() { bool b = false; std::swap(b, m_fresh); return b; }
+ private:
+ secure_vector<byte> m_stretch;
+ bool m_fresh = false;
+ };
+#endif
+
namespace {
/*
@@ -83,13 +95,15 @@ secure_vector<byte> ocb_hash(const L_computer& L,
const BlockCipher& cipher,
const byte ad[], size_t ad_len)
{
- secure_vector<byte> sum(16);
- secure_vector<byte> offset(16);
+ const size_t BS = cipher.block_size();
- secure_vector<byte> buf(16);
+ secure_vector<byte> sum(BS);
+ secure_vector<byte> offset(BS);
- const size_t ad_blocks = (ad_len / 16);
- const size_t ad_remainder = (ad_len % 16);
+ secure_vector<byte> buf(BS);
+
+ const size_t ad_blocks = (ad_len / BS);
+ const size_t ad_remainder = (ad_len % BS);
for(size_t i = 0; i != ad_blocks; ++i)
{
@@ -97,7 +111,7 @@ secure_vector<byte> ocb_hash(const L_computer& L,
offset ^= L(ctz(i+1));
buf = offset;
- xor_buf(&buf[0], &ad[16*i], 16);
+ xor_buf(&buf[0], &ad[BS*i], BS);
cipher.encrypt(buf);
@@ -109,8 +123,8 @@ secure_vector<byte> ocb_hash(const L_computer& L,
offset ^= L.star();
buf = offset;
- xor_buf(&buf[0], &ad[16*ad_blocks], ad_remainder);
- buf[ad_len % 16] ^= 0x80;
+ xor_buf(&buf[0], &ad[BS*ad_blocks], ad_remainder);
+ buf[ad_len % BS] ^= 0x80;
cipher.encrypt(buf);
@@ -123,11 +137,11 @@ secure_vector<byte> ocb_hash(const L_computer& L,
}
OCB_Mode::OCB_Mode(BlockCipher* cipher, size_t tag_size, bool decrypting) :
- Buffered_Filter(16, decrypting ? tag_size : 0),
+ Buffered_Filter(cipher->parallel_bytes(), decrypting ? tag_size : 0),
m_cipher(cipher), m_tag_size(tag_size),
- m_ad_hash(16), m_offset(16), m_checksum(16)
+ m_ad_hash(BS), m_offset(BS), m_checksum(BS)
{
- if(m_cipher->block_size() != 16)
+ if(m_cipher->block_size() != BS)
throw std::invalid_argument("OCB requires a 128 bit cipher so cannot be used with " +
m_cipher->name());
@@ -165,9 +179,9 @@ void OCB_Mode::set_nonce(const byte nonce[], size_t nonce_len)
if(1) // need to recompute stretch (save iv to compare)
{
- secure_vector<byte> buf(16);
+ secure_vector<byte> buf(BS);
- const size_t offset = 16 - nonce_len;
+ const size_t offset = BS - nonce_len;
copy_mem(&buf[offset], nonce, nonce_len);
buf[offset-1] = 1;
@@ -188,7 +202,7 @@ void OCB_Mode::set_nonce(const byte nonce[], size_t nonce_len)
const size_t shift_bytes = bottom / 8;
const size_t shift_bits = bottom % 8;
- for(size_t i = 0; i != 16; ++i)
+ for(size_t i = 0; i != BS; ++i)
{
m_offset[i] = (stretch[i+shift_bytes] << shift_bits);
m_offset[i] |= (stretch[i+shift_bytes+1] >> (8-shift_bits));
@@ -217,24 +231,24 @@ void OCB_Mode::end_msg()
void OCB_Encryption::buffered_block(const byte input[], size_t input_length)
{
- BOTAN_ASSERT(input_length % 16 == 0, "Input length is an even number of blocks");
+ BOTAN_ASSERT(input_length % BS == 0, "Input length is an even number of blocks");
- const size_t blocks = input_length / 16;
+ const size_t blocks = input_length / BS;
const L_computer& L = *m_L;
- secure_vector<byte> ctext_buf(16);
+ secure_vector<byte> ctext_buf(BS);
for(size_t i = 0; i != blocks; ++i)
{
// could run in parallel
- xor_buf(&m_checksum[0], &input[16*i], 16);
+ xor_buf(&m_checksum[0], &input[BS*i], BS);
m_offset ^= L(ctz(++m_block_index));
ctext_buf = m_offset;
- xor_buf(&ctext_buf[0], &input[16*i], 16);
+ xor_buf(&ctext_buf[0], &input[BS*i], BS);
m_cipher->encrypt(ctext_buf);
ctext_buf ^= m_offset;
@@ -244,22 +258,25 @@ void OCB_Encryption::buffered_block(const byte input[], size_t input_length)
void OCB_Encryption::buffered_final(const byte input[], size_t input_length)
{
- /*
- todo - might have multiple blocks here if buffering up multiple
- blocks for bitslice mode, run those first by calling buffered_write
- directly
- */
+ if(input_length >= BS)
+ {
+ const size_t final_blocks = input_length / BS;
+ const size_t final_bytes = final_blocks * BS;
+ buffered_block(input, final_bytes);
+ input += final_bytes;
+ input_length -= final_bytes;
+ }
if(input_length)
{
- BOTAN_ASSERT(input_length < 16, "Only a partial block left");
+ BOTAN_ASSERT(input_length < BS, "Only a partial block left");
xor_buf(&m_checksum[0], &input[0], input_length);
m_checksum[input_length] ^= 0x80;
m_offset ^= m_L->star(); // Offset_*
- secure_vector<byte> buf(16);
+ secure_vector<byte> buf(BS);
m_cipher->encrypt(m_offset, buf);
xor_buf(&buf[0], &input[0], input_length);
@@ -284,13 +301,13 @@ void OCB_Encryption::buffered_final(const byte input[], size_t input_length)
void OCB_Decryption::buffered_block(const byte input[], size_t input_length)
{
- BOTAN_ASSERT(input_length % 16 == 0, "Input length is an even number of blocks");
+ BOTAN_ASSERT(input_length % BS == 0, "Input length is an even number of blocks");
- const size_t blocks = input_length / 16;
+ const size_t blocks = input_length / BS;
const L_computer& L = *m_L;
- secure_vector<byte> ptext_buf(16);
+ secure_vector<byte> ptext_buf(BS);
for(size_t i = 0; i != blocks; ++i)
{
@@ -299,7 +316,7 @@ void OCB_Decryption::buffered_block(const byte input[], size_t input_length)
m_offset ^= L(ctz(++m_block_index));
ptext_buf = m_offset;
- xor_buf(&ptext_buf[0], &input[16*i], 16);
+ xor_buf(&ptext_buf[0], &input[BS*i], BS);
m_cipher->decrypt(ptext_buf);
ptext_buf ^= m_offset;
@@ -310,24 +327,27 @@ void OCB_Decryption::buffered_block(const byte input[], size_t input_length)
void OCB_Decryption::buffered_final(const byte input[], size_t input_length)
{
- /*
- todo - might have multiple blocks here if buffering up multiple
- blocks for bitslice mode, run those first by calling buffered_write
- directly
- */
-
BOTAN_ASSERT(input_length >= m_tag_size, "We have the tag");
const byte* included_tag = &input[input_length-m_tag_size];
input_length -= m_tag_size;
+ if(input_length >= BS)
+ {
+ const size_t final_blocks = input_length / BS;
+ const size_t final_bytes = final_blocks * BS;
+ buffered_block(input, final_bytes);
+ input += final_bytes;
+ input_length -= final_bytes;
+ }
+
if(input_length)
{
- BOTAN_ASSERT(input_length < 16, "Only a partial block left");
+ BOTAN_ASSERT(input_length < BS, "Only a partial block left");
m_offset ^= m_L->star(); // Offset_*
- secure_vector<byte> buf(16);
+ secure_vector<byte> buf(BS);
m_cipher->encrypt(m_offset, buf); // P_*
xor_buf(&buf[0], &input[0], input_length);
diff --git a/src/filters/modes/ocb/ocb.h b/src/filters/modes/ocb/ocb.h
index 8179f84a3..0c26fb7d6 100644
--- a/src/filters/modes/ocb/ocb.h
+++ b/src/filters/modes/ocb/ocb.h
@@ -16,6 +16,7 @@
namespace Botan {
class L_computer;
+//class Nonce_State;
/**
* OCB Mode (base class for OCB_Encryption and OCB_Decryption). Note
@@ -25,7 +26,6 @@ class L_computer;
http://tools.ietf.org/html/draft-irtf-cfrg-ocb-00
* @see Free Licenses http://www.cs.ucdavis.edu/~rogaway/ocb/license.htm
* @see OCB home page http://www.cs.ucdavis.edu/~rogaway/ocb
-
*/
class BOTAN_DLL OCB_Mode : public AEAD_Mode,
private Buffered_Filter
@@ -55,9 +55,12 @@ class BOTAN_DLL OCB_Mode : public AEAD_Mode,
}
protected:
+ static const size_t BS = 16;
+
// fixme make these private
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;