summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/pk_pad
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/botan/src/lib/pk_pad
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/botan/src/lib/pk_pad')
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme.cpp94
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme.h94
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme_oaep/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.cpp168
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.h62
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp109
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.h35
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/info.txt4
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.cpp31
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.h33
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/eme_raw/info.txt3
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa.cpp207
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa.h107
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.cpp133
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.h55
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa1/info.txt3
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp166
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h94
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_pssr/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.cpp291
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.h103
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.cpp92
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.h47
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_raw/info.txt3
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.cpp102
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.h52
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/emsa_x931/info.txt7
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.cpp163
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.h34
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/hash_id/info.txt3
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/info.txt18
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/iso9796/info.txt9
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.cpp322
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.h98
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/mgf1/info.txt3
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.cpp36
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.h31
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/padding.cpp44
-rw-r--r--comm/third_party/botan/src/lib/pk_pad/padding.h36
40 files changed, 2913 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme.cpp b/comm/third_party/botan/src/lib/pk_pad/eme.cpp
new file mode 100644
index 0000000000..ffedac923d
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme.cpp
@@ -0,0 +1,94 @@
+/*
+* EME Base Class
+* (C) 1999-2008 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/eme.h>
+#include <botan/scan_name.h>
+#include <botan/exceptn.h>
+#include <botan/parsing.h>
+
+#if defined(BOTAN_HAS_EME_OAEP)
+#include <botan/oaep.h>
+#endif
+
+#if defined(BOTAN_HAS_EME_PKCS1)
+#include <botan/eme_pkcs.h>
+#endif
+
+#if defined(BOTAN_HAS_EME_RAW)
+#include <botan/eme_raw.h>
+#endif
+
+namespace Botan {
+
+EME* get_eme(const std::string& algo_spec)
+ {
+#if defined(BOTAN_HAS_EME_RAW)
+ if(algo_spec == "Raw")
+ return new EME_Raw;
+#endif
+
+#if defined(BOTAN_HAS_EME_PKCS1)
+ if(algo_spec == "PKCS1v15" || algo_spec == "EME-PKCS1-v1_5")
+ return new EME_PKCS1v15;
+#endif
+
+#if defined(BOTAN_HAS_EME_OAEP)
+ SCAN_Name req(algo_spec);
+
+ if(req.algo_name() == "OAEP" ||
+ req.algo_name() == "EME-OAEP" ||
+ req.algo_name() == "EME1")
+ {
+ if(req.arg_count() == 1 ||
+ ((req.arg_count() == 2 || req.arg_count() == 3) && req.arg(1) == "MGF1"))
+ {
+ if(auto hash = HashFunction::create(req.arg(0)))
+ return new OAEP(hash.release(), req.arg(2, ""));
+ }
+ else if(req.arg_count() == 2 || req.arg_count() == 3)
+ {
+ auto mgf_params = parse_algorithm_name(req.arg(1));
+
+ if(mgf_params.size() == 2 && mgf_params[0] == "MGF1")
+ {
+ auto hash = HashFunction::create(req.arg(0));
+ auto mgf1_hash = HashFunction::create(mgf_params[1]);
+
+ if(hash && mgf1_hash)
+ {
+ return new OAEP(hash.release(), mgf1_hash.release(), req.arg(2, ""));
+ }
+ }
+ }
+ }
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+/*
+* Encode a message
+*/
+secure_vector<uint8_t> EME::encode(const uint8_t msg[], size_t msg_len,
+ size_t key_bits,
+ RandomNumberGenerator& rng) const
+ {
+ return pad(msg, msg_len, key_bits, rng);
+ }
+
+/*
+* Encode a message
+*/
+secure_vector<uint8_t> EME::encode(const secure_vector<uint8_t>& msg,
+ size_t key_bits,
+ RandomNumberGenerator& rng) const
+ {
+ return pad(msg.data(), msg.size(), key_bits, rng);
+ }
+
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme.h b/comm/third_party/botan/src/lib/pk_pad/eme.h
new file mode 100644
index 0000000000..38cce4b093
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme.h
@@ -0,0 +1,94 @@
+/*
+* EME Classes
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PUBKEY_EME_ENCRYPTION_PAD_H_
+#define BOTAN_PUBKEY_EME_ENCRYPTION_PAD_H_
+
+#include <botan/secmem.h>
+#include <string>
+
+BOTAN_FUTURE_INTERNAL_HEADER(eme.h)
+
+namespace Botan {
+
+class RandomNumberGenerator;
+
+/**
+* Encoding Method for Encryption
+*/
+class BOTAN_PUBLIC_API(2,0) EME
+ {
+ public:
+ virtual ~EME() = default;
+
+ /**
+ * Return the maximum input size in bytes we can support
+ * @param keybits the size of the key in bits
+ * @return upper bound of input in bytes
+ */
+ virtual size_t maximum_input_size(size_t keybits) const = 0;
+
+ /**
+ * Encode an input
+ * @param in the plaintext
+ * @param in_length length of plaintext in bytes
+ * @param key_length length of the key in bits
+ * @param rng a random number generator
+ * @return encoded plaintext
+ */
+ secure_vector<uint8_t> encode(const uint8_t in[],
+ size_t in_length,
+ size_t key_length,
+ RandomNumberGenerator& rng) const;
+
+ /**
+ * Encode an input
+ * @param in the plaintext
+ * @param key_length length of the key in bits
+ * @param rng a random number generator
+ * @return encoded plaintext
+ */
+ secure_vector<uint8_t> encode(const secure_vector<uint8_t>& in,
+ size_t key_length,
+ RandomNumberGenerator& rng) const;
+
+ /**
+ * Decode an input
+ * @param valid_mask written to specifies if output is valid
+ * @param in the encoded plaintext
+ * @param in_len length of encoded plaintext in bytes
+ * @return bytes of out[] written to along with
+ * validity mask (0xFF if valid, else 0x00)
+ */
+ virtual secure_vector<uint8_t> unpad(uint8_t& valid_mask,
+ const uint8_t in[],
+ size_t in_len) const = 0;
+
+ /**
+ * Encode an input
+ * @param in the plaintext
+ * @param in_length length of plaintext in bytes
+ * @param key_length length of the key in bits
+ * @param rng a random number generator
+ * @return encoded plaintext
+ */
+ virtual secure_vector<uint8_t> pad(const uint8_t in[],
+ size_t in_length,
+ size_t key_length,
+ RandomNumberGenerator& rng) const = 0;
+ };
+
+/**
+* Factory method for EME (message-encoding methods for encryption) objects
+* @param algo_spec the name of the EME to create
+* @return pointer to newly allocated object of that type
+*/
+BOTAN_PUBLIC_API(2,0) EME* get_eme(const std::string& algo_spec);
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme_oaep/info.txt b/comm/third_party/botan/src/lib/pk_pad/eme_oaep/info.txt
new file mode 100644
index 0000000000..cabe23fb85
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme_oaep/info.txt
@@ -0,0 +1,7 @@
+<defines>
+EME_OAEP -> 20180305
+</defines>
+
+<requires>
+mgf1
+</requires>
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.cpp b/comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.cpp
new file mode 100644
index 0000000000..428b6ac3bf
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.cpp
@@ -0,0 +1,168 @@
+/*
+* OAEP
+* (C) 1999-2010,2015,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/oaep.h>
+#include <botan/mgf1.h>
+#include <botan/exceptn.h>
+#include <botan/rng.h>
+#include <botan/internal/ct_utils.h>
+
+namespace Botan {
+
+/*
+* OAEP Pad Operation
+*/
+secure_vector<uint8_t> OAEP::pad(const uint8_t in[], size_t in_length,
+ size_t key_length,
+ RandomNumberGenerator& rng) const
+ {
+ key_length /= 8;
+
+ if(in_length > maximum_input_size(key_length * 8))
+ {
+ throw Invalid_Argument("OAEP: Input is too large");
+ }
+
+ secure_vector<uint8_t> out(key_length);
+
+ rng.randomize(out.data(), m_Phash.size());
+
+ buffer_insert(out, m_Phash.size(), m_Phash.data(), m_Phash.size());
+ out[out.size() - in_length - 1] = 0x01;
+ buffer_insert(out, out.size() - in_length, in, in_length);
+
+ mgf1_mask(*m_mgf1_hash,
+ out.data(), m_Phash.size(),
+ &out[m_Phash.size()], out.size() - m_Phash.size());
+
+ mgf1_mask(*m_mgf1_hash,
+ &out[m_Phash.size()], out.size() - m_Phash.size(),
+ out.data(), m_Phash.size());
+
+ return out;
+ }
+
+/*
+* OAEP Unpad Operation
+*/
+secure_vector<uint8_t> OAEP::unpad(uint8_t& valid_mask,
+ const uint8_t in[], size_t in_length) const
+ {
+ /*
+ Must be careful about error messages here; if an attacker can
+ distinguish them, it is easy to use the differences as an oracle to
+ find the secret key, as described in "A Chosen Ciphertext Attack on
+ RSA Optimal Asymmetric Encryption Padding (OAEP) as Standardized in
+ PKCS #1 v2.0", James Manger, Crypto 2001
+
+ Also have to be careful about timing attacks! Pointed out by Falko
+ Strenzke.
+
+ According to the standard (Section 7.1.1), the encryptor always
+ creates a message as follows:
+ i. Concatenate a single octet with hexadecimal value 0x00,
+ maskedSeed, and maskedDB to form an encoded message EM of
+ length k octets as
+ EM = 0x00 || maskedSeed || maskedDB.
+ where k is the length of the modulus N.
+ Therefore, the first byte can always be skipped safely.
+ */
+
+ const auto leading_0 = CT::Mask<uint8_t>::is_zero(in[0]);
+
+ secure_vector<uint8_t> input(in + 1, in + in_length);
+
+ const size_t hlen = m_Phash.size();
+
+ mgf1_mask(*m_mgf1_hash,
+ &input[hlen], input.size() - hlen,
+ input.data(), hlen);
+
+ mgf1_mask(*m_mgf1_hash,
+ input.data(), hlen,
+ &input[hlen], input.size() - hlen);
+
+ auto unpadded = oaep_find_delim(valid_mask, input.data(), input.size(), m_Phash);
+ valid_mask &= leading_0.unpoisoned_value();
+ return unpadded;
+ }
+
+secure_vector<uint8_t>
+oaep_find_delim(uint8_t& valid_mask,
+ const uint8_t input[], size_t input_len,
+ const secure_vector<uint8_t>& Phash)
+ {
+ const size_t hlen = Phash.size();
+
+ // Too short to be valid, reject immediately
+ if(input_len < 1 + 2*hlen)
+ {
+ return secure_vector<uint8_t>();
+ }
+
+ CT::poison(input, input_len);
+
+ size_t delim_idx = 2 * hlen;
+ CT::Mask<uint8_t> waiting_for_delim = CT::Mask<uint8_t>::set();
+ CT::Mask<uint8_t> bad_input_m = CT::Mask<uint8_t>::cleared();
+
+ for(size_t i = delim_idx; i < input_len; ++i)
+ {
+ const auto zero_m = CT::Mask<uint8_t>::is_zero(input[i]);
+ const auto one_m = CT::Mask<uint8_t>::is_equal(input[i], 1);
+
+ const auto add_m = waiting_for_delim & zero_m;
+
+ bad_input_m |= waiting_for_delim & ~(zero_m | one_m);
+
+ delim_idx += add_m.if_set_return(1);
+
+ waiting_for_delim &= zero_m;
+ }
+
+ // If we never saw any non-zero byte, then it's not valid input
+ bad_input_m |= waiting_for_delim;
+ bad_input_m |= CT::Mask<uint8_t>::is_zero(ct_compare_u8(&input[hlen], Phash.data(), hlen));
+
+ delim_idx += 1;
+
+ valid_mask = (~bad_input_m).unpoisoned_value();
+ const secure_vector<uint8_t> output = CT::copy_output(bad_input_m, input, input_len, delim_idx);
+
+ CT::unpoison(input, input_len);
+
+ return output;
+ }
+
+/*
+* Return the max input size for a given key size
+*/
+size_t OAEP::maximum_input_size(size_t keybits) const
+ {
+ if(keybits / 8 > 2*m_Phash.size() + 1)
+ return ((keybits / 8) - 2*m_Phash.size() - 1);
+ else
+ return 0;
+ }
+
+/*
+* OAEP Constructor
+*/
+OAEP::OAEP(HashFunction* hash, const std::string& P) : m_mgf1_hash(hash)
+ {
+ m_Phash = m_mgf1_hash->process(P);
+ }
+
+OAEP::OAEP(HashFunction* hash,
+ HashFunction* mgf1_hash,
+ const std::string& P) : m_mgf1_hash(mgf1_hash)
+ {
+ std::unique_ptr<HashFunction> phash(hash); // takes ownership
+ m_Phash = phash->process(P);
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.h b/comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.h
new file mode 100644
index 0000000000..383617b82c
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.h
@@ -0,0 +1,62 @@
+/*
+* OAEP
+* (C) 1999-2007,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_OAEP_H_
+#define BOTAN_OAEP_H_
+
+#include <botan/eme.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(oaep.h)
+
+namespace Botan {
+
+/**
+* OAEP (called EME1 in IEEE 1363 and in earlier versions of the library)
+* as specified in PKCS#1 v2.0 (RFC 2437)
+*/
+class BOTAN_PUBLIC_API(2,0) OAEP final : public EME
+ {
+ public:
+ size_t maximum_input_size(size_t) const override;
+
+ /**
+ * @param hash function to use for hashing (takes ownership)
+ * @param P an optional label. Normally empty.
+ */
+ OAEP(HashFunction* hash, const std::string& P = "");
+
+ /**
+ * @param hash function to use for hashing (takes ownership)
+ * @param mgf1_hash function to use for MGF1 (takes ownership)
+ * @param P an optional label. Normally empty.
+ */
+ OAEP(HashFunction* hash,
+ HashFunction* mgf1_hash,
+ const std::string& P = "");
+ private:
+ secure_vector<uint8_t> pad(const uint8_t in[],
+ size_t in_length,
+ size_t key_length,
+ RandomNumberGenerator& rng) const override;
+
+ secure_vector<uint8_t> unpad(uint8_t& valid_mask,
+ const uint8_t in[],
+ size_t in_len) const override;
+
+ secure_vector<uint8_t> m_Phash;
+ std::unique_ptr<HashFunction> m_mgf1_hash;
+ };
+
+secure_vector<uint8_t>
+BOTAN_TEST_API oaep_find_delim(uint8_t& valid_mask,
+ const uint8_t input[], size_t input_len,
+ const secure_vector<uint8_t>& Phash);
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp b/comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp
new file mode 100644
index 0000000000..eac3da5d9a
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp
@@ -0,0 +1,109 @@
+/*
+* PKCS #1 v1.5 Type 2 (encryption) padding
+* (C) 1999-2007,2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/eme_pkcs.h>
+#include <botan/exceptn.h>
+#include <botan/rng.h>
+#include <botan/internal/ct_utils.h>
+
+namespace Botan {
+
+/*
+* PKCS1 Pad Operation
+*/
+secure_vector<uint8_t> EME_PKCS1v15::pad(const uint8_t in[], size_t inlen,
+ size_t key_length,
+ RandomNumberGenerator& rng) const
+ {
+ key_length /= 8;
+
+ if(inlen > maximum_input_size(key_length * 8))
+ {
+ throw Invalid_Argument("PKCS1: Input is too large");
+ }
+
+ secure_vector<uint8_t> out(key_length);
+
+ out[0] = 0x02;
+ rng.randomize(out.data() + 1, (key_length - inlen - 2));
+
+ for(size_t j = 1; j != key_length - inlen - 1; ++j)
+ {
+ if(out[j] == 0)
+ {
+ out[j] = rng.next_nonzero_byte();
+ }
+ }
+
+ buffer_insert(out, key_length - inlen, in, inlen);
+
+ return out;
+ }
+
+/*
+* PKCS1 Unpad Operation
+*/
+secure_vector<uint8_t> EME_PKCS1v15::unpad(uint8_t& valid_mask,
+ const uint8_t in[], size_t inlen) const
+ {
+ /*
+ * RSA decryption pads the ciphertext up to the modulus size, so this only
+ * occurs with very (!) small keys, or when fuzzing.
+ *
+ * 11 bytes == 00,02 + 8 bytes mandatory padding + 00
+ */
+ if(inlen < 11)
+ {
+ valid_mask = false;
+ return secure_vector<uint8_t>();
+ }
+
+ CT::poison(in, inlen);
+
+ CT::Mask<uint8_t> bad_input_m = CT::Mask<uint8_t>::cleared();
+ CT::Mask<uint8_t> seen_zero_m = CT::Mask<uint8_t>::cleared();
+ size_t delim_idx = 2; // initial 0002
+
+ bad_input_m |= ~CT::Mask<uint8_t>::is_equal(in[0], 0);
+ bad_input_m |= ~CT::Mask<uint8_t>::is_equal(in[1], 2);
+
+ for(size_t i = 2; i < inlen; ++i)
+ {
+ const auto is_zero_m = CT::Mask<uint8_t>::is_zero(in[i]);
+ delim_idx += seen_zero_m.if_not_set_return(1);
+ seen_zero_m |= is_zero_m;
+ }
+
+ // no zero delim -> bad padding
+ bad_input_m |= ~seen_zero_m;
+ /*
+ delim indicates < 8 bytes padding -> bad padding
+
+ We require 11 here because we are counting also the 00 delim byte
+ */
+ bad_input_m |= CT::Mask<uint8_t>(CT::Mask<size_t>::is_lt(delim_idx, 11));
+
+ valid_mask = (~bad_input_m).unpoisoned_value();
+ const secure_vector<uint8_t> output = CT::copy_output(bad_input_m, in, inlen, delim_idx);
+
+ CT::unpoison(in, inlen);
+
+ return output;
+ }
+
+/*
+* Return the max input size for a given key size
+*/
+size_t EME_PKCS1v15::maximum_input_size(size_t keybits) const
+ {
+ if(keybits / 8 > 10)
+ return ((keybits / 8) - 10);
+ else
+ return 0;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.h b/comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.h
new file mode 100644
index 0000000000..fb7cf14197
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.h
@@ -0,0 +1,35 @@
+/*
+* EME PKCS#1 v1.5
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_EME_PKCS1_H_
+#define BOTAN_EME_PKCS1_H_
+
+#include <botan/eme.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(eme_pkcs.h)
+
+namespace Botan {
+
+/**
+* EME from PKCS #1 v1.5
+*/
+class BOTAN_PUBLIC_API(2,0) EME_PKCS1v15 final : public EME
+ {
+ public:
+ size_t maximum_input_size(size_t) const override;
+
+ secure_vector<uint8_t> pad(const uint8_t[], size_t, size_t,
+ RandomNumberGenerator&) const override;
+
+ secure_vector<uint8_t> unpad(uint8_t& valid_mask,
+ const uint8_t in[],
+ size_t in_len) const override;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/info.txt b/comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/info.txt
new file mode 100644
index 0000000000..772806e429
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/info.txt
@@ -0,0 +1,4 @@
+<defines>
+EME_PKCS1v15 -> 20131128
+EME_PKCS1 -> 20190426
+</defines>
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.cpp b/comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.cpp
new file mode 100644
index 0000000000..066e7afd8c
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.cpp
@@ -0,0 +1,31 @@
+/*
+* (C) 2015,2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/eme_raw.h>
+#include <botan/internal/bit_ops.h>
+#include <botan/internal/ct_utils.h>
+
+namespace Botan {
+
+secure_vector<uint8_t> EME_Raw::pad(const uint8_t in[], size_t in_length,
+ size_t,
+ RandomNumberGenerator&) const
+ {
+ return secure_vector<uint8_t>(in, in + in_length);
+ }
+
+secure_vector<uint8_t> EME_Raw::unpad(uint8_t& valid_mask,
+ const uint8_t in[], size_t in_length) const
+ {
+ valid_mask = 0xFF;
+ return CT::strip_leading_zeros(in, in_length);
+ }
+
+size_t EME_Raw::maximum_input_size(size_t keybits) const
+ {
+ return keybits / 8;
+ }
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.h b/comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.h
new file mode 100644
index 0000000000..840448c559
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.h
@@ -0,0 +1,33 @@
+/*
+* (C) 2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_EME_RAW_H_
+#define BOTAN_EME_RAW_H_
+
+#include <botan/eme.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(eme_raw.h)
+
+namespace Botan {
+
+class BOTAN_PUBLIC_API(2,0) EME_Raw final : public EME
+ {
+ public:
+ size_t maximum_input_size(size_t i) const override;
+
+ EME_Raw() = default;
+ private:
+ secure_vector<uint8_t> pad(const uint8_t[], size_t, size_t,
+ RandomNumberGenerator&) const override;
+
+ secure_vector<uint8_t> unpad(uint8_t& valid_mask,
+ const uint8_t in[],
+ size_t in_len) const override;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/eme_raw/info.txt b/comm/third_party/botan/src/lib/pk_pad/eme_raw/info.txt
new file mode 100644
index 0000000000..c42365e98a
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/eme_raw/info.txt
@@ -0,0 +1,3 @@
+<defines>
+EME_RAW -> 20150313
+</defines>
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa.cpp b/comm/third_party/botan/src/lib/pk_pad/emsa.cpp
new file mode 100644
index 0000000000..a3e4486862
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa.cpp
@@ -0,0 +1,207 @@
+/*
+* (C) 2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+#include <botan/scan_name.h>
+#include <botan/exceptn.h>
+
+#if defined(BOTAN_HAS_EMSA1)
+ #include <botan/emsa1.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA_X931)
+ #include <botan/emsa_x931.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA_PKCS1)
+ #include <botan/emsa_pkcs1.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA_PSSR)
+ #include <botan/pssr.h>
+#endif
+
+#if defined(BOTAN_HAS_EMSA_RAW)
+ #include <botan/emsa_raw.h>
+#endif
+
+#if defined(BOTAN_HAS_ISO_9796)
+ #include <botan/iso9796.h>
+#endif
+
+namespace Botan {
+
+AlgorithmIdentifier EMSA::config_for_x509(const Private_Key&,
+ const std::string&) const
+ {
+ throw Not_Implemented("Encoding " + name() + " not supported for signing X509 objects");
+ }
+
+EMSA* get_emsa(const std::string& algo_spec)
+ {
+ SCAN_Name req(algo_spec);
+
+#if defined(BOTAN_HAS_EMSA1)
+ if(req.algo_name() == "EMSA1" && req.arg_count() == 1)
+ {
+ if(auto hash = HashFunction::create(req.arg(0)))
+ return new EMSA1(hash.release());
+ }
+#endif
+
+#if defined(BOTAN_HAS_EMSA_PKCS1)
+ if(req.algo_name() == "EMSA_PKCS1" ||
+ req.algo_name() == "PKCS1v15" ||
+ req.algo_name() == "EMSA-PKCS1-v1_5" ||
+ req.algo_name() == "EMSA3")
+ {
+ if(req.arg_count() == 2 && req.arg(0) == "Raw")
+ {
+ return new EMSA_PKCS1v15_Raw(req.arg(1));
+ }
+ else if(req.arg_count() == 1)
+ {
+ if(req.arg(0) == "Raw")
+ {
+ return new EMSA_PKCS1v15_Raw;
+ }
+ else
+ {
+ if(auto hash = HashFunction::create(req.arg(0)))
+ {
+ return new EMSA_PKCS1v15(hash.release());
+ }
+ }
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_EMSA_PSSR)
+ if(req.algo_name() == "PSS_Raw" ||
+ req.algo_name() == "PSSR_Raw")
+ {
+ if(req.arg_count_between(1, 3) && req.arg(1, "MGF1") == "MGF1")
+ {
+ if(auto h = HashFunction::create(req.arg(0)))
+ {
+ if(req.arg_count() == 3)
+ {
+ const size_t salt_size = req.arg_as_integer(2, 0);
+ return new PSSR_Raw(h.release(), salt_size);
+ }
+ else
+ {
+ return new PSSR_Raw(h.release());
+ }
+ }
+ }
+ }
+
+ if(req.algo_name() == "PSS" ||
+ req.algo_name() == "PSSR" ||
+ req.algo_name() == "EMSA-PSS" ||
+ req.algo_name() == "PSS-MGF1" ||
+ req.algo_name() == "EMSA4")
+ {
+ if(req.arg_count_between(1, 3) && req.arg(1, "MGF1") == "MGF1")
+ {
+ if(auto h = HashFunction::create(req.arg(0)))
+ {
+ if(req.arg_count() == 3)
+ {
+ const size_t salt_size = req.arg_as_integer(2, 0);
+ return new PSSR(h.release(), salt_size);
+ }
+ else
+ {
+ return new PSSR(h.release());
+ }
+ }
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_ISO_9796)
+ if(req.algo_name() == "ISO_9796_DS2")
+ {
+ if(req.arg_count_between(1, 3))
+ {
+ if(auto h = HashFunction::create(req.arg(0)))
+ {
+ const size_t salt_size = req.arg_as_integer(2, h->output_length());
+ const bool implicit = req.arg(1, "exp") == "imp";
+ return new ISO_9796_DS2(h.release(), implicit, salt_size);
+ }
+ }
+ }
+ //ISO-9796-2 DS 3 is deterministic and DS2 without a salt
+ if(req.algo_name() == "ISO_9796_DS3")
+ {
+ if(req.arg_count_between(1, 2))
+ {
+ if(auto h = HashFunction::create(req.arg(0)))
+ {
+ const bool implicit = req.arg(1, "exp") == "imp";
+ return new ISO_9796_DS3(h.release(), implicit);
+ }
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_EMSA_X931)
+ if(req.algo_name() == "EMSA_X931" ||
+ req.algo_name() == "EMSA2" ||
+ req.algo_name() == "X9.31")
+ {
+ if(req.arg_count() == 1)
+ {
+ if(auto hash = HashFunction::create(req.arg(0)))
+ {
+ return new EMSA_X931(hash.release());
+ }
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_EMSA_RAW)
+ if(req.algo_name() == "Raw")
+ {
+ if(req.arg_count() == 0)
+ {
+ return new EMSA_Raw;
+ }
+ else
+ {
+ auto hash = HashFunction::create(req.arg(0));
+ if(hash)
+ return new EMSA_Raw(hash->output_length());
+ }
+ }
+#endif
+
+ throw Algorithm_Not_Found(algo_spec);
+ }
+
+std::string hash_for_emsa(const std::string& algo_spec)
+ {
+ SCAN_Name emsa_name(algo_spec);
+
+ if(emsa_name.arg_count() > 0)
+ {
+ const std::string pos_hash = emsa_name.arg(0);
+ return pos_hash;
+ }
+
+ // If we don't understand what this is return a safe default
+#if defined(BOTAN_HAS_SHA2_64)
+ return "SHA-512";
+#else
+ return "SHA-256";
+#endif
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa.h b/comm/third_party/botan/src/lib/pk_pad/emsa.h
new file mode 100644
index 0000000000..7178eae237
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa.h
@@ -0,0 +1,107 @@
+/*
+* EMSA Classes
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PUBKEY_EMSA_H_
+#define BOTAN_PUBKEY_EMSA_H_
+
+#include <botan/secmem.h>
+#include <botan/asn1_obj.h>
+#include <string>
+
+BOTAN_FUTURE_INTERNAL_HEADER(emsa.h)
+
+namespace Botan {
+
+class Private_Key;
+class RandomNumberGenerator;
+
+/**
+* EMSA, from IEEE 1363s Encoding Method for Signatures, Appendix
+*
+* Any way of encoding/padding signatures
+*/
+class BOTAN_PUBLIC_API(2,0) EMSA
+ {
+ public:
+ virtual ~EMSA() = default;
+
+ /**
+ * Add more data to the signature computation
+ * @param input some data
+ * @param length length of input in bytes
+ */
+ virtual void update(const uint8_t input[], size_t length) = 0;
+
+ /**
+ * @return raw hash
+ */
+ virtual secure_vector<uint8_t> raw_data() = 0;
+
+ /**
+ * Return the encoding of a message
+ * @param msg the result of raw_data()
+ * @param output_bits the desired output bit size
+ * @param rng a random number generator
+ * @return encoded signature
+ */
+ virtual secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator& rng) = 0;
+
+ /**
+ * Verify the encoding
+ * @param coded the received (coded) message representative
+ * @param raw the computed (local, uncoded) message representative
+ * @param key_bits the size of the key in bits
+ * @return true if coded is a valid encoding of raw, otherwise false
+ */
+ virtual bool verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits) = 0;
+
+ /**
+ * Prepare sig_algo for use in choose_sig_format for x509 certs
+ *
+ * @param key used for checking compatibility with the encoding scheme
+ * @param cert_hash_name is checked to equal the hash for the encoding
+ * @return algorithm identifier to signatures created using this key,
+ * padding method and hash.
+ */
+ virtual AlgorithmIdentifier config_for_x509(const Private_Key& key,
+ const std::string& cert_hash_name) const;
+
+ /**
+ * @return a new object representing the same encoding method as *this
+ */
+ virtual EMSA* clone() = 0;
+
+ /**
+ * @return the SCAN name of the encoding/padding scheme
+ */
+ virtual std::string name() const = 0;
+ };
+
+/**
+* Factory method for EMSA (message-encoding methods for signatures
+* with appendix) objects
+* @param algo_spec the name of the EMSA to create
+* @return pointer to newly allocated object of that type
+*/
+BOTAN_PUBLIC_API(2,0) EMSA* get_emsa(const std::string& algo_spec);
+
+/**
+* Returns the hash function used in the given EMSA scheme
+* If the hash function is not specified or not understood,
+* returns "SHA-512"
+* @param algo_spec the name of the EMSA
+* @return hash function used in the given EMSA scheme
+*/
+BOTAN_PUBLIC_API(2,0) std::string hash_for_emsa(const std::string& algo_spec);
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.cpp b/comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.cpp
new file mode 100644
index 0000000000..f7293db270
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.cpp
@@ -0,0 +1,133 @@
+/*
+* EMSA1
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/emsa1.h>
+#include <botan/exceptn.h>
+#include <botan/pk_keys.h>
+#include <botan/internal/padding.h>
+
+namespace Botan {
+
+namespace {
+
+secure_vector<uint8_t> emsa1_encoding(const secure_vector<uint8_t>& msg,
+ size_t output_bits)
+ {
+ if(8*msg.size() <= output_bits)
+ return msg;
+
+ size_t shift = 8*msg.size() - output_bits;
+
+ size_t byte_shift = shift / 8, bit_shift = shift % 8;
+ secure_vector<uint8_t> digest(msg.size() - byte_shift);
+
+ for(size_t j = 0; j != msg.size() - byte_shift; ++j)
+ digest[j] = msg[j];
+
+ if(bit_shift)
+ {
+ uint8_t carry = 0;
+ for(size_t j = 0; j != digest.size(); ++j)
+ {
+ uint8_t temp = digest[j];
+ digest[j] = (temp >> bit_shift) | carry;
+ carry = (temp << (8 - bit_shift));
+ }
+ }
+ return digest;
+ }
+
+}
+
+std::string EMSA1::name() const
+ {
+ return "EMSA1(" + m_hash->name() + ")";
+ }
+
+EMSA* EMSA1::clone()
+ {
+ return new EMSA1(m_hash->clone());
+ }
+
+void EMSA1::update(const uint8_t input[], size_t length)
+ {
+ m_hash->update(input, length);
+ }
+
+secure_vector<uint8_t> EMSA1::raw_data()
+ {
+ return m_hash->final();
+ }
+
+secure_vector<uint8_t> EMSA1::encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator&)
+ {
+ if(msg.size() != hash_output_length())
+ throw Encoding_Error("EMSA1::encoding_of: Invalid size for input");
+ return emsa1_encoding(msg, output_bits);
+ }
+
+bool EMSA1::verify(const secure_vector<uint8_t>& input,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits)
+ {
+ if(raw.size() != m_hash->output_length())
+ return false;
+
+ // Call emsa1_encoding to handle any required bit shifting
+ const secure_vector<uint8_t> our_coding = emsa1_encoding(raw, key_bits);
+
+ if(our_coding.size() < input.size())
+ return false;
+
+ const size_t offset = our_coding.size() - input.size(); // must be >= 0 per check above
+
+ // If our encoding is longer, all the bytes in it must be zero
+ for(size_t i = 0; i != offset; ++i)
+ if(our_coding[i] != 0)
+ return false;
+
+ return constant_time_compare(input.data(), &our_coding[offset], input.size());
+ }
+
+AlgorithmIdentifier EMSA1::config_for_x509(const Private_Key& key,
+ const std::string& cert_hash_name) const
+ {
+ if(cert_hash_name != m_hash->name())
+ throw Invalid_Argument("Hash function from opts and hash_fn argument"
+ " need to be identical");
+ // check that the signature algorithm and the padding scheme fit
+ if(!sig_algo_and_pad_ok(key.algo_name(), "EMSA1"))
+ {
+ throw Invalid_Argument("Encoding scheme with canonical name EMSA1"
+ " not supported for signature algorithm " + key.algo_name());
+ }
+
+ const OID oid = OID::from_string(key.algo_name() + "/" + name());
+
+ const std::string algo_name = key.algo_name();
+ std::vector<uint8_t> parameters;
+ if(algo_name == "DSA" ||
+ algo_name == "ECDSA" ||
+ algo_name == "ECGDSA" ||
+ algo_name == "ECKCDSA" ||
+ algo_name == "GOST-34.10" ||
+ algo_name == "GOST-34.10-2012-256" ||
+ algo_name == "GOST-34.10-2012-512")
+ {
+ // for DSA, ECDSA, GOST parameters "SHALL" be empty
+ }
+ else
+ {
+ parameters = key.algorithm_identifier().get_parameters();
+ }
+
+ return AlgorithmIdentifier(oid, parameters);
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.h b/comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.h
new file mode 100644
index 0000000000..76736bc276
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.h
@@ -0,0 +1,55 @@
+/*
+* EMSA1
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_EMSA1_H_
+#define BOTAN_EMSA1_H_
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(emsa1.h)
+
+namespace Botan {
+
+/**
+* EMSA1 from IEEE 1363
+* Essentially, sign the hash directly
+*/
+class BOTAN_PUBLIC_API(2,0) EMSA1 final : public EMSA
+ {
+ public:
+ /**
+ * @param hash the hash function to use
+ */
+ explicit EMSA1(HashFunction* hash) : m_hash(hash) {}
+
+ EMSA* clone() override;
+
+ std::string name() const override;
+
+ AlgorithmIdentifier config_for_x509(const Private_Key& key,
+ const std::string& cert_hash_name) const override;
+ private:
+ size_t hash_output_length() const { return m_hash->output_length(); }
+
+ void update(const uint8_t[], size_t) override;
+ secure_vector<uint8_t> raw_data() override;
+
+ secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator& rng) override;
+
+ bool verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits) override;
+
+ std::unique_ptr<HashFunction> m_hash;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa1/info.txt b/comm/third_party/botan/src/lib/pk_pad/emsa1/info.txt
new file mode 100644
index 0000000000..5b5bf1f6b0
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa1/info.txt
@@ -0,0 +1,3 @@
+<defines>
+EMSA1 -> 20131128
+</defines>
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp b/comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp
new file mode 100644
index 0000000000..85556a39ed
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp
@@ -0,0 +1,166 @@
+/*
+* PKCS #1 v1.5 signature padding
+* (C) 1999-2008 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/emsa_pkcs1.h>
+#include <botan/hash_id.h>
+#include <botan/exceptn.h>
+#include <botan/pk_keys.h>
+#include <botan/internal/padding.h>
+
+namespace Botan {
+
+namespace {
+
+secure_vector<uint8_t> emsa3_encoding(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ const uint8_t hash_id[],
+ size_t hash_id_length)
+ {
+ size_t output_length = output_bits / 8;
+ if(output_length < hash_id_length + msg.size() + 10)
+ throw Encoding_Error("emsa3_encoding: Output length is too small");
+
+ secure_vector<uint8_t> T(output_length);
+ const size_t P_LENGTH = output_length - msg.size() - hash_id_length - 2;
+
+ T[0] = 0x01;
+ set_mem(&T[1], P_LENGTH, 0xFF);
+ T[P_LENGTH+1] = 0x00;
+
+ if(hash_id_length > 0)
+ {
+ BOTAN_ASSERT_NONNULL(hash_id);
+ buffer_insert(T, P_LENGTH+2, hash_id, hash_id_length);
+ }
+
+ buffer_insert(T, output_length-msg.size(), msg.data(), msg.size());
+ return T;
+ }
+
+}
+
+void EMSA_PKCS1v15::update(const uint8_t input[], size_t length)
+ {
+ m_hash->update(input, length);
+ }
+
+secure_vector<uint8_t> EMSA_PKCS1v15::raw_data()
+ {
+ return m_hash->final();
+ }
+
+secure_vector<uint8_t>
+EMSA_PKCS1v15::encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator&)
+ {
+ if(msg.size() != m_hash->output_length())
+ throw Encoding_Error("EMSA_PKCS1v15::encoding_of: Bad input length");
+
+ return emsa3_encoding(msg, output_bits,
+ m_hash_id.data(), m_hash_id.size());
+ }
+
+bool EMSA_PKCS1v15::verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits)
+ {
+ if(raw.size() != m_hash->output_length())
+ return false;
+
+ try
+ {
+ return (coded == emsa3_encoding(raw, key_bits,
+ m_hash_id.data(), m_hash_id.size()));
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+AlgorithmIdentifier EMSA_PKCS1v15::config_for_x509(const Private_Key& key,
+ const std::string& cert_hash_name) const
+ {
+ if(cert_hash_name != m_hash->name())
+ throw Invalid_Argument("Hash function from opts and hash_fn argument"
+ " need to be identical");
+ // check that the signature algorithm and the padding scheme fit
+ if(!sig_algo_and_pad_ok(key.algo_name(), "EMSA3"))
+ {
+ throw Invalid_Argument("Encoding scheme with canonical name EMSA3"
+ " not supported for signature algorithm " + key.algo_name());
+ }
+
+ // for RSA PKCSv1.5 parameters "SHALL" be NULL
+
+ const OID oid = OID::from_string(key.algo_name() + "/" + name());
+ return AlgorithmIdentifier(oid, AlgorithmIdentifier::USE_NULL_PARAM);
+ }
+
+EMSA_PKCS1v15::EMSA_PKCS1v15(HashFunction* hash) : m_hash(hash)
+ {
+ m_hash_id = pkcs_hash_id(m_hash->name());
+ }
+
+EMSA_PKCS1v15_Raw::EMSA_PKCS1v15_Raw(const std::string& hash_algo)
+ {
+ if(!hash_algo.empty())
+ {
+ m_hash_id = pkcs_hash_id(hash_algo);
+ std::unique_ptr<HashFunction> hash(HashFunction::create_or_throw(hash_algo));
+ m_hash_name = hash->name();
+ m_hash_output_len = hash->output_length();
+ }
+ else
+ {
+ m_hash_output_len = 0;
+ }
+ }
+
+void EMSA_PKCS1v15_Raw::update(const uint8_t input[], size_t length)
+ {
+ m_message += std::make_pair(input, length);
+ }
+
+secure_vector<uint8_t> EMSA_PKCS1v15_Raw::raw_data()
+ {
+ secure_vector<uint8_t> ret;
+ std::swap(ret, m_message);
+
+ if(m_hash_output_len > 0 && ret.size() != m_hash_output_len)
+ throw Encoding_Error("EMSA_PKCS1v15_Raw::encoding_of: Bad input length");
+
+ return ret;
+ }
+
+secure_vector<uint8_t>
+EMSA_PKCS1v15_Raw::encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator&)
+ {
+ return emsa3_encoding(msg, output_bits, m_hash_id.data(), m_hash_id.size());
+ }
+
+bool EMSA_PKCS1v15_Raw::verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits)
+ {
+ if(m_hash_output_len > 0 && raw.size() != m_hash_output_len)
+ return false;
+
+ try
+ {
+ return (coded == emsa3_encoding(raw, key_bits, m_hash_id.data(), m_hash_id.size()));
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h b/comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h
new file mode 100644
index 0000000000..5b9cf7aea7
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h
@@ -0,0 +1,94 @@
+/*
+* PKCS #1 v1.5 signature padding
+* (C) 1999-2008 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_EMSA_PKCS1_H_
+#define BOTAN_EMSA_PKCS1_H_
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(emsa_pkcs1.h)
+
+namespace Botan {
+
+/**
+* PKCS #1 v1.5 signature padding
+* aka PKCS #1 block type 1
+* aka EMSA3 from IEEE 1363
+*/
+class BOTAN_PUBLIC_API(2,0) EMSA_PKCS1v15 final : public EMSA
+ {
+ public:
+ /**
+ * @param hash the hash function to use
+ */
+ explicit EMSA_PKCS1v15(HashFunction* hash);
+
+ EMSA* clone() override { return new EMSA_PKCS1v15(m_hash->clone()); }
+
+ void update(const uint8_t[], size_t) override;
+
+ secure_vector<uint8_t> raw_data() override;
+
+ secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>&, size_t,
+ RandomNumberGenerator& rng) override;
+
+ bool verify(const secure_vector<uint8_t>&, const secure_vector<uint8_t>&,
+ size_t) override;
+
+ std::string name() const override
+ { return "EMSA3(" + m_hash->name() + ")"; }
+
+ AlgorithmIdentifier config_for_x509(const Private_Key& key,
+ const std::string& cert_hash_name) const override;
+ private:
+ std::unique_ptr<HashFunction> m_hash;
+ std::vector<uint8_t> m_hash_id;
+ };
+
+/**
+* EMSA_PKCS1v15_Raw which is EMSA_PKCS1v15 without a hash or digest id
+* (which according to QCA docs is "identical to PKCS#11's CKM_RSA_PKCS
+* mechanism", something I have not confirmed)
+*/
+class BOTAN_PUBLIC_API(2,0) EMSA_PKCS1v15_Raw final : public EMSA
+ {
+ public:
+ EMSA* clone() override { return new EMSA_PKCS1v15_Raw(); }
+
+ void update(const uint8_t[], size_t) override;
+
+ secure_vector<uint8_t> raw_data() override;
+
+ secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>&, size_t,
+ RandomNumberGenerator& rng) override;
+
+ bool verify(const secure_vector<uint8_t>&, const secure_vector<uint8_t>&,
+ size_t) override;
+
+ /**
+ * @param hash_algo if non-empty, the digest id for that hash is
+ * included in the signature.
+ */
+ EMSA_PKCS1v15_Raw(const std::string& hash_algo = "");
+
+ std::string name() const override
+ {
+ if(m_hash_name.empty()) return "EMSA3(Raw)";
+ else return "EMSA3(Raw," + m_hash_name + ")";
+ }
+
+ private:
+ size_t m_hash_output_len = 0;
+ std::string m_hash_name;
+ std::vector<uint8_t> m_hash_id;
+ secure_vector<uint8_t> m_message;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/info.txt b/comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/info.txt
new file mode 100644
index 0000000000..b70f4e2445
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/info.txt
@@ -0,0 +1,7 @@
+<defines>
+EMSA_PKCS1 -> 20140118
+</defines>
+
+<requires>
+hash_id
+</requires>
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_pssr/info.txt b/comm/third_party/botan/src/lib/pk_pad/emsa_pssr/info.txt
new file mode 100644
index 0000000000..f514936c37
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_pssr/info.txt
@@ -0,0 +1,7 @@
+<defines>
+EMSA_PSSR -> 20131128
+</defines>
+
+<requires>
+mgf1
+</requires>
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.cpp b/comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.cpp
new file mode 100644
index 0000000000..652a7628ba
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.cpp
@@ -0,0 +1,291 @@
+/*
+* PSSR
+* (C) 1999-2007,2017 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/pssr.h>
+#include <botan/exceptn.h>
+#include <botan/rng.h>
+#include <botan/mgf1.h>
+#include <botan/internal/bit_ops.h>
+#include <botan/der_enc.h>
+#include <botan/pk_keys.h>
+#include <botan/internal/padding.h>
+
+namespace Botan {
+
+namespace {
+
+/*
+* PSSR Encode Operation
+*/
+secure_vector<uint8_t> pss_encode(HashFunction& hash,
+ const secure_vector<uint8_t>& msg,
+ const secure_vector<uint8_t>& salt,
+ size_t output_bits)
+ {
+ const size_t HASH_SIZE = hash.output_length();
+ const size_t SALT_SIZE = salt.size();
+
+ if(msg.size() != HASH_SIZE)
+ throw Encoding_Error("Cannot encode PSS string, input length invalid for hash");
+ if(output_bits < 8*HASH_SIZE + 8*SALT_SIZE + 9)
+ throw Encoding_Error("Cannot encode PSS string, output length too small");
+
+ const size_t output_length = (output_bits + 7) / 8;
+
+ for(size_t i = 0; i != 8; ++i)
+ hash.update(0);
+ hash.update(msg);
+ hash.update(salt);
+ secure_vector<uint8_t> H = hash.final();
+
+ secure_vector<uint8_t> EM(output_length);
+
+ EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01;
+ buffer_insert(EM, output_length - 1 - HASH_SIZE - SALT_SIZE, salt);
+ mgf1_mask(hash, H.data(), HASH_SIZE, EM.data(), output_length - HASH_SIZE - 1);
+ EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
+ buffer_insert(EM, output_length - 1 - HASH_SIZE, H);
+ EM[output_length-1] = 0xBC;
+ return EM;
+ }
+
+bool pss_verify(HashFunction& hash,
+ const secure_vector<uint8_t>& pss_repr,
+ const secure_vector<uint8_t>& message_hash,
+ size_t key_bits,
+ size_t* out_salt_size)
+ {
+ const size_t HASH_SIZE = hash.output_length();
+ const size_t KEY_BYTES = (key_bits + 7) / 8;
+
+ if(key_bits < 8*HASH_SIZE + 9)
+ return false;
+
+ if(message_hash.size() != HASH_SIZE)
+ return false;
+
+ if(pss_repr.size() > KEY_BYTES || pss_repr.size() <= 1)
+ return false;
+
+ if(pss_repr[pss_repr.size()-1] != 0xBC)
+ return false;
+
+ secure_vector<uint8_t> coded = pss_repr;
+ if(coded.size() < KEY_BYTES)
+ {
+ secure_vector<uint8_t> temp(KEY_BYTES);
+ buffer_insert(temp, KEY_BYTES - coded.size(), coded);
+ coded = temp;
+ }
+
+ const size_t TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits;
+ if(TOP_BITS > 8 - high_bit(coded[0]))
+ return false;
+
+ uint8_t* DB = coded.data();
+ const size_t DB_size = coded.size() - HASH_SIZE - 1;
+
+ const uint8_t* H = &coded[DB_size];
+ const size_t H_size = HASH_SIZE;
+
+ mgf1_mask(hash, H, H_size, DB, DB_size);
+ DB[0] &= 0xFF >> TOP_BITS;
+
+ size_t salt_offset = 0;
+ for(size_t j = 0; j != DB_size; ++j)
+ {
+ if(DB[j] == 0x01)
+ { salt_offset = j + 1; break; }
+ if(DB[j])
+ return false;
+ }
+ if(salt_offset == 0)
+ return false;
+
+ const size_t salt_size = DB_size - salt_offset;
+
+ for(size_t j = 0; j != 8; ++j)
+ hash.update(0);
+ hash.update(message_hash);
+ hash.update(&DB[salt_offset], salt_size);
+
+ const secure_vector<uint8_t> H2 = hash.final();
+
+ const bool ok = constant_time_compare(H, H2.data(), HASH_SIZE);
+
+ if(out_salt_size && ok)
+ *out_salt_size = salt_size;
+
+ return ok;
+ }
+
+}
+
+PSSR::PSSR(HashFunction* h) :
+ m_hash(h),
+ m_salt_size(m_hash->output_length()),
+ m_required_salt_len(false)
+ {
+ }
+
+PSSR::PSSR(HashFunction* h, size_t salt_size) :
+ m_hash(h),
+ m_salt_size(salt_size),
+ m_required_salt_len(true)
+ {
+ }
+
+/*
+* PSSR Update Operation
+*/
+void PSSR::update(const uint8_t input[], size_t length)
+ {
+ m_hash->update(input, length);
+ }
+
+/*
+* Return the raw (unencoded) data
+*/
+secure_vector<uint8_t> PSSR::raw_data()
+ {
+ return m_hash->final();
+ }
+
+secure_vector<uint8_t> PSSR::encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator& rng)
+ {
+ const secure_vector<uint8_t> salt = rng.random_vec(m_salt_size);
+ return pss_encode(*m_hash, msg, salt, output_bits);
+ }
+
+/*
+* PSSR Decode/Verify Operation
+*/
+bool PSSR::verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits)
+ {
+ size_t salt_size = 0;
+ const bool ok = pss_verify(*m_hash, coded, raw, key_bits, &salt_size);
+
+ if(m_required_salt_len && salt_size != m_salt_size)
+ return false;
+
+ return ok;
+ }
+
+EMSA* PSSR::clone()
+ {
+ return new PSSR(m_hash->clone(), m_salt_size);
+ }
+
+std::string PSSR::name() const
+ {
+ return "EMSA4(" + m_hash->name() + ",MGF1," + std::to_string(m_salt_size) + ")";
+ }
+
+AlgorithmIdentifier PSSR::config_for_x509(const Private_Key& key,
+ const std::string& cert_hash_name) const
+ {
+ if(cert_hash_name != m_hash->name())
+ throw Invalid_Argument("Hash function from opts and hash_fn argument"
+ " need to be identical");
+ // check that the signature algorithm and the padding scheme fit
+ if(!sig_algo_and_pad_ok(key.algo_name(), "EMSA4"))
+ {
+ throw Invalid_Argument("Encoding scheme with canonical name EMSA4"
+ " not supported for signature algorithm " + key.algo_name());
+ }
+
+ const AlgorithmIdentifier hash_id(cert_hash_name, AlgorithmIdentifier::USE_NULL_PARAM);
+ const AlgorithmIdentifier mgf_id("MGF1", hash_id.BER_encode());
+
+ std::vector<uint8_t> parameters;
+ DER_Encoder(parameters)
+ .start_cons(SEQUENCE)
+ .start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).encode(hash_id).end_cons()
+ .start_cons(ASN1_Tag(1), CONTEXT_SPECIFIC).encode(mgf_id).end_cons()
+ .start_cons(ASN1_Tag(2), CONTEXT_SPECIFIC).encode(m_salt_size).end_cons()
+ .start_cons(ASN1_Tag(3), CONTEXT_SPECIFIC).encode(size_t(1)).end_cons() // trailer field
+ .end_cons();
+
+ // hardcoded as RSA is the only valid algorithm for EMSA4 at the moment
+ return AlgorithmIdentifier("RSA/EMSA4", parameters);
+ }
+
+PSSR_Raw::PSSR_Raw(HashFunction* h) :
+ m_hash(h),
+ m_salt_size(m_hash->output_length()),
+ m_required_salt_len(false)
+ {
+ }
+
+PSSR_Raw::PSSR_Raw(HashFunction* h, size_t salt_size) :
+ m_hash(h),
+ m_salt_size(salt_size),
+ m_required_salt_len(true)
+ {
+ }
+
+/*
+* PSSR_Raw Update Operation
+*/
+void PSSR_Raw::update(const uint8_t input[], size_t length)
+ {
+ m_msg.insert(m_msg.end(), input, input + length);
+ }
+
+/*
+* Return the raw (unencoded) data
+*/
+secure_vector<uint8_t> PSSR_Raw::raw_data()
+ {
+ secure_vector<uint8_t> ret;
+ std::swap(ret, m_msg);
+
+ if(ret.size() != m_hash->output_length())
+ throw Encoding_Error("PSSR_Raw Bad input length, did not match hash");
+
+ return ret;
+ }
+
+secure_vector<uint8_t> PSSR_Raw::encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator& rng)
+ {
+ secure_vector<uint8_t> salt = rng.random_vec(m_salt_size);
+ return pss_encode(*m_hash, msg, salt, output_bits);
+ }
+
+/*
+* PSSR_Raw Decode/Verify Operation
+*/
+bool PSSR_Raw::verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits)
+ {
+ size_t salt_size = 0;
+ const bool ok = pss_verify(*m_hash, coded, raw, key_bits, &salt_size);
+
+ if(m_required_salt_len && salt_size != m_salt_size)
+ return false;
+
+ return ok;
+ }
+
+EMSA* PSSR_Raw::clone()
+ {
+ return new PSSR_Raw(m_hash->clone(), m_salt_size);
+ }
+
+std::string PSSR_Raw::name() const
+ {
+ return "PSSR_Raw(" + m_hash->name() + ",MGF1," + std::to_string(m_salt_size) + ")";
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.h b/comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.h
new file mode 100644
index 0000000000..47efacb518
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.h
@@ -0,0 +1,103 @@
+/*
+* PSSR
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PSSR_H_
+#define BOTAN_PSSR_H_
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(pssr.h)
+
+namespace Botan {
+
+/**
+* PSSR (called EMSA4 in IEEE 1363 and in old versions of the library)
+*/
+class BOTAN_PUBLIC_API(2,0) PSSR final : public EMSA
+ {
+ public:
+
+ /**
+ * @param hash the hash function to use
+ */
+ explicit PSSR(HashFunction* hash);
+
+ /**
+ * @param hash the hash function to use
+ * @param salt_size the size of the salt to use in bytes
+ */
+ PSSR(HashFunction* hash, size_t salt_size);
+
+ EMSA* clone() override;
+
+ std::string name() const override;
+
+ AlgorithmIdentifier config_for_x509(const Private_Key& key,
+ const std::string& cert_hash_name) const override;
+ private:
+ void update(const uint8_t input[], size_t length) override;
+
+ secure_vector<uint8_t> raw_data() override;
+
+ secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator& rng) override;
+
+ bool verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits) override;
+
+ std::unique_ptr<HashFunction> m_hash;
+ size_t m_salt_size;
+ bool m_required_salt_len;
+ };
+
+/**
+* PSSR_Raw
+* This accepts a pre-hashed buffer
+*/
+class BOTAN_PUBLIC_API(2,3) PSSR_Raw final : public EMSA
+ {
+ public:
+
+ /**
+ * @param hash the hash function to use
+ */
+ explicit PSSR_Raw(HashFunction* hash);
+
+ /**
+ * @param hash the hash function to use
+ * @param salt_size the size of the salt to use in bytes
+ */
+ PSSR_Raw(HashFunction* hash, size_t salt_size);
+
+ EMSA* clone() override;
+
+ std::string name() const override;
+ private:
+ void update(const uint8_t input[], size_t length) override;
+
+ secure_vector<uint8_t> raw_data() override;
+
+ secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator& rng) override;
+
+ bool verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits) override;
+
+ std::unique_ptr<HashFunction> m_hash;
+ secure_vector<uint8_t> m_msg;
+ size_t m_salt_size;
+ bool m_required_salt_len;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.cpp b/comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.cpp
new file mode 100644
index 0000000000..0ac11dc5ad
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.cpp
@@ -0,0 +1,92 @@
+/*
+* EMSA-Raw
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/emsa_raw.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+std::string EMSA_Raw::name() const
+ {
+ if(m_expected_size > 0)
+ return "Raw(" + std::to_string(m_expected_size) + ")";
+ return "Raw";
+ }
+
+/*
+* EMSA-Raw Encode Operation
+*/
+void EMSA_Raw::update(const uint8_t input[], size_t length)
+ {
+ m_message += std::make_pair(input, length);
+ }
+
+/*
+* Return the raw (unencoded) data
+*/
+secure_vector<uint8_t> EMSA_Raw::raw_data()
+ {
+ if(m_expected_size && m_message.size() != m_expected_size)
+ throw Invalid_Argument("EMSA_Raw was configured to use a " +
+ std::to_string(m_expected_size) +
+ " byte hash but instead was used for a " +
+ std::to_string(m_message.size()) + " hash");
+
+ secure_vector<uint8_t> output;
+ std::swap(m_message, output);
+ return output;
+ }
+
+/*
+* EMSA-Raw Encode Operation
+*/
+secure_vector<uint8_t>
+EMSA_Raw::encoding_of(const secure_vector<uint8_t>& msg,
+ size_t,
+ RandomNumberGenerator&)
+ {
+ if(m_expected_size && msg.size() != m_expected_size)
+ throw Invalid_Argument("EMSA_Raw was configured to use a " +
+ std::to_string(m_expected_size) +
+ " byte hash but instead was used for a " +
+ std::to_string(msg.size()) + " hash");
+
+ return msg;
+ }
+
+/*
+* EMSA-Raw Verify Operation
+*/
+bool EMSA_Raw::verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t)
+ {
+ if(m_expected_size && raw.size() != m_expected_size)
+ return false;
+
+ if(coded.size() == raw.size())
+ return (coded == raw);
+
+ if(coded.size() > raw.size())
+ return false;
+
+ // handle zero padding differences
+ const size_t leading_zeros_expected = raw.size() - coded.size();
+
+ bool same_modulo_leading_zeros = true;
+
+ for(size_t i = 0; i != leading_zeros_expected; ++i)
+ if(raw[i])
+ same_modulo_leading_zeros = false;
+
+ if(!constant_time_compare(coded.data(), raw.data() + leading_zeros_expected, coded.size()))
+ same_modulo_leading_zeros = false;
+
+ return same_modulo_leading_zeros;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.h b/comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.h
new file mode 100644
index 0000000000..dc01b94a2d
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.h
@@ -0,0 +1,47 @@
+/*
+* EMSA-Raw
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_EMSA_RAW_H_
+#define BOTAN_EMSA_RAW_H_
+
+#include <botan/emsa.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(emsa_raw.h)
+
+namespace Botan {
+
+/**
+* EMSA-Raw - sign inputs directly
+* Don't use this unless you know what you are doing.
+*/
+class BOTAN_PUBLIC_API(2,0) EMSA_Raw final : public EMSA
+ {
+ public:
+ EMSA* clone() override { return new EMSA_Raw(); }
+
+ explicit EMSA_Raw(size_t expected_hash_size = 0) :
+ m_expected_size(expected_hash_size) {}
+
+ std::string name() const override;
+ private:
+ void update(const uint8_t[], size_t) override;
+ secure_vector<uint8_t> raw_data() override;
+
+ secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>&, size_t,
+ RandomNumberGenerator&) override;
+
+ bool verify(const secure_vector<uint8_t>&,
+ const secure_vector<uint8_t>&,
+ size_t) override;
+
+ const size_t m_expected_size;
+ secure_vector<uint8_t> m_message;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_raw/info.txt b/comm/third_party/botan/src/lib/pk_pad/emsa_raw/info.txt
new file mode 100644
index 0000000000..ffd3cbe3b3
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_raw/info.txt
@@ -0,0 +1,3 @@
+<defines>
+EMSA_RAW -> 20131128
+</defines>
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.cpp b/comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.cpp
new file mode 100644
index 0000000000..b1f698f86d
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.cpp
@@ -0,0 +1,102 @@
+/*
+* EMSA_X931
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/emsa_x931.h>
+#include <botan/exceptn.h>
+#include <botan/hash_id.h>
+
+namespace Botan {
+
+namespace {
+
+secure_vector<uint8_t> emsa2_encoding(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ const secure_vector<uint8_t>& empty_hash,
+ uint8_t hash_id)
+ {
+ const size_t HASH_SIZE = empty_hash.size();
+
+ size_t output_length = (output_bits + 1) / 8;
+
+ if(msg.size() != HASH_SIZE)
+ throw Encoding_Error("EMSA_X931::encoding_of: Bad input length");
+ if(output_length < HASH_SIZE + 4)
+ throw Encoding_Error("EMSA_X931::encoding_of: Output length is too small");
+
+ const bool empty_input = (msg == empty_hash);
+
+ secure_vector<uint8_t> output(output_length);
+
+ output[0] = (empty_input ? 0x4B : 0x6B);
+ output[output_length - 3 - HASH_SIZE] = 0xBA;
+ set_mem(&output[1], output_length - 4 - HASH_SIZE, 0xBB);
+ buffer_insert(output, output_length - (HASH_SIZE + 2), msg.data(), msg.size());
+ output[output_length-2] = hash_id;
+ output[output_length-1] = 0xCC;
+
+ return output;
+ }
+
+}
+
+std::string EMSA_X931::name() const
+ {
+ return "EMSA2(" + m_hash->name() + ")";
+ }
+
+void EMSA_X931::update(const uint8_t input[], size_t length)
+ {
+ m_hash->update(input, length);
+ }
+
+secure_vector<uint8_t> EMSA_X931::raw_data()
+ {
+ return m_hash->final();
+ }
+
+/*
+* EMSA_X931 Encode Operation
+*/
+secure_vector<uint8_t> EMSA_X931::encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator&)
+ {
+ return emsa2_encoding(msg, output_bits, m_empty_hash, m_hash_id);
+ }
+
+/*
+* EMSA_X931 Verify Operation
+*/
+bool EMSA_X931::verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits)
+ {
+ try
+ {
+ return (coded == emsa2_encoding(raw, key_bits,
+ m_empty_hash, m_hash_id));
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
+
+/*
+* EMSA_X931 Constructor
+*/
+EMSA_X931::EMSA_X931(HashFunction* hash) : m_hash(hash)
+ {
+ m_empty_hash = m_hash->final();
+
+ m_hash_id = ieee1363_hash_id(hash->name());
+
+ if(!m_hash_id)
+ throw Encoding_Error("EMSA_X931 no hash identifier for " + hash->name());
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.h b/comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.h
new file mode 100644
index 0000000000..a2fef0468a
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.h
@@ -0,0 +1,52 @@
+/*
+* X9.31 EMSA
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_EMSA_X931_H_
+#define BOTAN_EMSA_X931_H_
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(emsa_x931.h)
+
+namespace Botan {
+
+/**
+* EMSA from X9.31 (EMSA2 in IEEE 1363)
+* Useful for Rabin-Williams, also sometimes used with RSA in
+* odd protocols.
+*/
+class BOTAN_PUBLIC_API(2,0) EMSA_X931 final : public EMSA
+ {
+ public:
+ /**
+ * @param hash the hash function to use
+ */
+ explicit EMSA_X931(HashFunction* hash);
+
+ EMSA* clone() override { return new EMSA_X931(m_hash->clone()); }
+
+ std::string name() const override;
+
+ private:
+ void update(const uint8_t[], size_t) override;
+ secure_vector<uint8_t> raw_data() override;
+
+ secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>&, size_t,
+ RandomNumberGenerator& rng) override;
+
+ bool verify(const secure_vector<uint8_t>&, const secure_vector<uint8_t>&,
+ size_t) override;
+
+ secure_vector<uint8_t> m_empty_hash;
+ std::unique_ptr<HashFunction> m_hash;
+ uint8_t m_hash_id;
+ };
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/emsa_x931/info.txt b/comm/third_party/botan/src/lib/pk_pad/emsa_x931/info.txt
new file mode 100644
index 0000000000..d3c5ca76ea
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/emsa_x931/info.txt
@@ -0,0 +1,7 @@
+<defines>
+EMSA_X931 -> 20140118
+</defines>
+
+<requires>
+hash_id
+</requires>
diff --git a/comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.cpp b/comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.cpp
new file mode 100644
index 0000000000..ec317f9692
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.cpp
@@ -0,0 +1,163 @@
+/*
+* Hash Function Identification
+* (C) 1999-2008 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/hash_id.h>
+#include <botan/exceptn.h>
+
+namespace Botan {
+
+namespace {
+
+const uint8_t MD5_PKCS_ID[] = {
+0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86,
+0xF7, 0x0D, 0x02, 0x05, 0x05, 0x00, 0x04, 0x10 };
+
+const uint8_t RIPEMD_160_PKCS_ID[] = {
+0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x24, 0x03, 0x02,
+0x01, 0x05, 0x00, 0x04, 0x14 };
+
+const uint8_t SHA_160_PKCS_ID[] = {
+0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02,
+0x1A, 0x05, 0x00, 0x04, 0x14 };
+
+const uint8_t SHA_224_PKCS_ID[] = {
+0x30, 0x2D, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C };
+
+const uint8_t SHA_256_PKCS_ID[] = {
+0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
+
+const uint8_t SHA_384_PKCS_ID[] = {
+0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 };
+
+const uint8_t SHA_512_PKCS_ID[] = {
+0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 };
+
+const uint8_t SHA_512_256_PKCS_ID[] = {
+0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+0x65, 0x03, 0x04, 0x02, 0x06, 0x05, 0x00, 0x04, 0x20 };
+
+const uint8_t SHA3_224_PKCS_ID[] = {
+0x30, 0x2D, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+0x03, 0x04, 0x02, 0x07, 0x05, 0x00, 0x04, 0x1C };
+
+const uint8_t SHA3_256_PKCS_ID[] = {
+0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, 0x20 };
+
+const uint8_t SHA3_384_PKCS_ID[] = {
+0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04, 0x30 };
+
+const uint8_t SHA3_512_PKCS_ID[] = {
+0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
+0x03, 0x04, 0x02, 0x0A, 0x05, 0x00, 0x04, 0x40 };
+
+const uint8_t SM3_PKCS_ID[] = {
+0x30, 0x30, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x81, 0x1C, 0xCF,
+0x55, 0x01, 0x83, 0x11, 0x05, 0x00, 0x04, 0x20,
+};
+
+const uint8_t TIGER_PKCS_ID[] = {
+0x30, 0x29, 0x30, 0x0D, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04,
+0x01, 0xDA, 0x47, 0x0C, 0x02, 0x05, 0x00, 0x04, 0x18 };
+
+}
+
+/*
+* HashID as specified by PKCS
+*/
+std::vector<uint8_t> pkcs_hash_id(const std::string& name)
+ {
+ // Special case for SSL/TLS RSA signatures
+ if(name == "Parallel(MD5,SHA-160)")
+ return std::vector<uint8_t>();
+
+ // If you add a value to this function, also update test_hash_id.cpp
+
+ if(name == "MD5")
+ return std::vector<uint8_t>(MD5_PKCS_ID,
+ MD5_PKCS_ID + sizeof(MD5_PKCS_ID));
+
+ if(name == "RIPEMD-160")
+ return std::vector<uint8_t>(RIPEMD_160_PKCS_ID,
+ RIPEMD_160_PKCS_ID + sizeof(RIPEMD_160_PKCS_ID));
+
+ if(name == "SHA-160" || name == "SHA-1" || name == "SHA1")
+ return std::vector<uint8_t>(SHA_160_PKCS_ID,
+ SHA_160_PKCS_ID + sizeof(SHA_160_PKCS_ID));
+
+ if(name == "SHA-224")
+ return std::vector<uint8_t>(SHA_224_PKCS_ID,
+ SHA_224_PKCS_ID + sizeof(SHA_224_PKCS_ID));
+
+ if(name == "SHA-256")
+ return std::vector<uint8_t>(SHA_256_PKCS_ID,
+ SHA_256_PKCS_ID + sizeof(SHA_256_PKCS_ID));
+
+ if(name == "SHA-384")
+ return std::vector<uint8_t>(SHA_384_PKCS_ID,
+ SHA_384_PKCS_ID + sizeof(SHA_384_PKCS_ID));
+
+ if(name == "SHA-512")
+ return std::vector<uint8_t>(SHA_512_PKCS_ID,
+ SHA_512_PKCS_ID + sizeof(SHA_512_PKCS_ID));
+
+ if(name == "SHA-512-256")
+ return std::vector<uint8_t>(SHA_512_256_PKCS_ID,
+ SHA_512_256_PKCS_ID + sizeof(SHA_512_256_PKCS_ID));
+
+ if(name == "SHA-3(224)")
+ return std::vector<uint8_t>(SHA3_224_PKCS_ID,
+ SHA3_224_PKCS_ID + sizeof(SHA3_224_PKCS_ID));
+
+ if(name == "SHA-3(256)")
+ return std::vector<uint8_t>(SHA3_256_PKCS_ID,
+ SHA3_256_PKCS_ID + sizeof(SHA3_256_PKCS_ID));
+
+ if(name == "SHA-3(384)")
+ return std::vector<uint8_t>(SHA3_384_PKCS_ID,
+ SHA3_384_PKCS_ID + sizeof(SHA3_384_PKCS_ID));
+
+ if(name == "SHA-3(512)")
+ return std::vector<uint8_t>(SHA3_512_PKCS_ID,
+ SHA3_512_PKCS_ID + sizeof(SHA3_512_PKCS_ID));
+
+ if(name == "SM3")
+ return std::vector<uint8_t>(SM3_PKCS_ID, SM3_PKCS_ID + sizeof(SM3_PKCS_ID));
+
+ if(name == "Tiger(24,3)")
+ return std::vector<uint8_t>(TIGER_PKCS_ID,
+ TIGER_PKCS_ID + sizeof(TIGER_PKCS_ID));
+
+ throw Invalid_Argument("No PKCS #1 identifier for " + name);
+ }
+
+/*
+* HashID as specified by IEEE 1363/X9.31
+*/
+uint8_t ieee1363_hash_id(const std::string& name)
+ {
+ if(name == "SHA-160" || name == "SHA-1" || name == "SHA1")
+ return 0x33;
+
+ if(name == "SHA-224") return 0x38;
+ if(name == "SHA-256") return 0x34;
+ if(name == "SHA-384") return 0x36;
+ if(name == "SHA-512") return 0x35;
+
+ if(name == "RIPEMD-160") return 0x31;
+
+ if(name == "Whirlpool") return 0x37;
+
+ return 0;
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.h b/comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.h
new file mode 100644
index 0000000000..75c86c0c65
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.h
@@ -0,0 +1,34 @@
+/*
+* Hash Function Identification
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_HASHID_H_
+#define BOTAN_HASHID_H_
+
+#include <botan/secmem.h>
+#include <string>
+
+namespace Botan {
+
+/**
+* Return the PKCS #1 hash identifier
+* @see RFC 3447 section 9.2
+* @param hash_name the name of the hash function
+* @return uint8_t sequence identifying the hash
+* @throw Invalid_Argument if the hash has no known PKCS #1 hash id
+*/
+BOTAN_PUBLIC_API(2,0) std::vector<uint8_t> pkcs_hash_id(const std::string& hash_name);
+
+/**
+* Return the IEEE 1363 hash identifier
+* @param hash_name the name of the hash function
+* @return uint8_t code identifying the hash, or 0 if not known
+*/
+BOTAN_PUBLIC_API(2,0) uint8_t ieee1363_hash_id(const std::string& hash_name);
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/hash_id/info.txt b/comm/third_party/botan/src/lib/pk_pad/hash_id/info.txt
new file mode 100644
index 0000000000..8cd930a9fe
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/hash_id/info.txt
@@ -0,0 +1,3 @@
+<defines>
+HASH_ID -> 20131128
+</defines>
diff --git a/comm/third_party/botan/src/lib/pk_pad/info.txt b/comm/third_party/botan/src/lib/pk_pad/info.txt
new file mode 100644
index 0000000000..e8fb00c8e3
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/info.txt
@@ -0,0 +1,18 @@
+<defines>
+PK_PADDING -> 20131128
+</defines>
+
+<requires>
+asn1
+rng
+pubkey
+</requires>
+
+<header:internal>
+padding.h
+</header:internal>
+
+<header:public>
+eme.h
+emsa.h
+</header:public>
diff --git a/comm/third_party/botan/src/lib/pk_pad/iso9796/info.txt b/comm/third_party/botan/src/lib/pk_pad/iso9796/info.txt
new file mode 100644
index 0000000000..92bdb3c7d2
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/iso9796/info.txt
@@ -0,0 +1,9 @@
+<defines>
+ISO_9796 -> 20161121
+</defines>
+
+<requires>
+mgf1
+hash_id
+</requires>
+
diff --git a/comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.cpp b/comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.cpp
new file mode 100644
index 0000000000..9fdb87e3b5
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.cpp
@@ -0,0 +1,322 @@
+/*
+ * ISO-9796-2 - Digital signature schemes giving message recovery schemes 2 and 3
+ * (C) 2016 Tobias Niemann, Hackmanit GmbH
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ */
+
+#include <botan/iso9796.h>
+#include <botan/rng.h>
+#include <botan/exceptn.h>
+#include <botan/mgf1.h>
+#include <botan/hash_id.h>
+#include <botan/internal/bit_ops.h>
+#include <botan/internal/ct_utils.h>
+
+namespace Botan {
+
+namespace {
+
+secure_vector<uint8_t> iso9796_encoding(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ std::unique_ptr<HashFunction>& hash,
+ size_t SALT_SIZE,
+ bool implicit,
+ RandomNumberGenerator& rng)
+ {
+ const size_t output_length = (output_bits + 7) / 8;
+
+ //set trailer length
+ size_t tLength = 1;
+ if(!implicit)
+ {
+ tLength = 2;
+ }
+ const size_t HASH_SIZE = hash->output_length();
+
+ if(output_length <= HASH_SIZE + SALT_SIZE + tLength)
+ {
+ throw Encoding_Error("ISO9796-2::encoding_of: Output length is too small");
+ }
+
+ //calculate message capacity
+ const size_t capacity = output_length - HASH_SIZE - SALT_SIZE - tLength - 1;
+
+ //msg1 is the recoverable and msg2 the unrecoverable message part.
+ secure_vector<uint8_t> msg1;
+ secure_vector<uint8_t> msg2;
+ if(msg.size() > capacity)
+ {
+ msg1 = secure_vector<uint8_t>(msg.begin(), msg.begin() + capacity);
+ msg2 = secure_vector<uint8_t>(msg.begin() + capacity, msg.end());
+ hash->update(msg2);
+ }
+ else
+ {
+ msg1 = msg;
+ }
+ msg2 = hash->final();
+
+ //compute H(C||msg1 ||H(msg2)||S)
+ const size_t msgLength = msg1.size();
+ secure_vector<uint8_t> salt = rng.random_vec(SALT_SIZE);
+ hash->update_be(static_cast<uint64_t>(msgLength) * 8);
+ hash->update(msg1);
+ hash->update(msg2);
+ hash->update(salt);
+ secure_vector<uint8_t> H = hash->final();
+
+ secure_vector<uint8_t> EM(output_length);
+
+ //compute message offset.
+ const size_t offset = output_length - HASH_SIZE - SALT_SIZE - tLength - msgLength - 1;
+
+ //insert message border (0x01), msg1 and salt into the output buffer
+ EM[offset] = 0x01;
+ buffer_insert(EM, offset + 1, msg1);
+ buffer_insert(EM, offset + 1 + msgLength, salt);
+
+ //apply mask
+ mgf1_mask(*hash, H.data(), HASH_SIZE, EM.data(),
+ output_length - HASH_SIZE - tLength);
+ buffer_insert(EM, output_length - HASH_SIZE - tLength, H);
+ //set implicit/ISO trailer
+ if(!implicit)
+ {
+ uint8_t hash_id = ieee1363_hash_id(hash->name());
+ if(!hash_id)
+ {
+ throw Encoding_Error("ISO9796-2::encoding_of: no hash identifier for " + hash->name());
+ }
+ EM[output_length - 1] = 0xCC;
+ EM[output_length - 2] = hash_id;
+
+ }
+ else
+ {
+ EM[output_length - 1] = 0xBC;
+ }
+ //clear the leftmost bit (confer bouncy castle)
+ EM[0] &= 0x7F;
+
+ return EM;
+ }
+
+bool iso9796_verification(const secure_vector<uint8_t>& const_coded,
+ const secure_vector<uint8_t>& raw, size_t key_bits, std::unique_ptr<HashFunction>& hash, size_t SALT_SIZE)
+ {
+ const size_t HASH_SIZE = hash->output_length();
+ const size_t KEY_BYTES = (key_bits + 7) / 8;
+
+ if(const_coded.size() != KEY_BYTES)
+ {
+ return false;
+ }
+ //get trailer length
+ size_t tLength;
+ if(const_coded[const_coded.size() - 1] == 0xBC)
+ {
+ tLength = 1;
+ }
+ else
+ {
+ uint8_t hash_id = ieee1363_hash_id(hash->name());
+ if((!const_coded[const_coded.size() - 2]) || (const_coded[const_coded.size() - 2] != hash_id) ||
+ (const_coded[const_coded.size() - 1] != 0xCC))
+ {
+ return false; //in case of wrong ISO trailer.
+ }
+ tLength = 2;
+ }
+
+ secure_vector<uint8_t> coded = const_coded;
+
+ CT::poison(coded.data(), coded.size());
+ //remove mask
+ uint8_t* DB = coded.data();
+ const size_t DB_size = coded.size() - HASH_SIZE - tLength;
+
+ const uint8_t* H = &coded[DB_size];
+
+ mgf1_mask(*hash, H, HASH_SIZE, DB, DB_size);
+ //clear the leftmost bit (confer bouncy castle)
+ DB[0] &= 0x7F;
+
+ //recover msg1 and salt
+ size_t msg1_offset = 1;
+
+ auto waiting_for_delim = CT::Mask<uint8_t>::set();
+ auto bad_input = CT::Mask<uint8_t>::cleared();
+
+ for(size_t j = 0; j < DB_size; ++j)
+ {
+ const auto is_zero = CT::Mask<uint8_t>::is_zero(DB[j]);
+ const auto is_one = CT::Mask<uint8_t>::is_equal(DB[j], 0x01);
+
+ const auto add_m = waiting_for_delim & is_zero;
+
+ bad_input |= waiting_for_delim & ~(is_zero | is_one);
+ msg1_offset += add_m.if_set_return(1);
+
+ waiting_for_delim &= is_zero;
+ }
+
+ //invalid, if delimiter 0x01 was not found or msg1_offset is too big
+ bad_input |= waiting_for_delim;
+ bad_input |= CT::Mask<size_t>::is_lt(coded.size(), tLength + HASH_SIZE + msg1_offset + SALT_SIZE);
+
+ //in case that msg1_offset is too big, just continue with offset = 0.
+ msg1_offset = CT::Mask<size_t>::expand(bad_input.value()).if_not_set_return(msg1_offset);
+
+ CT::unpoison(coded.data(), coded.size());
+ CT::unpoison(msg1_offset);
+
+ secure_vector<uint8_t> msg1(coded.begin() + msg1_offset,
+ coded.end() - tLength - HASH_SIZE - SALT_SIZE);
+ secure_vector<uint8_t> salt(coded.begin() + msg1_offset + msg1.size(),
+ coded.end() - tLength - HASH_SIZE);
+
+ //compute H2(C||msg1||H(msg2)||S*). * indicates a recovered value
+ const size_t capacity = (key_bits - 2 + 7) / 8 - HASH_SIZE - SALT_SIZE - tLength - 1;
+ secure_vector<uint8_t> msg1raw;
+ secure_vector<uint8_t> msg2;
+ if(raw.size() > capacity)
+ {
+ msg1raw = secure_vector<uint8_t> (raw.begin(), raw.begin() + capacity);
+ msg2 = secure_vector<uint8_t> (raw.begin() + capacity, raw.end());
+ hash->update(msg2);
+ }
+ else
+ {
+ msg1raw = raw;
+ }
+ msg2 = hash->final();
+
+ const uint64_t msg1rawLength = msg1raw.size();
+ hash->update_be(msg1rawLength * 8);
+ hash->update(msg1raw);
+ hash->update(msg2);
+ hash->update(salt);
+ secure_vector<uint8_t> H3 = hash->final();
+
+ //compute H3(C*||msg1*||H(msg2)||S*) * indicates a recovered value
+ const uint64_t msgLength = msg1.size();
+ hash->update_be(msgLength * 8);
+ hash->update(msg1);
+ hash->update(msg2);
+ hash->update(salt);
+ secure_vector<uint8_t> H2 = hash->final();
+
+ //check if H3 == H2
+ bad_input |= CT::Mask<uint8_t>::is_zero(ct_compare_u8(H3.data(), H2.data(), HASH_SIZE));
+
+ CT::unpoison(bad_input);
+ return (bad_input.is_set() == false);
+ }
+
+}
+
+EMSA* ISO_9796_DS2::clone()
+ {
+ return new ISO_9796_DS2(m_hash->clone(), m_implicit, m_SALT_SIZE);
+ }
+
+/*
+ * ISO-9796-2 signature scheme 2
+ * DS 2 is probabilistic
+ */
+void ISO_9796_DS2::update(const uint8_t input[], size_t length)
+ {
+ //need to buffer message completely, before digest
+ m_msg_buffer.insert(m_msg_buffer.end(), input, input+length);
+ }
+
+/*
+ * Return the raw (unencoded) data
+ */
+secure_vector<uint8_t> ISO_9796_DS2::raw_data()
+ {
+ secure_vector<uint8_t> retbuffer = m_msg_buffer;
+ m_msg_buffer.clear();
+ return retbuffer;
+ }
+
+/*
+ * ISO-9796-2 scheme 2 encode operation
+ */
+secure_vector<uint8_t> ISO_9796_DS2::encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator& rng)
+ {
+ return iso9796_encoding(msg, output_bits, m_hash, m_SALT_SIZE, m_implicit, rng);
+ }
+
+/*
+ * ISO-9796-2 scheme 2 verify operation
+ */
+bool ISO_9796_DS2::verify(const secure_vector<uint8_t>& const_coded,
+ const secure_vector<uint8_t>& raw, size_t key_bits)
+ {
+ return iso9796_verification(const_coded, raw, key_bits, m_hash, m_SALT_SIZE);
+ }
+
+/*
+ * Return the SCAN name
+ */
+std::string ISO_9796_DS2::name() const
+ {
+ return "ISO_9796_DS2(" + m_hash->name() + ","
+ + (m_implicit ? "imp" : "exp") + "," + std::to_string(m_SALT_SIZE) + ")";
+ }
+
+EMSA* ISO_9796_DS3::clone()
+ {
+ return new ISO_9796_DS3(m_hash->clone(), m_implicit);
+ }
+
+/*
+ * ISO-9796-2 signature scheme 3
+ * DS 3 is deterministic and equals DS2 without salt
+ */
+void ISO_9796_DS3::update(const uint8_t input[], size_t length)
+ {
+ //need to buffer message completely, before digest
+ m_msg_buffer.insert(m_msg_buffer.end(), input, input+length);
+ }
+
+/*
+ * Return the raw (unencoded) data
+ */
+secure_vector<uint8_t> ISO_9796_DS3::raw_data()
+ {
+ secure_vector<uint8_t> retbuffer = m_msg_buffer;
+ m_msg_buffer.clear();
+ return retbuffer;
+ }
+
+/*
+ * ISO-9796-2 scheme 3 encode operation
+ */
+secure_vector<uint8_t> ISO_9796_DS3::encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits, RandomNumberGenerator& rng)
+ {
+ return iso9796_encoding(msg, output_bits, m_hash, 0, m_implicit, rng);
+ }
+
+/*
+ * ISO-9796-2 scheme 3 verify operation
+ */
+bool ISO_9796_DS3::verify(const secure_vector<uint8_t>& const_coded,
+ const secure_vector<uint8_t>& raw, size_t key_bits)
+ {
+ return iso9796_verification(const_coded, raw, key_bits, m_hash, 0);
+ }
+/*
+ * Return the SCAN name
+ */
+std::string ISO_9796_DS3::name() const
+ {
+ return "ISO_9796_DS3(" + m_hash->name() + "," +
+ (m_implicit ? "imp" : "exp") + ")";
+ }
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.h b/comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.h
new file mode 100644
index 0000000000..9782e53b23
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.h
@@ -0,0 +1,98 @@
+/*
+ * ISO-9796-2 - Digital signature schemes giving message recovery schemes 2 and 3
+ * (C) 2016 Tobias Niemann, Hackmanit GmbH
+ *
+ * Botan is released under the Simplified BSD License (see license.txt)
+ */
+
+#ifndef BOTAN_ISO9796_H_
+#define BOTAN_ISO9796_H_
+
+#include <botan/emsa.h>
+#include <botan/hash.h>
+
+BOTAN_FUTURE_INTERNAL_HEADER(iso9796.h)
+
+namespace Botan {
+
+/**
+* ISO-9796-2 - Digital signature scheme 2 (probabilistic)
+*/
+class BOTAN_PUBLIC_API(2,0) ISO_9796_DS2 final : public EMSA
+ {
+ public:
+ /**
+ * @param hash function to use
+ * @param implicit whether or not the trailer is implicit
+ */
+ explicit ISO_9796_DS2(HashFunction* hash, bool implicit = false) : m_hash(hash), m_implicit(implicit),
+ m_SALT_SIZE(hash->output_length()) {}
+
+ /**
+ * @param hash function to use
+ * @param implicit whether or not the trailer is implicit
+ * @param salt_size size of the salt to use in bytes
+ */
+ ISO_9796_DS2(HashFunction* hash, bool implicit, size_t salt_size) : m_hash(hash), m_implicit(implicit),
+ m_SALT_SIZE(salt_size) {}
+
+ EMSA* clone() override;
+
+ std::string name() const override;
+ private:
+ void update(const uint8_t input[], size_t length) override;
+
+ secure_vector<uint8_t> raw_data() override;
+
+ secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator& rng) override;
+
+ bool verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits) override;
+
+ std::unique_ptr<HashFunction> m_hash;
+ bool m_implicit;
+ size_t m_SALT_SIZE;
+ secure_vector<uint8_t> m_msg_buffer;
+ };
+
+/**
+* ISO-9796-2 - Digital signature scheme 3 (deterministic)
+*/
+class BOTAN_PUBLIC_API(2,0) ISO_9796_DS3 final : public EMSA
+ {
+ public:
+ /**
+ * @param hash function to use
+ * @param implicit whether or not the trailer is implicit
+ */
+ ISO_9796_DS3(HashFunction* hash, bool implicit = false) : m_hash(hash), m_implicit(implicit)
+ {}
+
+ EMSA* clone() override;
+
+ std::string name() const override;
+ private:
+ void update(const uint8_t input[], size_t length) override;
+
+ secure_vector<uint8_t> raw_data() override;
+
+ secure_vector<uint8_t> encoding_of(const secure_vector<uint8_t>& msg,
+ size_t output_bits,
+ RandomNumberGenerator& rng) override;
+
+ bool verify(const secure_vector<uint8_t>& coded,
+ const secure_vector<uint8_t>& raw,
+ size_t key_bits) override;
+
+ std::unique_ptr<HashFunction> m_hash;
+ bool m_implicit;
+ secure_vector<uint8_t> m_msg_buffer;
+ };
+
+}
+
+#endif
+
diff --git a/comm/third_party/botan/src/lib/pk_pad/mgf1/info.txt b/comm/third_party/botan/src/lib/pk_pad/mgf1/info.txt
new file mode 100644
index 0000000000..f17c72fda4
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/mgf1/info.txt
@@ -0,0 +1,3 @@
+<defines>
+MGF1 -> 20140118
+</defines>
diff --git a/comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.cpp b/comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.cpp
new file mode 100644
index 0000000000..2e7ef99734
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.cpp
@@ -0,0 +1,36 @@
+/*
+* MGF1
+* (C) 1999-2007 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/mgf1.h>
+#include <botan/hash.h>
+#include <algorithm>
+
+namespace Botan {
+
+void mgf1_mask(HashFunction& hash,
+ const uint8_t in[], size_t in_len,
+ uint8_t out[], size_t out_len)
+ {
+ uint32_t counter = 0;
+
+ secure_vector<uint8_t> buffer(hash.output_length());
+ while(out_len)
+ {
+ hash.update(in, in_len);
+ hash.update_be(counter);
+ hash.final(buffer.data());
+
+ const size_t xored = std::min<size_t>(buffer.size(), out_len);
+ xor_buf(out, buffer.data(), xored);
+ out += xored;
+ out_len -= xored;
+
+ ++counter;
+ }
+ }
+
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.h b/comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.h
new file mode 100644
index 0000000000..9eb652a825
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.h
@@ -0,0 +1,31 @@
+/*
+* MGF1
+* (C) 1999-2007,2014 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_MGF1_H_
+#define BOTAN_MGF1_H_
+
+#include <botan/types.h>
+
+namespace Botan {
+
+class HashFunction;
+
+/**
+* MGF1 from PKCS #1 v2.0
+* @param hash hash function to use
+* @param in input buffer
+* @param in_len size of the input buffer in bytes
+* @param out output buffer
+* @param out_len size of the output buffer in bytes
+*/
+void BOTAN_PUBLIC_API(2,0) mgf1_mask(HashFunction& hash,
+ const uint8_t in[], size_t in_len,
+ uint8_t out[], size_t out_len);
+
+}
+
+#endif
diff --git a/comm/third_party/botan/src/lib/pk_pad/padding.cpp b/comm/third_party/botan/src/lib/pk_pad/padding.cpp
new file mode 100644
index 0000000000..bac3fcd7eb
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/padding.cpp
@@ -0,0 +1,44 @@
+/*
+* Sets of allowed padding schemes for public key types
+*
+* This file was automatically generated by ./src/scripts/oids.py on 2017-12-20
+*
+* All manual edits to this file will be lost. Edit the script
+* then regenerate this source file.
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/internal/padding.h>
+#include <map>
+#include <vector>
+#include <string>
+#include <algorithm>
+
+namespace Botan {
+
+const std::map<const std::string, std::vector<std::string>> allowed_signature_paddings =
+ {
+ { "DSA", {"EMSA1"} },
+ { "ECDSA", {"EMSA1"} },
+ { "ECGDSA", {"EMSA1"} },
+ { "ECKCDSA", {"EMSA1"} },
+ { "GOST-34.10", {"EMSA1"} },
+ { "GOST-34.10-2012-256", {"EMSA1"} },
+ { "GOST-34.10-2012-512", {"EMSA1"} },
+ { "RSA", {"EMSA4", "EMSA3"} },
+ };
+
+const std::vector<std::string> get_sig_paddings(const std::string algo)
+ {
+ if(allowed_signature_paddings.count(algo) > 0)
+ return allowed_signature_paddings.at(algo);
+ return {};
+ }
+
+bool sig_algo_and_pad_ok(const std::string algo, const std::string padding)
+ {
+ std::vector<std::string> pads = get_sig_paddings(algo);
+ return std::find(pads.begin(), pads.end(), padding) != pads.end();
+ }
+}
diff --git a/comm/third_party/botan/src/lib/pk_pad/padding.h b/comm/third_party/botan/src/lib/pk_pad/padding.h
new file mode 100644
index 0000000000..ed05ec3819
--- /dev/null
+++ b/comm/third_party/botan/src/lib/pk_pad/padding.h
@@ -0,0 +1,36 @@
+/*
+* (C) 2017 Fabian Weissberg, Rohde & Schwarz Cybersecurity
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_PADDING_H_
+#define BOTAN_PADDING_H_
+
+#include <botan/build.h>
+#include <string>
+#include <vector>
+
+namespace Botan {
+
+/**
+* Returns the allowed padding schemes when using the given
+* algorithm (key type) for creating digital signatures.
+*
+* @param algo the algorithm for which to look up supported padding schemes
+* @return a vector of supported padding schemes
+*/
+BOTAN_TEST_API const std::vector<std::string> get_sig_paddings(const std::string algo);
+
+/**
+* Returns true iff the given padding scheme is valid for the given
+* signature algorithm (key type).
+*
+* @param algo the signature algorithm to be used
+* @param padding the padding scheme to be used
+*/
+bool sig_algo_and_pad_ok(const std::string algo, const std::string padding);
+
+}
+
+#endif