aboutsummaryrefslogtreecommitdiffstats
path: root/src/aead
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-03-27 16:10:55 +0000
committerlloyd <[email protected]>2013-03-27 16:10:55 +0000
commite7d24d7884025c2051450a9c9d9ce0f944a8fa4a (patch)
tree1fb4af6e8541c7ee8cef757799fcb73eb56ed339 /src/aead
parent35ac296082030fffde867cbac768815efe271522 (diff)
Add an AEAD_Filter that wraps an AEAD_Mode, plus various bug fixes.
Diffstat (limited to 'src/aead')
-rw-r--r--src/aead/aead.h6
-rw-r--r--src/aead/eax/eax.cpp14
-rw-r--r--src/aead/gcm/gcm.cpp18
-rw-r--r--src/aead/ocb/ocb.cpp35
4 files changed, 46 insertions, 27 deletions
diff --git a/src/aead/aead.h b/src/aead/aead.h
index af6f0e76a..736de85e1 100644
--- a/src/aead/aead.h
+++ b/src/aead/aead.h
@@ -57,6 +57,12 @@ class AEAD_Mode : public SymmetricAlgorithm
*/
virtual secure_vector<byte> start(const byte nonce[], size_t nonce_len) = 0;
+ template<typename Alloc>
+ secure_vector<byte> start_vec(const std::vector<byte, Alloc>& nonce)
+ {
+ return start(&nonce[0], nonce.size());
+ }
+
/**
* Update (encrypt or decrypt) some data. Input must be in size
* update_granularity() byte blocks.
diff --git a/src/aead/eax/eax.cpp b/src/aead/eax/eax.cpp
index 8a7287062..fa0496f42 100644
--- a/src/aead/eax/eax.cpp
+++ b/src/aead/eax/eax.cpp
@@ -119,7 +119,7 @@ void EAX_Encryption::finish(secure_vector<byte>& buffer)
xor_buf(data_mac, m_nonce_mac, data_mac.size());
xor_buf(data_mac, m_ad_mac, data_mac.size());
- buffer += data_mac;
+ buffer += std::make_pair(&data_mac[0], tag_size());
}
void EAX_Decryption::update(secure_vector<byte>& buffer)
@@ -133,15 +133,15 @@ void EAX_Decryption::finish(secure_vector<byte>& buffer)
BOTAN_ASSERT(buffer.size() >= tag_size(),
"Have the tag as part of final input");
- const size_t input_length = buffer.size() - tag_size();
+ const size_t remaining = buffer.size() - tag_size();
- if(input_length) // handle any remaining input
+ if(remaining) // handle any remaining input
{
- m_cmac->update(&buffer[0], buffer.size());
- m_ctr->cipher(&buffer[0], &buffer[0], buffer.size());
+ m_cmac->update(&buffer[0], remaining);
+ m_ctr->cipher(&buffer[0], &buffer[0], remaining);
}
- const byte* included_tag = &buffer[input_length];
+ const byte* included_tag = &buffer[remaining];
secure_vector<byte> mac = m_cmac->final();
mac ^= m_nonce_mac;
@@ -149,6 +149,8 @@ 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);
}
}
diff --git a/src/aead/gcm/gcm.cpp b/src/aead/gcm/gcm.cpp
index 628dcc270..a067d162e 100644
--- a/src/aead/gcm/gcm.cpp
+++ b/src/aead/gcm/gcm.cpp
@@ -27,6 +27,8 @@ gcm_multiply(const secure_vector<byte>& x,
u64bit Z[2] = { 0, 0 };
+ // Both CLMUL and SSE2 versions would be useful
+
for(size_t i = 0; i != 2; ++i)
{
u64bit X = load_be<u64bit>(&x[0], i);
@@ -192,7 +194,7 @@ void GCM_Encryption::finish(secure_vector<byte>& buffer)
m_mac ^= m_enc_y0;
- buffer += m_mac;
+ buffer += std::make_pair(&m_mac[0], tag_size());
}
void GCM_Decryption::update(secure_vector<byte>& buffer)
@@ -207,22 +209,26 @@ void GCM_Decryption::finish(secure_vector<byte>& buffer)
BOTAN_ASSERT(buffer.size() >= tag_size(),
"Have the tag as part of final input");
+ const size_t remaining = buffer.size() - tag_size();
+
// handle any final input before the tag
- if(size_t input_length = buffer.size() - tag_size())
+ if(remaining)
{
- ghash_update(m_H, m_mac, &buffer[0], input_length);
- m_ctr->cipher(&buffer[0], &buffer[0], input_length);
- m_text_len += input_length;
+ ghash_update(m_H, m_mac, &buffer[0], remaining);
+ m_ctr->cipher(&buffer[0], &buffer[0], remaining);
+ m_text_len += remaining;
}
ghash_finalize(m_H, m_mac, m_ad_len, m_text_len);
m_mac ^= m_enc_y0;
- const byte* included_tag = &buffer[buffer.size() - tag_size()];
+ const byte* included_tag = &buffer[remaining];
if(!same_mem(&m_mac[0], included_tag, tag_size()))
throw Integrity_Failure("GCM tag check failed");
+
+ buffer.resize(remaining);
}
}
diff --git a/src/aead/ocb/ocb.cpp b/src/aead/ocb/ocb.cpp
index 5bd42766f..50b33960f 100644
--- a/src/aead/ocb/ocb.cpp
+++ b/src/aead/ocb/ocb.cpp
@@ -11,9 +11,6 @@
#include <botan/internal/bit_ops.h>
#include <algorithm>
-#include <botan/hex.h>
-#include <iostream>
-
namespace Botan {
// Has to be in Botan namespace so unique_ptr can reference it
@@ -377,33 +374,34 @@ void OCB_Decryption::finish(secure_vector<byte>& buffer)
{
BOTAN_ASSERT(buffer.size() >= tag_size(), "We have the tag");
- if(const size_t remaining_ctext = buffer.size() - tag_size())
+ const size_t remaining = buffer.size() - tag_size();
+
+ if(remaining)
{
- const size_t final_full_blocks = remaining_ctext / BS;
- const size_t remainder_bytes = remaining_ctext - (final_full_blocks * BS);
+ const size_t final_full_blocks = remaining / BS;
+ const size_t final_bytes = remaining - (final_full_blocks * BS);
decrypt(&buffer[0], final_full_blocks);
- if(remainder_bytes)
+ if(final_bytes)
{
- BOTAN_ASSERT(remainder_bytes < BS, "Only a partial block left");
+ BOTAN_ASSERT(final_bytes < BS, "Only a partial block left");
- byte* remainder = &buffer[buffer.size() - remainder_bytes];
+ byte* remainder = &buffer[remaining - final_bytes];
m_offset ^= m_L->star(); // Offset_*
secure_vector<byte> pad(BS);
m_cipher->encrypt(m_offset, pad); // P_*
- xor_buf(&remainder[0], &pad[0], remainder_bytes);
+ xor_buf(&remainder[0], &pad[0], final_bytes);
- xor_buf(&m_checksum[0], &remainder[0], remainder_bytes);
- m_checksum[remainder_bytes] ^= 0x80;
+ xor_buf(&m_checksum[0], &remainder[0], final_bytes);
+ m_checksum[final_bytes] ^= 0x80;
}
}
- const byte* included_tag = &buffer[buffer.size() - tag_size()];
-
+ // compute the mac
secure_vector<byte> mac = m_offset;
mac ^= m_checksum;
mac ^= m_L->dollar();
@@ -412,12 +410,19 @@ void OCB_Decryption::finish(secure_vector<byte>& buffer)
mac ^= m_ad_hash;
+ // reset state
zeroise(m_checksum);
zeroise(m_offset);
m_block_index = 0;
- if(!same_mem(&mac[0], included_tag, m_tag_size))
+ // compare mac
+ const byte* included_tag = &buffer[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);
}
}