aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2013-03-28 17:30:22 +0000
committerlloyd <[email protected]>2013-03-28 17:30:22 +0000
commit3bd9e5c14a7e244a5c154db3c821e69cad3df08c (patch)
treed28c925861046a647e4d589c3573b59cd1eb6805
parent55f11acaa300e5d96de593e69cb7e28d612a1959 (diff)
Add an offset to ignore at the start of the buffer in AEAD processing
which makes more complicated packet building easier to do in-place. For instance now update can take a buffer that contains a header and be told to ignore the header.
-rw-r--r--src/aead/aead.h16
-rw-r--r--src/aead/eax/eax.cpp45
-rw-r--r--src/aead/eax/eax.h8
-rw-r--r--src/aead/gcm/gcm.cpp45
-rw-r--r--src/aead/gcm/gcm.h8
-rw-r--r--src/aead/ocb/ocb.cpp54
-rw-r--r--src/aead/ocb/ocb.h8
7 files changed, 117 insertions, 67 deletions
diff --git a/src/aead/aead.h b/src/aead/aead.h
index 736de85e1..e0e07e8ab 100644
--- a/src/aead/aead.h
+++ b/src/aead/aead.h
@@ -34,6 +34,11 @@ class AEAD_Mode : public SymmetricAlgorithm
virtual size_t minimum_final_size() const = 0;
/**
+ * @return Random nonce appropriate for passing to start
+ */
+ //virtual secure_vector<byte> nonce(RandomNumberGenerator& rng) const = 0;
+
+ /**
* Set associated data that is not included in the ciphertext but
* that should be authenticated. Must be called after set_key
* and before end_msg.
@@ -47,6 +52,12 @@ class AEAD_Mode : public SymmetricAlgorithm
*/
virtual void set_associated_data(const byte ad[], size_t ad_len) = 0;
+ template<typename Alloc>
+ void set_associated_data_vec(const std::vector<byte, Alloc>& ad)
+ {
+ set_associated_data(&ad[0], ad.size());
+ }
+
virtual bool valid_nonce_length(size_t) const = 0;
/**
@@ -68,7 +79,7 @@ class AEAD_Mode : public SymmetricAlgorithm
* update_granularity() byte blocks.
* @param blocks in/out paramter which will possibly be resized
*/
- virtual void update(secure_vector<byte>& blocks) = 0;
+ virtual void update(secure_vector<byte>& blocks, size_t offset = 0) = 0;
/**
* Complete processing of a message. For decryption, may throw an exception
@@ -76,8 +87,9 @@ class AEAD_Mode : public SymmetricAlgorithm
*
* @param final_block in/out parameter which must be at least
* minimum_final_size() bytes, and will be set to any final output
+ * @param offset an offset into final_block to begin processing
*/
- virtual void finish(secure_vector<byte>& final_block) = 0;
+ virtual void finish(secure_vector<byte>& final_block, size_t offset = 0) = 0;
virtual ~AEAD_Mode() {}
};
diff --git a/src/aead/eax/eax.cpp b/src/aead/eax/eax.cpp
index 725a473f4..c6aaa9e85 100644
--- a/src/aead/eax/eax.cpp
+++ b/src/aead/eax/eax.cpp
@@ -108,15 +108,19 @@ secure_vector<byte> EAX_Mode::start(const byte nonce[], size_t nonce_len)
return secure_vector<byte>();
}
-void EAX_Encryption::update(secure_vector<byte>& buffer)
+void EAX_Encryption::update(secure_vector<byte>& buffer, size_t offset)
{
- m_ctr->cipher(&buffer[0], &buffer[0], buffer.size());
- m_cmac->update(&buffer[0], buffer.size());
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
+
+ m_ctr->cipher(buf, buf, sz);
+ m_cmac->update(buf, sz);
}
-void EAX_Encryption::finish(secure_vector<byte>& buffer)
+void EAX_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
{
- update(buffer);
+ update(buffer, offset);
secure_vector<byte> data_mac = m_cmac->final();
xor_buf(data_mac, m_nonce_mac, data_mac.size());
@@ -125,26 +129,33 @@ void EAX_Encryption::finish(secure_vector<byte>& buffer)
buffer += std::make_pair(&data_mac[0], tag_size());
}
-void EAX_Decryption::update(secure_vector<byte>& buffer)
+void EAX_Decryption::update(secure_vector<byte>& buffer, size_t offset)
{
- m_cmac->update(&buffer[0], buffer.size());
- m_ctr->cipher(&buffer[0], &buffer[0], buffer.size());
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
+
+ m_cmac->update(buf, sz);
+ m_ctr->cipher(buf, buf, sz);
}
-void EAX_Decryption::finish(secure_vector<byte>& buffer)
+void EAX_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
{
- BOTAN_ASSERT(buffer.size() >= tag_size(),
- "Have the tag as part of final input");
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
+
+ BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input");
- const size_t remaining = buffer.size() - tag_size();
+ const size_t remaining = sz - tag_size();
- if(remaining) // handle any remaining input
+ if(remaining)
{
- m_cmac->update(&buffer[0], remaining);
- m_ctr->cipher(&buffer[0], &buffer[0], remaining);
+ m_cmac->update(buf, remaining);
+ m_ctr->cipher(buf, buf, remaining);
}
- const byte* included_tag = &buffer[remaining];
+ const byte* included_tag = &buf[remaining];
secure_vector<byte> mac = m_cmac->final();
mac ^= m_nonce_mac;
@@ -153,7 +164,7 @@ 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);
+ buffer.resize(offset + remaining);
}
}
diff --git a/src/aead/eax/eax.h b/src/aead/eax/eax.h
index f3562f755..6720bdca4 100644
--- a/src/aead/eax/eax.h
+++ b/src/aead/eax/eax.h
@@ -75,9 +75,9 @@ class BOTAN_DLL EAX_Encryption : public EAX_Mode
size_t minimum_final_size() const override { return 0; }
- void update(secure_vector<byte>& blocks) override;
+ void update(secure_vector<byte>& blocks, size_t offset) override;
- void finish(secure_vector<byte>& final_block) override;
+ void finish(secure_vector<byte>& final_block, size_t offset) override;
};
/**
@@ -95,9 +95,9 @@ class BOTAN_DLL EAX_Decryption : public EAX_Mode
size_t minimum_final_size() const override { return tag_size(); }
- void update(secure_vector<byte>& blocks) override;
+ void update(secure_vector<byte>& blocks, size_t offset) override;
- void finish(secure_vector<byte>& final_block) override;
+ void finish(secure_vector<byte>& final_block, size_t offset) override;
};
}
diff --git a/src/aead/gcm/gcm.cpp b/src/aead/gcm/gcm.cpp
index a5ccee927..665fc4472 100644
--- a/src/aead/gcm/gcm.cpp
+++ b/src/aead/gcm/gcm.cpp
@@ -182,16 +182,20 @@ secure_vector<byte> GCM_Mode::start(const byte nonce[], size_t nonce_len)
return secure_vector<byte>();
}
-void GCM_Encryption::update(secure_vector<byte>& buffer)
+void GCM_Encryption::update(secure_vector<byte>& buffer, size_t offset)
{
- m_ctr->cipher(&buffer[0], &buffer[0], buffer.size());
- ghash_update(m_H, m_mac, &buffer[0], buffer.size());
- m_text_len += buffer.size();
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
+
+ m_ctr->cipher(buf, buf, sz);
+ ghash_update(m_H, m_mac, buf, sz);
+ m_text_len += sz;
}
-void GCM_Encryption::finish(secure_vector<byte>& buffer)
+void GCM_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
{
- update(buffer);
+ update(buffer, offset);
ghash_finalize(m_H, m_mac, m_ad_len, m_text_len);
@@ -200,25 +204,32 @@ void GCM_Encryption::finish(secure_vector<byte>& buffer)
buffer += std::make_pair(&m_mac[0], tag_size());
}
-void GCM_Decryption::update(secure_vector<byte>& buffer)
+void GCM_Decryption::update(secure_vector<byte>& buffer, size_t offset)
{
- ghash_update(m_H, m_mac, &buffer[0], buffer.size());
- m_ctr->cipher(&buffer[0], &buffer[0], buffer.size());
- m_text_len += buffer.size();
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
+
+ ghash_update(m_H, m_mac, buf, sz);
+ m_ctr->cipher(buf, buf, sz);
+ m_text_len += sz;
}
-void GCM_Decryption::finish(secure_vector<byte>& buffer)
+void GCM_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
{
- BOTAN_ASSERT(buffer.size() >= tag_size(),
- "Have the tag as part of final input");
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
+
+ BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input");
- const size_t remaining = buffer.size() - tag_size();
+ const size_t remaining = sz - tag_size();
// handle any final input before the tag
if(remaining)
{
- ghash_update(m_H, m_mac, &buffer[0], remaining);
- m_ctr->cipher(&buffer[0], &buffer[0], remaining);
+ ghash_update(m_H, m_mac, buf, remaining);
+ m_ctr->cipher(buf, buf, remaining);
m_text_len += remaining;
}
@@ -231,7 +242,7 @@ void GCM_Decryption::finish(secure_vector<byte>& buffer)
if(!same_mem(&m_mac[0], included_tag, tag_size()))
throw Integrity_Failure("GCM tag check failed");
- buffer.resize(remaining);
+ buffer.resize(offset + remaining);
}
}
diff --git a/src/aead/gcm/gcm.h b/src/aead/gcm/gcm.h
index cf7d94ced..bc7eaae20 100644
--- a/src/aead/gcm/gcm.h
+++ b/src/aead/gcm/gcm.h
@@ -70,9 +70,9 @@ class BOTAN_DLL GCM_Encryption : public GCM_Mode
size_t minimum_final_size() const override { return 0; }
- void update(secure_vector<byte>& blocks) override;
+ void update(secure_vector<byte>& blocks, size_t offset) override;
- void finish(secure_vector<byte>& final_block) override;
+ void finish(secure_vector<byte>& final_block, size_t offset) override;
};
/**
@@ -90,9 +90,9 @@ class BOTAN_DLL GCM_Decryption : public GCM_Mode
size_t minimum_final_size() const override { return tag_size(); }
- void update(secure_vector<byte>& blocks) override;
+ void update(secure_vector<byte>& blocks, size_t offset) override;
- void finish(secure_vector<byte>& final_block) override;
+ void finish(secure_vector<byte>& final_block, size_t offset) override;
};
}
diff --git a/src/aead/ocb/ocb.cpp b/src/aead/ocb/ocb.cpp
index ec5835d79..4cbd8bde8 100644
--- a/src/aead/ocb/ocb.cpp
+++ b/src/aead/ocb/ocb.cpp
@@ -272,26 +272,34 @@ void OCB_Encryption::encrypt(byte buffer[], size_t blocks)
m_checksum[i % BS] ^= csum_accum[i];
}
-void OCB_Encryption::update(secure_vector<byte>& buffer)
+void OCB_Encryption::update(secure_vector<byte>& buffer, size_t offset)
{
- BOTAN_ASSERT(buffer.size() % BS == 0, "Input length is an even number of blocks");
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
- encrypt(&buffer[0], buffer.size() / 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)
+void OCB_Encryption::finish(secure_vector<byte>& buffer, size_t offset)
{
- if(!buffer.empty())
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
+
+ if(sz)
{
- const size_t final_full_blocks = buffer.size() / BS;
- const size_t remainder_bytes = buffer.size() - (final_full_blocks * BS);
+ const size_t final_full_blocks = sz / BS;
+ const size_t remainder_bytes = sz - (final_full_blocks * BS);
- encrypt(&buffer[0], final_full_blocks);
+ encrypt(buf, final_full_blocks);
if(remainder_bytes)
{
BOTAN_ASSERT(remainder_bytes < BS, "Only a partial block left");
- byte* remainder = &buffer[buffer.size() - remainder_bytes];
+ byte* remainder = &buf[sz - remainder_bytes];
xor_buf(&m_checksum[0], &remainder[0], remainder_bytes);
m_checksum[remainder_bytes] ^= 0x80;
@@ -363,31 +371,39 @@ void OCB_Decryption::decrypt(byte buffer[], size_t blocks)
m_checksum[i % BS] ^= csum_accum[i];
}
-void OCB_Decryption::update(secure_vector<byte>& buffer)
+void OCB_Decryption::update(secure_vector<byte>& buffer, size_t offset)
{
- BOTAN_ASSERT(buffer.size() % BS == 0, "Input length is an even number of blocks");
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
- decrypt(&buffer[0], buffer.size() / BS);
+ BOTAN_ASSERT(sz % BS == 0, "Input length is an even number of blocks");
+
+ decrypt(buf, sz / BS);
}
-void OCB_Decryption::finish(secure_vector<byte>& buffer)
+void OCB_Decryption::finish(secure_vector<byte>& buffer, size_t offset)
{
- BOTAN_ASSERT(buffer.size() >= tag_size(), "We have the tag");
+ BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
+ const size_t sz = buffer.size() - offset;
+ byte* buf = &buffer[offset];
+
+ BOTAN_ASSERT(sz >= tag_size(), "We have the tag");
- const size_t remaining = buffer.size() - tag_size();
+ const size_t remaining = sz - tag_size();
if(remaining)
{
const size_t final_full_blocks = remaining / BS;
const size_t final_bytes = remaining - (final_full_blocks * BS);
- decrypt(&buffer[0], final_full_blocks);
+ decrypt(&buf[0], final_full_blocks);
if(final_bytes)
{
BOTAN_ASSERT(final_bytes < BS, "Only a partial block left");
- byte* remainder = &buffer[remaining - final_bytes];
+ byte* remainder = &buf[remaining - final_bytes];
m_offset ^= m_L->star(); // Offset_*
@@ -416,13 +432,13 @@ void OCB_Decryption::finish(secure_vector<byte>& buffer)
m_block_index = 0;
// compare mac
- const byte* included_tag = &buffer[remaining];
+ const byte* included_tag = &buf[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);
+ buffer.resize(remaining + offset);
}
}
diff --git a/src/aead/ocb/ocb.h b/src/aead/ocb/ocb.h
index 9d10c2656..d50710a79 100644
--- a/src/aead/ocb/ocb.h
+++ b/src/aead/ocb/ocb.h
@@ -84,9 +84,9 @@ class BOTAN_DLL OCB_Encryption : public OCB_Mode
size_t minimum_final_size() const override { return 0; }
- void update(secure_vector<byte>& blocks) override;
+ void update(secure_vector<byte>& blocks, size_t offset) override;
- void finish(secure_vector<byte>& final_block) override;
+ void finish(secure_vector<byte>& final_block, size_t offset) override;
private:
void encrypt(byte input[], size_t blocks);
};
@@ -103,9 +103,9 @@ class BOTAN_DLL OCB_Decryption : public OCB_Mode
size_t minimum_final_size() const override { return tag_size(); }
- void update(secure_vector<byte>& blocks) override;
+ void update(secure_vector<byte>& blocks, size_t offset) override;
- void finish(secure_vector<byte>& final_block) override;
+ void finish(secure_vector<byte>& final_block, size_t offset) override;
private:
void decrypt(byte input[], size_t blocks);
};