aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJose Pereira <[email protected]>2018-09-03 21:16:42 -0700
committerJose Pereira <[email protected]>2018-09-03 21:28:36 -0700
commitb073b7430285d7a5079380a71e0be925250c50e5 (patch)
tree97f703569e126622a77cb8c3c081cde9bc019e7d /src
parent96ff9f19cf5baf2fe05ebf8456939d6dda555e2c (diff)
Add support for hashing with CommonCrypto
Diffstat (limited to 'src')
-rw-r--r--src/lib/hash/hash.cpp20
-rw-r--r--src/lib/prov/commoncrypto/commoncrypto.h36
-rw-r--r--src/lib/prov/commoncrypto/commoncrypto_hash.cpp139
-rw-r--r--src/lib/prov/commoncrypto/info.txt9
-rw-r--r--src/tests/test_pubkey.cpp4
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);
}