From f15cdfc6d954fd3d835a6d1b56632f0b3746b368 Mon Sep 17 00:00:00 2001 From: Philipp Weber Date: Wed, 27 Apr 2016 15:22:08 +0200 Subject: add kdf1 implementation according to iso-18033 (preparation for ecies) --- doc/credits.rst | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'doc') diff --git a/doc/credits.rst b/doc/credits.rst index 6d62b6380..1b97ac3fc 100644 --- a/doc/credits.rst +++ b/doc/credits.rst @@ -104,3 +104,9 @@ snail-mail address (S), and Bitcoin address (B). W: https://www.kullo.net D: Build system S: Germany + + N: Philipp Weber + E: p.weber@sirrix.com + W: https://sirrix.com/ + D: KDF1-18033 + S: Saarland, Germany -- cgit v1.2.3 From 2a58a43264c7994c19a1f05d807e40ffd95644c2 Mon Sep 17 00:00:00 2001 From: Philipp Weber Date: Wed, 27 Apr 2016 15:39:40 +0200 Subject: add ecies implementation according to iso-18033 --- doc/credits.rst | 2 +- src/lib/pubkey/ecies/ecies.cpp | 385 ++++++++++++++++++++++++++++++++++ src/lib/pubkey/ecies/ecies.h | 293 ++++++++++++++++++++++++++ src/lib/pubkey/ecies/info.txt | 9 + src/tests/data/pubkey/ecies-18033.vec | 66 ++++++ src/tests/data/pubkey/ecies.vec | 126 +++++++++++ src/tests/test_ecies.cpp | 246 ++++++++++++++++++++++ 7 files changed, 1126 insertions(+), 1 deletion(-) create mode 100644 src/lib/pubkey/ecies/ecies.cpp create mode 100644 src/lib/pubkey/ecies/ecies.h create mode 100644 src/lib/pubkey/ecies/info.txt create mode 100644 src/tests/data/pubkey/ecies-18033.vec create mode 100644 src/tests/data/pubkey/ecies.vec create mode 100644 src/tests/test_ecies.cpp (limited to 'doc') diff --git a/doc/credits.rst b/doc/credits.rst index 1b97ac3fc..d113fc7de 100644 --- a/doc/credits.rst +++ b/doc/credits.rst @@ -108,5 +108,5 @@ snail-mail address (S), and Bitcoin address (B). N: Philipp Weber E: p.weber@sirrix.com W: https://sirrix.com/ - D: KDF1-18033 + D: KDF1-18033, ECIES S: Saarland, Germany diff --git a/src/lib/pubkey/ecies/ecies.cpp b/src/lib/pubkey/ecies/ecies.cpp new file mode 100644 index 000000000..51ba3d172 --- /dev/null +++ b/src/lib/pubkey/ecies/ecies.cpp @@ -0,0 +1,385 @@ +/* +* ECIES +* (C) 2016 Philipp Weber +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include +#include + +#include +#include + +namespace Botan { + +namespace { + +/** +* Private key type for ECIES_ECDH_KA_Operation +*/ +class ECIES_PrivateKey : public EC_PrivateKey, public PK_Key_Agreement_Key + { + public: + explicit ECIES_PrivateKey(const ECDH_PrivateKey& private_key) : + EC_PublicKey(private_key), + EC_PrivateKey(private_key), + PK_Key_Agreement_Key(), + m_key(private_key) + { + } + + std::vector public_value() const override + { + return m_key.public_value(); + } + + std::string algo_name() const override + { + return "ECIES"; + } + + size_t max_input_bits() const override + { + return m_key.max_input_bits(); + } + + private: + ECDH_PrivateKey m_key; + }; + +/** +* Implements ECDH key agreement without using the cofactor mode +*/ +class ECIES_ECDH_KA_Operation : public PK_Ops::Key_Agreement_with_KDF + { + public: + typedef ECIES_PrivateKey Key_Type; + + ECIES_ECDH_KA_Operation(const ECIES_PrivateKey& private_key, const std::string&) : + PK_Ops::Key_Agreement_with_KDF("Raw"), + m_key(private_key) + { + } + + secure_vector raw_agree(const byte w[], size_t w_len) override + { + const CurveGFp& curve = m_key.domain().get_curve(); + PointGFp point = OS2ECP(w, w_len, curve); + PointGFp S = point * m_key.private_value(); + BOTAN_ASSERT(S.on_the_curve(), "ECDH agreed value was on the curve"); + return BigInt::encode_1363(S.get_affine_x(), curve.get_p().bytes()); + } + + private: + ECIES_PrivateKey m_key; + }; + +/** +* Creates a PK_Key_Agreement instance for the given key and ecies_params +* Returns either ECIES_ECDH_KA_Operation or the default implementation for the given key, +* depending on the key and ecies_params +* @param private_key the private key used for the key agreement +* @param ecies_params settings for ecies +* @param for_encryption disable cofactor mode if the secret will be used for encryption +* (according to ISO 18033 cofactor mode is only used during decryption) +*/ +PK_Key_Agreement create_key_agreement(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params, + bool for_encryption) + { + const ECDH_PrivateKey* ecdh_key = dynamic_cast(&private_key); + + if(ecdh_key == nullptr && (ecies_params.cofactor_mode() || ecies_params.old_cofactor_mode() + || ecies_params.check_mode())) + { + // assume we have a private key from an external provider (e.g. pkcs#11): + // there is no way to determine or control whether the provider uses cofactor mode or not. + // ISO 18033 does not allow cofactor mode in combination with old cofactor mode or check mode + // => disable cofactor mode, old cofactor mode and check mode for unknown keys/providers (as a precaution). + throw Invalid_Argument("ECIES: cofactor, old cofactor and check mode are only supported for ECDH_PrivateKey"); + } + + if(ecdh_key && (for_encryption || !ecies_params.cofactor_mode())) + { + // ECDH_KA_Operation uses cofactor mode: use own key agreement method if cofactor should not be used. + return PK_Key_Agreement(ECIES_PrivateKey(*ecdh_key), "Raw"); + } + + return PK_Key_Agreement(private_key, "Raw"); // use default implementation + } +} + +BOTAN_REGISTER_PK_KEY_AGREE_OP("ECIES", ECIES_ECDH_KA_Operation); + +ECIES_KA_Operation::ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params, + bool for_encryption) : + m_ka(create_key_agreement(private_key, ecies_params, for_encryption)), + m_params(ecies_params) + { + } + +/** +* ECIES secret derivation according to ISO 18033-2 +*/ +SymmetricKey ECIES_KA_Operation::derive_secret(const std::vector& eph_public_key_bin, + const PointGFp& other_public_key_point) const + { + if(other_public_key_point.is_zero()) + { + throw Invalid_Argument("ECIES: other public key point is zero"); + } + + std::unique_ptr kdf = m_params.create_kdf(); + BOTAN_ASSERT(kdf != nullptr, "KDF is found"); + + PointGFp other_point = other_public_key_point; + + // ISO 18033: step b + if(m_params.old_cofactor_mode()) + { + other_point *= m_params.domain().get_cofactor(); + } + + secure_vector derivation_input; + + // ISO 18033: encryption step e / decryption step g + if(!m_params.single_hash_mode()) + { + derivation_input += eph_public_key_bin; + } + + // ISO 18033: encryption step f / decryption step h + secure_vector other_public_key_bin = EC2OSP(other_point, static_cast(m_params.compression_type())); + // Note: the argument `m_params.secret_length()` passed for `key_len` will only be used by providers because + // "Raw" is passed to the `PK_Key_Agreement` if the implementation of botan is used. + const SymmetricKey peh = m_ka.derive_key(m_params.domain().get_order().bytes(), other_public_key_bin.data(), other_public_key_bin.size()); + derivation_input.insert(derivation_input.end(), peh.begin(), peh.end()); + + // ISO 18033: encryption step g / decryption step i + return kdf->derive_key(m_params.secret_length(), derivation_input); + } + + +ECIES_KA_Params::ECIES_KA_Params(const EC_Group& domain, const std::string& kdf_spec, size_t length, + PointGFp::Compression_Type compression_type, ECIES_Flags flags) : + m_domain(domain), + m_kdf_spec(kdf_spec), + m_length(length), + m_compression_mode(compression_type), + m_flags(flags) + { + } + +std::unique_ptr ECIES_KA_Params::create_kdf() const + { + std::unique_ptr kdf = Botan::KDF::create(m_kdf_spec); + if(kdf == nullptr) + { + throw Algorithm_Not_Found(m_kdf_spec); + } + return kdf; + } + + +ECIES_System_Params::ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, + const std::string& dem_algo_spec, size_t dem_key_len, + const std::string& mac_spec, size_t mac_key_len, + PointGFp::Compression_Type compression_type, ECIES_Flags flags) : + ECIES_KA_Params(domain, kdf_spec, dem_key_len + mac_key_len, compression_type, flags), + m_dem_spec(dem_algo_spec), + m_dem_keylen(dem_key_len), + m_mac_spec(mac_spec), + m_mac_keylen(mac_key_len) + { + // ISO 18033: "At most one of CofactorMode, OldCofactorMode, and CheckMode may be 1." + if(cofactor_mode() + old_cofactor_mode() + check_mode() > 1) + { + throw Invalid_Argument("ECIES: only one of cofactor_mode, old_cofactor_mode and check_mode can be set"); + } + } + +ECIES_System_Params::ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, + const std::string& dem_algo_spec, size_t dem_key_len, + const std::string& mac_spec, size_t mac_key_len) : + ECIES_System_Params(domain, kdf_spec, dem_algo_spec, dem_key_len, mac_spec, mac_key_len, PointGFp::UNCOMPRESSED, + ECIES_Flags::NONE) + { + } + +std::unique_ptr ECIES_System_Params::create_mac() const + { + std::unique_ptr mac = Botan::MessageAuthenticationCode::create(m_mac_spec); + if(mac == nullptr) + { + throw Algorithm_Not_Found(m_mac_spec); + } + return mac; + } + +std::unique_ptr ECIES_System_Params::create_cipher(Botan::Cipher_Dir direction) const + { + Keyed_Filter* cipher = get_cipher(m_dem_spec, direction); + if(cipher == nullptr) + { + throw Algorithm_Not_Found(m_dem_spec); + } + return std::unique_ptr(cipher); + } + + +/* +* ECIES_Encryptor Constructor +*/ +ECIES_Encryptor::ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params) : + m_ka(private_key, ecies_params, true), + m_params(ecies_params), + m_eph_public_key_bin(private_key.public_value()), // returns the uncompressed public key, see conversion below + m_iv(), + m_other_point(), + m_label() + { + if(ecies_params.compression_type() != PointGFp::UNCOMPRESSED) + { + // ISO 18033: step d + // convert only if necessary; m_eph_public_key_bin has been initialized with the uncompressed format + m_eph_public_key_bin = unlock(EC2OSP(OS2ECP(m_eph_public_key_bin, m_params.domain().get_curve()), + static_cast(ecies_params.compression_type()))); + } + } + +/* +* ECIES_Encryptor Constructor +*/ +ECIES_Encryptor::ECIES_Encryptor(RandomNumberGenerator& rng, const ECIES_System_Params& ecies_params) : + ECIES_Encryptor(ECDH_PrivateKey(rng, ecies_params.domain()), ecies_params) + { + } + + +/* +* ECIES Encryption according to ISO 18033-2 +*/ +std::vector ECIES_Encryptor::enc(const byte data[], size_t length, RandomNumberGenerator&) const + { + if(m_other_point.is_zero()) + { + throw Invalid_State("ECIES: the other key is zero"); + } + + const SymmetricKey secret_key = m_ka.derive_secret(m_eph_public_key_bin, m_other_point); + + // encryption + std::unique_ptr cipher = m_params.create_cipher(ENCRYPTION); + BOTAN_ASSERT(cipher != nullptr, "Cipher is found"); + + cipher->set_key(SymmetricKey(secret_key.begin(), m_params.dem_keylen())); + if(m_iv.size() != 0) + { + cipher->set_iv(m_iv); + } + Pipe pipe(cipher.release()); + pipe.process_msg(data, length); + const secure_vector encrypted_data = pipe.read_all(0); + + // concat elements + std::unique_ptr mac = m_params.create_mac(); + BOTAN_ASSERT(mac != nullptr, "MAC is found"); + + secure_vector out(m_eph_public_key_bin.size() + encrypted_data.size() + mac->output_length()); + buffer_insert(out, 0, m_eph_public_key_bin); + buffer_insert(out, m_eph_public_key_bin.size(), encrypted_data); + + // mac + mac->set_key(secret_key.begin() + m_params.dem_keylen(), m_params.mac_keylen()); + mac->update(encrypted_data); + if(!m_label.empty()) + { + mac->update(m_label); + } + mac->final(out.data() + m_eph_public_key_bin.size() + encrypted_data.size()); + + return unlock(out); + } + + +ECIES_Decryptor::ECIES_Decryptor(const PK_Key_Agreement_Key& key, const ECIES_System_Params& ecies_params) : + m_ka(key, ecies_params, false), + m_params(ecies_params), + m_iv(), + m_label() + { + // ISO 18033: "If v > 1 and CheckMode = 0, then we must have gcd(µ, v) = 1." (v = index, µ = order) + if(!ecies_params.check_mode()) + { + Botan::BigInt cofactor = m_params.domain().get_cofactor(); + if(cofactor > 1 && Botan::gcd(cofactor, m_params.domain().get_order()) != 1) + { + throw Invalid_Argument("ECIES: gcd of cofactor and order must be 1 if check_mode is 0"); + } + } + } + +/** +* ECIES Decryption according to ISO 18033-2 +*/ +secure_vector ECIES_Decryptor::do_decrypt(byte& valid_mask, const byte in[], size_t in_len) const + { + size_t point_size = m_params.domain().get_curve().get_p().bytes(); + if(m_params.compression_type() != PointGFp::COMPRESSED) + { + point_size *= 2; // uncompressed and hybrid contains x AND y + } + point_size += 1; // format byte + + std::unique_ptr mac = m_params.create_mac(); + BOTAN_ASSERT(mac != nullptr, "MAC is found"); + + if(in_len < point_size + mac->output_length()) + { + throw Decoding_Error("ECIES decryption: ciphertext is too short"); + } + + // extract data + const std::vector other_public_key_bin(in, in + point_size); // the received (ephemeral) public key + const std::vector encrypted_data(in + point_size, in + in_len - mac->output_length()); + const std::vector mac_data(in + in_len - mac->output_length(), in + in_len); + + // ISO 18033: step a + PointGFp other_public_key = OS2ECP(other_public_key_bin, m_params.domain().get_curve()); + + // ISO 18033: step b + if(m_params.check_mode() && !other_public_key.on_the_curve()) + { + throw Decoding_Error("ECIES decryption: received public key is not on the curve"); + } + + // ISO 18033: step e (and step f because get_affine_x (called by ECDH_KA_Operation::raw_agree) + // throws Illegal_Transformation if the point is zero) + const SymmetricKey secret_key = m_ka.derive_secret(other_public_key_bin, other_public_key); + + // validate mac + mac->set_key(secret_key.begin() + m_params.dem_keylen(), m_params.mac_keylen()); + mac->update(encrypted_data); + if(!m_label.empty()) + { + mac->update(m_label); + } + const secure_vector calculated_mac = mac->final(); + valid_mask = CT::expand_mask(same_mem(mac_data.data(), calculated_mac.data(), mac_data.size())); + + // decrypt data + std::unique_ptr cipher = m_params.create_cipher(DECRYPTION); + BOTAN_ASSERT(cipher != nullptr, "Cipher is found"); + + cipher->set_key(SymmetricKey(secret_key.begin(), m_params.dem_keylen())); + if(m_iv.size() != 0) + { + cipher->set_iv(m_iv); + } + Pipe pipe(cipher.release()); + pipe.process_msg(encrypted_data); + return pipe.read_all(0); + } + +} diff --git a/src/lib/pubkey/ecies/ecies.h b/src/lib/pubkey/ecies/ecies.h new file mode 100644 index 000000000..07937556c --- /dev/null +++ b/src/lib/pubkey/ecies/ecies.h @@ -0,0 +1,293 @@ +/* +* ECIES +* (C) 2016 Philipp Weber +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_ECIES_H__ +#define BOTAN_ECIES_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Botan { + +class RandomNumberGenerator; + +enum class ECIES_Flags : uint32_t + { + NONE = 0, + + /// if set: prefix the input of the (ecdh) key agreement with the encoded (ephemeral) public key + SINGLE_HASH_MODE = 1, + + /// (decryption only) if set: use cofactor multiplication during (ecdh) key agreement + COFACTOR_MODE = 2, + + /// if set: use ecdhc instead of ecdh + OLD_COFACTOR_MODE = 4, + + /// (decryption only) if set: test if the (ephemeral) public key is on the curve + CHECK_MODE = 8 + }; + +inline ECIES_Flags operator |(ECIES_Flags a, ECIES_Flags b) + { + return static_cast(static_cast(a) | static_cast(b)); + } + +inline ECIES_Flags operator &(ECIES_Flags a, ECIES_Flags b) + { + return static_cast(static_cast(a) & static_cast(b)); + } + +/** +* Parameters for ecies secret derivation +*/ +class BOTAN_DLL ECIES_KA_Params + { + public: + /** + * @param domain ec domain parameters of the involved ec keys + * @param kdf_spec name of the key derivation function + * @param length length of the secret to be derived + * @param compression_type format of encoded keys (affects the secret derivation if single_hash_mode is used) + * @param flags options, see documentation of ECIES_Flags + */ + ECIES_KA_Params(const EC_Group& domain, const std::string& kdf_spec, size_t length, + PointGFp::Compression_Type compression_type, ECIES_Flags flags); + + virtual ~ECIES_KA_Params() = default; + + std::unique_ptr create_kdf() const; + + inline const EC_Group& domain() const + { + return m_domain; + } + + inline size_t secret_length() const + { + return m_length; + } + + inline bool single_hash_mode() const + { + return (m_flags & ECIES_Flags::SINGLE_HASH_MODE) == ECIES_Flags::SINGLE_HASH_MODE; + } + + inline bool cofactor_mode() const + { + return (m_flags & ECIES_Flags::COFACTOR_MODE) == ECIES_Flags::COFACTOR_MODE; + } + + inline bool old_cofactor_mode() const + { + return (m_flags & ECIES_Flags::OLD_COFACTOR_MODE) == ECIES_Flags::OLD_COFACTOR_MODE; + } + + inline bool check_mode() const + { + return (m_flags & ECIES_Flags::CHECK_MODE) == ECIES_Flags::CHECK_MODE; + } + + inline PointGFp::Compression_Type compression_type() const + { + return m_compression_mode; + } + + private: + const EC_Group m_domain; + const std::string m_kdf_spec; + const size_t m_length; + const PointGFp::Compression_Type m_compression_mode; + const ECIES_Flags m_flags; + }; + + +class BOTAN_DLL ECIES_System_Params : public ECIES_KA_Params + { + public: + /** + * @param domain ec domain parameters of the involved ec keys + * @param kdf_spec name of the key derivation function + * @param dem_algo_spec name of the data encryption method + * @param dem_key_len length of the key used for the data encryption method + * @param mac_spec name of the message authentication code + * @param mac_key_len length of the key used for the message authentication code + * @param compression_type format of encoded keys (affects the secret derivation if single_hash_mode is used) + * @param flags options, see documentation of ECIES_Flags + */ + ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, const std::string& dem_algo_spec, + size_t dem_key_len, const std::string& mac_spec, size_t mac_key_len); + + /** + * @param domain ec domain parameters of the involved ec keys + * @param kdf_spec name of the key derivation function + * @param dem_algo_spec name of the data encryption method + * @param dem_key_len length of the key used for the data encryption method + * @param mac_spec name of the message authentication code + * @param mac_key_len length of the key used for the message authentication code + */ + ECIES_System_Params(const EC_Group& domain, const std::string& kdf_spec, const std::string& dem_algo_spec, + size_t dem_key_len, const std::string& mac_spec, size_t mac_key_len, + PointGFp::Compression_Type compression_type, ECIES_Flags flags); + + virtual ~ECIES_System_Params() = default; + + /// creates an instance of the message authentication code + std::unique_ptr create_mac() const; + + /// creates an instance of the data encryption method + std::unique_ptr create_cipher(Botan::Cipher_Dir direction) const; + + /// returns the length of the key used by the data encryption method + inline size_t dem_keylen() const + { + return m_dem_keylen; + } + + /// returns the length of the key used by the message authentication code + inline size_t mac_keylen() const + { + return m_mac_keylen; + } + + private: + const std::string m_dem_spec; + const size_t m_dem_keylen; + const std::string m_mac_spec; + const size_t m_mac_keylen; + }; + + +/** +* ECIES secret derivation according to ISO 18033-2 +*/ +class BOTAN_DLL ECIES_KA_Operation + { + public: + /** + * @param private_key the (ephemeral) private key which is used to derive the secret + * @param ecies_params settings for ecies + * @param for_encryption disable cofactor mode if the secret will be used for encryption + * (according to ISO 18033 cofactor mode is only used during decryption) + */ + ECIES_KA_Operation(const PK_Key_Agreement_Key& private_key, const ECIES_KA_Params& ecies_params, + bool for_encryption); + + /** + * Performs a key agreement with the provided keys and derives the secret from the result + * @param eph_public_key_bin the encoded (ephemeral) public key which belongs to the used (ephemeral) private key + * @param other_public_key_point public key point of the other party + */ + SymmetricKey derive_secret(const std::vector& eph_public_key_bin, + const PointGFp& other_public_key_point) const; + + private: + const PK_Key_Agreement m_ka; + const ECIES_KA_Params m_params; + }; + + +/** +* ECIES Encryption according to ISO 18033-2 +*/ +class BOTAN_DLL ECIES_Encryptor : public PK_Encryptor + { + public: + /** + * @param private_key the (ephemeral) private key which is used for the key agreement + * @param ecies_params settings for ecies + */ + ECIES_Encryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params); + + /** + * Creates an ephemeral private key which is used for the key agreement + * @param rng random generator used during private key generation + * @param ecies_params settings for ecies + */ + ECIES_Encryptor(RandomNumberGenerator& rng, const ECIES_System_Params& ecies_params); + + /// Set the public key of the other party + inline void set_other_key(const Botan::PointGFp& public_point) + { + m_other_point = public_point; + } + + /// Set the initialization vector for the data encryption method + inline void set_initialization_vector(const InitializationVector& iv) + { + m_iv = iv; + } + + /// Set the label which is appended to the input for the message authentication code + inline void set_label(const std::string& label) + { + m_label = std::vector(label.begin(), label.end()); + } + + private: + std::vector enc(const byte data[], size_t length, RandomNumberGenerator&) const override; + + inline size_t maximum_input_size() const override + { + return std::numeric_limits::max(); + } + + const ECIES_KA_Operation m_ka; + const ECIES_System_Params m_params; + std::vector m_eph_public_key_bin; + InitializationVector m_iv; + PointGFp m_other_point; + std::vector m_label; + }; + + +/** +* ECIES Decryption according to ISO 18033-2 +*/ +class BOTAN_DLL ECIES_Decryptor : public PK_Decryptor + { + public: + /** + * @param private_key the private key which is used for the key agreement + * @param ecies_params settings for ecies + */ + ECIES_Decryptor(const PK_Key_Agreement_Key& private_key, const ECIES_System_Params& ecies_params); + + /// Set the initialization vector for the data encryption method + inline void set_initialization_vector(const InitializationVector& iv) + { + m_iv = iv; + } + + /// Set the label which is appended to the input for the message authentication code + inline void set_label(const std::string& label) + { + m_label = std::vector(label.begin(), label.end()); + } + + private: + secure_vector do_decrypt(byte& valid_mask, const byte in[], size_t in_len) const; + + const ECIES_KA_Operation m_ka; + const ECIES_System_Params m_params; + InitializationVector m_iv; + std::vector m_label; + }; + +} + +#endif diff --git a/src/lib/pubkey/ecies/info.txt b/src/lib/pubkey/ecies/info.txt new file mode 100644 index 000000000..dacefc88a --- /dev/null +++ b/src/lib/pubkey/ecies/info.txt @@ -0,0 +1,9 @@ +define ECIES 20160128 + + +kdf +mac +ecdh +modes +filters + \ No newline at end of file diff --git a/src/tests/data/pubkey/ecies-18033.vec b/src/tests/data/pubkey/ecies-18033.vec new file mode 100644 index 000000000..8937abd2c --- /dev/null +++ b/src/tests/data/pubkey/ecies-18033.vec @@ -0,0 +1,66 @@ +# ISO/IEC 18033-2 2006 +# ECIES-KEM test vectors for ECModp-Group + +# ---------------------------------------------------------------------------------------------------- + +# C.2.2 +# Kdf=Kdf1(Hash=Sha1()) +# Keylen=128 +# CofactorMode=0 +# OldCofactorMode=0 +# CheckMode=0 +# SingleHashMode=0 + +format = uncompressed + +p = 0xfffffffffffffffffffffffffffffffeffffffffffffffff +a = 0xfffffffffffffffffffffffffffffffefffffffffffffffc +b = 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1 +mu = 0xffffffffffffffffffffffff99def836146bc9b1b4d22831 +nu = 0x01 +gx = 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 +gy = 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811 + +# Public Key +hx = 0x1cbc74a41b4e84a1509f935e2328a0bb06104d8dbb8d2130 +hy = 0x7b2ab1f10d76fde1ea046a4ad5fb903734190151bb30cec2 + +# Private Key +x = 0xb67048c28d2d26a73f713d5ebb994ac92588464e7fe7d3f3 + +# Encoding format = uncompressed_fmt +r = 0x083d4ac64f1960a9836a84f91ca211a185814fa43a2c8f21 +C0 = 04ccc9ea07b8b71d25646b22b0e251362a3fa9e993042315df047b2e07dd2ffb89359945f3d22ca8757874be2536e0f924 +K = 9a709adeb6c7590ccfc7d594670dd2d74fcdda3f8622f2dbcf0f0c02966d5d9002db578c989bf4a5cc896d2a11d74e0c51efc1f8ee784897ab9b865a7232b5661b7cac87cf4150bdf23b015d7b525b797cf6d533e9f6ad49a4c6de5e7089724c9cadf0adf13ee51b41be6713653fc1cb2c95a1d1b771cc7429189861d7a829f3 + +# ---------------------------------------------------------------------------------------------------- + +# C.2.3 +# Kdf=Kdf1(Hash=Sha1()) +# Keylen=128 +# CofactorMode=0 +# OldCofactorMode=0 +# CheckMode=0 +# SingleHashMode=0 + +format = compressed + +p = 0xfffffffffffffffffffffffffffffffeffffffffffffffff +a = 0xfffffffffffffffffffffffffffffffefffffffffffffffc +b = 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1 +mu = 0xffffffffffffffffffffffff99def836146bc9b1b4d22831 +nu = 0x01 +gx = 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012 +gy = 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811 + +# Public Key +hx = 0x1cbc74a41b4e84a1509f935e2328a0bb06104d8dbb8d2130 +hy = 0x7b2ab1f10d76fde1ea046a4ad5fb903734190151bb30cec2 + +# Private Key +x = 0xb67048c28d2d26a73f713d5ebb994ac92588464e7fe7d3f3 + +# Encoding format = compressed_fmt +r = 0x083d4ac64f1960a9836a84f91ca211a185814fa43a2c8f21 +C0 = 02ccc9ea07b8b71d25646b22b0e251362a3fa9e993042315df +K = 8fbe0903fac2fa05df02278fe162708fb432f3cbf9bb14138d22be1d279f74bfb94f0843a153b708fcc8d9446c76f00e4ccabef85228195f732f4aedc5e48efcf2968c3a46f2df6f2afcbdf5ef79c958f233c6d208f3a7496e08f505d1c792b314b45ff647237b0aa186d0cdbab47a00fb4065d62cfc18f8a8d12c78ecbee3fd diff --git a/src/tests/data/pubkey/ecies.vec b/src/tests/data/pubkey/ecies.vec new file mode 100644 index 000000000..fcf0baf62 --- /dev/null +++ b/src/tests/data/pubkey/ecies.vec @@ -0,0 +1,126 @@ +# random keys created by botan + +# ciphertext created with bouncycastle 1.54. example: +# public static void main( String[] args ) +# throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidCipherTextException +# { +# X9ECParameters spec = SECNamedCurves.getByName( "secp160r1" ); +# ECDomainParameters ecDomain = new ECDomainParameters( spec.getCurve(), spec.getG(), spec.getN() ); +# +# ECPrivateKeyParameters alice = new ECPrivateKeyParameters( new BigInteger( "1239488582848888730519239446720775754920686817364", 10 ), ecDomain ); +# ECPrivateKeyParameters bob = new ECPrivateKeyParameters( new BigInteger( "1255825134563225934367124570783723166851629196761", 10 ), ecDomain ); +# ECPublicKeyParameters alicePublicKey = new ECPublicKeyParameters( alice.getParameters().getG().multiply( alice.getD() ), alice.getParameters() ); +# ECPublicKeyParameters bobPublicKey = new ECPublicKeyParameters( bob.getParameters().getG().multiply( bob.getD() ), bob.getParameters() ); +# +# byte[] d = new byte[ 0 ]; +# byte[] e = new byte[ 0 ]; +# byte[] iv = new byte[ 16 ]; +# CipherParameters p = new ParametersWithIV( new IESWithCipherParameters( d, e, 160, 256 ), iv ); +# +# IESEngine ecies = +# new IESEngine( new ECDHBasicAgreement(), new KDF2BytesGenerator( new SHA1Digest() ), new HMac( new SHA256Digest() ), new PaddedBufferedBlockCipher( new CBCBlockCipher( +# new AESEngine() ) ) ); +# ecies.init( true, alice, bobPublicKey, p ); +# +# byte[] message = Hex.decode( "00" ); +# byte[] result = ecies.processBlock( message, 0, message.length ); +# +# byte[] ephPublicKey = alicePublicKey.getQ().getEncoded( true ); +# byte[] out = Arrays.concatenate( ephPublicKey, result ); +# +# System.out.println( Hex.toHexString( out ) ); +# } + +Curve = secp160r1 +PrivateKey = 1239488582848888730519239446720775754920686817364 +OtherPrivateKey = 1255825134563225934367124570783723166851629196761 +Kdf = KDF2(SHA-1) +Dem = AES-256/CBC +DemKeyLen = 32 +Iv = 00000000000000000000000000000000 +Mac = HMAC(SHA-256) +MacKeyLen = 20 +Format = compressed +CofactorMode = 0 +OldCofactorMode = 0 +CheckMode = 0 +SingleHashMode = 1 +Label = +Plaintext = 00 +Ciphertext = 02b26eafa6b51a39790c32a75c2f10b3e8e89d698a6da2667af153734225c8922800db5e10b73975848cceac0fc78cef589b2e93a81cc204dbc7b9b901cbaa4509e61141d7 + +Curve = secp521r1 +PrivateKey = 4050298667054381376040649773970530311598264897556821662677634075002761777100287880684822948852132235484464537021197213998300006547176718172344447619746779823 +OtherPrivateKey = 2294226772740614508941417891614236736606752960073669253551166842586609531509032791476032516821966982891507407145617606630445744825404691681749451640151380153 +Kdf = KDF2(SHA-1) +Dem = Camellia-128/CBC +DemKeyLen = 16 +Iv = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Mac = HMAC(SHA-256) +MacKeyLen = 16 +Format = uncompressed +CofactorMode = 0 +OldCofactorMode = 0 +CheckMode = 0 +SingleHashMode = 1 +Label = Test +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = 0401519eaa0489ff9d51e98e4c22349463e2001cd06f8ce47d81d4007a79acf98e92c814686477cea666efc277dc84e15fc95e38aff8e16d478a44cd5c5f1517f8b1f300000591317f261c3d04a7207f01eae3ec70f23600f82c53cc0b85be7ac9f6ce79ef2ab416e5934d61ba9d346385d7545c57f77c7ea7c58e18c70cbfb0a24ae1b994eda8dbc666713558717077dde021d9252b7f68eef0bc369086f6a6cb991fcc2fbcac3671a122ba18541790974cef7420cb53e7d6f30d1b808dddd58a63413f7b + +# use secp112r2 - curve with cofactor != 1 +Curve = -----BEGIN EC PARAMETERS-----MHMCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDmEnwkwF84oKqvZcDvAsBA5R3vGBXbXtdPzDTIXXCQQdBEujCrXokrThZJ3QkoZDrc1G9YguN0fe826VbpcCDjbfCq/YuNdZfKEFINBLAgEE-----END EC PARAMETERS----- +PrivateKey = 656008468895526658474428975817604 +OtherPrivateKey = 563449446384594847151017584539074 +Kdf = KDF2(SHA-1) +Dem = Camellia-128/CBC +DemKeyLen = 16 +Iv = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Mac = HMAC(SHA-256) +MacKeyLen = 16 +Format = uncompressed +CofactorMode = 0 +OldCofactorMode = 1 +CheckMode = 0 +SingleHashMode = 1 +Label = Test +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = 048c40bda0986dadeb651178b4a8e64b7735fb02f43e621151849ea761a0f79fbb500b76e4eb9cd65281b804406536d04059b60689ed286490afcbf8f7f32dfefff8d37d29d335cb11aef3cc5d65f87571e3c8799974038f9d377a2683 + +# use secp112r2 - curve with cofactor != 1 +Curve = -----BEGIN EC PARAMETERS-----MHMCAQEwGgYHKoZIzj0BAQIPANt8Kr9i415mgHa+rSCLMCAEDmEnwkwF84oKqvZcDvAsBA5R3vGBXbXtdPzDTIXXCQQdBEujCrXokrThZJ3QkoZDrc1G9YguN0fe826VbpcCDjbfCq/YuNdZfKEFINBLAgEE-----END EC PARAMETERS----- +PrivateKey = 656008468895526658474428975817604 +OtherPrivateKey = 563449446384594847151017584539074 +Kdf = KDF2(SHA-1) +Dem = Camellia-128/CBC +DemKeyLen = 16 +Iv = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Mac = HMAC(SHA-256) +MacKeyLen = 16 +Format = uncompressed +CofactorMode = 1 +OldCofactorMode = 0 +CheckMode = 0 +SingleHashMode = 1 +Label = Test +Plaintext = 000102030405060708090A0B0C0D0E0F +Ciphertext = 048c40bda0986dadeb651178b4a8e64b7735fb02f43e621151849ea761230f2bddf1ffa3262673bcb3f468dd8b92c31a32e23935cfd27dfcc123928a18bbc82bdcada733be6d42119d3fb968ac4b77fff9a47d336fa025bfad3ee54286 + +# bouncycastle does not support aead ciphers with IESEngine -> empty ciphertext; the test suite asserts that the plaintext can be encrypted and decrypted properly + +Curve = brainpool512r1 +PrivateKey = 7978796978847894400103470063598909318992754342406974939475470191530421638356103244921001321651015274653183103561457607601257178840534133802655904526250737 +OtherPrivateKey = 2308129338363763325603164530220543667351108423592731601992535938718831256964324847657313285466745344259451280420400800014583532495130674675477133156417282 +Kdf = KDF2(SHA-1) +Dem = Twofish/GCM +DemKeyLen = 32 +Iv = 00000000000000000000000000000000 +Mac = HMAC(SHA-512) +MacKeyLen = 64 +Format = compressed +CofactorMode = 0 +OldCofactorMode = 0 +CheckMode = 0 +SingleHashMode = 0 +Label = Test +Plaintext = 00 +Ciphertext = diff --git a/src/tests/test_ecies.cpp b/src/tests/test_ecies.cpp new file mode 100644 index 000000000..2fba6c93f --- /dev/null +++ b/src/tests/test_ecies.cpp @@ -0,0 +1,246 @@ +/* +* (C) 2016 Philipp Weber +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "tests.h" + + +#if defined(BOTAN_HAS_ECIES) + #include "test_pubkey.h" + #include + #include + #include +#endif + +namespace Botan_Tests { + +namespace { + +#if defined(BOTAN_HAS_ECIES) + +using byte = Botan::byte; +using Flags = Botan::ECIES_Flags; + +Botan::PointGFp::Compression_Type get_compression_type(const std::string& format) + { + if(format == "uncompressed") + { + return Botan::PointGFp::UNCOMPRESSED; + } + else if(format == "compressed") + { + return Botan::PointGFp::COMPRESSED; + } + else if(format == "hybrid") + { + return Botan::PointGFp::HYBRID; + } + throw Botan::Invalid_Argument("invalid compression format"); + } + +Flags ecies_flags(bool cofactor_mode, bool old_cofactor_mode, bool check_mode, bool single_hash_mode) + { + return (cofactor_mode ? Flags::COFACTOR_MODE : Flags::NONE) + | (single_hash_mode ? Flags::SINGLE_HASH_MODE : Flags::NONE) + | (old_cofactor_mode ? Flags::OLD_COFACTOR_MODE : Flags::NONE) + | (check_mode ? Flags::CHECK_MODE : Flags::NONE); + } + +void check_encrypt_decrypt(Test::Result& result, const Botan::ECDH_PrivateKey& private_key, + const Botan::ECDH_PrivateKey& other_private_key, + const Botan::ECIES_System_Params& ecies_params, + const Botan::InitializationVector& iv, const std::string& label, + const std::vector& plaintext, const std::vector& ciphertext) + { + Botan::ECIES_Encryptor ecies_enc(private_key, ecies_params); + ecies_enc.set_other_key(other_private_key.public_point()); + Botan::ECIES_Decryptor ecies_dec(other_private_key, ecies_params); + if(!iv.bits_of().empty()) + { + ecies_enc.set_initialization_vector(iv); + ecies_dec.set_initialization_vector(iv); + } + if(!label.empty()) + { + ecies_enc.set_label(label); + ecies_dec.set_label(label); + } + + try + { + const std::vector encrypted = ecies_enc.encrypt(plaintext, Test::rng()); + if(!ciphertext.empty()) + { + result.test_eq("encrypted data", encrypted, ciphertext); + } + const Botan::secure_vector decrypted = ecies_dec.decrypt(encrypted); + result.test_eq("decrypted data equals plaintext", decrypted, plaintext); + } + catch(Botan::Lookup_Error& e) + { + result.test_note(std::string("Test not executed: ") + e.what()); + } + } + +void check_encrypt_decrypt(Test::Result& result, const Botan::ECDH_PrivateKey& private_key, + const Botan::ECDH_PrivateKey& other_private_key, + const Botan::ECIES_System_Params& ecies_params, size_t iv_length = 0) + { + static std::vector Plaintext { 1, 2, 3 }; + check_encrypt_decrypt(result, private_key, other_private_key, ecies_params, std::vector(iv_length, 0), "", + Plaintext, std::vector()); + } + +class ECIES_ISO_Tests : public Text_Based_Test + { + public: + ECIES_ISO_Tests() : Text_Based_Test( + "pubkey/ecies-18033.vec", + { "format", "p", "a", "b", "mu", "nu", "gx", "gy", "hx", "hy", "x", "r", "C0", "K" }) + { + } + + Test::Result run_one_test(const std::string&, const VarMap& vars) override + { + Test::Result result("ECIES-ISO"); + + // get test vectors defined by ISO 18033 + const Botan::PointGFp::Compression_Type compression_type = get_compression_type(get_req_str(vars, "format")); + const Botan::BigInt p = get_req_bn(vars, "p"); + const Botan::BigInt a = get_req_bn(vars, "a"); + const Botan::BigInt b = get_req_bn(vars, "b"); + const Botan::BigInt mu = get_req_bn(vars, "mu"); // order + const Botan::BigInt nu = get_req_bn(vars, "nu"); // cofactor + const Botan::BigInt gx = get_req_bn(vars, "gx"); // base point x + const Botan::BigInt gy = get_req_bn(vars, "gy"); // base point y + const Botan::BigInt hx = get_req_bn(vars, "hx"); // x of public point of bob + const Botan::BigInt hy = get_req_bn(vars, "hy"); // y of public point of bob + const Botan::BigInt x = get_req_bn(vars, "x"); // private key of bob + const Botan::BigInt r = get_req_bn(vars, "r"); // (ephemeral) private key of alice + const std::vector c0 = get_req_bin(vars, "C0"); // expected encoded (ephemeral) public key + const std::vector k = get_req_bin(vars, "K"); // expected derived secret + + const Botan::CurveGFp curve(p, a, b); + const Botan::EC_Group domain(curve, Botan::PointGFp(curve, gx, gy), mu, nu); + + // keys of bob + const Botan::ECDH_PrivateKey other_private_key(Test::rng(), domain, x); + const Botan::PointGFp other_public_key_point(curve, hx, hy); + const Botan::ECDH_PublicKey other_public_key(domain, other_public_key_point); + + // (ephemeral) keys of alice + const Botan::ECDH_PrivateKey eph_private_key(Test::rng(), domain, r); + const Botan::PointGFp eph_public_key_point = eph_private_key.public_point(); + const std::vector eph_public_key_bin = Botan::unlock( + Botan::EC2OSP(eph_public_key_point, compression_type)); + result.test_eq("encoded (ephemeral) public key", eph_public_key_bin, c0); + + // test secret derivation: ISO 18033 test vectors use KDF1 from ISO 18033 + // no cofactor-/oldcofactor-/singlehash-/check-mode and 128 byte secret length + Botan::ECIES_KA_Params ka_params(eph_private_key.domain(), "KDF1-18033(SHA-1)", 128, compression_type, + Flags::NONE); + const Botan::ECIES_KA_Operation ka(eph_private_key, ka_params, true); + const Botan::SymmetricKey secret_key = ka.derive_secret(eph_public_key_bin, other_public_key_point); + result.test_eq("derived secret key", secret_key.bits_of(), k); + + // test encryption / decryption + for(int i_cofactor_mode = 0; i_cofactor_mode < 2; ++i_cofactor_mode) + { + for(int i_single_hash_mode = 0; i_single_hash_mode < 2; ++i_single_hash_mode) + { + for(int i_old_cofactor_mode = 0; i_old_cofactor_mode < 2; ++i_old_cofactor_mode) + { + for(int i_check_mode = 0; i_check_mode < 2; ++i_check_mode) + { + for(int i_compression_type = 0; i_compression_type < 3; ++i_compression_type) + { + const bool cofactor_mode = i_cofactor_mode != 0; + const bool single_hash_mode = i_single_hash_mode != 0; + const bool old_cofactor_mode = i_old_cofactor_mode != 0; + const bool check_mode = i_check_mode != 0; + const Botan::PointGFp::Compression_Type compression_type = + static_cast(i_compression_type); + + Flags flags = ecies_flags(cofactor_mode, old_cofactor_mode, check_mode, single_hash_mode); + + if(cofactor_mode + check_mode + old_cofactor_mode > 1) + { + result.test_throws("throw on invalid ECIES_Flags", [&] + { + Botan::ECIES_System_Params(eph_private_key.domain(), "KDF2(SHA-1)", "AES-256/CBC", + 32, "HMAC(SHA-1)", 20, compression_type, flags); + }); + continue; + } + + Botan::ECIES_System_Params ecies_params(eph_private_key.domain(), "KDF2(SHA-1)", "AES-256/CBC", + 32, "HMAC(SHA-1)", 20, compression_type, flags); + check_encrypt_decrypt(result, eph_private_key, other_private_key, ecies_params, 16); + } + } + } + } + } + + return result; + } + }; + +BOTAN_REGISTER_TEST("ecies-iso", ECIES_ISO_Tests); + + +class ECIES_Tests : public Text_Based_Test + { + public: + ECIES_Tests() : Text_Based_Test( + "pubkey/ecies.vec", + { "Curve", "PrivateKey", "OtherPrivateKey", "Kdf", "Dem", "DemKeyLen", "Iv", "Mac", "MacKeyLen", "Format", + "CofactorMode", "OldCofactorMode", "CheckMode", "SingleHashMode", "Label", "Plaintext", "Ciphertext" }) + { + } + + Test::Result run_one_test(const std::string&, const VarMap& vars) override + { + Test::Result result("ECIES"); + + const std::string curve = get_req_str(vars, "Curve"); + const Botan::BigInt private_key_value = get_req_bn(vars, "PrivateKey"); + const Botan::BigInt other_private_key_value = get_req_bn(vars, "OtherPrivateKey"); + const std::string kdf = get_req_str(vars, "Kdf"); + const std::string dem = get_req_str(vars, "Dem"); + const size_t dem_key_len = get_req_sz(vars, "DemKeyLen"); + const std::vector iv = get_req_bin(vars, "Iv"); + const std::string mac = get_req_str(vars, "Mac"); + const size_t mac_key_len = get_req_sz(vars, "MacKeyLen"); + const Botan::PointGFp::Compression_Type compression_type = get_compression_type(get_req_str(vars, "Format")); + const bool cofactor_mode = get_req_sz(vars, "CofactorMode") != 0; + const bool old_cofactor_mode = get_req_sz(vars, "OldCofactorMode") != 0; + const bool check_mode = get_req_sz(vars, "CheckMode") != 0; + const bool single_hash_mode = get_req_sz(vars, "SingleHashMode") != 0; + const std::string label = get_req_str(vars, "Label"); + const std::vector plaintext = get_req_bin(vars, "Plaintext"); + const std::vector ciphertext = get_req_bin(vars, "Ciphertext"); + + const Flags flags = ecies_flags(cofactor_mode, old_cofactor_mode, check_mode, single_hash_mode); + const Botan::EC_Group domain(curve); + const Botan::ECDH_PrivateKey private_key(Test::rng(), domain, private_key_value); + const Botan::ECDH_PrivateKey other_private_key(Test::rng(), domain, other_private_key_value); + + const Botan::ECIES_System_Params ecies_params(private_key.domain(), kdf, dem, dem_key_len, mac, mac_key_len, + compression_type, flags); + check_encrypt_decrypt(result, private_key, other_private_key, ecies_params, iv, label, plaintext, ciphertext); + + return result; + } + + }; + +BOTAN_REGISTER_TEST("ecies", ECIES_Tests); + +#endif + +} + +} -- cgit v1.2.3 From 4f04a39d104a65d55762b6d03cf7ec21aac02ffa Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Mon, 23 May 2016 11:40:11 -0400 Subject: Fix GCM counter increment GCM is defined as having a 32-bit counter, but CTR_BE incremented the counter across the entire block. This caused incorrect results if a very large message (2**39 bits) was processed, or if the GHASH derived nonce ended up having a counter field near to 2**32 Thanks to Juraj Somorovsky for the bug report and repro. --- doc/news.rst | 13 ++++++++++++- src/lib/modes/aead/gcm/gcm.cpp | 2 +- src/lib/stream/ctr/ctr.cpp | 17 +++++++++++++++-- src/lib/stream/ctr/ctr.h | 3 +++ src/tests/data/aead/gcm.vec | 23 +++++++++++++++++++++++ 5 files changed, 54 insertions(+), 4 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index 2a9fe53a6..0087782d3 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -9,6 +9,17 @@ Version 1.11.30, Not Yet Released a MAC failure. Records like this are used by OpenSSL in TLS 1.0 connections in order to randomize the IV. +* A bug in GCM caused incorrect results if the 32-bit counter field + overflowed. With a 96-bit nonce, this could only occur if 2**32 + 128-bit blocks were encrypted. This actually exceeds the maximum + allowable length of a GCM plaintext. + + However if a GCM nonce of any other size is used, the bug triggers + randomly, with increasing probability on longer messages. For + instance when encrypting 256 MiB of data under a random 128 bit + nonce, an incorrect result would be produced about 1/256 of the + time. With 1 MiB texts, the probability of error reduced to 1/65536. + * The Transform and Keyed_Transform interfaces has been removed. The two concrete implementations of these interfaces were Cipher_Mode and the Compressor_tkk. The Cipher_Mode interface remains unchanged @@ -37,7 +48,7 @@ Version 1.11.30, Not Yet Released * X509_CRL previously had an option to cause it to ignore unknown critical extensions. This has been removed. - + * Added support for ChaCha stream cipher with 12 rounds. * Add ECGDSA signature algorithm (GH #479) diff --git a/src/lib/modes/aead/gcm/gcm.cpp b/src/lib/modes/aead/gcm/gcm.cpp index 1dc5efe4f..e23551cb4 100644 --- a/src/lib/modes/aead/gcm/gcm.cpp +++ b/src/lib/modes/aead/gcm/gcm.cpp @@ -168,7 +168,7 @@ GCM_Mode::GCM_Mode(BlockCipher* cipher, size_t tag_size) : m_ghash.reset(new GHASH); - m_ctr.reset(new CTR_BE(cipher)); // CTR_BE takes ownership of cipher + m_ctr.reset(new CTR_BE(cipher, 4)); // CTR_BE takes ownership of cipher if(m_tag_size != 8 && m_tag_size != 16) throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(m_tag_size)); diff --git a/src/lib/stream/ctr/ctr.cpp b/src/lib/stream/ctr/ctr.cpp index 88c7a8d8e..f5301c099 100644 --- a/src/lib/stream/ctr/ctr.cpp +++ b/src/lib/stream/ctr/ctr.cpp @@ -23,10 +23,23 @@ CTR_BE::CTR_BE(BlockCipher* ciph) : m_cipher(ciph), m_counter(m_cipher->parallel_bytes()), m_pad(m_counter.size()), + m_ctr_size(m_cipher->block_size()), m_pad_pos(0) { } +CTR_BE::CTR_BE(BlockCipher* cipher, size_t ctr_size) : + m_cipher(cipher), + m_counter(m_cipher->parallel_bytes()), + m_pad(m_counter.size()), + m_ctr_size(ctr_size), + m_pad_pos(0) + { + //BOTAN_CHECK_ARG(m_ctr_size > 0 && m_ctr_size <= cipher->block_size(), "Invalid CTR size"); + if(m_ctr_size == 0 || m_ctr_size > m_cipher->block_size()) + throw Invalid_Argument("Invalid CTR-BE counter size"); + } + void CTR_BE::clear() { m_cipher->clear(); @@ -79,7 +92,7 @@ void CTR_BE::set_iv(const byte iv[], size_t iv_len) { buffer_insert(m_counter, i*bs, &m_counter[(i-1)*bs], bs); - for(size_t j = 0; j != bs; ++j) + for(size_t j = 0; j != m_ctr_size; ++j) if(++m_counter[i*bs + (bs - 1 - j)]) break; } @@ -99,7 +112,7 @@ void CTR_BE::increment_counter() for(size_t i = 0; i != n_wide; ++i) { uint16_t carry = static_cast(n_wide); - for(size_t j = 0; carry && j != bs; ++j) + for(size_t j = 0; carry && j != m_ctr_size; ++j) { const size_t off = i*bs + (bs-1-j); const uint16_t cnt = static_cast(m_counter[off]) + carry; diff --git a/src/lib/stream/ctr/ctr.h b/src/lib/stream/ctr/ctr.h index 8e931605c..003297b92 100644 --- a/src/lib/stream/ctr/ctr.h +++ b/src/lib/stream/ctr/ctr.h @@ -44,12 +44,15 @@ class BOTAN_DLL CTR_BE final : public StreamCipher * @param cipher the underlying block cipher to use */ explicit CTR_BE(BlockCipher* cipher); + + CTR_BE(BlockCipher* cipher, size_t ctr_size); private: void key_schedule(const byte key[], size_t key_len) override; void increment_counter(); std::unique_ptr m_cipher; secure_vector m_counter, m_pad; + size_t m_ctr_size; size_t m_pad_pos; }; diff --git a/src/tests/data/aead/gcm.vec b/src/tests/data/aead/gcm.vec index 21bc3a53e..516e828ec 100644 --- a/src/tests/data/aead/gcm.vec +++ b/src/tests/data/aead/gcm.vec @@ -38,6 +38,29 @@ In = D9313225F88406E5A55909C5AFF5269A86A7A9531534F7DA2E4C303D8A318A721C3C0C9 AD = FEEDFACEDEADBEEFFEEDFACEDEADBEEFABADDAD2 Out = 8CE24998625615B603A033ACA13FB894BE9112A5C3A211A8BA262A3CCA7E2CA701E4A9A4FBA43C90CCDCB281D48C7C6FD62875D2ACA417034C34AEE5619CC5AEFFFE0BFA462AF43C1699D050 +# GCM vectors generated by OpenSSL via Python cryptography +# +# These GCM nonces are not 96 bits and so are hashed with GHASH to +# produce the counter value. For these inputs the CTR value is +# very near 2^32, which exposed a bug in GCM when the counter overflowed + +Key = 00000000000000000000000000000000 +Nonce = 0AAC82F3E53C2756034F7BD5827C9EDD +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 38C21B6430D9A3E4BC6749405765653AE91051E96CE0D076141DD7B515EC150FDB8A65EE988D206C9F64874664CDBF61257FFAE521B9A5EB5B35E3745F4232025B269A6CD7DCFE19153ECF7341CE2C6A6A87F95F2109841350DA3D24EEED4E4E32D2BED880737670FFE8ED76DB890FD72A0076300E50914984A777C9F2BC843977396C602B24E7A045F04D15CD2EAC01AD8808064CFE5A2DC1AE9FFFA4BF0A6F0C07668097DEEB9C5CA5EC1F9A52F96A403B73FEA2DBBF44473D355553EE7FB1B4D6630777DAF67804BE213089B9F78652CE970C582FD813F87FF0ECBACCE1CA46247E20D09F3E0B4EF6BFCD13244C6877F25E6646252CAD6EB7DBBA3476AAAC83BC3285FF70B50D6CDEDC8E5921944A + +Key = 00000000000000000000000000000000 +Nonce = 63ADFF969337DB7AAA3D862A8A827558 +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = E7813D2279516D5EE54E03371B0192FE2B66EF4BF3C7F741D2B8E1809CA5C1805908ADEFE6C5884736DF98B7EBCB08110B58C384E4A2FF25644CDFEAA2104FA3B33F00B689319EF7F09B2F066AEC96DC + +Key = 00000000000000000000000000000000 +Nonce = E60108DFED8198FB286E0A77E699DA7B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = A833DCC2EC04BEF5ED9E7E7FB08D61244CD795C21FEE194E7AAF7D9BD66B324F39FFC46DB5A7B9E1D6703F95290027DE6AC274CAE11C632F16261B71CE97EEA6CBE8A82B4F55F5A8B5CE1B268A7B35D8 + + + [AES-192/GCM] # Nist | Test Case 7 Key = 000000000000000000000000000000000000000000000000 -- cgit v1.2.3 From 9eda1f09887b8b1ba5d60e1e432ebf7d828726db Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 3 Jun 2016 09:39:09 -0400 Subject: Update release notes [ci skip] --- doc/news.rst | 49 ++++++++++++++++++++++++++++++++++++++++--------- doc/todo.rst | 1 + 2 files changed, 41 insertions(+), 9 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index 0087782d3..38c6c797b 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -10,15 +10,35 @@ Version 1.11.30, Not Yet Released connections in order to randomize the IV. * A bug in GCM caused incorrect results if the 32-bit counter field - overflowed. With a 96-bit nonce, this could only occur if 2**32 - 128-bit blocks were encrypted. This actually exceeds the maximum - allowable length of a GCM plaintext. - - However if a GCM nonce of any other size is used, the bug triggers - randomly, with increasing probability on longer messages. For - instance when encrypting 256 MiB of data under a random 128 bit - nonce, an incorrect result would be produced about 1/256 of the - time. With 1 MiB texts, the probability of error reduced to 1/65536. + overflowed. This bug has no implications on the security but affects + interoperability. + + With a 96-bit nonce, this could only occur if at least 2**32 128-bit + blocks (64 GiB) were encrypted. This actually exceeds the maximum + allowable length of a GCM plaintext; when messages longer than + 2**32 - 2 blocks are encrypted, GCM loses its security properties. + + In addition to 96-bit nonces, GCM also supports nonces of arbitrary + length using a different method which hashes the provided nonce + under the authentication key. When using such a nonce, the last 4 + bytes of the resulting CTR input might be near the overflow + boundary, with the probability of incorrect overflow increasing with + longer messages. when encrypting 256 MiB of data under a random 128 + bit nonce, an incorrect result would be produced about 1/256 of the + time. With 1 MiB texts, the probability of error is reduced to 1/65536. + + Since TLS uses GCM with 96 bit nonces and limits the length of any + record to far less than 64 GiB, TLS GCM ciphersuites are not + affected by this bug. + + Reported by Juraj Somorovsky, described also in "Nonce-Disrespecting + Adversaries: Practical Forgery Attacks on GCM in TLS" + (https://eprint.iacr.org/2016/475.pdf) + +* Previously when generating a new self-signed certificate or PKCS #10 + request, the subject DN was required to contain both common name + (CN) and country (C) fields. These restrictions have been removed. + GH #496 * The Transform and Keyed_Transform interfaces has been removed. The two concrete implementations of these interfaces were Cipher_Mode @@ -67,6 +87,17 @@ Version 1.11.30, Not Yet Released * Fix bcrypt function under Python 3 (GH #461) +* The ``unix_procs`` entropy source is deprecated and will be removed + in a future release. This entropy source attempts to get entropy by + running Unix programs like ``arp``, ``netstat``, and ``dmesg`` which + produce information which may be difficult for a remote attacker to + guess. This exists primarily as a last-ditch for Unix systems + without ``/dev/random``. But at this point such systems effectively + no longer exist, and the use of ``fork`` and ``exec`` by the library + complicates effective application sandboxing. + +* Changes to avoid implicit cast warnings in Visual C++ (GH #484) + Version 1.10.13, 2016-04-23 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/todo.rst b/doc/todo.rst index 930c23fbd..a66c97f4f 100644 --- a/doc/todo.rst +++ b/doc/todo.rst @@ -101,6 +101,7 @@ Public Key Crypto, Math * XMSS (draft-irtf-cfrg-xmss-hash-based-signatures) * SPHINCS-256 +* NEWHOPE RLWE scheme + BoringSSL compatible TLS cipher suites * EdDSA (GH #283) * Ed448-Goldilocks * FHMQV -- cgit v1.2.3 From 70a61c082408a22b516fbe0f3a81441c6c5f165e Mon Sep 17 00:00:00 2001 From: RenĂ© Korthaus Date: Tue, 14 Jun 2016 17:50:00 +0200 Subject: Add entry to credits --- doc/credits.rst | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'doc') diff --git a/doc/credits.rst b/doc/credits.rst index 6d62b6380..bd70890ff 100644 --- a/doc/credits.rst +++ b/doc/credits.rst @@ -104,3 +104,10 @@ snail-mail address (S), and Bitcoin address (B). W: https://www.kullo.net D: Build system S: Germany + + N: RenĂ© Korthaus + E: r.korthaus@sirrix.com + W: https://www.sirrix.com + P: C196 FF9D 3DDC A5E7 F98C E745 9AD0 F9FA 587E 74D6 + D: CI, ECGDSA, ECKCDSA + S: Bochum, Germany -- cgit v1.2.3 From 00337c4ea2af6b1727be0bdf9b719c98760a14fd Mon Sep 17 00:00:00 2001 From: SimCog Date: Tue, 14 Jun 2016 18:21:10 +0200 Subject: Adding StreamCipher::seek interface, supporting seek in ChaCha, and also adding ChaCha8 support --- doc/credits.rst | 7 + doc/license.txt | 1 + src/lib/prov/openssl/openssl_rc4.cpp | 5 + src/lib/stream/chacha/chacha.cpp | 28 +- src/lib/stream/chacha/chacha.h | 4 +- src/lib/stream/ctr/ctr.cpp | 4 + src/lib/stream/ctr/ctr.h | 2 + src/lib/stream/ofb/ofb.cpp | 5 + src/lib/stream/ofb/ofb.h | 2 + src/lib/stream/rc4/rc4.cpp | 4 + src/lib/stream/rc4/rc4.h | 2 + src/lib/stream/salsa20/salsa20.cpp | 4 + src/lib/stream/salsa20/salsa20.h | 2 + src/lib/stream/stream_cipher.h | 6 + src/tests/data/stream/chacha.vec | 506 +++++++++++++++++++++++++++++++++++ src/tests/test_stream.cpp | 6 +- 16 files changed, 583 insertions(+), 5 deletions(-) (limited to 'doc') diff --git a/doc/credits.rst b/doc/credits.rst index 6d62b6380..af78680a4 100644 --- a/doc/credits.rst +++ b/doc/credits.rst @@ -104,3 +104,10 @@ snail-mail address (S), and Bitcoin address (B). W: https://www.kullo.net D: Build system S: Germany + + N: Simon Cogliani + E: simon.cogliani@tanker.io + W: https://www.tanker.io/ + P: EA73 D0AF 5A81 A61A 8931 C2CA C9AB F2E4 3820 4F25 + D: Getting keystream of ChaCha + S: Paris, France diff --git a/doc/license.txt b/doc/license.txt index ef0b97ac1..fd4fd0a7b 100644 --- a/doc/license.txt +++ b/doc/license.txt @@ -29,6 +29,7 @@ Copyright (C) 1999-2013,2014,2015,2016 Jack Lloyd 2015,2016 Daniel Neus 2015 Uri Blumenthal 2015,2016 Kai Michaelis + 2016 Simon Cogliani All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/src/lib/prov/openssl/openssl_rc4.cpp b/src/lib/prov/openssl/openssl_rc4.cpp index e36535e08..070cdb14d 100644 --- a/src/lib/prov/openssl/openssl_rc4.cpp +++ b/src/lib/prov/openssl/openssl_rc4.cpp @@ -45,6 +45,11 @@ class OpenSSL_RC4 : public StreamCipher explicit OpenSSL_RC4(size_t skip = 0) : m_skip(skip) { clear(); } ~OpenSSL_RC4() { clear(); } + + void seek(u64bit) override + { + throw Exception("RC4 does not support seeking"); + } private: void cipher(const byte in[], byte out[], size_t length) override { diff --git a/src/lib/stream/chacha/chacha.cpp b/src/lib/stream/chacha/chacha.cpp index ac81fd70d..40da93029 100644 --- a/src/lib/stream/chacha/chacha.cpp +++ b/src/lib/stream/chacha/chacha.cpp @@ -12,8 +12,8 @@ namespace Botan { ChaCha::ChaCha(size_t rounds) : m_rounds(rounds) { - if(m_rounds != 12 && m_rounds != 20) - throw Invalid_Argument("ChaCha only supports 12 or 20 rounds"); + if(m_rounds != 8 && m_rounds != 12 && m_rounds != 20) + throw Invalid_Argument("ChaCha only supports 8, 12 or 20 rounds"); } namespace { @@ -67,7 +67,6 @@ void chacha(byte output[64], const u32bit input[16], size_t rounds) store_le(x14 + input[14], output + 4 * 14); store_le(x15 + input[15], output + 4 * 15); } - } /* @@ -173,4 +172,27 @@ std::string ChaCha::name() const return "ChaCha(" + std::to_string(m_rounds) + ")"; } +void ChaCha::seek(u64bit offset) + { + if (m_state.size() == 0 && m_buffer.size() == 0) + { + throw Invalid_State("You have to setup the stream cipher (key and iv)"); + } + + m_position = offset % m_buffer.size(); + + u64bit counter = offset / m_buffer.size(); + + byte out[8]; + + store_le(counter, out); + + m_state[12] = load_le(out, 0); + m_state[13] += load_le(out, 1); + + chacha(m_buffer.data(), m_state.data(), m_rounds); + + ++m_state[12]; + m_state[13] += (m_state[12] == 0); + } } diff --git a/src/lib/stream/chacha/chacha.h b/src/lib/stream/chacha/chacha.h index ba93d6260..f8f42e41d 100644 --- a/src/lib/stream/chacha/chacha.h +++ b/src/lib/stream/chacha/chacha.h @@ -21,7 +21,7 @@ class BOTAN_DLL ChaCha final : public StreamCipher StreamCipher* clone() const override { return new ChaCha(m_rounds); } /** - * Currently only 12 or 20 rounds are supported, all others + * Currently only 8, 12 or 20 rounds are supported, all others * will throw an exception */ ChaCha(size_t rounds); @@ -42,6 +42,8 @@ class BOTAN_DLL ChaCha final : public StreamCipher std::string name() const override; + void seek(u64bit offset) override; + private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/lib/stream/ctr/ctr.cpp b/src/lib/stream/ctr/ctr.cpp index f5301c099..43609ba2d 100644 --- a/src/lib/stream/ctr/ctr.cpp +++ b/src/lib/stream/ctr/ctr.cpp @@ -125,4 +125,8 @@ void CTR_BE::increment_counter() m_pad_pos = 0; } +void CTR_BE::seek(u64bit) + { + throw Not_Implemented("CTR_BE::seek"); + } } diff --git a/src/lib/stream/ctr/ctr.h b/src/lib/stream/ctr/ctr.h index 003297b92..5d5556254 100644 --- a/src/lib/stream/ctr/ctr.h +++ b/src/lib/stream/ctr/ctr.h @@ -46,6 +46,8 @@ class BOTAN_DLL CTR_BE final : public StreamCipher explicit CTR_BE(BlockCipher* cipher); CTR_BE(BlockCipher* cipher, size_t ctr_size); + + void seek(u64bit offset) override; private: void key_schedule(const byte key[], size_t key_len) override; void increment_counter(); diff --git a/src/lib/stream/ofb/ofb.cpp b/src/lib/stream/ofb/ofb.cpp index e8cb463db..3337a0c14 100644 --- a/src/lib/stream/ofb/ofb.cpp +++ b/src/lib/stream/ofb/ofb.cpp @@ -73,4 +73,9 @@ void OFB::set_iv(const byte iv[], size_t iv_len) m_buf_pos = 0; } + +void OFB::seek(u64bit) + { + throw Exception("OFB does not support seeking"); + } } diff --git a/src/lib/stream/ofb/ofb.h b/src/lib/stream/ofb/ofb.h index fecd47d9d..127a06578 100644 --- a/src/lib/stream/ofb/ofb.h +++ b/src/lib/stream/ofb/ofb.h @@ -44,6 +44,8 @@ class BOTAN_DLL OFB final : public StreamCipher * @param cipher the underlying block cipher to use */ explicit OFB(BlockCipher* cipher); + + void seek(u64bit offset) override; private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/lib/stream/rc4/rc4.cpp b/src/lib/stream/rc4/rc4.cpp index 895f38091..a4dea9e2b 100644 --- a/src/lib/stream/rc4/rc4.cpp +++ b/src/lib/stream/rc4/rc4.cpp @@ -113,4 +113,8 @@ void RC4::clear() */ RC4::RC4(size_t s) : m_SKIP(s) {} +void RC4::seek(u64bit) + { + throw Exception("RC4 does not support seeking"); + } } diff --git a/src/lib/stream/rc4/rc4.h b/src/lib/stream/rc4/rc4.h index f166a2772..88798fae6 100644 --- a/src/lib/stream/rc4/rc4.h +++ b/src/lib/stream/rc4/rc4.h @@ -39,6 +39,8 @@ class BOTAN_DLL RC4 final : public StreamCipher explicit RC4(size_t skip = 0); ~RC4() { clear(); } + + void seek(u64bit offset) override; private: void key_schedule(const byte[], size_t) override; void generate(); diff --git a/src/lib/stream/salsa20/salsa20.cpp b/src/lib/stream/salsa20/salsa20.cpp index 1d3fe3d28..f11fe5e59 100644 --- a/src/lib/stream/salsa20/salsa20.cpp +++ b/src/lib/stream/salsa20/salsa20.cpp @@ -227,4 +227,8 @@ void Salsa20::clear() m_position = 0; } +void Salsa20::seek(u64bit) + { + throw Not_Implemented("Salsa20::seek"); + } } diff --git a/src/lib/stream/salsa20/salsa20.h b/src/lib/stream/salsa20/salsa20.h index 7e75470da..8256ea4db 100644 --- a/src/lib/stream/salsa20/salsa20.h +++ b/src/lib/stream/salsa20/salsa20.h @@ -33,6 +33,8 @@ class BOTAN_DLL Salsa20 final : public StreamCipher void clear() override; std::string name() const override; StreamCipher* clone() const override { return new Salsa20; } + + void seek(u64bit offset) override; private: void key_schedule(const byte key[], size_t key_len) override; diff --git a/src/lib/stream/stream_cipher.h b/src/lib/stream/stream_cipher.h index bff1fd1a6..56bd2d5d9 100644 --- a/src/lib/stream/stream_cipher.h +++ b/src/lib/stream/stream_cipher.h @@ -80,6 +80,12 @@ class BOTAN_DLL StreamCipher : public SymmetricAlgorithm */ virtual StreamCipher* clone() const = 0; + /** + * Set the offset and the state used later to generate the keystream + * @param offset the offset where we begin to generate the keystream + */ + virtual void seek(u64bit offset) = 0; + StreamCipher(); virtual ~StreamCipher(); }; diff --git a/src/tests/data/stream/chacha.vec b/src/tests/data/stream/chacha.vec index 1c3c18c7c..f51ff0812 100644 --- a/src/tests/data/stream/chacha.vec +++ b/src/tests/data/stream/chacha.vec @@ -1,3 +1,104 @@ +[ChaCha(8)] + +# Tests got from the original implementation of Daniel J. Bernstein + +Key = 00000000000000000000000000000000 +Nonce = 0000000000000000 +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = E28A5FA4A67F8C5DEFED3E6FB7303486AA8427D31419A729572D777953491120B64AB8E72B8DEB85CD6AEA7CB6089A101824BEEB08814A428AAB1FA2C816081B + +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Nonce = 000000000000000000000002 +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = FD74BC4D822E344ACA041ACB39789BDA359D16B7709A7676B03B0F06117685B33B5E1E7DB844BE88ACCFC8370C808FB4BFBFDE831358476F09E34F2045AE61C0AC4120E44862548D3E5B577C695005115CFB158B9B6341BFC0561B9EAEE34D114583FB5FC901D5EA85019EAD2D4F618A5FC97954A5913576CD6BA32E710DA15A52D9A5B74B6E2F1D333C6405A5D6F64E2B1CED579A5FFBEB390A756755FED56AF37061CCC3A1D4DF6421F7A4D7811919F95A7F8533826DAB256A09E58CBFC5A04F83B063BBB169D2B05AFA6C8B3EC5880DB3346193860671AFFB3F9A5B56F771231393330816FFBD0E66F6D6B598178461CF5BE424A84A8D426DDB4B88FCB275 + +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 2E214501D03825E75AC476151531939D6DB48E04588D91CB6CAC080F87CDF6A95C6A0245E0333A970BB8E8C373A0CA81E2592224712B8002D3AA52835DF513F5D4CCCD346E24968A9BBE43C770EF563968821B21FDF26583F51D9F3ED89EBA912B2EC460C460BE062B8AE3604569FDFD0B1312F7705E9D7A33DCBE720D69308CD89AC06C58545C47148BD68C1E61A838DD3BFB88A5ADC721DEAB8147B9EC16A77FC8466C0B791D29AC2068769D8AA54A5D15A11580FA9A375F2D0072E1FB8EF5A27EF31B7710E196B3D061C911FFA93D067364D23B1FE69EA1318202BF94C8718CB44F4383D678C493A5C5502F02A9BA861534DD2BDC9559587BFEED4A08F5C3 + +# Test vector in a draft "Test Vectors for the Stream Cipher ChaCha draft-strombergson-chacha-test-vectors-00" available at the following link: http://tools.ietf.org/html/draft-strombergson-chacha-test-vectors-00. +# The document links a github repo where you can find all the vectors https://github.com/secworks/chacha_testvectors/ + +Key = 00000000000000000000000000000000 +Nonce = 0000000000000000 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = E28A5FA4A67F8C5DEFED3E6FB7303486AA8427D31419A729572D777953491120B64AB8E72B8DEB85CD6AEA7CB6089A101824BEEB08814A428AAB1FA2C816081B8A26AF448A1BA906368FD8C83831C18CEC8CED811A028E675B8D2BE8FCE081165CEAE9F1D1B7A975497749480569CEB83DE6A0A587D4984F19925F5D338E430D + +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Nonce = 0000000000000000 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 3E00EF2F895F40D67F5BB8E81F09A5A12C840EC3CE9A7F3B181BE188EF711A1E984CE172B9216F419F445367456D5619314A42A3DA86B001387BFDB80E0CFE42D2AEFA0DEAA5C151BF0ADB6C01F2A5ADC0FD581259F9A2AADCF20F8FD566A26B5032EC38BBC5DA98EE0C6F568B872A65A08ABF251DEB21BB4B56E5D8821E68AA + +Key = 01000000000000000000000000000000 +Nonce = 0000000000000000 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 03A7669888605A0765E8357475E58673F94FC8161DA76C2A3AA2F3CAF9FE5449E0FCF38EB882656AF83D430D410927D55C972AC4C92AB9DA3713E19F761EAA147138C25C8A7CE3D5E7546746FFD2E3515CE6A4B1B2D3F380138668ED39FA92F8A1AEE36258E05FAE6F566673511765FDB59E05163D55A708C5F9BC45045124CB + +Key = 0100000000000000000000000000000000000000000000000000000000000000 +Nonce = 0000000000000000 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = CF5EE9A0494AA9613E05D5ED725B804B12F4A465EE635ACC3A311DE8740489EA289D04F43C7518DB56EB4433E498A1238CD8464D3763DDBB9222EE3BD8FAE3C8B4355A7D93DD8867089EE643558B95754EFA2BD1A8A1E2D75BCDB32015542638291941FEB49965587C4FDFE219CF0EC132A6CD4DC067392E67982FE53278C0B4 + +Key = 00000000000000000000000000000000 +Nonce = 0100000000000000 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 25F5BEC6683916FF44BCCD12D102E692176663F4CAC53E719509CA74B6B2EEC85DA4236FB29902012ADC8F0D86C8187D25CD1C486966930D0204C4EE88A6AB355A6C9976C7BC6E78BAF3108C5364EF42B93B35D2694D2DDF72A4FC7ECDB968FCFE16BEDB8D48102FB54F1CE3636E914C0E2DADC7CAA2AB1929733A9263325E72 + +Key = 0000000000000000000000000000000000000000000000000000000000000000 +Nonce = 0100000000000000 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 2B8F4BB3798306CA5130D47C4F8D4ED13AA0EDCCC1BE6942090FAEECA0D7599B7FF0FE616BB25AA0153AD6FDC88B954903C22426D478B97B22B8F9B1DB00CF06470BDFFBC488A8B7C701EBF4061D75C5969186497C95367809AFA80BD843B040A79ABC6E73A91757F1DB73C8EACFA543B38F289D065AB2F3032D377B8C37FE46 + +Key = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Nonce = FFFFFFFFFFFFFFFF +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 2204D5B81CE662193E00966034F91302F14A3FB047F58B6E6EF0D721132304163E0FB640D76FF9C3B9CD99996E6E38FAD13F0E31C82244D33ABBC1B11E8BF12D9A81D78E9E56604DDFAE136921F51C9D81AE15119DB8E756DD28024493EE571D363AE4BBCD6E7D300F99D2673AEB92CCFC6E43A38DC31BACD66B28F17B22B28A + +Key = FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +Nonce = FFFFFFFFFFFFFFFF +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = E163BBF8C9A739D18925EE8362DAD2CDC973DF05225AFB2AA26396F2A9849A4A445E0547D31C1623C537DF4BA85C70A9884A35BCBF3DFAB077E98B0F68135F5481D4933F8B322AC0CD762C27235CE2B31534E0244A9A2F1FD5E94498D47FF108790C009CF9E1A348032A7694CB28024CD96D3498361EDB1785AF752D187AB54B + +Key = 55555555555555555555555555555555 +Nonce = 5555555555555555 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = F0A23BC36270E18ED0691DC384374B9B2C5CB60110A03F56FA48A9FBBAD961AA6BAB4D892E96261B6F1A0919514AE56F86E066E17C71A4176AC684AF1C931996950F754E728BD061D176ECF571C62A5EA5C776697B3193D3EA94CF17D7F0A14E504859D1A67C248AB298BE3BB7EDED3A23F61B6C5BD1A5A4CFC84BFC3D295AC5 + +Key = 5555555555555555555555555555555555555555555555555555555555555555 +Nonce = 5555555555555555 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 7CB78214E4D3465B6DC62CF7A1538C88996952B4FB72CB6105F1243CE3442E2975A59EBCD2B2A598290D7538491FE65BDBFEFD060D88798120A70D049DC2677DD48FF5A2513E497A5D54802D7484C4F1083944D8D0D14D6482CE09F7E5EBF20B29807D62C31874D02F5D3CC85381A745ECBC60525205E300A76961BFE51AC07C + +Key = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Nonce = AAAAAAAAAAAAAAAA +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 312D95C0BC38EFF4942DB2D50BDC500A30641EF7132DB1A8AE838B3BEA3A7AB03815D7A4CC09DBF5882A3433D743ACED48136EBAB73299506855C0F5437A36C6EF5AD3D6A4F6C35D9D66C2E34005B91BBBE3099E135A00CE2F700745BE6253195824D4B19F69731B6177E624358C7977E67552F519B470E3F7A8EC965DC3BEDA + +Key = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +Nonce = AAAAAAAAAAAAAAAA +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 40F9AB86C8F9A1A0CDC05A75E5531B612D71EF7F0CF9E387DF6ED6972F0AAE21311AA581F816C90E8A99DE990B6B95AAC92450F4E112712667B804C99E9C6EDAF8D144F560C8C0EA36880D3B77874C9A9103D147F6DED386284801A4EE158E5EA4F9C093FC55FD344C33349DC5B699E21DC83B4296F92EE3ECABF3D51F95FE3F + +Key = 00112233445566778899AABBCCDDEEFF +Nonce = 0F1E2D3C4B5A6978 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 29560D280B4528400A8F4B795369FB3A01105599E9F1ED58279CFC9ECE2DC5F99F1C2E52C98238F542A5C0A881D850B615D3ACD9FBDB026E9368565DA50E0D49DD5BE8EF74248B3E251D965D8FCB21E7CFE204D4007806FBEE3CE94C74BFBAD2C11C621BA048147C5CAA94D182CCFF6FD5CF44ADF96E3D68281BB49676AF87E7 + +Key = 00112233445566778899AABBCCDDEEFFFFEEDDCCBBAA99887766554433221100 +Nonce = 0F1E2D3C4B5A6978 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = DB43AD9D1E842D1272E4530E276B3F568F8859B3F7CF6D9D2C74FA53808CB5157A8EBF46AD3DCC4B6C7DADDE131784B0120E0E22F6D5F9FFA7407D4A21B695D9C5DD30BF55612FAB9BDD118920C19816470C7F5DCD42325DBBED8C57A56281C144CB0F03E81B3004624E0650A1CE5AFAF9A7CD8163F6DBD72602257DD96E471E + +Key = C46EC1B18CE8A878725A37E780DFB735 +Nonce = 1ADA31D5CF688221 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 6A870108859F679118F3E205E2A56A6826EF5A60A4102AC8D4770059FCB7C7BAE02F5CE004A6BFBBEA53014DD82107C0AA1C7CE11B7D78F2D50BD3602BBD25940560BB6A84289E0B38F5DD21D6EF6D7737E3EC0FB772DA2C71C2397762E5DBBBF449E3D1639CCBFA3E069C4D871ED6395B22AAF35C8DA6DE2DEC3D77880DA8E8 + +Key = C46EC1B18CE8A878725A37E780DFB7351F68ED2E194C79FBC6AEBEE1A667975D +Nonce = 1ADA31D5CF688221 +In = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 838751B42D8DDD8A3D77F48825A2BA752CF4047CB308A5978EF274973BE374C96AD848065871417B08F034E681FE46A93F7D5C61D1306614D4AAF257A7CFF08B16F2FDA170CC18A4B58A2667ED962774AF792A6E7F3C77992540711A7A136D7E8A2F8D3F93816709D45A3FA5F8CE72FDE15BE7B841ACBA3A2ABD557228D9FE4F [ChaCha(12)] @@ -43,8 +144,413 @@ In = 00000000000000000000000000000000000000000000000000000000000000000000000000 Out = F798A189F195E66982105FFB640BB7757F579DA31602FC93EC01AC56F85AC3C134A4547B733B46413042C9440049176905D3BE59EA1C53F15916155C2BE8241A38008B9A26BC35941E2444177C8ADE6689DE95264986D95889FB60E84629C9BD9A5ACB1CC118BE563EB9B3A4A472F82E09A7E778492B562EF7130E88DFE031C79DB9D4F7C7A899151B9A475032B63FC385245FE054E3DD5A97A5F576FE064025D3CE042C566AB2C507B138DB853E3D6959660996546CC9C4A6EAFDC777C040D70EAF46F76DAD3979E5C5360C3317166A1C894C94A371876A94DF7628FE4EAAF2CCB27D5AAAE0AD7AD0F9D4B6AD3B54098746D4524D38407A6DEB # From draft-irtf-cfrg-chacha20-poly1305-03 +# Key = 0000000000000000000000000000000000000000000000000000000000000000 Nonce = 000000000000000000000002 In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 Out = C2C64D378CD536374AE204B9EF933FCD1A8B2288B3DFA49672AB765B54EE27C78A970E0E955C14F3A88E741B97C286F75F8FC299E8148362FA198A39531BED6D +# Test seek offset +# Tests got from the original implementation of Daniel J. Bernstein +# +Seek = 0 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 103AF111C18B549D39248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED + +Seek = 1 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 3AF111C18B549D39248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89 + +Seek = 2 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = F111C18B549D39248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB + +Seek = 3 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 11C18B549D39248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08 + +Seek = 4 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = C18B549D39248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB0800 + +Seek = 5 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 8B549D39248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB080029 + +Seek = 6 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 549D39248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917 + +Seek = 7 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 9D39248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A5 + +Seek = 8 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 39248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540 + +Seek = 9 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 248FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7 + +Seek = 10 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 8FB07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B783 + +Seek = 11 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = B07D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833F + +Seek = 12 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 7D60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3 + +Seek = 13 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 60C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF398 + +Seek = 14 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = C29A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D + +Seek = 15 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 9A95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E + +Seek = 16 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 95D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63 + +Seek = 17 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = D1DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C9 + +Seek = 18 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = DB88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970 + +Seek = 19 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 88D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2 + +Seek = 20 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = D892F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E7 + +Seek = 21 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 92F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E751 + +Seek = 22 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = F7B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174 + +Seek = 23 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = B4AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174AD + +Seek = 24 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = AF709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9 + +Seek = 25 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 709A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6 + +Seek = 26 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 9A5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E697 + +Seek = 27 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 5FD47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972F + +Seek = 28 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = D47A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC5 + +Seek = 29 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 7A9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575 + +Seek = 30 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 9E4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0 + +Seek = 31 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 4BD5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A6 + +Seek = 32 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = D5FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63C + +Seek = 33 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = FF9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC + +Seek = 34 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 9A658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC80 + +Seek = 35 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 658DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802C + +Seek = 36 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 8DD52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3 + +Seek = 37 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = D52C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E6 + +Seek = 38 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 2C708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61E + +Seek = 39 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 708BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB1 + +Seek = 40 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 8BEF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198 + +Seek = 41 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = EF1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB19837 + +Seek = 42 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 1F0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB1983732 + +Seek = 43 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 0F622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276 + +Seek = 44 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 622B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D8 + +Seek = 45 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 2B3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865 + +Seek = 46 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 3747040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D86594 + +Seek = 47 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 47040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F + +Seek = 48 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 040FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F23 + +Seek = 49 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 0FA3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E + +Seek = 50 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = A3551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84 + +Seek = 51 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 551300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A9 + +Seek = 52 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 1300B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974 + +Seek = 53 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 00B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD + +Seek = 54 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = B1F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28 + +Seek = 55 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = F293150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B8 + +Seek = 56 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 93150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B + +Seek = 57 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 150A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B12 + +Seek = 58 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 0A88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B12B8 + +Seek = 59 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 88620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B12B8D9 + +Seek = 60 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 620D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B12B8D907 + +Seek = 61 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 0D5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B12B8D90790 + +Seek = 62 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 5FED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B12B8D907904F + +Seek = 63 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = ED89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B12B8D907904F9E + +Seek = 64 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = 89FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B12B8D907904F9ED6 + +Seek = 65 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = FB08002917A540B7833FF3981D0E63C970B2E75174ADB9E6972FC575C0A63CEC802CF3E61EB198373276D865948F237E84A974FD28B89B12B8D907904F9ED679 + +Seek = 4294967232 +Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F +Nonce = 000102030405060708090A0B +In = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +Out = DBF81BB406517BE1A54F4740E5DDDF2B7965747B757FA9D5B7EDD6B27FEDDB89D5D47F9B24E57DF393017A5079F61852CD8B86859884120AF867D25D3B259E2B diff --git a/src/tests/test_stream.cpp b/src/tests/test_stream.cpp index 232fdcdd9..d3d83c26c 100644 --- a/src/tests/test_stream.cpp +++ b/src/tests/test_stream.cpp @@ -18,7 +18,7 @@ class Stream_Cipher_Tests : public Text_Based_Test { public: Stream_Cipher_Tests(): Text_Based_Test("stream", - {"Key", "In", "Out"}, {"Nonce"}) {} + {"Key", "In", "Out"}, {"Nonce", "Seek"}) {} Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { @@ -26,6 +26,7 @@ class Stream_Cipher_Tests : public Text_Based_Test const std::vector input = get_req_bin(vars, "In"); const std::vector expected = get_req_bin(vars, "Out"); const std::vector nonce = get_opt_bin(vars, "Nonce"); + const size_t seek = get_opt_sz(vars, "Seek", 0); Test::Result result(algo); @@ -53,6 +54,9 @@ class Stream_Cipher_Tests : public Text_Based_Test if(nonce.size()) cipher->set_iv(nonce.data(), nonce.size()); + if (seek != 0) + cipher->seek(seek); + std::vector buf = input; cipher->encrypt(buf); -- cgit v1.2.3 From 6975d0d59bb51f42d6cca3e23c5f5646ef2f24b2 Mon Sep 17 00:00:00 2001 From: Mouse Date: Fri, 17 Jun 2016 22:35:47 -0400 Subject: Fix bug that prevents LaTeX documentation from being built --- doc/manual/srp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'doc') diff --git a/doc/manual/srp.rst b/doc/manual/srp.rst index e3aace5ff..74b67d890 100644 --- a/doc/manual/srp.rst +++ b/doc/manual/srp.rst @@ -10,7 +10,7 @@ This verifier is based on a password, but the password cannot be easily derived from the verifier. Later, the client and server can perform an SRP exchange, in which - .. warning:: +.. warning:: While knowledge of the verifier does not easily allow an attacker to get the raw password, they could still use the verifier to -- cgit v1.2.3 From 25a83f8a35f9a02de85b5d66474a92ab34a88c3b Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Sat, 18 Jun 2016 10:07:09 -0400 Subject: Update release notes [ci skip] --- doc/news.rst | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index 38c6c797b..eaf0c872b 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -42,14 +42,15 @@ Version 1.11.30, Not Yet Released * The Transform and Keyed_Transform interfaces has been removed. The two concrete implementations of these interfaces were Cipher_Mode - and the Compressor_tkk. The Cipher_Mode interface remains unchanged + and Compressor_Transform. The Cipher_Mode interface remains unchanged as the Transform and Keyed_Transform signatures have moved to it; no changes to Cipher_Mode usage should be necessary. Any uses of Transform& or Keyed_Transform& to refer to a cipher should be replaced by Cipher_Mode&. The compression algorithm interface has changed; the start function now takes the per-message compression ratio to use. Previously the compression level to use had to be set once, at creation time, and - the required `secure_vector` argument to start was required to be empty. + the required ``secure_vector`` argument to ``start`` was required to be empty. + The new API is documented in `compression.rst` in the manual. * Add IETF versions of the ChaCha20Poly1305 TLS ciphersuites from draft-ietf-tls-chacha20-poly1305-04. The previously implemented @@ -69,12 +70,20 @@ Version 1.11.30, Not Yet Released * X509_CRL previously had an option to cause it to ignore unknown critical extensions. This has been removed. -* Added support for ChaCha stream cipher with 12 rounds. +* Added StreamCipher::seek allowing seeking to arbitrary position + in the key stream. Currently only implemented for ChaCha. (GH #497) + +* Added support for ChaCha stream cipher with 8 or 12 rounds. * Add ECGDSA signature algorithm (GH #479) +* Add support for label argument to KDFs (GH #495) + * Add NIST SP800-108 and 56C KDFs (GH #481) +* Support for Card Verifiable Certificates and the obsolete EMSA1_BSI + signature padding scheme have been removed. (GH #487) + * A bug in the IETF version of ChaCha20Poly1305 (with 96 bit nonces) caused incorrect computation when the plaintext or AAD was exactly a multiple of 16 bytes. -- cgit v1.2.3 From 0b6d2a853638206dfa43420d5419e8b719505cc7 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Sun, 19 Jun 2016 00:24:30 -0400 Subject: Update for 1.11.30 release --- doc/news.rst | 2 +- readme.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index eaf0c872b..c5b99a12e 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -1,7 +1,7 @@ Release Notes ======================================== -Version 1.11.30, Not Yet Released +Version 1.11.30, 2016-06-19 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * In 1.11.23 a bug was introduced such that CBC-encrypted TLS packets diff --git a/readme.rst b/readme.rst index 0fe50df7c..d79da637f 100644 --- a/readme.rst +++ b/readme.rst @@ -97,9 +97,9 @@ Versions 1.11 and later require a working C++11 compiler; GCC 4.8 and later, Clang 3.4 and later, and MSVC 2013 are regularly tested. The latest development release is -`1.11.29 `_ -`(sig) `_ -released on 2016-03-20 +`1.11.30 `_ +`(sig) `_ +released on 2016-06-19 Old Stable Series (1.10) ---------------------------------------- -- cgit v1.2.3 From 4bff0f41baa6c61d7b3f648dfeb97ac955993970 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Sun, 19 Jun 2016 01:22:33 -0400 Subject: Tick to 1.11.31 [ci skip] --- botan_version.py | 2 +- doc/news.rst | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'doc') diff --git a/botan_version.py b/botan_version.py index e5e2b811a..c737e21a0 100644 --- a/botan_version.py +++ b/botan_version.py @@ -1,7 +1,7 @@ release_major = 1 release_minor = 11 -release_patch = 30 +release_patch = 31 release_so_abi_rev = release_patch # These are set by the distribution script diff --git a/doc/news.rst b/doc/news.rst index c5b99a12e..e9069565a 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -1,6 +1,9 @@ Release Notes ======================================== +Version 1.11.31, Not Yet Released +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Version 1.11.30, 2016-06-19 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From 0414a4f46c090e3e61d2f26d27bf5979f6d80ba9 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Mon, 4 Jul 2016 18:54:49 -0400 Subject: Update news.rst with changes so far for 1.11.31 [ci skip] --- doc/news.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index e9069565a..bf2ae4d6a 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -4,6 +4,17 @@ Release Notes Version 1.11.31, Not Yet Released ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* Add PKCS #11 support (GH #507) + +* Add ECIES encryption system (GH #483) + +* Add ECKCDSA signature algorithm (#504) + +* Add KDF1 from ISO 18033 (GH #483) + +* Fixes for FreeBSD (GH #517) and OpenBSD (GH #523) + + Version 1.11.30, 2016-06-19 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From b3bc80dfdb28aee0900b6ed92dff5ba8c5e4daf9 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Mon, 11 Jul 2016 13:18:43 -0400 Subject: Deprecate EGD --- doc/news.rst | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index bf2ae4d6a..8c4db8b09 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -14,6 +14,10 @@ Version 1.11.31, Not Yet Released * Fixes for FreeBSD (GH #517) and OpenBSD (GH #523) +* Support for getting entropy from EGD is deprecated, and will be removed in + a future release. The developers believe that it is unlikely that any modern + system requires EGD and so the code is now dead weight. If you rely on EGD + support, you should contact the developers by email or GitHub ASAP. Version 1.11.30, 2016-06-19 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From 2c8799b3d91e12b21eb3789f5cedc8a4fb7aaec1 Mon Sep 17 00:00:00 2001 From: Daniel Neus Date: Mon, 11 Jul 2016 14:13:00 +0200 Subject: DLIES rework With these fixes the implementation is now compatible with bouncycastle and it should operate as it is specified in "DHIES: An encryption scheme based on Diffie-Hellman Problem" or in BSI technical guideline TR-02102-1. In addition to the already present XOR-encrypion/decryption mode it's now possible to use DLIES with a block cipher. Previously the input to the KDF was the concatenation of the (ephemeral) public key and the secret value derived by the key agreement operation: ``` secure_vector vz(m_my_key.begin(), m_my_key.end()); vz += m_ka.derive_key(0, m_other_key).bits_of(); const size_t K_LENGTH = length + m_mac_keylen; secure_vector K = m_kdf->derive_key(K_LENGTH, vz); ``` I don't know why this was implemented like this. But now the input to the KDF is only the secret value obtained by the key agreement operation. Furthermore the order of the output was changed from {public key, tag, ciphertext} to {public key, ciphertext, tag}. Multiple test vectors added that were generated with bouncycastle and some with botan itself. --- doc/credits.rst | 6 + doc/license.txt | 1 + doc/news.rst | 11 + src/lib/pubkey/dlies/dlies.cpp | 257 ++++++---- src/lib/pubkey/dlies/dlies.h | 101 +++- src/lib/pubkey/dlies/info.txt | 3 +- src/tests/data/pubkey/dlies.vec | 1000 +++++++++++++++++++++++++++++++++++++-- src/tests/test_dlies.cpp | 151 +++++- 8 files changed, 1381 insertions(+), 149 deletions(-) (limited to 'doc') diff --git a/doc/credits.rst b/doc/credits.rst index d9d7f2c71..290067491 100644 --- a/doc/credits.rst +++ b/doc/credits.rst @@ -124,3 +124,9 @@ snail-mail address (S), and Bitcoin address (B). W: https://sirrix.com/ D: KDF1-18033, ECIES S: Saarland, Germany + + N: Daniel Neus + E: d.neus@sirrix.com + W: https://sirrix.com/ + D: CI, PKCS#11, RdSeed, BSI module policy + S: Bochum, Germany diff --git a/doc/license.txt b/doc/license.txt index fd4fd0a7b..b097646e8 100644 --- a/doc/license.txt +++ b/doc/license.txt @@ -30,6 +30,7 @@ Copyright (C) 1999-2013,2014,2015,2016 Jack Lloyd 2015 Uri Blumenthal 2015,2016 Kai Michaelis 2016 Simon Cogliani + 2015,2016 Rohde & Schwarz Cybersecurity All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/doc/news.rst b/doc/news.rst index 8c4db8b09..e6ab279cf 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -18,6 +18,17 @@ Version 1.11.31, Not Yet Released a future release. The developers believe that it is unlikely that any modern system requires EGD and so the code is now dead weight. If you rely on EGD support, you should contact the developers by email or GitHub ASAP. + +* Changes in DLIES: Previously the input to the KDF was the concatenation + of the (ephemeral) public key and the secret value derived by the key + agreement operation. Now the input is only the secret value obtained + by the key agreement operation. That's how it is specified in the original + paper "DHIES: An encryption scheme based on Diffie-Hellman Problem" or in BSI + technical guideline TR-02102-1 for example. In addition to the already present + XOR-encrypion/decryption mode it's now possible to use DLIES with a block cipher. + Furthermore the order of the output was changed from {public key, tag, ciphertext} + to {public key, ciphertext, tag}. Both modes are compatible with bouncycastle. + Version 1.11.30, 2016-06-19 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/lib/pubkey/dlies/dlies.cpp b/src/lib/pubkey/dlies/dlies.cpp index 2c98966b0..9666a1c23 100644 --- a/src/lib/pubkey/dlies/dlies.cpp +++ b/src/lib/pubkey/dlies/dlies.cpp @@ -1,6 +1,7 @@ /* * DLIES * (C) 1999-2007 Jack Lloyd +* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -10,128 +11,204 @@ namespace Botan { -/* -* DLIES_Encryptor Constructor -*/ -DLIES_Encryptor::DLIES_Encryptor(const PK_Key_Agreement_Key& key, - KDF* kdf_obj, - MessageAuthenticationCode* mac_obj, - size_t mac_kl) : - m_ka(key, "Raw"), - m_kdf(kdf_obj), - m_mac(mac_obj), - m_mac_keylen(mac_kl) +DLIES_Encryptor::DLIES_Encryptor(const DH_PrivateKey& own_priv_key, + KDF* kdf, + MessageAuthenticationCode* mac, + size_t mac_key_length) : + DLIES_Encryptor(own_priv_key, kdf, nullptr, 0, mac, mac_key_length) { - BOTAN_ASSERT_NONNULL(kdf_obj); - BOTAN_ASSERT_NONNULL(mac_obj); - m_my_key = key.public_value(); } -/* -* DLIES Encryption -*/ +DLIES_Encryptor::DLIES_Encryptor(const DH_PrivateKey& own_priv_key, + KDF* kdf, + Cipher_Mode* cipher, + size_t cipher_key_len, + MessageAuthenticationCode* mac, + size_t mac_key_length) : + m_other_pub_key(), + m_own_pub_key(own_priv_key.public_value()), + m_ka(own_priv_key, "Raw"), + m_kdf(kdf), + m_cipher(cipher), + m_cipher_key_len(cipher_key_len), + m_mac(mac), + m_mac_keylen(mac_key_length), + m_iv() + { + BOTAN_ASSERT_NONNULL(kdf); + BOTAN_ASSERT_NONNULL(mac); + } + std::vector DLIES_Encryptor::enc(const byte in[], size_t length, RandomNumberGenerator&) const { - if(length > maximum_input_size()) - throw Invalid_Argument("DLIES: Plaintext too large"); - if(m_other_key.empty()) + if(m_other_pub_key.empty()) + { throw Invalid_State("DLIES: The other key was never set"); + } - secure_vector out(m_my_key.size() + length + m_mac->output_length()); - buffer_insert(out, 0, m_my_key); - buffer_insert(out, m_my_key.size(), in, length); + // calculate secret value + const SymmetricKey secret_value = m_ka.derive_key(0, m_other_pub_key); - secure_vector vz(m_my_key.begin(), m_my_key.end()); - vz += m_ka.derive_key(0, m_other_key).bits_of(); + // derive secret key from secret value + const size_t required_key_length = m_cipher ? m_cipher_key_len + m_mac_keylen : length + m_mac_keylen; + const secure_vector secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of()); - const size_t K_LENGTH = length + m_mac_keylen; - secure_vector K = m_kdf->derive_key(K_LENGTH, vz); - - if(K.size() != K_LENGTH) + if(secret_keys.size() != required_key_length) + { throw Encoding_Error("DLIES: KDF did not provide sufficient output"); - byte* C = &out[m_my_key.size()]; - - m_mac->set_key(K.data(), m_mac_keylen); - xor_buf(C, &K[m_mac_keylen], length); - - m_mac->update(C, length); - for(size_t j = 0; j != 8; ++j) - m_mac->update(0); - - m_mac->final(C + length); + } + + secure_vector ciphertext(in, in + length); + const size_t cipher_key_len = m_cipher ? m_cipher_key_len : length; + + if(m_cipher) + { + SymmetricKey enc_key(secret_keys.data(), cipher_key_len); + m_cipher->set_key(enc_key); + + if(m_iv.size()) + { + m_cipher->start(m_iv.bits_of()); + } + + m_cipher->finish(ciphertext); + } + else + { + xor_buf(ciphertext, secret_keys, cipher_key_len); + } + + // calculate MAC + m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen); + secure_vector tag = m_mac->process(ciphertext); + + // out = (ephemeral) public key + ciphertext + tag + secure_vector out(m_own_pub_key.size() + ciphertext.size() + tag.size()); + buffer_insert(out, 0, m_own_pub_key); + buffer_insert(out, 0 + m_own_pub_key.size(), ciphertext); + buffer_insert(out, 0 + m_own_pub_key.size() + ciphertext.size(), tag); return unlock(out); } -/* -* Set the other parties public key -*/ -void DLIES_Encryptor::set_other_key(const std::vector& ok) - { - m_other_key = ok; - } - -/* +/** * Return the max size, in bytes, of a message +* Not_Implemented if DLIES is used in XOR encryption mode */ size_t DLIES_Encryptor::maximum_input_size() const { - return 32; + if(m_cipher) + { + // no limit in block cipher mode + return std::numeric_limits::max(); + } + else + { + // No way to determine if the KDF will output enough bits for XORing with the plaintext?! + throw Not_Implemented("Not implemented for XOR encryption mode"); + } } -/* -* DLIES_Decryptor Constructor -*/ -DLIES_Decryptor::DLIES_Decryptor(const PK_Key_Agreement_Key& key, - KDF* kdf_obj, - MessageAuthenticationCode* mac_obj, - size_t mac_kl) : - m_ka(key, "Raw"), - m_kdf(kdf_obj), - m_mac(mac_obj), - m_mac_keylen(mac_kl) +DLIES_Decryptor::DLIES_Decryptor(const DH_PrivateKey& own_priv_key, + KDF* kdf, + Cipher_Mode* cipher, + size_t cipher_key_len, + MessageAuthenticationCode* mac, + size_t mac_key_length) : + m_pub_key_size(own_priv_key.public_value().size()), + m_ka(own_priv_key, "Raw"), + m_kdf(kdf), + m_cipher(cipher), + m_cipher_key_len(cipher_key_len), + m_mac(mac), + m_mac_keylen(mac_key_length), + m_iv() { - m_my_key = key.public_value(); + BOTAN_ASSERT_NONNULL(kdf); + BOTAN_ASSERT_NONNULL(mac); } -/* -* DLIES Decryption -*/ +DLIES_Decryptor::DLIES_Decryptor(const DH_PrivateKey& own_priv_key, + KDF* kdf, + MessageAuthenticationCode* mac, + size_t mac_key_length) : + DLIES_Decryptor(own_priv_key, kdf, nullptr, 0, mac, mac_key_length) + {} + secure_vector DLIES_Decryptor::do_decrypt(byte& valid_mask, - const byte msg[], size_t length) const + const byte msg[], size_t length) const { - if(length < m_my_key.size() + m_mac->output_length()) + if(length < m_pub_key_size + m_mac->output_length()) + { throw Decoding_Error("DLIES decryption: ciphertext is too short"); + } - const size_t CIPHER_LEN = length - m_my_key.size() - m_mac->output_length(); - - std::vector v(msg, msg + m_my_key.size()); + // calculate secret value + std::vector other_pub_key(msg, msg + m_pub_key_size); + const SymmetricKey secret_value = m_ka.derive_key(0, other_pub_key); - secure_vector C(msg + m_my_key.size(), msg + m_my_key.size() + CIPHER_LEN); + const size_t ciphertext_len = length - m_pub_key_size - m_mac->output_length(); + size_t cipher_key_len = m_cipher ? m_cipher_key_len : ciphertext_len; - secure_vector T(msg + m_my_key.size() + CIPHER_LEN, - msg + m_my_key.size() + CIPHER_LEN + m_mac->output_length()); + // derive secret key from secret value + const size_t required_key_length = cipher_key_len + m_mac_keylen; + secure_vector secret_keys = m_kdf->derive_key(required_key_length, secret_value.bits_of()); - secure_vector vz(msg, msg + m_my_key.size()); - vz += m_ka.derive_key(0, v).bits_of(); - - const size_t K_LENGTH = C.size() + m_mac_keylen; - secure_vector K = m_kdf->derive_key(K_LENGTH, vz); - if(K.size() != K_LENGTH) + if(secret_keys.size() != required_key_length) + { throw Encoding_Error("DLIES: KDF did not provide sufficient output"); - - m_mac->set_key(K.data(), m_mac_keylen); - m_mac->update(C); - for(size_t j = 0; j != 8; ++j) - m_mac->update(0); - secure_vector T2 = m_mac->final(); - - valid_mask = CT::expand_mask(same_mem(T.data(), T2.data(), T.size())); - - xor_buf(C, K.data() + m_mac_keylen, C.size()); - - return C; + } + + secure_vector ciphertext(msg + m_pub_key_size, msg + m_pub_key_size + ciphertext_len); + + // calculate MAC + m_mac->set_key(secret_keys.data() + cipher_key_len, m_mac_keylen); + secure_vector calculated_tag = m_mac->process(ciphertext); + + // calculated tag == received tag ? + secure_vector tag(msg + m_pub_key_size + ciphertext_len, + msg + m_pub_key_size + ciphertext_len + m_mac->output_length()); + + valid_mask = CT::expand_mask(same_mem(tag.data(), calculated_tag.data(), tag.size())); + + // decrypt + if(m_cipher) + { + if(valid_mask) + { + SymmetricKey dec_key(secret_keys.data(), cipher_key_len); + m_cipher->set_key(dec_key); + + try + { + // the decryption can fail: + // e.g. Integrity_Failure is thrown if GCM is used and the message does not have a valid tag + + if(m_iv.size()) + { + m_cipher->start(m_iv.bits_of()); + } + + m_cipher->finish(ciphertext); + } + catch(...) + { + valid_mask = 0; + } + + } + else + { + return secure_vector(); + } + } + else + { + xor_buf(ciphertext, secret_keys.data(), cipher_key_len); + } + + return ciphertext; } } diff --git a/src/lib/pubkey/dlies/dlies.h b/src/lib/pubkey/dlies/dlies.h index 10471048d..5f7251d03 100644 --- a/src/lib/pubkey/dlies/dlies.h +++ b/src/lib/pubkey/dlies/dlies.h @@ -1,6 +1,7 @@ /* * DLIES * (C) 1999-2007 Jack Lloyd +* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -11,6 +12,8 @@ #include #include #include +#include +#include namespace Botan { @@ -20,24 +23,67 @@ namespace Botan { class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor { public: - DLIES_Encryptor(const PK_Key_Agreement_Key&, + /** + * Stream mode: use KDF to provide a stream of bytes to xor with the message + * + * @param own_priv_key own (ephemeral) DH private key + * @param kdf the KDF that should be used + * @param mac the MAC function that should be used + * @param mac_key_len key length of the MAC function. Default = 20 bytes + * + * output = (ephemeral) public key + ciphertext + tag + */ + DLIES_Encryptor(const DH_PrivateKey& own_priv_key, KDF* kdf, MessageAuthenticationCode* mac, size_t mac_key_len = 20); - void set_other_key(const std::vector&); + /** + * Block cipher mode + * + * @param own_priv_key own (ephemeral) DH private key + * @param kdf the KDF that should be used + * @param cipher the block cipher that should be used + * @param cipher_key_len the key length of the block cipher + * @param mac the MAC function that should be used + * @param mac_key_len key length of the MAC function. Default = 20 bytes + * + * output = (ephemeral) public key + ciphertext + tag + */ + DLIES_Encryptor(const DH_PrivateKey& own_priv_key, + KDF* kdf, + Cipher_Mode* cipher, + size_t cipher_key_len, + MessageAuthenticationCode* mac, + size_t mac_key_len = 20); + + // Set the other parties public key + inline void set_other_key(const std::vector& other_pub_key) + { + m_other_pub_key = other_pub_key; + } + + /// Set the initialization vector for the data encryption method + inline void set_initialization_vector(const InitializationVector& iv) + { + m_iv = iv; + } + private: std::vector enc(const byte[], size_t, RandomNumberGenerator&) const override; size_t maximum_input_size() const override; - std::vector m_other_key, m_my_key; - + std::vector m_other_pub_key; + std::vector m_own_pub_key; PK_Key_Agreement m_ka; std::unique_ptr m_kdf; + std::unique_ptr m_cipher; + const size_t m_cipher_key_len; std::unique_ptr m_mac; - size_t m_mac_keylen; + const size_t m_mac_keylen; + InitializationVector m_iv; }; /** @@ -46,21 +92,58 @@ class BOTAN_DLL DLIES_Encryptor : public PK_Encryptor class BOTAN_DLL DLIES_Decryptor : public PK_Decryptor { public: - DLIES_Decryptor(const PK_Key_Agreement_Key&, + /** + * Stream mode: use KDF to provide a stream of bytes to xor with the message + * + * @param own_priv_key own (ephemeral) DH private key + * @param kdf the KDF that should be used + * @param mac the MAC function that should be used + * @param mac_key_len key length of the MAC function. Default = 20 bytes + * + * input = (ephemeral) public key + ciphertext + tag + */ + DLIES_Decryptor(const DH_PrivateKey& own_priv_key, KDF* kdf, MessageAuthenticationCode* mac, size_t mac_key_len = 20); + /** + * Block cipher mode + * + * @param own_priv_key own (ephemeral) DH private key + * @param kdf the KDF that should be used + * @param cipher the block cipher that should be used + * @param cipher_key_len the key length of the block cipher + * @param mac the MAC function that should be used + * @param mac_key_len key length of the MAC function. Default = 20 bytes + * + * input = (ephemeral) public key + ciphertext + tag + */ + DLIES_Decryptor(const DH_PrivateKey& own_priv_key, + KDF* kdf, + Cipher_Mode* cipher, + size_t cipher_key_len, + MessageAuthenticationCode* mac, + size_t mac_key_len = 20); + + /// Set the initialization vector for the data decryption method + inline void set_initialization_vector(const InitializationVector& iv) + { + m_iv = iv; + } + private: secure_vector do_decrypt(byte& valid_mask, const byte in[], size_t in_len) const override; - std::vector m_my_key; - + const size_t m_pub_key_size; PK_Key_Agreement m_ka; std::unique_ptr m_kdf; + std::unique_ptr m_cipher; + const size_t m_cipher_key_len; std::unique_ptr m_mac; - size_t m_mac_keylen; + const size_t m_mac_keylen; + InitializationVector m_iv; }; } diff --git a/src/lib/pubkey/dlies/info.txt b/src/lib/pubkey/dlies/info.txt index ec1bac803..30362ad78 100644 --- a/src/lib/pubkey/dlies/info.txt +++ b/src/lib/pubkey/dlies/info.txt @@ -1,6 +1,7 @@ -define DLIES 20131128 +define DLIES 20160713 kdf mac +block diff --git a/src/tests/data/pubkey/dlies.vec b/src/tests/data/pubkey/dlies.vec index d0546b4e0..245cdeddc 100644 --- a/src/tests/data/pubkey/dlies.vec +++ b/src/tests/data/pubkey/dlies.vec @@ -1,42 +1,982 @@ +########################### Test vectors created with bouncycastle 1.54 ########################### -P = 179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194467627007 +########### Block cipher mode ########### + +#public static void main(String[] args) throws InvalidCipherTextException { +# // 2048-bit MODP Group. RFC3526 +# BigInteger g = new BigInteger( "2", 10 ); +# BigInteger p = new BigInteger( "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A0879" +# + "8E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +# + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +# + "83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +# + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +# + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16 ); +# +# DHParameters dhParams = new DHParameters( p, g ); +# +# // alice priv key +# BigInteger xAlice = new BigInteger( "A01E167DE1013D6859E6CB068B7BF272C1D49DC764AD7676BFA0D85177", 16 ); +# DHPrivateKeyParameters alicePriv = new DHPrivateKeyParameters( xAlice, dhParams ); +# +# // alice pub key +# BigInteger yAlice = g.modPow(xAlice, p); +# DHPublicKeyParameters alicePub = new DHPublicKeyParameters( yAlice, dhParams ); +# +# // bob priv key +# BigInteger xBob = new BigInteger( "8DD88BDC19AC1403A3FC3A0FC63D360F1062E3494177DC27F7EBCBD4A7", 16 ); +# +# // bob pub key +# BigInteger yBob = g.modPow(xBob, p); +# DHPublicKeyParameters bobPub = new DHPublicKeyParameters( yBob, dhParams ); +# +# // DLIES +# byte[] d = new byte[ 0 ]; // the derivation parameter for the KDF function +# byte[] e = new byte[ 0 ]; // the encoding parameter for the KDF function +# int macKeySize = 256; +# int cipherKeySize = 256; +# byte[] iv = new byte[ 16 ]; +# CipherParameters cipherParams = new ParametersWithIV( new IESWithCipherParameters( d, e, macKeySize, cipherKeySize ), iv ); +# +# IESEngine dlies = +# new IESEngine( new DHBasicAgreement(), new KDF2BytesGenerator( new SHA256Digest() ), new HMac( new SHA256Digest() ), new PaddedBufferedBlockCipher( new CBCBlockCipher( +# new AESEngine() ) ) ); +# dlies.init( true, alicePriv, bobPub, cipherParams ); +# +# byte[] message = Hex.decode( "00" ); +# byte[] result = dlies.processBlock( message, 0, message.length ); +# +# byte[] ephPublicKey = alicePub.getY().toByteArray(); +# byte[] out = Arrays.concatenate( ephPublicKey, result ); +# +# System.out.println( Hex.toHexString( out ) ); + +####### KDF2 + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb7c5f222b4215cd1b1c197fe8cfa2a252ad4c61a599ade3c8e8d0442b93afc626405fbe7bb1d103bdd8ce9468071a013f0f627c2cdcd61a253bbf81feb5ae6093aee4a5bd71f2a2f20764615d0e70561903de24a46cfbc9340f4fe5ce209ad48c97a4e3a3c5c75186a020f4b44008f270 + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb7c5f222b4215cd1b1c197fe8cfa2a252ad4c61a599ade3c8e8d0442b93afc626405fbe7bb1d103bdd8ce9468071a013f5be4a46a387f09e11d75b5d21993f4eeb287410282007dba329b59a588d84888dd6f6c8d74047ae9b82097e64da28721e70adb43526752aac237f565cdebf0be + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb7c5f222b4215cd1b1c197fe8cfa2a252ad4c61a599ade3c8e8d0442b93afc626405fbe7bb1d103bdd8ce9468071a013ff78712a17c1894f458195e0fff798d995090d935e3deb25e13fedb9abbce760da4f49b70ae6e0b6c6261a182386b687873e03f24ac64dd74ce841a4ab04a2bb6 + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbe0004a18072d33b7a7ac09362953dec57197a78ccdac0f1aa98d2a2eb6580a48053b0df23dfe2518253813dc1d1e6651cfefdaa03d8a2bd25201f40abbae203d1487b0d79c57aef0c5d2fb05f9f86f8fa2806eb3cec40a46b9bf7589142ef680bea0cf197e28dd4615c6f921418a4f54 + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbe0004a18072d33b7a7ac09362953dec57197a78ccdac0f1aa98d2a2eb6580a48053b0df23dfe2518253813dc1d1e6651457da847bc1f337d1219222f97d75fb2ae68938e7f28d7e9595b87627d07d0bed859d0fb0077655b1c36ec12024cfedb4f8db121fd82e3029c27f8bac0c6ba1e + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbe0004a18072d33b7a7ac09362953dec57197a78ccdac0f1aa98d2a2eb6580a48053b0df23dfe2518253813dc1d1e66513c34a7effee403da2137493cd7f3e55b77a0cdd894c7126cea1d50956297e9316ca319ae00b59f45fdc781d0569825835376d3ad8876d1e5351c958cc858de25 + +Kdf = KDF2(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb97f3ed7829ec1c4b6d22646252e19a267df9b0100f47f6a376c9b9d9c35a446d1eb7b12fe7f6d6e659d9c83c3c9b3c2a51405729857b99429f910de4fd993092b037a8270bbedcc5168f821167a256e4 + +Kdf = KDF2(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 16 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb97f3ed7829ec1c4b6d22646252e19a267df9b0100f47f6a376c9b9d9c35a446d1eb7b12fe7f6d6e659d9c83c3c9b3c2a3878d585b4501ae07e88d18b5ebb87b028347a4dd9a4624b849ab5b9bf18daf8 + +Kdf = KDF2(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb41ca8e7f448450d7c6ff6b7e61e0a4fba8f40c2944183f9c7c8a46bc7eb2d468aa5fb1cd9739320e6a60909994fb459b5515c49b1eb4a33015aa908886ec3bd26b57ad9158dbac9a8ede364fb763f5c2 + +Kdf = KDF2(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb41ca8e7f448450d7c6ff6b7e61e0a4fba8f40c2944183f9c7c8a46bc7eb2d468aa5fb1cd9739320e6a60909994fb459b06287932b21dbe518b9cb87a6147cbddfc72ec35f96ddf262271267bcfff1bdd + +Kdf = KDF2(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb9378fd44585fabeac1d9f2941fa7fd229d2353130ecf210c7926c388c5e1e5438b3c6ba20f7551ef03d769e0d1c04587983fa4707e64dbe643d21f3a98267a3f5f14e7f3 + +Kdf = KDF2(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 16 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb9378fd44585fabeac1d9f2941fa7fd229d2353130ecf210c7926c388c5e1e5438b3c6ba20f7551ef03d769e0d1c0458758b34c3789b3a3200b293ada094ea99522362b81 + +Kdf = KDF2(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbc220747adc100278b830f636b942d0daf1651e218ea592e01cd5a4a4234974a61b4a71ff4d1f19a5892d417fab9c21898ec74ba98720d2c72422e9214a68a9f4065d2a73 + +Kdf = KDF2(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 16 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbc220747adc100278b830f636b942d0daf1651e218ea592e01cd5a4a4234974a61b4a71ff4d1f19a5892d417fab9c2189cb14a54612e3a980d73c1e0ad972deb25753eb75 + +Kdf = KDF2(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb7c5f222b4215cd1b1c197fe8cfa2a252ad4c61a599ade3c8e8d0442b93afc626405fbe7bb1d103bdd8ce9468071a013fa0beb8264a28536dd671864fa73bf1d4 + +Kdf = KDF2(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbe0004a18072d33b7a7ac09362953dec57197a78ccdac0f1aa98d2a2eb6580a48053b0df23dfe2518253813dc1d1e6651825183042643dcaf2dc69700e29396d8 + +Kdf = KDF2(SHA-256) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb97f3ed7829ec1c4b6d22646252e19a267df9b0100f47f6a376c9b9d9c35a446d1eb7b12fe7f6d6e659d9c83c3c9b3c2a203a3d53a802d02c1be57381a72fa28c + +Kdf = KDF2(SHA-256) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb41ca8e7f448450d7c6ff6b7e61e0a4fba8f40c2944183f9c7c8a46bc7eb2d468aa5fb1cd9739320e6a60909994fb459bee03ba55e204037119a97f02f1a8cb9b + + +Kdf = KDF2(SHA-1) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb9378fd44585fabeac1d9f2941fa7fd229d2353130ecf210c7926c388c5e1e5438b3c6ba20f7551ef03d769e0d1c04587d25c8b9b56026ae8187f6c667c3bf57b + +Kdf = KDF2(SHA-1) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbc220747adc100278b830f636b942d0daf1651e218ea592e01cd5a4a4234974a61b4a71ff4d1f19a5892d417fab9c2189abcc03fbf5fdaa8d101408b13fe9cea3 + +####### KDF1-18033 + +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbd02e423bcbfd01b23c12d332dbd5f4748de89e038bc0841f254509c4119eb62d80013e6b6ea63ef00904494377677137449fbbe79ebe11c57a32e88d7b44ced4614eef8a4f1c8f061f1f60413af7ed6eddd9120d650ac9fd8216b12a6af8f1594ab117fd3536f2a44f70654330809ddc + +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbd02e423bcbfd01b23c12d332dbd5f4748de89e038bc0841f254509c4119eb62d80013e6b6ea63ef009044943776771378743bfaff20afd91f48a78f4af831e42335aff26ffa98c1bf74ef0e1437b6eba839de9dfca32869fa021fe19dbabbd1d6d3da10b1e4f434bf760da236666b10d + +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbd02e423bcbfd01b23c12d332dbd5f4748de89e038bc0841f254509c4119eb62d80013e6b6ea63ef00904494377677137edf4f8a39d3d8c791b3945f242ef5f321ea69a270bc6c2b24a55f3e65b67db24b7e9a8a270eb3f175b49461982a2c2d53b48fd296818f696454d13c10c7b1cc6 + +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb8ab1751efd5cda04c715d94f0dc7f21058ddd90215a6dbb5f3029121c80ce39692acef02ecc5e5deb71352b45682de7ada1f4ec465be2f5fbe25776c3c03baa2c62cc3b44fa762798f3efb687a5281b7063fa71fdfc483e53dc0bfabe2853510fecb29b110b75d2292567eab1c86cb24 + +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb8ab1751efd5cda04c715d94f0dc7f21058ddd90215a6dbb5f3029121c80ce39692acef02ecc5e5deb71352b45682de7aeba22adf488a429ce9bff1b51a916e917fb39d0a4719a6d3eadbfa1f5dbf93ada69056d0ba459693c9329446ceed6ab09bbd73a4651faa9107f56d132dd62072 + +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb8ab1751efd5cda04c715d94f0dc7f21058ddd90215a6dbb5f3029121c80ce39692acef02ecc5e5deb71352b45682de7a21a5db0631ab9bf0f14e60f819a5bc7d2559531bce85fc466d9fdf6f3ce9cadaa60b5f833dc881deb143630b7e8a267a16144d926038ec3c2359b0f092935d22 + +Kdf = KDF1-18033(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb20faa6b9b8e36197a44df7ee04a6eb517621c0c25b54004b8c18da9d307743e2f75e0a106b1cd8d275ed146f0ea2d66342511e50f37a91ad3eb5efce92a858a95458a9484f9a9c939bc8ab8a028bbf22 + +Kdf = KDF1-18033(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb20faa6b9b8e36197a44df7ee04a6eb517621c0c25b54004b8c18da9d307743e2f75e0a106b1cd8d275ed146f0ea2d66355baba71e14d2826cf99292581db0e3f6356280965ebfa456093b75a50089f7c + +Kdf = KDF1-18033(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 16 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb20faa6b9b8e36197a44df7ee04a6eb517621c0c25b54004b8c18da9d307743e2f75e0a106b1cd8d275ed146f0ea2d663fa3df2c346fec36f0181aafdde052872c021aeae057298c72068ea9271d19a30 + +Kdf = KDF1-18033(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb5905e1af473bff629d6559e6dfae76dd176135417ec1f8bd56da34e604f3cba3edfe626868e6a6f5706454cc808394ae979dbb099676e3e61f12de47d87eb2c68101edce237b18b3ba41eca6c8d4a2c6 + +Kdf = KDF1-18033(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb5905e1af473bff629d6559e6dfae76dd176135417ec1f8bd56da34e604f3cba3edfe626868e6a6f5706454cc808394ae08f8d798a81ef521ab83d5d63127c8df21bbeb596ca63fe3789c28091805f8eb + +Kdf = KDF1-18033(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 16 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb5905e1af473bff629d6559e6dfae76dd176135417ec1f8bd56da34e604f3cba3edfe626868e6a6f5706454cc808394aeed35c9fcb24b2a440873264c97aadc860dc89e8b95a4e644c5ac2bb5f19c2c5e + +Kdf = KDF1-18033(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb780aefcb510dadc91fb23e93c1dc3ab67515904c394001d13c57cc4e8f14120d8b5d102f8a0af143ac4ae59d8358714e71a4b9ae7881296a1f8e4fd7695a9cdc00613360 + +Kdf = KDF1-18033(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 16 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb780aefcb510dadc91fb23e93c1dc3ab67515904c394001d13c57cc4e8f14120d8b5d102f8a0af143ac4ae59d8358714e666ffa3f0881093199f6ab5e1f2bca9658b29114 + +Kdf = KDF1-18033(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 20 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb79d5d8fcd4cec89c61a875f1f44b76f2c6561450ec419bce39d5c18a83174866408ddcc61780820295438b12371cb6b77aa52d217e6b8f9bc0c940eee9f18827bfc42958 + +Kdf = KDF1-18033(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 16 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb79d5d8fcd4cec89c61a875f1f44b76f2c6561450ec419bce39d5c18a83174866408ddcc61780820295438b12371cb6b76f5a4cb193769a1cc3cabac1ef709ad5cd903113 + +Kdf = KDF1-18033(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb8ab1751efd5cda04c715d94f0dc7f21058ddd90215a6dbb5f3029121c80ce39692acef02ecc5e5deb71352b45682de7a0b65f9aea49d094a71b64333211e3349 + +Kdf = KDF1-18033(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbd02e423bcbfd01b23c12d332dbd5f4748de89e038bc0841f254509c4119eb62d80013e6b6ea63ef00904494377677137c1b3b063d80fea08ce2cb5d846b4d6bc + +Kdf = KDF1-18033(SHA-256) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb5905e1af473bff629d6559e6dfae76dd176135417ec1f8bd56da34e604f3cba3edfe626868e6a6f5706454cc808394aef9fe22486b2f76c889d1d4d4903128f2 + +Kdf = KDF1-18033(SHA-256) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb20faa6b9b8e36197a44df7ee04a6eb517621c0c25b54004b8c18da9d307743e2f75e0a106b1cd8d275ed146f0ea2d6635d54b68cd4f7e34845f8a658b2a1cc80 + +Kdf = KDF1-18033(SHA-1) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb79d5d8fcd4cec89c61a875f1f44b76f2c6561450ec419bce39d5c18a83174866408ddcc61780820295438b12371cb6b7846bbcb1320b46d3857d683c68754868 + +Kdf = KDF1-18033(SHA-1) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/CBC +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb780aefcb510dadc91fb23e93c1dc3ab67515904c394001d13c57cc4e8f14120d8b5d102f8a0af143ac4ae59d8358714e63cd5edcce32a71dfa645223fdc8249d + +########### Stream mode (XOR enc/dec) ########### + +#public static void main(String[] args) throws InvalidCipherTextException { +# // 2048-bit MODP Group. RFC3526 +# BigInteger g = new BigInteger( "2", 10 ); +# BigInteger p = new BigInteger( "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A0879" +# + "8E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" +# + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" +# + "83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" +# + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA0510" +# + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16 ); +# +# DHParameters dhParams = new DHParameters( p, g ); +# +# // alice priv key +# BigInteger xAlice = new BigInteger( "A01E167DE1013D6859E6CB068B7BF272C1D49DC764AD7676BFA0D85177", 16 ); +# DHPrivateKeyParameters alicePriv = new DHPrivateKeyParameters( xAlice, dhParams ); +# +# // alice pub key +# BigInteger yAlice = g.modPow(xAlice, p); +# DHPublicKeyParameters alicePub = new DHPublicKeyParameters( yAlice, dhParams ); +# +# // bob priv key +# BigInteger xBob = new BigInteger( "8DD88BDC19AC1403A3FC3A0FC63D360F1062E3494177DC27F7EBCBD4A7", 16 ); +# +# // bob pub key +# BigInteger yBob = g.modPow(xBob, p); +# DHPublicKeyParameters bobPub = new DHPublicKeyParameters( yBob, dhParams ); +# +# // DLIES +# byte[] d = new byte[ 0 ]; // the derivation parameter for the KDF function +# byte[] e = new byte[ 0 ]; // the encoding parameter for the KDF function +# int macKeySize = 160; +# int cipherKeySize = 256; +# byte[] iv = new byte[ 16 ]; +# CipherParameters cipherParams = new ParametersWithIV( new IESWithCipherParameters( d, e, macKeySize, cipherKeySize ), iv ); +# +# IESEngine dlies = +# new IESEngine( new DHBasicAgreement(), new KDF2BytesGenerator( new SHA256Digest() ), new HMac( new SHA256Digest() ) ); +# dlies.init( true, alicePriv, bobPub, cipherParams ); +# +# byte[] message = Hex.decode( "00" ); +# byte[] result = dlies.processBlock( message, 0, message.length ); +# +# byte[] ephPublicKey = alicePub.getY().toByteArray(); +# byte[] out = Arrays.concatenate( ephPublicKey, result ); +# +# System.out.println( Hex.toHexString( out ) ); +# } + +####### KDF2 + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb9b311515aa49918497c0c52f8c09e2cf6b3bc0343131a552b3d72ec4ee73f9628310a5d278a69c52f5a76c68031365e2504ef4abfa6e105f359e6d57c60a5beaf94a156544baba53139a3e90dd6218e504e58e1c8992df4565e68ec611c286bd + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb9b311515aa49918497c0c52f8c09e2cf6b3bc0343131a552b3d72ec4ee73f962baa771f5b54bef678412dfd3ea7380a42014b50aec4cc55d841b2ae20a168b3d5e51da011736d60e6ad446adc72f60e41f7f25c9d2e76badc473c110b7fc67b8 + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 20 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb9b311515aa49918497c0c52f8c09e2cf6b3bc0343131a552b3d72ec4ee73f96262aa912053ba6ece87a75b8e2c1cf4fc49c5b03f7c433feaf8386ccc44e48375dc7d2a6fa59403a0e44fc268e7fb88eaa9faa66f120ca4f133631f5aace793e1 + +Kdf = KDF2(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbfdeb30b4378e3a6583da338d50cc23086dc8c3b33bc8e6d5612a44a2e1f0c5cbb8dbdb9d5c1e326f78df5beb66336ce5d95cd9f7cf349218874524519c2b5977 + +Kdf = KDF2(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 20 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbfdeb30b4378e3a6583da338d50cc23086dc8c3b33bc8e6d5612a44a2e1f0c5cbf1a5cfd4cf6a4a507d8151956d5573f94713d848517c37657f9d278b0c1f927e + +Kdf = KDF2(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 16 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbfdeb30b4378e3a6583da338d50cc23086dc8c3b33bc8e6d5612a44a2e1f0c5cb0bdbd16fedfb41e28e6e52c6fc073a7f51d2951976602430a4788d9dcf94f40e + +Kdf = KDF2(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 20 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb070d66995d816ed81c1877398dbc56744848d0af4b63c374925eeeab5d99f55c3efe5a434f886c377d175a52798bc6edbb968932 + +Kdf = KDF2(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 16 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb070d66995d816ed81c1877398dbc56744848d0af4b63c374925eeeab5d99f55cda95ccfde6fdb8159f286781e3abb3b0d8252f7d + +Kdf = KDF2(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb9b311515aa49918497c0c52f8c09e2cf6b3bc0343131a552b3d72ec4ee73f9626e83627fdb17b36f71a61d52eb663564 + +Kdf = KDF2(SHA-256) +Mac = CMAC(AES-256) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fbfdeb30b4378e3a6583da338d50cc23086dc8c3b33bc8e6d5612a44a2e1f0c5cbe4f06420b4e196e8d31a1667b2b50355 + +Kdf = KDF2(SHA-1) +Mac = CMAC(AES-256) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb070d66995d816ed81c1877398dbc56744848d0af4b63c374925eeeab5d99f55cdeb9fc82441056058543f4240b7e5ebf + +####### KDF1-18033 + +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb068191059703df1b4b140329d94c796cd2e90d295c13bbdf475e08373bc7a22aec8bda0985f4cda3c620e9a2bfa0767d8ecfc5179cfe11c19672b1bef866e374a14a7ab51e90bbeaac8913d1b650e2addabe7f64debc1fb3a8110e6e58050817 + +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb068191059703df1b4b140329d94c796cd2e90d295c13bbdf475e08373bc7a22a43de2dfe50e0fb98b3e06e6df77d84eac49ac9f273b4c5a64ce5656f706a8df07e6ca7a88d26a28f3d4df96ae5b1146fa2709a87e70659bcf1ef9d0d531ba167 + +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 20 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb068191059703df1b4b140329d94c796cd2e90d295c13bbdf475e08373bc7a22a48f09818c5b240b402b40f080b9fd0f8103490c6592f8e56ae20ad10662f13415ada188324cb478888bab0b267ae5c05ba8acd20adc24beae6042b2d37541a77 + +Kdf = KDF1-18033(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb536ba065e41dad66225d9469433a5dc53362280c1979818a3349c170060c3ace16137afc5f0642407ba3db6717c739bfff83d3195da75b6c7a82f78169742573 + +Kdf = KDF1-18033(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 20 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb536ba065e41dad66225d9469433a5dc53362280c1979818a3349c170060c3acef0d102d22c4291474cd83749e499c1c65d179f1ec0cd27a3c995317597a135cc + +Kdf = KDF1-18033(SHA-256) +Mac = HMAC(SHA-256) +MacKeyLen = 16 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb536ba065e41dad66225d9469433a5dc53362280c1979818a3349c170060c3ace166abeaf1fa00a4815e47011090e272206df8c8f6362869c04eb0e704b625a87 + +Kdf = KDF1-18033(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 20 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb96e324a74d5941d71563b32059bba36cd6990ee07690fd5ac201f81e2091835b9e0d6e486f279855a6b4e4855bd12e030367e698 + +Kdf = KDF1-18033(SHA-1) +Mac = HMAC(SHA-1) +MacKeyLen = 16 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb96e324a74d5941d71563b32059bba36cd6990ee07690fd5ac201f81e2091835b30500fea11b5dfc1b60b691f3326c4d109970142 + +Kdf = KDF1-18033(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb068191059703df1b4b140329d94c796cd2e90d295c13bbdf475e08373bc7a22a6cfc28a4b15599d72666d18cb8a65e19 + +Kdf = KDF1-18033(SHA-256) +Mac = CMAC(AES-256) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb536ba065e41dad66225d9469433a5dc53362280c1979818a3349c170060c3aceb5f786c722ea79e5c262c8b8b8f0f2f5 + +Kdf = KDF1-18033(SHA-1) +Mac = CMAC(AES-256) +MacKeyLen = 32 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57dfafa0d81ac3aaca2570ad13cccd127239f4ee04843bb738234588f0daea53ccd8af65a5a00ed19fbb6f2eb57779ff2e38e3d5d27986253a1193dabf14d2402e1a33527866fa21f23f7abbee5f454aad762fc90139c8377bf6cc77af7f982404baea5ca4831dd8ed28babf2d43b1f65eff42167b82f020dfd4928d8e96dcb7845ecf8f560fbbf5646fae5bc4eda6d978e5fb333843a1f4525cfbdde756842a1e353f4de1503738eec6c9d901a78cdefedf8daaa49631da674b44cab2193c778bf29766730a656b42e96f84698f77913c718067048263034cf2a2f34572ab662e4b1c5b04cd71183433c591abd5613820544d46f7462bea57e44f23ab06e0fb96e324a74d5941d71563b32059bba36cd6990ee07690fd5ac201f81e2091835b29651165a98cf6ea7f18f6638151094a + +########################### Test vectors created with botan for AES-GCM tests ########################### + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +Cipher = AES-256/GCM +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57DFAFA0D81AC3AACA2570AD13CCCD127239F4EE04843BB738234588F0DAEA53CCD8AF65A5A00ED19FBB6F2EB57779FF2E38E3D5D27986253A1193DABF14D2402E1A33527866FA21F23F7ABBEE5F454AAD762FC90139C8377BF6CC77AF7F982404BAEA5CA4831DD8ED28BABF2D43B1F65EFF42167B82F020DFD4928D8E96DCB7845ECF8F560FBBF5646FAE5BC4EDA6D978E5FB333843A1F4525CFBDDE756842A1E353F4DE1503738EEC6C9D901A78CDEFEDF8DAAA49631DA674B44CAB2193C778BF29766730A656B42E96F84698F77913C718067048263034CF2A2F34572AB662E4B1C5B04CD71183433C591ABD5613820544D46F7462BEA57E44F23AB06E0FB142440A4B10508DB7E61E326B749F1B332A624C5DDF9E989A5D3A1FEC6FC5651A4FFBBC673A52C0B440DEFB8B3EEBB828A46DF1737A3E8DA67A3840041994D34C78D552A09423A4301F513CFF526D476C16C09D0C0F9D978B64A6AF8F883EBE704B412C72C91CE93B9DF82721ACFA6F3 + +Kdf = KDF2(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +Cipher = AES-256/GCM +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 +G = 2 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57DFAFA0D81AC3AACA2570AD13CCCD127239F4EE04843BB738234588F0DAEA53CCD8AF65A5A00ED19FBB6F2EB57779FF2E38E3D5D27986253A1193DABF14D2402E1A33527866FA21F23F7ABBEE5F454AAD762FC90139C8377BF6CC77AF7F982404BAEA5CA4831DD8ED28BABF2D43B1F65EFF42167B82F020DFD4928D8E96DCB7845ECF8F560FBBF5646FAE5BC4EDA6D978E5FB333843A1F4525CFBDDE756842A1E353F4DE1503738EEC6C9D901A78CDEFEDF8DAAA49631DA674B44CAB2193C778BF29766730A656B42E96F84698F77913C718067048263034CF2A2F34572AB662E4B1C5B04CD71183433C591ABD5613820544D46F7462BEA57E44F23AB06E0FB72CE0E99275D750433D9D8115E9F4FF5A91A341E1A3E73F64D8DBE1BFEC7FFA1D2CD8DEF2C0664017A337303455BCF37D076564864E0733DF29D910E8BF0308DCA81A064FEE96811A34B4D0E4BBA45BED459E7BE4FCA58918633F2C6CC34871759BE982DC459AB39F989E42113E0F0A2 + +Kdf = KDF2(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/GCM +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 G = 2 -X1 = 3895469730603000759730584760913911891226712505433061 -X2 = 3202115124466487737101087673031994924801994092564435 -Msg = AB5BBE0D -Ciphertext = 538F9C9CAC3EEB460B6D40B4AC331EBD3E2F3065E515177F47A083D1AC71533BF3B2931F52D71A99CA0804A633E1948F3B286453EA6CF0DD83C6DD1D2BD93B20F4942D9679CFDE5856DD81E152E1E5ADD023324B945CE68425B025AE5D0CF86C0D33244A60AF6045BD57018FFE5F84A9BF82193242FF32A64691586AAA298FE531CF06A56412DFEC3AD1F50FF8CD296310E5BB4D06E15AB0 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57DFAFA0D81AC3AACA2570AD13CCCD127239F4EE04843BB738234588F0DAEA53CCD8AF65A5A00ED19FBB6F2EB57779FF2E38E3D5D27986253A1193DABF14D2402E1A33527866FA21F23F7ABBEE5F454AAD762FC90139C8377BF6CC77AF7F982404BAEA5CA4831DD8ED28BABF2D43B1F65EFF42167B82F020DFD4928D8E96DCB7845ECF8F560FBBF5646FAE5BC4EDA6D978E5FB333843A1F4525CFBDDE756842A1E353F4DE1503738EEC6C9D901A78CDEFEDF8DAAA49631DA674B44CAB2193C778BF29766730A656B42E96F84698F77913C718067048263034CF2A2F34572AB662E4B1C5B04CD71183433C591ABD5613820544D46F7462BEA57E44F23AB06E0FB142440A4B10508DB7E61E326B749F1B332A624C5DDF9E989A5D3A1FEC6FC5651A4FFBBC673A52C0B440DEFB8B3EEBB82EAB5098B4E55338B28863B299D77FD6E -P = 179769313486231590770839156793787453197860296048756011706444423684197180216158519368947833795864925541502180565485980503646440548199239100050792877003355816639229553136239076508735759914822574862575007425302077447712589550957937778424442426617334727629299387668709205606050270810842907692932019128194467627007 +Kdf = KDF2(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/GCM +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 G = 2 -X1 = 4556286536649761359339945350124531773703491905870156 -X2 = 4102583277207195475485889175414309483746012144669284 -Msg = C43BB390 -Ciphertext = C04F6BD6D1BFBDE74E775FB391A29B2D6FB7EE84C13D2061291DBA8708E406B0A6788F69F7DFEBE4CA35B31917EACD7D36CDBEBDCC51567ADF3F287F57592A0F73E1C990B807E0A67ACAE3F07361DF123C59E0A95CFCA9DEB3C7CCDC47C925F975AF0948B3DE9EC1E34EED30391FD4080D77DD07F091E3D5D89BC158A96485B28477AA95D62EFB9FA1D2B44A38A698F81C9518355BAE8B74 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57DFAFA0D81AC3AACA2570AD13CCCD127239F4EE04843BB738234588F0DAEA53CCD8AF65A5A00ED19FBB6F2EB57779FF2E38E3D5D27986253A1193DABF14D2402E1A33527866FA21F23F7ABBEE5F454AAD762FC90139C8377BF6CC77AF7F982404BAEA5CA4831DD8ED28BABF2D43B1F65EFF42167B82F020DFD4928D8E96DCB7845ECF8F560FBBF5646FAE5BC4EDA6D978E5FB333843A1F4525CFBDDE756842A1E353F4DE1503738EEC6C9D901A78CDEFEDF8DAAA49631DA674B44CAB2193C778BF29766730A656B42E96F84698F77913C718067048263034CF2A2F34572AB662E4B1C5B04CD71183433C591ABD5613820544D46F7462BEA57E44F23AB06E0FB72CE0E99275D750433D9D8115E9F4FF5A91A341E1A3E73F64D8DBE1BFEC7FFA1D2CD8DEF2C0664017A337303455BCF37845E0B4A59D925366D35D40C344FE6BD -P = 1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919 +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +Cipher = AES-256/GCM +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 G = 2 -X1 = 1054639601167296898572220004033907486000310327029 -X2 = 1342657759849572617856127220396675041367757265787 -Msg = 3B06E0705DC9DBA971AA624393984D5B -Ciphertext = 2AB9B180CEF08E761EDB4D7B7C538FBA0FD37BACE9416789A0DD6551F2DDC6025C76A663F1AAD5000EC03418A6220ABA6D3DC5EA82D7340E2FFCB5665AD3A2223CDFF9C39889CBE31E44CD31BCFDCEFCF2A9916FD39E2720A7B826F7E6998F734F251C71DC970AF3FB12949C14AA759966733BFC976CAD0BE71FC5DBE285200E75647C62 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57DFAFA0D81AC3AACA2570AD13CCCD127239F4EE04843BB738234588F0DAEA53CCD8AF65A5A00ED19FBB6F2EB57779FF2E38E3D5D27986253A1193DABF14D2402E1A33527866FA21F23F7ABBEE5F454AAD762FC90139C8377BF6CC77AF7F982404BAEA5CA4831DD8ED28BABF2D43B1F65EFF42167B82F020DFD4928D8E96DCB7845ECF8F560FBBF5646FAE5BC4EDA6D978E5FB333843A1F4525CFBDDE756842A1E353F4DE1503738EEC6C9D901A78CDEFEDF8DAAA49631DA674B44CAB2193C778BF29766730A656B42E96F84698F77913C718067048263034CF2A2F34572AB662E4B1C5B04CD71183433C591ABD5613820544D46F7462BEA57E44F23AB06E0FB9A0B0CAB5C285FB0CB1F788213B6B82A2C2E485C1D514BAEF7FC241D57DB031D9E80361C55B562232759A660C89E0DE0E11BB8C807142C1C98C07C9BD08BFC7A3D9977133AD07DDED60728B46D668444A74BC001CFBFB8E8FE0BACF6A4078DD4212DC7CDC3291CB3F02AC0B7CDF6E65D -P = 1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919 +Kdf = KDF1-18033(SHA-512) +Mac = HMAC(SHA-512) +MacKeyLen = 64 +Cipher = AES-256/GCM +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 G = 2 -X1 = 1019791127804545295775858763356184757983418129858 -X2 = 791304855263120499982139573682243365135340447126 -Msg = DD92A05E19BBAD4A33CEFFA0FA2727E9 -Ciphertext = 3F0300C53C0BB02A3EF2EFCC751EE5D98AE991730C1C2FE39D11A74D32D892AD63A9EECA09BBBE606FB426E03BBD480FD224E09712BB85FE649D543CBC23113A39F9102C65D31DF330ADF233735C1D60D1BCDE22744392D2D9DE50393984F276A33DD85F763ED1226B88DF1662554AD27820F66A995FE1481189A2B8C3071D0C32EE9960 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57DFAFA0D81AC3AACA2570AD13CCCD127239F4EE04843BB738234588F0DAEA53CCD8AF65A5A00ED19FBB6F2EB57779FF2E38E3D5D27986253A1193DABF14D2402E1A33527866FA21F23F7ABBEE5F454AAD762FC90139C8377BF6CC77AF7F982404BAEA5CA4831DD8ED28BABF2D43B1F65EFF42167B82F020DFD4928D8E96DCB7845ECF8F560FBBF5646FAE5BC4EDA6D978E5FB333843A1F4525CFBDDE756842A1E353F4DE1503738EEC6C9D901A78CDEFEDF8DAAA49631DA674B44CAB2193C778BF29766730A656B42E96F84698F77913C718067048263034CF2A2F34572AB662E4B1C5B04CD71183433C591ABD5613820544D46F7462BEA57E44F23AB06E0FB7177BE14E602FEB0274B170E41879977CA357CD99EC7FF096964C0FE4AA7D39DC90D24DC433C695D3B2B4A7B88BF08B2099F5321322A66A5377C14FF3F7FF6C96FC72DA82DADAB8064248F0751EAEFC62ADFD4FA782D11EA953FA2FE924FFD7CB7310531D2A9A0091F23E0E195DAAB3E -P = 1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919 +Kdf = KDF1-18033(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/GCM +CipherKeyLen = 32 +IV = 00000000000000000000000000000000 +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 G = 2 -X1 = 1127072655127804554962850771491034708297993164117 -X2 = 909338501771729516589244957544435828677252574269 -Msg = 174E756AF8FFB51990BF3C69688D3A7F0B388F2BCE62A095BC12CD6DA2C2AD65 -Ciphertext = B99BBBC64F6320060200E6FFE7D1FE6E5EEA79DF142111AF88D377037BD9186341B7A7A27F2AE8BB77282B8EA13D821DD77186412CA3B9B5E1650A0D20687B1C8D556FD7D547D475F71BBD7D6417311F535A9A6D95CEA8AFD1146B1A1741828E8AD46B058507A67111CB62132350EEAC1212D90535677855E17B1DA9DC4CE790C4B917B1359123226FE62DCCE5475721F09CEA23 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57DFAFA0D81AC3AACA2570AD13CCCD127239F4EE04843BB738234588F0DAEA53CCD8AF65A5A00ED19FBB6F2EB57779FF2E38E3D5D27986253A1193DABF14D2402E1A33527866FA21F23F7ABBEE5F454AAD762FC90139C8377BF6CC77AF7F982404BAEA5CA4831DD8ED28BABF2D43B1F65EFF42167B82F020DFD4928D8E96DCB7845ECF8F560FBBF5646FAE5BC4EDA6D978E5FB333843A1F4525CFBDDE756842A1E353F4DE1503738EEC6C9D901A78CDEFEDF8DAAA49631DA674B44CAB2193C778BF29766730A656B42E96F84698F77913C718067048263034CF2A2F34572AB662E4B1C5B04CD71183433C591ABD5613820544D46F7462BEA57E44F23AB06E0FB7177BE14E602FEB0274B170E41879977CA357CD99EC7FF096964C0FE4AA7D39DC90D24DC433C695D3B2B4A7B88BF08B299019BFDC4ABE7BBED415937E9F58B9D -P = 1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919 +Kdf = KDF1-18033(SHA-512) +Mac = CMAC(AES-256) +MacKeyLen = 32 +Cipher = AES-256/GCM +CipherKeyLen = 32 +IV = 00112233445566778899aabbccddeeff +P = 32317006071311007300338913926423828248817941241140239112842009751400741706634354222619689417363569347117901737909704191754605873209195028853758986185622153212175412514901774520270235796078236248884246189477587641105928646099411723245426622522193230540919037680524235519125679715870117001058055877651038861847280257976054903569732561526167081339361799541336476559160368317896729073178384589680639671900977202194168647225871031411336429319536193471636533209717077448227988588565369208645296636077250268955505928362751121174096972998068410554359584866583291642136218231078990999448652468262416972035911852507045361090559 G = 2 -X1 = 1400390629906877310807893670888997072266707870316 -X2 = 1409894924299088894270577337460879151312883489271 -Msg = 75DAD921764736E389C4224DAF7B278EC291E682044742E2E9C7A025B54DD62F -Ciphertext = C591E27A2C12742A959652F5F341F558CA0C7DAF2E6B5ACE32DCAAF459553BA23EF0235EAFD86A7F2D70587239D858484E5CD36122C2B9F6E410C7A9C307B2A2A084BB1B634A15AC9F09E38EAF421D14C5A07B6EB5EDE6915E8DE9D3D9D01DBD8822FBD79BA7FF3DF921B5451BBD9A12AB41FD4DAB829599BC2736B23753063C0C5FFCBA7DB06DE26D3C441D126FC1A46531F593 +X1 = 4316760088048858173826993660634587631078362099236037980378049883427191 +X2 = 3824157470039532100357278938102046076290169354062923298804711018976423 +Msg = 75dad921764736e389c4224daf7b278ec291e682044742e2e9c7a025b54dd62f +Ciphertext = 57DFAFA0D81AC3AACA2570AD13CCCD127239F4EE04843BB738234588F0DAEA53CCD8AF65A5A00ED19FBB6F2EB57779FF2E38E3D5D27986253A1193DABF14D2402E1A33527866FA21F23F7ABBEE5F454AAD762FC90139C8377BF6CC77AF7F982404BAEA5CA4831DD8ED28BABF2D43B1F65EFF42167B82F020DFD4928D8E96DCB7845ECF8F560FBBF5646FAE5BC4EDA6D978E5FB333843A1F4525CFBDDE756842A1E353F4DE1503738EEC6C9D901A78CDEFEDF8DAAA49631DA674B44CAB2193C778BF29766730A656B42E96F84698F77913C718067048263034CF2A2F34572AB662E4B1C5B04CD71183433C591ABD5613820544D46F7462BEA57E44F23AB06E0FB9A0B0CAB5C285FB0CB1F788213B6B82A2C2E485C1D514BAEF7FC241D57DB031D9E80361C55B562232759A660C89E0DE0FB884998AEFEF7CE84F114928423F7E2 diff --git a/src/tests/test_dlies.cpp b/src/tests/test_dlies.cpp index ba8142dcb..75d751eaa 100644 --- a/src/tests/test_dlies.cpp +++ b/src/tests/test_dlies.cpp @@ -1,5 +1,6 @@ /* * (C) 2014,2015 Jack Lloyd +* (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -24,7 +25,7 @@ class DLIES_KAT_Tests : public Text_Based_Test public: DLIES_KAT_Tests() : Text_Based_Test( "pubkey/dlies.vec", - {"P", "G", "X1", "X2", "Msg", "Ciphertext"}) + {"Kdf", "Mac", "MacKeyLen", "Cipher", "CipherKeyLen", "IV", "P", "G", "X1", "X2", "Msg", "Ciphertext"}) {} Test::Result run_one_test(const std::string&, const VarMap& vars) override @@ -37,35 +38,52 @@ class DLIES_KAT_Tests : public Text_Based_Test const std::vector input = get_req_bin(vars, "Msg"); const std::vector expected = get_req_bin(vars, "Ciphertext"); - Botan::DL_Group domain(p, g); - - Botan::DH_PrivateKey from(Test::rng(), domain, x1); - Botan::DH_PrivateKey to(Test::rng(), domain, x2); + const std::string kdf_algo = get_req_str(vars, "Kdf"); + const std::string mac_algo = get_req_str(vars, "Mac"); + const size_t mac_key_len = get_req_sz(vars, "MacKeyLen"); - const std::string kdf_algo = "KDF2(SHA-1)"; - const std::string mac_algo = "HMAC(SHA-1)"; - const size_t mac_key_len = 16; + const std::string cipher_algo = get_opt_str(vars, "Cipher", ""); + const size_t cipher_key_len = get_opt_sz(vars, "CipherKeyLen", 0); + const std::vector iv = get_opt_bin(vars, "IV"); Test::Result result("DLIES"); std::unique_ptr kdf(Botan::KDF::create(kdf_algo)); - std::unique_ptr mac(Botan::MAC::create(mac_algo)); + if(!kdf) + { + result.test_note("Skipping due to missing KDF: " + kdf_algo); + return result; + } - if(!kdf || !mac) + std::unique_ptr mac(Botan::MAC::create(mac_algo)); + if(!mac) { - result.test_note("Skipping due to missing KDF or MAC algo"); + result.test_note("Skipping due to missing MAC: " + mac_algo); return result; } - Botan::DLIES_Encryptor encryptor(from, - kdf->clone(), - mac->clone(), - mac_key_len); + std::unique_ptr enc; + std::unique_ptr dec; + + if(! cipher_algo.empty()) + { + enc.reset(Botan::get_cipher_mode(cipher_algo, Botan::ENCRYPTION)); + dec.reset(Botan::get_cipher_mode(cipher_algo, Botan::DECRYPTION)); + } + + Botan::DL_Group domain(p, g); + + Botan::DH_PrivateKey from(Test::rng(), domain, x1); + Botan::DH_PrivateKey to(Test::rng(), domain, x2); - Botan::DLIES_Decryptor decryptor(to, - kdf.release(), - mac.release(), - mac_key_len); + Botan::DLIES_Encryptor encryptor(from, kdf->clone(), enc.release(), cipher_key_len, mac->clone(), mac_key_len); + Botan::DLIES_Decryptor decryptor(to, kdf.release(), dec.release(), cipher_key_len, mac.release(), mac_key_len); + + if(!iv.empty()) + { + encryptor.set_initialization_vector(iv); + decryptor.set_initialization_vector(iv); + } encryptor.set_other_key(to.public_value()); @@ -80,6 +98,101 @@ class DLIES_KAT_Tests : public Text_Based_Test BOTAN_REGISTER_TEST("dlies", DLIES_KAT_Tests); +Test::Result test_xor() + { + Test::Result result("DLIES XOR"); + + std::vector kdfs = { "KDF2(SHA-512)", "KDF1-18033(SHA-512)" }; + std::vector macs = { "HMAC(SHA-512)", "CMAC(AES-128)" }; + + const size_t mac_key_len = 16; + + std::unique_ptr kdf; + std::unique_ptr mac; + + Botan::DH_PrivateKey alice(Test::rng(), Botan::DL_Group("modp/ietf/2048")); + Botan::DH_PrivateKey bob(Test::rng(), Botan::DL_Group("modp/ietf/2048")); + + for(const auto& kfunc : kdfs) + { + kdf = Botan::KDF::create(kfunc); + + if(!kdf) + { + result.test_note("Skipping due to missing KDF: " + kfunc); + continue; + } + + for(const auto& mfunc : macs) + { + mac = Botan::MAC::create(mfunc); + + if(!mac) + { + result.test_note("Skipping due to missing MAC: " + mfunc); + continue; + } + + Botan::DLIES_Encryptor encryptor(alice, kdf->clone(), mac->clone(), mac_key_len); + + // negative test: other pub key not set + Botan::secure_vector plaintext = Test::rng().random_vec(32); + + result.test_throws("encrypt not possible without setting other public key", [&encryptor, &plaintext]() + { + encryptor.encrypt(plaintext, Test::rng()); + }); + + encryptor.set_other_key(bob.public_value()); + std::vector ciphertext = encryptor.encrypt(plaintext, Test::rng()); + + Botan::DLIES_Decryptor decryptor(bob, kdf->clone(), mac->clone(), mac_key_len); + + // negative test: ciphertext too short + result.test_throws("ciphertext too short", [ &decryptor ]() + { + decryptor.decrypt(std::vector(2)); + }); + + result.test_eq("decryption", decryptor.decrypt(ciphertext), plaintext); + + check_invalid_ciphertexts(result, decryptor, unlock(plaintext), ciphertext); + } + } + + return result; + } + +class DLIES_Unit_Tests : public Test + { + public: + std::vector run() override + { + std::vector results; + + std::vector> fns = + { + test_xor + }; + + for(size_t i = 0; i != fns.size(); ++i) + { + try + { + results.push_back(fns[ i ]()); + } + catch(std::exception& e) + { + results.push_back(Test::Result::Failure("DLIES unit tests " + std::to_string(i), e.what())); + } + } + + return results; + } + }; + +BOTAN_REGISTER_TEST("dlies-unit", DLIES_Unit_Tests); + #endif } -- cgit v1.2.3 From e9d99201b1629d6042387084d2e49025f4f5352c Mon Sep 17 00:00:00 2001 From: RenĂ© Korthaus Date: Wed, 13 Jul 2016 11:07:47 +0200 Subject: Update changelog with ANSI X9.23 padding bugfix --- doc/news.rst | 3 +++ 1 file changed, 3 insertions(+) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index 8c4db8b09..2d19dcf3f 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -19,6 +19,9 @@ Version 1.11.31, Not Yet Released system requires EGD and so the code is now dead weight. If you rely on EGD support, you should contact the developers by email or GitHub ASAP. +* Fix a bug in ANSI X9.23 padding mode, which returned one byte more + than the given block size (GH #529). + Version 1.11.30, 2016-06-19 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From a24e9a6ca4e2bc68cf8fbc82b8d72d35c7f93a71 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 15 Jul 2016 14:37:37 -0400 Subject: Fix undefined behavior in donna128 type Caused Curve25519 tests to fail when compiled by Clang on ARM, may have affected other 32-bit platforms. GH #532 --- doc/news.rst | 4 ++++ src/lib/utils/donna128.h | 18 ++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index 8c4db8b09..a5f6cba72 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -12,6 +12,10 @@ Version 1.11.31, Not Yet Released * Add KDF1 from ISO 18033 (GH #483) +* Fix undefined behavior in Curve25519 on platforms without a native 128-bit + integer type. This was known to produce incorrect results on 32-bit ARM + under Clang. GH #532 + * Fixes for FreeBSD (GH #517) and OpenBSD (GH #523) * Support for getting entropy from EGD is deprecated, and will be removed in diff --git a/src/lib/utils/donna128.h b/src/lib/utils/donna128.h index c2a3e0d2e..2a2d1e339 100644 --- a/src/lib/utils/donna128.h +++ b/src/lib/utils/donna128.h @@ -23,18 +23,24 @@ class donna128 friend donna128 operator>>(const donna128& x, size_t shift) { donna128 z = x; - const u64bit carry = z.h << (64 - shift); - z.h = (z.h >> shift); - z.l = (z.l >> shift) | carry; + if(shift > 0) + { + const u64bit carry = z.h << (64 - shift); + z.h = (z.h >> shift); + z.l = (z.l >> shift) | carry; + } return z; } friend donna128 operator<<(const donna128& x, size_t shift) { donna128 z = x; - const u64bit carry = z.l >> (64 - shift); - z.l = (z.l << shift); - z.h = (z.h << shift) | carry; + if(shift > 0) + { + const u64bit carry = z.l >> (64 - shift); + z.l = (z.l << shift); + z.h = (z.h << shift) | carry; + } return z; } -- cgit v1.2.3 From 93922f20f04058ec624f7db3c74d8aa5a3d06440 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Thu, 30 Jun 2016 13:15:30 -0400 Subject: Add Stateful_RNG Handles fork checking for HMAC_RNG and HMAC_DRBG AutoSeeded_RNG change - switch to HMAC_DRBG as default. Start removing the io buffer from entropy poller. Update default RNG poll bits to 256. Fix McEliece test, was using wrong RNG API. Update docs. --- doc/manual/rng.rst | 133 ++++++++------------- src/build-data/buildh.in | 15 ++- src/build-data/policy/bsi.txt | 1 - src/build-data/policy/modern.txt | 2 +- src/cli/speed.cpp | 6 +- .../entropy/darwin_secrandom/darwin_secrandom.cpp | 6 +- .../entropy/darwin_secrandom/darwin_secrandom.h | 2 + src/lib/entropy/dev_random/dev_random.cpp | 75 ++++++++---- src/lib/entropy/dev_random/dev_random.h | 6 +- src/lib/prov/tpm/tpm.h | 5 +- src/lib/rng/auto_rng.h | 47 ++++++++ src/lib/rng/auto_rng/auto_rng.h | 45 ------- src/lib/rng/auto_rng/info.txt | 9 -- src/lib/rng/hmac_drbg/hmac_drbg.cpp | 14 ++- src/lib/rng/hmac_drbg/hmac_drbg.h | 10 +- src/lib/rng/hmac_rng/hmac_rng.cpp | 109 ++++++----------- src/lib/rng/hmac_rng/hmac_rng.h | 14 ++- src/lib/rng/rng.cpp | 59 +++++---- src/lib/rng/rng.h | 46 ++++--- src/tests/test_mceliece.cpp | 2 +- src/tests/test_rng.cpp | 51 +++----- 21 files changed, 320 insertions(+), 337 deletions(-) create mode 100644 src/lib/rng/auto_rng.h delete mode 100644 src/lib/rng/auto_rng/auto_rng.h delete mode 100644 src/lib/rng/auto_rng/info.txt (limited to 'doc') diff --git a/doc/manual/rng.rst b/doc/manual/rng.rst index 300570c3a..7eb229a5e 100644 --- a/doc/manual/rng.rst +++ b/doc/manual/rng.rst @@ -3,108 +3,77 @@ Random Number Generators ======================================== -The random number generators provided in Botan are meant for creating -keys, IVs, padding, nonces, and anything else that requires 'random' -data. It is important to remember that the output of these classes -will vary, even if they are supplied with the same seed (ie, two -``Randpool`` objects with similar initial states will not produce the -same output, because the value of high resolution timers is added to -the state at various points). - -To create a random number generator, instantiate a ``AutoSeeded_RNG`` -object. This object will handle choosing the right algorithms from the -set of enabled ones and doing seeding using OS specific -routines. The main service a RandomNumberGenerator provides is, of -course, random numbers: +The base class ``RandomNumberGenerator`` is in the header ``botan/rng.h``. -.. cpp:function:: byte RandomNumberGenerator::next_byte() +The major interfaces are + +.. cpp:function:: void RandomNumberGenerator::randomize(byte* output_array, size_t length) - Generates a single random byte and returns it + Places *length* random bytes into the provided buffer. -.. cpp:function:: void RandomNumberGenerator::randomize(byte* data, size_t length) +.. cpp:function:: void RandomNumberGenerator::add_entropy(const byte* data, size_t length) - Places *length* bytes into the array pointed to by *data* + Incorporates provided data into the state of the PRNG, if at all + possible. This works for most RNG types, including the system and + TPM RNGs. But if the RNG doesn't support this operation, the data is + dropped, no error is indicated. -To ensure good quality output, a PRNG needs to be seeded with truly -random data. Normally this is done for you. However it may happen that -your application has access to data that is potentially unpredictable -to an attacker. If so, use +.. cpp:function:: void RandomNumberGenerator::randomize_with_input(byte* data, size_t length, \ + const byte* ad, size_t ad_len) -.. cpp:function:: void RandomNumberGenerator::add_entropy(const byte* data, \ - size_t length) + Like randomize, but first incorporates the additional input field + into the state of the RNG. The additional input could be anything which + parameterizes this request. -which incorporates the data into the current randomness state. Don't -worry about filtering the data or doing any kind of cryptographic -preprocessing (such as hashing); the RNG objects in botan are designed -such that you can feed them any arbitrary non-random or even -maliciously chosen data - as long as at some point some of the seed -data was good the output will be secure. +.. cpp:function:: byte RandomNumberGenerator::next_byte() + Generates a single random byte and returns it. Note that calling this + function several times is much slower than calling ``randomize`` once + to produce multiple bytes at a time. -Implementation Notes +RNG Types ---------------------------------------- -Randpool -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following RNG types are included + +HMAC_DRBG +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +HMAC DRBG is a random number generator designed by NIST and specified +in SP 800-90A. It can be instantiated with any hash function but is +typically used with SHA-256, SHA-384, or SHA-512. -``Randpool`` is the primary PRNG within Botan. In recent versions all -uses of it have been wrapped by an implementation of the X9.31 PRNG -(see below). If for some reason you should have cause to create a PRNG -instead of using the "global" one owned by the library, it would be -wise to consider the same on the grounds of general caution; while -``Randpool`` is designed with known attacks and PRNG weaknesses in -mind, it is not an standard/official PRNG. The remainder of this -section is a (fairly technical, though high-level) description of the -algorithms used in this PRNG. Unless you have a specific interest in -this subject, the rest of this section might prove somewhat -uninteresting. - -``Randpool`` has an internal state called pool, which is 512 bytes -long. This is where entropy is mixed into and extracted from. There is also a -small output buffer (called buffer), which holds the data which has already -been generated but has just not been output yet. - -It is based around a MAC and a block cipher (which are currently -HMAC(SHA-256) and AES-256). Where a specific size is mentioned, it -should be taken as a multiple of the cipher's block size. For example, -if a 256-bit block cipher were used instead of AES, all the sizes -internally would double. Every time some new output is needed, we -compute the MAC of a counter and a high resolution timer. The -resulting MAC is XORed into the output buffer (wrapping as needed), -and the output buffer is then encrypted with AES, producing 16 bytes -of output. - -After 8 blocks (or 128 bytes) have been produced, we mix the pool. To -do this, we first rekey both the MAC and the cipher; the new MAC key -is the MAC of the current pool under the old MAC key, while the new -cipher key is the MAC of the current pool under the just-chosen MAC -key. We then encrypt the entire pool in CBC mode, using the current -(unused) output buffer as the IV. We then generate a new output -buffer, using the mechanism described in the previous paragraph. - -To add randomness to the PRNG, we compute the MAC of the input and XOR -the output into the start of the pool. Then we remix the pool and -produce a new output buffer. The initial MAC operation should make it -very hard for chosen inputs to harm the security of ``Randpool``, and -as HMAC should be able to hold roughly 256 bits of state, it is -unlikely that we are wasting much input entropy (or, if we are, it -doesn't matter, because we have a very abundant supply). +HMAC DRBG seems to be the most conservative generator of the NIST +approved options. + +System_RNG +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In ``system_rng.h``, objects of ``System_RNG`` reference a single +(process global) reference to the system PRNG (/dev/urandom or +CryptGenRandom). + +AutoSeeded_RNG +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This instantiates a new instance of a userspace PRNG, seeds it with +a default entropy pool. ANSI X9.31 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +This generator is deprecated and will be removed in a future release. + ``ANSI_X931_PRNG`` is the standard issue X9.31 Appendix A.2.4 PRNG, though using AES-256 instead of 3DES as the block cipher. This PRNG implementation has been checked against official X9.31 test vectors. -Internally, the PRNG holds a pointer to another PRNG (typically -Randpool). This internal PRNG generates the key and seed used by the -X9.31 algorithm, as well as the date/time vectors. Each time an X9.31 -PRNG object receives entropy, it passes it along to the PRNG it is -holding, and then pulls out some random bits to generate a new key and -seed. This PRNG considers itself seeded as soon as the internal PRNG -is seeded. - +Internally, the PRNG holds a pointer to another RNG object. This +internal PRNG generates the key and seed used by the X9.31 algorithm, +as well as the date/time vectors. Each time an X9.31 PRNG object +receives entropy, it passes it along to the PRNG it is holding, and +then pulls out some random bits to generate a new key and seed. This +PRNG considers itself seeded as soon as the internal PRNG is seeded. Entropy Sources --------------------------------- diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in index bd8cb6899..82a4ecd50 100644 --- a/src/build-data/buildh.in +++ b/src/build-data/buildh.in @@ -99,13 +99,20 @@ /* * RNGs will automatically poll the system for additional seed material -* after producing this many bytes of output. +* after producing this many bytes of output. Set to zero to disable +* automatic reseeding. */ -#define BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED 4096 -#define BOTAN_RNG_RESEED_POLL_BITS 128 +#define BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED 16384 +#define BOTAN_RNG_RESEED_POLL_BITS 256 #define BOTAN_RNG_AUTO_RESEED_TIMEOUT std::chrono::milliseconds(10) #define BOTAN_RNG_RESEED_DEFAULT_TIMEOUT std::chrono::milliseconds(50) -#define BOTAN_AUTO_RNG_DRBG_HASH_FUNCTION "SHA-384" + +/** +* Controls how AutoSeeded_RNG is instantiated +*/ +#define BOTAN_AUTO_RNG_DRBG HMAC_DRBG +#define BOTAN_AUTO_RNG_HASH "SHA-256" +#define BOTAN_AUTO_RNG_ENTROPY_TARGET 256 /* * Specifies (in order) the list of entropy sources that will be used diff --git a/src/build-data/policy/bsi.txt b/src/build-data/policy/bsi.txt index 5e3c5b921..2ae2ac3b2 100644 --- a/src/build-data/policy/bsi.txt +++ b/src/build-data/policy/bsi.txt @@ -41,7 +41,6 @@ eckcdsa ecdh # rng -auto_rng hmac_rng hmac_drbg diff --git a/src/build-data/policy/modern.txt b/src/build-data/policy/modern.txt index f0b6934f0..5a8a2f126 100644 --- a/src/build-data/policy/modern.txt +++ b/src/build-data/policy/modern.txt @@ -38,8 +38,8 @@ eme_oaep emsa_pssr emsa1 -auto_rng hmac_rng +hmac_drbg ffi diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp index c6149bf68..1fc0d7343 100644 --- a/src/cli/speed.cpp +++ b/src/cli/speed.cpp @@ -427,12 +427,10 @@ class Speed final : public Command #if defined(BOTAN_HAS_HMAC_DRBG) for(std::string hash : { "SHA-256", "SHA-384", "SHA-512" }) { - - auto hmac = Botan::MessageAuthenticationCode::create("HMAC(" + hash + ")"); - Botan::HMAC_DRBG hmac_drbg(hmac->clone()); + Botan::HMAC_DRBG hmac_drbg(hash); bench_rng(hmac_drbg, hmac_drbg.name(), msec, buf_size); - Botan::HMAC_RNG hmac_rng(hmac->clone(), hmac->clone()); + Botan::HMAC_RNG hmac_rng(hash); bench_rng(hmac_rng, hmac_rng.name(), msec, buf_size); } #endif diff --git a/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp b/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp index 0a6b85955..7dde17155 100644 --- a/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp +++ b/src/lib/entropy/darwin_secrandom/darwin_secrandom.cpp @@ -16,11 +16,11 @@ namespace Botan { */ void Darwin_SecRandom::poll(Entropy_Accumulator& accum) { - secure_vector& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST); + m_io_buf.resize(BOTAN_SYSTEM_RNG_POLL_REQUEST); - if(0 == SecRandomCopyBytes(kSecRandomDefault, buf.size(), buf.data())) + if(0 == SecRandomCopyBytes(kSecRandomDefault, m_io_buf.size(), m_io_buf.data())) { - accum.add(buf.data(), buf.size(), BOTAN_ENTROPY_ESTIMATE_STRONG_RNG); + accum.add(m_io_buf.data(), m_io_buf.size(), BOTAN_ENTROPY_ESTIMATE_STRONG_RNG); } } diff --git a/src/lib/entropy/darwin_secrandom/darwin_secrandom.h b/src/lib/entropy/darwin_secrandom/darwin_secrandom.h index 09cdc208d..267d177f0 100644 --- a/src/lib/entropy/darwin_secrandom/darwin_secrandom.h +++ b/src/lib/entropy/darwin_secrandom/darwin_secrandom.h @@ -21,6 +21,8 @@ class Darwin_SecRandom final : public Entropy_Source std::string name() const override { return "darwin_secrandom"; } void poll(Entropy_Accumulator& accum) override; + private: + secure_vector m_io_buf; }; } diff --git a/src/lib/entropy/dev_random/dev_random.cpp b/src/lib/entropy/dev_random/dev_random.cpp index aca161d64..ff746f34e 100644 --- a/src/lib/entropy/dev_random/dev_random.cpp +++ b/src/lib/entropy/dev_random/dev_random.cpp @@ -6,6 +6,7 @@ */ #include +#include #include #include @@ -31,15 +32,39 @@ Device_EntropySource::Device_EntropySource(const std::vector& fsnam const int flags = O_RDONLY | O_NONBLOCK | O_NOCTTY; + m_max_fd = 0; + for(auto fsname : fsnames) { - fd_type fd = ::open(fsname.c_str(), flags); + int fd = ::open(fsname.c_str(), flags); - if(fd >= 0 && fd < FD_SETSIZE) - m_devices.push_back(fd); - else if(fd >= 0) - ::close(fd); + if(fd > 0) + { + if(fd > FD_SETSIZE) + { + ::close(fd); + throw Exception("Open of OS RNG succeeded but fd is too large for fd_set"); + } + + m_dev_fds.push_back(fd); + m_max_fd = std::max(m_max_fd, fd); + } + else + { + /* + ENOENT or EACCES is normal as some of the named devices may not exist + on this system. But any other errno value probably indicates + either a bug in the application or file descriptor exhaustion. + */ + if(errno != ENOENT && errno != EACCES) + { + throw Exception("Opening OS RNG device failed with errno " + + std::to_string(errno)); + } + } } + + m_io_buf.resize(BOTAN_SYSTEM_RNG_POLL_REQUEST); } /** @@ -47,8 +72,11 @@ Device_EntropySource destructor: close all open devices */ Device_EntropySource::~Device_EntropySource() { - for(size_t i = 0; i != m_devices.size(); ++i) - ::close(m_devices[i]); + for(int fd : m_dev_fds) + { + // ignoring return value here, can't throw in destructor anyway + ::close(fd); + } } /** @@ -56,35 +84,36 @@ Device_EntropySource::~Device_EntropySource() */ void Device_EntropySource::poll(Entropy_Accumulator& accum) { - if(m_devices.empty()) + if(m_dev_fds.empty()) return; - fd_type max_fd = m_devices[0]; fd_set read_set; FD_ZERO(&read_set); - for(size_t i = 0; i != m_devices.size(); ++i) + + for(int dev_fd : m_dev_fds) { - FD_SET(m_devices[i], &read_set); - max_fd = std::max(m_devices[i], max_fd); + FD_SET(dev_fd, &read_set); } struct ::timeval timeout; - timeout.tv_sec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS / 1000); timeout.tv_usec = (BOTAN_SYSTEM_RNG_POLL_TIMEOUT_MS % 1000) * 1000; - if(::select(max_fd + 1, &read_set, nullptr, nullptr, &timeout) < 0) - return; - - secure_vector& buf = accum.get_io_buf(BOTAN_SYSTEM_RNG_POLL_REQUEST); - - for(size_t i = 0; i != m_devices.size(); ++i) + if(::select(m_max_fd + 1, &read_set, nullptr, nullptr, &timeout) > 0) { - if(FD_ISSET(m_devices[i], &read_set)) + for(int dev_fd : m_dev_fds) { - const ssize_t got = ::read(m_devices[i], buf.data(), buf.size()); - if(got > 0) - accum.add(buf.data(), got, BOTAN_ENTROPY_ESTIMATE_STRONG_RNG); + if(FD_ISSET(dev_fd, &read_set)) + { + const ssize_t got = ::read(dev_fd, m_io_buf.data(), m_io_buf.size()); + + if(got > 0) + { + accum.add(m_io_buf.data(), + static_cast(got), + BOTAN_ENTROPY_ESTIMATE_STRONG_RNG); + } + } } } } diff --git a/src/lib/entropy/dev_random/dev_random.h b/src/lib/entropy/dev_random/dev_random.h index 1f29b2f64..05b36f3eb 100644 --- a/src/lib/entropy/dev_random/dev_random.h +++ b/src/lib/entropy/dev_random/dev_random.h @@ -25,10 +25,12 @@ class Device_EntropySource final : public Entropy_Source void poll(Entropy_Accumulator& accum) override; Device_EntropySource(const std::vector& fsnames); + ~Device_EntropySource(); private: - typedef int fd_type; - std::vector m_devices; + secure_vector m_io_buf; + std::vector m_dev_fds; + int m_max_fd; }; } diff --git a/src/lib/prov/tpm/tpm.h b/src/lib/prov/tpm/tpm.h index 15bc216ab..b8093518c 100644 --- a/src/lib/prov/tpm/tpm.h +++ b/src/lib/prov/tpm/tpm.h @@ -1,3 +1,4 @@ + /* * TPM 1.2 interface * (C) 2015 Jack Lloyd @@ -71,7 +72,7 @@ class BOTAN_DLL TPM_Context TSS_HTPM m_tpm; }; -class BOTAN_DLL TPM_RNG : public RandomNumberGenerator +class BOTAN_DLL TPM_RNG : public Hardware_RNG { public: TPM_RNG(TPM_Context& ctx) : m_ctx(ctx) {} @@ -90,7 +91,7 @@ class BOTAN_DLL TPM_RNG : public RandomNumberGenerator bool is_seeded() const override { return true; } - void clear() const override {} + void clear() override {} private: TPM_Context& m_ctx; diff --git a/src/lib/rng/auto_rng.h b/src/lib/rng/auto_rng.h new file mode 100644 index 000000000..b51390ae2 --- /dev/null +++ b/src/lib/rng/auto_rng.h @@ -0,0 +1,47 @@ +/* +* Auto Seeded RNG +* (C) 2008 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_AUTO_SEEDING_RNG_H__ +#define BOTAN_AUTO_SEEDING_RNG_H__ + +#include + +namespace Botan { + +class BOTAN_DLL AutoSeeded_RNG final : public RandomNumberGenerator + { + public: + void randomize(byte out[], size_t len) override; + + void randomize_with_input(byte output[], size_t output_len, + const byte input[], size_t input_len) override; + + bool is_seeded() const override { return m_rng->is_seeded(); } + + void clear() override { m_rng->clear(); m_counter = 0; } + + std::string name() const override { return m_rng->name(); } + + size_t reseed_with_sources(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override + { + return m_rng->reseed_with_sources(srcs, poll_bits, poll_timeout); + } + + void add_entropy(const byte in[], size_t len) override + { m_rng->add_entropy(in, len); } + + AutoSeeded_RNG(size_t bytes_before_reseed = BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED); + private: + std::unique_ptr m_rng; + uint32_t m_counter = 0; + }; + +} + +#endif diff --git a/src/lib/rng/auto_rng/auto_rng.h b/src/lib/rng/auto_rng/auto_rng.h deleted file mode 100644 index 72ea88d3e..000000000 --- a/src/lib/rng/auto_rng/auto_rng.h +++ /dev/null @@ -1,45 +0,0 @@ -/* -* Auto Seeded RNG -* (C) 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_AUTO_SEEDING_RNG_H__ -#define BOTAN_AUTO_SEEDING_RNG_H__ - -#include -#include - -namespace Botan { - -class AutoSeeded_RNG : public RandomNumberGenerator - { - public: - void randomize(byte out[], size_t len) override - { m_rng->randomize(out, len); } - - bool is_seeded() const override { return m_rng->is_seeded(); } - - void clear() override { m_rng->clear(); } - - std::string name() const override { return m_rng->name(); } - - size_t reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout) override - { - return m_rng->reseed_with_sources(srcs, poll_bits, poll_timeout); - } - - void add_entropy(const byte in[], size_t len) override - { m_rng->add_entropy(in, len); } - - AutoSeeded_RNG() : m_rng(RandomNumberGenerator::make_rng()) {} - private: - std::unique_ptr m_rng; - }; - -} - -#endif diff --git a/src/lib/rng/auto_rng/info.txt b/src/lib/rng/auto_rng/info.txt deleted file mode 100644 index 4f48f484b..000000000 --- a/src/lib/rng/auto_rng/info.txt +++ /dev/null @@ -1,9 +0,0 @@ -define AUTO_SEEDING_RNG 20131128 - - -hmac_rng -hmac -sha2_32 -sha2_64 -#dev_random|cryptoapi_rng|unix_procs|proc_walk - diff --git a/src/lib/rng/hmac_drbg/hmac_drbg.cpp b/src/lib/rng/hmac_drbg/hmac_drbg.cpp index 201a9f39b..6fdd7daf9 100644 --- a/src/lib/rng/hmac_drbg/hmac_drbg.cpp +++ b/src/lib/rng/hmac_drbg/hmac_drbg.cpp @@ -10,9 +10,14 @@ namespace Botan { -HMAC_DRBG::HMAC_DRBG(const std::string& hmac_hash) : - HMAC_DRBG(hmac_hash, BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED) - {} +HMAC_DRBG::HMAC_DRBG(MessageAuthenticationCode* hmac, + size_t max_bytes_before_reseed) : + Stateful_RNG(max_bytes_before_reseed), + m_mac(hmac) + { + m_V.resize(m_mac->output_length()); + clear(); + } HMAC_DRBG::HMAC_DRBG(const std::string& hmac_hash, size_t max_bytes_before_reseed) : @@ -27,12 +32,13 @@ HMAC_DRBG::HMAC_DRBG(const std::string& hmac_hash, } m_V.resize(m_mac->output_length()); - clear(); } void HMAC_DRBG::clear() { + Stateful_RNG::clear(); + for(size_t i = 0; i != m_V.size(); ++i) m_V[i] = 0x01; m_mac->set_key(std::vector(m_mac->output_length(), 0x00)); diff --git a/src/lib/rng/hmac_drbg/hmac_drbg.h b/src/lib/rng/hmac_drbg/hmac_drbg.h index f52ae9de1..8ee598470 100644 --- a/src/lib/rng/hmac_drbg/hmac_drbg.h +++ b/src/lib/rng/hmac_drbg/hmac_drbg.h @@ -19,10 +19,14 @@ namespace Botan { class BOTAN_DLL HMAC_DRBG final : public Stateful_RNG { public: - HMAC_DRBG(const std::string& hmac_hash); - + /** + * Initialize an HMAC_DRBG instance with the given hash function + */ HMAC_DRBG(const std::string& hmac_hash, - size_t max_bytes_before_reseed); + size_t max_bytes_before_reseed = BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED); + + HMAC_DRBG(MessageAuthenticationCode* hmac, + size_t max_bytes_before_reseed = BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED); std::string name() const override; diff --git a/src/lib/rng/hmac_rng/hmac_rng.cpp b/src/lib/rng/hmac_rng/hmac_rng.cpp index 7a9e4dbc5..410e3040a 100644 --- a/src/lib/rng/hmac_rng/hmac_rng.cpp +++ b/src/lib/rng/hmac_rng/hmac_rng.cpp @@ -9,15 +9,35 @@ #include #include #include -#include namespace Botan { +HMAC_RNG::HMAC_RNG(const std::string& hash, size_t max_before_reseed) : + Stateful_RNG(max_before_reseed) + { + m_extractor = MAC::create("HMAC(" + hash + ")"); + if(!m_extractor) + throw Invalid_Argument("HMAC_RNG hash not found"); + + m_prf.reset(m_extractor->clone()); + + if(!m_prf->valid_keylength(m_extractor->output_length()) || + !m_extractor->valid_keylength(m_prf->output_length())) + { + throw Invalid_Argument("HMAC_RNG: Bad algo combination " + + m_extractor->name() + " and " + + m_prf->name()); + } + + this->clear(); + } + /* * HMAC_RNG Constructor */ HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor, MessageAuthenticationCode* prf) : + Stateful_RNG(BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED), m_extractor(extractor), m_prf(prf) { if(!m_prf->valid_keylength(m_extractor->output_length()) || @@ -33,7 +53,7 @@ HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor, void HMAC_RNG::clear() { - m_collected_entropy_estimate = 0; + Stateful_RNG::clear(); m_counter = 0; // First PRF inputs are all zero, as specified in section 2 @@ -71,7 +91,7 @@ void HMAC_RNG::clear() void HMAC_RNG::new_K_value(byte label) { m_prf->update(m_K); - m_prf->update_be(m_pid); + m_prf->update_be(last_pid()); m_prf->update_be(OS::get_processor_timestamp()); m_prf->update_be(OS::get_system_timestamp_ns()); m_prf->update_be(m_counter++); @@ -84,76 +104,38 @@ void HMAC_RNG::new_K_value(byte label) */ void HMAC_RNG::randomize(byte out[], size_t length) { - if(!is_seeded() || m_pid != OS::get_process_id()) - { - reseed(256); - if(!is_seeded()) - throw PRNG_Unseeded(name()); - } - - const size_t max_per_prf_iter = m_prf->output_length() / 2; - - m_output_since_reseed += length; - - if(m_output_since_reseed >= BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED) - { - reseed_with_sources(Entropy_Sources::global_sources(), - BOTAN_RNG_RESEED_POLL_BITS, - BOTAN_RNG_AUTO_RESEED_TIMEOUT); - } + reseed_check(length); - /* - HMAC KDF as described in E-t-E, using a CTXinfo of "rng" - */ while(length) { new_K_value(Running); - const size_t copied = std::min(length, max_per_prf_iter); + const size_t copied = std::min(length, m_prf->output_length()); copy_mem(out, m_K.data(), copied); out += copied; length -= copied; } + + new_K_value(BlockFinished); } size_t HMAC_RNG::reseed_with_sources(Entropy_Sources& srcs, size_t poll_bits, std::chrono::milliseconds timeout) { + new_K_value(Reseed); + m_extractor->update(m_K); // m_K is the PRF output + /* - Using the terminology of E-t-E, XTR is the MAC function (normally - HMAC) seeded with XTS (below) and we form SKM, the key material, by - polling as many sources as we think needed to reach our polling - goal. We then also include feedback of the current PRK so that - a bad poll doesn't wipe us out. + * This ends up calling add_entropy which provides input to the extractor */ - - typedef std::chrono::system_clock clock; - auto deadline = clock::now() + timeout; - - double bits_collected = 0; - - Entropy_Accumulator accum([&](const byte in[], size_t in_len, double entropy_estimate) { - m_extractor->update(in, in_len); - bits_collected += entropy_estimate; - return (bits_collected >= poll_bits || clock::now() > deadline); - }); - - srcs.poll(accum); + size_t bits_collected = Stateful_RNG::reseed_with_sources(srcs, poll_bits, timeout); /* - * It is necessary to feed forward poll data. Otherwise, a good poll - * (collecting a large amount of conditional entropy) followed by a - * bad one (collecting little) would be unsafe. Do this by - * generating new PRF outputs using the previous key and feeding - * them into the extractor function. + Now derive the new PRK using everything that has been fed into + the extractor, and set the PRF key to that */ - new_K_value(Reseed); - m_extractor->update(m_K); // K is the CTXinfo=reseed PRF output - - /* Now derive the new PRK using everything that has been fed into - the extractor, and set the PRF key to that */ m_prf->set_key(m_extractor->final()); // Now generate a new PRF output to use as the XTS extractor salt @@ -164,32 +146,17 @@ size_t HMAC_RNG::reseed_with_sources(Entropy_Sources& srcs, zeroise(m_K); m_counter = 0; - m_collected_entropy_estimate = - std::min(m_collected_entropy_estimate + static_cast(bits_collected), - m_extractor->output_length() * 8); - - m_output_since_reseed = 0; - m_pid = OS::get_process_id(); - - return static_cast(bits_collected); - } - -bool HMAC_RNG::is_seeded() const - { - return (m_collected_entropy_estimate >= 256); + return bits_collected; } /* -* Add user-supplied entropy to the extractor input then reseed -* to incorporate it into the state +* Add user-supplied entropy to the extractor input then set remaining +* output length to for a reseed on next use. */ void HMAC_RNG::add_entropy(const byte input[], size_t length) { m_extractor->update(input, length); - - reseed_with_sources(Entropy_Sources::global_sources(), - BOTAN_RNG_RESEED_POLL_BITS, - BOTAN_RNG_RESEED_DEFAULT_TIMEOUT); + force_reseed(); } /* diff --git a/src/lib/rng/hmac_rng/hmac_rng.h b/src/lib/rng/hmac_rng/hmac_rng.h index 95ae25e39..f2f8a610d 100644 --- a/src/lib/rng/hmac_rng/hmac_rng.h +++ b/src/lib/rng/hmac_rng/hmac_rng.h @@ -24,11 +24,10 @@ namespace Botan { * Krawczyk's paper), for instance one could use HMAC(SHA-512) as the * extractor and CMAC(AES-256) as the PRF. */ -class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator +class BOTAN_DLL HMAC_RNG : public Stateful_RNG { public: void randomize(byte buf[], size_t len) override; - bool is_seeded() const override; void clear() override; std::string name() const override; @@ -44,23 +43,26 @@ class BOTAN_DLL HMAC_RNG : public RandomNumberGenerator */ HMAC_RNG(MessageAuthenticationCode* extractor, MessageAuthenticationCode* prf); + + /** + * Use the specified hash for both the extractor and PRF functions + */ + HMAC_RNG(const std::string& hash, + size_t max_before_reseed = BOTAN_RNG_MAX_OUTPUT_BEFORE_RESEED); private: std::unique_ptr m_extractor; std::unique_ptr m_prf; enum HMAC_PRF_Label { Running, + BlockFinished, Reseed, ExtractorSeed, }; void new_K_value(byte label); - size_t m_collected_entropy_estimate = 0; - size_t m_output_since_reseed = 0; - secure_vector m_K; u32bit m_counter = 0; - u32bit m_pid = 0; }; } diff --git a/src/lib/rng/rng.cpp b/src/lib/rng/rng.cpp index 526693561..8144ac293 100644 --- a/src/lib/rng/rng.cpp +++ b/src/lib/rng/rng.cpp @@ -6,12 +6,18 @@ */ #include -#include #include #include #include #include -#include + +#if defined(BOTAN_HAS_HMAC_DRBG) + #include +#endif + +#if defined(BOTAN_HAS_HMAC_RNG) + #include +#endif namespace Botan { @@ -50,9 +56,15 @@ size_t RandomNumberGenerator::reseed_with_sources(Entropy_Sources& srcs, return bits_collected; } -Stateful_RNG::Stateful_RNG(size_t bytes_before_reseed) : - m_max_bytes_before_reseed_required(bytes_before_reseed) +Stateful_RNG::Stateful_RNG(size_t bytes_before_reseed) : m_bytes_before_reseed(bytes_before_reseed) + { + } + +void Stateful_RNG::clear() { + m_successful_initialization = false; + m_bytes_since_reseed = 0; + m_last_pid = 0; } size_t Stateful_RNG::reseed_with_sources(Entropy_Sources& srcs, @@ -81,10 +93,9 @@ void Stateful_RNG::reseed_check(size_t bytes_requested) { this->reseed(BOTAN_RNG_RESEED_POLL_BITS); } - else if(m_max_bytes_before_reseed_required > 0 && - m_bytes_since_reseed >= m_max_bytes_before_reseed_required) + else if(m_bytes_before_reseed > 0 && m_bytes_since_reseed >= m_bytes_before_reseed) { - this->reseed_with_timeout(BOTAN_RNG_AUTO_RESEED_POLL_BITS, + this->reseed_with_timeout(BOTAN_RNG_RESEED_POLL_BITS, BOTAN_RNG_AUTO_RESEED_TIMEOUT); } @@ -112,8 +123,10 @@ RandomNumberGenerator* RandomNumberGenerator::make_rng() AutoSeeded_RNG::AutoSeeded_RNG(size_t max_bytes_before_reseed) { - m_rng.reset(new HMAC_DRBG(BOTAN_AUTO_RNG_DRBG_HASH_FUNCTION, max_bytes_before_reseed)); - size_t bits = m_rng->reseed(384); + m_rng.reset(new BOTAN_AUTO_RNG_DRBG(BOTAN_AUTO_RNG_HASH, max_bytes_before_reseed)); + + size_t bits = m_rng->reseed(BOTAN_AUTO_RNG_ENTROPY_TARGET); + if(!m_rng->is_seeded()) { throw Exception("AutoSeeded_RNG failed to gather enough entropy only got " + @@ -124,24 +137,22 @@ AutoSeeded_RNG::AutoSeeded_RNG(size_t max_bytes_before_reseed) void AutoSeeded_RNG::randomize(byte output[], size_t output_len) { /* - This data is not secret so skipping a vector/secure_vector allows - avoiding an allocation. + Form additional input which is provided to the PRNG implementation + to paramaterize the KDF output. */ - typedef std::chrono::high_resolution_clock clock; - - byte nonce_buf[16] = { 0 }; - const uint32_t cur_ctr = m_counter++; - const uint32_t cur_pid = OS::get_process_id(); - const uint64_t cur_time = clock::now().time_since_epoch().count(); - - store_le(cur_ctr, nonce_buf); - store_le(cur_pid, nonce_buf + 4); - store_le(cur_time, nonce_buf + 8); + byte additional_input[24] = { 0 }; + store_le(OS::get_system_timestamp_ns(), additional_input); + store_le(OS::get_processor_timestamp(), additional_input + 8); + store_le(OS::get_process_id(), additional_input + 16); + store_le(m_counter++, additional_input + 20); - m_rng->randomize_with_input(output, output_len, - nonce_buf, sizeof(nonce_buf)); + randomize_with_input(output, output_len, additional_input, sizeof(additional_input)); + } - ++m_counter; +void AutoSeeded_RNG::randomize_with_input(byte output[], size_t output_len, + const byte ad[], size_t ad_len) + { + m_rng->randomize_with_input(output, output_len, ad, ad_len); } } diff --git a/src/lib/rng/rng.h b/src/lib/rng/rng.h index 2e08ce553..d5fae0261 100644 --- a/src/lib/rng/rng.h +++ b/src/lib/rng/rng.h @@ -154,7 +154,7 @@ class BOTAN_DLL RandomNumberGenerator * bytes have been output. * * Not implemented by RNGs which access an external RNG, such as the -* system PRNG or an hardware RNG. +* system PRNG or a hardware RNG. */ class BOTAN_DLL Stateful_RNG : public RandomNumberGenerator { @@ -182,15 +182,36 @@ class BOTAN_DLL Stateful_RNG : public RandomNumberGenerator protected: void reseed_check(size_t bytes_requested); + void clear() override; + + /** + * Mark state as requiring a reseed on next use + */ + void force_reseed() { m_bytes_since_reseed = m_bytes_before_reseed; } + + uint32_t last_pid() const { return m_last_pid; } + + mutable std::mutex m_mutex; + private: - const size_t m_max_bytes_before_reseed_required; + const size_t m_bytes_before_reseed; size_t m_bytes_since_reseed = 0; uint32_t m_last_pid = 0; bool m_successful_initialization = false; }; +/** +* Convenience typedef +*/ typedef RandomNumberGenerator RNG; +/** +* Hardware RNG has no members but exists to tag hardware RNG types +*/ +class BOTAN_DLL Hardware_RNG : public RandomNumberGenerator + { + }; + /** * Null/stub RNG - fails if you try to use it for anything * This is not generally useful except for in certain tests @@ -212,7 +233,6 @@ class BOTAN_DLL Null_RNG final : public RandomNumberGenerator std::string name() const override { return "Null_RNG"; } }; - /** * Wraps access to a RNG in a mutex */ @@ -225,20 +245,6 @@ class BOTAN_DLL Serialized_RNG final : public RandomNumberGenerator m_rng->randomize(out, len); } - void randomize_with_input(byte output[], size_t output_length, - const byte input[], size_t input_length) override - { - std::lock_guard lock(m_mutex); - m_rng->randomize_with_input(output, output_length, - input, input_length); - } - - void add_entropy(const byte in[], size_t len) override - { - std::lock_guard lock(m_mutex); - m_rng->add_entropy(in, len); - } - bool is_seeded() const override { std::lock_guard lock(m_mutex); @@ -265,6 +271,12 @@ class BOTAN_DLL Serialized_RNG final : public RandomNumberGenerator return m_rng->reseed_with_sources(src, bits, msec); } + void add_entropy(const byte in[], size_t len) override + { + std::lock_guard lock(m_mutex); + m_rng->add_entropy(in, len); + } + Serialized_RNG() : m_rng(RandomNumberGenerator::make_rng()) {} explicit Serialized_RNG(RandomNumberGenerator* rng) : m_rng(rng) {} private: diff --git a/src/tests/test_mceliece.cpp b/src/tests/test_mceliece.cpp index 8c0ad4564..8658bf5e6 100644 --- a/src/tests/test_mceliece.cpp +++ b/src/tests/test_mceliece.cpp @@ -77,7 +77,7 @@ class McEliece_Keygen_Encrypt_Test : public Text_Based_Test result.test_eq("private key fingerprint", hash_bytes(mce_priv.pkcs8_private_key()), fprint_priv); rng.clear(); - rng.add_entropy(encrypt_seed.data(), encrypt_seed.size()); + rng.initialize_with(encrypt_seed.data(), encrypt_seed.size()); try { diff --git a/src/tests/test_rng.cpp b/src/tests/test_rng.cpp index 7f1c1f123..d8c10bf55 100644 --- a/src/tests/test_rng.cpp +++ b/src/tests/test_rng.cpp @@ -21,37 +21,10 @@ namespace { Botan::RandomNumberGenerator* get_rng(const std::string& algo_str, const std::vector& ikm) { - class AllOnce_RNG : public Fixed_Output_RNG - { - public: - explicit AllOnce_RNG(const std::vector& in) : Fixed_Output_RNG(in) {} - - Botan::secure_vector random_vec(size_t) override - { - Botan::secure_vector vec(this->remaining()); - this->randomize(vec.data(), vec.size()); - return vec; - } - }; - const std::vector algo_name = Botan::parse_algorithm_name(algo_str); const std::string rng_name = algo_name[0]; -#if defined(BOTAN_HAS_HMAC_DRBG) - if(rng_name == "HMAC_DRBG") - { - auto mac = Botan::MessageAuthenticationCode::create("HMAC(" + algo_name[1] + ")"); - - if(!mac) - { - return nullptr; - } - - return new Botan::HMAC_DRBG(mac.release(), new AllOnce_RNG(ikm)); - } - -#endif #if defined(BOTAN_HAS_X931_RNG) if(rng_name == "X9.31-RNG") @@ -110,7 +83,8 @@ class HMAC_DRBG_Tests : public Text_Based_Test { public: HMAC_DRBG_Tests() : Text_Based_Test("hmac_drbg.vec", - {"EntropyInput", "EntropyInputReseed", "Out"}) {} + {"EntropyInput", "EntropyInputReseed", "Out"}, + {"AdditionalInput1", "AdditionalInput2"}) {} Test::Result run_one_test(const std::string& algo, const VarMap& vars) override { @@ -118,23 +92,30 @@ class HMAC_DRBG_Tests : public Text_Based_Test const std::vector reseed_input = get_req_bin(vars, "EntropyInputReseed"); const std::vector expected = get_req_bin(vars, "Out"); - Test::Result result(algo); + const std::vector ad1 = get_opt_bin(vars, "AdditionalInput1"); + const std::vector ad2 = get_opt_bin(vars, "AdditionalInput2"); - std::unique_ptr rng(get_rng(algo, seed_input)); - if(!rng) + Test::Result result("HMAC_DRBG(" + algo + ")"); + + auto mac = Botan::MessageAuthenticationCode::create("HMAC(" + algo + ")"); + if(!mac) { - result.note_missing("RNG " + algo); + result.note_missing("HMAC(" + algo + ")"); return result; } - rng->reseed(0); // force initialization + std::unique_ptr rng(new Botan::HMAC_DRBG(mac.release(), 0)); + rng->initialize_with(seed_input.data(), seed_input.size()); // now reseed rng->add_entropy(reseed_input.data(), reseed_input.size()); - rng->random_vec(expected.size()); // discard 1st block + std::vector out(expected.size()); + // first block is discarded + rng->randomize_with_input(out.data(), out.size(), ad1.data(), ad1.size()); + rng->randomize_with_input(out.data(), out.size(), ad2.data(), ad2.size()); - result.test_eq("rng", rng->random_vec(expected.size()), expected); + result.test_eq("rng", out, expected); return result; } -- cgit v1.2.3 From 3404b86897748307457f16a32dd7492e39564365 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Mon, 18 Jul 2016 16:51:04 -0400 Subject: Update news [ci skip] --- doc/news.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index 6edc34e62..67f458fec 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -12,6 +12,10 @@ Version 1.11.31, Not Yet Released * Add KDF1 from ISO 18033 (GH #483) +* RNG changes: NIST SP900-80's HMAC_DRBG is now the default generator + for userspace RNG (AutoSeeded_RNG). HMAC_DRBG now attempts to detect + use of fork (via pid checks) + * Fix undefined behavior in Curve25519 on platforms without a native 128-bit integer type. This was known to produce incorrect results on 32-bit ARM under Clang. GH #532 @@ -22,7 +26,7 @@ Version 1.11.31, Not Yet Released a future release. The developers believe that it is unlikely that any modern system requires EGD and so the code is now dead weight. If you rely on EGD support, you should contact the developers by email or GitHub ASAP. - + * Changes in DLIES: Previously the input to the KDF was the concatenation of the (ephemeral) public key and the secret value derived by the key agreement operation. Now the input is only the secret value obtained @@ -33,7 +37,6 @@ Version 1.11.31, Not Yet Released Furthermore the order of the output was changed from {public key, tag, ciphertext} to {public key, ciphertext, tag}. Both modes are compatible with bouncycastle. - * Fix a bug in ANSI X9.23 padding mode, which returned one byte more than the given block size (GH #529). -- cgit v1.2.3 From a22a54fd962f4aafa7ea3d6a888d8d4ab779f1ba Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 12 Aug 2016 12:36:36 -0400 Subject: Changes to TLS::Callbacks for GH PR #457 Make TLS::Channel::m_callbacks a reference, so deriving from TLS::Callbacks works Split out the compat (std::function) based interface to Compat_Callbacks. This avoids the overhead of empty std::functions when using the virtual interface, and ensures the virtual interface works since there is no callback path that does not involve a vtable lookup. Rename the TLS::Callback functions. Since the idea is that often an owning class will pass *this as the callbacks argument, it is good to namespace the virtual functions so as not to conflict with other names chosen by the class. Specifically, prefixes all cb functions with tls_ Revert changes to use the old style alert callback (with no longer used data/len params) so no API changes are required for old code. The new Callbacks interface continues to just receive the alert code itself. Switch to virtual function interface in CLI tls_client for testing. Inline tls_server_handshake_state.h - only used in tls_server.cpp Fix tests - test looked like it was creating a new client object but it was not actually being used. And when enabled, it failed because the queues were not being emptied in between. So, fix that. --- doc/manual/tls.rst | 144 +++++++++++++++---------------- src/cli/tls_client.cpp | 38 ++++---- src/cli/tls_proxy.cpp | 17 ++-- src/cli/tls_server.cpp | 12 ++- src/lib/tls/info.txt | 1 - src/lib/tls/tls_blocking.cpp | 8 +- src/lib/tls/tls_blocking.h | 2 + src/lib/tls/tls_callbacks.h | 106 ++++++++++++++++------- src/lib/tls/tls_channel.cpp | 31 +++---- src/lib/tls/tls_channel.h | 23 ++--- src/lib/tls/tls_client.cpp | 9 +- src/lib/tls/tls_client.h | 57 +++++++++--- src/lib/tls/tls_handshake_state.cpp | 10 ++- src/lib/tls/tls_handshake_state.h | 14 +-- src/lib/tls/tls_record.h | 4 - src/lib/tls/tls_server.cpp | 36 ++++++-- src/lib/tls/tls_server.h | 23 ++++- src/lib/tls/tls_server_handshake_state.h | 48 ----------- src/tests/unit_tls.cpp | 93 ++++++++++++-------- 19 files changed, 376 insertions(+), 300 deletions(-) delete mode 100644 src/lib/tls/tls_server_handshake_state.h (limited to 'doc') diff --git a/doc/manual/tls.rst b/doc/manual/tls.rst index a10a4280c..7210fc092 100644 --- a/doc/manual/tls.rst +++ b/doc/manual/tls.rst @@ -22,44 +22,52 @@ instance, by reading from a network socket) it passes that information to TLS using :cpp:func:`TLS::Channel::received_data`. If the data passed in results in some change in the state, such as a handshake completing, or some data or an alert being received from the other -side, then a user provided callback will be invoked. If the reader is -familiar with OpenSSL's BIO layer, it might be analagous to saying the -only way of interacting with Botan's TLS is via a `BIO_mem` I/O +side, then the appropriate user provided callback will be invoked. + +If the reader is familiar with OpenSSL's BIO layer, it might be analagous +to saying the only way of interacting with Botan's TLS is via a `BIO_mem` I/O abstraction. This makes the library completely agnostic to how you write your network layer, be it blocking sockets, libevent, asio, a -message queue, etc. +message queue, lwIP on RTOS, some carrier pidgeons, etc. -The callbacks for TLS have the signatures +Starting in 1.11.31, the application callbacks are encapsulated as the class +``TLS::Callbacks`` with the following members. The first four (``tls_emit_data``, +``tls_record_received``, ``tls_alert``, and ``tls_session_established``) are +mandatory for using TLS, all others are optional and provide additional +information about the connection. - .. cpp:function:: void output_fn(const byte data[], size_t data_len) + .. cpp:function:: void tls_emit_data(const byte data[], size_t data_len) - TLS requests that all bytes of *data* be queued up to send to the - counterparty. After this function returns, *data* will be - overwritten, so a copy of the input must be made if the callback + The TLS stack requests that all bytes of *data* be queued up to send to the + counterparty. After this function returns, the buffer containing *data* will + be overwritten, so a copy of the input must be made if the callback cannot send the data immediately. - .. cpp:function:: void data_cb(const byte data[], size_t data_len) + The write can be deferred but for TLS all writes must occur *in order*. + For DTLS this is not strictly required, but is still recommended. + + .. cpp:function:: void tls_record_received(uint64_t rec_no, const byte data[], size_t data_len) + + Called once for each application_data record which is received, with the + matching (TLS level) record sequence number. - Called whenever application data is received from the other side - of the connection, in which case *data* and *data_len* specify - the data received. This array will be overwritten sometime after - the callback returns, so again a copy should be made if need be. + Currently empty records are ignored and do not instigate a callback, + but this may change in a future release. - .. cpp:function:: void alert_cb(Alert alert, const byte data[], size_t data_len) + As with ``tls_emit_data``, the array will be overwritten sometime after + the callback returns, so a copy should be made if needed. - Called when an alert is received. Normally, data is null and - data_len is 0, as most alerts have no associated data. However, - if TLS heartbeats (see :rfc:`6520`) were negotiated, and we - initiated a heartbeat, then if/when the other party responds, - ``alert_cb`` will be called with whatever data was included in - the heartbeat response (if any) along with a psuedo-alert value - of ``HEARTBEAT_PAYLOAD``. + .. cpp:function:: void tls_alert(Alert alert) - .. cpp:function:: bool handshake_cb(const TLS::Session& session) + Called when an alert is received from the peer. Note that alerts + received before the handshake is complete are not authenticated and + could have been inserted by a MITM attacker. + + .. cpp:function:: bool tls_session_established(const TLS::Session& session) Called whenever a negotiation completes. This can happen more - than once on any connection. The *session* parameter provides - information about the session which was established. + than once on any connection, if renegotiation occurs. The *session* parameter + provides information about the session which was just established. If this function returns false, the session will not be cached for later resumption. @@ -68,8 +76,22 @@ The callbacks for TLS have the signatures exception which will send a close message to the counterparty and reset the connection state. -You can of course use tools like ``std::bind`` to bind additional -parameters to your callback functions. + .. cpp:function:: void tls_inspect_handshake_msg(const Handshake_Message&) + + This callback is optional, and can be used to inspect all handshake messages + while the session establishment occurs. + + .. cpp:function:: void tls_log_debug(const char*) + + This callback is for exerimental purposes and currently unused. It may be + removed or modified in a future release. + +Versions from 1.11.0 to 1.11.30 did not have ``TLS::Callbacks` and instead +used independent std::functions to pass the various callback functions. +This interface is currently still included but is deprecated and will be removed +in a future release. For the documentation for this interface, please check +the docs in 1.11.30. This version of the manual only documents the new interface +added in 1.11.31. TLS Channels ---------------------------------------- @@ -80,16 +102,6 @@ available: .. cpp:class:: TLS::Channel - .. cpp:type:: std::function output_fn - - .. cpp:type:: std::function data_cb - - .. cpp:type:: std::function alert_cb - - .. cpp:type:: std::function handshake_cb - - Typedefs used in the code for the functions described above - .. cpp:function:: size_t received_data(const byte buf[], size_t buf_size) .. cpp:function:: size_t received_data(const std::vector& buf) @@ -194,10 +206,7 @@ TLS Clients .. cpp:class:: TLS::Client .. cpp:function:: Client( \ - output_fn out, \ - data_cb app_data_cb, \ - alert_cb alert_cb, \ - handshake_cb hs_cb, \ + Callbacks& callbacks, Session_Manager& session_manager, \ Credentials_Manager& creds, \ const Policy& policy, \ @@ -211,29 +220,8 @@ TLS Clients Initialize a new TLS client. The constructor will immediately initiate a new session. - The *output_fn* callback will be called with output that - should be sent to the counterparty. For instance this will be - called immediately from the constructor after the client hello - message is constructed. An implementation of *output_fn* is - allowed to defer the write (for instance if writing when the - callback occurs would block), but should eventually write the data - to the counterparty *in order*. - - The *data_cb* will be called with data sent by the counterparty - after it has been processed. The byte array and size_t represent - the plaintext value and size. - - The *alert_cb* will be called when a protocol alert is received, - commonly with a close alert during connection teardown. - - The *handshake_cb* function is called when a handshake - (either initial or renegotiation) is completed. The return value of - the callback specifies if the session should be cached for later - resumption. If the function for some reason desires to prevent the - connection from completing, it should throw an exception - (preferably a TLS::Exception, which can provide more specific alert - information to the counterparty). The :cpp:class:`TLS::Session` - provides information about the session that was just established. + The *callbacks* parameter specifies the various application callbacks + which pertain to this particular client connection. The *session_manager* is an interface for storing TLS sessions, which allows for session resumption upon reconnecting to a server. @@ -285,10 +273,7 @@ TLS Servers .. cpp:class:: TLS::Server .. cpp:function:: Server( \ - output_fn output, \ - data_cb data_cb, \ - alert_cb alert_cb, \ - handshake_cb handshake_cb, \ + Callbacks& callbacks, Session_Manager& session_manager, \ Credentials_Manager& creds, \ const Policy& policy, \ @@ -298,11 +283,11 @@ TLS Servers size_t reserved_io_buffer_size = 16*1024 \ ) -The first 8 arguments as well as the final argument +The first 5 arguments as well as the final argument *reserved_io_buffer_size*, are treated similiarly to the :ref:`client `. -The (optional) argument, *proto_chooser*, is a function called if the +The (optional) argument, *next_proto*, is a function called if the client sent the ALPN extension to negotiate an application protocol. In that case, the function should choose a protocol to use and return it. Alternately it can throw an exception to abort the @@ -312,7 +297,7 @@ should be of type `NO_APPLICATION_PROTOCOL`. The optional argument *is_datagram* specifies if this is a TLS or DTLS server; unlike clients, which know what type of protocol (TLS vs DTLS) they are negotiating from the start via the *offer_version*, servers -would not until they actually received a hello without this parameter. +would not until they actually received a client hello. Code for a TLS server using asio is in `src/cli/tls_proxy.cpp`. @@ -516,7 +501,7 @@ policy settings from a file. Values without an explicit mode use old-style CBC with HMAC encryption. Default value: "AES-256/GCM", "AES-128/GCM", "ChaCha20Poly1305", - "AES-256/CCM", "AES-128/CCM", "AES-256/CCM-8", "AES-128/CCM-8", + "AES-256/CCM", "AES-128/CCM", "AES-256/CCM(8)", "AES-128/CCM(8)", "AES-256", "AES-128" Also allowed: "Camellia-256/GCM", "Camellia-128/GCM", @@ -529,15 +514,18 @@ policy settings from a file. .. note:: - The current ChaCha20Poly1305 ciphersuites are non-standard but - as of 2015 were implemented and deployed by Google and - elsewhere. Support will be changed to using IETF standard - ChaCha20Poly1305 ciphersuites when those are defined. + Before 1.11.30 only the non-standard ChaCha20Poly1305 ciphersuite + was implemented. The RFC 7905 ciphersuites are supported in 1.11.30 + onwards. .. note:: Support for the broken RC4 cipher was removed in 1.11.17 + .. note:: + + SEED and 3DES are deprecated and will be removed in a future release. + .. cpp:function:: std::vector allowed_macs() const Returns the list of algorithms we are willing to use for @@ -577,6 +565,10 @@ policy settings from a file. Also allowed (disabled by default): "" (meaning anonymous) + .. note:: + + DSA authentication is deprecated and will be removed in a future release. + .. cpp:function:: std::vector allowed_ecc_curves() const Return a list of ECC curves we are willing to use, in order of preference. diff --git a/src/cli/tls_client.cpp b/src/cli/tls_client.cpp index e2fc1f027..082daf4ac 100644 --- a/src/cli/tls_client.cpp +++ b/src/cli/tls_client.cpp @@ -36,7 +36,7 @@ namespace Botan_CLI { -class TLS_Client final : public Command +class TLS_Client final : public Command, public Botan::TLS::Callbacks { public: TLS_Client() : Command("tls_client host --port=443 --print-certs --policy= " @@ -99,15 +99,10 @@ class TLS_Client final : public Command const std::vector protocols_to_offer = Botan::split_on("next-protocols", ','); - int sockfd = connect_to_host(host, port, use_tcp); + m_sockfd = connect_to_host(host, port, use_tcp); using namespace std::placeholders; - auto socket_write = - use_tcp ? - std::bind(stream_socket_write, sockfd, _1, _2) : - std::bind(dgram_socket_write, sockfd, _1, _2); - auto version = policy->latest_supported_version(!use_tcp); if(flag_set("tls1.0")) @@ -119,11 +114,7 @@ class TLS_Client final : public Command version = Botan::TLS::Protocol_Version::TLS_V11; } - Botan::TLS::Client client(Botan::TLS::Callbacks( - socket_write, - std::bind(&TLS_Client::process_data, this, _1, _2), - std::bind(&TLS_Client::alert_received, this, _1), - std::bind(&TLS_Client::handshake_complete, this, _1)), + Botan::TLS::Client client(*this, *session_mgr, creds, *policy, @@ -138,7 +129,7 @@ class TLS_Client final : public Command { fd_set readfds; FD_ZERO(&readfds); - FD_SET(sockfd, &readfds); + FD_SET(m_sockfd, &readfds); if(client.is_active()) { @@ -154,13 +145,13 @@ class TLS_Client final : public Command struct timeval timeout = { 1, 0 }; - ::select(sockfd + 1, &readfds, nullptr, nullptr, &timeout); + ::select(m_sockfd + 1, &readfds, nullptr, nullptr, &timeout); - if(FD_ISSET(sockfd, &readfds)) + if(FD_ISSET(m_sockfd, &readfds)) { uint8_t buf[4*1024] = { 0 }; - ssize_t got = ::read(sockfd, buf, sizeof(buf)); + ssize_t got = ::read(m_sockfd, buf, sizeof(buf)); if(got == 0) { @@ -218,7 +209,7 @@ class TLS_Client final : public Command } } - ::close(sockfd); + ::close(m_sockfd); } private: @@ -258,7 +249,7 @@ class TLS_Client final : public Command return fd; } - bool handshake_complete(const Botan::TLS::Session& session) + bool tls_session_established(const Botan::TLS::Session& session) override { output() << "Handshake complete, " << session.version().to_string() << " using " << session.ciphersuite().to_string() << "\n"; @@ -292,13 +283,13 @@ class TLS_Client final : public Command throw CLI_Error("Socket write failed errno=" + std::to_string(errno)); } - static void stream_socket_write(int sockfd, const uint8_t buf[], size_t length) + void tls_emit_data(const uint8_t buf[], size_t length) override { size_t offset = 0; while(length) { - ssize_t sent = ::send(sockfd, (const char*)buf + offset, + ssize_t sent = ::send(m_sockfd, (const char*)buf + offset, length, MSG_NOSIGNAL); if(sent == -1) @@ -314,16 +305,19 @@ class TLS_Client final : public Command } } - void alert_received(Botan::TLS::Alert alert) + void tls_alert(Botan::TLS::Alert alert) { output() << "Alert: " << alert.type_string() << "\n"; } - void process_data(const uint8_t buf[], size_t buf_size) + void tls_record_received(uint64_t seq_no, const uint8_t buf[], size_t buf_size) { for(size_t i = 0; i != buf_size; ++i) output() << buf[i]; } + + private: + int m_sockfd; }; BOTAN_REGISTER_COMMAND("tls_client", TLS_Client); diff --git a/src/cli/tls_proxy.cpp b/src/cli/tls_proxy.cpp index d52a67631..5140654de 100644 --- a/src/cli/tls_proxy.cpp +++ b/src/cli/tls_proxy.cpp @@ -60,7 +60,7 @@ void log_text_message(const char* where, const uint8_t buf[], size_t buf_len) //std::cout << where << ' ' << std::string(c, c + buf_len) << std::endl; } -class tls_proxy_session : public boost::enable_shared_from_this +class tls_proxy_session : public boost::enable_shared_from_this, public Botan::TLS::Callbacks { public: enum { readbuf_size = 4 * 1024 }; @@ -112,10 +112,7 @@ class tls_proxy_session : public boost::enable_shared_from_this 0) m_p2c_pending.insert(m_p2c_pending.end(), buf, buf + buf_len); @@ -269,7 +266,7 @@ class tls_proxy_session : public boost::enable_shared_from_this diff --git a/src/lib/tls/tls_blocking.cpp b/src/lib/tls/tls_blocking.cpp index 3910d242c..34ebc6c91 100644 --- a/src/lib/tls/tls_blocking.cpp +++ b/src/lib/tls/tls_blocking.cpp @@ -24,12 +24,13 @@ Blocking_Client::Blocking_Client(read_fn reader, const Protocol_Version& offer_version, const std::vector& next) : m_read(reader), - m_channel(TLS::Callbacks( + m_callbacks(new TLS::Compat_Callbacks( writer, std::bind(&Blocking_Client::data_cb, this, _1, _2), - std::bind(&Blocking_Client::alert_cb, this, _1), + std::function(std::bind(&Blocking_Client::alert_cb, this, _1)), std::bind(&Blocking_Client::handshake_cb, this, _1) - ), + )), + m_channel(*m_callbacks.get(), session_manager, creds, policy, @@ -38,6 +39,7 @@ Blocking_Client::Blocking_Client(read_fn reader, offer_version, next) { + printf("hi\n"); } bool Blocking_Client::handshake_cb(const Session& session) diff --git a/src/lib/tls/tls_blocking.h b/src/lib/tls/tls_blocking.h index cba44b524..0f2986710 100644 --- a/src/lib/tls/tls_blocking.h +++ b/src/lib/tls/tls_blocking.h @@ -33,6 +33,7 @@ class BOTAN_DLL Blocking_Client typedef std::function read_fn; typedef std::function write_fn; + BOTAN_DEPRECATED("Use the regular TLS::Client interface") Blocking_Client(read_fn reader, write_fn writer, Session_Manager& session_manager, @@ -93,6 +94,7 @@ class BOTAN_DLL Blocking_Client void alert_cb(const Alert& alert); read_fn m_read; + std::unique_ptr m_callbacks; TLS::Client m_channel; secure_vector m_plaintext; }; diff --git a/src/lib/tls/tls_callbacks.h b/src/lib/tls/tls_callbacks.h index 216c58ce2..db1b70693 100644 --- a/src/lib/tls/tls_callbacks.h +++ b/src/lib/tls/tls_callbacks.h @@ -1,6 +1,7 @@ /* * TLS Callbacks * (C) 2016 Matthias Gierlings +* 2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -14,33 +15,76 @@ namespace Botan { namespace TLS { -class Handshake_State; class Handshake_Message; /** -* Virtual Interface for TLS-Channel related callback handling. The default -* implementations involving std::function are only provided for compatibility -* purposes. New implementations should override the virtual member methods -* out_fn(), app_data(), alert(), handshake() and handshake_msg() instead. -* +* Encapsulates the callbacks that a TLS channel will make which are due to +* channel specific operations. */ class BOTAN_DLL Callbacks + { + public: + virtual ~Callbacks() {} + + /** + * Mandatory callback: output function + * The channel will call this with data which needs to be sent to the peer + * (eg, over a socket or some other form of IPC). The array will be overwritten + * when the function returns so a copy must be made if the data cannot be + * sent immediately. + */ + virtual void tls_emit_data(const uint8_t data[], size_t size) = 0; + + /** + * Mandatory callback: process application data + * Called when application data record is received from the peer. + * Again the array is overwritten immediately after the function returns. + * seq_no is the underlying TLS/DTLS record sequence number. + */ + virtual void tls_record_received(u64bit seq_no, const uint8_t data[], size_t size) = 0; + + /** + * Mandary callback: alert received + * Called when an alert is received from the peer + * If fatal, the connection is closing. If not fatal, the connection may + * still be closing (depending on the error and the peer). + */ + virtual void tls_alert(Alert alert) = 0; + + /** + * Mandatory callback: session established + * Called when a session is established. Throw an exception to abort + * the connection. Return false to prevent the session from being cached. + * Return true to cache the session in the configured session manager. + */ + virtual bool tls_session_established(const Session& session) = 0; + + /** + * Optional callback: inspect handshake message + */ + virtual void tls_inspect_handshake_msg(const Handshake_Message&) {} + + /** + * Optional callback: debug logging. (not currently used) + */ + virtual bool tls_log_debug(const char*) { return false; } + }; + +/** +* TLS::Callbacks using std::function for compatability with the old API signatures. +* This type is only provided for backward compatibility. +* New implementations should derive from TLS::Callbacks instead. +*/ +class BOTAN_DLL Compat_Callbacks final : public Callbacks { public: typedef std::function output_fn; typedef std::function data_cb; - typedef std::function alert_cb; + typedef std::function alert_cb; typedef std::function handshake_cb; typedef std::function handshake_msg_cb; /** - * DEPRECATED: This constructor is only provided for backward - * compatibility. New implementations should override the - * virtual member methods out_fn(), app_data(), alert(), - * handshake() and handshake_msg() and use the default constructor - * Callbacks(). - * - * Encapsulates a set of callback functions required by a TLS Channel. * @param output_fn is called with data for the outbound socket * * @param app_data_cb is called when new application data is received @@ -49,48 +93,50 @@ class BOTAN_DLL Callbacks * * @param handshake_cb is called when a handshake is completed */ - BOTAN_DEPRECATED("Use TLS::Callbacks() (virtual interface).") - Callbacks(output_fn out, data_cb app_data_cb, alert_cb alert_cb, - handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr) + BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).") + Compat_Callbacks(output_fn out, data_cb app_data_cb, alert_cb alert_cb, + handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr) : m_output_function(out), m_app_data_cb(app_data_cb), - m_alert_cb(alert_cb), m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb) {} + m_alert_cb(std::bind(alert_cb, std::placeholders::_1, nullptr, 0)), + m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb) {} - Callbacks() - : m_output_function(nullptr), m_app_data_cb(nullptr), - m_alert_cb(nullptr), m_hs_cb(nullptr), m_hs_msg_cb(nullptr) {} - - - virtual ~Callbacks() {} + BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).") + Compat_Callbacks(output_fn out, data_cb app_data_cb, + std::function alert_cb, + handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr) + : m_output_function(out), m_app_data_cb(app_data_cb), + m_alert_cb(alert_cb), + m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb) {} - virtual void out_fn(const byte data[], size_t size) const + void tls_emit_data(const byte data[], size_t size) override { BOTAN_ASSERT(m_output_function != nullptr, "Invalid TLS output function callback."); m_output_function(data, size); } - virtual void app_data(const byte data[], size_t size) const + void tls_record_received(u64bit /*seq_no*/, const byte data[], size_t size) override { BOTAN_ASSERT(m_app_data_cb != nullptr, "Invalid TLS app data callback."); m_app_data_cb(data, size); } - virtual void alert(Alert alert) const + void tls_alert(Alert alert) override { BOTAN_ASSERT(m_alert_cb != nullptr, "Invalid TLS alert callback."); m_alert_cb(alert); } - virtual bool handshake(const Session& session) const + bool tls_session_established(const Session& session) override { BOTAN_ASSERT(m_hs_cb != nullptr, "Invalid TLS handshake callback."); return m_hs_cb(session); } - virtual void handshake_msg(const Handshake_Message& hmsg) const + void tls_inspect_handshake_msg(const Handshake_Message& hmsg) override { // The handshake message callback is optional so we can // not assume it has been set. @@ -100,7 +146,7 @@ class BOTAN_DLL Callbacks private: const output_fn m_output_function; const data_cb m_app_data_cb; - const alert_cb m_alert_cb; + const std::function m_alert_cb; const handshake_cb m_hs_cb; const handshake_msg_cb m_hs_msg_cb; }; diff --git a/src/lib/tls/tls_channel.cpp b/src/lib/tls/tls_channel.cpp index b78796536..5f882af64 100644 --- a/src/lib/tls/tls_channel.cpp +++ b/src/lib/tls/tls_channel.cpp @@ -1,6 +1,6 @@ /* * TLS Channels -* (C) 2011,2012,2014,2015 Jack Lloyd +* (C) 2011,2012,2014,2015,2016 Jack Lloyd * 2016 Matthias Gierlings * * Botan is released under the Simplified BSD License (see license.txt) @@ -21,7 +21,7 @@ namespace TLS { size_t TLS::Channel::IO_BUF_DEFAULT_SIZE = 10*1024; -Channel::Channel(const Callbacks& callbacks, +Channel::Channel(Callbacks& callbacks, Session_Manager& session_manager, RandomNumberGenerator& rng, const Policy& policy, @@ -47,7 +47,8 @@ Channel::Channel(output_fn out, bool is_datagram, size_t io_buf_sz) : m_is_datagram(is_datagram), - m_callbacks(Callbacks(out, app_data_cb, alert_cb, hs_cb, hs_msg_cb)), + m_compat_callbacks(new Compat_Callbacks(out, app_data_cb, alert_cb, hs_cb, hs_msg_cb)), + m_callbacks(*m_compat_callbacks.get()), m_session_manager(session_manager), m_policy(policy), m_rng(rng) @@ -319,15 +320,15 @@ size_t Channel::received_data(const byte input[], size_t input_size) if(record_type == HANDSHAKE || record_type == CHANGE_CIPHER_SPEC) { - process_handshake_ccs(record_data, record_sequence, record_type, record_version); + process_handshake_ccs(record_data, record_sequence, record_type, record_version); } else if(record_type == APPLICATION_DATA) { - process_application_data(record_data); + process_application_data(record_sequence, record_data); } else if(record_type == ALERT) { - process_alert(record_data); + process_alert(record_data); } else if(record_type != NO_RECORD) throw Unexpected_Message("Unexpected record type " + @@ -359,10 +360,10 @@ size_t Channel::received_data(const byte input[], size_t input_size) } } -void Channel::process_handshake_ccs(secure_vector& record, - u64bit& record_sequence, - Record_Type& record_type, - Protocol_Version& record_version) +void Channel::process_handshake_ccs(const secure_vector& record, + u64bit record_sequence, + Record_Type record_type, + Protocol_Version record_version) { if(!m_pending_state) { @@ -422,7 +423,7 @@ void Channel::process_handshake_ccs(secure_vector& record, } } -void Channel::process_application_data(secure_vector& record) +void Channel::process_application_data(u64bit seq_no, const secure_vector& record) { if(!active_state()) throw Unexpected_Message("Application data before handshake done"); @@ -433,17 +434,17 @@ void Channel::process_application_data(secure_vector& record) * following record. Avoid spurious callbacks. */ if(record.size() > 0) - m_callbacks.app_data(record.data(), record.size()); + callbacks().tls_record_received(seq_no, record.data(), record.size()); } -void Channel::process_alert(secure_vector& record) +void Channel::process_alert(const secure_vector& record) { Alert alert_msg(record); if(alert_msg.type() == Alert::NO_RENEGOTIATION) m_pending_state.reset(); - m_callbacks.alert(alert_msg); + callbacks().tls_alert(alert_msg); if(alert_msg.is_fatal()) { @@ -478,7 +479,7 @@ void Channel::write_record(Connection_Cipher_State* cipher_state, u16bit epoch, cipher_state, m_rng); - m_callbacks.out_fn(m_writebuf.data(), m_writebuf.size()); + callbacks().tls_emit_data(m_writebuf.data(), m_writebuf.size()); } void Channel::send_record_array(u16bit epoch, byte type, const byte input[], size_t length) diff --git a/src/lib/tls/tls_channel.h b/src/lib/tls/tls_channel.h index 7c59e1d6f..073af760f 100644 --- a/src/lib/tls/tls_channel.h +++ b/src/lib/tls/tls_channel.h @@ -36,12 +36,12 @@ class BOTAN_DLL Channel public: typedef std::function output_fn; typedef std::function data_cb; - typedef std::function alert_cb; + typedef std::function alert_cb; typedef std::function handshake_cb; typedef std::function handshake_msg_cb; static size_t IO_BUF_DEFAULT_SIZE; - Channel(const Callbacks& callbacks, + Channel(Callbacks& callbacks, Session_Manager& session_manager, RandomNumberGenerator& rng, const Policy& policy, @@ -215,9 +215,9 @@ class BOTAN_DLL Channel const Policy& policy() const { return m_policy; } - bool save_session(const Session& session) const { return m_callbacks.handshake(session); } + bool save_session(const Session& session) const { return callbacks().tls_session_established(session); } - Callbacks get_callbacks() const { return m_callbacks; } + Callbacks& callbacks() const { return m_callbacks; } private: void init(size_t io_buf_sze); @@ -245,19 +245,20 @@ class BOTAN_DLL Channel const Handshake_State* pending_state() const { return m_pending_state.get(); } /* methods to handle incoming traffic through Channel::receive_data. */ - void process_handshake_ccs(secure_vector& record, - u64bit& record_sequence, - Record_Type& record_type, - Protocol_Version& record_version); + void process_handshake_ccs(const secure_vector& record, + u64bit record_sequence, + Record_Type record_type, + Protocol_Version record_version); - void process_application_data(secure_vector& record); + void process_application_data(u64bit req_no, const secure_vector& record); - void process_alert(secure_vector& record); + void process_alert(const secure_vector& record); bool m_is_datagram; /* callbacks */ - Callbacks m_callbacks; + std::unique_ptr m_compat_callbacks; + Callbacks& m_callbacks; /* external state */ Session_Manager& m_session_manager; diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp index ab7beddbd..f77521c03 100644 --- a/src/lib/tls/tls_client.cpp +++ b/src/lib/tls/tls_client.cpp @@ -24,7 +24,7 @@ class Client_Handshake_State : public Handshake_State public: // using Handshake_State::Handshake_State; - Client_Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : Handshake_State(io, cb) {} + Client_Handshake_State(Handshake_IO* io, Callbacks& cb) : Handshake_State(io, cb) {} const Public_Key& get_server_public_Key() const { @@ -43,7 +43,7 @@ class Client_Handshake_State : public Handshake_State /* * TLS Client Constructor */ -Client::Client(const Callbacks& callbacks, +Client::Client(Callbacks& callbacks, Session_Manager& session_manager, Credentials_Manager& creds, const Policy& policy, @@ -112,10 +112,7 @@ void Client::init(const Protocol_Version& protocol_version, Handshake_State* Client::new_handshake_state(Handshake_IO* io) { - return new Client_Handshake_State(io, - std::bind(&TLS::Callbacks::handshake_msg, - get_callbacks(), - std::placeholders::_1)); + return new Client_Handshake_State(io, callbacks()); } std::vector diff --git a/src/lib/tls/tls_client.h b/src/lib/tls/tls_client.h index 6452294cd..09af053af 100644 --- a/src/lib/tls/tls_client.h +++ b/src/lib/tls/tls_client.h @@ -23,6 +23,7 @@ namespace TLS { class BOTAN_DLL Client final : public Channel { public: + /** * Set up a new TLS client session * @@ -48,7 +49,51 @@ class BOTAN_DLL Client final : public Channel * be preallocated for the read and write buffers. Smaller * values just mean reallocations and copies are more likely. */ + Client(Callbacks& callbacks, + Session_Manager& session_manager, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng, + const Server_Information& server_info = Server_Information(), + const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(), + const std::vector& next_protocols = {}, + size_t reserved_io_buffer_size = TLS::Client::IO_BUF_DEFAULT_SIZE + ); + /** + * DEPRECATED. This constructor is only provided for backward + * compatibility and should not be used in new code. + * + * Set up a new TLS client session + * + * @param output_fn is called with data for the outbound socket + * + * @param app_data_cb is called when new application data is received + * + * @param alert_cb is called when a TLS alert is received + * + * @param handshake_cb is called when a handshake is completed + * + * @param session_manager manages session state + * + * @param creds manages application/user credentials + * + * @param policy specifies other connection policy information + * + * @param rng a random number generator + * + * @param server_info is identifying information about the TLS server + * + * @param offer_version specifies which version we will offer + * to the TLS server. + * + * @param next_protocols specifies protocols to advertise with ALPN + * + * @param reserved_io_buffer_size This many bytes of memory will + * be preallocated for the read and write buffers. Smaller + * values just mean reallocations and copies are more likely. + */ + BOTAN_DEPRECATED("Use TLS::Client(TLS::Callbacks ...)") Client(output_fn out, data_cb app_data_cb, alert_cb alert_cb, @@ -82,18 +127,6 @@ class BOTAN_DLL Client final : public Channel const std::vector& next_protocols = {} ); - - Client(const Callbacks& callbacks, - Session_Manager& session_manager, - Credentials_Manager& creds, - const Policy& policy, - RandomNumberGenerator& rng, - const Server_Information& server_info = Server_Information(), - const Protocol_Version& offer_version = Protocol_Version::latest_tls_version(), - const std::vector& next_protocols = {}, - size_t reserved_io_buffer_size = TLS::Client::IO_BUF_DEFAULT_SIZE - ); - const std::string& application_protocol() const { return m_application_protocol; } private: void init(const Protocol_Version& protocol_version, diff --git a/src/lib/tls/tls_handshake_state.cpp b/src/lib/tls/tls_handshake_state.cpp index afc32ba87..71cacdabd 100644 --- a/src/lib/tls/tls_handshake_state.cpp +++ b/src/lib/tls/tls_handshake_state.cpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace Botan { @@ -174,8 +175,8 @@ std::string handshake_mask_to_string(u32bit mask) /* * Initialize the SSL/TLS Handshake State */ -Handshake_State::Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : - m_msg_callback(cb), +Handshake_State::Handshake_State(Handshake_IO* io, Callbacks& cb) : + m_callbacks(cb), m_handshake_io(io), m_version(m_handshake_io->initial_record_version()) { @@ -183,6 +184,11 @@ Handshake_State::Handshake_State(Handshake_IO* io, handshake_msg_cb cb) : Handshake_State::~Handshake_State() {} +void Handshake_State::note_message(const Handshake_Message& msg) + { + m_callbacks.tls_inspect_handshake_msg(msg); + } + void Handshake_State::hello_verify_request(const Hello_Verify_Request& hello_verify) { note_message(hello_verify); diff --git a/src/lib/tls/tls_handshake_state.h b/src/lib/tls/tls_handshake_state.h index 2943a8637..bdec10d14 100644 --- a/src/lib/tls/tls_handshake_state.h +++ b/src/lib/tls/tls_handshake_state.h @@ -24,6 +24,7 @@ class KDF; namespace TLS { +class Callbacks; class Policy; class Hello_Verify_Request; @@ -45,9 +46,7 @@ class Finished; class Handshake_State { public: - typedef std::function handshake_msg_cb; - - Handshake_State(Handshake_IO* io, handshake_msg_cb cb); + Handshake_State(Handshake_IO* io, Callbacks& callbacks); virtual ~Handshake_State(); @@ -164,15 +163,10 @@ class Handshake_State const Handshake_Hash& hash() const { return m_handshake_hash; } - void note_message(const Handshake_Message& msg) - { - if(m_msg_callback) - m_msg_callback(msg); - } - + void note_message(const Handshake_Message& msg); private: - handshake_msg_cb m_msg_callback; + Callbacks& m_callbacks; std::unique_ptr m_handshake_io; diff --git a/src/lib/tls/tls_record.h b/src/lib/tls/tls_record.h index 53e447af6..c16b919b5 100644 --- a/src/lib/tls/tls_record.h +++ b/src/lib/tls/tls_record.h @@ -102,10 +102,6 @@ class Record m_type(type), m_size(data.size()) {}; secure_vector& get_data() { return m_data; } - void set_data(secure_vector data) - { - m_data.swap(data); - } Protocol_Version* get_protocol_version() { return m_protocol_version; } diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp index 96af3cc90..5eccec2a7 100644 --- a/src/lib/tls/tls_server.cpp +++ b/src/lib/tls/tls_server.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -17,9 +16,34 @@ namespace Botan { namespace TLS { -namespace { +class Server_Handshake_State : public Handshake_State + { + public: + Server_Handshake_State(Handshake_IO* io, Callbacks& cb) + : Handshake_State(io, cb) {} + + Private_Key* server_rsa_kex_key() { return m_server_rsa_kex_key; } + void set_server_rsa_kex_key(Private_Key* key) + { m_server_rsa_kex_key = key; } + + bool allow_session_resumption() const + { return m_allow_session_resumption; } + void set_allow_session_resumption(bool allow_session_resumption) + { m_allow_session_resumption = allow_session_resumption; } + + private: + // Used by the server only, in case of RSA key exchange. Not owned + Private_Key* m_server_rsa_kex_key = nullptr; + /* + * Used by the server to know if resumption should be allowed on + * a server-initiated renegotiation + */ + bool m_allow_session_resumption = true; + }; + +namespace { bool check_for_resume(Session& session_info, Session_Manager& session_manager, @@ -213,7 +237,7 @@ get_server_certs(const std::string& hostname, /* * TLS Server Constructor */ -Server::Server(const Callbacks& callbacks, +Server::Server(Callbacks& callbacks, Session_Manager& session_manager, Credentials_Manager& creds, const Policy& policy, @@ -268,11 +292,7 @@ Server::Server(output_fn output, Handshake_State* Server::new_handshake_state(Handshake_IO* io) { - std::unique_ptr state( - new Server_Handshake_State(io, - std::bind(&TLS::Callbacks::handshake_msg, - get_callbacks(), - std::placeholders::_1))); + std::unique_ptr state(new Server_Handshake_State(io, callbacks())); state->set_expected_next(CLIENT_HELLO); return state.release(); diff --git a/src/lib/tls/tls_server.h b/src/lib/tls/tls_server.h index c0960a66e..508dde440 100644 --- a/src/lib/tls/tls_server.h +++ b/src/lib/tls/tls_server.h @@ -30,8 +30,29 @@ class BOTAN_DLL Server final : public Channel /** * Server initialization + * + * @param callbacks contains a set of callback function references + * required by the TLS client. + * + * @param session_manager manages session state + * + * @param creds manages application/user credentials + * + * @param policy specifies other connection policy information + * + * @param rng a random number generator + * + * @param next_proto is called with client's ALPN protocol list + * and returns chosen protocol. + * + * @param is_datagram set to true if this server should expect DTLS + * connections. Otherwise TLS connections are expected. + * + * @param reserved_io_buffer_size This many bytes of memory will + * be preallocated for the read and write buffers. Smaller + * values just mean reallocations and copies are more likely. */ - Server(const Callbacks& callbacks, + Server(Callbacks& callbacks, Session_Manager& session_manager, Credentials_Manager& creds, const Policy& policy, diff --git a/src/lib/tls/tls_server_handshake_state.h b/src/lib/tls/tls_server_handshake_state.h deleted file mode 100644 index c65cade96..000000000 --- a/src/lib/tls/tls_server_handshake_state.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -* TLS Server -* (C) 2004-2011,2012,2016 Jack Lloyd -* 2016 Matthias Gierlings -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_TLS_SERVER_HANDSHAKE_STATE_H__ -#define BOTAN_TLS_SERVER_HANDSHAKE_STATE_H__ - -#include -namespace Botan { - -namespace TLS { - -class Server_Handshake_State : public Handshake_State - { - public: - Server_Handshake_State(Handshake_IO* io, handshake_msg_cb cb) - : Handshake_State(io, cb) {} - - Private_Key* server_rsa_kex_key() { return m_server_rsa_kex_key; } - void set_server_rsa_kex_key(Private_Key* key) - { m_server_rsa_kex_key = key; } - - bool allow_session_resumption() const - { return m_allow_session_resumption; } - void set_allow_session_resumption(bool allow_session_resumption) - { m_allow_session_resumption = allow_session_resumption; } - - - private: - // Used by the server only, in case of RSA key exchange. Not owned - Private_Key* m_server_rsa_kex_key = nullptr; - - /* - * Used by the server to know if resumption should be allowed on - * a server-initiated renegotiation - */ - bool m_allow_session_resumption = true; - }; - -} - -} - -#endif diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp index 150ed2794..2797e7d21 100644 --- a/src/tests/unit_tls.cpp +++ b/src/tests/unit_tls.cpp @@ -166,6 +166,10 @@ void print_alert(Botan::TLS::Alert) { } +void alert_cb_with_data(Botan::TLS::Alert, const byte[], size_t) + { + } + Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, Botan::Credentials_Manager& creds, Botan::TLS::Policy& policy) @@ -219,27 +223,31 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, { std::vector c2s_traffic, s2c_traffic, client_recv, server_recv, client_sent, server_sent; + std::unique_ptr server_cb(new Botan::TLS::Compat_Callbacks( + queue_inserter(s2c_traffic), + queue_inserter(server_recv), + std::function(alert_cb_with_data), + handshake_complete)); + // TLS::Server object constructed by new constructor using virtual callback interface. std::unique_ptr server( - new Botan::TLS::Server(Botan::TLS::Callbacks( - queue_inserter(s2c_traffic), - queue_inserter(server_recv), - print_alert, - handshake_complete), - server_sessions, - creds, - policy, - rng, - next_protocol_chooser, - false)); + new Botan::TLS::Server(*server_cb, + server_sessions, + creds, + policy, + rng, + next_protocol_chooser, + false)); + + std::unique_ptr client_cb(new Botan::TLS::Compat_Callbacks( + queue_inserter(c2s_traffic), + queue_inserter(client_recv), + std::function(alert_cb_with_data), + handshake_complete)); // TLS::Client object constructed by new constructor using virtual callback interface. std::unique_ptr client( - new Botan::TLS::Client(Botan::TLS::Callbacks( - queue_inserter(c2s_traffic), - queue_inserter(client_recv), - print_alert, - handshake_complete), + new Botan::TLS::Client(*client_cb, client_sessions, creds, policy, @@ -255,11 +263,18 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, { if(ctor_sel == 1) { + c2s_traffic.clear(); + s2c_traffic.clear(); + server_recv.clear(); + client_recv.clear(); + client_sent.clear(); + server_sent.clear(); + // TLS::Server object constructed by legacy constructor. - server = std::unique_ptr( + server.reset( new Botan::TLS::Server(queue_inserter(s2c_traffic), queue_inserter(server_recv), - print_alert, + alert_cb_with_data, handshake_complete, server_sessions, creds, @@ -269,10 +284,10 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, false)); // TLS::Client object constructed by legacy constructor. - std::unique_ptr client( + client.reset( new Botan::TLS::Client(queue_inserter(c2s_traffic), queue_inserter(client_recv), - print_alert, + alert_cb_with_data, handshake_complete, client_sessions, creds, @@ -485,13 +500,21 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, { std::vector c2s_traffic, s2c_traffic, client_recv, server_recv, client_sent, server_sent; + std::unique_ptr server_cb(new Botan::TLS::Compat_Callbacks( + queue_inserter(s2c_traffic), + queue_inserter(server_recv), + std::function(print_alert), + handshake_complete)); + + std::unique_ptr client_cb(new Botan::TLS::Compat_Callbacks( + queue_inserter(c2s_traffic), + queue_inserter(client_recv), + std::function(print_alert), + handshake_complete)); + // TLS::Server object constructed by new constructor using virtual callback interface. std::unique_ptr server( - new Botan::TLS::Server(Botan::TLS::Callbacks( - queue_inserter(s2c_traffic), - queue_inserter(server_recv), - print_alert, - handshake_complete), + new Botan::TLS::Server(*server_cb, server_sessions, creds, policy, @@ -501,11 +524,7 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, // TLS::Client object constructed by new constructor using virtual callback interface. std::unique_ptr client( - new Botan::TLS::Client(Botan::TLS::Callbacks( - queue_inserter(c2s_traffic), - queue_inserter(client_recv), - print_alert, - handshake_complete), + new Botan::TLS::Client(*client_cb, client_sessions, creds, policy, @@ -521,11 +540,17 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, { if(ctor_sel == 1) { + c2s_traffic.clear(); + s2c_traffic.clear(); + server_recv.clear(); + client_recv.clear(); + client_sent.clear(); + server_sent.clear(); // TLS::Server object constructed by legacy constructor. - server = std::unique_ptr( + server.reset( new Botan::TLS::Server(queue_inserter(s2c_traffic), queue_inserter(server_recv), - print_alert, + alert_cb_with_data, handshake_complete, server_sessions, creds, @@ -535,10 +560,10 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, true)); // TLS::Client object constructed by legacy constructor. - std::unique_ptr client( + client.reset( new Botan::TLS::Client(queue_inserter(c2s_traffic), queue_inserter(client_recv), - print_alert, + alert_cb_with_data, handshake_complete, client_sessions, creds, -- cgit v1.2.3 From dd5cda336851212e200f3b62cf9c89a6984725c3 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Tue, 16 Aug 2016 15:45:10 -0400 Subject: Add a Callbacks function for ALPN --- doc/manual/tls.rst | 44 ++++++++++++++++++++++++++++++-------------- src/lib/tls/tls_callbacks.h | 35 +++++++++++++++++++++++++++++++---- src/lib/tls/tls_server.cpp | 16 +++++++++++----- src/lib/tls/tls_server.h | 7 ++----- src/tests/unit_tls.cpp | 10 ++++++---- 5 files changed, 80 insertions(+), 32 deletions(-) (limited to 'doc') diff --git a/doc/manual/tls.rst b/doc/manual/tls.rst index 7210fc092..6c1ca42f2 100644 --- a/doc/manual/tls.rst +++ b/doc/manual/tls.rst @@ -38,17 +38,21 @@ information about the connection. .. cpp:function:: void tls_emit_data(const byte data[], size_t data_len) - The TLS stack requests that all bytes of *data* be queued up to send to the + Mandatory. The TLS stack requests that all bytes of *data* be queued up to send to the counterparty. After this function returns, the buffer containing *data* will be overwritten, so a copy of the input must be made if the callback cannot send the data immediately. - The write can be deferred but for TLS all writes must occur *in order*. - For DTLS this is not strictly required, but is still recommended. + As an example you could ``send`` to perform a blocking write on a socket, + or append the data to a queue managed by your application, and initiate + an asyncronous write. + + For TLS all writes must occur *in the order requested*. + For DTLS this ordering is not strictly required, but is still recommended. .. cpp:function:: void tls_record_received(uint64_t rec_no, const byte data[], size_t data_len) - Called once for each application_data record which is received, with the + Mandatory. Called once for each application_data record which is received, with the matching (TLS level) record sequence number. Currently empty records are ignored and do not instigate a callback, @@ -57,15 +61,21 @@ information about the connection. As with ``tls_emit_data``, the array will be overwritten sometime after the callback returns, so a copy should be made if needed. + For TLS the record number will always increase. + + For DTLS, it is possible to receive records with the `rec_no` field + field out of order or repeated. It is even possible (from a malicious or + faulty peer) to receive multiple copies of a single record with differing plaintexts. + .. cpp:function:: void tls_alert(Alert alert) - Called when an alert is received from the peer. Note that alerts + Mandatory. Called when an alert is received from the peer. Note that alerts received before the handshake is complete are not authenticated and could have been inserted by a MITM attacker. .. cpp:function:: bool tls_session_established(const TLS::Session& session) - Called whenever a negotiation completes. This can happen more + Mandatory. Called whenever a negotiation completes. This can happen more than once on any connection, if renegotiation occurs. The *session* parameter provides information about the session which was just established. @@ -76,6 +86,13 @@ information about the connection. exception which will send a close message to the counterparty and reset the connection state. + .. cpp:function:: std::string tls_server_choose_app_protocol(const std::vector& client_protos) + + Optional. Called by the server when a client includes a list of protocols in the ALPN extension. + The server then choose which protocol to use, or "" to disable sending any ALPN response. + The default implementation returns the empty string all of the time, effectively disabling + ALPN responses. + .. cpp:function:: void tls_inspect_handshake_msg(const Handshake_Message&) This callback is optional, and can be used to inspect all handshake messages @@ -90,7 +107,7 @@ Versions from 1.11.0 to 1.11.30 did not have ``TLS::Callbacks` and instead used independent std::functions to pass the various callback functions. This interface is currently still included but is deprecated and will be removed in a future release. For the documentation for this interface, please check -the docs in 1.11.30. This version of the manual only documents the new interface +the docs for 1.11.30. This version of the manual only documents the new interface added in 1.11.31. TLS Channels @@ -278,7 +295,6 @@ TLS Servers Credentials_Manager& creds, \ const Policy& policy, \ RandomNumberGenerator& rng, \ - next_protocol_fn next_proto = next_protocol_fn(), \ bool is_datagram = false, \ size_t reserved_io_buffer_size = 16*1024 \ ) @@ -287,12 +303,12 @@ The first 5 arguments as well as the final argument *reserved_io_buffer_size*, are treated similiarly to the :ref:`client `. -The (optional) argument, *next_proto*, is a function called if the -client sent the ALPN extension to negotiate an application -protocol. In that case, the function should choose a protocol to use -and return it. Alternately it can throw an exception to abort the -exchange; the ALPN specification says that if this occurs the alert -should be of type `NO_APPLICATION_PROTOCOL`. +If a client sends the ALPN extension, the ``callbacks`` function +``tls_server_choose_app_protocol`` will be called and the result +sent back to the client. If the empty string is returned, the server +will not send an ALPN response. The function can also throw an exception +to abort the handshake entirely, the ALPN specification says that if this +occurs the alert should be of type `NO_APPLICATION_PROTOCOL`. The optional argument *is_datagram* specifies if this is a TLS or DTLS server; unlike clients, which know what type of protocol (TLS vs DTLS) diff --git a/src/lib/tls/tls_callbacks.h b/src/lib/tls/tls_callbacks.h index db1b70693..5c7b21a99 100644 --- a/src/lib/tls/tls_callbacks.h +++ b/src/lib/tls/tls_callbacks.h @@ -61,9 +61,25 @@ class BOTAN_DLL Callbacks /** * Optional callback: inspect handshake message + * Throw an exception to abort the handshake. */ virtual void tls_inspect_handshake_msg(const Handshake_Message&) {} + /** + * Optional callback for server: choose ALPN protocol + * ALPN (RFC 7301) works by the client sending a list of application + * protocols it is willing to negotiate. The server then selects which + * protocol to use, which is not necessarily even on the list that + * the client sent. + * + * If the empty string is returned from this function the server will + * just ignore the client ALPN extension. + */ + virtual std::string tls_server_choose_app_protocol(const std::vector& client_protos) + { + return ""; + } + /** * Optional callback: debug logging. (not currently used) */ @@ -83,6 +99,7 @@ class BOTAN_DLL Compat_Callbacks final : public Callbacks typedef std::function alert_cb; typedef std::function handshake_cb; typedef std::function handshake_msg_cb; + typedef std::function)> next_protocol_fn; /** * @param output_fn is called with data for the outbound socket @@ -95,18 +112,21 @@ class BOTAN_DLL Compat_Callbacks final : public Callbacks */ BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).") Compat_Callbacks(output_fn out, data_cb app_data_cb, alert_cb alert_cb, - handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr) + handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr, + next_protocol_fn next_proto = nullptr) : m_output_function(out), m_app_data_cb(app_data_cb), m_alert_cb(std::bind(alert_cb, std::placeholders::_1, nullptr, 0)), - m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb) {} + m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {} BOTAN_DEPRECATED("Use TLS::Callbacks (virtual interface).") Compat_Callbacks(output_fn out, data_cb app_data_cb, std::function alert_cb, - handshake_cb hs_cb, handshake_msg_cb hs_msg_cb = nullptr) + handshake_cb hs_cb, + handshake_msg_cb hs_msg_cb = nullptr, + next_protocol_fn next_proto = nullptr) : m_output_function(out), m_app_data_cb(app_data_cb), m_alert_cb(alert_cb), - m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb) {} + m_hs_cb(hs_cb), m_hs_msg_cb(hs_msg_cb), m_next_proto(next_proto) {} void tls_emit_data(const byte data[], size_t size) override { @@ -136,6 +156,12 @@ class BOTAN_DLL Compat_Callbacks final : public Callbacks return m_hs_cb(session); } + std::string tls_server_choose_app_protocol(const std::vector& client_protos) override + { + if(m_next_proto != nullptr) { return m_next_proto(client_protos); } + return ""; + } + void tls_inspect_handshake_msg(const Handshake_Message& hmsg) override { // The handshake message callback is optional so we can @@ -149,6 +175,7 @@ class BOTAN_DLL Compat_Callbacks final : public Callbacks const std::function m_alert_cb; const handshake_cb m_hs_cb; const handshake_msg_cb m_hs_msg_cb; + const next_protocol_fn m_next_proto; }; } diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp index 5eccec2a7..2e546eab1 100644 --- a/src/lib/tls/tls_server.cpp +++ b/src/lib/tls/tls_server.cpp @@ -242,13 +242,11 @@ Server::Server(Callbacks& callbacks, Credentials_Manager& creds, const Policy& policy, RandomNumberGenerator& rng, - next_protocol_fn next_proto, bool is_datagram, size_t io_buf_sz) : Channel(callbacks, session_manager, rng, policy, is_datagram, io_buf_sz), - m_creds(creds), - m_choose_next_protocol(next_proto) + m_creds(creds) { } @@ -419,8 +417,16 @@ void Server::process_client_hello_msg(const Handshake_State* active_state, catch(...) {} m_next_protocol = ""; - if(m_choose_next_protocol && pending_state.client_hello()->supports_alpn()) - m_next_protocol = m_choose_next_protocol(pending_state.client_hello()->next_protocols()); + if(pending_state.client_hello()->supports_alpn()) + { + m_next_protocol = callbacks().tls_server_choose_app_protocol(pending_state.client_hello()->next_protocols()); + + // if the callback return was empty, fall back to the (deprecated) std::function + if(m_next_protocol.empty() && m_choose_next_protocol) + { + m_next_protocol = m_choose_next_protocol(pending_state.client_hello()->next_protocols()); + } + } if(resuming) { diff --git a/src/lib/tls/tls_server.h b/src/lib/tls/tls_server.h index 508dde440..051eda445 100644 --- a/src/lib/tls/tls_server.h +++ b/src/lib/tls/tls_server.h @@ -42,9 +42,6 @@ class BOTAN_DLL Server final : public Channel * * @param rng a random number generator * - * @param next_proto is called with client's ALPN protocol list - * and returns chosen protocol. - * * @param is_datagram set to true if this server should expect DTLS * connections. Otherwise TLS connections are expected. * @@ -57,7 +54,6 @@ class BOTAN_DLL Server final : public Channel Credentials_Manager& creds, const Policy& policy, RandomNumberGenerator& rng, - next_protocol_fn next_proto = next_protocol_fn(), bool is_datagram = false, size_t reserved_io_buffer_size = TLS::Server::IO_BUF_DEFAULT_SIZE ); @@ -148,9 +144,10 @@ class BOTAN_DLL Server final : public Channel Handshake_State* new_handshake_state(Handshake_IO* io) override; Credentials_Manager& m_creds; + std::string m_next_protocol; + // Set by deprecated constructor, Server calls both this fn and Callbacks version next_protocol_fn m_choose_next_protocol; - std::string m_next_protocol; }; } diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp index 2797e7d21..f0caa4aef 100644 --- a/src/tests/unit_tls.cpp +++ b/src/tests/unit_tls.cpp @@ -227,7 +227,9 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, queue_inserter(s2c_traffic), queue_inserter(server_recv), std::function(alert_cb_with_data), - handshake_complete)); + handshake_complete, + nullptr, + next_protocol_chooser)); // TLS::Server object constructed by new constructor using virtual callback interface. std::unique_ptr server( @@ -236,7 +238,6 @@ Test::Result test_tls_handshake(Botan::TLS::Protocol_Version offer_version, creds, policy, rng, - next_protocol_chooser, false)); std::unique_ptr client_cb(new Botan::TLS::Compat_Callbacks( @@ -504,7 +505,9 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, queue_inserter(s2c_traffic), queue_inserter(server_recv), std::function(print_alert), - handshake_complete)); + handshake_complete, + nullptr, + next_protocol_chooser)); std::unique_ptr client_cb(new Botan::TLS::Compat_Callbacks( queue_inserter(c2s_traffic), @@ -519,7 +522,6 @@ Test::Result test_dtls_handshake(Botan::TLS::Protocol_Version offer_version, creds, policy, rng, - next_protocol_chooser, true)); // TLS::Client object constructed by new constructor using virtual callback interface. -- cgit v1.2.3 From bf990c7fc77990cf8e43b8f1bd769cd23bfbbcf7 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Wed, 17 Aug 2016 11:24:03 -0400 Subject: Deprecations [ci skip] --- doc/deprecated.txt | 28 ++++++++++++++++++++++++++++ doc/news.rst | 7 +++++++ 2 files changed, 35 insertions(+) create mode 100644 doc/deprecated.txt (limited to 'doc') diff --git a/doc/deprecated.txt b/doc/deprecated.txt new file mode 100644 index 000000000..bb7bb28ef --- /dev/null +++ b/doc/deprecated.txt @@ -0,0 +1,28 @@ +Currently deprecated: + +- Rabin-Williams signatures + +- Nyberg-Rueppel signatures + +- MARS, RC2, RC5, RC6, SAFER, TEA + +- MD2, HAS-160, RIPEMD-128 + +- TLS 3DES and SEED ciphersuites in TLS + +- DSA auth in TLS (not ECDSA) + +- Old (Google specific) ChaCha20 TLS ciphersuites + +- All built in ECC groups < 256 bits + +- All built in MODP groups < 2048 bits + +- All pre-created DSA groups + +- All support for BeOS/Haiku including BeOS entropy source + +- EGD entropy source + +- Unix process exec entropy source + diff --git a/doc/news.rst b/doc/news.rst index 67f458fec..0c9018be0 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -27,6 +27,13 @@ Version 1.11.31, Not Yet Released system requires EGD and so the code is now dead weight. If you rely on EGD support, you should contact the developers by email or GitHub ASAP. +* The TLS ciphersuites using 3DES and SEED are deprecated and will be removed in + a future release. + +* Support for BeOS/Haiku has not been tested in 5 years and is in an unknown state. + Unless reports are received of successful builds and use on this platform, support + for BeOS/Haiku will be removed in a future release. + * Changes in DLIES: Previously the input to the KDF was the concatenation of the (ephemeral) public key and the secret value derived by the key agreement operation. Now the input is only the secret value obtained -- cgit v1.2.3 From bcc4d24bb25bd1cb1ee53e1f6dadbafd21c126d5 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Sat, 20 Aug 2016 18:39:38 -0400 Subject: Doc/relnote updates [ci skip] --- doc/contributing.rst | 1 - doc/deprecated.txt | 5 ++-- doc/news.rst | 72 +++++++++++++++++++++++++++++++++------------------- doc/todo.rst | 8 ++++++ 4 files changed, 57 insertions(+), 29 deletions(-) (limited to 'doc') diff --git a/doc/contributing.rst b/doc/contributing.rst index a0b8daec1..0d160c680 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -38,7 +38,6 @@ Library Layout * ``entropy`` has various entropy sources * ``asn1`` is the DER encoder/decoder * ``cert/x509`` is X.509 certificates, PKCS #10 requests, OCSP -* ``cert/cvc`` is Card Verifiable Certificates (ePassport credentials) * ``tls`` contains the TLS implementation * ``filters`` is a filter/pipe API for data transforms * ``compression`` has the compression wrappers (zlib, bzip2, lzma) diff --git a/doc/deprecated.txt b/doc/deprecated.txt index bb7bb28ef..456a7e6b7 100644 --- a/doc/deprecated.txt +++ b/doc/deprecated.txt @@ -6,9 +6,11 @@ Currently deprecated: - MARS, RC2, RC5, RC6, SAFER, TEA +- ECB Cipher_Mode + - MD2, HAS-160, RIPEMD-128 -- TLS 3DES and SEED ciphersuites in TLS +- 3DES and SEED ciphersuites in TLS - DSA auth in TLS (not ECDSA) @@ -25,4 +27,3 @@ Currently deprecated: - EGD entropy source - Unix process exec entropy source - diff --git a/doc/news.rst b/doc/news.rst index 0c9018be0..6e9b88479 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -4,48 +4,68 @@ Release Notes Version 1.11.31, Not Yet Released ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* Add PKCS #11 support (GH #507) - -* Add ECIES encryption system (GH #483) +* Fix undefined behavior in Curve25519 on platforms without a native 128-bit + integer type. This was known to produce incorrect results on 32-bit ARM + under Clang. GH #532 (CVE-2016-6878) + +* If X509_Certificate::allowed_usage was called with more than one Key_Usage + set in the enum value, the function would return true if *any* of the allowed + usages were set, instead of if *all* of the allowed usages are set. + GH #591 (CVE-2016-6879) + +* Incompatible changes in DLIES: Previously the input to the KDF was + the concatenation of the (ephemeral) public key and the secret value + derived by the key agreement operation. Now the input is only the + secret value obtained by the key agreement operation. That's how it + is specified in the original paper "DHIES: An encryption scheme + based on Diffie-Hellman Problem" or in BSI technical guideline + TR-02102-1 for example. In addition to the already present + XOR-encrypion/decryption mode it's now possible to use DLIES with a + block cipher. Furthermore the order of the output was changed from + {public key, tag, ciphertext} to {public key, ciphertext, tag}. Both + modes are compatible with bouncycastle. + +* Add initial PKCS #11 support (GH #507). Currently includes a low level + wrapper to all of PKCS #11 (p11.h) and high level code for RSA and ECDSA + signatures and hardware RNG access. * Add ECKCDSA signature algorithm (#504) * Add KDF1 from ISO 18033 (GH #483) +* Add FRP256v1 curve (GH #551) + * RNG changes: NIST SP900-80's HMAC_DRBG is now the default generator for userspace RNG (AutoSeeded_RNG). HMAC_DRBG now attempts to detect use of fork (via pid checks) -* Fix undefined behavior in Curve25519 on platforms without a native 128-bit - integer type. This was known to produce incorrect results on 32-bit ARM - under Clang. GH #532 +* The X9.31 and HMAC_RNG RNGs are deprecated and will be removed in a + future release. If you need a userspace PRNG switch to HMAC_DRBG + (or AutoSeeded_RNG which is HMAC_DRBG with useful defaults). + +* Fix a bug in ANSI X9.23 padding mode, which returned one byte more + than the given block size (GH #529). * Fixes for FreeBSD (GH #517) and OpenBSD (GH #523) -* Support for getting entropy from EGD is deprecated, and will be removed in - a future release. The developers believe that it is unlikely that any modern - system requires EGD and so the code is now dead weight. If you rely on EGD - support, you should contact the developers by email or GitHub ASAP. +* New deprecations. See the full list in doc/deprecated.txt -* The TLS ciphersuites using 3DES and SEED are deprecated and will be removed in - a future release. + Support for getting entropy from EGD is deprecated, and will be + removed in a future release. The developers believe that it is + unlikely that any modern system requires EGD and so the code is now + dead weight. If you rely on EGD support, you should contact the + developers by email or GitHub ASAP. -* Support for BeOS/Haiku has not been tested in 5 years and is in an unknown state. - Unless reports are received of successful builds and use on this platform, support - for BeOS/Haiku will be removed in a future release. + The TLS ciphersuites using 3DES and SEED are deprecated and will be + removed in a future release. -* Changes in DLIES: Previously the input to the KDF was the concatenation - of the (ephemeral) public key and the secret value derived by the key - agreement operation. Now the input is only the secret value obtained - by the key agreement operation. That's how it is specified in the original - paper "DHIES: An encryption scheme based on Diffie-Hellman Problem" or in BSI - technical guideline TR-02102-1 for example. In addition to the already present - XOR-encrypion/decryption mode it's now possible to use DLIES with a block cipher. - Furthermore the order of the output was changed from {public key, tag, ciphertext} - to {public key, ciphertext, tag}. Both modes are compatible with bouncycastle. + ECB mode Cipher_Mode is deprecated and will be removed in a future + release. -* Fix a bug in ANSI X9.23 padding mode, which returned one byte more - than the given block size (GH #529). + Support for BeOS/Haiku has not been tested in 5+ years and is in an + unknown state. Unless reports are received of successful builds and + use on this platform, support for BeOS/Haiku will be removed in a + future release. Version 1.11.30, 2016-06-19 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/doc/todo.rst b/doc/todo.rst index a66c97f4f..b6c55a898 100644 --- a/doc/todo.rst +++ b/doc/todo.rst @@ -7,6 +7,14 @@ ticket on GitHub to make sure you're on the right track. Request a new feature by opening a pull request to update this file. +Documentation +---------------------------------------- + +* TPM (no docs) +* PKCS #11 (no docs) +* X.509 certs, path validation +* Specific docs covering one major topic (RSA, ECDSA, AES/GCM, ...) + CLI ---------------------------------------- -- cgit v1.2.3 From 80c160f08f2a69eb4e41a68380796bf31fd2f924 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Fri, 19 Aug 2016 07:51:47 -0400 Subject: RNG changes (GH #593) Change reseed interval logic to count calls to `randomize` rather than bytes, to match SP 800-90A Changes RNG reseeding API: there is no implicit reference to the global entropy sources within the RNGs anymore. The entropy sources must be supplied with the API call. Adds support for reseding directly from another RNG (such as a system or hardware RNG). Stateful_RNG keeps optional references to both an RNG and a set of entropy sources. During a reseed, both sources are used if set. These can be provided to HMAC_DRBG constructor. For HMAC_DRBG, SP800-90A requires we output no more than 2**16 bytes per DRBG request. We treat requests longer than that as if the caller had instead made several sequential maximum-length requests. This means it is possible for one or more reseeds to trigger even in the course of generating a single (long) output (generate a 256-bit key and use ChaCha or HKDF if this is a problem). Adds RNG::randomize_with_ts_input which takes timestamps and uses them as the additional_data DRBG field. Stateful_RNG overrides this to also include the process ID and the reseed counter. AutoSeeded_RNG's `randomize` uses this. Officially deprecates RNG::make_rng and the Serialized_RNG construtor which creates an AutoSeeded_RNG. With these removed, it would be possible to perform a build with no AutoSeeded_RNG/HMAC_DRBG at all (eg, for applications which only use the system RNG). Tests courtesy @cordney in GH PRs #598 and #600 --- doc/deprecated.txt | 5 + src/build-data/buildh.in | 10 +- src/build-data/policy/bsi.txt | 1 + src/build-data/policy/modern.txt | 2 +- src/cli/cli.h | 7 +- src/cli/speed.cpp | 16 +- src/cli/utils.cpp | 10 +- src/lib/entropy/entropy_src.h | 5 + src/lib/ffi/ffi.cpp | 2 +- src/lib/prov/pkcs11/p11_randomgenerator.h | 4 +- src/lib/pubkey/rfc6979/rfc6979.cpp | 2 +- src/lib/rng/auto_rng.h | 47 ----- src/lib/rng/auto_rng/auto_rng.cpp | 116 ++++++++++ src/lib/rng/auto_rng/auto_rng.h | 67 ++++++ src/lib/rng/auto_rng/info.txt | 1 + src/lib/rng/hmac_drbg/hmac_drbg.cpp | 99 ++++++--- src/lib/rng/hmac_drbg/hmac_drbg.h | 68 +++++- src/lib/rng/hmac_drbg/info.txt | 1 + src/lib/rng/hmac_rng/hmac_rng.cpp | 86 +++++--- src/lib/rng/hmac_rng/hmac_rng.h | 70 +++++-- src/lib/rng/hmac_rng/info.txt | 1 + src/lib/rng/info.txt | 2 - src/lib/rng/rdrand_rng/rdrand_rng.h | 3 +- src/lib/rng/rng.cpp | 140 +++---------- src/lib/rng/rng.h | 137 ++++-------- src/lib/rng/stateful_rng/info.txt | 2 + src/lib/rng/stateful_rng/stateful_rng.cpp | 112 ++++++++++ src/lib/rng/stateful_rng/stateful_rng.h | 118 +++++++++++ src/lib/rng/x931_rng/info.txt | 4 + src/lib/rng/x931_rng/x931_rng.cpp | 10 +- src/lib/rng/x931_rng/x931_rng.h | 9 +- src/lib/utils/os_utils.cpp | 6 +- src/lib/utils/os_utils.h | 2 +- src/tests/main.cpp | 24 ++- src/tests/test_mceliece.cpp | 2 +- src/tests/test_pkcs11_high_level.cpp | 12 +- src/tests/test_rng.cpp | 337 +++++++++++++++++++++++++++++- src/tests/test_rng.h | 34 +-- src/tests/tests.cpp | 2 +- 39 files changed, 1152 insertions(+), 424 deletions(-) delete mode 100644 src/lib/rng/auto_rng.h create mode 100644 src/lib/rng/auto_rng/auto_rng.cpp create mode 100644 src/lib/rng/auto_rng/auto_rng.h create mode 100644 src/lib/rng/auto_rng/info.txt create mode 100644 src/lib/rng/stateful_rng/info.txt create mode 100644 src/lib/rng/stateful_rng/stateful_rng.cpp create mode 100644 src/lib/rng/stateful_rng/stateful_rng.h (limited to 'doc') diff --git a/doc/deprecated.txt b/doc/deprecated.txt index 456a7e6b7..d62954d1d 100644 --- a/doc/deprecated.txt +++ b/doc/deprecated.txt @@ -1,5 +1,10 @@ Currently deprecated: +- PRNGs X9.31 (no longer approved) and HMAC_RNG (non-standard) + Use HMAC_DRBG + +- ECB mode for block ciphers + - Rabin-Williams signatures - Nyberg-Rueppel signatures diff --git a/src/build-data/buildh.in b/src/build-data/buildh.in index 01527b522..e943973a0 100644 --- a/src/build-data/buildh.in +++ b/src/build-data/buildh.in @@ -98,11 +98,10 @@ #define BOTAN_PRIVATE_KEY_STRONG_CHECKS_ON_GENERATE 1 /* -* RNGs will automatically poll the system for additional seed material -* after producing this many bytes of output. Set to zero to disable -* automatic reseeding. +* Userspace RNGs like HMAC_DRBG will reseed after a specified number +* of outputs are generated. Set to zero to disable automatic reseeding. */ -#define BOTAN_RNG_DEFAULT_MAX_OUTPUT_BEFORE_RESEED 16384 +#define BOTAN_RNG_DEFAULT_RESEED_INTERVAL 1024 #define BOTAN_RNG_RESEED_POLL_BITS 256 #define BOTAN_RNG_AUTO_RESEED_TIMEOUT std::chrono::milliseconds(10) #define BOTAN_RNG_RESEED_DEFAULT_TIMEOUT std::chrono::milliseconds(50) @@ -111,8 +110,7 @@ * Controls how AutoSeeded_RNG is instantiated */ #define BOTAN_AUTO_RNG_DRBG HMAC_DRBG -#define BOTAN_AUTO_RNG_HASH "SHA-256" -#define BOTAN_AUTO_RNG_ENTROPY_TARGET 256 +#define BOTAN_AUTO_RNG_HMAC "HMAC(SHA-384)" /* * Specifies (in order) the list of entropy sources that will be used diff --git a/src/build-data/policy/bsi.txt b/src/build-data/policy/bsi.txt index 7eb092292..7f2b09610 100644 --- a/src/build-data/policy/bsi.txt +++ b/src/build-data/policy/bsi.txt @@ -41,6 +41,7 @@ eckcdsa ecdh # rng +auto_rng hmac_rng hmac_drbg diff --git a/src/build-data/policy/modern.txt b/src/build-data/policy/modern.txt index 30b7fbfd8..a98ec5077 100644 --- a/src/build-data/policy/modern.txt +++ b/src/build-data/policy/modern.txt @@ -38,7 +38,7 @@ eme_oaep emsa_pssr emsa1 -hmac_rng +auto_rng hmac_drbg ffi diff --git a/src/cli/cli.h b/src/cli/cli.h index 11cc8add7..7e2d49f0f 100644 --- a/src/cli/cli.h +++ b/src/cli/cli.h @@ -10,7 +10,10 @@ #include #include #include -#include + +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + #include +#endif #if defined(BOTAN_HAS_SYSTEM_RNG) #include @@ -471,7 +474,9 @@ class Command if(rng_type == "auto") { +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) m_rng.reset(new Botan::AutoSeeded_RNG); +#endif } if(!m_rng) diff --git a/src/cli/speed.cpp b/src/cli/speed.cpp index 1299b0d19..222a98d3f 100644 --- a/src/cli/speed.cpp +++ b/src/cli/speed.cpp @@ -19,9 +19,12 @@ #include #include #include -#include #include +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + #include +#endif + #if defined(BOTAN_HAS_SYSTEM_RNG) #include #endif @@ -413,8 +416,10 @@ class Speed final : public Command #endif else if(algo == "RNG") { +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) Botan::AutoSeeded_RNG auto_rng; bench_rng(auto_rng, "AutoSeeded_RNG (periodic reseed)", msec, buf_size); +#endif #if defined(BOTAN_HAS_SYSTEM_RNG) bench_rng(Botan::system_rng(), "System_RNG", msec, buf_size); @@ -428,7 +433,7 @@ class Speed final : public Command #if defined(BOTAN_HAS_HMAC_DRBG) for(std::string hash : { "SHA-256", "SHA-384", "SHA-512" }) { - Botan::HMAC_DRBG hmac_drbg(hash, 0); + Botan::HMAC_DRBG hmac_drbg(hash); bench_rng(hmac_drbg, hmac_drbg.name(), msec, buf_size); } #endif @@ -436,7 +441,7 @@ class Speed final : public Command #if defined(BOTAN_HAS_HMAC_RNG) for(std::string hash : { "SHA-256", "SHA-384", "SHA-512" }) { - Botan::HMAC_RNG hmac_rng(hash, 0); + Botan::HMAC_RNG hmac_rng(Botan::MessageAuthenticationCode::create("HMAC(" + hash + ")")); bench_rng(hmac_rng, hmac_rng.name(), msec, buf_size); } #endif @@ -595,8 +600,9 @@ class Speed final : public Command { Botan::secure_vector buffer(buf_size); - rng.add_entropy(buffer.data(), buffer.size()); - rng.reseed(256); +#if defined(BOTAN_HAS_SYSTEM_RNG) + rng.reseed_from_rng(Botan::system_rng(), 256); +#endif Timer timer(rng_name, "", "generate", buffer.size()); timer.run_until_elapsed(runtime, [&] { rng.randomize(buffer.data(), buffer.size()); }); diff --git a/src/cli/utils.cpp b/src/cli/utils.cpp index b0d364581..610a14dc1 100644 --- a/src/cli/utils.cpp +++ b/src/cli/utils.cpp @@ -7,7 +7,6 @@ #include "cli.h" #include -#include #include #include #include @@ -16,6 +15,10 @@ #include #endif +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + #include +#endif + #if defined(BOTAN_HAS_SYSTEM_RNG) #include #endif @@ -179,7 +182,12 @@ class RNG final : public Command } else { +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) rng.reset(new Botan::AutoSeeded_RNG); +#else + error_output() << "auto_rng disabled in build\n"; + return; +#endif } for(const std::string& req : get_arg_list("bytes")) diff --git a/src/lib/entropy/entropy_src.h b/src/lib/entropy/entropy_src.h index 64d988e7c..94c67a18e 100644 --- a/src/lib/entropy/entropy_src.h +++ b/src/lib/entropy/entropy_src.h @@ -8,12 +8,17 @@ #ifndef BOTAN_ENTROPY_H__ #define BOTAN_ENTROPY_H__ +#include #include #include #include +#include +#include namespace Botan { +class RandomNumberGenerator; + /** * Abstract interface to a source of entropy */ diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp index 028b286b6..e42f32234 100644 --- a/src/lib/ffi/ffi.cpp +++ b/src/lib/ffi/ffi.cpp @@ -287,7 +287,7 @@ int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t out_len) int botan_rng_reseed(botan_rng_t rng, size_t bits) { - return BOTAN_FFI_DO(Botan::RandomNumberGenerator, rng, r, { r.reseed(bits); }); + return BOTAN_FFI_DO(Botan::RandomNumberGenerator, rng, r, { r.reseed_from_rng(Botan::system_rng(), bits); }); } int botan_hash_init(botan_hash_t* hash, const char* hash_name, uint32_t flags) diff --git a/src/lib/prov/pkcs11/p11_randomgenerator.h b/src/lib/prov/pkcs11/p11_randomgenerator.h index 84673278d..a291c89f3 100644 --- a/src/lib/prov/pkcs11/p11_randomgenerator.h +++ b/src/lib/prov/pkcs11/p11_randomgenerator.h @@ -22,7 +22,7 @@ namespace PKCS11 { class Module; /// A random generator that only fetches random from the PKCS#11 RNG -class BOTAN_DLL PKCS11_RNG final : public RandomNumberGenerator +class BOTAN_DLL PKCS11_RNG final : public Hardware_RNG { public: /// Initialize the RNG with the PKCS#11 session that provides access to the cryptoki functions @@ -43,7 +43,7 @@ class BOTAN_DLL PKCS11_RNG final : public RandomNumberGenerator } /// No operation - always returns 0 - size_t reseed_with_sources(Entropy_Sources&, size_t, std::chrono::milliseconds) override + size_t reseed(Entropy_Sources&, size_t, std::chrono::milliseconds) override { return 0; } diff --git a/src/lib/pubkey/rfc6979/rfc6979.cpp b/src/lib/pubkey/rfc6979/rfc6979.cpp index 1173eefee..94b313c3a 100644 --- a/src/lib/pubkey/rfc6979/rfc6979.cpp +++ b/src/lib/pubkey/rfc6979/rfc6979.cpp @@ -17,10 +17,10 @@ RFC6979_Nonce_Generator::RFC6979_Nonce_Generator(const std::string& hash, m_order(order), m_qlen(m_order.bits()), m_rlen(m_qlen / 8 + (m_qlen % 8 ? 1 : 0)), - m_hmac_drbg(new HMAC_DRBG(hash, 0)), m_rng_in(m_rlen * 2), m_rng_out(m_rlen) { + m_hmac_drbg.reset(new HMAC_DRBG(MessageAuthenticationCode::create("HMAC(" + hash + ")"))); BigInt::encode_1363(m_rng_in.data(), m_rlen, x); } diff --git a/src/lib/rng/auto_rng.h b/src/lib/rng/auto_rng.h deleted file mode 100644 index 3085623ef..000000000 --- a/src/lib/rng/auto_rng.h +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Auto Seeded RNG -* (C) 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_AUTO_SEEDING_RNG_H__ -#define BOTAN_AUTO_SEEDING_RNG_H__ - -#include - -namespace Botan { - -class BOTAN_DLL AutoSeeded_RNG final : public RandomNumberGenerator - { - public: - void randomize(byte out[], size_t len) override; - - void randomize_with_input(byte output[], size_t output_len, - const byte input[], size_t input_len) override; - - bool is_seeded() const override { return m_rng->is_seeded(); } - - void clear() override { m_rng->clear(); m_counter = 0; } - - std::string name() const override { return m_rng->name(); } - - size_t reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout) override - { - return m_rng->reseed_with_sources(srcs, poll_bits, poll_timeout); - } - - void add_entropy(const byte in[], size_t len) override - { m_rng->add_entropy(in, len); } - - AutoSeeded_RNG(size_t max_output_before_reseed = BOTAN_RNG_DEFAULT_MAX_OUTPUT_BEFORE_RESEED); - private: - std::unique_ptr m_rng; - uint32_t m_counter = 0; - }; - -} - -#endif diff --git a/src/lib/rng/auto_rng/auto_rng.cpp b/src/lib/rng/auto_rng/auto_rng.cpp new file mode 100644 index 000000000..a9da085bc --- /dev/null +++ b/src/lib/rng/auto_rng/auto_rng.cpp @@ -0,0 +1,116 @@ +/* +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include + +#if defined(BOTAN_HAS_HMAC_DRBG) + #include +#endif + +#if defined(BOTAN_HAS_HMAC_RNG) + #include +#endif + +#if defined(BOTAN_HAS_SYSTEM_RNG) + #include +#endif + +namespace Botan { + +AutoSeeded_RNG::~AutoSeeded_RNG() + { + // for unique_ptr + } + +AutoSeeded_RNG::AutoSeeded_RNG(RandomNumberGenerator& underlying_rng, + size_t reseed_interval) + { + m_rng.reset(new BOTAN_AUTO_RNG_DRBG(MessageAuthenticationCode::create(BOTAN_AUTO_RNG_HMAC), + underlying_rng, + reseed_interval)); + force_reseed(); + } + +AutoSeeded_RNG::AutoSeeded_RNG(Entropy_Sources& entropy_sources, + size_t reseed_interval) + { + m_rng.reset(new BOTAN_AUTO_RNG_DRBG(MessageAuthenticationCode::create(BOTAN_AUTO_RNG_HMAC), + entropy_sources, + reseed_interval)); + force_reseed(); + } + +AutoSeeded_RNG::AutoSeeded_RNG(RandomNumberGenerator& underlying_rng, + Entropy_Sources& entropy_sources, + size_t reseed_interval) + { + m_rng.reset(new BOTAN_AUTO_RNG_DRBG(MessageAuthenticationCode::create(BOTAN_AUTO_RNG_HMAC), + underlying_rng, + entropy_sources, + reseed_interval)); + force_reseed(); + } + +AutoSeeded_RNG::AutoSeeded_RNG(size_t reseed_interval) : +#if defined(BOTAN_HAS_SYSTEM_RNG) + AutoSeeded_RNG(system_rng(), reseed_interval) +#else + AutoSeeded_RNG(Entropy_Sources::global_sources(), reseed_interval) +#endif + { + } + +void AutoSeeded_RNG::force_reseed() + { + m_rng->force_reseed(); + m_rng->next_byte(); + + if(!m_rng->is_seeded()) + { + throw Exception("AutoSeeded_RNG reseeding failed"); + } + } + +bool AutoSeeded_RNG::is_seeded() const + { + return m_rng->is_seeded(); + } + +void AutoSeeded_RNG::clear() + { + m_rng->clear(); + } + +std::string AutoSeeded_RNG::name() const + { + return m_rng->name(); + } + +void AutoSeeded_RNG::add_entropy(const byte in[], size_t len) + { + m_rng->add_entropy(in, len); + } + +size_t AutoSeeded_RNG::reseed(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) + { + return m_rng->reseed(srcs, poll_bits, poll_timeout); + } + +void AutoSeeded_RNG::randomize(byte output[], size_t output_len) + { + randomize_with_ts_input(output, output_len); + } + +void AutoSeeded_RNG::randomize_with_input(byte output[], size_t output_len, + const byte ad[], size_t ad_len) + { + m_rng->randomize_with_input(output, output_len, ad, ad_len); + } + +} diff --git a/src/lib/rng/auto_rng/auto_rng.h b/src/lib/rng/auto_rng/auto_rng.h new file mode 100644 index 000000000..6ef1aa291 --- /dev/null +++ b/src/lib/rng/auto_rng/auto_rng.h @@ -0,0 +1,67 @@ +/* +* Auto Seeded RNG +* (C) 2008,2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_AUTO_SEEDING_RNG_H__ +#define BOTAN_AUTO_SEEDING_RNG_H__ + +#include + +namespace Botan { + +class Stateful_RNG; + +/** +* A userspace PRNG +*/ +class BOTAN_DLL AutoSeeded_RNG final : public RandomNumberGenerator + { + public: + void randomize(byte out[], size_t len) override; + + void randomize_with_input(byte output[], size_t output_len, + const byte input[], size_t input_len) override; + + bool is_seeded() const override; + + void force_reseed(); + + size_t reseed(Entropy_Sources& srcs, + size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS, + std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override; + + void add_entropy(const byte in[], size_t len) override; + + std::string name() const override; + + void clear() override; + + /** + * If no RNG or entropy sources are provided to AutoSeeded_RNG, it uses the system RNG + * (if available) or else a default group of entropy sources (all other systems) to + * gather seed material. + */ + AutoSeeded_RNG(size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + AutoSeeded_RNG(RandomNumberGenerator& underlying_rng, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + AutoSeeded_RNG(Entropy_Sources& entropy_sources, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + AutoSeeded_RNG(RandomNumberGenerator& underlying_rng, + Entropy_Sources& entropy_sources, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + ~AutoSeeded_RNG(); + + private: + std::unique_ptr m_rng; + }; + +} + +#endif diff --git a/src/lib/rng/auto_rng/info.txt b/src/lib/rng/auto_rng/info.txt new file mode 100644 index 000000000..b77e6aa54 --- /dev/null +++ b/src/lib/rng/auto_rng/info.txt @@ -0,0 +1 @@ +define AUTO_SEEDING_RNG 20160821 diff --git a/src/lib/rng/hmac_drbg/hmac_drbg.cpp b/src/lib/rng/hmac_drbg/hmac_drbg.cpp index 7325804e3..6ea66aa2e 100644 --- a/src/lib/rng/hmac_drbg/hmac_drbg.cpp +++ b/src/lib/rng/hmac_drbg/hmac_drbg.cpp @@ -10,28 +10,42 @@ namespace Botan { -HMAC_DRBG::HMAC_DRBG(MessageAuthenticationCode* hmac, - size_t max_output_before_reseed) : - Stateful_RNG(max_output_before_reseed), - m_mac(hmac) +HMAC_DRBG::HMAC_DRBG(std::unique_ptr prf, + RandomNumberGenerator& underlying_rng, + size_t reseed_interval) : + Stateful_RNG(underlying_rng, reseed_interval), + m_mac(std::move(prf)) { - m_V.resize(m_mac->output_length()); + BOTAN_ASSERT_NONNULL(m_mac); clear(); } -HMAC_DRBG::HMAC_DRBG(const std::string& hmac_hash, - size_t max_output_before_reseed) : - Stateful_RNG(max_output_before_reseed) +HMAC_DRBG::HMAC_DRBG(std::unique_ptr prf, + RandomNumberGenerator& underlying_rng, + Entropy_Sources& entropy_sources, + size_t reseed_interval) : + Stateful_RNG(underlying_rng, entropy_sources, reseed_interval), + m_mac(std::move(prf)) { - const std::string hmac = "HMAC(" + hmac_hash + ")"; + BOTAN_ASSERT_NONNULL(m_mac); + clear(); + } - m_mac = MessageAuthenticationCode::create(hmac); - if(!m_mac) - { - throw Algorithm_Not_Found(hmac); - } +HMAC_DRBG::HMAC_DRBG(std::unique_ptr prf, + Entropy_Sources& entropy_sources, + size_t reseed_interval) : + Stateful_RNG(entropy_sources, reseed_interval), + m_mac(std::move(prf)) + { + BOTAN_ASSERT_NONNULL(m_mac); + clear(); + } - m_V.resize(m_mac->output_length()); +HMAC_DRBG::HMAC_DRBG(std::unique_ptr prf) : + Stateful_RNG(), + m_mac(std::move(prf)) + { + BOTAN_ASSERT_NONNULL(m_mac); clear(); } @@ -39,6 +53,7 @@ void HMAC_DRBG::clear() { Stateful_RNG::clear(); + m_V.resize(m_mac->output_length()); for(size_t i = 0; i != m_V.size(); ++i) m_V[i] = 0x01; m_mac->set_key(std::vector(m_mac->output_length(), 0x00)); @@ -61,25 +76,45 @@ void HMAC_DRBG::randomize(byte output[], size_t output_len) void HMAC_DRBG::randomize_with_input(byte output[], size_t output_len, const byte input[], size_t input_len) { - reseed_check(output_len); - - if(input_len > 0) + /** + * SP 800-90A requires we reject any request for a DRBG output + * longer than max_number_of_bits_per_request. This is an + * implementation-dependent value, but NIST requires for HMAC_DRBG + * that every implementation set a value no more than 2**19 bits + * (or 64 KiB). + * + * To avoid inconveniencing the caller who wants a large output for + * whatever reason, instead treat very long output requests as + * if multiple maximum-length requests had been made. + */ + const size_t max_number_of_bytes_per_request = 64*1024; + + while(output_len > 0) { - update(input, input_len); - } + size_t this_req = std::min(max_number_of_bytes_per_request, output_len); + output_len -= this_req; - while(output_len) - { - const size_t to_copy = std::min(output_len, m_V.size()); - m_mac->update(m_V.data(), m_V.size()); - m_mac->final(m_V.data()); - copy_mem(output, m_V.data(), to_copy); + reseed_check(); + + if(input_len > 0) + { + update(input, input_len); + } + + while(this_req) + { + const size_t to_copy = std::min(this_req, m_V.size()); + m_mac->update(m_V.data(), m_V.size()); + m_mac->final(m_V.data()); + copy_mem(output, m_V.data(), to_copy); - output += to_copy; - output_len -= to_copy; + output += to_copy; + this_req -= to_copy; + } + + update(input, input_len); } - update(input, input_len); } /* @@ -113,4 +148,10 @@ void HMAC_DRBG::add_entropy(const byte input[], size_t input_len) update(input, input_len); } +size_t HMAC_DRBG::security_level() const + { + // sqrt of hash size + return m_mac->output_length() * 8 / 2; + } + } diff --git a/src/lib/rng/hmac_drbg/hmac_drbg.h b/src/lib/rng/hmac_drbg/hmac_drbg.h index 0e294dbdb..4f96af816 100644 --- a/src/lib/rng/hmac_drbg/hmac_drbg.h +++ b/src/lib/rng/hmac_drbg/hmac_drbg.h @@ -8,11 +8,13 @@ #ifndef BOTAN_HMAC_DRBG_H__ #define BOTAN_HMAC_DRBG_H__ -#include +#include #include namespace Botan { +class Entropy_Sources; + /** * HMAC_DRBG from NIST SP800-90A */ @@ -20,13 +22,64 @@ class BOTAN_DLL HMAC_DRBG final : public Stateful_RNG { public: /** - * Initialize an HMAC_DRBG instance with the given hash function + * Initialize an HMAC_DRBG instance with the given MAC as PRF (normally HMAC) + * + * Automatic reseeding is disabled completely, as it as no access to + * any source for seed material. + * + * If a fork is detected, the RNG will be unable to reseed itself + * in response. In this case, an exception will be thrown rather + * than generating duplicated output. + */ + HMAC_DRBG(std::unique_ptr prf); + + /** + * Initialize an HMAC_DRBG instance with the given MAC as PRF (normally HMAC) + * + * @param underlying_rng is a reference to some RNG which will be used + * to perform the periodic reseeding + * @param reseed_interval specifies a limit of how many times + * the RNG will be called before automatic reseeding is performed. + */ + HMAC_DRBG(std::unique_ptr prf, + RandomNumberGenerator& underlying_rng, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + /** + * Initialize an HMAC_DRBG instance with the given MAC as PRF (normally HMAC) + * + * @param entropy_sources will be polled to perform reseeding periodically + * @param reseed_interval specifies a limit of how many times + * the RNG will be called before automatic reseeding is performed. */ - HMAC_DRBG(const std::string& hmac_hash, - size_t max_output_before_reseed = BOTAN_RNG_DEFAULT_MAX_OUTPUT_BEFORE_RESEED); + HMAC_DRBG(std::unique_ptr prf, + Entropy_Sources& entropy_sources, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); - HMAC_DRBG(MessageAuthenticationCode* hmac, - size_t max_output_before_reseed = BOTAN_RNG_DEFAULT_MAX_OUTPUT_BEFORE_RESEED); + /** + * Initialize an HMAC_DRBG instance with the given MAC as PRF (normally HMAC) + * + * @param underlying_rng is a reference to some RNG which will be used + * to perform the periodic reseeding + * @param entropy_sources will be polled to perform reseeding periodically + * @param reseed_interval specifies a limit of how many times + * the RNG will be called before automatic reseeding is performed. + */ + HMAC_DRBG(std::unique_ptr prf, + RandomNumberGenerator& underlying_rng, + Entropy_Sources& entropy_sources, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + /** + * Constructor taking a string for the hash + */ + HMAC_DRBG(const std::string& hmac_hash) : Stateful_RNG() + { + m_mac = MessageAuthenticationCode::create("HMAC(" + hmac_hash + ")"); + if(!m_mac) + throw Algorithm_Not_Found(hmac_hash); + clear(); + } std::string name() const override; @@ -38,6 +91,9 @@ class BOTAN_DLL HMAC_DRBG final : public Stateful_RNG const byte input[], size_t input_len) override; void add_entropy(const byte input[], size_t input_len) override; + + size_t security_level() const override; + private: void update(const byte input[], size_t input_len); diff --git a/src/lib/rng/hmac_drbg/info.txt b/src/lib/rng/hmac_drbg/info.txt index f386db199..7f2c12fd0 100644 --- a/src/lib/rng/hmac_drbg/info.txt +++ b/src/lib/rng/hmac_drbg/info.txt @@ -2,4 +2,5 @@ define HMAC_DRBG 20140319 hmac +stateful_rng diff --git a/src/lib/rng/hmac_rng/hmac_rng.cpp b/src/lib/rng/hmac_rng/hmac_rng.cpp index c100cf70f..d66c538ab 100644 --- a/src/lib/rng/hmac_rng/hmac_rng.cpp +++ b/src/lib/rng/hmac_rng/hmac_rng.cpp @@ -12,43 +12,71 @@ namespace Botan { -HMAC_RNG::HMAC_RNG(const std::string& hash, size_t max_output_before_reseed) : - Stateful_RNG(max_output_before_reseed) +HMAC_RNG::HMAC_RNG(std::unique_ptr prf, + RandomNumberGenerator& underlying_rng, + Entropy_Sources& entropy_sources, + size_t reseed_interval) : + Stateful_RNG(underlying_rng, reseed_interval), + m_prf(std::move(prf)) { - m_extractor = MAC::create("HMAC(" + hash + ")"); - if(!m_extractor) - throw Invalid_Argument("HMAC_RNG hash not found"); + BOTAN_ASSERT_NONNULL(m_prf); - m_prf.reset(m_extractor->clone()); + if(!m_prf->valid_keylength(m_prf->output_length())) + { + throw Invalid_Argument("HMAC_RNG cannot use " + m_prf->name()); + } + + m_extractor.reset(m_prf->clone()); + this->clear(); + } - if(!m_prf->valid_keylength(m_extractor->output_length()) || - !m_extractor->valid_keylength(m_prf->output_length())) +HMAC_RNG::HMAC_RNG(std::unique_ptr prf, + RandomNumberGenerator& underlying_rng, + size_t reseed_interval) : + Stateful_RNG(underlying_rng, reseed_interval), + m_prf(std::move(prf)) + { + BOTAN_ASSERT_NONNULL(m_prf); + + if(!m_prf->valid_keylength(m_prf->output_length())) { - throw Invalid_Argument("HMAC_RNG: Bad algo combination " + - m_extractor->name() + " and " + - m_prf->name()); + throw Invalid_Argument("HMAC_RNG cannot use " + m_prf->name()); } + m_extractor.reset(m_prf->clone()); this->clear(); } -/* -* HMAC_RNG Constructor -*/ -HMAC_RNG::HMAC_RNG(MessageAuthenticationCode* extractor, - MessageAuthenticationCode* prf, - size_t max_output_before_reseed) : - Stateful_RNG(max_output_before_reseed), - m_extractor(extractor), m_prf(prf) +HMAC_RNG::HMAC_RNG(std::unique_ptr prf, + Entropy_Sources& entropy_sources, + size_t reseed_interval) : + Stateful_RNG(entropy_sources, reseed_interval), + m_prf(std::move(prf)), + m_extractor(m_prf->clone()) { - if(!m_prf->valid_keylength(m_extractor->output_length()) || - !m_extractor->valid_keylength(m_prf->output_length())) + BOTAN_ASSERT_NONNULL(m_prf); + + if(!m_prf->valid_keylength(m_prf->output_length())) + { + throw Invalid_Argument("HMAC_RNG cannot use " + m_prf->name()); + } + + m_extractor.reset(m_prf->clone()); + this->clear(); + } + +HMAC_RNG::HMAC_RNG(std::unique_ptr prf) : + Stateful_RNG(), + m_prf(std::move(prf)) + { + BOTAN_ASSERT_NONNULL(m_prf); + + if(!m_prf->valid_keylength(m_prf->output_length())) { - throw Invalid_Argument("HMAC_RNG: Bad algo combination " + - m_extractor->name() + " and " + - m_prf->name()); + throw Invalid_Argument("HMAC_RNG cannot use " + m_prf->name()); } + m_extractor.reset(m_prf->clone()); this->clear(); } @@ -105,7 +133,7 @@ void HMAC_RNG::new_K_value(byte label) */ void HMAC_RNG::randomize(byte out[], size_t length) { - reseed_check(length); + reseed_check(); while(length) { @@ -121,9 +149,9 @@ void HMAC_RNG::randomize(byte out[], size_t length) new_K_value(BlockFinished); } -size_t HMAC_RNG::reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds timeout) +size_t HMAC_RNG::reseed(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds timeout) { new_K_value(Reseed); m_extractor->update(m_K); // m_K is the PRF output @@ -131,7 +159,7 @@ size_t HMAC_RNG::reseed_with_sources(Entropy_Sources& srcs, /* * This ends up calling add_entropy which provides input to the extractor */ - size_t bits_collected = Stateful_RNG::reseed_with_sources(srcs, poll_bits, timeout); + size_t bits_collected = Stateful_RNG::reseed(srcs, poll_bits, timeout); /* Now derive the new PRK using everything that has been fed into diff --git a/src/lib/rng/hmac_rng/hmac_rng.h b/src/lib/rng/hmac_rng/hmac_rng.h index a2538a83a..d6e9b4896 100644 --- a/src/lib/rng/hmac_rng/hmac_rng.h +++ b/src/lib/rng/hmac_rng/hmac_rng.h @@ -1,6 +1,6 @@ /* * HMAC RNG -* (C) 2008,2013 Jack Lloyd +* (C) 2008,2013,2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -8,9 +8,8 @@ #ifndef BOTAN_HMAC_RNG_H__ #define BOTAN_HMAC_RNG_H__ +#include #include -#include -#include namespace Botan { @@ -19,40 +18,69 @@ namespace Botan { * Key Derivation Functions and an HMAC-based KDF" by Hugo Krawczyk * (henceforce, 'E-t-E') * -* However it actually can be parameterized with any two MAC functions, +* However it actually could be parameterized with any two MAC functions, * not restricted to HMAC (this variation is also described in * Krawczyk's paper), for instance one could use HMAC(SHA-512) as the * extractor and CMAC(AES-256) as the PRF. */ -class BOTAN_DLL HMAC_RNG : public Stateful_RNG +class BOTAN_DLL HMAC_RNG final : public Stateful_RNG { public: + /** + * Initialize an HMAC_RNG instance with the given MAC as PRF (normally HMAC) + * @param underlying_rng is a reference to some RNG which will be used + * to perform the periodic reseeding. + * @param entropy_sources will be polled to perform reseeding periodically + * @param reseed_interval specifies a limit of how many times + * the RNG will be called before automatic reseeding is performed. + */ + HMAC_RNG(std::unique_ptr prf, + RandomNumberGenerator& underlying_rng, + Entropy_Sources& entropy_sources, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + /** + * Initialize an HMAC_RNG instance with the given MAC as PRF (normally HMAC) + * @param underlying_rng is a reference to some RNG which will be used + * to perform the periodic reseeding. + * @param reseed_interval specifies a limit of how many times + * the RNG will be called before automatic reseeding is performed. + */ + HMAC_RNG(std::unique_ptr prf, + RandomNumberGenerator& underlying_rng, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + /* + * Initialize an HMAC_RNG instance with the given MAC as PRF (normally HMAC) + * @param entropy_sources will be polled to perform reseeding periodically + * @param reseed_interval specifies a limit of how many times + * the RNG will be called before automatic reseeding is performed. + */ + HMAC_RNG(std::unique_ptr prf, + Entropy_Sources& entropy_sources, + size_t reseed_interval = BOTAN_RNG_DEFAULT_RESEED_INTERVAL); + + /** + * Initialize an HMAC_RNG instance with the given MAC as PRF (normally HMAC) + * Automatic reseeding is disabled completely. + */ + HMAC_RNG(std::unique_ptr prf); + void randomize(byte buf[], size_t len) override; void clear() override; std::string name() const override; - size_t reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout) override; + size_t reseed(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override; void add_entropy(const byte[], size_t) override; - /** - * @param extractor a MAC used for extracting the entropy - * @param prf a MAC used as a PRF using HKDF construction - */ - HMAC_RNG(MessageAuthenticationCode* extractor, - MessageAuthenticationCode* prf, - size_t max_output_before_reseed = BOTAN_RNG_DEFAULT_MAX_OUTPUT_BEFORE_RESEED); + size_t security_level() const override { return m_prf->output_length() * 8 / 2; } - /** - * Use the specified hash for both the extractor and PRF functions - */ - HMAC_RNG(const std::string& hash, - size_t max_output_before_reseed = BOTAN_RNG_DEFAULT_MAX_OUTPUT_BEFORE_RESEED); private: - std::unique_ptr m_extractor; std::unique_ptr m_prf; + std::unique_ptr m_extractor; enum HMAC_PRF_Label { Running, diff --git a/src/lib/rng/hmac_rng/info.txt b/src/lib/rng/hmac_rng/info.txt index 36a8a7a34..2b7f49c8a 100644 --- a/src/lib/rng/hmac_rng/info.txt +++ b/src/lib/rng/hmac_rng/info.txt @@ -2,4 +2,5 @@ define HMAC_RNG 20131128 mac +stateful_rng diff --git a/src/lib/rng/info.txt b/src/lib/rng/info.txt index 84ba3ce89..655e35fd1 100644 --- a/src/lib/rng/info.txt +++ b/src/lib/rng/info.txt @@ -1,5 +1,3 @@ -define AUTO_SEEDING_RNG 20131128 - entropy hmac_drbg diff --git a/src/lib/rng/rdrand_rng/rdrand_rng.h b/src/lib/rng/rdrand_rng/rdrand_rng.h index d0fb37c16..fcd54035b 100644 --- a/src/lib/rng/rdrand_rng/rdrand_rng.h +++ b/src/lib/rng/rdrand_rng/rdrand_rng.h @@ -45,8 +45,7 @@ class BOTAN_DLL RDRAND_RNG : public Hardware_RNG void add_entropy(const uint8_t[], size_t) override { /* no op */ } - size_t reseed_with_sources(Entropy_Sources&, size_t, - std::chrono::milliseconds) override + size_t reseed(Entropy_Sources&, size_t, std::chrono::milliseconds) override { return 0; /* no op */ } std::string name() const override { return "RDRAND"; } diff --git a/src/lib/rng/rng.cpp b/src/lib/rng/rng.cpp index 5501c143e..8c2982312 100644 --- a/src/lib/rng/rng.cpp +++ b/src/lib/rng/rng.cpp @@ -1,144 +1,62 @@ /* -* Random Number Generator -* (C) 1999-2008,2016 Jack Lloyd +* (C) 2016 Jack Lloyd * * Botan is released under the Simplified BSD License (see license.txt) */ #include -#include -#include #include #include -#if defined(BOTAN_HAS_HMAC_DRBG) - #include -#endif - -#if defined(BOTAN_HAS_HMAC_RNG) - #include +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + #include #endif namespace Botan { -size_t RandomNumberGenerator::reseed(size_t bits_to_collect) +void RandomNumberGenerator::randomize_with_ts_input(byte output[], size_t output_len) { - return this->reseed_with_timeout(bits_to_collect, - BOTAN_RNG_RESEED_DEFAULT_TIMEOUT); - } - -size_t RandomNumberGenerator::reseed_with_timeout(size_t bits_to_collect, - std::chrono::milliseconds timeout) - { - return this->reseed_with_sources(Entropy_Sources::global_sources(), - bits_to_collect, - timeout); - } - -size_t RandomNumberGenerator::reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout) - { - return srcs.poll(*this, poll_bits, poll_timeout); - } - -Stateful_RNG::Stateful_RNG(size_t max_output_before_reseed) : m_max_output_before_reseed(max_output_before_reseed) - { - } - -void Stateful_RNG::clear() - { - m_successful_initialization = false; - m_bytes_since_reseed = 0; - m_last_pid = 0; - } - -size_t Stateful_RNG::reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout) - { - size_t bits_collected = RandomNumberGenerator::reseed_with_sources(srcs, poll_bits, poll_timeout); - - if(bits_collected >= poll_bits) - { - m_successful_initialization = true; - m_bytes_since_reseed = 0; - } + /* + Form additional input which is provided to the PRNG implementation + to paramaterize the KDF output. + */ + byte additional_input[16] = { 0 }; + store_le(OS::get_system_timestamp_ns(), additional_input); + store_le(OS::get_processor_timestamp(), additional_input + 8); - return bits_collected; + randomize_with_input(output, output_len, additional_input, sizeof(additional_input)); } -void Stateful_RNG::reseed_check(size_t bytes_requested) +void RandomNumberGenerator::randomize_with_input(byte output[], size_t output_len, + const byte input[], size_t input_len) { - const bool fork_detected = (m_last_pid > 0) && (OS::get_process_id() != m_last_pid); - - m_bytes_since_reseed += bytes_requested; - m_last_pid = OS::get_process_id(); - - if(!is_seeded() || fork_detected) - { - this->reseed(BOTAN_RNG_RESEED_POLL_BITS); - } - else if(m_max_output_before_reseed > 0 && m_bytes_since_reseed >= m_max_output_before_reseed) - { - this->reseed_with_timeout(BOTAN_RNG_RESEED_POLL_BITS, - BOTAN_RNG_AUTO_RESEED_TIMEOUT); - } - - if(!is_seeded()) - { - throw PRNG_Unseeded(name()); - } + this->add_entropy(input, input_len); + this->randomize(output, output_len); } -void Stateful_RNG::initialize_with(const byte input[], size_t len) +size_t RandomNumberGenerator::reseed(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) { - add_entropy(input, len); - m_successful_initialization = true; + return srcs.poll(*this, poll_bits, poll_timeout); } -bool Stateful_RNG::is_seeded() const +void RandomNumberGenerator::reseed_from_rng(RandomNumberGenerator& rng, size_t poll_bits) { - return m_successful_initialization; + secure_vector buf(poll_bits / 8); + rng.randomize(buf.data(), buf.size()); + this->add_entropy(buf.data(), buf.size()); } RandomNumberGenerator* RandomNumberGenerator::make_rng() { +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) return new AutoSeeded_RNG; +#else + throw Exception("make_rng failed, no AutoSeeded_RNG in this build"); +#endif } -AutoSeeded_RNG::AutoSeeded_RNG(size_t max_output_before_reseed) - { - m_rng.reset(new BOTAN_AUTO_RNG_DRBG(BOTAN_AUTO_RNG_HASH, max_output_before_reseed)); - - size_t bits = m_rng->reseed(BOTAN_AUTO_RNG_ENTROPY_TARGET); - - if(!m_rng->is_seeded()) - { - throw Exception("AutoSeeded_RNG failed to gather enough entropy only got " + - std::to_string(bits) + " bits"); - } - } - -void AutoSeeded_RNG::randomize(byte output[], size_t output_len) - { - /* - Form additional input which is provided to the PRNG implementation - to paramaterize the KDF output. - */ - byte additional_input[24] = { 0 }; - store_le(OS::get_system_timestamp_ns(), additional_input); - store_le(OS::get_processor_timestamp(), additional_input + 8); - store_le(OS::get_process_id(), additional_input + 16); - store_le(m_counter++, additional_input + 20); - - randomize_with_input(output, output_len, additional_input, sizeof(additional_input)); - } - -void AutoSeeded_RNG::randomize_with_input(byte output[], size_t output_len, - const byte ad[], size_t ad_len) - { - m_rng->randomize_with_input(output, output_len, ad, ad_len); - } +Serialized_RNG::Serialized_RNG() : m_rng(RandomNumberGenerator::make_rng()) {} } diff --git a/src/lib/rng/rng.h b/src/lib/rng/rng.h index 7da560b85..d1cdcfff2 100644 --- a/src/lib/rng/rng.h +++ b/src/lib/rng/rng.h @@ -8,6 +8,7 @@ #ifndef BOTAN_RANDOM_NUMBER_GENERATOR_H__ #define BOTAN_RANDOM_NUMBER_GENERATOR_H__ +#include #include #include #include @@ -19,7 +20,7 @@ namespace Botan { class Entropy_Sources; /** -* An interface to a generic RNG +* An interface to a cryptographic random number generator */ class BOTAN_DLL RandomNumberGenerator { @@ -45,6 +46,8 @@ class BOTAN_DLL RandomNumberGenerator * Incorporate some additional data into the RNG state. For * example adding nonces or timestamps from a peer's protocol * message can help hedge against VM state rollback attacks. + * A few RNG types do not accept any externally provided input, + * in which case this function is a no-op. * * @param inputs a byte array containg the entropy to be added * @param length the length of the byte array in @@ -56,27 +59,41 @@ class BOTAN_DLL RandomNumberGenerator */ template void add_entropy_T(const T& t) { - add_entropy(reinterpret_cast(&t), sizeof(T)); + this->add_entropy(reinterpret_cast(&t), sizeof(T)); } /** - * Incorporate entropy into the RNG state then produce output - * Some RNG types implement this using a single operation. + * Incorporate entropy into the RNG state then produce output. + * Some RNG types implement this using a single operation, default + * calls add_entropy + randomize in sequence. + * + * Use this to further bind the outputs to your current + * process/protocol state. For instance if generating a new key + * for use in a session, include a session ID or other such + * value. See NIST SP 800-90 A, B, C series for more ideas. */ virtual void randomize_with_input(byte output[], size_t output_len, - const byte input[], size_t input_len) - { - this->add_entropy(input, input_len); - this->randomize(output, output_len); - } + const byte input[], size_t input_len); + + /** + * This calls `randomize_with_input` using some timestamps as extra input. + * + * For a stateful RNG using non-random but potentially unique data as the + * additional_input can help protect against problems with fork, VM state + * rollback, or other cases where somehow an RNG state is duplicated. If + * both of the duplicated RNG states later incorporate a timestamp (and the + * timestamps don't themselves repeat), their outputs will diverge. + */ + virtual void randomize_with_ts_input(byte output[], size_t output_len); /** - * Return the name of this object + * Return the name of this RNG type */ virtual std::string name() const = 0; /** - * Clear all internally held values of this RNG. + * Clear all internally held values of this RNG + * @post is_seeded() == false */ virtual void clear() = 0; @@ -91,28 +108,17 @@ class BOTAN_DLL RandomNumberGenerator * or until the timeout expires. Returns estimate of the number * of bits collected. */ - virtual size_t reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout); + virtual size_t reseed(Entropy_Sources& srcs, + size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS, + std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT); /** - * Reseed this RNG from the default entropy sources and a default timeout - * @param bits_to_collect is the number of bits of entropy to - * attempt to gather from the entropy sources - * @param poll_timeout try not to run longer than this, even if - * not enough entropy has been collected + * Reseed by reading specified bits from the RNG */ - size_t reseed(size_t bits_to_collect = BOTAN_RNG_RESEED_POLL_BITS); + virtual void reseed_from_rng(RandomNumberGenerator& rng, + size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS); - /** - * Reseed this RNG from the default entropy sources - * @param bits_to_collect is the number of bits of entropy to - * attempt to gather from the entropy sources - * @param poll_timeout try not to run longer than this, even if - * not enough entropy has been collected - */ - size_t reseed_with_timeout(size_t bits_to_collect, - std::chrono::milliseconds poll_timeout); + // Some utility functions built on the interface above: /** * Return a random vector @@ -122,7 +128,7 @@ class BOTAN_DLL RandomNumberGenerator secure_vector random_vec(size_t bytes) { secure_vector output(bytes); - randomize(output.data(), output.size()); + this->randomize(output.data(), output.size()); return output; } @@ -139,9 +145,9 @@ class BOTAN_DLL RandomNumberGenerator byte next_nonzero_byte() { - byte b = next_byte(); + byte b = this->next_byte(); while(b == 0) - b = next_byte(); + b = this->next_byte(); return b; } @@ -150,64 +156,10 @@ class BOTAN_DLL RandomNumberGenerator * Added in 1.8.0 * Use AutoSeeded_RNG instead */ + BOTAN_DEPRECATED("Use AutoSeeded_RNG") static RandomNumberGenerator* make_rng(); }; -/** -* Inherited by RNGs which maintain in-process state, like HMAC_DRBG. -* On Unix these RNGs are vulnerable to problems with fork, where the -* RNG state is duplicated, and the parent and child process RNGs will -* produce identical output until one of them reseeds. Stateful_RNG -* reseeds itself whenever a fork is detected, or after a set number of -* bytes have been output. -* -* Not implemented by RNGs which access an external RNG, such as the -* system PRNG or a hardware RNG. -*/ -class BOTAN_DLL Stateful_RNG : public RandomNumberGenerator - { - public: - Stateful_RNG(size_t max_output_before_reseed); - - virtual bool is_seeded() const override final; - - /** - * Consume this input and mark the RNG as initialized regardless - * of the length of the input or the current seeded state of - * the RNG. - */ - void initialize_with(const byte input[], size_t length); - - /** - * Poll provided sources for up to poll_bits bits of entropy - * or until the timeout expires. Returns estimate of the number - * of bits collected. - */ - size_t reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout) override; - - protected: - void reseed_check(size_t bytes_requested); - - void clear() override; - - /** - * Mark state as requiring a reseed on next use - */ - void force_reseed() { m_bytes_since_reseed = m_max_output_before_reseed; } - - uint32_t last_pid() const { return m_last_pid; } - - mutable std::mutex m_mutex; - - private: - const size_t m_max_output_before_reseed; - size_t m_bytes_since_reseed = 0; - uint32_t m_last_pid = 0; - bool m_successful_initialization = false; - }; - /** * Convenience typedef */ @@ -271,12 +223,12 @@ class BOTAN_DLL Serialized_RNG final : public RandomNumberGenerator return m_rng->name(); } - size_t reseed_with_sources(Entropy_Sources& src, - size_t bits, - std::chrono::milliseconds msec) override + size_t reseed(Entropy_Sources& src, + size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS, + std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override { std::lock_guard lock(m_mutex); - return m_rng->reseed_with_sources(src, bits, msec); + return m_rng->reseed(src, poll_bits, poll_timeout); } void add_entropy(const byte in[], size_t len) override @@ -285,7 +237,8 @@ class BOTAN_DLL Serialized_RNG final : public RandomNumberGenerator m_rng->add_entropy(in, len); } - Serialized_RNG() : m_rng(RandomNumberGenerator::make_rng()) {} + BOTAN_DEPRECATED("Create an AutoSeeded_RNG for other constructor") Serialized_RNG(); + explicit Serialized_RNG(RandomNumberGenerator* rng) : m_rng(rng) {} private: mutable std::mutex m_mutex; diff --git a/src/lib/rng/stateful_rng/info.txt b/src/lib/rng/stateful_rng/info.txt new file mode 100644 index 000000000..b4dcedf4a --- /dev/null +++ b/src/lib/rng/stateful_rng/info.txt @@ -0,0 +1,2 @@ +define STATEFUL_RNG 20160819 + diff --git a/src/lib/rng/stateful_rng/stateful_rng.cpp b/src/lib/rng/stateful_rng/stateful_rng.cpp new file mode 100644 index 000000000..1349c1208 --- /dev/null +++ b/src/lib/rng/stateful_rng/stateful_rng.cpp @@ -0,0 +1,112 @@ +/* +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include +#include + +namespace Botan { + +void Stateful_RNG::clear() + { + m_reseed_counter = 0; + m_last_pid = 0; + } + +void Stateful_RNG::force_reseed() + { + m_reseed_counter = 0; + } + +bool Stateful_RNG::is_seeded() const + { + return m_reseed_counter > 0; + } + +void Stateful_RNG::initialize_with(const byte input[], size_t len) + { + add_entropy(input, len); + + if(8*len >= security_level()) + { + m_reseed_counter = 1; + } + } + +void Stateful_RNG::randomize_with_ts_input(byte output[], size_t output_len) + { + byte additional_input[24] = { 0 }; + store_le(OS::get_system_timestamp_ns(), additional_input); + store_le(OS::get_processor_timestamp(), additional_input + 8); + store_le(m_last_pid, additional_input + 16); + store_le(static_cast(m_reseed_counter), additional_input + 20); + + randomize_with_input(output, output_len, additional_input, sizeof(additional_input)); + } + +size_t Stateful_RNG::reseed(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) + { + size_t bits_collected = RandomNumberGenerator::reseed(srcs, poll_bits, poll_timeout); + + if(bits_collected >= security_level()) + { + m_reseed_counter = 1; + } + + return bits_collected; + } + +void Stateful_RNG::reseed_from_rng(RandomNumberGenerator& rng, size_t poll_bits) + { + RandomNumberGenerator::reseed_from_rng(rng, poll_bits); + + if(poll_bits >= security_level()) + { + m_reseed_counter = 1; + } + } + +void Stateful_RNG::reseed_check() + { + const uint32_t cur_pid = OS::get_process_id(); + + const bool fork_detected = (m_last_pid > 0) && (cur_pid != m_last_pid); + + if(is_seeded() == false || + fork_detected || + (m_reseed_interval > 0 && m_reseed_counter >= m_reseed_interval)) + { + m_reseed_counter = 0; + m_last_pid = cur_pid; + + if(m_underlying_rng) + { + reseed_from_rng(*m_underlying_rng, security_level()); + } + + if(m_entropy_sources) + { + reseed(*m_entropy_sources, security_level()); + } + + if(!is_seeded()) + { + if(fork_detected) + throw Exception("Detected use of fork but cannot reseed DRBG"); + else + throw PRNG_Unseeded(name()); + } + } + else + { + BOTAN_ASSERT(m_reseed_counter != 0, "RNG is seeded"); + m_reseed_counter += 1; + } + } + +} diff --git a/src/lib/rng/stateful_rng/stateful_rng.h b/src/lib/rng/stateful_rng/stateful_rng.h new file mode 100644 index 000000000..11f0c7e3d --- /dev/null +++ b/src/lib/rng/stateful_rng/stateful_rng.h @@ -0,0 +1,118 @@ +/* +* (C) 2016 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_STATEFUL_RNG_H__ +#define BOTAN_STATEFUL_RNG_H__ + +#include + +namespace Botan { + +/** +* Inherited by RNGs which maintain in-process state, like HMAC_DRBG. +* On Unix these RNGs are vulnerable to problems with fork, where the +* RNG state is duplicated, and the parent and child process RNGs will +* produce identical output until one of them reseeds. Stateful_RNG +* reseeds itself whenever a fork is detected, or after a set number of +* bytes have been output. +* +* Not implemented by RNGs which access an external RNG, such as the +* system PRNG or a hardware RNG. +*/ +class BOTAN_DLL Stateful_RNG : public RandomNumberGenerator + { + public: + Stateful_RNG(RandomNumberGenerator& rng, + Entropy_Sources& entropy_sources, + size_t reseed_interval) : + m_underlying_rng(&rng), + m_entropy_sources(&entropy_sources), + m_reseed_interval(reseed_interval) + {} + + Stateful_RNG(RandomNumberGenerator& rng, size_t reseed_interval) : + m_underlying_rng(&rng), + m_reseed_interval(reseed_interval) + {} + + Stateful_RNG(Entropy_Sources& entropy_sources, size_t reseed_interval) : + m_entropy_sources(&entropy_sources), + m_reseed_interval(reseed_interval) + {} + + /** + * In this case, automatic reseeding is impossible + */ + Stateful_RNG() : m_reseed_interval(0) {} + + /** + * Consume this input and mark the RNG as initialized regardless + * of the length of the input or the current seeded state of + * the RNG. + */ + void initialize_with(const byte input[], size_t length); + + bool is_seeded() const override final; + + /** + * Mark state as requiring a reseed on next use + */ + void force_reseed(); + + void reseed_from_rng(RandomNumberGenerator& rng, + size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS) override final; + + /** + * Overrides default implementation and also includes the current + * process ID and the reseed counter. + */ + void randomize_with_ts_input(byte output[], size_t output_len) override final; + + /** + * Poll provided sources for up to poll_bits bits of entropy + * or until the timeout expires. Returns estimate of the number + * of bits collected. + */ + size_t reseed(Entropy_Sources& srcs, + size_t poll_bits = BOTAN_RNG_RESEED_POLL_BITS, + std::chrono::milliseconds poll_timeout = BOTAN_RNG_RESEED_DEFAULT_TIMEOUT) override; + + /** + * Return intended security level of this DRBG + */ + virtual size_t security_level() const = 0; + + void clear() override; + + protected: + /** + * Called with lock held + */ + void reseed_check(); + + uint32_t last_pid() const { return m_last_pid; } + + private: + // A non-owned and possibly null pointer to shared RNG + RandomNumberGenerator* m_underlying_rng = nullptr; + + // A non-owned and possibly null pointer to a shared Entropy_Source + Entropy_Sources* m_entropy_sources = nullptr; + + const size_t m_reseed_interval; + + /* + * Set to 1 after a sucessful seeding, then incremented. Reset + * to 0 by clear() or a fork. This logic is used even if + * automatic reseeding is disabled (via m_reseed_interval = 0) + */ + size_t m_reseed_counter = 0; + uint32_t m_last_pid = 0; + }; + +} + +#endif diff --git a/src/lib/rng/x931_rng/info.txt b/src/lib/rng/x931_rng/info.txt index b61dc7ec9..4a4418083 100644 --- a/src/lib/rng/x931_rng/info.txt +++ b/src/lib/rng/x931_rng/info.txt @@ -1 +1,5 @@ define X931_RNG 20131128 + + +stateful_rng + diff --git a/src/lib/rng/x931_rng/x931_rng.cpp b/src/lib/rng/x931_rng/x931_rng.cpp index 020d9a5a5..ed44dc743 100644 --- a/src/lib/rng/x931_rng/x931_rng.cpp +++ b/src/lib/rng/x931_rng/x931_rng.cpp @@ -14,7 +14,7 @@ void ANSI_X931_RNG::randomize(byte out[], size_t length) { if(!is_seeded()) { - reseed(BOTAN_RNG_RESEED_POLL_BITS); + rekey(); if(!is_seeded()) throw PRNG_Unseeded(name()); @@ -72,11 +72,11 @@ void ANSI_X931_RNG::rekey() } } -size_t ANSI_X931_RNG::reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout) +size_t ANSI_X931_RNG::reseed(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) { - size_t bits = m_prng->reseed_with_sources(srcs, poll_bits, poll_timeout); + size_t bits = m_prng->reseed(srcs, poll_bits, poll_timeout); rekey(); return bits; } diff --git a/src/lib/rng/x931_rng/x931_rng.h b/src/lib/rng/x931_rng/x931_rng.h index ed7124a08..861fcffde 100644 --- a/src/lib/rng/x931_rng/x931_rng.h +++ b/src/lib/rng/x931_rng/x931_rng.h @@ -16,7 +16,7 @@ namespace Botan { /** * ANSI X9.31 RNG */ -class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator +class BOTAN_DLL ANSI_X931_RNG final : public RandomNumberGenerator { public: void randomize(byte[], size_t) override; @@ -24,9 +24,9 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator void clear() override; std::string name() const override; - size_t reseed_with_sources(Entropy_Sources& srcs, - size_t poll_bits, - std::chrono::milliseconds poll_timeout) override; + size_t reseed(Entropy_Sources& srcs, + size_t poll_bits, + std::chrono::milliseconds poll_timeout) override; void add_entropy(const byte[], size_t) override; @@ -35,6 +35,7 @@ class BOTAN_DLL ANSI_X931_RNG : public RandomNumberGenerator * @param rng the underlying PRNG for generating inputs * (eg, an HMAC_RNG) */ + BOTAN_DEPRECATED("X9.31 RNG is deprecated and will be removed soon") ANSI_X931_RNG(BlockCipher* cipher, RandomNumberGenerator* rng); diff --git a/src/lib/utils/os_utils.cpp b/src/lib/utils/os_utils.cpp index 86776bdd0..c00c898a3 100644 --- a/src/lib/utils/os_utils.cpp +++ b/src/lib/utils/os_utils.cpp @@ -19,7 +19,7 @@ #include #endif -#if defined(BOTAN_TARGET_OS_TYPE_IS_WINDOWS) +#if defined(BOTAN_TARGET_OS_IS_WINDOWS) #include #endif @@ -29,12 +29,12 @@ namespace OS { uint32_t get_process_id() { -#if defined(BOTAN_TARGET_OS_IS_UNIX) +#if defined(BOTAN_TARGET_OS_TYPE_IS_UNIX) return ::getpid(); #elif defined(BOTAN_TARGET_OS_IS_WINDOWS) return ::GetCurrentProcessId(); #else - return 0; + throw Exception("get_process_id not supported"); #endif } diff --git a/src/lib/utils/os_utils.h b/src/lib/utils/os_utils.h index 3335463f7..590ed4ae7 100644 --- a/src/lib/utils/os_utils.h +++ b/src/lib/utils/os_utils.h @@ -15,7 +15,7 @@ namespace Botan { namespace OS { /** -* Returns the OS assigned process ID, if available. Otherwise returns 0. +* Returns the OS assigned process ID, if available. Otherwise throws. */ uint32_t get_process_id(); diff --git a/src/tests/main.cpp b/src/tests/main.cpp index 79be98a0e..07aaac519 100644 --- a/src/tests/main.cpp +++ b/src/tests/main.cpp @@ -15,8 +15,8 @@ #include #include -#include #include +#include #if defined(BOTAN_HAS_HMAC_DRBG) #include @@ -26,6 +26,10 @@ #include #endif +#if defined(BOTAN_HAS_AUTO_SEEDING_RNG) + #include +#endif + namespace { class Test_Runner : public Botan_CLI::Command @@ -140,7 +144,14 @@ class Test_Runner : public Botan_CLI::Command } output() << " rng:HMAC_DRBG with seed '" << Botan::hex_encode(seed) << "'"; - std::unique_ptr drbg(new Botan::HMAC_DRBG("SHA-384", 0)); + + // Expand out the seed to 512 bits to make the DRBG happy + std::unique_ptr sha512(Botan::HashFunction::create("SHA-512")); + sha512->update(seed); + seed.resize(sha512->output_length()); + sha512->final(seed.data()); + + std::unique_ptr drbg(new Botan::HMAC_DRBG("SHA-384")); drbg->initialize_with(seed.data(), seed.size()); rng.reset(new Botan::Serialized_RNG(drbg.release())); @@ -152,16 +163,19 @@ class Test_Runner : public Botan_CLI::Command #if defined(BOTAN_HAS_SYSTEM_RNG) output() << " rng:system"; rng.reset(new Botan::System_RNG); -#else - // AutoSeeded_RNG always available +#elif defined(BOTAN_HAS_AUTO_SEEDING_RNG) output() << " rng:autoseeded"; rng.reset(new Botan::Serialized_RNG(new Botan::AutoSeeded_RNG)); #endif #endif - output() << "\n"; + if(rng.get() == nullptr) + { + throw Botan_Tests::Test_Error("No usable RNG enabled in build, aborting tests"); + } + Botan_Tests::Test::setup_tests(soak_level, log_success, data_dir, pkcs11_lib, rng.get()); const size_t failed = run_tests(req, output(), threads); diff --git a/src/tests/test_mceliece.cpp b/src/tests/test_mceliece.cpp index 8658bf5e6..5e3501b3e 100644 --- a/src/tests/test_mceliece.cpp +++ b/src/tests/test_mceliece.cpp @@ -67,7 +67,7 @@ class McEliece_Keygen_Encrypt_Test : public Text_Based_Test const size_t keygen_n = get_req_sz(vars, "KeyN"); const size_t keygen_t = get_req_sz(vars, "KeyT"); - Botan::HMAC_DRBG rng("SHA-384", 0); + Botan::HMAC_DRBG rng("SHA-384"); rng.initialize_with(keygen_seed.data(), keygen_seed.size()); Botan::McEliece_PrivateKey mce_priv(rng, keygen_n, keygen_t); diff --git a/src/tests/test_pkcs11_high_level.cpp b/src/tests/test_pkcs11_high_level.cpp index 8e894ef28..e8c19224e 100644 --- a/src/tests/test_pkcs11_high_level.cpp +++ b/src/tests/test_pkcs11_high_level.cpp @@ -1346,18 +1346,12 @@ Test::Result test_pkcs11_hmac_drbg() Test::Result result("PKCS11 HMAC_DRBG using PKCS11_RNG"); TestSession test_session(true); - // FIXME: this is only a temporary fix - // It should be possible to instantiate HMAC_DRBG with PKCS11_RNG and - // HMAC_DRBG should reseed itself from PKCS11_RNG - HMAC_DRBG drbg(MessageAuthenticationCode::create("HMAC(SHA-512)").release()); + PKCS11_RNG p11_rng(test_session.session()); + HMAC_DRBG drbg(MessageAuthenticationCode::create("HMAC(SHA-512)"), p11_rng); // result.test_success("HMAC_DRBG(HMAC(SHA512)) instantiated with PKCS11_RNG"); result.test_eq("HMAC_DRBG is not seeded yet.", drbg.is_seeded(), false); - - PKCS11_RNG p11_rng(test_session.session()); - secure_vector rnd = p11_rng.random_vec(64); - - drbg.initialize_with(rnd.data(), rnd.size()); + secure_vector rnd = drbg.random_vec(64); result.test_eq("HMAC_DRBG is seeded now", drbg.is_seeded(), true); std::string personalization_string = "Botan PKCS#11 Tests"; diff --git a/src/tests/test_rng.cpp b/src/tests/test_rng.cpp index ab5a38135..3368ab52b 100644 --- a/src/tests/test_rng.cpp +++ b/src/tests/test_rng.cpp @@ -1,5 +1,6 @@ /* * (C) 2014,2015 Jack Lloyd +* (C) 2016 RenĂ© Korthaus, Rohde & Schwarz Cybersecurity * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -15,6 +16,17 @@ #include #endif +#if defined(BOTAN_HAS_ENTROPY_SOURCE) + #include +#endif + +#if defined(BOTAN_TARGET_OS_TYPE_IS_UNIX) + #include + #include +#endif + +#include + namespace Botan_Tests { namespace { @@ -81,7 +93,7 @@ class HMAC_DRBG_Tests : public Text_Based_Test return result; } - std::unique_ptr rng(new Botan::HMAC_DRBG(mac.release(), 0)); + std::unique_ptr rng(new Botan::HMAC_DRBG(std::move(mac))); rng->initialize_with(seed_input.data(), seed_input.size()); // now reseed @@ -100,23 +112,69 @@ class HMAC_DRBG_Tests : public Text_Based_Test BOTAN_REGISTER_TEST("hmac_drbg", HMAC_DRBG_Tests); -class HMAC_DRBG_Reseed_Tests : public Test +class HMAC_DRBG_Unit_Tests : public Test { - public: - HMAC_DRBG_Reseed_Tests() : Test() {} + private: + class Broken_Entropy_Source : public Botan::Entropy_Source + { + public: + std::string name() const override { return "Broken Entropy Source"; } - std::vector run() override + size_t poll(Botan::RandomNumberGenerator&) override + { + throw Botan::Exception("polling not available"); + } + }; + + class Insufficient_Entropy_Source : public Botan::Entropy_Source { - Test::Result result("HMAC_DRBG Reseed"); + public: + std::string name() const override { return "Insufficient Entropy Source"; } + + size_t poll(Botan::RandomNumberGenerator&) override + { + return 0; + } + }; + + class Request_Counting_RNG : public Botan::RandomNumberGenerator + { + public: + Request_Counting_RNG() : m_randomize_count(0) {}; + + bool is_seeded() const override { return true; } + + void clear() override {} + + void randomize(byte[], size_t) override + { + m_randomize_count++; + } + + void add_entropy(const byte[], size_t) override {} + + std::string name() const override { return "Request_Counting_RNG"; } + + size_t randomize_count() { return m_randomize_count; } + + private: + size_t m_randomize_count; + }; + + public: + Test::Result test_reseed_kat() + { + Test::Result result("HMAC_DRBG Reseed KAT"); auto mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); if(!mac) { result.note_missing("HMAC(SHA-256)"); - return {result}; + return result; } - Botan::HMAC_DRBG rng(mac.release(), 17); + Request_Counting_RNG counting_rng; + Botan::HMAC_DRBG rng(std::move(mac), counting_rng, Botan::Entropy_Sources::global_sources(), 2); Botan::secure_vector seed_input( {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}); Botan::secure_vector output_after_initialization( @@ -130,16 +188,273 @@ class HMAC_DRBG_Reseed_Tests : public Test Botan::secure_vector out(16); rng.randomize(out.data(), out.size()); + result.test_eq("underlying RNG calls", counting_rng.randomize_count(), size_t(0)); result.test_eq("out before reseed", out, output_after_initialization); - // reseed must happend here + // reseed must happen here rng.randomize(out.data(), out.size()); + result.test_eq("underlying RNG calls", counting_rng.randomize_count(), size_t(1)); result.test_ne("out after reseed", out, output_without_reseed); - return {result}; + + return result; + } + + Test::Result test_reseed() + { + Test::Result result("HMAC_DRBG Reseed"); + + auto mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + if(!mac) + { + result.note_missing("HMAC(SHA-256)"); + return result; + } + + // test reseed_interval is enforced + Request_Counting_RNG counting_rng; + Botan::HMAC_DRBG rng(std::move(mac), counting_rng, 2); + + rng.random_vec(7); + result.test_eq("initial seeding", counting_rng.randomize_count(), 1); + rng.random_vec(9); + result.test_eq("still initial seed", counting_rng.randomize_count(), 1); + + rng.random_vec(1); + result.test_eq("first reseed", counting_rng.randomize_count(), 2); + rng.random_vec(15); + result.test_eq("still first reseed", counting_rng.randomize_count(), 2); + + rng.random_vec(15); + result.test_eq("second reseed", counting_rng.randomize_count(), 3); + rng.random_vec(1); + result.test_eq("still second reseed", counting_rng.randomize_count(), 3); + + // request > max_number_of_bits_per_request, do reseeds occur? + rng.random_vec(64*1024 + 1); + result.test_eq("request exceeds output limit", counting_rng.randomize_count(), 4); + + rng.random_vec(9*64*1024 + 1); + result.test_eq("request exceeds output limit", counting_rng.randomize_count(), 9); + + return result; + } + + Test::Result test_broken_entropy_input() + { + Test::Result result("HMAC_DRBG Broken Entropy Input"); + + auto mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + if(!mac) + { + result.note_missing("HMAC(SHA-256)"); + return result; + } + + // make sure no output is generated when the entropy input source is broken + + const size_t reseed_interval = 1024; + + // underlying_rng throws exception + Botan::Null_RNG broken_entropy_input_rng; + Botan::HMAC_DRBG rng_with_broken_rng(std::move(mac), broken_entropy_input_rng, reseed_interval); + + result.test_throws("broken underlying rng", [&rng_with_broken_rng] () { rng_with_broken_rng.random_vec(16); }); + + // entropy_sources throw exception + std::unique_ptr broken_entropy_source_1(new Broken_Entropy_Source()); + std::unique_ptr broken_entropy_source_2(new Broken_Entropy_Source()); + + Botan::Entropy_Sources broken_entropy_sources; + broken_entropy_sources.add_source(std::move(broken_entropy_source_1)); + broken_entropy_sources.add_source(std::move(broken_entropy_source_2)); + + mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + Botan::HMAC_DRBG rng_with_broken_es(std::move(mac), broken_entropy_sources, reseed_interval); + result.test_throws("broken entropy sources", [&rng_with_broken_es] () { rng_with_broken_es.random_vec(16); }); + + // entropy source returns insufficient entropy + Botan::Entropy_Sources insufficient_entropy_sources; + std::unique_ptr insufficient_entropy_source(new Insufficient_Entropy_Source()); + insufficient_entropy_sources.add_source(std::move(insufficient_entropy_source)); + + mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + Botan::HMAC_DRBG rng_with_insufficient_es(std::move(mac), insufficient_entropy_sources, reseed_interval); + result.test_throws("insufficient entropy source", [&rng_with_insufficient_es] () { rng_with_insufficient_es.random_vec(16); }); + + // one of or both underlying_rng and entropy_sources throw exception + mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + Botan::HMAC_DRBG rng_with_broken_rng_and_es(std::move(mac), broken_entropy_input_rng, + Botan::Entropy_Sources::global_sources(), reseed_interval); + result.test_throws("broken underlying rng but good entropy sources", [&rng_with_broken_rng_and_es] () + { rng_with_broken_rng_and_es.random_vec(16); }); + + mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + Botan::HMAC_DRBG rng_with_rng_and_broken_es(std::move(mac), Test::rng(), broken_entropy_sources, reseed_interval); + result.test_throws("good underlying rng but broken entropy sources", [&rng_with_rng_and_broken_es] () + { rng_with_rng_and_broken_es.random_vec(16); }); + + mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + Botan::HMAC_DRBG rng_with_broken_rng_and_broken_es(std::move(mac), broken_entropy_input_rng, broken_entropy_sources, reseed_interval); + result.test_throws("underlying rng and entropy sources broken", [&rng_with_broken_rng_and_broken_es] () + { rng_with_broken_rng_and_broken_es.random_vec(16); }); + + return result; + } + + Test::Result test_check_nonce() + { + Test::Result result("HMAC_DRBG Nonce Check"); + + auto mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + if(!mac) + { + result.note_missing("HMAC(SHA-256)"); + return result; + } + + // make sure the nonce has at least 1/2*security_strength bits + + // SHA-256 -> 128 bits security strength + for( auto nonce_size : { 0, 4, 15, 16, 17, 32 } ) + { + if(!mac) + { + mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + } + + Botan::HMAC_DRBG rng(std::move(mac)); + result.test_eq("not seeded", rng.is_seeded(), false); + std::vector nonce(nonce_size); + rng.initialize_with(nonce.data(), nonce.size()); + + if(nonce_size < 16) + { + result.test_eq("not seeded", rng.is_seeded(), false); + result.test_throws("invalid nonce size", [&rng, &nonce] () { rng.random_vec(16); }); + } + else + { + result.test_eq("is seeded", rng.is_seeded(), true); + rng.random_vec(16); + } + } + + return result; + } + + Test::Result test_prediction_resistance() + { + Test::Result result("HMAC_DRBG Prediction Resistance"); + + auto mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + if(!mac) + { + result.note_missing("HMAC(SHA-256)"); + return result; + } + + // set max_output_before_reseed = 1, forcing a reseed on every request + Request_Counting_RNG counting_rng; + Botan::HMAC_DRBG rng(std::move(mac), counting_rng, 1); + + rng.random_vec(16); + result.test_eq("first request", counting_rng.randomize_count(), size_t(1)); + + rng.random_vec(16); + result.test_eq("second request", counting_rng.randomize_count(), size_t(2)); + + rng.random_vec(16); + result.test_eq("third request", counting_rng.randomize_count(), size_t(3)); + + return result; + } + + Test::Result test_fork_safety() + { + Test::Result result("HMAC_DRBG Fork Safety"); + +#if defined(BOTAN_TARGET_OS_TYPE_IS_UNIX) + auto mac = Botan::MessageAuthenticationCode::create("HMAC(SHA-256)"); + if(!mac) + { + result.note_missing("HMAC(SHA-256)"); + return result; + } + + const size_t reseed_interval = 1024; + + // make sure rng is reseeded after every fork + Request_Counting_RNG counting_rng; + Botan::HMAC_DRBG rng(std::move(mac), counting_rng, reseed_interval); + + rng.random_vec(16); + result.test_eq("first request", counting_rng.randomize_count(), size_t(1)); + + // fork and request from parent and child, both should output different sequences + size_t count = counting_rng.randomize_count(); + Botan::secure_vector parent_bytes(16), child_bytes(16); + int fd[2]; + int rc = pipe(fd); + if(rc != 0) + { + result.test_failure("failed to create pipe"); + } + + pid_t pid = fork(); + if ( pid == -1 ) + { + result.test_failure("failed to fork process"); + return result; + } + else if ( pid != 0 ) + { + // parent process, wait for randomize_count from child's rng + close(fd[1]); + read(fd[0], &count, sizeof(count)); + close(fd[0]); + + + result.test_eq("parent not reseeded", counting_rng.randomize_count(), 1); + result.test_eq("child reseed occurred", count, 2); + + parent_bytes = rng.random_vec(16); + read(fd[0], &child_bytes[0], child_bytes.size()); + result.test_ne("parent and child output sequences differ", parent_bytes, child_bytes); + close(fd[0]); + + int status = 0; + ::waitpid(pid, &status, 0); + } + else + { + // child process, send randomize_count and first output sequence back to parent + close(fd[0]); + rng.randomize(&child_bytes[0], child_bytes.size()); + count = counting_rng.randomize_count(); + write(fd[1], &count, sizeof(count)); + rng.randomize(&child_bytes[0], child_bytes.size()); + write(fd[1], &child_bytes[0], child_bytes.size()); + close(fd[1]); + _exit(0); + } +#endif + return result; + } + + std::vector run() override + { + std::vector results; + results.push_back(test_reseed_kat()); + results.push_back(test_reseed()); + results.push_back(test_broken_entropy_input()); + results.push_back(test_check_nonce()); + results.push_back(test_prediction_resistance()); + results.push_back(test_fork_safety()); + return results; } }; -BOTAN_REGISTER_TEST("hmac_drbg_reseed", HMAC_DRBG_Reseed_Tests); +BOTAN_REGISTER_TEST("hmac_drbg_unit", HMAC_DRBG_Unit_Tests); #endif diff --git a/src/tests/test_rng.h b/src/tests/test_rng.h index 6c29b1d55..0379a2ee9 100644 --- a/src/tests/test_rng.h +++ b/src/tests/test_rng.h @@ -15,13 +15,6 @@ #include #include -#if defined(BOTAN_HAS_SYSTEM_RNG) - #include -#else - #include -#endif - - namespace Botan_Tests { /** @@ -43,9 +36,9 @@ class Fixed_Output_RNG : public Botan::RandomNumberGenerator return out; } - size_t reseed_with_sources(Botan::Entropy_Sources&, - size_t, - std::chrono::milliseconds) override { return 0; } + size_t reseed(Botan::Entropy_Sources&, + size_t, + std::chrono::milliseconds) override { return 0; } void randomize(uint8_t out[], size_t len) override { @@ -87,7 +80,7 @@ class Fixed_Output_RNG : public Botan::RandomNumberGenerator class Fixed_Output_Position_RNG : public Fixed_Output_RNG { public: - bool is_seeded() const override { return !m_buf.empty() || m_rng->is_seeded(); } + bool is_seeded() const override { return !m_buf.empty() || Test::rng().is_seeded(); } uint8_t random() override { @@ -114,7 +107,7 @@ class Fixed_Output_Position_RNG : public Fixed_Output_RNG } else { // return random - m_rng->randomize(out,len); + Test::rng().randomize(out,len); } } @@ -127,32 +120,19 @@ class Fixed_Output_Position_RNG : public Fixed_Output_RNG explicit Fixed_Output_Position_RNG(const std::vector& in, uint32_t pos) : Fixed_Output_RNG(in), - m_pos(pos), - m_rng{} + m_pos(pos) { -#if defined(BOTAN_HAS_SYSTEM_RNG) - m_rng.reset(new Botan::System_RNG); -#else - m_rng.reset(new Botan::AutoSeeded_RNG); -#endif } explicit Fixed_Output_Position_RNG(const std::string& in_str, uint32_t pos) : Fixed_Output_RNG(in_str), - m_pos(pos), - m_rng{} + m_pos(pos) { -#if defined(BOTAN_HAS_SYSTEM_RNG) - m_rng.reset(new Botan::System_RNG); -#else - m_rng.reset(new Botan::AutoSeeded_RNG); -#endif } private: uint32_t m_pos = 0; uint32_t m_requests = 0; - std::unique_ptr m_rng; }; class SeedCapturing_RNG : public Botan::RandomNumberGenerator diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp index d3467460e..a6f96144c 100644 --- a/src/tests/tests.cpp +++ b/src/tests/tests.cpp @@ -127,7 +127,7 @@ bool Test::Result::test_ne(const std::string& what, const uint8_t expected[], size_t expected_len) { if(produced_len == expected_len && Botan::same_mem(produced, expected, expected_len)) - return test_failure(who() + ":" + what + " produced matching"); + return test_failure(who() + ": " + what + " produced matching"); return test_success(); } -- cgit v1.2.3 From bc647fd495eba07dd893f0247d9912852aa499d7 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Wed, 24 Aug 2016 12:26:29 -0400 Subject: Add release notes for 1.8.15 which escaped news.rst [ci skip] --- doc/news.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index 6e9b88479..5b4cef681 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -296,6 +296,19 @@ Version 1.11.29, 2016-03-20 * Support for locking allocator on Windows using VirtualLock. GH #450 +Version 1.18.15, 2016-02-13 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* NOTE WELL: Botan 1.8 is not supported for security issues anymore. + Moving to 1.10 or 1.11 is certainly recommended. +* Fix CVE-2014-9742: Insufficient randomness in Miller-Rabin primality check +* Fix CVE-2016-2194: Infinite loop in modulur square root algorithm +* Fix CVE-2015-5726: Crash in BER decoder +* Fix CVE-2015-5727: Excess memory allocation in BER decoder + Note: Unlike the fix in 1.10 which checks that the source actually + contains enough data to satisfy the read before allocating the + memory, 1.8.15 simply rejects all ASN.1 blocks larger than 1 MiB. + This simpler check avoids the problem without breaking ABI. + Version 1.10.12, 2016-02-03 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit v1.2.3 From c3824edd7e02825182feb2d62df77394444c79da Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Wed, 24 Aug 2016 12:53:45 -0400 Subject: git notes [ci skip] --- doc/contributing.rst | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'doc') diff --git a/doc/contributing.rst b/doc/contributing.rst index 0d160c680..64b609af5 100644 --- a/doc/contributing.rst +++ b/doc/contributing.rst @@ -112,9 +112,11 @@ Sending patches ======================================== All contributions should be submitted as pull requests via GitHub -(https://github.com/randombit/botan). If you are planning a large change email -the mailing list or open a discussion ticket on github before starting out to -make sure you are on the right path. +(https://github.com/randombit/botan). If you are planning a large +change email the mailing list or open a discussion ticket on github +before starting out to make sure you are on the right path. And once +you have something written, free to open a [WIP] PR for early review +and comment. If possible please sign your git commits using a PGP key. See https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work for @@ -136,6 +138,21 @@ Also, try building and testing it on whatever hardware you have handy, especially non-x86 platforms, or especially C++11 compilers other than the regularly tested GCC, Clang, and Visual Studio compilers. +Git Usage +======================================== + +Do *NOT* merge ``master`` into your topic branch, this creates +needless commits and noise in history. Instead, as needed, rebase your +branch against master (``git rebase -i master``) and force push the +branch to update the PR. If the GitHub PR page does not report any +merge conflicts and nobody asks you to rebase, you don't need to +rebase. + +Try to keep your history clean and use rebase to squash your commits +as needed. If your diff is less than roughly 100 lines, it should +probably be a single commit. Only split commits as needed to help with +review/understanding of the change. + External Dependencies ======================================== -- cgit v1.2.3 From 949ff42b3bb0ff4751b414aad5fcbe90d8d26d99 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Wed, 24 Aug 2016 13:15:18 -0400 Subject: Update release notes [ci skip] --- doc/news.rst | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index 5b4cef681..b5cfa86ab 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -36,20 +36,56 @@ Version 1.11.31, Not Yet Released * Add FRP256v1 curve (GH #551) * RNG changes: NIST SP900-80's HMAC_DRBG is now the default generator - for userspace RNG (AutoSeeded_RNG). HMAC_DRBG now attempts to detect - use of fork (via pid checks) + for userspace RNG (in AutoSeeded_RNG). HMAC_DRBG now attempts to detect + use of fork via pid checks and perform automatic reseeding. + GH #520 -* The X9.31 and HMAC_RNG RNGs are deprecated and will be removed in a - future release. If you need a userspace PRNG switch to HMAC_DRBG - (or AutoSeeded_RNG which is HMAC_DRBG with useful defaults). +* Add RDRAND_RNG which directly exposes the CPU RNG (GH #543) + +* Add PKCS #1 v1.5 id for SHA-512/256 (GH #554) + +* Add X509_Time::to_std_timepoint (GH #560) * Fix a bug in ANSI X9.23 padding mode, which returned one byte more than the given block size (GH #529). -* Fixes for FreeBSD (GH #517) and OpenBSD (GH #523) +* Fix bug in SipHash::clear, which did not reset all state (GH #547) + +* Fixes for FreeBSD (GH #517) and OpenBSD (GH #523). The compiler defaults + to Clang on FreeBSD now. + +* SonarQube static analysis integration (GH #592) + +* Switched Travis CI to Ubuntu 14.04 LTS (GH #592) + +* Clean up in TLS ciphersuite handling (GH #583) + +* Threefish-512 AVX2 optimization work (GH #581) + +* Remove build configuration host and timestamp from build.h + This makes this header reproducible and allows using ccache's direct mode + (GH #586 see also #587) + +* Prevent building for x86-64 with x86-32 compiler and the reverse (GH #585) + +* Avoid build problem on 32-bit userspace ARMv8 (GH #563) + +* Refactor of internal MP headers (GH #549) + +* Avoid MSVC C4100 warning (GH #525) + +* More tests for RSA-KEM (GH #538), DH (GH #556), EME (GH #553), + cipher mode padding (GH #529), CTS mode (GH #531), + KDF1/ISO18033 (GH #537), OctetString (GH #545), OIDs (GH #546), + parallel hash (GH #548), charset handling (GH #555), + BigInt (GH #558) * New deprecations. See the full list in doc/deprecated.txt + The X9.31 and HMAC_RNG RNGs are deprecated. + If you need a userspace PRNG, use HMAC_DRBG (or AutoSeeded_RNG + which is HMAC_DRBG with defaults). + Support for getting entropy from EGD is deprecated, and will be removed in a future release. The developers believe that it is unlikely that any modern system requires EGD and so the code is now -- cgit v1.2.3 From 2e2e8a274f75e639809e95405d5284bcf095cd3e Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Mon, 29 Aug 2016 10:57:43 -0400 Subject: Update release notes --- doc/news.rst | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index b5cfa86ab..5837a8af9 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -35,10 +35,23 @@ Version 1.11.31, Not Yet Released * Add FRP256v1 curve (GH #551) -* RNG changes: NIST SP900-80's HMAC_DRBG is now the default generator - for userspace RNG (in AutoSeeded_RNG). HMAC_DRBG now attempts to detect - use of fork via pid checks and perform automatic reseeding. - GH #520 +* Changes for userspace PRNGs HMAC_DRBG and HMAC_RNG (GH #520 and #593) + + These RNGs now derive from Stateful_RNG which handles issues like periodic + reseeding and (on Unix) detecting use of fork. Previously these measures were + included only in HMAC_RNG. + + Stateful_RNG allows reseeding from another RNG and/or a specified set of + entropy sources. For example it is possible to configure a HMAC_DRBG to reseed + using a PKCS #11 token RNG, the CPU's RDSEED instruction, and the system RNG + but disabling all other entropy polls. + +* AutoSeeded_RNG now uses NIST SP800-90a HMAC_DRBG(SHA-384). (GH #520) + +* On Windows and Unix systems, the system PRNG is used as the sole reseeding + source for a default AutoSeeded_RNG, completely skipping the standard entropy + polling code. New constructors allow specifying the reseed RNG and/or entropy + sources. (GH #520) * Add RDRAND_RNG which directly exposes the CPU RNG (GH #543) @@ -58,6 +71,8 @@ Version 1.11.31, Not Yet Released * Switched Travis CI to Ubuntu 14.04 LTS (GH #592) +* Added ARM32, ARM64, PPC32, PPC64, and MinGW x86 cross compile targets to Travis CI (GH #608) + * Clean up in TLS ciphersuite handling (GH #583) * Threefish-512 AVX2 optimization work (GH #581) @@ -74,11 +89,13 @@ Version 1.11.31, Not Yet Released * Avoid MSVC C4100 warning (GH #525) +* Change botan.exe to botan-cli.exe on Windows to workaround VC issue (GH #584) + * More tests for RSA-KEM (GH #538), DH (GH #556), EME (GH #553), cipher mode padding (GH #529), CTS mode (GH #531), KDF1/ISO18033 (GH #537), OctetString (GH #545), OIDs (GH #546), parallel hash (GH #548), charset handling (GH #555), - BigInt (GH #558) + BigInt (GH #558), HMAC_DRBG (GH #598 #600) * New deprecations. See the full list in doc/deprecated.txt -- cgit v1.2.3 From fd12f8400adacdf66f00a6bf17dd47eac8a580cd Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Tue, 30 Aug 2016 08:50:26 -0400 Subject: Add ECIES to news [ci skip] --- doc/news.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index 5837a8af9..ca7686725 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -23,13 +23,15 @@ Version 1.11.31, Not Yet Released XOR-encrypion/decryption mode it's now possible to use DLIES with a block cipher. Furthermore the order of the output was changed from {public key, tag, ciphertext} to {public key, ciphertext, tag}. Both - modes are compatible with bouncycastle. + modes are compatible with BouncyCastle. * Add initial PKCS #11 support (GH #507). Currently includes a low level wrapper to all of PKCS #11 (p11.h) and high level code for RSA and ECDSA signatures and hardware RNG access. -* Add ECKCDSA signature algorithm (#504) +* Add ECIES encryption scheme, compatible with BouncyCastle (GH #483) + +* Add ECKCDSA signature algorithm (GH #504) * Add KDF1 from ISO 18033 (GH #483) -- cgit v1.2.3 From 48a1bd58cb188141845082196b684ec5ed1dd635 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Tue, 30 Aug 2016 11:58:28 -0400 Subject: Update todo [ci skip] --- doc/todo.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'doc') diff --git a/doc/todo.rst b/doc/todo.rst index b6c55a898..c0ebe6e8d 100644 --- a/doc/todo.rst +++ b/doc/todo.rst @@ -22,7 +22,6 @@ CLI for an example * `encrypt` / `decrypt` tools providing password and/or public key based file encryption -* `bcrypt` cmdlet * Make help output more helpful * More microbenchmarks in `speed`: modular exponentiation, ECC point multiplication, other BigInt operations @@ -34,6 +33,7 @@ TLS * Make DTLS support optional at build time * Make TLS v1.0 and v1.1 optional at build time * Curve25519 key exchange +* NEWHOPE (CECPQ1) key exchange (GH #613) * TLS OCSP stapling (RFC 6066) * Encrypt-then-MAC extension (RFC 7366) * Authentication using TOFU (sqlite3 storage) @@ -47,6 +47,7 @@ TLS PKIX ---------------------------------------- +* Test suite for validation of 'real world' cert chains (GH #611) * Support multiple DNS names in certificates * X.509 policy constraints * OCSP responder logic @@ -109,7 +110,6 @@ Public Key Crypto, Math * XMSS (draft-irtf-cfrg-xmss-hash-based-signatures) * SPHINCS-256 -* NEWHOPE RLWE scheme + BoringSSL compatible TLS cipher suites * EdDSA (GH #283) * Ed448-Goldilocks * FHMQV -- cgit v1.2.3 From 5e946f93e8e751d2104f58583d4f209ca631aff1 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Tue, 30 Aug 2016 14:18:37 -0400 Subject: Update for 1.11.31 release --- doc/news.rst | 2 +- doc/security.rst | 18 ++++++++++++++++++ readme.rst | 6 +++--- 3 files changed, 22 insertions(+), 4 deletions(-) (limited to 'doc') diff --git a/doc/news.rst b/doc/news.rst index ca7686725..711f982a8 100644 --- a/doc/news.rst +++ b/doc/news.rst @@ -1,7 +1,7 @@ Release Notes ======================================== -Version 1.11.31, Not Yet Released +Version 1.11.31, 2016-08-30 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Fix undefined behavior in Curve25519 on platforms without a native 128-bit diff --git a/doc/security.rst b/doc/security.rst index 23b46f30d..6223943e0 100644 --- a/doc/security.rst +++ b/doc/security.rst @@ -19,6 +19,24 @@ Advisories 2016 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* 2016-08-30 (CVE-2016-6878) Undefined behavior in Curve25519 + + On systems without a native 128-bit integer type, the Curve25519 code invoked + undefined behavior. This was known to produce incorrect results on 32-bit ARM + when compiled by Clang. + + Introduced in 1.11.12, fixed in 1.11.31 + +* 2016-08-30 (CVE-2016-6879) Bad result from X509_Certificate::allowed_usage + + If allowed_usage was called with more than one Key_Usage set in the enum + value, the function would return true if *any* of the allowed usages were set, + instead of if *all* of the allowed usages are set. This could be used to + bypass an application key usage check. Credit to Daniel Neus of Rohde & + Schwarz Cybersecurity for finding this issue. + + Introduced in 1.11.0, fixed in 1.11.31 + * 2016-03-17 (CVE-2016-2849): ECDSA side channel ECDSA (and DSA) signature algorithms perform a modular inverse on the diff --git a/readme.rst b/readme.rst index 2f6134ba8..35f58d159 100644 --- a/readme.rst +++ b/readme.rst @@ -100,9 +100,9 @@ Versions 1.11 and later require a working C++11 compiler; GCC 4.8 and later, Clang 3.4 and later, and MSVC 2013 are regularly tested. The latest development release is -`1.11.30 `_ -`(sig) `_ -released on 2016-06-19 +`1.11.31 `_ +`(sig) `_ +released on 2016-08-30 Old Stable Series (1.10) ---------------------------------------- -- cgit v1.2.3