Commit 83c2778611a4f71b7bd841f643ac457af3f23248

Edward Thomson 2021-12-12T15:14:21

sha: support CommonCrypto for SHA256

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e1a4405..2b5a284 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -30,7 +30,7 @@ option(USE_NSEC                "Support nanosecond precision file mtimes and cti
 option(USE_SSH                 "Link with libssh2 to enable SSH support"               OFF)
 option(USE_HTTPS               "Enable HTTPS support. Can be set to a specific backend" ON)
 option(USE_SHA1                "Enable SHA1. Can be set to CollisionDetection(ON)/HTTPS" ON)
-option(USE_SHA256              "Enable SHA256." ON)
+option(USE_SHA256              "Enable SHA256. Can be set to HTTPS/Builtin" ON)
 option(USE_GSSAPI              "Link with libgssapi for SPNEGO auth"      OFF)
    set(USE_HTTP_PARSER         "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.")
    set(REGEX_BACKEND           "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
diff --git a/cmake/SelectHashes.cmake b/cmake/SelectHashes.cmake
index a34651a..acd4706 100644
--- a/cmake/SelectHashes.cmake
+++ b/cmake/SelectHashes.cmake
@@ -47,12 +47,26 @@ else()
 	message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
 endif()
 
-if(USE_SHA256 STREQUAL ON)
+if(USE_SHA256 STREQUAL ON AND USE_HTTPS)
+	SET(USE_SHA256 "HTTPS")
+elseif(USE_SHA256 STREQUAL ON)
 	SET(USE_SHA256 "Builtin")
 endif()
 
+if(USE_SHA256 STREQUAL "HTTPS")
+	if(USE_HTTPS STREQUAL "SecureTransport")
+		set(USE_SHA256 "CommonCrypto")
+	elseif(USE_HTTPS STREQUAL "WinHTTP")
+		set(USE_SHA256 "Win32")
+	elseif(USE_HTTPS)
+		set(USE_SHA256 ${USE_HTTPS})
+	endif()
+endif()
+
 if(USE_SHA256 STREQUAL "Builtin")
 	set(GIT_SHA256_BUILTIN 1)
+elseif(USE_SHA256 STREQUAL "CommonCrypto")
+	set(GIT_SHA256_COMMON_CRYPTO 1)
 else()
 	message(FATAL_ERROR "Asked for unknown SHA256 backend: ${USE_SHA256}")
 endif()
diff --git a/src/features.h.in b/src/features.h.in
index 5e217a3..3085259 100644
--- a/src/features.h.in
+++ b/src/features.h.in
@@ -49,6 +49,7 @@
 #cmakedefine GIT_SHA1_MBEDTLS 1
 
 #cmakedefine GIT_SHA256_BUILTIN 1
+#cmakedefine GIT_SHA256_COMMON_CRYPTO 1
 
 #cmakedefine GIT_RAND_GETENTROPY 1
 
diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt
index dca0e44..e18789c 100644
--- a/src/util/CMakeLists.txt
+++ b/src/util/CMakeLists.txt
@@ -47,7 +47,14 @@ endif()
 
 list(SORT UTIL_SRC_SHA1)
 
-file(GLOB UTIL_SRC_SHA256 hash/builtin.* hash/rfc6234/*)
+if(USE_SHA256 STREQUAL "Builtin")
+	file(GLOB UTIL_SRC_SHA256 hash/builtin.* hash/rfc6234/*)
+elseif(USE_SHA256 STREQUAL "CommonCrypto")
+	file(GLOB UTIL_SRC_SHA256 hash/common_crypto.*)
+else()
+	message(FATAL_ERROR "Asked for unknown SHA256 backend: ${USE_SHA256}")
+endif()
+
 list(SORT UTIL_SRC_SHA256)
 
 #
diff --git a/src/util/hash/common_crypto.c b/src/util/hash/common_crypto.c
index 9d608f4..b327ba9 100644
--- a/src/util/hash/common_crypto.c
+++ b/src/util/hash/common_crypto.c
@@ -9,6 +9,8 @@
 
 #define CC_LONG_MAX ((CC_LONG)-1)
 
+#ifdef GIT_SHA1_COMMON_CRYPTO
+
 int git_hash_sha1_global_init(void)
 {
 	return 0;
@@ -55,3 +57,56 @@ int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *ctx)
 	CC_SHA1_Final(out, &ctx->c);
 	return 0;
 }
+
+#endif
+
+#ifdef GIT_SHA256_COMMON_CRYPTO
+
+int git_hash_sha256_global_init(void)
+{
+	return 0;
+}
+
+int git_hash_sha256_ctx_init(git_hash_sha256_ctx *ctx)
+{
+	return git_hash_sha256_init(ctx);
+}
+
+void git_hash_sha256_ctx_cleanup(git_hash_sha256_ctx *ctx)
+{
+	GIT_UNUSED(ctx);
+}
+
+int git_hash_sha256_init(git_hash_sha256_ctx *ctx)
+{
+	GIT_ASSERT_ARG(ctx);
+	CC_SHA256_Init(&ctx->c);
+	return 0;
+}
+
+int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *_data, size_t len)
+{
+	const unsigned char *data = _data;
+
+	GIT_ASSERT_ARG(ctx);
+
+	while (len > 0) {
+		CC_LONG chunk = (len > CC_LONG_MAX) ? CC_LONG_MAX : (CC_LONG)len;
+
+		CC_SHA256_Update(&ctx->c, data, chunk);
+
+		data += chunk;
+		len -= chunk;
+	}
+
+	return 0;
+}
+
+int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *ctx)
+{
+	GIT_ASSERT_ARG(ctx);
+	CC_SHA256_Final(out, &ctx->c);
+	return 0;
+}
+
+#endif
diff --git a/src/util/hash/common_crypto.h b/src/util/hash/common_crypto.h
index 5b92f0f..157712b 100644
--- a/src/util/hash/common_crypto.h
+++ b/src/util/hash/common_crypto.h
@@ -12,8 +12,16 @@
 
 #include <CommonCrypto/CommonDigest.h>
 
+#ifdef GIT_SHA1_COMMON_CRYPTO
 struct git_hash_sha1_ctx {
 	CC_SHA1_CTX c;
 };
+#endif
+
+#ifdef GIT_SHA256_COMMON_CRYPTO
+struct git_hash_sha256_ctx {
+	CC_SHA256_CTX c;
+};
+#endif
 
 #endif
diff --git a/src/util/hash/sha.h b/src/util/hash/sha.h
index fad3f03..d0928d3 100644
--- a/src/util/hash/sha.h
+++ b/src/util/hash/sha.h
@@ -13,24 +13,28 @@
 typedef struct git_hash_sha1_ctx git_hash_sha1_ctx;
 typedef struct git_hash_sha256_ctx git_hash_sha256_ctx;
 
-#if defined(GIT_SHA1_COMMON_CRYPTO)
+#if defined(GIT_SHA1_COMMON_CRYPTO) || defined(GIT_SHA256_COMMON_CRYPTO)
 # include "common_crypto.h"
-#elif defined(GIT_SHA1_OPENSSL)
+#endif
+
+#if defined(GIT_SHA1_OPENSSL) || defined(GIT_SHA1_COMMON_CRYPTO)
 # include "openssl.h"
-#elif defined(GIT_SHA1_WIN32)
+#endif
+
+#if defined(GIT_SHA1_WIN32) || defined(GIT_SHA256_WIN32)
 # include "win32.h"
-#elif defined(GIT_SHA1_MBEDTLS)
+#endif
+
+#if defined(GIT_SHA1_MBEDTLS) || defined(GIT_SHA256_MBEDTLS)
 # include "mbedtls.h"
-#elif defined(GIT_SHA1_COLLISIONDETECT)
+#endif
+
+#if defined(GIT_SHA1_COLLISIONDETECT)
 # include "collisiondetect.h"
-#else
-# error "unknown sha1 implementation"
 #endif
 
 #if defined(GIT_SHA256_BUILTIN)
 # include "builtin.h"
-#else
-# error "unknown sha256 implementation"
 #endif
 
 /*