mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-11 18:17:54 +00:00
Merge pull request #1055 from ethomson/sha1_win32
Win32 CryptoAPI and CNG support for SHA1
This commit is contained in:
commit
3741a37f5e
@ -39,11 +39,14 @@ ENDIF()
|
|||||||
# Specify sha1 implementation
|
# Specify sha1 implementation
|
||||||
IF (SHA1_TYPE STREQUAL "ppc")
|
IF (SHA1_TYPE STREQUAL "ppc")
|
||||||
ADD_DEFINITIONS(-DPPC_SHA1)
|
ADD_DEFINITIONS(-DPPC_SHA1)
|
||||||
FILE(GLOB SRC_SHA1 src/ppc/*.c src/ppc/*.S)
|
FILE(GLOB SRC_SHA1 src/hash/hash_ppc.c src/hash/hash_ppc_core.S)
|
||||||
ELSEIF (OPENSSL_FOUND) # libcrypto's implementation is faster than ours
|
ELSEIF (WIN32 AND NOT MINGW AND NOT SHA1_TYPE STREQUAL "builtin")
|
||||||
ADD_DEFINITIONS(-DOPENSSL_SHA)
|
ADD_DEFINITIONS(-DWIN32_SHA1)
|
||||||
ELSE ()
|
FILE(GLOB SRC_SHA1 src/hash/hash_win32.c)
|
||||||
FILE(GLOB SRC_SHA1 src/sha1/*.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()
|
ENDIF()
|
||||||
|
|
||||||
IF (NOT WIN32)
|
IF (NOT WIN32)
|
||||||
|
@ -27,8 +27,10 @@ GIT_BEGIN_DECL
|
|||||||
*
|
*
|
||||||
* If libgit2 has been built without GIT_THREADS
|
* If libgit2 has been built without GIT_THREADS
|
||||||
* support, this function is a no-op.
|
* 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.
|
* Shutdown the threading system.
|
||||||
|
@ -85,8 +85,8 @@ static int lock_file(git_filebuf *file, int flags)
|
|||||||
|
|
||||||
while ((read_bytes = p_read(source, buffer, sizeof(buffer))) > 0) {
|
while ((read_bytes = p_read(source, buffer, sizeof(buffer))) > 0) {
|
||||||
p_write(file->fd, buffer, read_bytes);
|
p_write(file->fd, buffer, read_bytes);
|
||||||
if (file->digest)
|
if (file->compute_digest)
|
||||||
git_hash_update(file->digest, buffer, read_bytes);
|
git_hash_update(&file->digest, buffer, read_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
p_close(source);
|
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))
|
if (file->fd_is_open && file->path_lock && git_path_exists(file->path_lock))
|
||||||
p_unlink(file->path_lock);
|
p_unlink(file->path_lock);
|
||||||
|
|
||||||
if (file->digest)
|
if (file->compute_digest) {
|
||||||
git_hash_free_ctx(file->digest);
|
git_hash_ctx_cleanup(&file->digest);
|
||||||
|
file->compute_digest = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (file->buffer)
|
if (file->buffer)
|
||||||
git__free(file->buffer);
|
git__free(file->buffer);
|
||||||
@ -149,8 +151,8 @@ static int write_normal(git_filebuf *file, void *source, size_t len)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file->digest)
|
if (file->compute_digest)
|
||||||
git_hash_update(file->digest, source, len);
|
git_hash_update(&file->digest, source, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -186,8 +188,8 @@ static int write_deflate(git_filebuf *file, void *source, size_t len)
|
|||||||
|
|
||||||
assert(zs->avail_in == 0);
|
assert(zs->avail_in == 0);
|
||||||
|
|
||||||
if (file->digest)
|
if (file->compute_digest)
|
||||||
git_hash_update(file->digest, source, len);
|
git_hash_update(&file->digest, source, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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 we are hashing on-write, allocate a new hash context */
|
||||||
if (flags & GIT_FILEBUF_HASH_CONTENTS) {
|
if (flags & GIT_FILEBUF_HASH_CONTENTS) {
|
||||||
file->digest = git_hash_new_ctx();
|
file->compute_digest = 1;
|
||||||
GITERR_CHECK_ALLOC(file->digest);
|
|
||||||
|
if (git_hash_ctx_init(&file->digest) < 0)
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
compression = flags >> GIT_FILEBUF_DEFLATE_SHIFT;
|
compression = flags >> GIT_FILEBUF_DEFLATE_SHIFT;
|
||||||
@ -291,16 +295,16 @@ cleanup:
|
|||||||
|
|
||||||
int git_filebuf_hash(git_oid *oid, git_filebuf *file)
|
int git_filebuf_hash(git_oid *oid, git_filebuf *file)
|
||||||
{
|
{
|
||||||
assert(oid && file && file->digest);
|
assert(oid && file && file->compute_digest);
|
||||||
|
|
||||||
flush_buffer(file);
|
flush_buffer(file);
|
||||||
|
|
||||||
if (verify_last_error(file) < 0)
|
if (verify_last_error(file) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
git_hash_final(oid, file->digest);
|
git_hash_final(oid, &file->digest);
|
||||||
git_hash_free_ctx(file->digest);
|
git_hash_ctx_cleanup(&file->digest);
|
||||||
file->digest = NULL;
|
file->compute_digest = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ struct git_filebuf {
|
|||||||
|
|
||||||
int (*write)(struct git_filebuf *file, void *source, size_t len);
|
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 *buffer;
|
||||||
unsigned char *z_buf;
|
unsigned char *z_buf;
|
||||||
|
51
src/global.c
51
src/global.c
@ -6,6 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
#include "hash.h"
|
||||||
#include "git2/threads.h"
|
#include "git2/threads.h"
|
||||||
#include "thread-utils.h"
|
#include "thread-utils.h"
|
||||||
|
|
||||||
@ -38,19 +39,39 @@ git_mutex git__mwindow_mutex;
|
|||||||
* functions are not available in that case.
|
* 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)
|
#if defined(GIT_THREADS) && defined(GIT_WIN32)
|
||||||
|
|
||||||
static DWORD _tls_index;
|
static DWORD _tls_index;
|
||||||
static int _tls_init = 0;
|
static int _tls_init = 0;
|
||||||
|
|
||||||
void git_threads_init(void)
|
int git_threads_init(void)
|
||||||
{
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
if (_tls_init)
|
if (_tls_init)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
_tls_index = TlsAlloc();
|
_tls_index = TlsAlloc();
|
||||||
_tls_init = 1;
|
|
||||||
git_mutex_init(&git__mwindow_mutex);
|
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)
|
void git_threads_shutdown(void)
|
||||||
@ -58,6 +79,9 @@ void git_threads_shutdown(void)
|
|||||||
TlsFree(_tls_index);
|
TlsFree(_tls_index);
|
||||||
_tls_init = 0;
|
_tls_init = 0;
|
||||||
git_mutex_free(&git__mwindow_mutex);
|
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)
|
git_global_st *git__global_state(void)
|
||||||
@ -88,19 +112,31 @@ static void cb__free_status(void *st)
|
|||||||
git__free(st);
|
git__free(st);
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_threads_init(void)
|
int git_threads_init(void)
|
||||||
{
|
{
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
if (_tls_init)
|
if (_tls_init)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
pthread_key_create(&_tls_key, &cb__free_status);
|
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)
|
void git_threads_shutdown(void)
|
||||||
{
|
{
|
||||||
pthread_key_delete(_tls_key);
|
pthread_key_delete(_tls_key);
|
||||||
_tls_init = 0;
|
_tls_init = 0;
|
||||||
|
|
||||||
|
/* Shut down any subsystems that have global state */
|
||||||
|
git_hash_global_shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
git_global_st *git__global_state(void)
|
git_global_st *git__global_state(void)
|
||||||
@ -125,9 +161,10 @@ git_global_st *git__global_state(void)
|
|||||||
|
|
||||||
static git_global_st __state;
|
static git_global_st __state;
|
||||||
|
|
||||||
void git_threads_init(void)
|
int git_threads_init(void)
|
||||||
{
|
{
|
||||||
/* noop */
|
/* noop */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git_threads_shutdown(void)
|
void git_threads_shutdown(void)
|
||||||
|
@ -8,6 +8,15 @@
|
|||||||
#define INCLUDE_global_h__
|
#define INCLUDE_global_h__
|
||||||
|
|
||||||
#include "mwindow.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 {
|
typedef struct {
|
||||||
git_error *last_error;
|
git_error *last_error;
|
||||||
|
81
src/hash.c
81
src/hash.c
@ -8,67 +8,40 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
|
||||||
#if defined(PPC_SHA1)
|
int git_hash_buf(git_oid *out, const void *data, size_t len)
|
||||||
# include "ppc/sha1.h"
|
|
||||||
#else
|
|
||||||
# include "sha1.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct git_hash_ctx {
|
|
||||||
SHA_CTX c;
|
|
||||||
};
|
|
||||||
|
|
||||||
git_hash_ctx *git_hash_new_ctx(void)
|
|
||||||
{
|
{
|
||||||
git_hash_ctx *ctx = git__malloc(sizeof(*ctx));
|
git_hash_ctx ctx;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
if (!ctx)
|
if (git_hash_ctx_init(&ctx) < 0)
|
||||||
return NULL;
|
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);
|
git_hash_ctx 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;
|
|
||||||
size_t i;
|
size_t i;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
SHA1_Init(&c);
|
if (git_hash_ctx_init(&ctx) < 0)
|
||||||
for (i = 0; i < n; i++)
|
return -1;
|
||||||
SHA1_Update(&c, vec[i].data, vec[i].len);
|
|
||||||
SHA1_Final(out->id, &c);
|
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;
|
||||||
}
|
}
|
||||||
|
30
src/hash.h
30
src/hash.h
@ -9,21 +9,35 @@
|
|||||||
|
|
||||||
#include "git2/oid.h"
|
#include "git2/oid.h"
|
||||||
|
|
||||||
|
typedef struct git_hash_prov git_hash_prov;
|
||||||
typedef struct git_hash_ctx git_hash_ctx;
|
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 {
|
typedef struct {
|
||||||
void *data;
|
void *data;
|
||||||
size_t len;
|
size_t len;
|
||||||
} git_buf_vec;
|
} git_buf_vec;
|
||||||
|
|
||||||
git_hash_ctx *git_hash_new_ctx(void);
|
int git_hash_init(git_hash_ctx *c);
|
||||||
void git_hash_free_ctx(git_hash_ctx *ctx);
|
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);
|
int git_hash_buf(git_oid *out, const void *data, size_t len);
|
||||||
void git_hash_update(git_hash_ctx *c, const void *data, size_t len);
|
int git_hash_vec(git_oid *out, git_buf_vec *vec, size_t n);
|
||||||
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);
|
|
||||||
|
|
||||||
#endif /* INCLUDE_hash_h__ */
|
#endif /* INCLUDE_hash_h__ */
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "sha1.h"
|
#include "hash.h"
|
||||||
|
#include "hash/hash_generic.h"
|
||||||
|
|
||||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
#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_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 )
|
#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 A,B,C,D,E;
|
||||||
unsigned int array[16];
|
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;
|
ctx->H[4] += E;
|
||||||
}
|
}
|
||||||
|
|
||||||
void git__blk_SHA1_Init(blk_SHA_CTX *ctx)
|
int git_hash_init(git_hash_ctx *ctx)
|
||||||
{
|
{
|
||||||
ctx->size = 0;
|
ctx->size = 0;
|
||||||
|
|
||||||
@ -230,9 +231,11 @@ void git__blk_SHA1_Init(blk_SHA_CTX *ctx)
|
|||||||
ctx->H[2] = 0x98badcfe;
|
ctx->H[2] = 0x98badcfe;
|
||||||
ctx->H[3] = 0x10325476;
|
ctx->H[3] = 0x10325476;
|
||||||
ctx->H[4] = 0xc3d2e1f0;
|
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;
|
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;
|
len -= left;
|
||||||
data = ((const char *)data + left);
|
data = ((const char *)data + left);
|
||||||
if (lenW)
|
if (lenW)
|
||||||
return;
|
return 0;
|
||||||
blk_SHA1_Block(ctx, ctx->W);
|
hash__block(ctx, ctx->W);
|
||||||
}
|
}
|
||||||
while (len >= 64) {
|
while (len >= 64) {
|
||||||
blk_SHA1_Block(ctx, data);
|
hash__block(ctx, data);
|
||||||
data = ((const char *)data + 64);
|
data = ((const char *)data + 64);
|
||||||
len -= 64;
|
len -= 64;
|
||||||
}
|
}
|
||||||
if (len)
|
if (len)
|
||||||
memcpy(ctx->W, data, 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 };
|
static const unsigned char pad[64] = { 0x80 };
|
||||||
unsigned int padlen[2];
|
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));
|
padlen[1] = htonl((uint32_t)(ctx->size << 3));
|
||||||
|
|
||||||
i = ctx->size & 63;
|
i = ctx->size & 63;
|
||||||
git__blk_SHA1_Update(ctx, pad, 1+ (63 & (55 - i)));
|
git_hash_update(ctx, pad, 1+ (63 & (55 - i)));
|
||||||
git__blk_SHA1_Update(ctx, padlen, 8);
|
git_hash_update(ctx, padlen, 8);
|
||||||
|
|
||||||
/* Output hash */
|
/* Output hash */
|
||||||
for (i = 0; i < 5; i++)
|
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;
|
||||||
}
|
}
|
||||||
|
|
24
src/hash/hash_generic.h
Normal file
24
src/hash/hash_generic.h
Normal file
@ -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__ */
|
45
src/hash/hash_openssl.h
Normal file
45
src/hash/hash_openssl.h
Normal file
@ -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 <openssl/sha.h>
|
||||||
|
|
||||||
|
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__ */
|
@ -4,14 +4,17 @@
|
|||||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||||
* a Linking Exception. For full terms see the included COPYING file.
|
* a Linking Exception. For full terms see the included COPYING file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#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);
|
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[0] = 0x67452301;
|
||||||
c->hash[1] = 0xEFCDAB89;
|
c->hash[1] = 0xEFCDAB89;
|
||||||
@ -23,7 +26,7 @@ int ppc_SHA1_Init(ppc_SHA_CTX *c)
|
|||||||
return 0;
|
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;
|
unsigned long nb;
|
||||||
const unsigned char *p = ptr;
|
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;
|
nb = n;
|
||||||
memcpy(&c->buf.b[c->cnt], p, nb);
|
memcpy(&c->buf.b[c->cnt], p, nb);
|
||||||
if ((c->cnt += nb) == 64) {
|
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;
|
c->cnt = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nb = n >> 6;
|
nb = n >> 6;
|
||||||
ppc_sha1_core(c->hash, p, nb);
|
hash_ppc_core(c->hash, p, nb);
|
||||||
nb <<= 6;
|
nb <<= 6;
|
||||||
}
|
}
|
||||||
n -= nb;
|
n -= nb;
|
||||||
@ -50,7 +53,7 @@ int ppc_SHA1_Update(ppc_SHA_CTX *c, const void *ptr, unsigned long n)
|
|||||||
return 0;
|
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;
|
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 > 56) {
|
||||||
if (cnt < 64)
|
if (cnt < 64)
|
||||||
memset(&c->buf.b[cnt], 0, 64 - cnt);
|
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;
|
cnt = 0;
|
||||||
}
|
}
|
||||||
if (cnt < 56)
|
if (cnt < 56)
|
||||||
memset(&c->buf.b[cnt], 0, 56 - cnt);
|
memset(&c->buf.b[cnt], 0, 56 - cnt);
|
||||||
c->buf.l[7] = c->len;
|
c->buf.l[7] = c->len;
|
||||||
ppc_sha1_core(c->hash, c->buf.b, 1);
|
hash_ppc_core(c->hash, c->buf.b, 1);
|
||||||
memcpy(hash, c->hash, 20);
|
memcpy(oid->id, c->hash, 20);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -4,9 +4,13 @@
|
|||||||
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
* This file is part of libgit2, distributed under the GNU GPL v2 with
|
||||||
* a Linking Exception. For full terms see the included COPYING file.
|
* a Linking Exception. For full terms see the included COPYING file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDE_hash_ppc_h__
|
||||||
|
#define INCLUDE_hash_ppc_h__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef struct {
|
struct git_hash_ctx {
|
||||||
uint32_t hash[5];
|
uint32_t hash[5];
|
||||||
uint32_t cnt;
|
uint32_t cnt;
|
||||||
uint64_t len;
|
uint64_t len;
|
||||||
@ -14,13 +18,11 @@ typedef struct {
|
|||||||
unsigned char b[64];
|
unsigned char b[64];
|
||||||
uint64_t l[8];
|
uint64_t l[8];
|
||||||
} buf;
|
} buf;
|
||||||
} ppc_SHA_CTX;
|
};
|
||||||
|
|
||||||
int ppc_SHA1_Init(ppc_SHA_CTX *c);
|
#define git_hash_global_init() 0
|
||||||
int ppc_SHA1_Update(ppc_SHA_CTX *c, const void *p, unsigned long n);
|
#define git_hash_global_shutdown() /* noop */
|
||||||
int ppc_SHA1_Final(unsigned char *hash, ppc_SHA_CTX *c);
|
#define git_hash_ctx_init(ctx) git_hash_init(ctx)
|
||||||
|
#define git_hash_ctx_cleanup(ctx)
|
||||||
|
|
||||||
#define SHA_CTX ppc_SHA_CTX
|
#endif /* INCLUDE_hash_generic_h__ */
|
||||||
#define SHA1_Init ppc_SHA1_Init
|
|
||||||
#define SHA1_Update ppc_SHA1_Update
|
|
||||||
#define SHA1_Final ppc_SHA1_Final
|
|
@ -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)+12, (s)+12,); \
|
||||||
STEPUP4(fn, (t)+16, (s)+16, loadk)
|
STEPUP4(fn, (t)+16, (s)+16, loadk)
|
||||||
|
|
||||||
.globl ppc_sha1_core
|
.globl hash_ppc_core
|
||||||
ppc_sha1_core:
|
hash_ppc_core:
|
||||||
stwu %r1,-80(%r1)
|
stwu %r1,-80(%r1)
|
||||||
stmw %r13,4(%r1)
|
stmw %r13,4(%r1)
|
||||||
|
|
291
src/hash/hash_win32.c
Normal file
291
src/hash/hash_win32.c
Normal file
@ -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 <wincrypt.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
140
src/hash/hash_win32.h
Normal file
140
src/hash/hash_win32.h
Normal file
@ -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 <wincrypt.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
|
||||||
|
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__ */
|
@ -17,7 +17,6 @@
|
|||||||
#include "posix.h"
|
#include "posix.h"
|
||||||
#include "pack.h"
|
#include "pack.h"
|
||||||
#include "filebuf.h"
|
#include "filebuf.h"
|
||||||
#include "sha1.h"
|
|
||||||
|
|
||||||
#define UINT31_MAX (0x7FFFFFFF)
|
#define UINT31_MAX (0x7FFFFFFF)
|
||||||
|
|
||||||
@ -462,7 +461,10 @@ int git_indexer_stream_finalize(git_indexer_stream *idx, git_transfer_progress *
|
|||||||
struct entry *entry;
|
struct entry *entry;
|
||||||
void *packfile_hash;
|
void *packfile_hash;
|
||||||
git_oid file_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 */
|
/* Test for this before resolve_deltas(), as it plays with idx->off */
|
||||||
if (idx->off < idx->pack->mwf.size - GIT_OID_RAWSZ) {
|
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) */
|
/* Write out the object names (SHA-1 hashes) */
|
||||||
SHA1_Init(&ctx);
|
|
||||||
git_vector_foreach(&idx->objects, i, entry) {
|
git_vector_foreach(&idx->objects, i, entry) {
|
||||||
git_filebuf_write(&idx->index_file, &entry->oid, sizeof(git_oid));
|
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 */
|
/* Write out the CRC32 values */
|
||||||
git_vector_foreach(&idx->objects, i, entry) {
|
git_vector_foreach(&idx->objects, i, entry) {
|
||||||
@ -582,6 +583,7 @@ on_error:
|
|||||||
p_close(idx->pack->mwf.fd);
|
p_close(idx->pack->mwf.fd);
|
||||||
git_filebuf_cleanup(&idx->index_file);
|
git_filebuf_cleanup(&idx->index_file);
|
||||||
git_buf_free(&filename);
|
git_buf_free(&filename);
|
||||||
|
git_hash_ctx_cleanup(&ctx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -682,7 +684,10 @@ int git_indexer_write(git_indexer *idx)
|
|||||||
struct entry *entry;
|
struct entry *entry;
|
||||||
void *packfile_hash;
|
void *packfile_hash;
|
||||||
git_oid file_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);
|
git_vector_sort(&idx->objects);
|
||||||
|
|
||||||
@ -712,14 +717,14 @@ int git_indexer_write(git_indexer *idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write out the object names (SHA-1 hashes) */
|
/* Write out the object names (SHA-1 hashes) */
|
||||||
SHA1_Init(&ctx);
|
|
||||||
git_vector_foreach(&idx->objects, i, entry) {
|
git_vector_foreach(&idx->objects, i, entry) {
|
||||||
error = git_filebuf_write(&idx->file, &entry->oid, sizeof(git_oid));
|
if ((error = git_filebuf_write(&idx->file, &entry->oid, sizeof(git_oid))) < 0 ||
|
||||||
SHA1_Update(&ctx, &entry->oid, GIT_OID_RAWSZ);
|
(error = git_hash_update(&ctx, &entry->oid, GIT_OID_RAWSZ)) < 0)
|
||||||
if (error < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
SHA1_Final(idx->hash.id, &ctx);
|
|
||||||
|
if ((error = git_hash_final(&idx->hash, &ctx)) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
/* Write out the CRC32 values */
|
/* Write out the CRC32 values */
|
||||||
git_vector_foreach(&idx->objects, i, entry) {
|
git_vector_foreach(&idx->objects, i, entry) {
|
||||||
@ -797,6 +802,7 @@ cleanup:
|
|||||||
if (error < 0)
|
if (error < 0)
|
||||||
git_filebuf_cleanup(&idx->file);
|
git_filebuf_cleanup(&idx->file);
|
||||||
git_buf_free(&filename);
|
git_buf_free(&filename);
|
||||||
|
git_hash_ctx_cleanup(&ctx);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
27
src/odb.c
27
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;
|
int hdr_len;
|
||||||
char hdr[64], buffer[2048];
|
char hdr[64], buffer[2048];
|
||||||
git_hash_ctx *ctx;
|
git_hash_ctx ctx;
|
||||||
ssize_t read_len = 0;
|
ssize_t read_len = 0;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
if (!git_object_typeisloose(type)) {
|
if (!git_object_typeisloose(type)) {
|
||||||
giterr_set(GITERR_INVALID, "Invalid object type for hash");
|
giterr_set(GITERR_INVALID, "Invalid object type for hash");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((error = git_hash_ctx_init(&ctx)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
hdr_len = format_object_header(hdr, sizeof(hdr), size, type);
|
hdr_len = format_object_header(hdr, sizeof(hdr), size, type);
|
||||||
|
|
||||||
ctx = git_hash_new_ctx();
|
if ((error = git_hash_update(&ctx, hdr, hdr_len)) < 0)
|
||||||
GITERR_CHECK_ALLOC(ctx);
|
goto done;
|
||||||
|
|
||||||
git_hash_update(ctx, hdr, hdr_len);
|
|
||||||
|
|
||||||
while (size > 0 && (read_len = p_read(fd, buffer, sizeof(buffer))) > 0) {
|
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;
|
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
|
* If size is not zero, the file was truncated after we originally
|
||||||
* stat'd it, so we consider this a read failure too */
|
* stat'd it, so we consider this a read failure too */
|
||||||
if (read_len < 0 || size > 0) {
|
if (read_len < 0 || size > 0) {
|
||||||
git_hash_free_ctx(ctx);
|
|
||||||
giterr_set(GITERR_OS, "Error reading file for hashing");
|
giterr_set(GITERR_OS, "Error reading file for hashing");
|
||||||
|
error = -1;
|
||||||
|
|
||||||
|
goto done;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
git_hash_final(out, ctx);
|
error = git_hash_final(out, &ctx);
|
||||||
git_hash_free_ctx(ctx);
|
|
||||||
|
|
||||||
return 0;
|
done:
|
||||||
|
git_hash_ctx_cleanup(&ctx);
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_odb__hashfd_filtered(
|
int git_odb__hashfd_filtered(
|
||||||
|
@ -103,7 +103,7 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo)
|
|||||||
|
|
||||||
*out = NULL;
|
*out = NULL;
|
||||||
|
|
||||||
pb = git__calloc(sizeof(*pb), 1);
|
pb = git__calloc(1, sizeof(*pb));
|
||||||
GITERR_CHECK_ALLOC(pb);
|
GITERR_CHECK_ALLOC(pb);
|
||||||
|
|
||||||
pb->object_ix = git_oidmap_alloc();
|
pb->object_ix = git_oidmap_alloc();
|
||||||
@ -113,9 +113,8 @@ int git_packbuilder_new(git_packbuilder **out, git_repository *repo)
|
|||||||
|
|
||||||
pb->repo = repo;
|
pb->repo = repo;
|
||||||
pb->nr_threads = 1; /* do not spawn any thread by default */
|
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 ||
|
git_repository_odb(&pb->odb, repo) < 0 ||
|
||||||
packbuilder_config(pb) < 0)
|
packbuilder_config(pb) < 0)
|
||||||
goto on_error;
|
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)
|
if (git_buf_put(buf, (char *)hdr, hdr_len) < 0)
|
||||||
goto on_error;
|
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 (type == GIT_OBJ_REF_DELTA) {
|
||||||
if (git_buf_put(buf, (char *)po->delta->id.id,
|
if (git_buf_put(buf, (char *)po->delta->id.id, GIT_OID_RAWSZ) < 0 ||
|
||||||
GIT_OID_RAWSZ) < 0)
|
git_hash_update(&pb->ctx, po->delta->id.id, GIT_OID_RAWSZ) < 0)
|
||||||
goto on_error;
|
goto on_error;
|
||||||
|
|
||||||
git_hash_update(pb->ctx, po->delta->id.id, GIT_OID_RAWSZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Write data */
|
/* Write data */
|
||||||
@ -319,11 +317,10 @@ static int write_object(git_buf *buf, git_packbuilder *pb, git_pobject *po)
|
|||||||
size = zbuf.size;
|
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;
|
goto on_error;
|
||||||
|
|
||||||
git_hash_update(pb->ctx, data, size);
|
|
||||||
|
|
||||||
if (po->delta_data)
|
if (po->delta_data)
|
||||||
git__free(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)
|
if (cb(&ph, sizeof(ph), data) < 0)
|
||||||
goto on_error;
|
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;
|
pb->nr_remaining = pb->nr_objects;
|
||||||
do {
|
do {
|
||||||
@ -592,7 +590,9 @@ static int write_pack(git_packbuilder *pb,
|
|||||||
|
|
||||||
git__free(write_order);
|
git__free(write_order);
|
||||||
git_buf_free(&buf);
|
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);
|
return cb(pb->pack_oid.id, GIT_OID_RAWSZ, data);
|
||||||
|
|
||||||
@ -1318,14 +1318,13 @@ void git_packbuilder_free(git_packbuilder *pb)
|
|||||||
if (pb->odb)
|
if (pb->odb)
|
||||||
git_odb_free(pb->odb);
|
git_odb_free(pb->odb);
|
||||||
|
|
||||||
if (pb->ctx)
|
|
||||||
git_hash_free_ctx(pb->ctx);
|
|
||||||
|
|
||||||
if (pb->object_ix)
|
if (pb->object_ix)
|
||||||
git_oidmap_free(pb->object_ix);
|
git_oidmap_free(pb->object_ix);
|
||||||
|
|
||||||
if (pb->object_list)
|
if (pb->object_list)
|
||||||
git__free(pb->object_list);
|
git__free(pb->object_list);
|
||||||
|
|
||||||
|
git_hash_ctx_cleanup(&pb->ctx);
|
||||||
|
|
||||||
git__free(pb);
|
git__free(pb);
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ struct git_packbuilder {
|
|||||||
git_repository *repo; /* associated repository */
|
git_repository *repo; /* associated repository */
|
||||||
git_odb *odb; /* associated object database */
|
git_odb *odb; /* associated object database */
|
||||||
|
|
||||||
git_hash_ctx *ctx;
|
git_hash_ctx ctx;
|
||||||
|
|
||||||
uint32_t nr_objects,
|
uint32_t nr_objects,
|
||||||
nr_alloc,
|
nr_alloc,
|
||||||
|
33
src/sha1.h
33
src/sha1.h
@ -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 <openssl/sha.h>
|
|
||||||
|
|
||||||
#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
|
|
@ -23,25 +23,25 @@ static char *bye_text = "bye world\n";
|
|||||||
|
|
||||||
void test_object_raw_hash__hash_by_blocks(void)
|
void test_object_raw_hash__hash_by_blocks(void)
|
||||||
{
|
{
|
||||||
git_hash_ctx *ctx;
|
git_hash_ctx ctx;
|
||||||
git_oid id1, id2;
|
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 */
|
/* should already be init'd */
|
||||||
git_hash_update(ctx, hello_text, strlen(hello_text));
|
cl_git_pass(git_hash_update(&ctx, hello_text, strlen(hello_text)));
|
||||||
git_hash_final(&id2, ctx);
|
cl_git_pass(git_hash_final(&id2, &ctx));
|
||||||
cl_git_pass(git_oid_fromstr(&id1, hello_id));
|
cl_git_pass(git_oid_fromstr(&id1, hello_id));
|
||||||
cl_assert(git_oid_cmp(&id1, &id2) == 0);
|
cl_assert(git_oid_cmp(&id1, &id2) == 0);
|
||||||
|
|
||||||
/* reinit should permit reuse */
|
/* reinit should permit reuse */
|
||||||
git_hash_init(ctx);
|
cl_git_pass(git_hash_init(&ctx));
|
||||||
git_hash_update(ctx, bye_text, strlen(bye_text));
|
cl_git_pass(git_hash_update(&ctx, bye_text, strlen(bye_text)));
|
||||||
git_hash_final(&id2, ctx);
|
cl_git_pass(git_hash_final(&id2, &ctx));
|
||||||
cl_git_pass(git_oid_fromstr(&id1, bye_id));
|
cl_git_pass(git_oid_fromstr(&id1, bye_id));
|
||||||
cl_assert(git_oid_cmp(&id1, &id2) == 0);
|
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)
|
void test_object_raw_hash__hash_buffer_in_single_call(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user