From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- comm/third_party/botan/src/lib/pk_pad/eme.cpp | 94 ++++++ comm/third_party/botan/src/lib/pk_pad/eme.h | 94 ++++++ .../botan/src/lib/pk_pad/eme_oaep/info.txt | 7 + .../botan/src/lib/pk_pad/eme_oaep/oaep.cpp | 168 +++++++++++ .../botan/src/lib/pk_pad/eme_oaep/oaep.h | 62 ++++ .../botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp | 109 +++++++ .../botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.h | 35 +++ .../botan/src/lib/pk_pad/eme_pkcs1/info.txt | 4 + .../botan/src/lib/pk_pad/eme_raw/eme_raw.cpp | 31 ++ .../botan/src/lib/pk_pad/eme_raw/eme_raw.h | 33 +++ .../botan/src/lib/pk_pad/eme_raw/info.txt | 3 + comm/third_party/botan/src/lib/pk_pad/emsa.cpp | 207 +++++++++++++ comm/third_party/botan/src/lib/pk_pad/emsa.h | 107 +++++++ .../botan/src/lib/pk_pad/emsa1/emsa1.cpp | 133 +++++++++ .../third_party/botan/src/lib/pk_pad/emsa1/emsa1.h | 55 ++++ .../botan/src/lib/pk_pad/emsa1/info.txt | 3 + .../botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp | 166 +++++++++++ .../botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h | 94 ++++++ .../botan/src/lib/pk_pad/emsa_pkcs1/info.txt | 7 + .../botan/src/lib/pk_pad/emsa_pssr/info.txt | 7 + .../botan/src/lib/pk_pad/emsa_pssr/pssr.cpp | 291 +++++++++++++++++++ .../botan/src/lib/pk_pad/emsa_pssr/pssr.h | 103 +++++++ .../botan/src/lib/pk_pad/emsa_raw/emsa_raw.cpp | 92 ++++++ .../botan/src/lib/pk_pad/emsa_raw/emsa_raw.h | 47 +++ .../botan/src/lib/pk_pad/emsa_raw/info.txt | 3 + .../botan/src/lib/pk_pad/emsa_x931/emsa_x931.cpp | 102 +++++++ .../botan/src/lib/pk_pad/emsa_x931/emsa_x931.h | 52 ++++ .../botan/src/lib/pk_pad/emsa_x931/info.txt | 7 + .../botan/src/lib/pk_pad/hash_id/hash_id.cpp | 163 +++++++++++ .../botan/src/lib/pk_pad/hash_id/hash_id.h | 34 +++ .../botan/src/lib/pk_pad/hash_id/info.txt | 3 + comm/third_party/botan/src/lib/pk_pad/info.txt | 18 ++ .../botan/src/lib/pk_pad/iso9796/info.txt | 9 + .../botan/src/lib/pk_pad/iso9796/iso9796.cpp | 322 +++++++++++++++++++++ .../botan/src/lib/pk_pad/iso9796/iso9796.h | 98 +++++++ .../third_party/botan/src/lib/pk_pad/mgf1/info.txt | 3 + .../third_party/botan/src/lib/pk_pad/mgf1/mgf1.cpp | 36 +++ comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.h | 31 ++ comm/third_party/botan/src/lib/pk_pad/padding.cpp | 44 +++ comm/third_party/botan/src/lib/pk_pad/padding.h | 36 +++ 40 files changed, 2913 insertions(+) create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme_oaep/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme_oaep/oaep.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/eme_pkcs.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme_pkcs1/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme_raw/eme_raw.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/eme_raw/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa1/emsa1.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa1/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/emsa_pkcs1.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_pkcs1/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_pssr/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_pssr/pssr.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_raw/emsa_raw.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_raw/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_x931/emsa_x931.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/emsa_x931/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/hash_id/hash_id.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/hash_id/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/iso9796/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/iso9796/iso9796.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/mgf1/info.txt create mode 100644 comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/mgf1/mgf1.h create mode 100644 comm/third_party/botan/src/lib/pk_pad/padding.cpp create mode 100644 comm/third_party/botan/src/lib/pk_pad/padding.h (limited to 'comm/third_party/botan/src/lib/pk_pad') 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 +#include +#include +#include + +#if defined(BOTAN_HAS_EME_OAEP) +#include +#endif + +#if defined(BOTAN_HAS_EME_PKCS1) +#include +#endif + +#if defined(BOTAN_HAS_EME_RAW) +#include +#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 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 EME::encode(const secure_vector& 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 +#include + +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 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 encode(const secure_vector& 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 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 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 @@ + +EME_OAEP -> 20180305 + + + +mgf1 + 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 +#include +#include +#include +#include + +namespace Botan { + +/* +* OAEP Pad Operation +*/ +secure_vector 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 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 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::is_zero(in[0]); + + secure_vector 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 +oaep_find_delim(uint8_t& valid_mask, + const uint8_t input[], size_t input_len, + const secure_vector& Phash) + { + const size_t hlen = Phash.size(); + + // Too short to be valid, reject immediately + if(input_len < 1 + 2*hlen) + { + return secure_vector(); + } + + CT::poison(input, input_len); + + size_t delim_idx = 2 * hlen; + CT::Mask waiting_for_delim = CT::Mask::set(); + CT::Mask bad_input_m = CT::Mask::cleared(); + + for(size_t i = delim_idx; i < input_len; ++i) + { + const auto zero_m = CT::Mask::is_zero(input[i]); + const auto one_m = CT::Mask::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::is_zero(ct_compare_u8(&input[hlen], Phash.data(), hlen)); + + delim_idx += 1; + + valid_mask = (~bad_input_m).unpoisoned_value(); + const secure_vector 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 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 +#include + +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 pad(const uint8_t in[], + size_t in_length, + size_t key_length, + RandomNumberGenerator& rng) const override; + + secure_vector unpad(uint8_t& valid_mask, + const uint8_t in[], + size_t in_len) const override; + + secure_vector m_Phash; + std::unique_ptr m_mgf1_hash; + }; + +secure_vector +BOTAN_TEST_API oaep_find_delim(uint8_t& valid_mask, + const uint8_t input[], size_t input_len, + const secure_vector& 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 +#include +#include +#include + +namespace Botan { + +/* +* PKCS1 Pad Operation +*/ +secure_vector 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 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 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(); + } + + CT::poison(in, inlen); + + CT::Mask bad_input_m = CT::Mask::cleared(); + CT::Mask seen_zero_m = CT::Mask::cleared(); + size_t delim_idx = 2; // initial 0002 + + bad_input_m |= ~CT::Mask::is_equal(in[0], 0); + bad_input_m |= ~CT::Mask::is_equal(in[1], 2); + + for(size_t i = 2; i < inlen; ++i) + { + const auto is_zero_m = CT::Mask::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(CT::Mask::is_lt(delim_idx, 11)); + + valid_mask = (~bad_input_m).unpoisoned_value(); + const secure_vector 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_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 pad(const uint8_t[], size_t, size_t, + RandomNumberGenerator&) const override; + + secure_vector 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 @@ + +EME_PKCS1v15 -> 20131128 +EME_PKCS1 -> 20190426 + 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 +#include +#include + +namespace Botan { + +secure_vector EME_Raw::pad(const uint8_t in[], size_t in_length, + size_t, + RandomNumberGenerator&) const + { + return secure_vector(in, in + in_length); + } + +secure_vector 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_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 pad(const uint8_t[], size_t, size_t, + RandomNumberGenerator&) const override; + + secure_vector 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 @@ + +EME_RAW -> 20150313 + 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 +#include +#include +#include + +#if defined(BOTAN_HAS_EMSA1) + #include +#endif + +#if defined(BOTAN_HAS_EMSA_X931) + #include +#endif + +#if defined(BOTAN_HAS_EMSA_PKCS1) + #include +#endif + +#if defined(BOTAN_HAS_EMSA_PSSR) + #include +#endif + +#if defined(BOTAN_HAS_EMSA_RAW) + #include +#endif + +#if defined(BOTAN_HAS_ISO_9796) + #include +#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 +#include +#include + +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 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 encoding_of(const secure_vector& 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& coded, + const secure_vector& 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 +#include +#include +#include + +namespace Botan { + +namespace { + +secure_vector emsa1_encoding(const secure_vector& 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 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 EMSA1::raw_data() + { + return m_hash->final(); + } + +secure_vector EMSA1::encoding_of(const secure_vector& 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& input, + const secure_vector& 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 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 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 +#include + +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 raw_data() override; + + secure_vector encoding_of(const secure_vector& msg, + size_t output_bits, + RandomNumberGenerator& rng) override; + + bool verify(const secure_vector& coded, + const secure_vector& raw, + size_t key_bits) override; + + std::unique_ptr 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 @@ + +EMSA1 -> 20131128 + 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 +#include +#include +#include +#include + +namespace Botan { + +namespace { + +secure_vector emsa3_encoding(const secure_vector& 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 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 EMSA_PKCS1v15::raw_data() + { + return m_hash->final(); + } + +secure_vector +EMSA_PKCS1v15::encoding_of(const secure_vector& 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& coded, + const secure_vector& 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 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 EMSA_PKCS1v15_Raw::raw_data() + { + secure_vector 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 +EMSA_PKCS1v15_Raw::encoding_of(const secure_vector& 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& coded, + const secure_vector& 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 +#include + +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 raw_data() override; + + secure_vector encoding_of(const secure_vector&, size_t, + RandomNumberGenerator& rng) override; + + bool verify(const secure_vector&, const secure_vector&, + 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 m_hash; + std::vector 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 raw_data() override; + + secure_vector encoding_of(const secure_vector&, size_t, + RandomNumberGenerator& rng) override; + + bool verify(const secure_vector&, const secure_vector&, + 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 m_hash_id; + secure_vector 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 @@ + +EMSA_PKCS1 -> 20140118 + + + +hash_id + 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 @@ + +EMSA_PSSR -> 20131128 + + + +mgf1 + 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 +#include +#include +#include +#include +#include +#include +#include + +namespace Botan { + +namespace { + +/* +* PSSR Encode Operation +*/ +secure_vector pss_encode(HashFunction& hash, + const secure_vector& msg, + const secure_vector& 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 H = hash.final(); + + secure_vector 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& pss_repr, + const secure_vector& 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 coded = pss_repr; + if(coded.size() < KEY_BYTES) + { + secure_vector 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 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 PSSR::raw_data() + { + return m_hash->final(); + } + +secure_vector PSSR::encoding_of(const secure_vector& msg, + size_t output_bits, + RandomNumberGenerator& rng) + { + const secure_vector 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& coded, + const secure_vector& 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 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 PSSR_Raw::raw_data() + { + secure_vector 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 PSSR_Raw::encoding_of(const secure_vector& msg, + size_t output_bits, + RandomNumberGenerator& rng) + { + secure_vector 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& coded, + const secure_vector& 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 +#include + +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 raw_data() override; + + secure_vector encoding_of(const secure_vector& msg, + size_t output_bits, + RandomNumberGenerator& rng) override; + + bool verify(const secure_vector& coded, + const secure_vector& raw, + size_t key_bits) override; + + std::unique_ptr 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 raw_data() override; + + secure_vector encoding_of(const secure_vector& msg, + size_t output_bits, + RandomNumberGenerator& rng) override; + + bool verify(const secure_vector& coded, + const secure_vector& raw, + size_t key_bits) override; + + std::unique_ptr m_hash; + secure_vector 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 +#include + +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 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 output; + std::swap(m_message, output); + return output; + } + +/* +* EMSA-Raw Encode Operation +*/ +secure_vector +EMSA_Raw::encoding_of(const secure_vector& 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& coded, + const secure_vector& 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_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 raw_data() override; + + secure_vector encoding_of(const secure_vector&, size_t, + RandomNumberGenerator&) override; + + bool verify(const secure_vector&, + const secure_vector&, + size_t) override; + + const size_t m_expected_size; + secure_vector 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 @@ + +EMSA_RAW -> 20131128 + 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 +#include +#include + +namespace Botan { + +namespace { + +secure_vector emsa2_encoding(const secure_vector& msg, + size_t output_bits, + const secure_vector& 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 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 EMSA_X931::raw_data() + { + return m_hash->final(); + } + +/* +* EMSA_X931 Encode Operation +*/ +secure_vector EMSA_X931::encoding_of(const secure_vector& 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& coded, + const secure_vector& 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 +#include + +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 raw_data() override; + + secure_vector encoding_of(const secure_vector&, size_t, + RandomNumberGenerator& rng) override; + + bool verify(const secure_vector&, const secure_vector&, + size_t) override; + + secure_vector m_empty_hash; + std::unique_ptr 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 @@ + +EMSA_X931 -> 20140118 + + + +hash_id + 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 +#include + +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 pkcs_hash_id(const std::string& name) + { + // Special case for SSL/TLS RSA signatures + if(name == "Parallel(MD5,SHA-160)") + return std::vector(); + + // If you add a value to this function, also update test_hash_id.cpp + + if(name == "MD5") + return std::vector(MD5_PKCS_ID, + MD5_PKCS_ID + sizeof(MD5_PKCS_ID)); + + if(name == "RIPEMD-160") + return std::vector(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(SHA_160_PKCS_ID, + SHA_160_PKCS_ID + sizeof(SHA_160_PKCS_ID)); + + if(name == "SHA-224") + return std::vector(SHA_224_PKCS_ID, + SHA_224_PKCS_ID + sizeof(SHA_224_PKCS_ID)); + + if(name == "SHA-256") + return std::vector(SHA_256_PKCS_ID, + SHA_256_PKCS_ID + sizeof(SHA_256_PKCS_ID)); + + if(name == "SHA-384") + return std::vector(SHA_384_PKCS_ID, + SHA_384_PKCS_ID + sizeof(SHA_384_PKCS_ID)); + + if(name == "SHA-512") + return std::vector(SHA_512_PKCS_ID, + SHA_512_PKCS_ID + sizeof(SHA_512_PKCS_ID)); + + if(name == "SHA-512-256") + return std::vector(SHA_512_256_PKCS_ID, + SHA_512_256_PKCS_ID + sizeof(SHA_512_256_PKCS_ID)); + + if(name == "SHA-3(224)") + return std::vector(SHA3_224_PKCS_ID, + SHA3_224_PKCS_ID + sizeof(SHA3_224_PKCS_ID)); + + if(name == "SHA-3(256)") + return std::vector(SHA3_256_PKCS_ID, + SHA3_256_PKCS_ID + sizeof(SHA3_256_PKCS_ID)); + + if(name == "SHA-3(384)") + return std::vector(SHA3_384_PKCS_ID, + SHA3_384_PKCS_ID + sizeof(SHA3_384_PKCS_ID)); + + if(name == "SHA-3(512)") + return std::vector(SHA3_512_PKCS_ID, + SHA3_512_PKCS_ID + sizeof(SHA3_512_PKCS_ID)); + + if(name == "SM3") + return std::vector(SM3_PKCS_ID, SM3_PKCS_ID + sizeof(SM3_PKCS_ID)); + + if(name == "Tiger(24,3)") + return std::vector(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 +#include + +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 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 @@ + +HASH_ID -> 20131128 + 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 @@ + +PK_PADDING -> 20131128 + + + +asn1 +rng +pubkey + + + +padding.h + + + +eme.h +emsa.h + 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 @@ + +ISO_9796 -> 20161121 + + + +mgf1 +hash_id + + 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 +#include +#include +#include +#include +#include +#include + +namespace Botan { + +namespace { + +secure_vector iso9796_encoding(const secure_vector& msg, + size_t output_bits, + std::unique_ptr& 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 msg1; + secure_vector msg2; + if(msg.size() > capacity) + { + msg1 = secure_vector(msg.begin(), msg.begin() + capacity); + msg2 = secure_vector(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 salt = rng.random_vec(SALT_SIZE); + hash->update_be(static_cast(msgLength) * 8); + hash->update(msg1); + hash->update(msg2); + hash->update(salt); + secure_vector H = hash->final(); + + secure_vector 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& const_coded, + const secure_vector& raw, size_t key_bits, std::unique_ptr& 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 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::set(); + auto bad_input = CT::Mask::cleared(); + + for(size_t j = 0; j < DB_size; ++j) + { + const auto is_zero = CT::Mask::is_zero(DB[j]); + const auto is_one = CT::Mask::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::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::expand(bad_input.value()).if_not_set_return(msg1_offset); + + CT::unpoison(coded.data(), coded.size()); + CT::unpoison(msg1_offset); + + secure_vector msg1(coded.begin() + msg1_offset, + coded.end() - tLength - HASH_SIZE - SALT_SIZE); + secure_vector 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 msg1raw; + secure_vector msg2; + if(raw.size() > capacity) + { + msg1raw = secure_vector (raw.begin(), raw.begin() + capacity); + msg2 = secure_vector (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 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 H2 = hash->final(); + + //check if H3 == H2 + bad_input |= CT::Mask::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 ISO_9796_DS2::raw_data() + { + secure_vector retbuffer = m_msg_buffer; + m_msg_buffer.clear(); + return retbuffer; + } + +/* + * ISO-9796-2 scheme 2 encode operation + */ +secure_vector ISO_9796_DS2::encoding_of(const secure_vector& 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& const_coded, + const secure_vector& 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 ISO_9796_DS3::raw_data() + { + secure_vector retbuffer = m_msg_buffer; + m_msg_buffer.clear(); + return retbuffer; + } + +/* + * ISO-9796-2 scheme 3 encode operation + */ +secure_vector ISO_9796_DS3::encoding_of(const secure_vector& 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& const_coded, + const secure_vector& 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 +#include + +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 raw_data() override; + + secure_vector encoding_of(const secure_vector& msg, + size_t output_bits, + RandomNumberGenerator& rng) override; + + bool verify(const secure_vector& coded, + const secure_vector& raw, + size_t key_bits) override; + + std::unique_ptr m_hash; + bool m_implicit; + size_t m_SALT_SIZE; + secure_vector 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 raw_data() override; + + secure_vector encoding_of(const secure_vector& msg, + size_t output_bits, + RandomNumberGenerator& rng) override; + + bool verify(const secure_vector& coded, + const secure_vector& raw, + size_t key_bits) override; + + std::unique_ptr m_hash; + bool m_implicit; + secure_vector 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 @@ + +MGF1 -> 20140118 + 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 +#include +#include + +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 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(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 + +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 +#include +#include +#include +#include + +namespace Botan { + +const std::map> 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 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 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 +#include +#include + +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 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 -- cgit v1.2.3