/* * BER encode a PKCS #8 private key, encrypted */ std::vector<uint8_t> BER_encode_encrypted_pbkdf_msec(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, std::chrono::milliseconds pbkdf_msec, size_t* pbkdf_iterations, const std::string& cipher, const std::string& pbkdf_hash) { #if defined(BOTAN_HAS_PKCS5_PBES2) const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info = pbes2_encrypt_msec(key.private_key_info(), pass, pbkdf_msec, pbkdf_iterations, cipher.empty() ? "AES-256/CBC" : cipher, pbkdf_hash.empty() ? "SHA-256" : pbkdf_hash, rng); std::vector<uint8_t> output; DER_Encoder(output) .start_cons(SEQUENCE) .encode(pbe_info.first) .encode(pbe_info.second, OCTET_STRING) .end_cons(); return output; #else BOTAN_UNUSED(key, rng, pass, pbkdf_msec, pbkdf_iterations, cipher, pbkdf_hash); throw Encoding_Error("BER_encode_encrypted_pbkdf_msec cannot encrypt because PBES2 disabled in build"); #endif }
/* * Extract an unencrypted private key and return it */ Private_Key* load_key(const std::string& fsname, RandomNumberGenerator& rng) { BOTAN_UNUSED(rng); DataSource_Stream in(fsname); return PKCS8::load_key(in).release(); }
/* * BER encode a PKCS #8 private key, encrypted */ std::vector<uint8_t> BER_encode(const Private_Key& key, RandomNumberGenerator& rng, const std::string& pass, std::chrono::milliseconds msec, const std::string& pbe_algo) { #if defined(BOTAN_HAS_PKCS5_PBES2) const auto pbe_params = choose_pbe_params(pbe_algo, key.algo_name()); const std::pair<AlgorithmIdentifier, std::vector<uint8_t>> pbe_info = pbes2_encrypt_msec(PKCS8::BER_encode(key), pass, msec, nullptr, pbe_params.first, pbe_params.second, rng); std::vector<uint8_t> output; DER_Encoder der(output); der.start_cons(SEQUENCE) .encode(pbe_info.first) .encode(pbe_info.second, OCTET_STRING) .end_cons(); return output; #else BOTAN_UNUSED(key, rng, pass, msec, pbe_algo); throw Encoding_Error("PKCS8::BER_encode cannot encrypt because PBES2 was disabled in build"); #endif }
/* * Extract an encrypted private key and return it */ Private_Key* load_key(DataSource& source, RandomNumberGenerator& rng, std::function<std::string ()> get_pass) { BOTAN_UNUSED(rng); return PKCS8::load_key(source, get_pass).release(); }
/* * Extract an encrypted private key and return it */ Private_Key* load_key(DataSource& source, RandomNumberGenerator& rng, const std::string& pass) { BOTAN_UNUSED(rng); return PKCS8::load_key(source, pass).release(); }
std::unique_ptr<PasswordHashFamily> PasswordHashFamily::create(const std::string& algo_spec, const std::string& provider) { const SCAN_Name req(algo_spec); #if defined(BOTAN_HAS_PBKDF2) if(req.algo_name() == "PBKDF2") { // TODO OpenSSL if(provider.empty() || provider == "base") { if(auto mac = MessageAuthenticationCode::create(req.arg(0))) return std::unique_ptr<PasswordHashFamily>(new PBKDF2_Family(mac.release())); if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")")) return std::unique_ptr<PasswordHashFamily>(new PBKDF2_Family(mac.release())); } return nullptr; } #endif #if defined(BOTAN_HAS_SCRYPT) if(req.algo_name() == "Scrypt") { return std::unique_ptr<PasswordHashFamily>(new Scrypt_Family); } #endif #if defined(BOTAN_HAS_PGP_S2K) if(req.algo_name() == "OpenPGP-S2K" && req.arg_count() == 1) { if(auto hash = HashFunction::create(req.arg(0))) { return std::unique_ptr<PasswordHashFamily>(new RFC4880_S2K_Family(hash.release())); } } #endif BOTAN_UNUSED(req); BOTAN_UNUSED(provider); return nullptr; }
ticks ECDSA_Timing_Test::measure_critical_function(std::vector<uint8_t> input) { const Botan::BigInt k(input.data(), input.size()); const Botan::BigInt msg(Timing_Test::timing_test_rng(), m_order.bits()); ticks start = get_ticks(); //The following ECDSA operations involve and should not leak any information about k. const Botan::PointGFp k_times_P = m_base_point.blinded_multiply(k, Timing_Test::timing_test_rng()); const Botan::BigInt r = m_mod_order.reduce(k_times_P.get_affine_x()); const Botan::BigInt s = m_mod_order.multiply(inverse_mod(k, m_order), mul_add(m_x, r, msg)); BOTAN_UNUSED(r); BOTAN_UNUSED(s); ticks end = get_ticks(); return (end - start); }
std::unique_ptr<Timing_Test> Timing_Test_Command::lookup_timing_test(const std::string& test_type) { #if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EME_PKCS1v15) && defined(BOTAN_HAS_EME_RAW) if(test_type == "bleichenbacher") { return std::unique_ptr<Timing_Test>(new Bleichenbacker_Timing_Test(2048)); } #endif #if defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EME_OAEP) && defined(BOTAN_HAS_EME_RAW) if(test_type == "manger") { return std::unique_ptr<Timing_Test>(new Manger_Timing_Test(2048)); } #endif #if defined(BOTAN_HAS_ECDSA) if(test_type == "ecdsa") { return std::unique_ptr<Timing_Test>(new ECDSA_Timing_Test("secp384r1")); } #endif #if defined(BOTAN_HAS_EC_CURVE_GFP) if(test_type == "ecc_mul") { return std::unique_ptr<Timing_Test>(new ECC_Mul_Timing_Test("brainpool512r1")); } #endif #if defined(BOTAN_HAS_NUMBERTHEORY) if(test_type == "inverse_mod") { return std::unique_ptr<Timing_Test>(new Invmod_Timing_Test(512)); } #endif #if defined(BOTAN_HAS_TLS_CBC) if(test_type == "lucky13sha1sec3" || test_type == "lucky13sha1sec4") { return std::unique_ptr<Timing_Test>(new Lucky13_Timing_Test("SHA-1", 20)); } if(test_type == "lucky13sha256sec3" || test_type == "lucky13sha256sec4") { return std::unique_ptr<Timing_Test>(new Lucky13_Timing_Test("SHA-256", 32)); } if(test_type == "lucky13sha384") { return std::unique_ptr<Timing_Test>(new Lucky13_Timing_Test("SHA-384", 48)); } #endif BOTAN_UNUSED(test_type); return nullptr; }
std::vector<Botan::CPUID::CPUID_bits> CPUID::bit_from_string(const std::string& tok) { #if defined(BOTAN_TARGET_CPU_IS_X86_FAMILY) if(tok == "sse2" || tok == "simd") return {Botan::CPUID::CPUID_SSE2_BIT}; if(tok == "ssse3") return {Botan::CPUID::CPUID_SSSE3_BIT}; if(tok == "aesni") return {Botan::CPUID::CPUID_AESNI_BIT}; if(tok == "clmul") return {Botan::CPUID::CPUID_CLMUL_BIT}; if(tok == "avx2") return {Botan::CPUID::CPUID_AVX2_BIT}; if(tok == "sha") return {Botan::CPUID::CPUID_SHA_BIT}; if(tok == "bmi2") return {Botan::CPUID::CPUID_BMI2_BIT}; if(tok == "adx") return {Botan::CPUID::CPUID_ADX_BIT}; if(tok == "intel_sha") return {Botan::CPUID::CPUID_SHA_BIT}; #elif defined(BOTAN_TARGET_CPU_IS_PPC_FAMILY) if(tok == "altivec" || tok == "simd") return {Botan::CPUID::CPUID_ALTIVEC_BIT}; #elif defined(BOTAN_TARGET_CPU_IS_ARM_FAMILY) if(tok == "neon" || tok == "simd") return {Botan::CPUID::CPUID_ARM_NEON_BIT}; if(tok == "armv8sha1") return {Botan::CPUID::CPUID_ARM_SHA1_BIT}; if(tok == "armv8sha2") return {Botan::CPUID::CPUID_ARM_SHA2_BIT}; if(tok == "armv8aes") return {Botan::CPUID::CPUID_ARM_AES_BIT}; if(tok == "armv8pmull") return {Botan::CPUID::CPUID_ARM_PMULL_BIT}; if(tok == "armv8sha3") return {Botan::CPUID::CPUID_ARM_SHA3_BIT}; if(tok == "armv8sha2_512") return {Botan::CPUID::CPUID_ARM_SHA2_512_BIT}; if(tok == "armv8sm3") return {Botan::CPUID::CPUID_ARM_SM3_BIT}; if(tok == "armv8sm4") return {Botan::CPUID::CPUID_ARM_SM4_BIT}; #else BOTAN_UNUSED(tok); #endif return {}; }
std::vector<std::string> get_files_recursive(const std::string& dir) { std::vector<std::string> files; #if defined(BOTAN_TARGET_OS_HAS_STL_FILESYSTEM_MSVC) && defined(BOTAN_BUILD_COMPILER_IS_MSVC) files = impl_stl_filesystem(dir); #elif defined(BOTAN_HAS_BOOST_FILESYSTEM) files = impl_boost_filesystem(dir); #elif defined(BOTAN_TARGET_OS_HAS_READDIR) files = impl_readdir(dir); #else BOTAN_UNUSED(dir); throw No_Filesystem_Access(); #endif std::sort(files.begin(), files.end()); return files; }
ticks ECDSA_Timing_Test::measure_critical_function(std::vector<uint8_t> input) { const Botan::BigInt k(input.data(), input.size()); const Botan::BigInt msg(5); // fixed message to minimize noise ticks start = get_ticks(); //The following ECDSA operations involve and should not leak any information about k. const Botan::BigInt k_inv = Botan::inverse_mod(k, m_group.get_order()); const Botan::PointGFp k_times_P = m_group.blinded_base_point_multiply(k, Timing_Test::timing_test_rng(), m_ws); const Botan::BigInt r = m_group.mod_order(k_times_P.get_affine_x()); const Botan::BigInt s = m_group.multiply_mod_order(k_inv, mul_add(m_x, r, msg)); BOTAN_UNUSED(r, s); ticks end = get_ticks(); return (end - start); }
std::vector<std::string> probe_provider_private_key(const std::string& alg_name, const std::vector<std::string> possible) { std::vector<std::string> providers; for(auto&& prov : possible) { if(prov == "base" || #if defined(BOTAN_HAS_OPENSSL) (prov == "openssl" && alg_name == "RSA") || #endif 0) { providers.push_back(prov); // available } } BOTAN_UNUSED(alg_name); return providers; }
std::unique_ptr<KDF> KDF::create(const std::string& algo_spec, const std::string& provider) { const SCAN_Name req(algo_spec); #if defined(BOTAN_HAS_HKDF) if(req.algo_name() == "HKDF" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { return kdf_create_mac_or_hash<HKDF>(req.arg(0)); } } if(req.algo_name() == "HKDF-Extract" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { return kdf_create_mac_or_hash<HKDF_Extract>(req.arg(0)); } } if(req.algo_name() == "HKDF-Expand" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { return kdf_create_mac_or_hash<HKDF_Expand>(req.arg(0)); } } #endif #if defined(BOTAN_HAS_KDF2) if(req.algo_name() == "KDF2" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { if(auto hash = HashFunction::create(req.arg(0))) return std::unique_ptr<KDF>(new KDF2(hash.release())); } } #endif #if defined(BOTAN_HAS_KDF1_18033) if(req.algo_name() == "KDF1-18033" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { if(auto hash = HashFunction::create(req.arg(0))) return std::unique_ptr<KDF>(new KDF1_18033(hash.release())); } } #endif #if defined(BOTAN_HAS_KDF1) if(req.algo_name() == "KDF1" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { if(auto hash = HashFunction::create(req.arg(0))) return std::unique_ptr<KDF>(new KDF1(hash.release())); } } #endif #if defined(BOTAN_HAS_TLS_V10_PRF) if(req.algo_name() == "TLS-PRF" && req.arg_count() == 0) { if(provider.empty() || provider == "base") { return std::unique_ptr<KDF>(new TLS_PRF); } } #endif #if defined(BOTAN_HAS_TLS_V12_PRF) if(req.algo_name() == "TLS-12-PRF" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { return kdf_create_mac_or_hash<TLS_12_PRF>(req.arg(0)); } } #endif #if defined(BOTAN_HAS_X942_PRF) if(req.algo_name() == "X9.42-PRF" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { return std::unique_ptr<KDF>(new X942_PRF(req.arg(0))); } } #endif #if defined(BOTAN_HAS_SP800_108) if(req.algo_name() == "SP800-108-Counter" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { return kdf_create_mac_or_hash<SP800_108_Counter>(req.arg(0)); } } if(req.algo_name() == "SP800-108-Feedback" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { return kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0)); } } if(req.algo_name() == "SP800-108-Pipeline" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { return kdf_create_mac_or_hash<SP800_108_Pipeline>(req.arg(0)); } } #endif #if defined(BOTAN_HAS_SP800_56A) if(req.algo_name() == "SP800-56A" && req.arg_count() == 1) { if(auto hash = HashFunction::create(req.arg(0))) return std::unique_ptr<KDF>(new SP800_56A_Hash(hash.release())); if(auto mac = MessageAuthenticationCode::create(req.arg(0))) return std::unique_ptr<KDF>(new SP800_56A_HMAC(mac.release())); } #endif #if defined(BOTAN_HAS_SP800_56C) if(req.algo_name() == "SP800-56C" && req.arg_count() == 1) { std::unique_ptr<KDF> exp(kdf_create_mac_or_hash<SP800_108_Feedback>(req.arg(0))); if(exp) { if(auto mac = MessageAuthenticationCode::create(req.arg(0))) return std::unique_ptr<KDF>(new SP800_56C(mac.release(), exp.release())); if(auto mac = MessageAuthenticationCode::create("HMAC(" + req.arg(0) + ")")) return std::unique_ptr<KDF>(new SP800_56C(mac.release(), exp.release())); } } #endif BOTAN_UNUSED(req); BOTAN_UNUSED(provider); return nullptr; }
std::shared_ptr<const X509_CRL> Certificate_Store_MacOS::find_crl_for(const X509_Certificate& subject) const { BOTAN_UNUSED(subject); return {}; }
std::shared_ptr<const X509_Certificate> Certificate_Store_MacOS::find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const { BOTAN_UNUSED(subject_hash); throw Not_Implemented("Certificate_Store_MacOS::find_cert_by_raw_subject_dn_sha256"); }
Cert_Pointer Certificate_Store_Windows::find_cert_by_raw_subject_dn_sha256( const std::vector<uint8_t>& subject_hash) const { BOTAN_UNUSED(subject_hash); throw Not_Implemented("Certificate_Store_Windows::find_cert_by_raw_subject_dn_sha256"); }
/* * Make a copy of this private key */ Private_Key* copy_key(const Private_Key& key, RandomNumberGenerator& rng) { BOTAN_UNUSED(rng); return PKCS8::copy_key(key).release(); }
std::shared_ptr<const X509_CRL> Certificate_Store_Windows::find_crl_for(const X509_Certificate& subject) const { // TODO: this could be implemented by using the CertFindCRLInStore function BOTAN_UNUSED(subject); return {}; }
std::unique_ptr<Private_Key> create_private_key(const std::string& alg_name, RandomNumberGenerator& rng, const std::string& params, const std::string& provider) { /* * Default paramaters are chosen for work factor > 2**128 where possible */ #if defined(BOTAN_HAS_CURVE_25519) if(alg_name == "Curve25519") return std::unique_ptr<Private_Key>(new Curve25519_PrivateKey(rng)); #endif #if defined(BOTAN_HAS_RSA) if(alg_name == "RSA") { const size_t rsa_bits = (params.empty() ? 3072 : to_u32bit(params)); #if defined(BOTAN_HAS_OPENSSL) if(provider.empty() || provider == "openssl") { std::unique_ptr<Botan::Private_Key> pk; if((pk = make_openssl_rsa_private_key(rng, rsa_bits))) return pk; if(!provider.empty()) return nullptr; } #endif return std::unique_ptr<Private_Key>(new RSA_PrivateKey(rng, rsa_bits)); } #endif #if defined(BOTAN_HAS_MCELIECE) if(alg_name == "McEliece") { std::vector<std::string> mce_param = Botan::split_on(params.empty() ? "2960,57" : params, ','); if(mce_param.size() != 2) throw Invalid_Argument("create_private_key bad McEliece parameters " + params); size_t mce_n = Botan::to_u32bit(mce_param[0]); size_t mce_t = Botan::to_u32bit(mce_param[1]); return std::unique_ptr<Botan::Private_Key>(new Botan::McEliece_PrivateKey(rng, mce_n, mce_t)); } #endif #if defined(BOTAN_HAS_XMSS) if(alg_name == "XMSS") { return std::unique_ptr<Private_Key>( new XMSS_PrivateKey(XMSS_Parameters(params.empty() ? "XMSS_SHA2-512_W16_H10" : params).oid(), rng)); } #endif #if defined(BOTAN_HAS_ED25519) if(alg_name == "Ed25519") { return std::unique_ptr<Private_Key>(new Ed25519_PrivateKey(rng)); } #endif // ECC crypto #if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO) if(alg_name == "ECDSA" || alg_name == "ECDH" || alg_name == "ECKCDSA" || alg_name == "ECGDSA" || alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc" || alg_name == "GOST-34.10") { const EC_Group ec_group(params.empty() ? default_ec_group_for(alg_name) : params); #if defined(BOTAN_HAS_ECDSA) if(alg_name == "ECDSA") return std::unique_ptr<Private_Key>(new ECDSA_PrivateKey(rng, ec_group)); #endif #if defined(BOTAN_HAS_ECDH) if(alg_name == "ECDH") return std::unique_ptr<Private_Key>(new ECDH_PrivateKey(rng, ec_group)); #endif #if defined(BOTAN_HAS_ECKCDSA) if(alg_name == "ECKCDSA") return std::unique_ptr<Private_Key>(new ECKCDSA_PrivateKey(rng, ec_group)); #endif #if defined(BOTAN_HAS_GOST_34_10_2001) if(alg_name == "GOST-34.10") return std::unique_ptr<Private_Key>(new GOST_3410_PrivateKey(rng, ec_group)); #endif #if defined(BOTAN_HAS_SM2) if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") return std::unique_ptr<Private_Key>(new SM2_PrivateKey(rng, ec_group)); #endif #if defined(BOTAN_HAS_ECGDSA) if(alg_name == "ECGDSA") return std::unique_ptr<Private_Key>(new ECGDSA_PrivateKey(rng, ec_group)); #endif } #endif // DL crypto #if defined(BOTAN_HAS_DL_GROUP) if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal") { std::string default_group = (alg_name == "DSA") ? "dsa/botan/2048" : "modp/ietf/2048"; DL_Group modp_group(params.empty() ? default_group : params); #if defined(BOTAN_HAS_DIFFIE_HELLMAN) if(alg_name == "DH") return std::unique_ptr<Private_Key>(new DH_PrivateKey(rng, modp_group)); #endif #if defined(BOTAN_HAS_DSA) if(alg_name == "DSA") return std::unique_ptr<Private_Key>(new DSA_PrivateKey(rng, modp_group)); #endif #if defined(BOTAN_HAS_ELGAMAL) if(alg_name == "ElGamal") return std::unique_ptr<Private_Key>(new ElGamal_PrivateKey(rng, modp_group)); #endif } #endif BOTAN_UNUSED(alg_name, rng, params, provider); return std::unique_ptr<Private_Key>(); }
/* * Extract an unencrypted private key and return it */ Private_Key* load_key(DataSource& source, RandomNumberGenerator& rng) { BOTAN_UNUSED(rng); return PKCS8::load_key(source).release(); }
std::unique_ptr<StreamCipher> StreamCipher::create(const std::string& algo_spec, const std::string& provider) { const SCAN_Name req(algo_spec); #if defined(BOTAN_HAS_CTR_BE) if((req.algo_name() == "CTR-BE" || req.algo_name() == "CTR") && req.arg_count_between(1,2)) { if(provider.empty() || provider == "base") { auto cipher = BlockCipher::create(req.arg(0)); if(cipher) { size_t ctr_size = req.arg_as_integer(1, cipher->block_size()); return std::unique_ptr<StreamCipher>(new CTR_BE(cipher.release(), ctr_size)); } } } #endif #if defined(BOTAN_HAS_CHACHA) if(req.algo_name() == "ChaCha") { if(provider.empty() || provider == "base") return std::unique_ptr<StreamCipher>(new ChaCha(req.arg_as_integer(0, 20))); } if(req.algo_name() == "ChaCha20") { if(provider.empty() || provider == "base") return std::unique_ptr<StreamCipher>(new ChaCha(20)); } #endif #if defined(BOTAN_HAS_SALSA20) if(req.algo_name() == "Salsa20") { if(provider.empty() || provider == "base") return std::unique_ptr<StreamCipher>(new Salsa20); } #endif #if defined(BOTAN_HAS_SHAKE_CIPHER) if(req.algo_name() == "SHAKE-128") { if(provider.empty() || provider == "base") return std::unique_ptr<StreamCipher>(new SHAKE_128_Cipher); } #endif #if defined(BOTAN_HAS_OFB) if(req.algo_name() == "OFB" && req.arg_count() == 1) { if(provider.empty() || provider == "base") { if(auto c = BlockCipher::create(req.arg(0))) return std::unique_ptr<StreamCipher>(new OFB(c.release())); } } #endif #if defined(BOTAN_HAS_RC4) if(req.algo_name() == "RC4" || req.algo_name() == "ARC4" || req.algo_name() == "MARK-4") { const size_t skip = (req.algo_name() == "MARK-4") ? 256 : req.arg_as_integer(0, 0); #if defined(BOTAN_HAS_OPENSSL) if(provider.empty() || provider == "openssl") { return std::unique_ptr<StreamCipher>(make_openssl_rc4(skip)); } #endif if(provider.empty() || provider == "base") { return std::unique_ptr<StreamCipher>(new RC4(skip)); } } #endif BOTAN_UNUSED(req); BOTAN_UNUSED(provider); return nullptr; }