aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-09-04 19:30:16 -0400
committerJack Lloyd <[email protected]>2018-09-04 19:30:16 -0400
commit3b336f2a80053d472380b29aab06ad0acb66d3f1 (patch)
tree04ab9a62e4d06095376faa6f983bda1627cb2f9a
parentad2cad62e0fcd186d489e56a136e376c0fa3a8f0 (diff)
parentc81c5281eef4bc467cc1e101bd99438198b703c7 (diff)
Merge GH #1667 Add hashing with CommonCrypto
-rwxr-xr-xconfigure.py2
-rw-r--r--news.rst2
-rw-r--r--src/build-data/os/darwin.txt1
-rw-r--r--src/build-data/os/ios.txt1
-rw-r--r--src/lib/hash/hash.cpp20
-rw-r--r--src/lib/prov/commoncrypto/commoncrypto.h34
-rw-r--r--src/lib/prov/commoncrypto/commoncrypto_hash.cpp139
-rw-r--r--src/lib/prov/commoncrypto/info.txt13
-rwxr-xr-xsrc/scripts/ci_build.py6
-rw-r--r--src/tests/test_pubkey.cpp4
10 files changed, 215 insertions, 7 deletions
diff --git a/configure.py b/configure.py
index 21b1f8f1a..1025835e5 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/build-data/os/darwin.txt b/src/build-data/os/darwin.txt
index 056d535e7..5f460b1c6 100644
--- a/src/build-data/os/darwin.txt
+++ b/src/build-data/os/darwin.txt
@@ -16,6 +16,7 @@ arc4random
dev_random
security_framework
+commoncrypto
sockets
threads
filesystem
diff --git a/src/build-data/os/ios.txt b/src/build-data/os/ios.txt
index 0e3eb7c4b..286e10fd1 100644
--- a/src/build-data/os/ios.txt
+++ b/src/build-data/os/ios.txt
@@ -10,6 +10,7 @@ posix1
posix_mlock
arc4random
+commoncrypto
sockets
threads
filesystem
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..34b2a3f35
--- /dev/null
+++ b/src/lib/prov/commoncrypto/commoncrypto.h
@@ -0,0 +1,34 @@
+/*
+* 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>
+
+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..bb5a5debe
--- /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 <CommonCrypto/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..00f92cd58
--- /dev/null
+++ b/src/lib/prov/commoncrypto/info.txt
@@ -0,0 +1,13 @@
+<defines>
+COMMONCRYPTO -> 20180903
+</defines>
+
+load_on vendor
+
+<header:internal>
+commoncrypto.h
+</header:internal>
+
+<os_features>
+commoncrypto
+</os_features>
diff --git a/src/scripts/ci_build.py b/src/scripts/ci_build.py
index 66d537d53..fe73156af 100755
--- a/src/scripts/ci_build.py
+++ b/src/scripts/ci_build.py
@@ -170,12 +170,16 @@ def determine_flags(target, target_os, target_cpu, target_cc, cc_bin, ccache, ro
if target_os in ['osx', 'linux']:
flags += ['--with-bzip2', '--with-sqlite', '--with-zlib']
+ if target_os in ['osx', 'ios']:
+ flags += ['--with-commoncrypto']
+
if target_os == 'osx':
# Test Boost on OS X
flags += ['--with-boost']
# Travis has 10.12 as default image
flags += ['--with-os-features=getentropy']
- elif target_os == 'linux':
+
+ if target_os == 'linux':
flags += ['--with-lzma']
if target_os == 'linux':
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);
}