Commit 9985edb579b75c40e33af1c42415c90fc669b73f

Edward Thomson 2018-02-01T06:32:55

hash: set error messages on failure

diff --git a/src/hash/hash_win32.c b/src/hash/hash_win32.c
index 20ba9a5..50c23e8 100644
--- a/src/hash/hash_win32.c
+++ b/src/hash/hash_win32.c
@@ -24,16 +24,20 @@ GIT_INLINE(int) hash_cng_prov_init(void)
 	DWORD dll_path_len, size_len;
 
 	/* Only use CNG on Windows 2008 / Vista SP1  or better (Windows 6.0 SP1) */
-	if (!git_has_win32_version(6, 0, 1))
+	if (!git_has_win32_version(6, 0, 1)) {
+		giterr_set(GITERR_SHA1, "CryptoNG is not supported on this platform");
 		return -1;
+	}
 
 	/* Load bcrypt.dll explicitly from the system directory */
 	if ((dll_path_len = GetSystemDirectory(dll_path, MAX_PATH)) == 0 ||
 		dll_path_len > MAX_PATH ||
 		StringCchCat(dll_path, MAX_PATH, "\\") < 0 ||
 		StringCchCat(dll_path, MAX_PATH, GIT_HASH_CNG_DLL_NAME) < 0 ||
-		(hash_prov.prov.cng.dll = LoadLibrary(dll_path)) == NULL)
+		(hash_prov.prov.cng.dll = LoadLibrary(dll_path)) == NULL) {
+		giterr_set(GITERR_SHA1, "CryptoNG library could not be loaded");
 		return -1;
+	}
 
 	/* Load the function addresses */
 	if ((hash_prov.prov.cng.open_algorithm_provider = (hash_win32_cng_open_algorithm_provider_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptOpenAlgorithmProvider")) == NULL ||
@@ -44,12 +48,16 @@ GIT_INLINE(int) hash_cng_prov_init(void)
 		(hash_prov.prov.cng.destroy_hash = (hash_win32_cng_destroy_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptDestroyHash")) == NULL ||
 		(hash_prov.prov.cng.close_algorithm_provider = (hash_win32_cng_close_algorithm_provider_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptCloseAlgorithmProvider")) == NULL) {
 		FreeLibrary(hash_prov.prov.cng.dll);
+
+		giterr_set(GITERR_OS, "CryptoNG functions could not be loaded");
 		return -1;
 	}
 
 	/* Load the SHA1 algorithm */
 	if (hash_prov.prov.cng.open_algorithm_provider(&hash_prov.prov.cng.handle, GIT_HASH_CNG_HASH_TYPE, NULL, GIT_HASH_CNG_HASH_REUSABLE) < 0) {
 		FreeLibrary(hash_prov.prov.cng.dll);
+
+		giterr_set(GITERR_OS "algorithm provider could not be initialized");
 		return -1;
 	}
 
@@ -57,6 +65,8 @@ GIT_INLINE(int) hash_cng_prov_init(void)
 	if (hash_prov.prov.cng.get_property(hash_prov.prov.cng.handle, GIT_HASH_CNG_HASH_OBJECT_LEN, (PBYTE)&hash_prov.prov.cng.hash_object_size, sizeof(DWORD), &size_len, 0) < 0) {
 		hash_prov.prov.cng.close_algorithm_provider(hash_prov.prov.cng.handle, 0);
 		FreeLibrary(hash_prov.prov.cng.dll);
+
+		giterr_set(GITERR_OS, "algorithm handle could not be found");
 		return -1;
 	}
 
@@ -75,8 +85,10 @@ GIT_INLINE(void) hash_cng_prov_shutdown(void)
 /* Initialize CryptoAPI */
 GIT_INLINE(int) hash_cryptoapi_prov_init()
 {
-	if (!CryptAcquireContext(&hash_prov.prov.cryptoapi.handle, NULL, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+	if (!CryptAcquireContext(&hash_prov.prov.cryptoapi.handle, NULL, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
+		giterr_set(GITERR_OS, "legacy hash context could not be started");
 		return -1;
+	}
 
 	hash_prov.type = CRYPTOAPI;
 	return 0;
@@ -129,6 +141,7 @@ GIT_INLINE(int) hash_cryptoapi_init(git_hash_ctx *ctx)
 
 	if (!CryptCreateHash(ctx->prov->prov.cryptoapi.handle, CALG_SHA1, 0, 0, &ctx->ctx.cryptoapi.hash_handle)) {
 		ctx->ctx.cryptoapi.valid = 0;
+		giterr_set(GITERR_OS, "legacy hash implementation could not be created");
 		return -1;
 	}
 
@@ -145,8 +158,10 @@ GIT_INLINE(int) hash_cryptoapi_update(git_hash_ctx *ctx, const void *_data, size
 	while (len > 0) {
 		DWORD chunk = (len > MAXDWORD) ? MAXDWORD : (DWORD)len;
 
-		if (!CryptHashData(ctx->ctx.cryptoapi.hash_handle, data, chunk, 0))
+		if (!CryptHashData(ctx->ctx.cryptoapi.hash_handle, data, chunk, 0)) {
+			giterr_set(GITERR_OS, "legacy hash data could not be updated");
 			return -1;
+		}
 
 		data += chunk;
 		len -= chunk;
@@ -162,8 +177,10 @@ GIT_INLINE(int) hash_cryptoapi_final(git_oid *out, git_hash_ctx *ctx)
 
 	assert(ctx->ctx.cryptoapi.valid);
 
-	if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out->id, &len, 0))
+	if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out->id, &len, 0)) {
+		giterr_set(GITERR_OS, "legacy hash data could not be finished");
 		error = -1;
+	}
 
 	CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle);
 	ctx->ctx.cryptoapi.valid = 0;
@@ -186,6 +203,8 @@ GIT_INLINE(int) hash_ctx_cng_init(git_hash_ctx *ctx)
 
 	if (hash_prov.prov.cng.create_hash(hash_prov.prov.cng.handle, &ctx->ctx.cng.hash_handle, ctx->ctx.cng.hash_object, hash_prov.prov.cng.hash_object_size, NULL, 0, 0) < 0) {
 		git__free(ctx->ctx.cng.hash_object);
+
+		giterr_set(GITERR_OS, "hash implementation could not be created");
 		return -1;
 	}
 
@@ -203,8 +222,10 @@ GIT_INLINE(int) hash_cng_init(git_hash_ctx *ctx)
 		return 0;
 
 	/* CNG needs to be finished to restart */
-	if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, hash, GIT_OID_RAWSZ, 0) < 0)
+	if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, hash, GIT_OID_RAWSZ, 0) < 0) {
+		giterr_set(GITERR_OS, "hash implementation could not be finished");
 		return -1;
+	}
 
 	ctx->ctx.cng.updated = 0;
 
@@ -218,8 +239,10 @@ GIT_INLINE(int) hash_cng_update(git_hash_ctx *ctx, const void *_data, size_t len
 	while (len > 0) {
 		ULONG chunk = (len > ULONG_MAX) ? ULONG_MAX : (ULONG)len;
 
-		if (ctx->prov->prov.cng.hash_data(ctx->ctx.cng.hash_handle, data, chunk, 0) < 0)
+		if (ctx->prov->prov.cng.hash_data(ctx->ctx.cng.hash_handle, data, chunk, 0) < 0) {
+			giterr_set(GITERR_OS, "hash could not be updated");
 			return -1;
+		}
 
 		data += chunk;
 		len -= chunk;
@@ -230,8 +253,10 @@ GIT_INLINE(int) hash_cng_update(git_hash_ctx *ctx, const void *_data, size_t len
 
 GIT_INLINE(int) hash_cng_final(git_oid *out, git_hash_ctx *ctx)
 {
-	if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, out->id, GIT_OID_RAWSZ, 0) < 0)
+	if (ctx->prov->prov.cng.finish_hash(ctx->ctx.cng.hash_handle, out->id, GIT_OID_RAWSZ, 0) < 0) {
+		giterr_set(GITERR_OS, "hash could not be finished");
 		return -1;
+	}
 
 	ctx->ctx.cng.updated = 0;