From dbe3754faf68687ccf58743d6f500d36e6419e77 Mon Sep 17 00:00:00 2001 From: Jack Lloyd Date: Mon, 19 Oct 2015 19:25:28 -0400 Subject: Break up openssl provider For RSA, RC4, and ECDSA put the openssl versions in the same directory as the base version. They just rely on a macro check for the openssl module to test for the desire to use OpenSSL. --- src/lib/block/openssl_block/info.txt | 5 + src/lib/block/openssl_block/openssl_block.cpp | 214 +++++++++++++++++++ src/lib/hash/openssl_hash/info.txt | 5 + src/lib/hash/openssl_hash/openssl_hash.cpp | 117 ++++++++++ src/lib/pubkey/ecdsa/openssl_ecdsa.cpp | 213 ++++++++++++++++++ src/lib/pubkey/rsa/openssl_rsa.cpp | 297 ++++++++++++++++++++++++++ src/lib/stream/rc4/openssl_rc4.cpp | 61 ++++++ src/lib/utils/openssl/info.txt | 16 ++ src/lib/utils/openssl/openssl.h | 35 +++ src/lib/vendor/openssl/info.txt | 11 - src/lib/vendor/openssl/openssl.h | 36 ---- src/lib/vendor/openssl/openssl_block.cpp | 216 ------------------- src/lib/vendor/openssl/openssl_ecdsa.cpp | 207 ------------------ src/lib/vendor/openssl/openssl_hash.cpp | 117 ---------- src/lib/vendor/openssl/openssl_rc4.cpp | 56 ----- src/lib/vendor/openssl/openssl_rsa.cpp | 297 -------------------------- 16 files changed, 963 insertions(+), 940 deletions(-) create mode 100644 src/lib/block/openssl_block/info.txt create mode 100644 src/lib/block/openssl_block/openssl_block.cpp create mode 100644 src/lib/hash/openssl_hash/info.txt create mode 100644 src/lib/hash/openssl_hash/openssl_hash.cpp create mode 100644 src/lib/pubkey/ecdsa/openssl_ecdsa.cpp create mode 100644 src/lib/pubkey/rsa/openssl_rsa.cpp create mode 100644 src/lib/stream/rc4/openssl_rc4.cpp create mode 100644 src/lib/utils/openssl/info.txt create mode 100644 src/lib/utils/openssl/openssl.h delete mode 100644 src/lib/vendor/openssl/info.txt delete mode 100644 src/lib/vendor/openssl/openssl.h delete mode 100644 src/lib/vendor/openssl/openssl_block.cpp delete mode 100644 src/lib/vendor/openssl/openssl_ecdsa.cpp delete mode 100644 src/lib/vendor/openssl/openssl_hash.cpp delete mode 100644 src/lib/vendor/openssl/openssl_rc4.cpp delete mode 100644 src/lib/vendor/openssl/openssl_rsa.cpp (limited to 'src/lib') diff --git a/src/lib/block/openssl_block/info.txt b/src/lib/block/openssl_block/info.txt new file mode 100644 index 000000000..62feaac95 --- /dev/null +++ b/src/lib/block/openssl_block/info.txt @@ -0,0 +1,5 @@ +define OPENSSL_BLOCK_CIPHER 20151019 + + +openssl + diff --git a/src/lib/block/openssl_block/openssl_block.cpp b/src/lib/block/openssl_block/openssl_block.cpp new file mode 100644 index 000000000..a35919e3a --- /dev/null +++ b/src/lib/block/openssl_block/openssl_block.cpp @@ -0,0 +1,214 @@ +/* +* Block Ciphers via OpenSSL +* (C) 1999-2010,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include +#include +#include + +namespace Botan { + +namespace { + +class OpenSSL_BlockCipher : public BlockCipher + { + public: + void clear(); + std::string name() const { return cipher_name; } + BlockCipher* clone() const; + + size_t block_size() const { return block_sz; } + + OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&); + + OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&, + size_t, size_t, size_t); + + Key_Length_Specification key_spec() const { return cipher_key_spec; } + + ~OpenSSL_BlockCipher(); + private: + void encrypt_n(const byte in[], byte out[], size_t blocks) const + { + int out_len = 0; + EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * block_sz); + } + + void decrypt_n(const byte in[], byte out[], size_t blocks) const + { + int out_len = 0; + EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * block_sz); + } + + void key_schedule(const byte[], size_t); + + size_t block_sz; + Key_Length_Specification cipher_key_spec; + std::string cipher_name; + mutable EVP_CIPHER_CTX encrypt, decrypt; + }; + +OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo, + const std::string& algo_name) : + block_sz(EVP_CIPHER_block_size(algo)), + cipher_key_spec(EVP_CIPHER_key_length(algo)), + cipher_name(algo_name) + { + if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) + throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in"); + + EVP_CIPHER_CTX_init(&encrypt); + EVP_CIPHER_CTX_init(&decrypt); + + EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr); + EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr); + + EVP_CIPHER_CTX_set_padding(&encrypt, 0); + EVP_CIPHER_CTX_set_padding(&decrypt, 0); + } + +OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo, + const std::string& algo_name, + size_t key_min, size_t key_max, + size_t key_mod) : + block_sz(EVP_CIPHER_block_size(algo)), + cipher_key_spec(key_min, key_max, key_mod), + cipher_name(algo_name) + { + if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) + throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in"); + + EVP_CIPHER_CTX_init(&encrypt); + EVP_CIPHER_CTX_init(&decrypt); + + EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr); + EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr); + + EVP_CIPHER_CTX_set_padding(&encrypt, 0); + EVP_CIPHER_CTX_set_padding(&decrypt, 0); + } + +OpenSSL_BlockCipher::~OpenSSL_BlockCipher() + { + EVP_CIPHER_CTX_cleanup(&encrypt); + EVP_CIPHER_CTX_cleanup(&decrypt); + } + +/* +* Set the key +*/ +void OpenSSL_BlockCipher::key_schedule(const byte key[], size_t length) + { + secure_vector full_key(key, key + length); + + if(cipher_name == "TripleDES" && length == 16) + { + full_key += std::make_pair(key, 8); + } + else + if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 || + EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0) + throw Invalid_Argument("OpenSSL_BlockCipher: Bad key length for " + + cipher_name); + + EVP_EncryptInit_ex(&encrypt, nullptr, nullptr, full_key.data(), nullptr); + EVP_DecryptInit_ex(&decrypt, nullptr, nullptr, full_key.data(), nullptr); + } + +/* +* Return a clone of this object +*/ +BlockCipher* OpenSSL_BlockCipher::clone() const + { + return new OpenSSL_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt), + cipher_name, + cipher_key_spec.minimum_keylength(), + cipher_key_spec.maximum_keylength(), + cipher_key_spec.keylength_multiple()); + } + +/* +* Clear memory of sensitive data +*/ +void OpenSSL_BlockCipher::clear() + { + const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt); + + EVP_CIPHER_CTX_cleanup(&encrypt); + EVP_CIPHER_CTX_cleanup(&decrypt); + EVP_CIPHER_CTX_init(&encrypt); + EVP_CIPHER_CTX_init(&decrypt); + EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr); + EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr); + EVP_CIPHER_CTX_set_padding(&encrypt, 0); + EVP_CIPHER_CTX_set_padding(&decrypt, 0); + } + +std::function +make_evp_block_maker(const EVP_CIPHER* cipher, const char* algo) + { + return [cipher,algo](const BlockCipher::Spec&) + { + return new OpenSSL_BlockCipher(cipher, algo); + }; + } + +std::function +make_evp_block_maker_keylen(const EVP_CIPHER* cipher, const char* algo, + size_t kmin, size_t kmax, size_t kmod) + { + return [cipher,algo,kmin,kmax,kmod](const BlockCipher::Spec&) + { + return new OpenSSL_BlockCipher(cipher, algo, kmin, kmax, kmod); + }; + } + +#define BOTAN_REGISTER_OPENSSL_EVP_BLOCK(NAME, EVP) \ + BOTAN_REGISTER_TYPE(BlockCipher, EVP_BlockCipher ## EVP, NAME, \ + make_evp_block_maker(EVP(), NAME), "openssl", BOTAN_OPENSSL_BLOCK_PRIO); + +#define BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN(NAME, EVP, KMIN, KMAX, KMOD) \ + BOTAN_REGISTER_TYPE(BlockCipher, OpenSSL_BlockCipher ## EVP, NAME, \ + make_evp_block_maker_keylen(EVP(), NAME, KMIN, KMAX, KMOD), \ + "openssl", BOTAN_OPENSSL_BLOCK_PRIO); + +#if !defined(OPENSSL_NO_AES) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-128", EVP_aes_128_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-192", EVP_aes_192_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-256", EVP_aes_256_ecb); +#endif + +#if !defined(OPENSSL_NO_DES) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("DES", EVP_des_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("TripleDES", EVP_des_ede3_ecb, 16, 24, 8); +#endif + +#if !defined(OPENSSL_NO_BF) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("Blowfish", EVP_bf_ecb, 1, 56, 1); +#endif + +#if !defined(OPENSSL_NO_CAST) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("CAST-128", EVP_cast5_ecb, 1, 16, 1); +#endif + +#if !defined(OPENSSL_NO_CAMELLIA) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-128", EVP_camellia_128_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-192", EVP_camellia_192_ecb); + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-256", EVP_camellia_256_ecb); +#endif + +#if !defined(OPENSSL_NO_IDEA) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("IDEA", EVP_idea_ecb); +#endif + +#if !defined(OPENSSL_NO_SEED) + BOTAN_REGISTER_OPENSSL_EVP_BLOCK("SEED", EVP_seed_ecb); +#endif + +} + +} diff --git a/src/lib/hash/openssl_hash/info.txt b/src/lib/hash/openssl_hash/info.txt new file mode 100644 index 000000000..c375d272e --- /dev/null +++ b/src/lib/hash/openssl_hash/info.txt @@ -0,0 +1,5 @@ +define OPENSSL_HASH_FUNCTION 20151019 + + +openssl + diff --git a/src/lib/hash/openssl_hash/openssl_hash.cpp b/src/lib/hash/openssl_hash/openssl_hash.cpp new file mode 100644 index 000000000..c89dd777d --- /dev/null +++ b/src/lib/hash/openssl_hash/openssl_hash.cpp @@ -0,0 +1,117 @@ +/* +* OpenSSL Hash Functions +* (C) 1999-2007,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include +#include +#include +#include + +namespace Botan { + +namespace { + +class OpenSSL_HashFunction : public HashFunction + { + public: + void clear() + { + const EVP_MD* algo = EVP_MD_CTX_md(&m_md); + EVP_DigestInit_ex(&m_md, algo, nullptr); + } + + std::string name() const { return m_name; } + + HashFunction* clone() const + { + const EVP_MD* algo = EVP_MD_CTX_md(&m_md); + return new OpenSSL_HashFunction(algo, name()); + } + + size_t output_length() const + { + return EVP_MD_size(EVP_MD_CTX_md(&m_md)); + } + + size_t hash_block_size() const + { + return EVP_MD_block_size(EVP_MD_CTX_md(&m_md)); + } + + OpenSSL_HashFunction(const EVP_MD* md, const std::string& name) : m_name(name) + { + EVP_MD_CTX_init(&m_md); + EVP_DigestInit_ex(&m_md, md, nullptr); + } + + ~OpenSSL_HashFunction() + { + EVP_MD_CTX_cleanup(&m_md); + } + + private: + void add_data(const byte input[], size_t length) + { + EVP_DigestUpdate(&m_md, input, length); + } + + void final_result(byte output[]) + { + EVP_DigestFinal_ex(&m_md, output, nullptr); + const EVP_MD* algo = EVP_MD_CTX_md(&m_md); + EVP_DigestInit_ex(&m_md, algo, nullptr); + } + + std::string m_name; + EVP_MD_CTX m_md; + }; + +std::function +make_evp_hash_maker(const EVP_MD* md, const char* algo) + { + return [md,algo](const HashFunction::Spec&) + { + return new OpenSSL_HashFunction(md, algo); + }; + } + +#define BOTAN_REGISTER_OPENSSL_EVP_HASH(NAME, EVP) \ + BOTAN_REGISTER_TYPE(HashFunction, OpenSSL_HashFunction ## EVP, NAME, \ + make_evp_hash_maker(EVP(), NAME), "openssl", BOTAN_OPENSSL_HASH_PRIO); + +#if !defined(OPENSSL_NO_SHA) + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-160", EVP_sha1); +#endif + +#if !defined(OPENSSL_NO_SHA256) + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-224", EVP_sha224); + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-256", EVP_sha256); +#endif + +#if !defined(OPENSSL_NO_SHA512) + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-384", EVP_sha384); + BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-512", EVP_sha512); +#endif + +#if !defined(OPENSSL_NO_MD2) + BOTAN_REGISTER_OPENSSL_EVP_HASH("MD2", EVP_md2); +#endif + +#if !defined(OPENSSL_NO_MD4) + BOTAN_REGISTER_OPENSSL_EVP_HASH("MD4", EVP_md4); +#endif + +#if !defined(OPENSSL_NO_MD5) + BOTAN_REGISTER_OPENSSL_EVP_HASH("MD5", EVP_md5); +#endif + +#if !defined(OPENSSL_NO_RIPEMD) + BOTAN_REGISTER_OPENSSL_EVP_HASH("RIPEMD-160", EVP_ripemd160); +#endif + +} + +} diff --git a/src/lib/pubkey/ecdsa/openssl_ecdsa.cpp b/src/lib/pubkey/ecdsa/openssl_ecdsa.cpp new file mode 100644 index 000000000..502702804 --- /dev/null +++ b/src/lib/pubkey/ecdsa/openssl_ecdsa.cpp @@ -0,0 +1,213 @@ +/* +* ECDSA via OpenSSL +* (C) 2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include + +#if defined(BOTAN_HAS_OPENSSL) + +#include +#include + +#if !defined(OPENSSL_NO_ECDSA) + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace Botan { + +namespace { + +secure_vector PKCS8_for_openssl(const EC_PrivateKey& ec) + { + const PointGFp& pub_key = ec.public_point(); + const BigInt& priv_key = ec.private_value(); + + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(static_cast(1)) + .encode(BigInt::encode_1363(priv_key, priv_key.bytes()), OCTET_STRING) + .start_cons(ASN1_Tag(0), PRIVATE) + .raw_bytes(ec.domain().DER_encode(EC_DOMPAR_ENC_OID)) + .end_cons() + .start_cons(ASN1_Tag(1), PRIVATE) + .encode(EC2OSP(pub_key, PointGFp::UNCOMPRESSED), BIT_STRING) + .end_cons() + .end_cons() + .get_contents(); + } + +int OpenSSL_EC_nid_for(const OID& oid) + { + if(oid.empty()) + return -1; + + static const std::map nid_map = { + //{ "secp160r1", NID_secp160r1 }, + //{ "secp160r2", NID_secp160r2 }, + { "secp192r1", NID_X9_62_prime192v1 }, + { "secp224r1", NID_secp224r1 }, + { "secp256r1", NID_X9_62_prime256v1 }, + { "secp384r1", NID_secp384r1 }, + { "secp521r1", NID_secp521r1 } + // TODO: OpenSSL 1.0.2 added brainpool curves + }; + + const std::string name = OIDS::lookup(oid); + auto i = nid_map.find(name); + if(i != nid_map.end()) + return i->second; + + return -1; + } + +class OpenSSL_ECDSA_Verification_Operation : public PK_Ops::Verification_with_EMSA + { + public: + typedef ECDSA_PublicKey Key_Type; + + static OpenSSL_ECDSA_Verification_Operation* make(const Spec& spec) + { + if(const ECDSA_PublicKey* ecdsa = dynamic_cast(&spec.key())) + { + const int nid = OpenSSL_EC_nid_for(ecdsa->domain().get_oid()); + if(nid > 0) + return new OpenSSL_ECDSA_Verification_Operation(*ecdsa, spec.padding(), nid); + } + + return nullptr; + } + + OpenSSL_ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa, const std::string& emsa, int nid) : + PK_Ops::Verification_with_EMSA(emsa), m_ossl_ec(::EC_KEY_new(), ::EC_KEY_free) + { + std::unique_ptr<::EC_GROUP, std::function> grp(::EC_GROUP_new_by_curve_name(nid), + ::EC_GROUP_free); + + if(!grp) + throw OpenSSL_Error("EC_GROUP_new_by_curve_name"); + + ::EC_KEY_set_group(m_ossl_ec.get(), grp.get()); + + const secure_vector enc = EC2OSP(ecdsa.public_point(), PointGFp::UNCOMPRESSED); + const byte* enc_ptr = enc.data(); + EC_KEY* key_ptr = m_ossl_ec.get(); + if(!::o2i_ECPublicKey(&key_ptr, &enc_ptr, enc.size())) + throw OpenSSL_Error("o2i_ECPublicKey"); + + const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get()); + m_order_bits = ::EC_GROUP_get_degree(group); + } + + size_t message_parts() const override { return 2; } + size_t message_part_size() const override { return (m_order_bits + 7) / 8; } + size_t max_input_bits() const override { return m_order_bits; } + + bool with_recovery() const override { return false; } + + bool verify(const byte msg[], size_t msg_len, + const byte sig_bytes[], size_t sig_len) override + { + if(sig_len != message_part_size() * message_parts()) + return false; + + std::unique_ptr> sig(nullptr, ECDSA_SIG_free); + sig.reset(::ECDSA_SIG_new()); + + sig->r = BN_bin2bn(sig_bytes , sig_len / 2, nullptr); + sig->s = BN_bin2bn(sig_bytes + sig_len / 2, sig_len / 2, nullptr); + + const int res = ECDSA_do_verify(msg, msg_len, sig.get(), m_ossl_ec.get()); + if(res < 0) + throw OpenSSL_Error("ECDSA_do_verify"); + return (res == 1); + } + + private: + std::unique_ptr> m_ossl_ec; + size_t m_order_bits = 0; + }; + +class OpenSSL_ECDSA_Signing_Operation : public PK_Ops::Signature_with_EMSA + { + public: + typedef ECDSA_PrivateKey Key_Type; + + static OpenSSL_ECDSA_Signing_Operation* make(const Spec& spec) + { + if(const ECDSA_PrivateKey* ecdsa = dynamic_cast(&spec.key())) + { + const int nid = OpenSSL_EC_nid_for(ecdsa->domain().get_oid()); + if(nid > 0) + return new OpenSSL_ECDSA_Signing_Operation(*ecdsa, spec.padding()); + } + + return nullptr; + } + + OpenSSL_ECDSA_Signing_Operation(const ECDSA_PrivateKey& ecdsa, const std::string& emsa) : + PK_Ops::Signature_with_EMSA(emsa), + m_ossl_ec(nullptr, ::EC_KEY_free) + { + const secure_vector der = PKCS8_for_openssl(ecdsa); + const byte* der_ptr = der.data(); + m_ossl_ec.reset(d2i_ECPrivateKey(nullptr, &der_ptr, der.size())); + if(!m_ossl_ec) + throw OpenSSL_Error("d2i_ECPrivateKey"); + + const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get()); + m_order_bits = ::EC_GROUP_get_degree(group); + } + + secure_vector raw_sign(const byte msg[], size_t msg_len, + RandomNumberGenerator&) override + { + std::unique_ptr> sig(nullptr, ECDSA_SIG_free); + sig.reset(::ECDSA_do_sign(msg, msg_len, m_ossl_ec.get())); + + if(!sig) + throw OpenSSL_Error("ECDSA_do_sign"); + + const size_t order_bytes = message_part_size(); + const size_t r_bytes = BN_num_bytes(sig->r); + const size_t s_bytes = BN_num_bytes(sig->s); + secure_vector sigval(2*order_bytes); + BN_bn2bin(sig->r, &sigval[order_bytes - r_bytes]); + BN_bn2bin(sig->s, &sigval[2*order_bytes - s_bytes]); + return sigval; + } + + size_t message_parts() const override { return 2; } + size_t message_part_size() const override { return (m_order_bits + 7) / 8; } + size_t max_input_bits() const override { return m_order_bits; } + + private: + std::unique_ptr> m_ossl_ec; + size_t m_order_bits = 0; + }; + +BOTAN_REGISTER_TYPE(PK_Ops::Verification, OpenSSL_ECDSA_Verification_Operation, "ECDSA", + OpenSSL_ECDSA_Verification_Operation::make, + "openssl", BOTAN_OPENSSL_ECDSA_PRIO); + +BOTAN_REGISTER_TYPE(PK_Ops::Signature, OpenSSL_ECDSA_Signing_Operation, "ECDSA", + OpenSSL_ECDSA_Signing_Operation::make, + "openssl", BOTAN_OPENSSL_ECDSA_PRIO); + +} + +} + +#endif + +#endif diff --git a/src/lib/pubkey/rsa/openssl_rsa.cpp b/src/lib/pubkey/rsa/openssl_rsa.cpp new file mode 100644 index 000000000..f2825634a --- /dev/null +++ b/src/lib/pubkey/rsa/openssl_rsa.cpp @@ -0,0 +1,297 @@ +/* +* RSA operations provided by OpenSSL +* (C) 2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include + +#if defined(BOTAN_HAS_OPENSSL) + +#include +#include +#include +#include + +#include +#include +#include + +namespace Botan { + +namespace { + +std::pair get_openssl_enc_pad(const std::string& eme) + { + ERR_load_crypto_strings(); + if(eme == "Raw") + return std::make_pair(RSA_NO_PADDING, 0); + else if(eme == "EME-PKCS1-v1_5") + return std::make_pair(RSA_PKCS1_PADDING, 11); + else if(eme == "OAEP(SHA-1)") + return std::make_pair(RSA_PKCS1_OAEP_PADDING, 41); + else + throw Lookup_Error("OpenSSL RSA does not support EME " + eme); + } + +secure_vector strip_leading_zeros(const secure_vector& input) + { + size_t leading_zeros = 0; + + for(size_t i = 0; i != input.size(); ++i) + { + if(input[i] != 0) + break; + ++leading_zeros; + } + + secure_vector output(&input[leading_zeros], + &input[input.size()]); + return output; + } + +class OpenSSL_RSA_Encryption_Operation : public PK_Ops::Encryption + { + public: + typedef RSA_PublicKey Key_Type; + + static OpenSSL_RSA_Encryption_Operation* make(const Spec& spec) + { + try + { + if(auto* key = dynamic_cast(&spec.key())) + { + auto pad_info = get_openssl_enc_pad(spec.padding()); + return new OpenSSL_RSA_Encryption_Operation(*key, pad_info.first, pad_info.second); + } + } + catch(...) {} + + return nullptr; + } + + OpenSSL_RSA_Encryption_Operation(const RSA_PublicKey& rsa, int pad, size_t pad_overhead) : + m_openssl_rsa(nullptr, ::RSA_free), m_padding(pad) + { + const std::vector der = rsa.x509_subject_public_key(); + const byte* der_ptr = der.data(); + m_openssl_rsa.reset(::d2i_RSAPublicKey(nullptr, &der_ptr, der.size())); + if(!m_openssl_rsa) + throw OpenSSL_Error("d2i_RSAPublicKey"); + + m_bits = 8 * (n_size() - pad_overhead) - 1; + } + + size_t max_input_bits() const override { return m_bits; }; + + secure_vector encrypt(const byte msg[], size_t msg_len, + RandomNumberGenerator&) override + { + const size_t mod_sz = n_size(); + + if(msg_len > mod_sz) + throw Invalid_Argument("Input too large for RSA key"); + + secure_vector outbuf(mod_sz); + + secure_vector inbuf; + + if(m_padding == RSA_NO_PADDING) + { + inbuf.resize(mod_sz); + copy_mem(&inbuf[mod_sz - msg_len], msg, msg_len); + } + else + { + inbuf.assign(msg, msg + msg_len); + } + + int rc = ::RSA_public_encrypt(inbuf.size(), inbuf.data(), outbuf.data(), + m_openssl_rsa.get(), m_padding); + if(rc < 0) + throw OpenSSL_Error("RSA_public_encrypt"); + + return outbuf; + } + + private: + size_t n_size() const { return ::RSA_size(m_openssl_rsa.get()); } + std::unique_ptr> m_openssl_rsa; + size_t m_bits = 0; + int m_padding = 0; + }; + +class OpenSSL_RSA_Decryption_Operation : public PK_Ops::Decryption + { + public: + typedef RSA_PrivateKey Key_Type; + + static OpenSSL_RSA_Decryption_Operation* make(const Spec& spec) + { + try + { + if(auto* key = dynamic_cast(&spec.key())) + { + auto pad_info = get_openssl_enc_pad(spec.padding()); + return new OpenSSL_RSA_Decryption_Operation(*key, pad_info.first); + } + } + catch(...) {} + + return nullptr; + } + + OpenSSL_RSA_Decryption_Operation(const RSA_PrivateKey& rsa, int pad) : + m_openssl_rsa(nullptr, ::RSA_free), m_padding(pad) + { + const secure_vector der = rsa.pkcs8_private_key(); + const byte* der_ptr = der.data(); + m_openssl_rsa.reset(d2i_RSAPrivateKey(nullptr, &der_ptr, der.size())); + if(!m_openssl_rsa) + throw OpenSSL_Error("d2i_RSAPrivateKey"); + } + + size_t max_input_bits() const override { return ::BN_num_bits(m_openssl_rsa->n) - 1; } + + secure_vector decrypt(const byte msg[], size_t msg_len) override + { + secure_vector buf(::RSA_size(m_openssl_rsa.get())); + int rc = ::RSA_private_decrypt(msg_len, msg, buf.data(), m_openssl_rsa.get(), m_padding); + if(rc < 0 || static_cast(rc) > buf.size()) + throw OpenSSL_Error("RSA_private_decrypt"); + buf.resize(rc); + + if(m_padding == RSA_NO_PADDING) + { + return strip_leading_zeros(buf); + } + return buf; + } + + private: + std::unique_ptr> m_openssl_rsa; + int m_padding = 0; + }; + +class OpenSSL_RSA_Verification_Operation : public PK_Ops::Verification_with_EMSA + { + public: + typedef RSA_PublicKey Key_Type; + + static OpenSSL_RSA_Verification_Operation* make(const Spec& spec) + { + if(const RSA_PublicKey* rsa = dynamic_cast(&spec.key())) + { + return new OpenSSL_RSA_Verification_Operation(*rsa, spec.padding()); + } + + return nullptr; + } + + OpenSSL_RSA_Verification_Operation(const RSA_PublicKey& rsa, const std::string& emsa) : + PK_Ops::Verification_with_EMSA(emsa), + m_openssl_rsa(nullptr, ::RSA_free) + { + const std::vector der = rsa.x509_subject_public_key(); + const byte* der_ptr = der.data(); + m_openssl_rsa.reset(::d2i_RSAPublicKey(nullptr, &der_ptr, der.size())); + } + + size_t max_input_bits() const override { return ::BN_num_bits(m_openssl_rsa->n) - 1; } + + bool with_recovery() const override { return true; } + + secure_vector verify_mr(const byte msg[], size_t msg_len) override + { + const size_t mod_sz = ::RSA_size(m_openssl_rsa.get()); + + if(msg_len > mod_sz) + throw Invalid_Argument("OpenSSL RSA verify input too large"); + + secure_vector inbuf(mod_sz); + copy_mem(&inbuf[mod_sz - msg_len], msg, msg_len); + + secure_vector outbuf(mod_sz); + + int rc = ::RSA_public_decrypt(inbuf.size(), inbuf.data(), outbuf.data(), + m_openssl_rsa.get(), RSA_NO_PADDING); + if(rc < 0) + throw Invalid_Argument("RSA_public_decrypt"); + + return strip_leading_zeros(outbuf); + } + private: + std::unique_ptr> m_openssl_rsa; + }; + +class OpenSSL_RSA_Signing_Operation : public PK_Ops::Signature_with_EMSA + { + public: + typedef RSA_PrivateKey Key_Type; + + static OpenSSL_RSA_Signing_Operation* make(const Spec& spec) + { + if(const RSA_PrivateKey* rsa = dynamic_cast(&spec.key())) + { + return new OpenSSL_RSA_Signing_Operation(*rsa, spec.padding()); + } + + return nullptr; + } + + OpenSSL_RSA_Signing_Operation(const RSA_PrivateKey& rsa, const std::string& emsa) : + PK_Ops::Signature_with_EMSA(emsa), + m_openssl_rsa(nullptr, ::RSA_free) + { + const secure_vector der = rsa.pkcs8_private_key(); + const byte* der_ptr = der.data(); + m_openssl_rsa.reset(d2i_RSAPrivateKey(nullptr, &der_ptr, der.size())); + if(!m_openssl_rsa) + throw OpenSSL_Error("d2i_RSAPrivateKey"); + } + + secure_vector raw_sign(const byte msg[], size_t msg_len, + RandomNumberGenerator&) override + { + const size_t mod_sz = ::RSA_size(m_openssl_rsa.get()); + + if(msg_len > mod_sz) + throw Invalid_Argument("OpenSSL RSA sign input too large"); + + secure_vector inbuf(mod_sz); + copy_mem(&inbuf[mod_sz - msg_len], msg, msg_len); + + secure_vector outbuf(mod_sz); + + int rc = ::RSA_private_encrypt(inbuf.size(), inbuf.data(), outbuf.data(), + m_openssl_rsa.get(), RSA_NO_PADDING); + if(rc < 0) + throw OpenSSL_Error("RSA_private_encrypt"); + + return outbuf; + } + + size_t max_input_bits() const override { return ::BN_num_bits(m_openssl_rsa->n) - 1; } + + private: + std::unique_ptr> m_openssl_rsa; + }; + +BOTAN_REGISTER_TYPE(PK_Ops::Verification, OpenSSL_RSA_Verification_Operation, "RSA", + OpenSSL_RSA_Verification_Operation::make, "openssl", BOTAN_OPENSSL_RSA_PRIO); + +BOTAN_REGISTER_TYPE(PK_Ops::Signature, OpenSSL_RSA_Signing_Operation, "RSA", + OpenSSL_RSA_Signing_Operation::make, "openssl", BOTAN_OPENSSL_RSA_PRIO); + +BOTAN_REGISTER_TYPE(PK_Ops::Encryption, OpenSSL_RSA_Encryption_Operation, "RSA", + OpenSSL_RSA_Encryption_Operation::make, "openssl", BOTAN_OPENSSL_RSA_PRIO); + +BOTAN_REGISTER_TYPE(PK_Ops::Decryption, OpenSSL_RSA_Decryption_Operation, "RSA", + OpenSSL_RSA_Decryption_Operation::make, "openssl", BOTAN_OPENSSL_RSA_PRIO); + +} + +} + +#endif // BOTAN_HAS_OPENSSL diff --git a/src/lib/stream/rc4/openssl_rc4.cpp b/src/lib/stream/rc4/openssl_rc4.cpp new file mode 100644 index 000000000..e4f180a9b --- /dev/null +++ b/src/lib/stream/rc4/openssl_rc4.cpp @@ -0,0 +1,61 @@ +/* +* OpenSSL RC4 +* (C) 1999-2007,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include + +#if defined(BOTAN_HAS_OPENSSL) + +#include +#include +#include +#include + +namespace Botan { + +namespace { + +class OpenSSL_RC4 : public StreamCipher + { + public: + void clear() { clear_mem(&m_rc4, 1); } + + std::string name() const { return "RC4"; } + StreamCipher* clone() const { return new OpenSSL_RC4; } + + Key_Length_Specification key_spec() const + { + return Key_Length_Specification(1, 32); + } + + OpenSSL_RC4(size_t skip = 0) : m_skip(skip) { clear(); } + ~OpenSSL_RC4() { clear(); } + private: + void cipher(const byte in[], byte out[], size_t length) + { + ::RC4(&m_rc4, length, in, out); + } + + void key_schedule(const byte key[], size_t length) + { + ::RC4_set_key(&m_rc4, length, key); + byte d = 0; + for(size_t i = 0; i != m_skip; ++i) + ::RC4(&m_rc4, 1, &d, &d); + } + + size_t m_skip; + RC4_KEY m_rc4; + }; + +} + +BOTAN_REGISTER_TYPE(StreamCipher, OpenSSL_RC4, "RC4", (make_new_T_1len), + "openssl", BOTAN_OPENSSL_RC4_PRIO); + +} + +#endif diff --git a/src/lib/utils/openssl/info.txt b/src/lib/utils/openssl/info.txt new file mode 100644 index 000000000..13ea92cbf --- /dev/null +++ b/src/lib/utils/openssl/info.txt @@ -0,0 +1,16 @@ +define OPENSSL 20150829 + +# This base module doesn't have any code, but other code using openssl +# rely on it either macro check for BOTAN_HAS_OPENSSL or a module +# dependency on openssl to test for the existence of and desire to use +# OpenSSL for certain operations. + +load_on vendor + + +openssl.h + + + +all -> crypto + diff --git a/src/lib/utils/openssl/openssl.h b/src/lib/utils/openssl/openssl.h new file mode 100644 index 000000000..022db6223 --- /dev/null +++ b/src/lib/utils/openssl/openssl.h @@ -0,0 +1,35 @@ +/* +* Utils for calling OpenSSL +* (C) 2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_OPENSSL_H__ +#define BOTAN_OPENSSL_H__ + +#include +#include +#include + +#include + +namespace Botan { + +class OpenSSL_Error : public Exception + { + public: + OpenSSL_Error(const std::string& what) : + Exception(what + " failed: " + ERR_error_string(ERR_get_error(), nullptr)) {} + }; + +#define BOTAN_OPENSSL_BLOCK_PRIO 150 +#define BOTAN_OPENSSL_HASH_PRIO 150 +#define BOTAN_OPENSSL_RC4_PRIO 150 + +#define BOTAN_OPENSSL_RSA_PRIO 150 +#define BOTAN_OPENSSL_ECDSA_PRIO 150 + +} + +#endif diff --git a/src/lib/vendor/openssl/info.txt b/src/lib/vendor/openssl/info.txt deleted file mode 100644 index 1381e2019..000000000 --- a/src/lib/vendor/openssl/info.txt +++ /dev/null @@ -1,11 +0,0 @@ -define OPENSSL 20150829 - -load_on vendor - - -openssl.h - - - -all -> crypto - diff --git a/src/lib/vendor/openssl/openssl.h b/src/lib/vendor/openssl/openssl.h deleted file mode 100644 index 86cc8fd35..000000000 --- a/src/lib/vendor/openssl/openssl.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -* Utils for calling OpenSSL -* (C) 2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_OPENSSL_H__ -#define BOTAN_OPENSSL_H__ - -#include -#include -#include - -#include - -namespace Botan { - -class OpenSSL_Error : public Exception - { - public: - OpenSSL_Error(const std::string& what) : - Exception(what + " failed: " + ERR_error_string(ERR_get_error(), nullptr)) {} - }; - -#define BOTAN_OPENSSL_BLOCK_PRIO 150 -#define BOTAN_OPENSSL_HASH_PRIO 150 -#define BOTAN_OPENSSL_RC4_PRIO 150 - -#define BOTAN_OPENSSL_RSA_PRIO 90 -#define BOTAN_OPENSSL_ECDSA_PRIO 90 - - -} - -#endif diff --git a/src/lib/vendor/openssl/openssl_block.cpp b/src/lib/vendor/openssl/openssl_block.cpp deleted file mode 100644 index 5c28f46b1..000000000 --- a/src/lib/vendor/openssl/openssl_block.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* -* Block Ciphers via OpenSSL -* (C) 1999-2010,2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include -#include -#include -#include - -namespace Botan { - -namespace { - -class OpenSSL_BlockCipher : public BlockCipher - { - public: - void clear(); - std::string name() const { return cipher_name; } - BlockCipher* clone() const; - - size_t block_size() const { return block_sz; } - - OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&); - - OpenSSL_BlockCipher(const EVP_CIPHER*, const std::string&, - size_t, size_t, size_t); - - Key_Length_Specification key_spec() const { return cipher_key_spec; } - - ~OpenSSL_BlockCipher(); - private: - void encrypt_n(const byte in[], byte out[], size_t blocks) const - { - int out_len = 0; - EVP_EncryptUpdate(&encrypt, out, &out_len, in, blocks * block_sz); - } - - void decrypt_n(const byte in[], byte out[], size_t blocks) const - { - int out_len = 0; - EVP_DecryptUpdate(&decrypt, out, &out_len, in, blocks * block_sz); - } - - void key_schedule(const byte[], size_t); - - size_t block_sz; - Key_Length_Specification cipher_key_spec; - std::string cipher_name; - mutable EVP_CIPHER_CTX encrypt, decrypt; - }; - -OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo, - const std::string& algo_name) : - block_sz(EVP_CIPHER_block_size(algo)), - cipher_key_spec(EVP_CIPHER_key_length(algo)), - cipher_name(algo_name) - { - if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) - throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in"); - - EVP_CIPHER_CTX_init(&encrypt); - EVP_CIPHER_CTX_init(&decrypt); - - EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr); - EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr); - - EVP_CIPHER_CTX_set_padding(&encrypt, 0); - EVP_CIPHER_CTX_set_padding(&decrypt, 0); - } - -OpenSSL_BlockCipher::OpenSSL_BlockCipher(const EVP_CIPHER* algo, - const std::string& algo_name, - size_t key_min, size_t key_max, - size_t key_mod) : - block_sz(EVP_CIPHER_block_size(algo)), - cipher_key_spec(key_min, key_max, key_mod), - cipher_name(algo_name) - { - if(EVP_CIPHER_mode(algo) != EVP_CIPH_ECB_MODE) - throw Invalid_Argument("OpenSSL_BlockCipher: Non-ECB EVP was passed in"); - - EVP_CIPHER_CTX_init(&encrypt); - EVP_CIPHER_CTX_init(&decrypt); - - EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr); - EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr); - - EVP_CIPHER_CTX_set_padding(&encrypt, 0); - EVP_CIPHER_CTX_set_padding(&decrypt, 0); - } - -OpenSSL_BlockCipher::~OpenSSL_BlockCipher() - { - EVP_CIPHER_CTX_cleanup(&encrypt); - EVP_CIPHER_CTX_cleanup(&decrypt); - } - -/* -* Set the key -*/ -void OpenSSL_BlockCipher::key_schedule(const byte key[], size_t length) - { - secure_vector full_key(key, key + length); - - if(cipher_name == "TripleDES" && length == 16) - { - full_key += std::make_pair(key, 8); - } - else - if(EVP_CIPHER_CTX_set_key_length(&encrypt, length) == 0 || - EVP_CIPHER_CTX_set_key_length(&decrypt, length) == 0) - throw Invalid_Argument("OpenSSL_BlockCipher: Bad key length for " + - cipher_name); - - EVP_EncryptInit_ex(&encrypt, nullptr, nullptr, full_key.data(), nullptr); - EVP_DecryptInit_ex(&decrypt, nullptr, nullptr, full_key.data(), nullptr); - } - -/* -* Return a clone of this object -*/ -BlockCipher* OpenSSL_BlockCipher::clone() const - { - return new OpenSSL_BlockCipher(EVP_CIPHER_CTX_cipher(&encrypt), - cipher_name, - cipher_key_spec.minimum_keylength(), - cipher_key_spec.maximum_keylength(), - cipher_key_spec.keylength_multiple()); - } - -/* -* Clear memory of sensitive data -*/ -void OpenSSL_BlockCipher::clear() - { - const EVP_CIPHER* algo = EVP_CIPHER_CTX_cipher(&encrypt); - - EVP_CIPHER_CTX_cleanup(&encrypt); - EVP_CIPHER_CTX_cleanup(&decrypt); - EVP_CIPHER_CTX_init(&encrypt); - EVP_CIPHER_CTX_init(&decrypt); - EVP_EncryptInit_ex(&encrypt, algo, nullptr, nullptr, nullptr); - EVP_DecryptInit_ex(&decrypt, algo, nullptr, nullptr, nullptr); - EVP_CIPHER_CTX_set_padding(&encrypt, 0); - EVP_CIPHER_CTX_set_padding(&decrypt, 0); - } - -std::function -make_evp_block_maker(const EVP_CIPHER* cipher, const char* algo) - { - return [cipher,algo](const BlockCipher::Spec&) - { - return new OpenSSL_BlockCipher(cipher, algo); - }; - } - -std::function -make_evp_block_maker_keylen(const EVP_CIPHER* cipher, const char* algo, - size_t kmin, size_t kmax, size_t kmod) - { - return [cipher,algo,kmin,kmax,kmod](const BlockCipher::Spec&) - { - return new OpenSSL_BlockCipher(cipher, algo, kmin, kmax, kmod); - }; - } - -#define BOTAN_OPENSSL_BLOCK_PRIO 150 - -#define BOTAN_REGISTER_OPENSSL_EVP_BLOCK(NAME, EVP) \ - BOTAN_REGISTER_TYPE(BlockCipher, EVP_BlockCipher ## EVP, NAME, \ - make_evp_block_maker(EVP(), NAME), "openssl", BOTAN_OPENSSL_BLOCK_PRIO); - -#define BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN(NAME, EVP, KMIN, KMAX, KMOD) \ - BOTAN_REGISTER_TYPE(BlockCipher, OpenSSL_BlockCipher ## EVP, NAME, \ - make_evp_block_maker_keylen(EVP(), NAME, KMIN, KMAX, KMOD), \ - "openssl", BOTAN_OPENSSL_BLOCK_PRIO); - -#if !defined(OPENSSL_NO_AES) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-128", EVP_aes_128_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-192", EVP_aes_192_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("AES-256", EVP_aes_256_ecb); -#endif - -#if !defined(OPENSSL_NO_DES) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("DES", EVP_des_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("TripleDES", EVP_des_ede3_ecb, 16, 24, 8); -#endif - -#if !defined(OPENSSL_NO_BF) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("Blowfish", EVP_bf_ecb, 1, 56, 1); -#endif - -#if !defined(OPENSSL_NO_CAST) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK_KEYLEN("CAST-128", EVP_cast5_ecb, 1, 16, 1); -#endif - -#if !defined(OPENSSL_NO_CAMELLIA) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-128", EVP_camellia_128_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-192", EVP_camellia_192_ecb); - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("Camellia-256", EVP_camellia_256_ecb); -#endif - -#if !defined(OPENSSL_NO_IDEA) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("IDEA", EVP_idea_ecb); -#endif - -#if !defined(OPENSSL_NO_SEED) - BOTAN_REGISTER_OPENSSL_EVP_BLOCK("SEED", EVP_seed_ecb); -#endif - -} - -} diff --git a/src/lib/vendor/openssl/openssl_ecdsa.cpp b/src/lib/vendor/openssl/openssl_ecdsa.cpp deleted file mode 100644 index 0651cc280..000000000 --- a/src/lib/vendor/openssl/openssl_ecdsa.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* -* ECDSA via OpenSSL -* (C) 2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include -#include - -#if defined(BOTAN_HAS_ECDSA) && !defined(OPENSSL_NO_ECDSA) - -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace Botan { - -namespace { - -secure_vector PKCS8_for_openssl(const EC_PrivateKey& ec) - { - const PointGFp& pub_key = ec.public_point(); - const BigInt& priv_key = ec.private_value(); - - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(static_cast(1)) - .encode(BigInt::encode_1363(priv_key, priv_key.bytes()), OCTET_STRING) - .start_cons(ASN1_Tag(0), PRIVATE) - .raw_bytes(ec.domain().DER_encode(EC_DOMPAR_ENC_OID)) - .end_cons() - .start_cons(ASN1_Tag(1), PRIVATE) - .encode(EC2OSP(pub_key, PointGFp::UNCOMPRESSED), BIT_STRING) - .end_cons() - .end_cons() - .get_contents(); - } - -int OpenSSL_EC_nid_for(const OID& oid) - { - if(oid.empty()) - return -1; - - static const std::map nid_map = { - //{ "secp160r1", NID_secp160r1 }, - //{ "secp160r2", NID_secp160r2 }, - { "secp192r1", NID_X9_62_prime192v1 }, - { "secp224r1", NID_secp224r1 }, - { "secp256r1", NID_X9_62_prime256v1 }, - { "secp384r1", NID_secp384r1 }, - { "secp521r1", NID_secp521r1 } - // TODO: OpenSSL 1.0.2 added brainpool curves - }; - - const std::string name = OIDS::lookup(oid); - auto i = nid_map.find(name); - if(i != nid_map.end()) - return i->second; - - return -1; - } - -class OpenSSL_ECDSA_Verification_Operation : public PK_Ops::Verification_with_EMSA - { - public: - typedef ECDSA_PublicKey Key_Type; - - static OpenSSL_ECDSA_Verification_Operation* make(const Spec& spec) - { - if(const ECDSA_PublicKey* ecdsa = dynamic_cast(&spec.key())) - { - const int nid = OpenSSL_EC_nid_for(ecdsa->domain().get_oid()); - if(nid > 0) - return new OpenSSL_ECDSA_Verification_Operation(*ecdsa, spec.padding(), nid); - } - - return nullptr; - } - - OpenSSL_ECDSA_Verification_Operation(const ECDSA_PublicKey& ecdsa, const std::string& emsa, int nid) : - PK_Ops::Verification_with_EMSA(emsa), m_ossl_ec(::EC_KEY_new(), ::EC_KEY_free) - { - std::unique_ptr<::EC_GROUP, std::function> grp(::EC_GROUP_new_by_curve_name(nid), - ::EC_GROUP_free); - - if(!grp) - throw OpenSSL_Error("EC_GROUP_new_by_curve_name"); - - ::EC_KEY_set_group(m_ossl_ec.get(), grp.get()); - - const secure_vector enc = EC2OSP(ecdsa.public_point(), PointGFp::UNCOMPRESSED); - const byte* enc_ptr = enc.data(); - EC_KEY* key_ptr = m_ossl_ec.get(); - if(!::o2i_ECPublicKey(&key_ptr, &enc_ptr, enc.size())) - throw OpenSSL_Error("o2i_ECPublicKey"); - - const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get()); - m_order_bits = ::EC_GROUP_get_degree(group); - } - - size_t message_parts() const override { return 2; } - size_t message_part_size() const override { return (m_order_bits + 7) / 8; } - size_t max_input_bits() const override { return m_order_bits; } - - bool with_recovery() const override { return false; } - - bool verify(const byte msg[], size_t msg_len, - const byte sig_bytes[], size_t sig_len) override - { - if(sig_len != message_part_size() * message_parts()) - return false; - - std::unique_ptr> sig(nullptr, ECDSA_SIG_free); - sig.reset(::ECDSA_SIG_new()); - - sig->r = BN_bin2bn(sig_bytes , sig_len / 2, nullptr); - sig->s = BN_bin2bn(sig_bytes + sig_len / 2, sig_len / 2, nullptr); - - const int res = ECDSA_do_verify(msg, msg_len, sig.get(), m_ossl_ec.get()); - if(res < 0) - throw OpenSSL_Error("ECDSA_do_verify"); - return (res == 1); - } - - private: - std::unique_ptr> m_ossl_ec; - size_t m_order_bits = 0; - }; - -class OpenSSL_ECDSA_Signing_Operation : public PK_Ops::Signature_with_EMSA - { - public: - typedef ECDSA_PrivateKey Key_Type; - - static OpenSSL_ECDSA_Signing_Operation* make(const Spec& spec) - { - if(const ECDSA_PrivateKey* ecdsa = dynamic_cast(&spec.key())) - { - const int nid = OpenSSL_EC_nid_for(ecdsa->domain().get_oid()); - if(nid > 0) - return new OpenSSL_ECDSA_Signing_Operation(*ecdsa, spec.padding()); - } - - return nullptr; - } - - OpenSSL_ECDSA_Signing_Operation(const ECDSA_PrivateKey& ecdsa, const std::string& emsa) : - PK_Ops::Signature_with_EMSA(emsa), - m_ossl_ec(nullptr, ::EC_KEY_free) - { - const secure_vector der = PKCS8_for_openssl(ecdsa); - const byte* der_ptr = der.data(); - m_ossl_ec.reset(d2i_ECPrivateKey(nullptr, &der_ptr, der.size())); - if(!m_ossl_ec) - throw OpenSSL_Error("d2i_ECPrivateKey"); - - const EC_GROUP* group = ::EC_KEY_get0_group(m_ossl_ec.get()); - m_order_bits = ::EC_GROUP_get_degree(group); - } - - secure_vector raw_sign(const byte msg[], size_t msg_len, - RandomNumberGenerator&) override - { - std::unique_ptr> sig(nullptr, ECDSA_SIG_free); - sig.reset(::ECDSA_do_sign(msg, msg_len, m_ossl_ec.get())); - - if(!sig) - throw OpenSSL_Error("ECDSA_do_sign"); - - const size_t order_bytes = message_part_size(); - const size_t r_bytes = BN_num_bytes(sig->r); - const size_t s_bytes = BN_num_bytes(sig->s); - secure_vector sigval(2*order_bytes); - BN_bn2bin(sig->r, &sigval[order_bytes - r_bytes]); - BN_bn2bin(sig->s, &sigval[2*order_bytes - s_bytes]); - return sigval; - } - - size_t message_parts() const override { return 2; } - size_t message_part_size() const override { return (m_order_bits + 7) / 8; } - size_t max_input_bits() const override { return m_order_bits; } - - private: - std::unique_ptr> m_ossl_ec; - size_t m_order_bits = 0; - }; - -BOTAN_REGISTER_TYPE(PK_Ops::Verification, OpenSSL_ECDSA_Verification_Operation, "ECDSA", - OpenSSL_ECDSA_Verification_Operation::make, - "openssl", BOTAN_OPENSSL_ECDSA_PRIO); - -BOTAN_REGISTER_TYPE(PK_Ops::Signature, OpenSSL_ECDSA_Signing_Operation, "ECDSA", - OpenSSL_ECDSA_Signing_Operation::make, - "openssl", BOTAN_OPENSSL_ECDSA_PRIO); - -} - -} - -#endif // BOTAN_HAS_ECDSA && !OPENSSL_NO_ECDSA diff --git a/src/lib/vendor/openssl/openssl_hash.cpp b/src/lib/vendor/openssl/openssl_hash.cpp deleted file mode 100644 index c89dd777d..000000000 --- a/src/lib/vendor/openssl/openssl_hash.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* -* OpenSSL Hash Functions -* (C) 1999-2007,2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include -#include -#include -#include - -namespace Botan { - -namespace { - -class OpenSSL_HashFunction : public HashFunction - { - public: - void clear() - { - const EVP_MD* algo = EVP_MD_CTX_md(&m_md); - EVP_DigestInit_ex(&m_md, algo, nullptr); - } - - std::string name() const { return m_name; } - - HashFunction* clone() const - { - const EVP_MD* algo = EVP_MD_CTX_md(&m_md); - return new OpenSSL_HashFunction(algo, name()); - } - - size_t output_length() const - { - return EVP_MD_size(EVP_MD_CTX_md(&m_md)); - } - - size_t hash_block_size() const - { - return EVP_MD_block_size(EVP_MD_CTX_md(&m_md)); - } - - OpenSSL_HashFunction(const EVP_MD* md, const std::string& name) : m_name(name) - { - EVP_MD_CTX_init(&m_md); - EVP_DigestInit_ex(&m_md, md, nullptr); - } - - ~OpenSSL_HashFunction() - { - EVP_MD_CTX_cleanup(&m_md); - } - - private: - void add_data(const byte input[], size_t length) - { - EVP_DigestUpdate(&m_md, input, length); - } - - void final_result(byte output[]) - { - EVP_DigestFinal_ex(&m_md, output, nullptr); - const EVP_MD* algo = EVP_MD_CTX_md(&m_md); - EVP_DigestInit_ex(&m_md, algo, nullptr); - } - - std::string m_name; - EVP_MD_CTX m_md; - }; - -std::function -make_evp_hash_maker(const EVP_MD* md, const char* algo) - { - return [md,algo](const HashFunction::Spec&) - { - return new OpenSSL_HashFunction(md, algo); - }; - } - -#define BOTAN_REGISTER_OPENSSL_EVP_HASH(NAME, EVP) \ - BOTAN_REGISTER_TYPE(HashFunction, OpenSSL_HashFunction ## EVP, NAME, \ - make_evp_hash_maker(EVP(), NAME), "openssl", BOTAN_OPENSSL_HASH_PRIO); - -#if !defined(OPENSSL_NO_SHA) - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-160", EVP_sha1); -#endif - -#if !defined(OPENSSL_NO_SHA256) - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-224", EVP_sha224); - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-256", EVP_sha256); -#endif - -#if !defined(OPENSSL_NO_SHA512) - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-384", EVP_sha384); - BOTAN_REGISTER_OPENSSL_EVP_HASH("SHA-512", EVP_sha512); -#endif - -#if !defined(OPENSSL_NO_MD2) - BOTAN_REGISTER_OPENSSL_EVP_HASH("MD2", EVP_md2); -#endif - -#if !defined(OPENSSL_NO_MD4) - BOTAN_REGISTER_OPENSSL_EVP_HASH("MD4", EVP_md4); -#endif - -#if !defined(OPENSSL_NO_MD5) - BOTAN_REGISTER_OPENSSL_EVP_HASH("MD5", EVP_md5); -#endif - -#if !defined(OPENSSL_NO_RIPEMD) - BOTAN_REGISTER_OPENSSL_EVP_HASH("RIPEMD-160", EVP_ripemd160); -#endif - -} - -} diff --git a/src/lib/vendor/openssl/openssl_rc4.cpp b/src/lib/vendor/openssl/openssl_rc4.cpp deleted file mode 100644 index 1f5675095..000000000 --- a/src/lib/vendor/openssl/openssl_rc4.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/* -* OpenSSL RC4 -* (C) 1999-2007,2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include -#include -#include -#include -#include - -namespace Botan { - -namespace { - -class OpenSSL_RC4 : public StreamCipher - { - public: - void clear() { clear_mem(&m_rc4, 1); } - - std::string name() const { return "RC4"; } - StreamCipher* clone() const { return new OpenSSL_RC4; } - - Key_Length_Specification key_spec() const - { - return Key_Length_Specification(1, 32); - } - - OpenSSL_RC4(size_t skip = 0) : m_skip(skip) { clear(); } - ~OpenSSL_RC4() { clear(); } - private: - void cipher(const byte in[], byte out[], size_t length) - { - ::RC4(&m_rc4, length, in, out); - } - - void key_schedule(const byte key[], size_t length) - { - ::RC4_set_key(&m_rc4, length, key); - byte d = 0; - for(size_t i = 0; i != m_skip; ++i) - ::RC4(&m_rc4, 1, &d, &d); - } - - size_t m_skip; - RC4_KEY m_rc4; - }; - -} - -BOTAN_REGISTER_TYPE(StreamCipher, OpenSSL_RC4, "RC4", (make_new_T_1len), - "openssl", BOTAN_OPENSSL_RC4_PRIO); - -} diff --git a/src/lib/vendor/openssl/openssl_rsa.cpp b/src/lib/vendor/openssl/openssl_rsa.cpp deleted file mode 100644 index 3a7cd0dcf..000000000 --- a/src/lib/vendor/openssl/openssl_rsa.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* -* OpenSSL RSA interface -* (C) 2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include - -#if defined(BOTAN_HAS_RSA) - -#include -#include -#include -#include - -#include -#include -#include - -namespace Botan { - -namespace { - -std::pair get_openssl_enc_pad(const std::string& eme) - { - ERR_load_crypto_strings(); - if(eme == "Raw") - return std::make_pair(RSA_NO_PADDING, 0); - else if(eme == "EME-PKCS1-v1_5") - return std::make_pair(RSA_PKCS1_PADDING, 11); - else if(eme == "OAEP(SHA-1)") - return std::make_pair(RSA_PKCS1_OAEP_PADDING, 41); - else - throw Lookup_Error("OpenSSL RSA does not support EME " + eme); - } - -secure_vector strip_leading_zeros(const secure_vector& input) - { - size_t leading_zeros = 0; - - for(size_t i = 0; i != input.size(); ++i) - { - if(input[i] != 0) - break; - ++leading_zeros; - } - - secure_vector output(&input[leading_zeros], - &input[input.size()]); - return output; - } - -class OpenSSL_RSA_Encryption_Operation : public PK_Ops::Encryption - { - public: - typedef RSA_PublicKey Key_Type; - - static OpenSSL_RSA_Encryption_Operation* make(const Spec& spec) - { - try - { - if(auto* key = dynamic_cast(&spec.key())) - { - auto pad_info = get_openssl_enc_pad(spec.padding()); - return new OpenSSL_RSA_Encryption_Operation(*key, pad_info.first, pad_info.second); - } - } - catch(...) {} - - return nullptr; - } - - OpenSSL_RSA_Encryption_Operation(const RSA_PublicKey& rsa, int pad, size_t pad_overhead) : - m_openssl_rsa(nullptr, ::RSA_free), m_padding(pad) - { - const std::vector der = rsa.x509_subject_public_key(); - const byte* der_ptr = der.data(); - m_openssl_rsa.reset(::d2i_RSAPublicKey(nullptr, &der_ptr, der.size())); - if(!m_openssl_rsa) - throw OpenSSL_Error("d2i_RSAPublicKey"); - - m_bits = 8 * (n_size() - pad_overhead) - 1; - } - - size_t max_input_bits() const override { return m_bits; }; - - secure_vector encrypt(const byte msg[], size_t msg_len, - RandomNumberGenerator&) override - { - const size_t mod_sz = n_size(); - - if(msg_len > mod_sz) - throw Invalid_Argument("Input too large for RSA key"); - - secure_vector outbuf(mod_sz); - - secure_vector inbuf; - - if(m_padding == RSA_NO_PADDING) - { - inbuf.resize(mod_sz); - copy_mem(&inbuf[mod_sz - msg_len], msg, msg_len); - } - else - { - inbuf.assign(msg, msg + msg_len); - } - - int rc = ::RSA_public_encrypt(inbuf.size(), inbuf.data(), outbuf.data(), - m_openssl_rsa.get(), m_padding); - if(rc < 0) - throw OpenSSL_Error("RSA_public_encrypt"); - - return outbuf; - } - - private: - size_t n_size() const { return ::RSA_size(m_openssl_rsa.get()); } - std::unique_ptr> m_openssl_rsa; - size_t m_bits = 0; - int m_padding = 0; - }; - -class OpenSSL_RSA_Decryption_Operation : public PK_Ops::Decryption - { - public: - typedef RSA_PrivateKey Key_Type; - - static OpenSSL_RSA_Decryption_Operation* make(const Spec& spec) - { - try - { - if(auto* key = dynamic_cast(&spec.key())) - { - auto pad_info = get_openssl_enc_pad(spec.padding()); - return new OpenSSL_RSA_Decryption_Operation(*key, pad_info.first); - } - } - catch(...) {} - - return nullptr; - } - - OpenSSL_RSA_Decryption_Operation(const RSA_PrivateKey& rsa, int pad) : - m_openssl_rsa(nullptr, ::RSA_free), m_padding(pad) - { - const secure_vector der = rsa.pkcs8_private_key(); - const byte* der_ptr = der.data(); - m_openssl_rsa.reset(d2i_RSAPrivateKey(nullptr, &der_ptr, der.size())); - if(!m_openssl_rsa) - throw OpenSSL_Error("d2i_RSAPrivateKey"); - } - - size_t max_input_bits() const override { return ::BN_num_bits(m_openssl_rsa->n) - 1; } - - secure_vector decrypt(const byte msg[], size_t msg_len) override - { - secure_vector buf(::RSA_size(m_openssl_rsa.get())); - int rc = ::RSA_private_decrypt(msg_len, msg, buf.data(), m_openssl_rsa.get(), m_padding); - if(rc < 0 || static_cast(rc) > buf.size()) - throw OpenSSL_Error("RSA_private_decrypt"); - buf.resize(rc); - - if(m_padding == RSA_NO_PADDING) - { - return strip_leading_zeros(buf); - } - return buf; - } - - private: - std::unique_ptr> m_openssl_rsa; - int m_padding = 0; - }; - -class OpenSSL_RSA_Verification_Operation : public PK_Ops::Verification_with_EMSA - { - public: - typedef RSA_PublicKey Key_Type; - - static OpenSSL_RSA_Verification_Operation* make(const Spec& spec) - { - if(const RSA_PublicKey* rsa = dynamic_cast(&spec.key())) - { - return new OpenSSL_RSA_Verification_Operation(*rsa, spec.padding()); - } - - return nullptr; - } - - OpenSSL_RSA_Verification_Operation(const RSA_PublicKey& rsa, const std::string& emsa) : - PK_Ops::Verification_with_EMSA(emsa), - m_openssl_rsa(nullptr, ::RSA_free) - { - const std::vector der = rsa.x509_subject_public_key(); - const byte* der_ptr = der.data(); - m_openssl_rsa.reset(::d2i_RSAPublicKey(nullptr, &der_ptr, der.size())); - } - - size_t max_input_bits() const override { return ::BN_num_bits(m_openssl_rsa->n) - 1; } - - bool with_recovery() const override { return true; } - - secure_vector verify_mr(const byte msg[], size_t msg_len) override - { - const size_t mod_sz = ::RSA_size(m_openssl_rsa.get()); - - if(msg_len > mod_sz) - throw Invalid_Argument("OpenSSL RSA verify input too large"); - - secure_vector inbuf(mod_sz); - copy_mem(&inbuf[mod_sz - msg_len], msg, msg_len); - - secure_vector outbuf(mod_sz); - - int rc = ::RSA_public_decrypt(inbuf.size(), inbuf.data(), outbuf.data(), - m_openssl_rsa.get(), RSA_NO_PADDING); - if(rc < 0) - throw Invalid_Argument("RSA_public_decrypt"); - - return strip_leading_zeros(outbuf); - } - private: - std::unique_ptr> m_openssl_rsa; - }; - -class OpenSSL_RSA_Signing_Operation : public PK_Ops::Signature_with_EMSA - { - public: - typedef RSA_PrivateKey Key_Type; - - static OpenSSL_RSA_Signing_Operation* make(const Spec& spec) - { - if(const RSA_PrivateKey* rsa = dynamic_cast(&spec.key())) - { - return new OpenSSL_RSA_Signing_Operation(*rsa, spec.padding()); - } - - return nullptr; - } - - OpenSSL_RSA_Signing_Operation(const RSA_PrivateKey& rsa, const std::string& emsa) : - PK_Ops::Signature_with_EMSA(emsa), - m_openssl_rsa(nullptr, ::RSA_free) - { - const secure_vector der = rsa.pkcs8_private_key(); - const byte* der_ptr = der.data(); - m_openssl_rsa.reset(d2i_RSAPrivateKey(nullptr, &der_ptr, der.size())); - if(!m_openssl_rsa) - throw OpenSSL_Error("d2i_RSAPrivateKey"); - } - - secure_vector raw_sign(const byte msg[], size_t msg_len, - RandomNumberGenerator&) override - { - const size_t mod_sz = ::RSA_size(m_openssl_rsa.get()); - - if(msg_len > mod_sz) - throw Invalid_Argument("OpenSSL RSA sign input too large"); - - secure_vector inbuf(mod_sz); - copy_mem(&inbuf[mod_sz - msg_len], msg, msg_len); - - secure_vector outbuf(mod_sz); - - int rc = ::RSA_private_encrypt(inbuf.size(), inbuf.data(), outbuf.data(), - m_openssl_rsa.get(), RSA_NO_PADDING); - if(rc < 0) - throw OpenSSL_Error("RSA_private_encrypt"); - - return outbuf; - } - - size_t max_input_bits() const override { return ::BN_num_bits(m_openssl_rsa->n) - 1; } - - private: - std::unique_ptr> m_openssl_rsa; - }; - -BOTAN_REGISTER_TYPE(PK_Ops::Verification, OpenSSL_RSA_Verification_Operation, "RSA", - OpenSSL_RSA_Verification_Operation::make, "openssl", BOTAN_OPENSSL_RSA_PRIO); - -BOTAN_REGISTER_TYPE(PK_Ops::Signature, OpenSSL_RSA_Signing_Operation, "RSA", - OpenSSL_RSA_Signing_Operation::make, "openssl", BOTAN_OPENSSL_RSA_PRIO); - -BOTAN_REGISTER_TYPE(PK_Ops::Encryption, OpenSSL_RSA_Encryption_Operation, "RSA", - OpenSSL_RSA_Encryption_Operation::make, "openssl", BOTAN_OPENSSL_RSA_PRIO); - -BOTAN_REGISTER_TYPE(PK_Ops::Decryption, OpenSSL_RSA_Decryption_Operation, "RSA", - OpenSSL_RSA_Decryption_Operation::make, "openssl", BOTAN_OPENSSL_RSA_PRIO); - -} - -} - -#endif // BOTAN_HAS_RSA -- cgit v1.2.3