aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/filters/modes/ocb/ocb.cpp44
1 files changed, 34 insertions, 10 deletions
diff --git a/src/filters/modes/ocb/ocb.cpp b/src/filters/modes/ocb/ocb.cpp
index 24f777b73..5750e3da2 100644
--- a/src/filters/modes/ocb/ocb.cpp
+++ b/src/filters/modes/ocb/ocb.cpp
@@ -307,24 +307,48 @@ void OCB_Decryption::buffered_block(const byte input[], size_t input_length)
const size_t blocks = input_length / BS;
- const L_computer& L = *m_L;
+ const size_t par_bytes = m_cipher->parallel_bytes();
+
+ BOTAN_ASSERT(par_bytes % BS == 0, "Cipher is parallel in full blocks");
+
+ const size_t par_blocks = par_bytes / BS;
+
+ const L_computer& L = *m_L; // convenient name
- secure_vector<byte> ptext_buf(BS);
+ secure_vector<byte> ptext_buf(par_bytes);
+ secure_vector<byte> csum_accum(par_bytes);
+ secure_vector<byte> offsets(par_bytes);
+
+ size_t blocks_left = blocks;
- for(size_t i = 0; i != blocks; ++i)
+ while(blocks_left)
{
- // could run in parallel
+ const size_t to_proc = std::min(blocks_left, par_blocks);
+ const size_t proc_bytes = to_proc * BS;
- m_offset ^= L(ctz(++m_block_index));
+ for(size_t i = 0; i != to_proc; ++i)
+ {
+ m_offset ^= L(ctz(++m_block_index));
+ copy_mem(&offsets[BS*i], &m_offset[0], BS);
+ }
+
+ copy_mem(&ptext_buf[0], &input[0], proc_bytes);
- ptext_buf = m_offset;
- xor_buf(&ptext_buf[0], &input[BS*i], BS);
+ ptext_buf ^= offsets;
m_cipher->decrypt(ptext_buf);
- ptext_buf ^= m_offset;
+ ptext_buf ^= offsets;
+
+ xor_buf(&csum_accum[0], &ptext_buf[0], proc_bytes);
- send(ptext_buf);
- m_checksum ^= ptext_buf;
+ send(ptext_buf, proc_bytes);
+
+ input += proc_bytes;
+ blocks_left -= to_proc;
}
+
+ // fold into checksum
+ for(size_t i = 0; i != csum_accum.size(); ++i)
+ m_checksum[i % BS] ^= csum_accum[i];
}
void OCB_Decryption::buffered_final(const byte input[], size_t input_length)