diff options
Diffstat (limited to 'comm/third_party/botan/src/lib/hash/mdx_hash/mdx_hash.cpp')
-rw-r--r-- | comm/third_party/botan/src/lib/hash/mdx_hash/mdx_hash.cpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/hash/mdx_hash/mdx_hash.cpp b/comm/third_party/botan/src/lib/hash/mdx_hash/mdx_hash.cpp new file mode 100644 index 0000000000..64ae516a82 --- /dev/null +++ b/comm/third_party/botan/src/lib/hash/mdx_hash/mdx_hash.cpp @@ -0,0 +1,121 @@ +/* +* Merkle-Damgard Hash Function +* (C) 1999-2008,2018 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/mdx_hash.h> +#include <botan/exceptn.h> +#include <botan/loadstor.h> +#include <botan/internal/bit_ops.h> + +namespace Botan { + +/* +* MDx_HashFunction Constructor +*/ +MDx_HashFunction::MDx_HashFunction(size_t block_len, + bool byte_big_endian, + bool bit_big_endian, + uint8_t cnt_size) : + m_pad_char(bit_big_endian == true ? 0x80 : 0x01), + m_counter_size(cnt_size), + m_block_bits(ceil_log2(block_len)), + m_count_big_endian(byte_big_endian), + m_count(0), + m_buffer(block_len), + m_position(0) + { + if(!is_power_of_2(block_len)) + throw Invalid_Argument("MDx_HashFunction block length must be a power of 2"); + if(m_block_bits < 3 || m_block_bits > 16) + throw Invalid_Argument("MDx_HashFunction block size too large or too small"); + if(m_counter_size < 8 || m_counter_size > block_len) + throw Invalid_State("MDx_HashFunction invalid counter length"); + } + +/* +* Clear memory of sensitive data +*/ +void MDx_HashFunction::clear() + { + zeroise(m_buffer); + m_count = m_position = 0; + } + +/* +* Update the hash +*/ +void MDx_HashFunction::add_data(const uint8_t input[], size_t length) + { + const size_t block_len = static_cast<size_t>(1) << m_block_bits; + + m_count += length; + + if(m_position) + { + buffer_insert(m_buffer, m_position, input, length); + + if(m_position + length >= block_len) + { + compress_n(m_buffer.data(), 1); + input += (block_len - m_position); + length -= (block_len - m_position); + m_position = 0; + } + } + + // Just in case the compiler can't figure out block_len is a power of 2 + const size_t full_blocks = length >> m_block_bits; + const size_t remaining = length & (block_len - 1); + + if(full_blocks > 0) + { + compress_n(input, full_blocks); + } + + buffer_insert(m_buffer, m_position, input + full_blocks * block_len, remaining); + m_position += remaining; + } + +/* +* Finalize a hash +*/ +void MDx_HashFunction::final_result(uint8_t output[]) + { + const size_t block_len = static_cast<size_t>(1) << m_block_bits; + + clear_mem(&m_buffer[m_position], block_len - m_position); + m_buffer[m_position] = m_pad_char; + + if(m_position >= block_len - m_counter_size) + { + compress_n(m_buffer.data(), 1); + zeroise(m_buffer); + } + + write_count(&m_buffer[block_len - m_counter_size]); + + compress_n(m_buffer.data(), 1); + copy_out(output); + clear(); + } + +/* +* Write the count bits to the buffer +*/ +void MDx_HashFunction::write_count(uint8_t out[]) + { + BOTAN_ASSERT_NOMSG(m_counter_size <= output_length()); + BOTAN_ASSERT_NOMSG(m_counter_size >= 8); + + const uint64_t bit_count = m_count * 8; + + if(m_count_big_endian) + store_be(bit_count, out + m_counter_size - 8); + else + store_le(bit_count, out + m_counter_size - 8); + } + +} |