summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/mac
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--comm/third_party/botan/src/lib/mac/cbc_mac/cbc_mac.cpp99
-rw-r--r--comm/third_party/botan/src/lib/mac/cbc_mac/cbc_mac.h50
-rw-r--r--comm/third_party/botan/src/lib/mac/cbc_mac/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/mac/cmac/cmac.cpp139
-rw-r--r--comm/third_party/botan/src/lib/mac/cmac/cmac.h67
-rw-r--r--comm/third_party/botan/src/lib/mac/cmac/info.txt8
-rw-r--r--comm/third_party/botan/src/lib/mac/gmac/gmac.cpp134
-rw-r--r--comm/third_party/botan/src/lib/mac/gmac/gmac.h64
-rw-r--r--comm/third_party/botan/src/lib/mac/gmac/info.txt8
-rw-r--r--comm/third_party/botan/src/lib/mac/hmac/hmac.cpp150
-rw-r--r--comm/third_party/botan/src/lib/mac/hmac/hmac.h52
-rw-r--r--comm/third_party/botan/src/lib/mac/hmac/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/mac/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/mac/mac.cpp171
-rw-r--r--comm/third_party/botan/src/lib/mac/mac.h143
-rw-r--r--comm/third_party/botan/src/lib/mac/poly1305/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/mac/poly1305/poly1305.cpp211
-rw-r--r--comm/third_party/botan/src/lib/mac/poly1305/poly1305.h50
-rw-r--r--comm/third_party/botan/src/lib/mac/siphash/info.txt3
-rw-r--r--comm/third_party/botan/src/lib/mac/siphash/siphash.cpp136
-rw-r--r--comm/third_party/botan/src/lib/mac/siphash/siphash.h47
-rw-r--r--comm/third_party/botan/src/lib/mac/x919_mac/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/mac/x919_mac/x919_mac.cpp99
-rw-r--r--comm/third_party/botan/src/lib/mac/x919_mac/x919_mac.h51
24 files changed, 1717 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/mac/cbc_mac/cbc_mac.cpp b/comm/third_party/botan/src/lib/mac/cbc_mac/cbc_mac.cpp
new file mode 100644
index 0000000000..ba403b564a
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/cbc_mac/cbc_mac.cpp
@@ -0,0 +1,99 @@
+/*
+* CBC-MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/cbc_mac.h>
+
+namespace Botan {
+
+/*
+* Update an CBC-MAC Calculation
+*/
+void CBC_MAC::add_data(const uint8_t input[], size_t length)
+ {
+ verify_key_set(m_state.empty() == false);
+
+ size_t xored = std::min(output_length() - m_position, length);
+ xor_buf(&m_state[m_position], input, xored);
+ m_position += xored;
+
+ if(m_position < output_length())
+ return;
+
+ m_cipher->encrypt(m_state);
+ input += xored;
+ length -= xored;
+ while(length >= output_length())
+ {
+ xor_buf(m_state, input, output_length());
+ m_cipher->encrypt(m_state);
+ input += output_length();
+ length -= output_length();
+ }
+
+ xor_buf(m_state, input, length);
+ m_position = length;
+ }
+
+/*
+* Finalize an CBC-MAC Calculation
+*/
+void CBC_MAC::final_result(uint8_t mac[])
+ {
+ verify_key_set(m_state.empty() == false);
+
+ if(m_position)
+ m_cipher->encrypt(m_state);
+
+ copy_mem(mac, m_state.data(), m_state.size());
+ zeroise(m_state);
+ m_position = 0;
+ }
+
+/*
+* CBC-MAC Key Schedule
+*/
+void CBC_MAC::key_schedule(const uint8_t key[], size_t length)
+ {
+ m_state.resize(m_cipher->block_size());
+ m_cipher->set_key(key, length);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void CBC_MAC::clear()
+ {
+ m_cipher->clear();
+ zap(m_state);
+ m_position = 0;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string CBC_MAC::name() const
+ {
+ return "CBC-MAC(" + m_cipher->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* CBC_MAC::clone() const
+ {
+ return new CBC_MAC(m_cipher->clone());
+ }
+
+/*
+* CBC-MAC Constructor
+*/
+CBC_MAC::CBC_MAC(BlockCipher* cipher) :
+ m_cipher(cipher)
+ {
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/mac/cbc_mac/cbc_mac.h b/comm/third_party/botan/src/lib/mac/cbc_mac/cbc_mac.h
new file mode 100644
index 0000000000..ed4eb2bd18
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/cbc_mac/cbc_mac.h
@@ -0,0 +1,50 @@
+/*
+* CBC-MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_CBC_MAC_H_
+#define BOTAN_CBC_MAC_H_
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(cbc_mac.h)
+
+namespace Botan {
+
+/**
+* CBC-MAC
+*/
+class BOTAN_PUBLIC_API(2,0) CBC_MAC final : public MessageAuthenticationCode
+ {
+ public:
+ std::string name() const override;
+ MessageAuthenticationCode* clone() const override;
+ size_t output_length() const override { return m_cipher->block_size(); }
+ void clear() override;
+
+ Key_Length_Specification key_spec() const override
+ {
+ return m_cipher->key_spec();
+ }
+
+ /**
+ * @param cipher the block cipher to use
+ */
+ explicit CBC_MAC(BlockCipher* cipher);
+ private:
+ void add_data(const uint8_t[], size_t) override;
+ void final_result(uint8_t[]) override;
+ void key_schedule(const uint8_t[], size_t) override;
+
+ std::unique_ptr<BlockCipher> m_cipher;
+ secure_vector<uint8_t> m_state;
+ size_t m_position = 0;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/mac/cbc_mac/info.txt b/comm/third_party/botan/src/lib/mac/cbc_mac/info.txt
new file mode 100644
index 0000000000..994a63872b
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/cbc_mac/info.txt
@@ -0,0 +1,7 @@
+<defines>
+CBC_MAC -> 20131128
+</defines>
+
+<requires>
+block
+</requires>
diff --git a/comm/third_party/botan/src/lib/mac/cmac/cmac.cpp b/comm/third_party/botan/src/lib/mac/cmac/cmac.cpp
new file mode 100644
index 0000000000..38752471dd
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/cmac/cmac.cpp
@@ -0,0 +1,139 @@
+/*
+* CMAC
+* (C) 1999-2007,2014 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/cmac.h>
+#include <botan/exceptn.h>
+#include <botan/internal/poly_dbl.h>
+
+namespace Botan {
+
+/*
+* Perform CMAC's multiplication in GF(2^n)
+*/
+secure_vector<uint8_t> CMAC::poly_double(const secure_vector<uint8_t>& in)
+ {
+ secure_vector<uint8_t> out(in.size());
+ poly_double_n(out.data(), in.data(), out.size());
+ return out;
+ }
+
+/*
+* Update an CMAC Calculation
+*/
+void CMAC::add_data(const uint8_t input[], size_t length)
+ {
+ const size_t bs = output_length();
+
+ buffer_insert(m_buffer, m_position, input, length);
+ if(m_position + length > bs)
+ {
+ xor_buf(m_state, m_buffer, bs);
+ m_cipher->encrypt(m_state);
+ input += (bs - m_position);
+ length -= (bs - m_position);
+ while(length > bs)
+ {
+ xor_buf(m_state, input, bs);
+ m_cipher->encrypt(m_state);
+ input += bs;
+ length -= bs;
+ }
+ copy_mem(m_buffer.data(), input, length);
+ m_position = 0;
+ }
+ m_position += length;
+ }
+
+/*
+* Finalize an CMAC Calculation
+*/
+void CMAC::final_result(uint8_t mac[])
+ {
+ xor_buf(m_state, m_buffer, m_position);
+
+ if(m_position == output_length())
+ {
+ xor_buf(m_state, m_B, output_length());
+ }
+ else
+ {
+ m_state[m_position] ^= 0x80;
+ xor_buf(m_state, m_P, output_length());
+ }
+
+ m_cipher->encrypt(m_state);
+
+ copy_mem(mac, m_state.data(), output_length());
+
+ zeroise(m_state);
+ zeroise(m_buffer);
+ m_position = 0;
+ }
+
+/*
+* CMAC Key Schedule
+*/
+void CMAC::key_schedule(const uint8_t key[], size_t length)
+ {
+ clear();
+ m_cipher->set_key(key, length);
+ m_cipher->encrypt(m_B);
+ poly_double_n(m_B.data(), m_B.size());
+ poly_double_n(m_P.data(), m_B.data(), m_P.size());
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void CMAC::clear()
+ {
+ m_cipher->clear();
+ zeroise(m_state);
+ zeroise(m_buffer);
+ zeroise(m_B);
+ zeroise(m_P);
+ m_position = 0;
+ }
+
+/*
+* Return the name of this type
+*/
+std::string CMAC::name() const
+ {
+ return "CMAC(" + m_cipher->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* CMAC::clone() const
+ {
+ return new CMAC(m_cipher->clone());
+ }
+
+/*
+* CMAC Constructor
+*/
+CMAC::CMAC(BlockCipher* cipher) :
+ m_cipher(cipher),
+ m_block_size(m_cipher->block_size())
+ {
+ if(poly_double_supported_size(m_block_size) == false)
+ {
+ throw Invalid_Argument("CMAC cannot use the " +
+ std::to_string(m_block_size * 8) +
+ " bit cipher " + m_cipher->name());
+ }
+
+ m_state.resize(output_length());
+ m_buffer.resize(output_length());
+ m_B.resize(output_length());
+ m_P.resize(output_length());
+ m_position = 0;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/mac/cmac/cmac.h b/comm/third_party/botan/src/lib/mac/cmac/cmac.h
new file mode 100644
index 0000000000..f73167590d
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/cmac/cmac.h
@@ -0,0 +1,67 @@
+/*
+* CMAC
+* (C) 1999-2007,2014 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_CMAC_H_
+#define BOTAN_CMAC_H_
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(cmac.h)
+
+namespace Botan {
+
+/**
+* CMAC, also known as OMAC1
+*/
+class BOTAN_PUBLIC_API(2,0) CMAC final : public MessageAuthenticationCode
+ {
+ public:
+ std::string name() const override;
+ size_t output_length() const override { return m_block_size; }
+ MessageAuthenticationCode* clone() const override;
+
+ void clear() override;
+
+ Key_Length_Specification key_spec() const override
+ {
+ return m_cipher->key_spec();
+ }
+
+ /**
+ * CMAC's polynomial doubling operation
+ *
+ * This function was only exposed for use elsewhere in the library, but it is not
+ * longer used. This function will be removed in a future release.
+ *
+ * @param in the input
+ */
+ static secure_vector<uint8_t>
+ BOTAN_DEPRECATED("This was only for internal use and is no longer used")
+ poly_double(const secure_vector<uint8_t>& in);
+
+ /**
+ * @param cipher the block cipher to use
+ */
+ explicit CMAC(BlockCipher* cipher);
+
+ CMAC(const CMAC&) = delete;
+ CMAC& operator=(const CMAC&) = delete;
+ private:
+ void add_data(const uint8_t[], size_t) override;
+ void final_result(uint8_t[]) override;
+ void key_schedule(const uint8_t[], size_t) override;
+
+ std::unique_ptr<BlockCipher> m_cipher;
+ secure_vector<uint8_t> m_buffer, m_state, m_B, m_P;
+ const size_t m_block_size;
+ size_t m_position;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/mac/cmac/info.txt b/comm/third_party/botan/src/lib/mac/cmac/info.txt
new file mode 100644
index 0000000000..d78b3851ee
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/cmac/info.txt
@@ -0,0 +1,8 @@
+<defines>
+CMAC -> 20131128
+</defines>
+
+<requires>
+block
+poly_dbl
+</requires>
diff --git a/comm/third_party/botan/src/lib/mac/gmac/gmac.cpp b/comm/third_party/botan/src/lib/mac/gmac/gmac.cpp
new file mode 100644
index 0000000000..6b162857f3
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/gmac/gmac.cpp
@@ -0,0 +1,134 @@
+/*
+ * GMAC
+ * (C) 2016 Matthias Gierlings, René Korthaus
+ * (C) 2017 Jack Lloyd
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ */
+
+#include <botan/gmac.h>
+#include <botan/ghash.h>
+#include <botan/exceptn.h>
+#include <botan/block_cipher.h>
+
+namespace Botan {
+
+GMAC::GMAC(BlockCipher* cipher) :
+ m_cipher(cipher),
+ m_ghash(new GHASH),
+ m_aad_buf(GCM_BS),
+ m_aad_buf_pos(0),
+ m_initialized(false)
+ {
+ }
+
+void GMAC::clear()
+ {
+ m_cipher->clear();
+ m_ghash->clear();
+ zeroise(m_aad_buf);
+ m_aad_buf_pos = 0;
+ m_initialized = false;
+ }
+
+GMAC::~GMAC() { /* for unique_ptr */ }
+
+Key_Length_Specification GMAC::key_spec() const
+ {
+ return m_cipher->key_spec();
+ }
+
+std::string GMAC::name() const
+ {
+ return "GMAC(" + m_cipher->name() + ")";
+ }
+
+size_t GMAC::output_length() const
+ {
+ return GCM_BS;
+ }
+
+void GMAC::add_data(const uint8_t input[], size_t size)
+ {
+ if(m_aad_buf_pos > 0)
+ {
+ const size_t taking = std::min(GCM_BS - m_aad_buf_pos, size);
+ copy_mem(&m_aad_buf[m_aad_buf_pos], input, taking);
+ m_aad_buf_pos += taking;
+ input += taking;
+ size -= taking;
+
+ if(m_aad_buf_pos == GCM_BS)
+ {
+ m_ghash->update_associated_data(m_aad_buf.data(), GCM_BS);
+ m_aad_buf_pos = 0;
+ }
+ }
+
+ const size_t left_over = size % GCM_BS;
+ const size_t full_blocks = size - left_over;
+ m_ghash->update_associated_data(input, full_blocks);
+ input += full_blocks;
+
+ if(left_over > 0)
+ {
+ copy_mem(&m_aad_buf[m_aad_buf_pos], input, left_over);
+ m_aad_buf_pos += left_over;
+ }
+ }
+
+void GMAC::key_schedule(const uint8_t key[], size_t size)
+ {
+ clear();
+ m_cipher->set_key(key, size);
+
+ secure_vector<uint8_t> H(GCM_BS);
+ m_cipher->encrypt(H);
+ m_ghash->set_key(H);
+ }
+
+void GMAC::start_msg(const uint8_t nonce[], size_t nonce_len)
+ {
+ secure_vector<uint8_t> y0(GCM_BS);
+
+ if(nonce_len == 12)
+ {
+ copy_mem(y0.data(), nonce, nonce_len);
+ y0[GCM_BS - 1] = 1;
+ }
+ else
+ {
+ m_ghash->ghash_update(y0, nonce, nonce_len);
+ m_ghash->add_final_block(y0, 0, nonce_len);
+ }
+
+ secure_vector<uint8_t> m_enc_y0(GCM_BS);
+ m_cipher->encrypt(y0.data(), m_enc_y0.data());
+ m_ghash->start(m_enc_y0.data(), m_enc_y0.size());
+ m_initialized = true;
+ }
+
+void GMAC::final_result(uint8_t mac[])
+ {
+ // This ensures the GMAC computation has been initialized with a fresh
+ // nonce. The aim of this check is to prevent developers from re-using
+ // nonces (and potential nonce-reuse attacks).
+ if(m_initialized == false)
+ throw Invalid_State("GMAC was not used with a fresh nonce");
+
+ // process the rest of the aad buffer. Even if it is a partial block only
+ // ghash_update will process it properly.
+ if(m_aad_buf_pos > 0)
+ {
+ m_ghash->update_associated_data(m_aad_buf.data(), m_aad_buf_pos);
+ }
+
+ m_ghash->final(mac, output_length());
+ clear();
+ }
+
+MessageAuthenticationCode* GMAC::clone() const
+ {
+ return new GMAC(m_cipher->clone());
+ }
+}
diff --git a/comm/third_party/botan/src/lib/mac/gmac/gmac.h b/comm/third_party/botan/src/lib/mac/gmac/gmac.h
new file mode 100644
index 0000000000..b78aeec6f1
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/gmac/gmac.h
@@ -0,0 +1,64 @@
+/*
+ * GMAC
+ * (C) 2016 Matthias Gierlings, René Korthaus
+ * (C) 2017 Jack Lloyd
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ */
+
+#ifndef BOTAN_GMAC_H_
+#define BOTAN_GMAC_H_
+
+#include <botan/mac.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(gmac.h)
+
+namespace Botan {
+
+class BlockCipher;
+class GHASH;
+
+/**
+* GMAC
+*
+* GMAC requires a unique initialization vector be used for each message.
+* This must be provided via the MessageAuthenticationCode::start() API
+*/
+class BOTAN_PUBLIC_API(2,0) GMAC final : public MessageAuthenticationCode
+ {
+ public:
+ void clear() override;
+ std::string name() const override;
+ size_t output_length() const override;
+ MessageAuthenticationCode* clone() const override;
+
+ Key_Length_Specification key_spec() const override;
+
+ /**
+ * Creates a new GMAC instance.
+ *
+ * @param cipher the underlying block cipher to use
+ */
+ explicit GMAC(BlockCipher* cipher);
+
+ GMAC(const GMAC&) = delete;
+ GMAC& operator=(const GMAC&) = delete;
+
+ ~GMAC();
+
+ private:
+ void add_data(const uint8_t[], size_t) override;
+ void final_result(uint8_t[]) override;
+ void start_msg(const uint8_t nonce[], size_t nonce_len) override;
+ void key_schedule(const uint8_t key[], size_t size) override;
+
+ static const size_t GCM_BS = 16;
+ std::unique_ptr<BlockCipher> m_cipher;
+ std::unique_ptr<GHASH> m_ghash;
+ secure_vector<uint8_t> m_aad_buf;
+ size_t m_aad_buf_pos;
+ bool m_initialized;
+ };
+
+}
+#endif
diff --git a/comm/third_party/botan/src/lib/mac/gmac/info.txt b/comm/third_party/botan/src/lib/mac/gmac/info.txt
new file mode 100644
index 0000000000..cc473feb90
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/gmac/info.txt
@@ -0,0 +1,8 @@
+<defines>
+GMAC -> 20160207
+</defines>
+
+<requires>
+ghash
+block
+</requires>
diff --git a/comm/third_party/botan/src/lib/mac/hmac/hmac.cpp b/comm/third_party/botan/src/lib/mac/hmac/hmac.cpp
new file mode 100644
index 0000000000..eada1e1bcf
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/hmac/hmac.cpp
@@ -0,0 +1,150 @@
+/*
+* HMAC
+* (C) 1999-2007,2014,2020 Jack Lloyd
+* 2007 Yves Jerschow
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/hmac.h>
+#include <botan/internal/ct_utils.h>
+
+namespace Botan {
+
+/*
+* Update a HMAC Calculation
+*/
+void HMAC::add_data(const uint8_t input[], size_t length)
+ {
+ verify_key_set(m_ikey.empty() == false);
+ m_hash->update(input, length);
+ }
+
+/*
+* Finalize a HMAC Calculation
+*/
+void HMAC::final_result(uint8_t mac[])
+ {
+ verify_key_set(m_okey.empty() == false);
+ m_hash->final(mac);
+ m_hash->update(m_okey);
+ m_hash->update(mac, m_hash_output_length);
+ m_hash->final(mac);
+ m_hash->update(m_ikey);
+ }
+
+Key_Length_Specification HMAC::key_spec() const
+ {
+ // Support very long lengths for things like PBKDF2 and the TLS PRF
+ return Key_Length_Specification(0, 4096);
+ }
+
+size_t HMAC::output_length() const
+ {
+ return m_hash_output_length;
+ }
+
+/*
+* HMAC Key Schedule
+*/
+void HMAC::key_schedule(const uint8_t key[], size_t length)
+ {
+ const uint8_t ipad = 0x36;
+ const uint8_t opad = 0x5C;
+
+ m_hash->clear();
+
+ m_ikey.resize(m_hash_block_size);
+ m_okey.resize(m_hash_block_size);
+
+ clear_mem(m_ikey.data(), m_ikey.size());
+ clear_mem(m_okey.data(), m_okey.size());
+
+ /*
+ * Sometimes the HMAC key length itself is sensitive, as with PBKDF2 where it
+ * reveals the length of the passphrase. Make some attempt to hide this to
+ * side channels. Clearly if the secret is longer than the block size then the
+ * branch to hash first reveals that. In addition, counting the number of
+ * compression functions executed reveals the size at the granularity of the
+ * hash function's block size.
+ *
+ * The greater concern is for smaller keys; being able to detect when a
+ * passphrase is say 4 bytes may assist choosing weaker targets. Even though
+ * the loop bounds are constant, we can only actually read key[0..length] so
+ * it doesn't seem possible to make this computation truly constant time.
+ *
+ * We don't mind leaking if the length is exactly zero since that's
+ * trivial to simply check.
+ */
+
+ if(length > m_hash_block_size)
+ {
+ m_hash->update(key, length);
+ m_hash->final(m_ikey.data());
+ }
+ else if(length > 0)
+ {
+ for(size_t i = 0, i_mod_length = 0; i != m_hash_block_size; ++i)
+ {
+ /*
+ access key[i % length] but avoiding division due to variable
+ time computation on some processors.
+ */
+ auto needs_reduction = CT::Mask<size_t>::is_lte(length, i_mod_length);
+ i_mod_length = needs_reduction.select(0, i_mod_length);
+ const uint8_t kb = key[i_mod_length];
+
+ auto in_range = CT::Mask<size_t>::is_lt(i, length);
+ m_ikey[i] = static_cast<uint8_t>(in_range.if_set_return(kb));
+ i_mod_length += 1;
+ }
+ }
+
+ for(size_t i = 0; i != m_hash_block_size; ++i)
+ {
+ m_ikey[i] ^= ipad;
+ m_okey[i] = m_ikey[i] ^ ipad ^ opad;
+ }
+
+ m_hash->update(m_ikey);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void HMAC::clear()
+ {
+ m_hash->clear();
+ zap(m_ikey);
+ zap(m_okey);
+ }
+
+/*
+* Return the name of this type
+*/
+std::string HMAC::name() const
+ {
+ return "HMAC(" + m_hash->name() + ")";
+ }
+
+/*
+* Return a clone of this object
+*/
+MessageAuthenticationCode* HMAC::clone() const
+ {
+ return new HMAC(m_hash->clone());
+ }
+
+/*
+* HMAC Constructor
+*/
+HMAC::HMAC(HashFunction* hash) :
+ m_hash(hash),
+ m_hash_output_length(m_hash->output_length()),
+ m_hash_block_size(m_hash->hash_block_size())
+ {
+ BOTAN_ARG_CHECK(m_hash_block_size >= m_hash_output_length,
+ "HMAC is not compatible with this hash function");
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/mac/hmac/hmac.h b/comm/third_party/botan/src/lib/mac/hmac/hmac.h
new file mode 100644
index 0000000000..1f2f4227d4
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/hmac/hmac.h
@@ -0,0 +1,52 @@
+/*
+* HMAC
+* (C) 1999-2007,2014 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_HMAC_H_
+#define BOTAN_HMAC_H_
+
+#include <botan/mac.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(hmac.h)
+
+namespace Botan {
+
+/**
+* HMAC
+*/
+class BOTAN_PUBLIC_API(2,0) HMAC final : public MessageAuthenticationCode
+ {
+ public:
+ void clear() override;
+ std::string name() const override;
+ MessageAuthenticationCode* clone() const override;
+
+ size_t output_length() const override;
+
+ Key_Length_Specification key_spec() const override;
+
+ /**
+ * @param hash the hash to use for HMACing
+ */
+ explicit HMAC(HashFunction* hash);
+
+ HMAC(const HMAC&) = delete;
+ HMAC& operator=(const HMAC&) = delete;
+ private:
+ void add_data(const uint8_t[], size_t) override;
+ void final_result(uint8_t[]) override;
+ void key_schedule(const uint8_t[], size_t) override;
+
+ std::unique_ptr<HashFunction> m_hash;
+ secure_vector<uint8_t> m_ikey, m_okey;
+ size_t m_hash_output_length;
+ size_t m_hash_block_size;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/mac/hmac/info.txt b/comm/third_party/botan/src/lib/mac/hmac/info.txt
new file mode 100644
index 0000000000..50dc665dc9
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/hmac/info.txt
@@ -0,0 +1,7 @@
+<defines>
+HMAC -> 20131128
+</defines>
+
+<requires>
+hash
+</requires>
diff --git a/comm/third_party/botan/src/lib/mac/info.txt b/comm/third_party/botan/src/lib/mac/info.txt
new file mode 100644
index 0000000000..7aef92b879
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/info.txt
@@ -0,0 +1,7 @@
+<defines>
+MAC -> 20150626
+</defines>
+
+<header:public>
+mac.h
+</header:public>
diff --git a/comm/third_party/botan/src/lib/mac/mac.cpp b/comm/third_party/botan/src/lib/mac/mac.cpp
new file mode 100644
index 0000000000..4c3fc5230e
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/mac.cpp
@@ -0,0 +1,171 @@
+/*
+* Message Authentication Code base class
+* (C) 1999-2008 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/mac.h>
+#include <botan/exceptn.h>
+#include <botan/scan_name.h>
+#include <botan/mem_ops.h>
+
+#if defined(BOTAN_HAS_CBC_MAC)
+ #include <botan/cbc_mac.h>
+#endif
+
+#if defined(BOTAN_HAS_CMAC)
+ #include <botan/cmac.h>
+#endif
+
+#if defined(BOTAN_HAS_GMAC)
+ #include <botan/gmac.h>
+ #include <botan/block_cipher.h>
+#endif
+
+#if defined(BOTAN_HAS_HMAC)
+ #include <botan/hmac.h>
+ #include <botan/hash.h>
+#endif
+
+#if defined(BOTAN_HAS_POLY1305)
+ #include <botan/poly1305.h>
+#endif
+
+#if defined(BOTAN_HAS_SIPHASH)
+ #include <botan/siphash.h>
+#endif
+
+#if defined(BOTAN_HAS_ANSI_X919_MAC)
+ #include <botan/x919_mac.h>
+#endif
+
+namespace Botan {
+
+std::unique_ptr<MessageAuthenticationCode>
+MessageAuthenticationCode::create(const std::string& algo_spec,
+ const std::string& provider)
+ {
+ const SCAN_Name req(algo_spec);
+
+#if defined(BOTAN_HAS_GMAC)
+ if(req.algo_name() == "GMAC" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ if(auto bc = BlockCipher::create(req.arg(0)))
+ return std::unique_ptr<MessageAuthenticationCode>(new GMAC(bc.release()));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_HMAC)
+ if(req.algo_name() == "HMAC" && req.arg_count() == 1)
+ {
+ // TODO OpenSSL
+ if(provider.empty() || provider == "base")
+ {
+ if(auto h = HashFunction::create(req.arg(0)))
+ return std::unique_ptr<MessageAuthenticationCode>(new HMAC(h.release()));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_POLY1305)
+ if(req.algo_name() == "Poly1305" && req.arg_count() == 0)
+ {
+ if(provider.empty() || provider == "base")
+ return std::unique_ptr<MessageAuthenticationCode>(new Poly1305);
+ }
+#endif
+
+#if defined(BOTAN_HAS_SIPHASH)
+ if(req.algo_name() == "SipHash")
+ {
+ if(provider.empty() || provider == "base")
+ {
+ return std::unique_ptr<MessageAuthenticationCode>(
+ new SipHash(req.arg_as_integer(0, 2), req.arg_as_integer(1, 4)));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_CMAC)
+ if((req.algo_name() == "CMAC" || req.algo_name() == "OMAC") && req.arg_count() == 1)
+ {
+ // TODO: OpenSSL CMAC
+ if(provider.empty() || provider == "base")
+ {
+ if(auto bc = BlockCipher::create(req.arg(0)))
+ return std::unique_ptr<MessageAuthenticationCode>(new CMAC(bc.release()));
+ }
+ }
+#endif
+
+
+#if defined(BOTAN_HAS_CBC_MAC)
+ if(req.algo_name() == "CBC-MAC" && req.arg_count() == 1)
+ {
+ if(provider.empty() || provider == "base")
+ {
+ if(auto bc = BlockCipher::create(req.arg(0)))
+ return std::unique_ptr<MessageAuthenticationCode>(new CBC_MAC(bc.release()));
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_ANSI_X919_MAC)
+ if(req.algo_name() == "X9.19-MAC")
+ {
+ if(provider.empty() || provider == "base")
+ {
+ return std::unique_ptr<MessageAuthenticationCode>(new ANSI_X919_MAC);
+ }
+ }
+#endif
+
+ BOTAN_UNUSED(req);
+ BOTAN_UNUSED(provider);
+
+ return nullptr;
+ }
+
+std::vector<std::string>
+MessageAuthenticationCode::providers(const std::string& algo_spec)
+ {
+ return probe_providers_of<MessageAuthenticationCode>(algo_spec, {"base", "openssl"});
+ }
+
+//static
+std::unique_ptr<MessageAuthenticationCode>
+MessageAuthenticationCode::create_or_throw(const std::string& algo,
+ const std::string& provider)
+ {
+ if(auto mac = MessageAuthenticationCode::create(algo, provider))
+ {
+ return mac;
+ }
+ throw Lookup_Error("MAC", algo, provider);
+ }
+
+void MessageAuthenticationCode::start_msg(const uint8_t nonce[], size_t nonce_len)
+ {
+ BOTAN_UNUSED(nonce);
+ if(nonce_len > 0)
+ throw Invalid_IV_Length(name(), nonce_len);
+ }
+
+/*
+* Default (deterministic) MAC verification operation
+*/
+bool MessageAuthenticationCode::verify_mac(const uint8_t mac[], size_t length)
+ {
+ secure_vector<uint8_t> our_mac = final();
+
+ if(our_mac.size() != length)
+ return false;
+
+ return constant_time_compare(our_mac.data(), mac, length);
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/mac/mac.h b/comm/third_party/botan/src/lib/mac/mac.h
new file mode 100644
index 0000000000..de30b7dbb2
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/mac.h
@@ -0,0 +1,143 @@
+/*
+* Base class for message authentiction codes
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_MESSAGE_AUTH_CODE_BASE_H_
+#define BOTAN_MESSAGE_AUTH_CODE_BASE_H_
+
+#include <botan/buf_comp.h>
+#include <botan/sym_algo.h>
+#include <string>
+#include <memory>
+
+namespace Botan {
+
+/**
+* This class represents Message Authentication Code (MAC) objects.
+*/
+class BOTAN_PUBLIC_API(2,0) MessageAuthenticationCode : public Buffered_Computation,
+ public SymmetricAlgorithm
+ {
+ public:
+ /**
+ * Create an instance based on a name
+ * If provider is empty then best available is chosen.
+ * @param algo_spec algorithm name
+ * @param provider provider implementation to use
+ * @return a null pointer if the algo/provider combination cannot be found
+ */
+ static std::unique_ptr<MessageAuthenticationCode>
+ create(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ /*
+ * Create an instance based on a name
+ * If provider is empty then best available is chosen.
+ * @param algo_spec algorithm name
+ * @param provider provider implementation to use
+ * Throws a Lookup_Error if algo/provider combination cannot be found
+ */
+ static std::unique_ptr<MessageAuthenticationCode>
+ create_or_throw(const std::string& algo_spec,
+ const std::string& provider = "");
+
+ /**
+ * @return list of available providers for this algorithm, empty if not available
+ */
+ static std::vector<std::string> providers(const std::string& algo_spec);
+
+ virtual ~MessageAuthenticationCode() = default;
+
+ /**
+ * Prepare for processing a message under the specified nonce
+ *
+ * Most MACs neither require nor support a nonce; for these algorithms
+ * calling `start_msg` is optional and calling it with anything other than
+ * an empty string is an error. One MAC which *requires* a per-message
+ * nonce be specified is GMAC.
+ *
+ * @param nonce the message nonce bytes
+ * @param nonce_len the size of len in bytes
+ * Default implementation simply rejects all non-empty nonces
+ * since most hash/MAC algorithms do not support randomization
+ */
+ virtual void start_msg(const uint8_t nonce[], size_t nonce_len);
+
+ /**
+ * Begin processing a message with a nonce
+ *
+ * @param nonce the per message nonce
+ */
+ template<typename Alloc>
+ void start(const std::vector<uint8_t, Alloc>& nonce)
+ {
+ start_msg(nonce.data(), nonce.size());
+ }
+
+ /**
+ * Begin processing a message.
+ * @param nonce the per message nonce
+ * @param nonce_len length of nonce
+ */
+ void start(const uint8_t nonce[], size_t nonce_len)
+ {
+ start_msg(nonce, nonce_len);
+ }
+
+ /**
+ * Begin processing a message.
+ */
+ void start()
+ {
+ return start_msg(nullptr, 0);
+ }
+
+ /**
+ * Verify a MAC.
+ * @param in the MAC to verify as a byte array
+ * @param length the length of param in
+ * @return true if the MAC is valid, false otherwise
+ */
+ virtual bool verify_mac(const uint8_t in[], size_t length);
+
+ /**
+ * Verify a MAC.
+ * @param in the MAC to verify as a byte array
+ * @return true if the MAC is valid, false otherwise
+ */
+ virtual bool verify_mac(const std::vector<uint8_t>& in)
+ {
+ return verify_mac(in.data(), in.size());
+ }
+
+ /**
+ * Verify a MAC.
+ * @param in the MAC to verify as a byte array
+ * @return true if the MAC is valid, false otherwise
+ */
+ virtual bool verify_mac(const secure_vector<uint8_t>& in)
+ {
+ return verify_mac(in.data(), in.size());
+ }
+
+ /**
+ * Get a new object representing the same algorithm as *this
+ */
+ virtual MessageAuthenticationCode* clone() const = 0;
+
+ /**
+ * @return provider information about this implementation. Default is "base",
+ * might also return "sse2", "avx2", "openssl", or some other arbitrary string.
+ */
+ virtual std::string provider() const { return "base"; }
+
+ };
+
+typedef MessageAuthenticationCode MAC;
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/mac/poly1305/info.txt b/comm/third_party/botan/src/lib/mac/poly1305/info.txt
new file mode 100644
index 0000000000..868f97241d
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/poly1305/info.txt
@@ -0,0 +1,7 @@
+<defines>
+POLY1305 -> 20141227
+</defines>
+
+<header:public>
+poly1305.h
+</header:public>
diff --git a/comm/third_party/botan/src/lib/mac/poly1305/poly1305.cpp b/comm/third_party/botan/src/lib/mac/poly1305/poly1305.cpp
new file mode 100644
index 0000000000..333a21a1a6
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/poly1305/poly1305.cpp
@@ -0,0 +1,211 @@
+/*
+* Derived from poly1305-donna-64.h by Andrew Moon <liquidsun@gmail.com>
+* in https://github.com/floodyberry/poly1305-donna
+*
+* (C) 2014 Andrew Moon
+* (C) 2014 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/poly1305.h>
+#include <botan/loadstor.h>
+#include <botan/mul128.h>
+#include <botan/internal/donna128.h>
+#include <botan/internal/ct_utils.h>
+
+namespace Botan {
+
+namespace {
+
+void poly1305_init(secure_vector<uint64_t>& X, const uint8_t key[32])
+ {
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+ const uint64_t t0 = load_le<uint64_t>(key, 0);
+ const uint64_t t1 = load_le<uint64_t>(key, 1);
+
+ X[0] = ( t0 ) & 0xffc0fffffff;
+ X[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
+ X[2] = ((t1 >> 24) ) & 0x00ffffffc0f;
+
+ /* h = 0 */
+ X[3] = 0;
+ X[4] = 0;
+ X[5] = 0;
+
+ /* save pad for later */
+ X[6] = load_le<uint64_t>(key, 2);
+ X[7] = load_le<uint64_t>(key, 3);
+ }
+
+void poly1305_blocks(secure_vector<uint64_t>& X, const uint8_t *m, size_t blocks, bool is_final = false)
+ {
+#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
+ typedef donna128 uint128_t;
+#endif
+
+ const uint64_t hibit = is_final ? 0 : (static_cast<uint64_t>(1) << 40); /* 1 << 128 */
+
+ const uint64_t r0 = X[0];
+ const uint64_t r1 = X[1];
+ const uint64_t r2 = X[2];
+
+ const uint64_t M44 = 0xFFFFFFFFFFF;
+ const uint64_t M42 = 0x3FFFFFFFFFF;
+
+ uint64_t h0 = X[3+0];
+ uint64_t h1 = X[3+1];
+ uint64_t h2 = X[3+2];
+
+ const uint64_t s1 = r1 * 20;
+ const uint64_t s2 = r2 * 20;
+
+ for(size_t i = 0; i != blocks; ++i)
+ {
+ const uint64_t t0 = load_le<uint64_t>(m, 0);
+ const uint64_t t1 = load_le<uint64_t>(m, 1);
+
+ h0 += (( t0 ) & M44);
+ h1 += (((t0 >> 44) | (t1 << 20)) & M44);
+ h2 += (((t1 >> 24) ) & M42) | hibit;
+
+ const uint128_t d0 = uint128_t(h0) * r0 + uint128_t(h1) * s2 + uint128_t(h2) * s1;
+ const uint64_t c0 = carry_shift(d0, 44);
+
+ const uint128_t d1 = uint128_t(h0) * r1 + uint128_t(h1) * r0 + uint128_t(h2) * s2 + c0;
+ const uint64_t c1 = carry_shift(d1, 44);
+
+ const uint128_t d2 = uint128_t(h0) * r2 + uint128_t(h1) * r1 + uint128_t(h2) * r0 + c1;
+ const uint64_t c2 = carry_shift(d2, 42);
+
+ h0 = d0 & M44;
+ h1 = d1 & M44;
+ h2 = d2 & M42;
+
+ h0 += c2 * 5;
+ h1 += carry_shift(h0, 44);
+ h0 = h0 & M44;
+
+ m += 16;
+ }
+
+ X[3+0] = h0;
+ X[3+1] = h1;
+ X[3+2] = h2;
+ }
+
+void poly1305_finish(secure_vector<uint64_t>& X, uint8_t mac[16])
+ {
+ const uint64_t M44 = 0xFFFFFFFFFFF;
+ const uint64_t M42 = 0x3FFFFFFFFFF;
+
+ /* fully carry h */
+ uint64_t h0 = X[3+0];
+ uint64_t h1 = X[3+1];
+ uint64_t h2 = X[3+2];
+
+ uint64_t c;
+ c = (h1 >> 44); h1 &= M44;
+ h2 += c; c = (h2 >> 42); h2 &= M42;
+ h0 += c * 5; c = (h0 >> 44); h0 &= M44;
+ h1 += c; c = (h1 >> 44); h1 &= M44;
+ h2 += c; c = (h2 >> 42); h2 &= M42;
+ h0 += c * 5; c = (h0 >> 44); h0 &= M44;
+ h1 += c;
+
+ /* compute h + -p */
+ uint64_t g0 = h0 + 5; c = (g0 >> 44); g0 &= M44;
+ uint64_t g1 = h1 + c; c = (g1 >> 44); g1 &= M44;
+ uint64_t g2 = h2 + c - (static_cast<uint64_t>(1) << 42);
+
+ /* select h if h < p, or h + -p if h >= p */
+ const auto c_mask = CT::Mask<uint64_t>::expand(c);
+ h0 = c_mask.select(g0, h0);
+ h1 = c_mask.select(g1, h1);
+ h2 = c_mask.select(g2, h2);
+
+ /* h = (h + pad) */
+ const uint64_t t0 = X[6];
+ const uint64_t t1 = X[7];
+
+ h0 += (( t0 ) & M44) ; c = (h0 >> 44); h0 &= M44;
+ h1 += (((t0 >> 44) | (t1 << 20)) & M44) + c; c = (h1 >> 44); h1 &= M44;
+ h2 += (((t1 >> 24) ) & M42) + c; h2 &= M42;
+
+ /* mac = h % (2^128) */
+ h0 = ((h0 ) | (h1 << 44));
+ h1 = ((h1 >> 20) | (h2 << 24));
+
+ store_le(mac, h0, h1);
+
+ /* zero out the state */
+ clear_mem(X.data(), X.size());
+ }
+
+}
+
+void Poly1305::clear()
+ {
+ zap(m_poly);
+ zap(m_buf);
+ m_buf_pos = 0;
+ }
+
+void Poly1305::key_schedule(const uint8_t key[], size_t)
+ {
+ m_buf_pos = 0;
+ m_buf.resize(16);
+ m_poly.resize(8);
+
+ poly1305_init(m_poly, key);
+ }
+
+void Poly1305::add_data(const uint8_t input[], size_t length)
+ {
+ verify_key_set(m_poly.size() == 8);
+
+ if(m_buf_pos)
+ {
+ buffer_insert(m_buf, m_buf_pos, input, length);
+
+ if(m_buf_pos + length >= m_buf.size())
+ {
+ poly1305_blocks(m_poly, m_buf.data(), 1);
+ input += (m_buf.size() - m_buf_pos);
+ length -= (m_buf.size() - m_buf_pos);
+ m_buf_pos = 0;
+ }
+ }
+
+ const size_t full_blocks = length / m_buf.size();
+ const size_t remaining = length % m_buf.size();
+
+ if(full_blocks)
+ poly1305_blocks(m_poly, input, full_blocks);
+
+ buffer_insert(m_buf, m_buf_pos, input + full_blocks * m_buf.size(), remaining);
+ m_buf_pos += remaining;
+ }
+
+void Poly1305::final_result(uint8_t out[])
+ {
+ verify_key_set(m_poly.size() == 8);
+
+ if(m_buf_pos != 0)
+ {
+ m_buf[m_buf_pos] = 1;
+ const size_t len = m_buf.size() - m_buf_pos - 1;
+ if (len > 0)
+ {
+ clear_mem(&m_buf[m_buf_pos+1], len);
+ }
+ poly1305_blocks(m_poly, m_buf.data(), 1, true);
+ }
+
+ poly1305_finish(m_poly, out);
+
+ m_poly.clear();
+ m_buf_pos = 0;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/mac/poly1305/poly1305.h b/comm/third_party/botan/src/lib/mac/poly1305/poly1305.h
new file mode 100644
index 0000000000..fdd01ecd1a
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/poly1305/poly1305.h
@@ -0,0 +1,50 @@
+/*
+* Poly1305
+* (C) 2014 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_MAC_POLY1305_H_
+#define BOTAN_MAC_POLY1305_H_
+
+#include <botan/mac.h>
+#include <memory>
+
+BOTAN_FUTURE_INTERNAL_HEADER(poly1305.h)
+
+namespace Botan {
+
+/**
+* DJB's Poly1305
+* Important note: each key can only be used once
+*/
+class BOTAN_PUBLIC_API(2,0) Poly1305 final : public MessageAuthenticationCode
+ {
+ public:
+ std::string name() const override { return "Poly1305"; }
+
+ MessageAuthenticationCode* clone() const override { return new Poly1305; }
+
+ void clear() override;
+
+ size_t output_length() const override { return 16; }
+
+ Key_Length_Specification key_spec() const override
+ {
+ return Key_Length_Specification(32);
+ }
+
+ private:
+ void add_data(const uint8_t[], size_t) override;
+ void final_result(uint8_t[]) override;
+ void key_schedule(const uint8_t[], size_t) override;
+
+ secure_vector<uint64_t> m_poly;
+ secure_vector<uint8_t> m_buf;
+ size_t m_buf_pos = 0;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/mac/siphash/info.txt b/comm/third_party/botan/src/lib/mac/siphash/info.txt
new file mode 100644
index 0000000000..8d4c20d1a8
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/siphash/info.txt
@@ -0,0 +1,3 @@
+<defines>
+SIPHASH -> 20150110
+</defines>
diff --git a/comm/third_party/botan/src/lib/mac/siphash/siphash.cpp b/comm/third_party/botan/src/lib/mac/siphash/siphash.cpp
new file mode 100644
index 0000000000..566d5d5def
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/siphash/siphash.cpp
@@ -0,0 +1,136 @@
+/*
+* SipHash
+* (C) 2014,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/siphash.h>
+#include <botan/loadstor.h>
+#include <botan/rotate.h>
+
+namespace Botan {
+
+namespace {
+
+void SipRounds(uint64_t M, secure_vector<uint64_t>& V, size_t r)
+ {
+ uint64_t V0 = V[0], V1 = V[1], V2 = V[2], V3 = V[3];
+
+ V3 ^= M;
+ for(size_t i = 0; i != r; ++i)
+ {
+ V0 += V1; V2 += V3;
+ V1 = rotl<13>(V1);
+ V3 = rotl<16>(V3);
+ V1 ^= V0; V3 ^= V2;
+ V0 = rotl<32>(V0);
+
+ V2 += V1; V0 += V3;
+ V1 = rotl<17>(V1);
+ V3 = rotl<21>(V3);
+ V1 ^= V2; V3 ^= V0;
+ V2 = rotl<32>(V2);
+ }
+ V0 ^= M;
+
+ V[0] = V0; V[1] = V1; V[2] = V2; V[3] = V3;
+ }
+
+}
+
+void SipHash::add_data(const uint8_t input[], size_t length)
+ {
+ verify_key_set(m_V.empty() == false);
+
+ // SipHash counts the message length mod 256
+ m_words += static_cast<uint8_t>(length);
+
+ if(m_mbuf_pos)
+ {
+ while(length && m_mbuf_pos != 8)
+ {
+ m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(input[0]) << 56);
+ ++m_mbuf_pos;
+ ++input;
+ length--;
+ }
+
+ if(m_mbuf_pos == 8)
+ {
+ SipRounds(m_mbuf, m_V, m_C);
+ m_mbuf_pos = 0;
+ m_mbuf = 0;
+ }
+ }
+
+ while(length >= 8)
+ {
+ SipRounds(load_le<uint64_t>(input, 0), m_V, m_C);
+ input += 8;
+ length -= 8;
+ }
+
+ for(size_t i = 0; i != length; ++i)
+ {
+ m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(input[i]) << 56);
+ m_mbuf_pos++;
+ }
+ }
+
+void SipHash::final_result(uint8_t mac[])
+ {
+ verify_key_set(m_V.empty() == false);
+
+ if(m_mbuf_pos == 0)
+ {
+ m_mbuf = (static_cast<uint64_t>(m_words) << 56);
+ }
+ else if(m_mbuf_pos < 8)
+ {
+ m_mbuf = (m_mbuf >> (64-m_mbuf_pos*8)) | (static_cast<uint64_t>(m_words) << 56);
+ }
+
+ SipRounds(m_mbuf, m_V, m_C);
+
+ m_V[2] ^= 0xFF;
+ SipRounds(0, m_V, m_D);
+
+ const uint64_t X = m_V[0] ^ m_V[1] ^ m_V[2] ^ m_V[3];
+
+ store_le(X, mac);
+
+ clear();
+ }
+
+void SipHash::key_schedule(const uint8_t key[], size_t)
+ {
+ const uint64_t K0 = load_le<uint64_t>(key, 0);
+ const uint64_t K1 = load_le<uint64_t>(key, 1);
+
+ m_V.resize(4);
+ m_V[0] = K0 ^ 0x736F6D6570736575;
+ m_V[1] = K1 ^ 0x646F72616E646F6D;
+ m_V[2] = K0 ^ 0x6C7967656E657261;
+ m_V[3] = K1 ^ 0x7465646279746573;
+ }
+
+void SipHash::clear()
+ {
+ zap(m_V);
+ m_mbuf = 0;
+ m_mbuf_pos = 0;
+ m_words = 0;
+ }
+
+std::string SipHash::name() const
+ {
+ return "SipHash(" + std::to_string(m_C) + "," + std::to_string(m_D) + ")";
+ }
+
+MessageAuthenticationCode* SipHash::clone() const
+ {
+ return new SipHash(m_C, m_D);
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/mac/siphash/siphash.h b/comm/third_party/botan/src/lib/mac/siphash/siphash.h
new file mode 100644
index 0000000000..d60df8dfce
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/siphash/siphash.h
@@ -0,0 +1,47 @@
+/*
+* SipHash
+* (C) 2014,2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_SIPHASH_H_
+#define BOTAN_SIPHASH_H_
+
+#include <botan/mac.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(siphash.h)
+
+namespace Botan {
+
+class BOTAN_PUBLIC_API(2,0) SipHash final : public MessageAuthenticationCode
+ {
+ public:
+ SipHash(size_t c = 2, size_t d = 4) : m_C(c), m_D(d) {}
+
+ void clear() override;
+ std::string name() const override;
+
+ MessageAuthenticationCode* clone() const override;
+
+ size_t output_length() const override { return 8; }
+
+ Key_Length_Specification key_spec() const override
+ {
+ return Key_Length_Specification(16);
+ }
+ private:
+ void add_data(const uint8_t[], size_t) override;
+ void final_result(uint8_t[]) override;
+ void key_schedule(const uint8_t[], size_t) override;
+
+ const size_t m_C, m_D;
+ secure_vector<uint64_t> m_V;
+ uint64_t m_mbuf = 0;
+ size_t m_mbuf_pos = 0;
+ uint8_t m_words = 0;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/mac/x919_mac/info.txt b/comm/third_party/botan/src/lib/mac/x919_mac/info.txt
new file mode 100644
index 0000000000..65d6cee645
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/x919_mac/info.txt
@@ -0,0 +1,7 @@
+<defines>
+ANSI_X919_MAC -> 20131128
+</defines>
+
+<requires>
+des
+</requires>
diff --git a/comm/third_party/botan/src/lib/mac/x919_mac/x919_mac.cpp b/comm/third_party/botan/src/lib/mac/x919_mac/x919_mac.cpp
new file mode 100644
index 0000000000..0cbf087959
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/x919_mac/x919_mac.cpp
@@ -0,0 +1,99 @@
+/*
+* ANSI X9.19 MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/x919_mac.h>
+
+namespace Botan {
+
+/*
+* Update an ANSI X9.19 MAC Calculation
+*/
+void ANSI_X919_MAC::add_data(const uint8_t input[], size_t length)
+ {
+ verify_key_set(m_state.empty() == false);
+
+ size_t xored = std::min(8 - m_position, length);
+ xor_buf(&m_state[m_position], input, xored);
+ m_position += xored;
+
+ if(m_position < 8) return;
+
+ m_des1->encrypt(m_state);
+ input += xored;
+ length -= xored;
+ while(length >= 8)
+ {
+ xor_buf(m_state, input, 8);
+ m_des1->encrypt(m_state);
+ input += 8;
+ length -= 8;
+ }
+
+ xor_buf(m_state, input, length);
+ m_position = length;
+ }
+
+/*
+* Finalize an ANSI X9.19 MAC Calculation
+*/
+void ANSI_X919_MAC::final_result(uint8_t mac[])
+ {
+ if(m_position)
+ m_des1->encrypt(m_state);
+ m_des2->decrypt(m_state.data(), mac);
+ m_des1->encrypt(mac);
+ zeroise(m_state);
+ m_position = 0;
+ }
+
+/*
+* ANSI X9.19 MAC Key Schedule
+*/
+void ANSI_X919_MAC::key_schedule(const uint8_t key[], size_t length)
+ {
+ m_state.resize(8);
+
+ m_des1->set_key(key, 8);
+
+ if(length == 16)
+ key += 8;
+
+ m_des2->set_key(key, 8);
+ }
+
+/*
+* Clear memory of sensitive data
+*/
+void ANSI_X919_MAC::clear()
+ {
+ m_des1->clear();
+ m_des2->clear();
+ zap(m_state);
+ m_position = 0;
+ }
+
+std::string ANSI_X919_MAC::name() const
+ {
+ return "X9.19-MAC";
+ }
+
+MessageAuthenticationCode* ANSI_X919_MAC::clone() const
+ {
+ return new ANSI_X919_MAC;
+ }
+
+/*
+* ANSI X9.19 MAC Constructor
+*/
+ANSI_X919_MAC::ANSI_X919_MAC() :
+ m_des1(BlockCipher::create("DES")),
+ m_des2(m_des1->clone()),
+ m_position(0)
+ {
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/mac/x919_mac/x919_mac.h b/comm/third_party/botan/src/lib/mac/x919_mac/x919_mac.h
new file mode 100644
index 0000000000..3df38b9aa6
--- /dev/null
+++ b/comm/third_party/botan/src/lib/mac/x919_mac/x919_mac.h
@@ -0,0 +1,51 @@
+/*
+* ANSI X9.19 MAC
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_ANSI_X919_MAC_H_
+#define BOTAN_ANSI_X919_MAC_H_
+
+#include <botan/mac.h>
+#include <botan/block_cipher.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(x919_mac.h)
+
+namespace Botan {
+
+/**
+* DES/3DES-based MAC from ANSI X9.19
+*/
+class BOTAN_PUBLIC_API(2,0) ANSI_X919_MAC final : public MessageAuthenticationCode
+ {
+ public:
+ void clear() override;
+ std::string name() const override;
+ size_t output_length() const override { return 8; }
+
+ MessageAuthenticationCode* clone() const override;
+
+ Key_Length_Specification key_spec() const override
+ {
+ return Key_Length_Specification(8, 16, 8);
+ }
+
+ ANSI_X919_MAC();
+
+ ANSI_X919_MAC(const ANSI_X919_MAC&) = delete;
+ ANSI_X919_MAC& operator=(const ANSI_X919_MAC&) = delete;
+ private:
+ void add_data(const uint8_t[], size_t) override;
+ void final_result(uint8_t[]) override;
+ void key_schedule(const uint8_t[], size_t) override;
+
+ std::unique_ptr<BlockCipher> m_des1, m_des2;
+ secure_vector<uint8_t> m_state;
+ size_t m_position;
+ };
+
+}
+
+#endif