Commit bd48bf3f by Patrick Steinhardt

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.
parent bbf034ab
......@@ -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)
......
......@@ -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);
......
/*
* 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
/*
* 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__ */
/*
* 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment