diff --git a/CMakeLists.txt b/CMakeLists.txt index 85f86c00b..bde872fe4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,11 +39,14 @@ ENDIF() # Specify sha1 implementation IF (SHA1_TYPE STREQUAL "ppc") ADD_DEFINITIONS(-DPPC_SHA1) - FILE(GLOB SRC_SHA1 src/ppc/*.c src/ppc/*.S) -ELSEIF (OPENSSL_FOUND) # libcrypto's implementation is faster than ours - ADD_DEFINITIONS(-DOPENSSL_SHA) -ELSE () - FILE(GLOB SRC_SHA1 src/sha1/*.c) + FILE(GLOB SRC_SHA1 src/hash/hash_ppc.c src/hash/hash_ppc_core.S) +ELSEIF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin") + ADD_DEFINITIONS(-DWIN32_SHA1) + FILE(GLOB SRC_SHA1 src/hash/hash_win32.c) +ELSEIF (OPENSSL_FOUND AND NOT SHA1_TYPE STREQUAL "builtin") + ADD_DEFINITIONS(-DOPENSSL_SHA1) +ELSE() + FILE(GLOB SRC_SHA1 src/hash/hash_generic.c) ENDIF() IF (NOT WIN32) diff --git a/include/git2/threads.h b/include/git2/threads.h index 567a10487..f448f6a4d 100644 --- a/include/git2/threads.h +++ b/include/git2/threads.h @@ -27,8 +27,10 @@ GIT_BEGIN_DECL * * If libgit2 has been built without GIT_THREADS * support, this function is a no-op. + * + * @return 0 or an error code */ -GIT_EXTERN(void) git_threads_init(void); +GIT_EXTERN(int) git_threads_init(void); /** * Shutdown the threading system. diff --git a/src/filebuf.c b/src/filebuf.c index 5e5db0db6..0eb5b458a 100644 --- a/src/filebuf.c +++ b/src/filebuf.c @@ -85,8 +85,8 @@ static int lock_file(git_filebuf *file, int flags) while ((read_bytes = p_read(source, buffer, sizeof(buffer))) > 0) { p_write(file->fd, buffer, read_bytes); - if (file->digest) - git_hash_update(file->digest, buffer, read_bytes); + if (file->compute_digest) + git_hash_update(&file->digest, buffer, read_bytes); } p_close(source); @@ -108,8 +108,10 @@ void git_filebuf_cleanup(git_filebuf *file) if (file->fd_is_open && file->path_lock && git_path_exists(file->path_lock)) p_unlink(file->path_lock); - if (file->digest) - git_hash_free_ctx(file->digest); + if (file->compute_digest) { + git_hash_ctx_cleanup(&file->digest); + file->compute_digest = 0; + } if (file->buffer) git__free(file->buffer); @@ -149,8 +151,8 @@ static int write_normal(git_filebuf *file, void *source, size_t len) return -1; } - if (file->digest) - git_hash_update(file->digest, source, len); + if (file->compute_digest) + git_hash_update(&file->digest, source, len); } return 0; @@ -186,8 +188,8 @@ static int write_deflate(git_filebuf *file, void *source, size_t len) assert(zs->avail_in == 0); - if (file->digest) - git_hash_update(file->digest, source, len); + if (file->compute_digest) + git_hash_update(&file->digest, source, len); } return 0; @@ -221,8 +223,10 @@ int git_filebuf_open(git_filebuf *file, const char *path, int flags) /* If we are hashing on-write, allocate a new hash context */ if (flags & GIT_FILEBUF_HASH_CONTENTS) { - file->digest = git_hash_new_ctx(); - GITERR_CHECK_ALLOC(file->digest); + file->compute_digest = 1; + + if (git_hash_ctx_init(&file->digest) < 0) + goto cleanup; } compression = flags >> GIT_FILEBUF_DEFLATE_SHIFT; @@ -291,16 +295,16 @@ cleanup: int git_filebuf_hash(git_oid *oid, git_filebuf *file) { - assert(oid && file && file->digest); + assert(oid && file && file->compute_digest); flush_buffer(file); if (verify_last_error(file) < 0) return -1; - git_hash_final(oid, file->digest); - git_hash_free_ctx(file->digest); - file->digest = NULL; + git_hash_final(oid, &file->digest); + git_hash_ctx_cleanup(&file->digest); + file->compute_digest = 0; return 0; } diff --git a/src/filebuf.h b/src/filebuf.h index a74bb0ce1..dcaad9bd8 100644 --- a/src/filebuf.h +++ b/src/filebuf.h @@ -31,7 +31,8 @@ struct git_filebuf { int (*write)(struct git_filebuf *file, void *source, size_t len); - git_hash_ctx *digest; + bool compute_digest; + git_hash_ctx digest; unsigned char *buffer; unsigned char *z_buf; diff --git a/src/global.c b/src/global.c index 22127faf7..d085089c3 100644 --- a/src/global.c +++ b/src/global.c @@ -6,6 +6,7 @@ */ #include "common.h" #include "global.h" +#include "hash.h" #include "git2/threads.h" #include "thread-utils.h" @@ -38,19 +39,39 @@ git_mutex git__mwindow_mutex; * functions are not available in that case. */ +/* + * `git_threads_init()` allows subsystems to perform global setup, + * which may take place in the global scope. An explicit memory + * fence exists at the exit of `git_threads_init()`. Without this, + * CPU cores are free to reorder cache invalidation of `_tls_init` + * before cache invalidation of the subsystems' newly written global + * state. + */ #if defined(GIT_THREADS) && defined(GIT_WIN32) static DWORD _tls_index; static int _tls_init = 0; -void git_threads_init(void) +int git_threads_init(void) { + int error; + if (_tls_init) - return; + return 0; _tls_index = TlsAlloc(); - _tls_init = 1; git_mutex_init(&git__mwindow_mutex); + + /* Initialize any other subsystems that have global state */ + if ((error = git_hash_global_init()) >= 0) + _tls_init = 1; + + if (error == 0) + _tls_init = 1; + + GIT_MEMORY_BARRIER; + + return error; } void git_threads_shutdown(void) @@ -58,6 +79,9 @@ void git_threads_shutdown(void) TlsFree(_tls_index); _tls_init = 0; git_mutex_free(&git__mwindow_mutex); + + /* Shut down any subsystems that have global state */ + git_hash_global_shutdown(); } git_global_st *git__global_state(void) @@ -88,19 +112,31 @@ static void cb__free_status(void *st) git__free(st); } -void git_threads_init(void) +int git_threads_init(void) { + int error = 0; + if (_tls_init) - return; + return 0; pthread_key_create(&_tls_key, &cb__free_status); - _tls_init = 1; + + /* Initialize any other subsystems that have global state */ + if ((error = git_hash_global_init()) >= 0) + _tls_init = 1; + + GIT_MEMORY_BARRIER; + + return error; } void git_threads_shutdown(void) { pthread_key_delete(_tls_key); _tls_init = 0; + + /* Shut down any subsystems that have global state */ + git_hash_global_shutdown(); } git_global_st *git__global_state(void) @@ -125,9 +161,10 @@ git_global_st *git__global_state(void) static git_global_st __state; -void git_threads_init(void) +int git_threads_init(void) { /* noop */ + return 0; } void git_threads_shutdown(void) diff --git a/src/global.h b/src/global.h index 0ad41ee63..b117714a8 100644 --- a/src/global.h +++ b/src/global.h @@ -8,6 +8,15 @@ #define INCLUDE_global_h__ #include "mwindow.h" +#include "hash.h" + +#if defined(GIT_THREADS) && defined(_MSC_VER) +# define GIT_MEMORY_BARRIER MemoryBarrier() +#elif defined(GIT_THREADS) +# define GIT_MEMORY_BARRIER __sync_synchronize() +#else +# define GIT_MEMORY_BARRIER /* noop */ +#endif typedef struct { git_error *last_error; diff --git a/src/hash.c b/src/hash.c index 460756913..21db2e129 100644 --- a/src/hash.c +++ b/src/hash.c @@ -8,67 +8,40 @@ #include "common.h" #include "hash.h" -#if defined(PPC_SHA1) -# include "ppc/sha1.h" -#else -# include "sha1.h" -#endif - -struct git_hash_ctx { - SHA_CTX c; -}; - -git_hash_ctx *git_hash_new_ctx(void) +int git_hash_buf(git_oid *out, const void *data, size_t len) { - git_hash_ctx *ctx = git__malloc(sizeof(*ctx)); + git_hash_ctx ctx; + int error = 0; - if (!ctx) - return NULL; + if (git_hash_ctx_init(&ctx) < 0) + return -1; - SHA1_Init(&ctx->c); + if ((error = git_hash_update(&ctx, data, len)) >= 0) + error = git_hash_final(out, &ctx); - return ctx; + git_hash_ctx_cleanup(&ctx); + + return error; } -void git_hash_free_ctx(git_hash_ctx *ctx) +int git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n) { - git__free(ctx); -} - -void git_hash_init(git_hash_ctx *ctx) -{ - assert(ctx); - SHA1_Init(&ctx->c); -} - -void git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) -{ - assert(ctx); - SHA1_Update(&ctx->c, data, len); -} - -void git_hash_final(git_oid *out, git_hash_ctx *ctx) -{ - assert(ctx); - SHA1_Final(out->id, &ctx->c); -} - -void git_hash_buf(git_oid *out, const void *data, size_t len) -{ - SHA_CTX c; - - SHA1_Init(&c); - SHA1_Update(&c, data, len); - SHA1_Final(out->id, &c); -} - -void git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n) -{ - SHA_CTX c; + git_hash_ctx ctx; size_t i; + int error = 0; - SHA1_Init(&c); - for (i = 0; i < n; i++) - SHA1_Update(&c, vec[i].data, vec[i].len); - SHA1_Final(out->id, &c); + if (git_hash_ctx_init(&ctx) < 0) + return -1; + + for (i = 0; i < n; i++) { + if ((error = git_hash_update(&ctx, vec[i].data, vec[i].len)) < 0) + goto done; + } + + error = git_hash_final(out, &ctx); + +done: + git_hash_ctx_cleanup(&ctx); + + return error; } diff --git a/src/hash.h b/src/hash.h index 33d7b20cd..127be282f 100644 --- a/src/hash.h +++ b/src/hash.h @@ -9,21 +9,35 @@ #include "git2/oid.h" +typedef struct git_hash_prov git_hash_prov; typedef struct git_hash_ctx git_hash_ctx; +int git_hash_global_init(void); +void git_hash_global_shutdown(void); + +int git_hash_ctx_init(git_hash_ctx *ctx); +void git_hash_ctx_cleanup(git_hash_ctx *ctx); + +#if defined(OPENSSL_SHA1) +# include "hash/hash_openssl.h" +#elif defined(WIN32_SHA1) +# include "hash/hash_win32.h" +#elif defined(PPC_SHA1) +# include "hash/hash_ppc.h" +#else +# include "hash/hash_generic.h" +#endif + typedef struct { void *data; size_t len; } git_buf_vec; -git_hash_ctx *git_hash_new_ctx(void); -void git_hash_free_ctx(git_hash_ctx *ctx); +int git_hash_init(git_hash_ctx *c); +int git_hash_update(git_hash_ctx *c, const void *data, size_t len); +int git_hash_final(git_oid *out, git_hash_ctx *c); -void git_hash_init(git_hash_ctx *c); -void git_hash_update(git_hash_ctx *c, const void *data, size_t len); -void git_hash_final(git_oid *out, git_hash_ctx *c); - -void git_hash_buf(git_oid *out, const void *data, size_t len); -void git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n); +int git_hash_buf(git_oid *out, const void *data, size_t len); +int git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n); #endif /* INCLUDE_hash_h__ */ diff --git a/src/sha1/sha1.c b/src/hash/hash_generic.c similarity index 94% rename from src/sha1/sha1.c rename to src/hash/hash_generic.c index 8aaedeb8f..30d7a5d1e 100644 --- a/src/sha1/sha1.c +++ b/src/hash/hash_generic.c @@ -6,7 +6,8 @@ */ #include "common.h" -#include "sha1.h" +#include "hash.h" +#include "hash/hash_generic.h" #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) @@ -112,7 +113,7 @@ #define T_40_59(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, ((B&C)+(D&(B^C))) , 0x8f1bbcdc, A, B, C, D, E ) #define T_60_79(t, A, B, C, D, E) SHA_ROUND(t, SHA_MIX, (B^C^D) , 0xca62c1d6, A, B, C, D, E ) -static void blk_SHA1_Block(blk_SHA_CTX *ctx, const unsigned int *data) +static void hash__block(git_hash_ctx *ctx, const unsigned int *data) { unsigned int A,B,C,D,E; unsigned int array[16]; @@ -220,7 +221,7 @@ static void blk_SHA1_Block(blk_SHA_CTX *ctx, const unsigned int *data) ctx->H[4] += E; } -void git__blk_SHA1_Init(blk_SHA_CTX *ctx) +int git_hash_init(git_hash_ctx *ctx) { ctx->size = 0; @@ -230,9 +231,11 @@ void git__blk_SHA1_Init(blk_SHA_CTX *ctx) ctx->H[2] = 0x98badcfe; ctx->H[3] = 0x10325476; ctx->H[4] = 0xc3d2e1f0; + + return 0; } -void git__blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, size_t len) +int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) { unsigned int lenW = ctx->size & 63; @@ -248,19 +251,21 @@ void git__blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, size_t len) len -= left; data = ((const char *)data + left); if (lenW) - return; - blk_SHA1_Block(ctx, ctx->W); + return 0; + hash__block(ctx, ctx->W); } while (len >= 64) { - blk_SHA1_Block(ctx, data); + hash__block(ctx, data); data = ((const char *)data + 64); len -= 64; } if (len) memcpy(ctx->W, data, len); + + return 0; } -void git__blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx) +int git_hash_final(git_oid *out, git_hash_ctx *ctx) { static const unsigned char pad[64] = { 0x80 }; unsigned int padlen[2]; @@ -271,10 +276,13 @@ void git__blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx) padlen[1] = htonl((uint32_t)(ctx->size << 3)); i = ctx->size & 63; - git__blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i))); - git__blk_SHA1_Update(ctx, padlen, 8); + git_hash_update(ctx, pad, 1+ (63 & (55 - i))); + git_hash_update(ctx, padlen, 8); /* Output hash */ for (i = 0; i < 5; i++) - put_be32(hashout + i*4, ctx->H[i]); + put_be32(out->id + i*4, ctx->H[i]); + + return 0; } + diff --git a/src/hash/hash_generic.h b/src/hash/hash_generic.h new file mode 100644 index 000000000..7c4be7873 --- /dev/null +++ b/src/hash/hash_generic.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_generic_h__ +#define INCLUDE_hash_generic_h__ + +#include "hash.h" + +struct git_hash_ctx { + unsigned long long size; + unsigned int H[5]; + unsigned int W[16]; +}; + +#define git_hash_global_init() 0 +#define git_hash_global_shutdown() /* noop */ +#define git_hash_ctx_init(ctx) git_hash_init(ctx) +#define git_hash_ctx_cleanup(ctx) + +#endif /* INCLUDE_hash_generic_h__ */ diff --git a/src/hash/hash_openssl.h b/src/hash/hash_openssl.h new file mode 100644 index 000000000..3ae49a732 --- /dev/null +++ b/src/hash/hash_openssl.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_openssl_h__ +#define INCLUDE_hash_openssl_h__ + +#include "hash.h" + +#include + +struct git_hash_ctx { + SHA_CTX c; +}; + +#define git_hash_global_init() 0 +#define git_hash_global_shutdown() /* noop */ +#define git_hash_ctx_init(ctx) git_hash_init(ctx) +#define git_hash_ctx_cleanup(ctx) + +GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx) +{ + assert(ctx); + SHA1_Init(&ctx->c); + return 0; +} + +GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) +{ + assert(ctx); + SHA1_Update(&ctx->c, data, len); + return 0; +} + +GIT_INLINE(int) git_hash_final(git_oid *out, git_hash_ctx *ctx) +{ + assert(ctx); + SHA1_Final(out->id, &ctx->c); + return 0; +} + +#endif /* INCLUDE_hash_openssl_h__ */ diff --git a/src/ppc/sha1.c b/src/hash/hash_ppc.c similarity index 70% rename from src/ppc/sha1.c rename to src/hash/hash_ppc.c index 803b81d0a..de89e9f5e 100644 --- a/src/ppc/sha1.c +++ b/src/hash/hash_ppc.c @@ -4,14 +4,17 @@ * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ + #include #include -#include "sha1.h" -extern void ppc_sha1_core(uint32_t *hash, const unsigned char *p, +#include "common.h" +#include "hash.h" + +extern void hash_ppc_core(uint32_t *hash, const unsigned char *p, unsigned int nblocks); -int ppc_SHA1_Init(ppc_SHA_CTX *c) +int git_hash_init(git_hash_ctx *c) { c->hash[0] = 0x67452301; c->hash[1] = 0xEFCDAB89; @@ -23,7 +26,7 @@ int ppc_SHA1_Init(ppc_SHA_CTX *c) return 0; } -int ppc_SHA1_Update(ppc_SHA_CTX *c, const void *ptr, unsigned long n) +int git_hash_update(git_hash_ctx *c, const void *ptr, size_t n) { unsigned long nb; const unsigned char *p = ptr; @@ -36,12 +39,12 @@ int ppc_SHA1_Update(ppc_SHA_CTX *c, const void *ptr, unsigned long n) nb = n; memcpy(&c->buf.b[c->cnt], p, nb); if ((c->cnt += nb) == 64) { - ppc_sha1_core(c->hash, c->buf.b, 1); + hash_ppc_core(c->hash, c->buf.b, 1); c->cnt = 0; } } else { nb = n >> 6; - ppc_sha1_core(c->hash, p, nb); + hash_ppc_core(c->hash, p, nb); nb <<= 6; } n -= nb; @@ -50,7 +53,7 @@ int ppc_SHA1_Update(ppc_SHA_CTX *c, const void *ptr, unsigned long n) return 0; } -int ppc_SHA1_Final(unsigned char *hash, ppc_SHA_CTX *c) +int git_hash_final(git_oid *oid, git_hash_ctx *c) { unsigned int cnt = c->cnt; @@ -58,13 +61,14 @@ int ppc_SHA1_Final(unsigned char *hash, ppc_SHA_CTX *c) if (cnt > 56) { if (cnt < 64) memset(&c->buf.b[cnt], 0, 64 - cnt); - ppc_sha1_core(c->hash, c->buf.b, 1); + hash_ppc_core(c->hash, c->buf.b, 1); cnt = 0; } if (cnt < 56) memset(&c->buf.b[cnt], 0, 56 - cnt); c->buf.l[7] = c->len; - ppc_sha1_core(c->hash, c->buf.b, 1); - memcpy(hash, c->hash, 20); + hash_ppc_core(c->hash, c->buf.b, 1); + memcpy(oid->id, c->hash, 20); return 0; } + diff --git a/src/ppc/sha1.h b/src/hash/hash_ppc.h similarity index 50% rename from src/ppc/sha1.h rename to src/hash/hash_ppc.h index aca4e5dda..935f73f7f 100644 --- a/src/ppc/sha1.h +++ b/src/hash/hash_ppc.h @@ -4,9 +4,13 @@ * This file is part of libgit2, distributed under the GNU GPL v2 with * a Linking Exception. For full terms see the included COPYING file. */ + +#ifndef INCLUDE_hash_ppc_h__ +#define INCLUDE_hash_ppc_h__ + #include -typedef struct { +struct git_hash_ctx { uint32_t hash[5]; uint32_t cnt; uint64_t len; @@ -14,13 +18,11 @@ typedef struct { unsigned char b[64]; uint64_t l[8]; } buf; -} ppc_SHA_CTX; +}; -int ppc_SHA1_Init(ppc_SHA_CTX *c); -int ppc_SHA1_Update(ppc_SHA_CTX *c, const void *p, unsigned long n); -int ppc_SHA1_Final(unsigned char *hash, ppc_SHA_CTX *c); +#define git_hash_global_init() 0 +#define git_hash_global_shutdown() /* noop */ +#define git_hash_ctx_init(ctx) git_hash_init(ctx) +#define git_hash_ctx_cleanup(ctx) -#define SHA_CTX ppc_SHA_CTX -#define SHA1_Init ppc_SHA1_Init -#define SHA1_Update ppc_SHA1_Update -#define SHA1_Final ppc_SHA1_Final +#endif /* INCLUDE_hash_generic_h__ */ diff --git a/src/ppc/sha1ppc.S b/src/hash/hash_ppc_core.S similarity index 99% rename from src/ppc/sha1ppc.S rename to src/hash/hash_ppc_core.S index 1711eef6e..1de816cf5 100644 --- a/src/ppc/sha1ppc.S +++ b/src/hash/hash_ppc_core.S @@ -162,8 +162,8 @@ add RE(t),RE(t),%r0; rotlwi RB(t),RB(t),30 STEPUP4(fn, (t)+12, (s)+12,); \ STEPUP4(fn, (t)+16, (s)+16, loadk) - .globl ppc_sha1_core -ppc_sha1_core: + .globl hash_ppc_core +hash_ppc_core: stwu %r1,-80(%r1) stmw %r13,4(%r1) diff --git a/src/hash/hash_win32.c b/src/hash/hash_win32.c new file mode 100644 index 000000000..a89dffa7c --- /dev/null +++ b/src/hash/hash_win32.c @@ -0,0 +1,291 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#include "common.h" +#include "global.h" +#include "hash.h" +#include "hash/hash_win32.h" + +#include +#include + +static struct git_hash_prov hash_prov = {0}; + +/* Hash initialization */ + +/* Initialize CNG, if available */ +GIT_INLINE(int) hash_cng_prov_init(void) +{ + OSVERSIONINFOEX version_test = {0}; + DWORD version_test_mask; + DWORDLONG version_condition_mask = 0; + char dll_path[MAX_PATH]; + DWORD dll_path_len, size_len; + + return -1; + + /* Only use CNG on Windows 2008 / Vista SP1 or better (Windows 6.0 SP1) */ + version_test.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + version_test.dwMajorVersion = 6; + version_test.dwMinorVersion = 0; + version_test.wServicePackMajor = 1; + version_test.wServicePackMinor = 0; + + version_test_mask = (VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR); + + VER_SET_CONDITION(version_condition_mask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(version_condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(version_condition_mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + VER_SET_CONDITION(version_condition_mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); + + if (!VerifyVersionInfo(&version_test, version_test_mask, version_condition_mask)) + 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) + 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 || + (hash_prov.prov.cng.get_property = (hash_win32_cng_get_property_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptGetProperty")) == NULL || + (hash_prov.prov.cng.create_hash = (hash_win32_cng_create_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptCreateHash")) == NULL || + (hash_prov.prov.cng.finish_hash = (hash_win32_cng_finish_hash_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptFinishHash")) == NULL || + (hash_prov.prov.cng.hash_data = (hash_win32_cng_hash_data_fn)GetProcAddress(hash_prov.prov.cng.dll, "BCryptHashData")) == NULL || + (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); + 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); + return -1; + } + + /* Get storage space for the hash object */ + 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); + return -1; + } + + hash_prov.type = CNG; + return 0; +} + +GIT_INLINE(void) hash_cng_prov_shutdown(void) +{ + hash_prov.prov.cng.close_algorithm_provider(hash_prov.prov.cng.handle, 0); + FreeLibrary(hash_prov.prov.cng.dll); + + hash_prov.type = INVALID; +} + +/* Initialize CryptoAPI */ +GIT_INLINE(int) hash_cryptoapi_prov_init() +{ + if (!CryptAcquireContext(&hash_prov.prov.cryptoapi.handle, NULL, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + return -1; + + hash_prov.type = CRYPTOAPI; + return 0; +} + +GIT_INLINE(void) hash_cryptoapi_prov_shutdown(void) +{ + CryptReleaseContext(hash_prov.prov.cryptoapi.handle, 0); + + hash_prov.type = INVALID; +} + +int git_hash_global_init() +{ + int error = 0; + + if (hash_prov.type != INVALID) + return 0; + + if ((error = hash_cng_prov_init()) < 0) + error = hash_cryptoapi_prov_init(); + + return error; +} + +void git_hash_global_shutdown() +{ + if (hash_prov.type == CNG) + hash_cng_prov_shutdown(); + else if(hash_prov.type == CRYPTOAPI) + hash_cryptoapi_prov_shutdown(); +} + +/* CryptoAPI: available in Windows XP and newer */ + +GIT_INLINE(int) hash_ctx_cryptoapi_init(git_hash_ctx *ctx) +{ + ctx->type = CRYPTOAPI; + ctx->prov = &hash_prov; + + return git_hash_init(ctx); +} + +GIT_INLINE(int) hash_cryptoapi_init(git_hash_ctx *ctx) +{ + if (ctx->ctx.cryptoapi.valid) + CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle); + + if (!CryptCreateHash(ctx->prov->prov.cryptoapi.handle, CALG_SHA1, 0, 0, &ctx->ctx.cryptoapi.hash_handle)) { + ctx->ctx.cryptoapi.valid = 0; + return -1; + } + + ctx->ctx.cryptoapi.valid = 1; + return 0; +} + +GIT_INLINE(int) hash_cryptoapi_update(git_hash_ctx *ctx, const void *data, size_t len) +{ + assert(ctx->ctx.cryptoapi.valid); + + if (!CryptHashData(ctx->ctx.cryptoapi.hash_handle, (const BYTE *)data, len, 0)) + return -1; + + return 0; +} + +GIT_INLINE(int) hash_cryptoapi_final(git_oid *out, git_hash_ctx *ctx) +{ + DWORD len = 20; + int error = 0; + + assert(ctx->ctx.cryptoapi.valid); + + if (!CryptGetHashParam(ctx->ctx.cryptoapi.hash_handle, HP_HASHVAL, out->id, &len, 0)) + error = -1; + + CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle); + ctx->ctx.cryptoapi.valid = 0; + + return error; +} + +GIT_INLINE(void) hash_ctx_cryptoapi_cleanup(git_hash_ctx *ctx) +{ + if (ctx->ctx.cryptoapi.valid) + CryptDestroyHash(ctx->ctx.cryptoapi.hash_handle); +} + +/* CNG: Available in Windows Server 2008 and newer */ + +GIT_INLINE(int) hash_ctx_cng_init(git_hash_ctx *ctx) +{ + if ((ctx->ctx.cng.hash_object = git__malloc(hash_prov.prov.cng.hash_object_size)) == NULL) + return -1; + + 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); + return -1; + } + + ctx->type = CNG; + ctx->prov = &hash_prov; + + return 0; +} + +GIT_INLINE(int) hash_cng_init(git_hash_ctx *ctx) +{ + BYTE hash[GIT_OID_RAWSZ]; + + if (!ctx->ctx.cng.updated) + 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) + return -1; + + ctx->ctx.cng.updated = 0; + + return 0; +} + +GIT_INLINE(int) hash_cng_update(git_hash_ctx *ctx, const void *data, size_t len) +{ + if (ctx->prov->prov.cng.hash_data(ctx->ctx.cng.hash_handle, (PBYTE)data, len, 0) < 0) + return -1; + + return 0; +} + +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) + return -1; + + ctx->ctx.cng.updated = 0; + + return 0; +} + +GIT_INLINE(void) hash_ctx_cng_cleanup(git_hash_ctx *ctx) +{ + ctx->prov->prov.cng.destroy_hash(ctx->ctx.cng.hash_handle); + git__free(ctx->ctx.cng.hash_object); +} + +/* Indirection between CryptoAPI and CNG */ + +int git_hash_ctx_init(git_hash_ctx *ctx) +{ + int error = 0; + + assert(ctx); + + /* + * When compiled with GIT_THREADS, the global hash_prov data is + * initialized with git_threads_init. Otherwise, it must be initialized + * at first use. + */ + if (hash_prov.type == INVALID && (error = git_hash_global_init()) < 0) + return error; + + memset(ctx, 0x0, sizeof(git_hash_ctx)); + + return (hash_prov.type == CNG) ? hash_ctx_cng_init(ctx) : hash_ctx_cryptoapi_init(ctx); +} + +int git_hash_init(git_hash_ctx *ctx) +{ + assert(ctx && ctx->type); + return (ctx->type == CNG) ? hash_cng_init(ctx) : hash_cryptoapi_init(ctx); +} + +int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) +{ + assert(ctx && ctx->type); + return (ctx->type == CNG) ? hash_cng_update(ctx, data, len) : hash_cryptoapi_update(ctx, data, len); +} + +int git_hash_final(git_oid *out, git_hash_ctx *ctx) +{ + assert(ctx && ctx->type); + return (ctx->type == CNG) ? hash_cng_final(out, ctx) : hash_cryptoapi_final(out, ctx); +} + +void git_hash_ctx_cleanup(git_hash_ctx *ctx) +{ + assert(ctx); + + if (ctx->type == CNG) + hash_ctx_cng_cleanup(ctx); + else if(ctx->type == CRYPTOAPI) + hash_ctx_cryptoapi_cleanup(ctx); +} diff --git a/src/hash/hash_win32.h b/src/hash/hash_win32.h new file mode 100644 index 000000000..b91da3e37 --- /dev/null +++ b/src/hash/hash_win32.h @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2009-2012 the libgit2 contributors + * + * This file is part of libgit2, distributed under the GNU GPL v2 with + * a Linking Exception. For full terms see the included COPYING file. + */ + +#ifndef INCLUDE_hash_win32_h__ +#define INCLUDE_hash_win32_h__ + +#include "common.h" +#include "hash.h" + +#include +#include + +enum hash_win32_prov_type { + INVALID = 0, + CRYPTOAPI, + CNG +}; + +/* + * CryptoAPI is available for hashing on Windows XP and newer. + */ + +struct hash_cryptoapi_prov { + HCRYPTPROV handle; +}; + +/* + * CNG (bcrypt.dll) is significantly more performant than CryptoAPI and is + * preferred, however it is only available on Windows 2008 and newer and + * must therefore be dynamically loaded, and we must inline constants that + * would not exist when building in pre-Windows 2008 environments. + */ + +#define GIT_HASH_CNG_DLL_NAME "bcrypt.dll" + +/* BCRYPT_SHA1_ALGORITHM */ +#define GIT_HASH_CNG_HASH_TYPE L"SHA1" + +/* BCRYPT_OBJECT_LENGTH */ +#define GIT_HASH_CNG_HASH_OBJECT_LEN L"ObjectLength" + +/* BCRYPT_HASH_REUSEABLE_FLAGS */ +#define GIT_HASH_CNG_HASH_REUSABLE 0x00000020 + +/* Function declarations for CNG */ +typedef NTSTATUS (WINAPI *hash_win32_cng_open_algorithm_provider_fn)( + HANDLE /* BCRYPT_ALG_HANDLE */ *phAlgorithm, + LPCWSTR pszAlgId, + LPCWSTR pszImplementation, + DWORD dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_get_property_fn)( + HANDLE /* BCRYPT_HANDLE */ hObject, + LPCWSTR pszProperty, + PUCHAR pbOutput, + ULONG cbOutput, + ULONG *pcbResult, + ULONG dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_create_hash_fn)( + HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm, + HANDLE /* BCRYPT_HASH_HANDLE */ *phHash, + PUCHAR pbHashObject, ULONG cbHashObject, + PUCHAR pbSecret, + ULONG cbSecret, + ULONG dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_finish_hash_fn)( + HANDLE /* BCRYPT_HASH_HANDLE */ hHash, + PUCHAR pbOutput, + ULONG cbOutput, + ULONG dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_hash_data_fn)( + HANDLE /* BCRYPT_HASH_HANDLE */ hHash, + PUCHAR pbInput, + ULONG cbInput, + ULONG dwFlags); + +typedef NTSTATUS (WINAPI *hash_win32_cng_destroy_hash_fn)( + HANDLE /* BCRYPT_HASH_HANDLE */ hHash); + +typedef NTSTATUS (WINAPI *hash_win32_cng_close_algorithm_provider_fn)( + HANDLE /* BCRYPT_ALG_HANDLE */ hAlgorithm, + ULONG dwFlags); + +struct hash_cng_prov { + /* DLL for CNG */ + HINSTANCE dll; + + /* Function pointers for CNG */ + hash_win32_cng_open_algorithm_provider_fn open_algorithm_provider; + hash_win32_cng_get_property_fn get_property; + hash_win32_cng_create_hash_fn create_hash; + hash_win32_cng_finish_hash_fn finish_hash; + hash_win32_cng_hash_data_fn hash_data; + hash_win32_cng_destroy_hash_fn destroy_hash; + hash_win32_cng_close_algorithm_provider_fn close_algorithm_provider; + + HANDLE /* BCRYPT_ALG_HANDLE */ handle; + DWORD hash_object_size; +}; + +struct git_hash_prov { + enum hash_win32_prov_type type; + + union { + struct hash_cryptoapi_prov cryptoapi; + struct hash_cng_prov cng; + } prov; +}; + +/* Hash contexts */ + +struct hash_cryptoapi_ctx { + bool valid; + HCRYPTHASH hash_handle; +}; + +struct hash_cng_ctx { + bool updated; + HANDLE /* BCRYPT_HASH_HANDLE */ hash_handle; + PBYTE hash_object; +}; + +struct git_hash_ctx { + enum hash_win32_prov_type type; + git_hash_prov *prov; + + union { + struct hash_cryptoapi_ctx cryptoapi; + struct hash_cng_ctx cng; + } ctx; +}; + +#endif /* INCLUDE_hash_openssl_h__ */ diff --git a/src/indexer.c b/src/indexer.c index ec4ef7147..4a4ed325a 100644 --- a/src/indexer.c +++ b/src/indexer.c @@ -17,7 +17,6 @@ #include "posix.h" #include "pack.h" #include "filebuf.h" -#include "sha1.h" #define UINT31_MAX (0x7FFFFFFF) @@ -462,7 +461,10 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * struct entry *entry; void *packfile_hash; git_oid file_hash; - SHA_CTX ctx; + git_hash_ctx ctx; + + if (git_hash_ctx_init(&ctx) < 0) + return -1; /* Test for this before resolve_deltas(), as it plays with idx->off */ if (idx->off < idx->pack->mwf.size - GIT_OID_RAWSZ) { @@ -502,12 +504,11 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress * } /* Write out the object names (SHA-1 hashes) */ - SHA1_Init(&ctx); git_vector_foreach(&idx->objects, i, entry) { git_filebuf_write(&idx->index_file, &entry->oid, sizeof(git_oid)); - SHA1_Update(&ctx, &entry->oid, GIT_OID_RAWSZ); + git_hash_update(&ctx, &entry->oid, GIT_OID_RAWSZ); } - SHA1_Final(idx->hash.id, &ctx); + git_hash_final(&idx->hash, &ctx); /* Write out the CRC32 values */ git_vector_foreach(&idx->objects, i, entry) { @@ -582,6 +583,7 @@ on_error: p_close(idx->pack->mwf.fd); git_filebuf_cleanup(&idx->index_file); git_buf_free(&filename); + git_hash_ctx_cleanup(&ctx); return -1; } @@ -682,7 +684,10 @@ int git_indexer_write(git_indexer *idx) struct entry *entry; void *packfile_hash; git_oid file_hash; - SHA_CTX ctx; + git_hash_ctx ctx; + + if (git_hash_ctx_init(&ctx) < 0) + return -1; git_vector_sort(&idx->objects); @@ -712,14 +717,14 @@ int git_indexer_write(git_indexer *idx) } /* Write out the object names (SHA-1 hashes) */ - SHA1_Init(&ctx); git_vector_foreach(&idx->objects, i, entry) { - error = git_filebuf_write(&idx->file, &entry->oid, sizeof(git_oid)); - SHA1_Update(&ctx, &entry->oid, GIT_OID_RAWSZ); - if (error < 0) + if ((error = git_filebuf_write(&idx->file, &entry->oid, sizeof(git_oid))) < 0 || + (error = git_hash_update(&ctx, &entry->oid, GIT_OID_RAWSZ)) < 0) goto cleanup; } - SHA1_Final(idx->hash.id, &ctx); + + if ((error = git_hash_final(&idx->hash, &ctx)) < 0) + goto cleanup; /* Write out the CRC32 values */ git_vector_foreach(&idx->objects, i, entry) { @@ -797,6 +802,7 @@ cleanup: if (error < 0) git_filebuf_cleanup(&idx->file); git_buf_free(&filename); + git_hash_ctx_cleanup(&ctx); return error; } diff --git a/src/odb.c b/src/odb.c index d6b1de946..bc135e35c 100644 --- a/src/odb.c +++ b/src/odb.c @@ -117,23 +117,27 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type) { int hdr_len; char hdr[64], buffer[2048]; - git_hash_ctx *ctx; + git_hash_ctx ctx; ssize_t read_len = 0; + int error = 0; if (!git_object_typeisloose(type)) { giterr_set(GITERR_INVALID, "Invalid object type for hash"); return -1; } + if ((error = git_hash_ctx_init(&ctx)) < 0) + return -1; + hdr_len = format_object_header(hdr, sizeof(hdr), size, type); - ctx = git_hash_new_ctx(); - GITERR_CHECK_ALLOC(ctx); - - git_hash_update(ctx, hdr, hdr_len); + if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0) + goto done; while (size > 0 && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) { - git_hash_update(ctx, buffer, read_len); + if ((error = git_hash_update(&ctx, buffer, read_len)) < 0) + goto done; + size -= read_len; } @@ -141,15 +145,18 @@ int git_odb__hashfd(git_oid *out, git_file fd, size_t size, git_otype type) * If size is not zero, the file was truncated after we originally * stat'd it, so we consider this a read failure too */ if (read_len < 0 || size > 0) { - git_hash_free_ctx(ctx); giterr_set(GITERR_OS, "Error reading file for hashing"); + error = -1; + + goto done; return -1; } - git_hash_final(out, ctx); - git_hash_free_ctx(ctx); + error = git_hash_final(out, &ctx); - return 0; +done: + git_hash_ctx_cleanup(&ctx); + return error; } int git_odb__hashfd_filtered( diff --git a/src/pack-objects.c b/src/pack-objects.c index 7acc93328..f75267629 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -103,7 +103,7 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo) *out = NULL; - pb = git__calloc(sizeof(*pb), 1); + pb = git__calloc(1, sizeof(*pb)); GITERR_CHECK_ALLOC(pb); pb->object_ix = git_oidmap_alloc(); @@ -113,9 +113,8 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo) pb->repo = repo; pb->nr_threads = 1; /* do not spawn any thread by default */ - pb->ctx = git_hash_new_ctx(); - if (!pb->ctx || + if (git_hash_ctx_init(&pb->ctx) < 0 || git_repository_odb(&pb->odb, repo) < 0 || packbuilder_config(pb) < 0) goto on_error; @@ -297,14 +296,13 @@ static int write_object(git_buf *buf, git_packbuilder *pb, git_pobject *po) if (git_buf_put(buf, (char *)hdr, hdr_len) < 0) goto on_error; - git_hash_update(pb->ctx, hdr, hdr_len); + if (git_hash_update(&pb->ctx, hdr, hdr_len) < 0) + goto on_error; if (type == GIT_OBJ_REF_DELTA) { - if (git_buf_put(buf, (char *)po->delta->id.id, - GIT_OID_RAWSZ) < 0) + if (git_buf_put(buf, (char *)po->delta->id.id, GIT_OID_RAWSZ) < 0 || + git_hash_update(&pb->ctx, po->delta->id.id, GIT_OID_RAWSZ) < 0) goto on_error; - - git_hash_update(pb->ctx, po->delta->id.id, GIT_OID_RAWSZ); } /* Write data */ @@ -319,11 +317,10 @@ static int write_object(git_buf *buf, git_packbuilder *pb, git_pobject *po) size = zbuf.size; } - if (git_buf_put(buf, data, size) < 0) + if (git_buf_put(buf, data, size) < 0 || + git_hash_update(&pb->ctx, data, size) < 0) goto on_error; - git_hash_update(pb->ctx, data, size); - if (po->delta_data) git__free(po->delta_data); @@ -573,7 +570,8 @@ static int write_pack(git_packbuilder *pb, if (cb(&ph, sizeof(ph), data) < 0) goto on_error; - git_hash_update(pb->ctx, &ph, sizeof(ph)); + if (git_hash_update(&pb->ctx, &ph, sizeof(ph)) < 0) + goto on_error; pb->nr_remaining = pb->nr_objects; do { @@ -592,7 +590,9 @@ static int write_pack(git_packbuilder *pb, git__free(write_order); git_buf_free(&buf); - git_hash_final(&pb->pack_oid, pb->ctx); + + if (git_hash_final(&pb->pack_oid, &pb->ctx) < 0) + goto on_error; return cb(pb->pack_oid.id, GIT_OID_RAWSZ, data); @@ -1318,14 +1318,13 @@ void git_packbuilder_free(git_packbuilder *pb) if (pb->odb) git_odb_free(pb->odb); - if (pb->ctx) - git_hash_free_ctx(pb->ctx); - if (pb->object_ix) git_oidmap_free(pb->object_ix); if (pb->object_list) git__free(pb->object_list); + git_hash_ctx_cleanup(&pb->ctx); + git__free(pb); } diff --git a/src/pack-objects.h b/src/pack-objects.h index 0a88f7dd7..8c01f7189 100644 --- a/src/pack-objects.h +++ b/src/pack-objects.h @@ -52,7 +52,7 @@ struct git_packbuilder { git_repository *repo; /* associated repository */ git_odb *odb; /* associated object database */ - git_hash_ctx *ctx; + git_hash_ctx ctx; uint32_t nr_objects, nr_alloc, diff --git a/src/sha1.h b/src/sha1.h deleted file mode 100644 index 41e8abad6..000000000 --- a/src/sha1.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2009-2012 the libgit2 contributors - * - * This file is part of libgit2, distributed under the GNU GPL v2 with - * a Linking Exception. For full terms see the included COPYING file. - */ - -#ifndef INCLUDE_sha1_h__ -#define INCLUDE_sha1_h__ - -#ifdef OPENSSL_SHA -# include - -#else -typedef struct { - unsigned long long size; - unsigned int H[5]; - unsigned int W[16]; -} blk_SHA_CTX; - - -void git__blk_SHA1_Init(blk_SHA_CTX *ctx); -void git__blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, size_t len); -void git__blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx); - -#define SHA_CTX blk_SHA_CTX -#define SHA1_Init git__blk_SHA1_Init -#define SHA1_Update git__blk_SHA1_Update -#define SHA1_Final git__blk_SHA1_Final - -#endif // OPENSSL_SHA - -#endif diff --git a/tests-clar/object/raw/hash.c b/tests-clar/object/raw/hash.c index 4b8b1b74c..f26035e45 100644 --- a/tests-clar/object/raw/hash.c +++ b/tests-clar/object/raw/hash.c @@ -23,25 +23,25 @@ static char *bye_text = "bye world\n"; void test_object_raw_hash__hash_by_blocks(void) { - git_hash_ctx *ctx; + git_hash_ctx ctx; git_oid id1, id2; - cl_assert((ctx = git_hash_new_ctx()) != NULL); + cl_git_pass(git_hash_ctx_init(&ctx)); /* should already be init'd */ - git_hash_update(ctx, hello_text, strlen(hello_text)); - git_hash_final(&id2, ctx); + cl_git_pass(git_hash_update(&ctx, hello_text, strlen(hello_text))); + cl_git_pass(git_hash_final(&id2, &ctx)); cl_git_pass(git_oid_fromstr(&id1, hello_id)); cl_assert(git_oid_cmp(&id1, &id2) == 0); /* reinit should permit reuse */ - git_hash_init(ctx); - git_hash_update(ctx, bye_text, strlen(bye_text)); - git_hash_final(&id2, ctx); + cl_git_pass(git_hash_init(&ctx)); + cl_git_pass(git_hash_update(&ctx, bye_text, strlen(bye_text))); + cl_git_pass(git_hash_final(&id2, &ctx)); cl_git_pass(git_oid_fromstr(&id1, bye_id)); cl_assert(git_oid_cmp(&id1, &id2) == 0); - git_hash_free_ctx(ctx); + git_hash_ctx_cleanup(&ctx); } void test_object_raw_hash__hash_buffer_in_single_call(void)