aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/modes/aead/siv/siv.cpp
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-09-24 17:19:09 -0400
committerJack Lloyd <[email protected]>2017-09-24 17:56:10 -0400
commit0272dce7955951de74189568c43123b386445531 (patch)
treec89bdf47f1f1d7dda29ac3d53a72dfa8ce418231 /src/lib/modes/aead/siv/siv.cpp
parentf53db790a5a2a7ffb770199bcf42fcdcf948e737 (diff)
Better tests for SIV
Correct errors in the AEAD tests that assumed process/update always return something - that isn't true for SIV Minor optimizations in CMAC and CTR to cache the block size instead of making a zillion virtual calls for it. Generalize SIV slightly to where it could support a non-128 bit cipher, but don't pull the trigger on it since I can't find any implementations to crosscheck with.
Diffstat (limited to 'src/lib/modes/aead/siv/siv.cpp')
-rw-r--r--src/lib/modes/aead/siv/siv.cpp50
1 files changed, 29 insertions, 21 deletions
diff --git a/src/lib/modes/aead/siv/siv.cpp b/src/lib/modes/aead/siv/siv.cpp
index 1ddfd4d88..8b2cc4ef0 100644
--- a/src/lib/modes/aead/siv/siv.cpp
+++ b/src/lib/modes/aead/siv/siv.cpp
@@ -1,6 +1,6 @@
/*
* SIV Mode Encryption
-* (C) 2013 Jack Lloyd
+* (C) 2013,2017 Jack Lloyd
* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
*
* Botan is released under the Simplified BSD License (see license.txt)
@@ -17,7 +17,8 @@ namespace Botan {
SIV_Mode::SIV_Mode(BlockCipher* cipher) :
m_name(cipher->name() + "/SIV"),
m_ctr(new CTR_BE(cipher->clone())),
- m_cmac(new CMAC(cipher))
+ m_mac(new CMAC(cipher)),
+ m_bs(cipher->block_size())
{
if(cipher->block_size() != 16)
throw Invalid_Argument("SIV requires a 128 bit block cipher");
@@ -31,7 +32,7 @@ SIV_Mode::~SIV_Mode()
void SIV_Mode::clear()
{
m_ctr->clear();
- m_cmac->clear();
+ m_mac->clear();
reset();
}
@@ -65,23 +66,27 @@ size_t SIV_Mode::update_granularity() const
Key_Length_Specification SIV_Mode::key_spec() const
{
- return m_cmac->key_spec().multiple(2);
+ return m_mac->key_spec().multiple(2);
}
void SIV_Mode::key_schedule(const uint8_t key[], size_t length)
{
const size_t keylen = length / 2;
- m_cmac->set_key(key, keylen);
+ m_mac->set_key(key, keylen);
m_ctr->set_key(key + keylen, keylen);
m_ad_macs.clear();
}
void SIV_Mode::set_associated_data_n(size_t n, const uint8_t ad[], size_t length)
{
+ const size_t max_ads = block_size() * 8 - 2;
+ if(n > max_ads)
+ throw Invalid_Argument(name() + " allows no more than " + std::to_string(max_ads) + " ADs");
+
if(n >= m_ad_macs.size())
m_ad_macs.resize(n+1);
- m_ad_macs[n] = m_cmac->process(ad, length);
+ m_ad_macs[n] = m_mac->process(ad, length);
}
void SIV_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
@@ -90,7 +95,7 @@ void SIV_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
throw Invalid_IV_Length(name(), nonce_len);
if(nonce_len)
- m_nonce = m_cmac->process(nonce, nonce_len);
+ m_nonce = m_mac->process(nonce, nonce_len);
else
m_nonce.clear();
@@ -106,9 +111,9 @@ size_t SIV_Mode::process(uint8_t buf[], size_t sz)
secure_vector<uint8_t> SIV_Mode::S2V(const uint8_t* text, size_t text_len)
{
- const uint8_t zero[16] = { 0 };
+ const std::vector<uint8_t> zeros(block_size());
- secure_vector<uint8_t> V = m_cmac->process(zero, 16);
+ secure_vector<uint8_t> V = m_mac->process(zeros.data(), zeros.size());
for(size_t i = 0; i != m_ad_macs.size(); ++i)
{
@@ -122,25 +127,25 @@ secure_vector<uint8_t> SIV_Mode::S2V(const uint8_t* text, size_t text_len)
V ^= m_nonce;
}
- if(text_len < 16)
+ if(text_len < block_size())
{
poly_double_n(V.data(), V.size());
xor_buf(V.data(), text, text_len);
V[text_len] ^= 0x80;
- return m_cmac->process(V);
+ return m_mac->process(V);
}
- m_cmac->update(text, text_len - 16);
- xor_buf(V.data(), &text[text_len - 16], 16);
- m_cmac->update(V);
+ m_mac->update(text, text_len - block_size());
+ xor_buf(V.data(), &text[text_len - block_size()], block_size());
+ m_mac->update(V);
- return m_cmac->final();
+ return m_mac->final();
}
void SIV_Mode::set_ctr_iv(secure_vector<uint8_t> V)
{
- V[8] &= 0x7F;
- V[12] &= 0x7F;
+ V[m_bs-8] &= 0x7F;
+ V[m_bs-4] &= 0x7F;
ctr().set_iv(V.data(), V.size());
}
@@ -150,8 +155,9 @@ void SIV_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
+ msg_buf().clear();
- secure_vector<uint8_t> V = S2V(buffer.data() + offset, buffer.size() - offset);
+ const secure_vector<uint8_t> V = S2V(buffer.data() + offset, buffer.size() - offset);
buffer.insert(buffer.begin() + offset, V.begin(), V.end());
@@ -164,12 +170,14 @@ void SIV_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
+ msg_buf().clear();
const size_t sz = buffer.size() - offset;
BOTAN_ASSERT(sz >= tag_size(), "We have the tag");
- secure_vector<uint8_t> V(buffer.data() + offset, buffer.data() + offset + 16);
+ secure_vector<uint8_t> V(buffer.data() + offset,
+ buffer.data() + offset + block_size());
set_ctr_iv(V);
@@ -177,9 +185,9 @@ void SIV_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
buffer.data() + offset,
buffer.size() - offset - V.size());
- secure_vector<uint8_t> T = S2V(buffer.data() + offset, buffer.size() - offset - V.size());
+ const secure_vector<uint8_t> T = S2V(buffer.data() + offset, buffer.size() - offset - V.size());
- if(T != V)
+ if(!constant_time_compare(T.data(), V.data(), T.size()))
throw Integrity_Failure("SIV tag check failed");
buffer.resize(buffer.size() - tag_size());