summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/hash/mdx_hash/mdx_hash.cpp
diff options
context:
space:
mode:
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.cpp121
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);
+ }
+
+}