aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure.py2
-rw-r--r--news.rst2
-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
7 files changed, 206 insertions, 6 deletions
diff --git a/configure.py b/configure.py
index b03802e56..24f74e134 100755
--- a/configure.py
+++ b/configure.py
@@ -523,7 +523,7 @@ def process_command_line(args): # pylint: disable=too-many-locals,too-many-state
help='minimize build')
# Should be derived from info.txt but this runs too early
- third_party = ['bearssl', 'boost', 'bzip2', 'lzma', 'openssl', 'sqlite3', 'zlib', 'tpm']
+ third_party = ['bearssl', 'boost', 'bzip2', 'lzma', 'openssl', 'commoncrypto', 'sqlite3', 'zlib', 'tpm']
for mod in third_party:
mods_group.add_option('--with-%s' % (mod),
diff --git a/news.rst b/news.rst
index be731b75d..8e75f558e 100644
--- a/news.rst
+++ b/news.rst
@@ -4,6 +4,8 @@ Release Notes
Version 2.8.0, Not Yet Released
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+* CommonCrypto hashing support (MD4, MD5, SHA, SHA224, SHA256, SHA384, SHA512)
+
* Support for negotiating TLS versions 1.0 and 1.1 is disabled in the default
TLS policy. In addition, support for negotiating TLS ciphersuites using CBC or
CCM mode is disabled by default. Applications which need to interop with old
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);
}