diff options
-rw-r--r-- | src/filters/modes/ocb/ocb.cpp | 44 |
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) |