diff options
author | Jose Pereira <[email protected]> | 2018-09-03 21:16:42 -0700 |
---|---|---|
committer | Jose Pereira <[email protected]> | 2018-09-03 21:28:36 -0700 |
commit | b073b7430285d7a5079380a71e0be925250c50e5 (patch) | |
tree | 97f703569e126622a77cb8c3c081cde9bc019e7d /src | |
parent | 96ff9f19cf5baf2fe05ebf8456939d6dda555e2c (diff) |
Add support for hashing with CommonCrypto
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/hash/hash.cpp | 20 | ||||
-rw-r--r-- | src/lib/prov/commoncrypto/commoncrypto.h | 36 | ||||
-rw-r--r-- | src/lib/prov/commoncrypto/commoncrypto_hash.cpp | 139 | ||||
-rw-r--r-- | src/lib/prov/commoncrypto/info.txt | 9 | ||||
-rw-r--r-- | src/tests/test_pubkey.cpp | 4 |
5 files changed, 203 insertions, 5 deletions
diff --git a/src/lib/hash/hash.cpp b/src/lib/hash/hash.cpp index e30d00080..ad1a1bf0c 100644 --- a/src/lib/hash/hash.cpp +++ b/src/lib/hash/hash.cpp @@ -101,11 +101,27 @@ #include <botan/internal/openssl.h> #endif +#if defined(BOTAN_HAS_COMMONCRYPTO) + #include <botan/internal/commoncrypto.h> +#endif + namespace Botan { std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec, const std::string& provider) { + +#if defined(BOTAN_HAS_COMMONCRYPTO) + if(provider.empty() || provider == "commoncrypto") + { + if(auto hash = make_commoncrypto_hash(algo_spec)) + return hash; + + if(!provider.empty()) + return nullptr; + } +#endif + #if defined(BOTAN_HAS_OPENSSL) if(provider.empty() || provider == "openssl") { @@ -128,8 +144,6 @@ std::unique_ptr<HashFunction> HashFunction::create(const std::string& algo_spec, } #endif - // TODO: CommonCrypto hashes - if(provider.empty() == false && provider != "base") return nullptr; // unknown provider @@ -354,7 +368,7 @@ HashFunction::create_or_throw(const std::string& algo, std::vector<std::string> HashFunction::providers(const std::string& algo_spec) { - return probe_providers_of<HashFunction>(algo_spec, {"base", "bearssl", "openssl"}); + return probe_providers_of<HashFunction>(algo_spec, {"base", "bearssl", "openssl", "commoncrypto"}); } } diff --git a/src/lib/prov/commoncrypto/commoncrypto.h b/src/lib/prov/commoncrypto/commoncrypto.h new file mode 100644 index 000000000..da4adc8bf --- /dev/null +++ b/src/lib/prov/commoncrypto/commoncrypto.h @@ -0,0 +1,36 @@ +/* +* Utils for calling CommonCrypto +* (C) 2018 Jose Pereira +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#ifndef BOTAN_INTERNAL_COMMONCRYPTO_H_ +#define BOTAN_INTERNAL_COMMONCRYPTO_H_ + +#include <botan/pk_ops_fwd.h> +#include <botan/secmem.h> +#include <botan/exceptn.h> +#include <memory> +#include <string> + +#include <CommonCrypto/CommonCrypto.h> + +namespace Botan { + +class HashFunction; + +class BOTAN_PUBLIC_API(2,0) CommonCrypto_Error final : public Exception + { + public: + CommonCrypto_Error(const std::string& what) : + Exception(what + " failed.") {} + }; + +/* Hash */ + +std::unique_ptr<HashFunction> make_commoncrypto_hash(const std::string& name); + +} + +#endif diff --git a/src/lib/prov/commoncrypto/commoncrypto_hash.cpp b/src/lib/prov/commoncrypto/commoncrypto_hash.cpp new file mode 100644 index 000000000..81afa0e01 --- /dev/null +++ b/src/lib/prov/commoncrypto/commoncrypto_hash.cpp @@ -0,0 +1,139 @@ +/* +* CommonCrypto Hash Functions +* (C) 2018 Jose Pereira +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include <botan/hash.h> +#include <botan/internal/commoncrypto.h> + +#include <unordered_map> + +namespace Botan { + +namespace { + +template <class CTX> +class CommonCrypto_HashFunction final : public HashFunction + { + public: + + struct digest_config_t { + std::string name; + size_t digestLength; + size_t blockSize; + int (*init)(CTX *); + int (*update)(CTX *, const void *, CC_LONG len); + int (*final)(unsigned char *, CTX*); + }; + + void clear() override + { + if(m_info.init(&m_ctx) != 1) + throw CommonCrypto_Error("CC_" + m_info.name + "_Init"); + } + + std::string provider() const override { return "commoncrypto"; } + std::string name() const override { return m_info.name; } + + HashFunction* clone() const override + { + return new CommonCrypto_HashFunction(m_info); + } + + std::unique_ptr<HashFunction> copy_state() const override + { + return std::unique_ptr<CommonCrypto_HashFunction>( + new CommonCrypto_HashFunction(m_info, m_ctx)); + } + + size_t output_length() const override + { + return m_info.digestLength; + } + + size_t hash_block_size() const override + { + return m_info.blockSize; + } + + CommonCrypto_HashFunction(const digest_config_t& info) : + m_info(info) + { + clear(); + } + + CommonCrypto_HashFunction(const digest_config_t& info, const CTX &ctx) : + m_ctx(ctx), m_info(info) {} + + private: + void add_data(const uint8_t input[], size_t length) override + { + if(m_info.update(&m_ctx, input, length) != 1) + throw CommonCrypto_Error("CC_" + m_info.name + "_Update"); + } + + void final_result(uint8_t output[]) override + { + if(m_info.final(output, &m_ctx) != 1) + throw CommonCrypto_Error("CC_" + m_info.name + "_Final"); + clear(); + } + + CTX m_ctx; + digest_config_t m_info; + }; +} + +std::unique_ptr<HashFunction> +make_commoncrypto_hash(const std::string& name) + { +#define MAKE_COMMONCRYPTO_HASH_3(name, hash, ctx) \ + std::unique_ptr<HashFunction>( \ + new CommonCrypto_HashFunction<CC_ ## ctx ## _CTX >({ \ + name, \ + CC_ ## hash ## _DIGEST_LENGTH, \ + CC_ ## hash ## _BLOCK_BYTES, \ + CC_ ## hash ## _Init, \ + CC_ ## hash ## _Update, \ + CC_ ## hash ## _Final \ + })); + +#define MAKE_COMMONCRYPTO_HASH_2(name, id) \ + MAKE_COMMONCRYPTO_HASH_3(name, id, id) + +#define MAKE_COMMONCRYPTO_HASH_1(id) \ + MAKE_COMMONCRYPTO_HASH_2(#id, id) + +#if defined(BOTAN_HAS_SHA2_32) + if(name == "SHA-224") + return MAKE_COMMONCRYPTO_HASH_3(name, SHA224, SHA256); + if(name == "SHA-256") + return MAKE_COMMONCRYPTO_HASH_2(name, SHA256); +#endif +#if defined(BOTAN_HAS_SHA2_64) + if(name == "SHA-384") + return MAKE_COMMONCRYPTO_HASH_3(name, SHA384, SHA512); + if(name == "SHA-512") + return MAKE_COMMONCRYPTO_HASH_2(name, SHA512); +#endif + +#if defined(BOTAN_HAS_SHA1) + if(name == "SHA-160" || name == "SHA-1" || name == "SHA1") + return MAKE_COMMONCRYPTO_HASH_2(name, SHA1); +#endif + +#if defined(BOTAN_HAS_MD5) + if(name == "MD5") + return MAKE_COMMONCRYPTO_HASH_1(MD5); + #endif + +#if defined(BOTAN_HAS_MD4) + if(name == "MD4") + return MAKE_COMMONCRYPTO_HASH_1(MD4); +#endif + return nullptr; + } + +} diff --git a/src/lib/prov/commoncrypto/info.txt b/src/lib/prov/commoncrypto/info.txt new file mode 100644 index 000000000..00dfb27ae --- /dev/null +++ b/src/lib/prov/commoncrypto/info.txt @@ -0,0 +1,9 @@ +<defines> +COMMONCRYPTO -> 20180903 +</defines> + +load_on vendor + +<header:internal> +commoncrypto.h +</header:internal> diff --git a/src/tests/test_pubkey.cpp b/src/tests/test_pubkey.cpp index 20bdc73ac..80b95b70b 100644 --- a/src/tests/test_pubkey.cpp +++ b/src/tests/test_pubkey.cpp @@ -93,7 +93,7 @@ std::string PK_Test::choose_padding(const VarMap& vars, std::vector<std::string> PK_Test::possible_providers(const std::string& /*params*/) { - return Test::provider_filter({ "base", "bearssl", "openssl", "tpm" }); + return Test::provider_filter({ "base", "commoncrypto", "bearssl", "openssl", "tpm" }); } Test::Result @@ -531,7 +531,7 @@ std::vector<std::string> PK_Key_Generation_Test::possible_providers( const std::string& algo) { std::vector<std::string> pk_provider = - Botan::probe_provider_private_key(algo, { "base", "openssl", "tpm" }); + Botan::probe_provider_private_key(algo, { "base", "commoncrypto", "openssl", "tpm" }); return Test::provider_filter(pk_provider); } |