Commit ce78c83b73ba06c2528b884e5dc4b2d7e9fc2df5

Edward Thomson 2021-12-13T15:31:21

sha: ensure we test both cng and cryptoapi on windows When GIT_SHA1_WIN32 or GIT_SHA256_WIN32 is used, ensure that we test both CryptoNG ("cng") and CryptoAPI.

diff --git a/src/util/hash/win32.c b/src/util/hash/win32.c
index 3320f79..bc5833b 100644
--- a/src/util/hash/win32.c
+++ b/src/util/hash/win32.c
@@ -239,6 +239,27 @@ static int hash_provider_init(void)
 	return error;
 }
 
+git_hash_win32_provider_t git_hash_win32_provider(void)
+{
+	return hash_provider.type;
+}
+
+int git_hash_win32_set_provider(git_hash_win32_provider_t provider)
+{
+	if (provider == hash_provider.type)
+		return 0;
+
+	hash_provider_shutdown();
+
+	if (provider == GIT_HASH_WIN32_CNG)
+		return cng_provider_init();
+	else if (provider == GIT_HASH_WIN32_CRYPTOAPI)
+		return cryptoapi_provider_init();
+
+	git_error_set(GIT_ERROR_SHA, "unsupported win32 provider");
+	return -1;
+}
+
 /* CryptoAPI: available in Windows XP and newer */
 
 GIT_INLINE(int) hash_cryptoapi_init(git_hash_win32_ctx *ctx)
diff --git a/src/util/hash/win32.h b/src/util/hash/win32.h
index c058047..a9fb87a 100644
--- a/src/util/hash/win32.h
+++ b/src/util/hash/win32.h
@@ -38,6 +38,13 @@ typedef struct {
 	} ctx;
 } git_hash_win32_ctx;
 
+/*
+ * Gets/sets the current hash provider (cng or cryptoapi).  This is only
+ * for testing purposes.
+ */
+git_hash_win32_provider_t git_hash_win32_provider(void);
+int git_hash_win32_set_provider(git_hash_win32_provider_t provider);
+
 #ifdef GIT_SHA1_WIN32
 struct git_hash_sha1_ctx {
 	git_hash_win32_ctx win32;
diff --git a/tests/util/sha1.c b/tests/util/sha1.c
index 6898275..fe4032c 100644
--- a/tests/util/sha1.c
+++ b/tests/util/sha1.c
@@ -3,13 +3,25 @@
 
 #define FIXTURE_DIR "sha1"
 
+#ifdef GIT_SHA1_WIN32
+static git_hash_win32_provider_t orig_provider;
+#endif
+
 void test_sha1__initialize(void)
 {
+#ifdef GIT_SHA1_WIN32
+	orig_provider = git_hash_win32_provider();
+#endif
+
 	cl_fixture_sandbox(FIXTURE_DIR);
 }
 
 void test_sha1__cleanup(void)
 {
+#ifdef GIT_SHA1_WIN32
+	git_hash_win32_set_provider(orig_provider);
+#endif
+
 	cl_fixture_cleanup(FIXTURE_DIR);
 }
 
@@ -68,3 +80,21 @@ void test_sha1__detect_collision_attack(void)
 #endif
 }
 
+void test_sha1__win32_providers(void)
+{
+#ifdef GIT_SHA1_WIN32
+	unsigned char expected[GIT_HASH_SHA1_SIZE] = {
+		0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
+		0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
+	};
+	unsigned char actual[GIT_HASH_SHA1_SIZE];
+
+	git_hash_win32_set_provider(GIT_HASH_WIN32_CRYPTOAPI);
+	cl_git_pass(sha1_file(actual, FIXTURE_DIR "/shattered-1.pdf"));
+	cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA1_SIZE));
+
+	git_hash_win32_set_provider(GIT_HASH_WIN32_CNG);
+	cl_git_pass(sha1_file(actual, FIXTURE_DIR "/shattered-1.pdf"));
+	cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA1_SIZE));
+#endif
+}
diff --git a/tests/util/sha256.c b/tests/util/sha256.c
index a44de32..75b3d73 100644
--- a/tests/util/sha256.c
+++ b/tests/util/sha256.c
@@ -3,13 +3,25 @@
 
 #define FIXTURE_DIR "sha1"
 
-void test_core_sha256__initialize(void)
+#ifdef GIT_SHA256_WIN32
+static git_hash_win32_provider_t orig_provider;
+#endif
+
+void test_sha256__initialize(void)
 {
+#ifdef GIT_SHA256_WIN32
+	orig_provider = git_hash_win32_provider();
+#endif
+
 	cl_fixture_sandbox(FIXTURE_DIR);
 }
 
-void test_core_sha256__cleanup(void)
+void test_sha256__cleanup(void)
 {
+#ifdef GIT_SHA256_WIN32
+	git_hash_win32_set_provider(orig_provider);
+#endif
+
 	cl_fixture_cleanup(FIXTURE_DIR);
 }
 
@@ -37,7 +49,7 @@ static int sha256_file(unsigned char *out, const char *filename)
 	return ret;
 }
 
-void test_core_sha256__empty(void)
+void test_sha256__empty(void)
 {
 	unsigned char expected[GIT_HASH_SHA256_SIZE] = {
 		0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
@@ -51,7 +63,7 @@ void test_core_sha256__empty(void)
 	cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA256_SIZE));
 }
 
-void test_core_sha256__hello(void)
+void test_sha256__hello(void)
 {
 	unsigned char expected[GIT_HASH_SHA256_SIZE] = {
 		0xaa, 0x32, 0x7f, 0xae, 0x5c, 0x91, 0x58, 0x3a,
@@ -65,7 +77,7 @@ void test_core_sha256__hello(void)
 	cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA256_SIZE));
 }
 
-void test_core_sha256__pdf(void)
+void test_sha256__pdf(void)
 {
 	unsigned char expected[GIT_HASH_SHA256_SIZE] = {
 		0x2b, 0xb7, 0x87, 0xa7, 0x3e, 0x37, 0x35, 0x2f,
@@ -79,3 +91,23 @@ void test_core_sha256__pdf(void)
 	cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA256_SIZE));
 }
 
+void test_sha256__win32_providers(void)
+{
+#ifdef GIT_SHA256_WIN32
+	unsigned char expected[GIT_HASH_SHA256_SIZE] = {
+		0x2b, 0xb7, 0x87, 0xa7, 0x3e, 0x37, 0x35, 0x2f,
+		0x92, 0x38, 0x3a, 0xbe, 0x7e, 0x29, 0x02, 0x93,
+		0x6d, 0x10, 0x59, 0xad, 0x9f, 0x1b, 0xa6, 0xda,
+		0xaa, 0x9c, 0x1e, 0x58, 0xee, 0x69, 0x70, 0xd0
+	};
+	unsigned char actual[GIT_HASH_SHA256_SIZE];
+
+	git_hash_win32_set_provider(GIT_HASH_WIN32_CRYPTOAPI);
+	cl_git_pass(sha256_file(actual, FIXTURE_DIR "/shattered-1.pdf"));
+	cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA256_SIZE));
+
+	git_hash_win32_set_provider(GIT_HASH_WIN32_CNG);
+	cl_git_pass(sha256_file(actual, FIXTURE_DIR "/shattered-1.pdf"));
+	cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA256_SIZE));
+#endif
+}