mirror of
https://github.com/libgit2/libgit2.git
synced 2026-01-25 11:06:32 +00:00
hash: introduce source files to break include circles
The hash source files have circular include dependencies right now, which shows by our broken generic hash implementation. The "hash.h" header declares two functions and the `git_hash_ctx` typedef before actually including the hash backend header and can only declare the remaining hash functions after the include due to possibly static function declarations inside of the implementation includes. Let's break this cycle and help maintainability by creating a real implementation file for each of the hash implementations. Instead of relying on the exact include order, we now especially avoid the use of `GIT_INLINE` for function declarations.
This commit is contained in:
@@ -40,8 +40,10 @@ ELSEIF(SHA1_BACKEND STREQUAL "OpenSSL")
|
||||
ELSE()
|
||||
LIST(APPEND LIBGIT2_PC_REQUIRES "openssl")
|
||||
ENDIF()
|
||||
FILE(GLOB SRC_SHA1 hash/hash_openssl.c)
|
||||
ELSEIF(SHA1_BACKEND STREQUAL "CommonCrypto")
|
||||
SET(GIT_SHA1_COMMON_CRYPTO 1)
|
||||
FILE(GLOB SRC_SHA1 hash/hash_common_crypto.c)
|
||||
ELSEIF(SHA1_BACKEND STREQUAL "mbedTLS")
|
||||
SET(GIT_SHA1_MBEDTLS 1)
|
||||
FILE(GLOB SRC_SHA1 hash/hash_mbedtls.c)
|
||||
|
||||
14
src/hash.h
14
src/hash.h
@@ -13,8 +13,10 @@
|
||||
|
||||
typedef struct git_hash_ctx git_hash_ctx;
|
||||
|
||||
int git_hash_ctx_init(git_hash_ctx *ctx);
|
||||
void git_hash_ctx_cleanup(git_hash_ctx *ctx);
|
||||
typedef struct {
|
||||
void *data;
|
||||
size_t len;
|
||||
} git_buf_vec;
|
||||
|
||||
#if defined(GIT_SHA1_COLLISIONDETECT)
|
||||
# include "hash/hash_collisiondetect.h"
|
||||
@@ -30,10 +32,10 @@ void git_hash_ctx_cleanup(git_hash_ctx *ctx);
|
||||
# include "hash/hash_generic.h"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
size_t len;
|
||||
} git_buf_vec;
|
||||
int git_hash_global_init(void);
|
||||
|
||||
int git_hash_ctx_init(git_hash_ctx *ctx);
|
||||
void git_hash_ctx_cleanup(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);
|
||||
|
||||
48
src/hash/hash_collisiondetect.c
Normal file
48
src/hash/hash_collisiondetect.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* 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 "hash_collisiondetect.h"
|
||||
|
||||
int git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_ctx_init(git_hash_ctx *ctx)
|
||||
{
|
||||
return git_hash_init(ctx);
|
||||
}
|
||||
|
||||
void git_hash_ctx_cleanup(git_hash_ctx *ctx)
|
||||
{
|
||||
GIT_UNUSED(ctx);
|
||||
}
|
||||
|
||||
int git_hash_init(git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
SHA1DCInit(&ctx->c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
|
||||
{
|
||||
assert(ctx);
|
||||
SHA1DCUpdate(&ctx->c, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_final(git_oid *out, git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
if (SHA1DCFinal(out->id, &ctx->c)) {
|
||||
git_error_set(GIT_ERROR_SHA1, "SHA1 collision attack detected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -9,43 +9,11 @@
|
||||
#define INCLUDE_hash_hash_collisiondetect_h__
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#include "sha1dc/sha1.h"
|
||||
|
||||
struct git_hash_ctx {
|
||||
SHA1_CTX c;
|
||||
};
|
||||
|
||||
#define git_hash_ctx_init(ctx) git_hash_init(ctx)
|
||||
#define git_hash_ctx_cleanup(ctx)
|
||||
|
||||
GIT_INLINE(int) git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
SHA1DCInit(&ctx->c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
|
||||
{
|
||||
assert(ctx);
|
||||
SHA1DCUpdate(&ctx->c, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_hash_final(git_oid *out, git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
if (SHA1DCFinal(out->id, &ctx->c)) {
|
||||
git_error_set(GIT_ERROR_SHA1, "SHA1 collision attack detected");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
57
src/hash/hash_common_crypto.c
Normal file
57
src/hash/hash_common_crypto.c
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* 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 "hash_common_crypto.h"
|
||||
|
||||
#define CC_LONG_MAX ((CC_LONG)-1)
|
||||
|
||||
int git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_ctx_init(git_hash_ctx *ctx)
|
||||
{
|
||||
return git_hash_init(ctx);
|
||||
}
|
||||
|
||||
void git_hash_ctx_cleanup(git_hash_ctx *ctx)
|
||||
{
|
||||
GIT_UNUSED(ctx);
|
||||
}
|
||||
|
||||
int git_hash_init(git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
CC_SHA1_Init(&ctx->c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_update(git_hash_ctx *ctx, const void *_data, size_t len)
|
||||
{
|
||||
const unsigned char *data = _data;
|
||||
|
||||
assert(ctx);
|
||||
|
||||
while (len > 0) {
|
||||
CC_LONG chunk = (len > CC_LONG_MAX) ? CC_LONG_MAX : (CC_LONG)len;
|
||||
|
||||
CC_SHA1_Update(&ctx->c, data, chunk);
|
||||
|
||||
data += chunk;
|
||||
len -= chunk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_final(git_oid *out, git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
CC_SHA1_Final(out->id, &ctx->c);
|
||||
return 0;
|
||||
}
|
||||
@@ -16,46 +16,4 @@ struct git_hash_ctx {
|
||||
CC_SHA1_CTX c;
|
||||
};
|
||||
|
||||
#define CC_LONG_MAX ((CC_LONG)-1)
|
||||
|
||||
#define git_hash_ctx_init(ctx) git_hash_init(ctx)
|
||||
#define git_hash_ctx_cleanup(ctx)
|
||||
|
||||
GIT_INLINE(int) git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
CC_SHA1_Init(&ctx->c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *_data, size_t len)
|
||||
{
|
||||
const unsigned char *data = _data;
|
||||
|
||||
assert(ctx);
|
||||
|
||||
while (len > 0) {
|
||||
CC_LONG chunk = (len > CC_LONG_MAX) ? CC_LONG_MAX : (CC_LONG)len;
|
||||
|
||||
CC_SHA1_Update(&ctx->c, data, chunk);
|
||||
|
||||
data += chunk;
|
||||
len -= chunk;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_hash_final(git_oid *out, git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
CC_SHA1_Final(out->id, &ctx->c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
|
||||
#include "hash_generic.h"
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
|
||||
/*
|
||||
@@ -221,6 +219,21 @@ static void hash__block(git_hash_ctx *ctx, const unsigned int *data)
|
||||
ctx->H[4] += E;
|
||||
}
|
||||
|
||||
int git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_ctx_init(git_hash_ctx *ctx)
|
||||
{
|
||||
return git_hash_init(ctx);
|
||||
}
|
||||
|
||||
void git_hash_ctx_cleanup(git_hash_ctx *ctx)
|
||||
{
|
||||
GIT_UNUSED(ctx);
|
||||
}
|
||||
|
||||
int git_hash_init(git_hash_ctx *ctx)
|
||||
{
|
||||
ctx->size = 0;
|
||||
@@ -285,4 +298,3 @@ int git_hash_final(git_oid *out, git_hash_ctx *ctx)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#ifndef INCLUDE_hash_hash_generic_h__
|
||||
#define INCLUDE_hash_hash_generic_h__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
struct git_hash_ctx {
|
||||
@@ -18,12 +16,4 @@ struct git_hash_ctx {
|
||||
unsigned int W[16];
|
||||
};
|
||||
|
||||
#define git_hash_ctx_init(ctx) git_hash_init(ctx)
|
||||
#define git_hash_ctx_cleanup(ctx)
|
||||
|
||||
GIT_INLINE(int) git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,6 +9,16 @@
|
||||
#include "hash.h"
|
||||
#include "hash/hash_mbedtls.h"
|
||||
|
||||
int git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_ctx_init(git_hash_ctx *ctx)
|
||||
{
|
||||
return git_hash_init(ctx);
|
||||
}
|
||||
|
||||
void git_hash_ctx_cleanup(git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
|
||||
@@ -8,17 +8,12 @@
|
||||
#ifndef INCLUDE_hash_mbedtld_h__
|
||||
#define INCLUDE_hash_mbedtld_h__
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#include <mbedtls/sha1.h>
|
||||
|
||||
struct git_hash_ctx {
|
||||
mbedtls_sha1_context c;
|
||||
};
|
||||
|
||||
#define git_hash_ctx_init(ctx) git_hash_init(ctx)
|
||||
|
||||
GIT_INLINE(int) git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* INCLUDE_hash_mbedtld_h__ */
|
||||
|
||||
59
src/hash/hash_openssl.c
Normal file
59
src/hash/hash_openssl.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) the libgit2 contributors. All rights reserved.
|
||||
*
|
||||
* 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 "hash_openssl.h"
|
||||
|
||||
int git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_ctx_init(git_hash_ctx *ctx)
|
||||
{
|
||||
return git_hash_init(ctx);
|
||||
}
|
||||
|
||||
void git_hash_ctx_cleanup(git_hash_ctx *ctx)
|
||||
{
|
||||
GIT_UNUSED(ctx);
|
||||
}
|
||||
|
||||
int git_hash_init(git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
|
||||
if (SHA1_Init(&ctx->c) != 1) {
|
||||
git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to initialize hash context");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
|
||||
{
|
||||
assert(ctx);
|
||||
|
||||
if (SHA1_Update(&ctx->c, data, len) != 1) {
|
||||
git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to update hash");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_hash_final(git_oid *out, git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
|
||||
if (SHA1_Final(out->id, &ctx->c) != 1) {
|
||||
git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to finalize hash");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -8,6 +8,8 @@
|
||||
#ifndef INCLUDE_hash_hash_openssl_h__
|
||||
#define INCLUDE_hash_hash_openssl_h__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "hash.h"
|
||||
|
||||
#include <openssl/sha.h>
|
||||
@@ -16,48 +18,4 @@ struct git_hash_ctx {
|
||||
SHA_CTX c;
|
||||
};
|
||||
|
||||
#define git_hash_ctx_init(ctx) git_hash_init(ctx)
|
||||
#define git_hash_ctx_cleanup(ctx)
|
||||
|
||||
GIT_INLINE(int) git_hash_global_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_hash_init(git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
|
||||
if (SHA1_Init(&ctx->c) != 1) {
|
||||
git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to initialize hash context");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
|
||||
{
|
||||
assert(ctx);
|
||||
|
||||
if (SHA1_Update(&ctx->c, data, len) != 1) {
|
||||
git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to update hash");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GIT_INLINE(int) git_hash_final(git_oid *out, git_hash_ctx *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
|
||||
if (SHA1_Final(out->id, &ctx->c) != 1) {
|
||||
git_error_set(GIT_ERROR_SHA1, "hash_openssl: failed to finalize hash");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,11 +8,21 @@
|
||||
#include "hash_win32.h"
|
||||
|
||||
#include "global.h"
|
||||
#include "hash.h"
|
||||
|
||||
#include <wincrypt.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#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
|
||||
|
||||
static struct git_hash_prov hash_prov = {0};
|
||||
|
||||
/* Hash initialization */
|
||||
@@ -101,7 +111,7 @@ GIT_INLINE(void) hash_cryptoapi_prov_shutdown(void)
|
||||
hash_prov.type = INVALID;
|
||||
}
|
||||
|
||||
static void git_hash_global_shutdown(void)
|
||||
static void sha1_shutdown(void)
|
||||
{
|
||||
if (hash_prov.type == CNG)
|
||||
hash_cng_prov_shutdown();
|
||||
@@ -119,7 +129,7 @@ int git_hash_global_init(void)
|
||||
if ((error = hash_cng_prov_init()) < 0)
|
||||
error = hash_cryptoapi_prov_init();
|
||||
|
||||
git__on_shutdown(git_hash_global_shutdown);
|
||||
git__on_shutdown(sha1_shutdown);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -36,17 +36,6 @@ struct hash_cryptoapi_prov {
|
||||
* 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,
|
||||
@@ -138,6 +127,4 @@ struct git_hash_ctx {
|
||||
} ctx;
|
||||
};
|
||||
|
||||
extern int git_hash_global_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user