Commit b900981c by Edward Thomson

sha: add sha256 algorithm

Add support for a SHA256 hash algorithm, and add the "builtin" SHA256
hash engine (from RFC 6234).
parent 36df49c2
...@@ -30,6 +30,7 @@ option(USE_NSEC "Support nanosecond precision file mtimes and cti ...@@ -30,6 +30,7 @@ option(USE_NSEC "Support nanosecond precision file mtimes and cti
option(USE_SSH "Link with libssh2 to enable SSH support" OFF) option(USE_SSH "Link with libssh2 to enable SSH support" OFF)
option(USE_HTTPS "Enable HTTPS support. Can be set to a specific backend" ON) option(USE_HTTPS "Enable HTTPS support. Can be set to a specific backend" ON)
option(USE_SHA1 "Enable SHA1. Can be set to CollisionDetection(ON)/HTTPS" ON) option(USE_SHA1 "Enable SHA1. Can be set to CollisionDetection(ON)/HTTPS" ON)
option(USE_SHA256 "Enable SHA256." ON)
option(USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF) option(USE_GSSAPI "Link with libgssapi for SPNEGO auth" OFF)
set(USE_HTTP_PARSER "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.") set(USE_HTTP_PARSER "" CACHE STRING "Specifies the HTTP Parser implementation; either system or builtin.")
set(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.") set(REGEX_BACKEND "" CACHE STRING "Regular expression implementation. One of regcomp_l, pcre2, pcre, regcomp, or builtin.")
......
...@@ -1144,3 +1144,43 @@ worldwide. This software is distributed without any warranty. ...@@ -1144,3 +1144,43 @@ worldwide. This software is distributed without any warranty.
See <http://creativecommons.org/publicdomain/zero/1.0/>. See <http://creativecommons.org/publicdomain/zero/1.0/>.
----------------------------------------------------------------------
The built-in SHA256 support (src/hash/rfc6234) is taken from RFC 6234
under the following license:
Copyright (c) 2011 IETF Trust and the persons identified as
authors of the code. All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions are met:
- Redistributions of source code must retain the above
copyright notice, this list of conditions and
the following disclaimer.
- Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
- Neither the name of Internet Society, IETF or IETF Trust, nor
the names of specific contributors, may be used to endorse or
promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
...@@ -4,6 +4,7 @@ include(SanitizeBool) ...@@ -4,6 +4,7 @@ include(SanitizeBool)
# USE_SHA1=CollisionDetection(ON)/HTTPS/Generic/OFF # USE_SHA1=CollisionDetection(ON)/HTTPS/Generic/OFF
sanitizebool(USE_SHA1) sanitizebool(USE_SHA1)
sanitizebool(USE_SHA256)
if(USE_SHA1 STREQUAL ON) if(USE_SHA1 STREQUAL ON)
SET(USE_SHA1 "CollisionDetection") SET(USE_SHA1 "CollisionDetection")
...@@ -46,4 +47,15 @@ else() ...@@ -46,4 +47,15 @@ else()
message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}") message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
endif() endif()
add_feature_info(SHA ON "using ${USE_SHA1}") if(USE_SHA256 STREQUAL ON)
SET(USE_SHA256 "Builtin")
endif()
if(USE_SHA256 STREQUAL "Builtin")
set(GIT_SHA256_BUILTIN 1)
else()
message(FATAL_ERROR "Asked for unknown SHA256 backend: ${USE_SHA256}")
endif()
add_feature_info(SHA1 ON "using ${USE_SHA1}")
add_feature_info(SHA256 ON "using ${USE_SHA256}")
...@@ -48,6 +48,8 @@ ...@@ -48,6 +48,8 @@
#cmakedefine GIT_SHA1_OPENSSL 1 #cmakedefine GIT_SHA1_OPENSSL 1
#cmakedefine GIT_SHA1_MBEDTLS 1 #cmakedefine GIT_SHA1_MBEDTLS 1
#cmakedefine GIT_SHA256_BUILTIN 1
#cmakedefine GIT_RAND_GETENTROPY 1 #cmakedefine GIT_RAND_GETENTROPY 1
#endif #endif
...@@ -29,29 +29,32 @@ endif() ...@@ -29,29 +29,32 @@ endif()
# #
if(USE_SHA1 STREQUAL "CollisionDetection") if(USE_SHA1 STREQUAL "CollisionDetection")
file(GLOB UTIL_SRC_HASH hash/collisiondetect.* hash/sha1dc/*) file(GLOB UTIL_SRC_SHA1 hash/collisiondetect.* hash/sha1dc/*)
target_compile_definitions(util PRIVATE SHA1DC_NO_STANDARD_INCLUDES=1) target_compile_definitions(util PRIVATE SHA1DC_NO_STANDARD_INCLUDES=1)
target_compile_definitions(util PRIVATE SHA1DC_CUSTOM_INCLUDE_SHA1_C=\"git2_util.h\") target_compile_definitions(util PRIVATE SHA1DC_CUSTOM_INCLUDE_SHA1_C=\"git2_util.h\")
target_compile_definitions(util PRIVATE SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"git2_util.h\") target_compile_definitions(util PRIVATE SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"git2_util.h\")
elseif(USE_SHA1 STREQUAL "OpenSSL") elseif(USE_SHA1 STREQUAL "OpenSSL")
file(GLOB UTIL_SRC_HASH hash/openssl.*) file(GLOB UTIL_SRC_SHA1 hash/openssl.*)
elseif(USE_SHA1 STREQUAL "CommonCrypto") elseif(USE_SHA1 STREQUAL "CommonCrypto")
file(GLOB UTIL_SRC_HASH hash/common_crypto.*) file(GLOB UTIL_SRC_SHA1 hash/common_crypto.*)
elseif(USE_SHA1 STREQUAL "mbedTLS") elseif(USE_SHA1 STREQUAL "mbedTLS")
file(GLOB UTIL_SRC_HASH hash/mbedtls.*) file(GLOB UTIL_SRC_SHA1 hash/mbedtls.*)
elseif(USE_SHA1 STREQUAL "Win32") elseif(USE_SHA1 STREQUAL "Win32")
file(GLOB UTIL_SRC_HASH hash/win32.*) file(GLOB UTIL_SRC_SHA1 hash/win32.*)
else() else()
message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}") message(FATAL_ERROR "Asked for unknown SHA1 backend: ${USE_SHA1}")
endif() endif()
list(SORT UTIL_SRC_HASH) list(SORT UTIL_SRC_SHA1)
file(GLOB UTIL_SRC_SHA256 hash/builtin.* hash/rfc6234/*)
list(SORT UTIL_SRC_SHA256)
# #
# Build the library # Build the library
# #
target_sources(util PRIVATE ${UTIL_SRC} ${UTIL_SRC_OS} ${UTIL_SRC_HASH}) target_sources(util PRIVATE ${UTIL_SRC} ${UTIL_SRC_OS} ${UTIL_SRC_SHA1} ${UTIL_SRC_SHA256})
ide_split_sources(util) ide_split_sources(util)
target_include_directories(util PRIVATE ${UTIL_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES} PUBLIC ${libgit2_SOURCE_DIR}/include) target_include_directories(util PRIVATE ${UTIL_INCLUDES} ${LIBGIT2_DEPENDENCY_INCLUDES} PUBLIC ${libgit2_SOURCE_DIR}/include)
......
...@@ -9,7 +9,11 @@ ...@@ -9,7 +9,11 @@
int git_hash_global_init(void) int git_hash_global_init(void)
{ {
return git_hash_sha1_global_init(); if (git_hash_sha1_global_init() < 0 ||
git_hash_sha256_global_init() < 0)
return -1;
return 0;
} }
int git_hash_ctx_init(git_hash_ctx *ctx, git_hash_algorithm_t algorithm) int git_hash_ctx_init(git_hash_ctx *ctx, git_hash_algorithm_t algorithm)
...@@ -20,6 +24,9 @@ int git_hash_ctx_init(git_hash_ctx *ctx, git_hash_algorithm_t algorithm) ...@@ -20,6 +24,9 @@ int git_hash_ctx_init(git_hash_ctx *ctx, git_hash_algorithm_t algorithm)
case GIT_HASH_ALGORITHM_SHA1: case GIT_HASH_ALGORITHM_SHA1:
error = git_hash_sha1_ctx_init(&ctx->ctx.sha1); error = git_hash_sha1_ctx_init(&ctx->ctx.sha1);
break; break;
case GIT_HASH_ALGORITHM_SHA256:
error = git_hash_sha256_ctx_init(&ctx->ctx.sha256);
break;
default: default:
git_error_set(GIT_ERROR_INTERNAL, "unknown hash algorithm"); git_error_set(GIT_ERROR_INTERNAL, "unknown hash algorithm");
error = -1; error = -1;
...@@ -35,6 +42,9 @@ void git_hash_ctx_cleanup(git_hash_ctx *ctx) ...@@ -35,6 +42,9 @@ void git_hash_ctx_cleanup(git_hash_ctx *ctx)
case GIT_HASH_ALGORITHM_SHA1: case GIT_HASH_ALGORITHM_SHA1:
git_hash_sha1_ctx_cleanup(&ctx->ctx.sha1); git_hash_sha1_ctx_cleanup(&ctx->ctx.sha1);
return; return;
case GIT_HASH_ALGORITHM_SHA256:
git_hash_sha256_ctx_cleanup(&ctx->ctx.sha256);
return;
default: default:
/* unreachable */ ; /* unreachable */ ;
} }
...@@ -45,6 +55,8 @@ int git_hash_init(git_hash_ctx *ctx) ...@@ -45,6 +55,8 @@ int git_hash_init(git_hash_ctx *ctx)
switch (ctx->algorithm) { switch (ctx->algorithm) {
case GIT_HASH_ALGORITHM_SHA1: case GIT_HASH_ALGORITHM_SHA1:
return git_hash_sha1_init(&ctx->ctx.sha1); return git_hash_sha1_init(&ctx->ctx.sha1);
case GIT_HASH_ALGORITHM_SHA256:
return git_hash_sha256_init(&ctx->ctx.sha256);
default: default:
/* unreachable */ ; /* unreachable */ ;
} }
...@@ -58,6 +70,8 @@ int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len) ...@@ -58,6 +70,8 @@ int git_hash_update(git_hash_ctx *ctx, const void *data, size_t len)
switch (ctx->algorithm) { switch (ctx->algorithm) {
case GIT_HASH_ALGORITHM_SHA1: case GIT_HASH_ALGORITHM_SHA1:
return git_hash_sha1_update(&ctx->ctx.sha1, data, len); return git_hash_sha1_update(&ctx->ctx.sha1, data, len);
case GIT_HASH_ALGORITHM_SHA256:
return git_hash_sha256_update(&ctx->ctx.sha256, data, len);
default: default:
/* unreachable */ ; /* unreachable */ ;
} }
...@@ -71,6 +85,8 @@ int git_hash_final(unsigned char *out, git_hash_ctx *ctx) ...@@ -71,6 +85,8 @@ int git_hash_final(unsigned char *out, git_hash_ctx *ctx)
switch (ctx->algorithm) { switch (ctx->algorithm) {
case GIT_HASH_ALGORITHM_SHA1: case GIT_HASH_ALGORITHM_SHA1:
return git_hash_sha1_final(out, &ctx->ctx.sha1); return git_hash_sha1_final(out, &ctx->ctx.sha1);
case GIT_HASH_ALGORITHM_SHA256:
return git_hash_sha256_final(out, &ctx->ctx.sha256);
default: default:
/* unreachable */ ; /* unreachable */ ;
} }
......
...@@ -19,12 +19,14 @@ typedef struct { ...@@ -19,12 +19,14 @@ typedef struct {
typedef enum { typedef enum {
GIT_HASH_ALGORITHM_NONE = 0, GIT_HASH_ALGORITHM_NONE = 0,
GIT_HASH_ALGORITHM_SHA1 GIT_HASH_ALGORITHM_SHA1,
GIT_HASH_ALGORITHM_SHA256
} git_hash_algorithm_t; } git_hash_algorithm_t;
typedef struct git_hash_ctx { typedef struct git_hash_ctx {
union { union {
git_hash_sha1_ctx sha1; git_hash_sha1_ctx sha1;
git_hash_sha256_ctx sha256;
} ctx; } ctx;
git_hash_algorithm_t algorithm; git_hash_algorithm_t algorithm;
} git_hash_ctx; } git_hash_ctx;
......
/*
* 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 "builtin.h"
int git_hash_sha256_global_init(void)
{
return 0;
}
int git_hash_sha256_ctx_init(git_hash_sha256_ctx *ctx)
{
return git_hash_sha256_init(ctx);
}
void git_hash_sha256_ctx_cleanup(git_hash_sha256_ctx *ctx)
{
GIT_UNUSED(ctx);
}
int git_hash_sha256_init(git_hash_sha256_ctx *ctx)
{
GIT_ASSERT_ARG(ctx);
if (SHA256Reset(&ctx->c)) {
git_error_set(GIT_ERROR_SHA, "SHA256 error");
return -1;
}
return 0;
}
int git_hash_sha256_update(git_hash_sha256_ctx *ctx, const void *data, size_t len)
{
GIT_ASSERT_ARG(ctx);
if (SHA256Input(&ctx->c, data, len)) {
git_error_set(GIT_ERROR_SHA, "SHA256 error");
return -1;
}
return 0;
}
int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *ctx)
{
GIT_ASSERT_ARG(ctx);
if (SHA256Result(&ctx->c, out)) {
git_error_set(GIT_ERROR_SHA, "SHA256 error");
return -1;
}
return 0;
}
/*
* 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.
*/
#ifndef INCLUDE_hash_builtin_h__
#define INCLUDE_hash_builtin_h__
#include "hash/sha.h"
#include "rfc6234/sha.h"
struct git_hash_sha256_ctx {
SHA256Context c;
};
#endif
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "git2_util.h" #include "git2_util.h"
typedef struct git_hash_sha1_ctx git_hash_sha1_ctx; typedef struct git_hash_sha1_ctx git_hash_sha1_ctx;
typedef struct git_hash_sha256_ctx git_hash_sha256_ctx;
#if defined(GIT_SHA1_COMMON_CRYPTO) #if defined(GIT_SHA1_COMMON_CRYPTO)
# include "common_crypto.h" # include "common_crypto.h"
...@@ -26,6 +27,16 @@ typedef struct git_hash_sha1_ctx git_hash_sha1_ctx; ...@@ -26,6 +27,16 @@ typedef struct git_hash_sha1_ctx git_hash_sha1_ctx;
# error "unknown sha1 implementation" # error "unknown sha1 implementation"
#endif #endif
#if defined(GIT_SHA256_BUILTIN)
# include "builtin.h"
#else
# error "unknown sha256 implementation"
#endif
/*
* SHA1
*/
#define GIT_HASH_SHA1_SIZE 20 #define GIT_HASH_SHA1_SIZE 20
int git_hash_sha1_global_init(void); int git_hash_sha1_global_init(void);
...@@ -37,4 +48,19 @@ int git_hash_sha1_init(git_hash_sha1_ctx *c); ...@@ -37,4 +48,19 @@ int git_hash_sha1_init(git_hash_sha1_ctx *c);
int git_hash_sha1_update(git_hash_sha1_ctx *c, const void *data, size_t len); int git_hash_sha1_update(git_hash_sha1_ctx *c, const void *data, size_t len);
int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *c); int git_hash_sha1_final(unsigned char *out, git_hash_sha1_ctx *c);
/*
* SHA256
*/
#define GIT_HASH_SHA256_SIZE 32
int git_hash_sha256_global_init(void);
int git_hash_sha256_ctx_init(git_hash_sha256_ctx *ctx);
void git_hash_sha256_ctx_cleanup(git_hash_sha256_ctx *ctx);
int git_hash_sha256_init(git_hash_sha256_ctx *c);
int git_hash_sha256_update(git_hash_sha256_ctx *c, const void *data, size_t len);
int git_hash_sha256_final(unsigned char *out, git_hash_sha256_ctx *c);
#endif #endif
#include "clar_libgit2.h"
#include "hash.h"
#define FIXTURE_DIR "sha1"
void test_core_sha256__initialize(void)
{
cl_fixture_sandbox(FIXTURE_DIR);
}
void test_core_sha256__cleanup(void)
{
cl_fixture_cleanup(FIXTURE_DIR);
}
static int sha256_file(unsigned char *out, const char *filename)
{
git_hash_ctx ctx;
char buf[2048];
int fd, ret;
ssize_t read_len;
fd = p_open(filename, O_RDONLY);
cl_assert(fd >= 0);
cl_git_pass(git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA256));
while ((read_len = p_read(fd, buf, 2048)) > 0)
cl_git_pass(git_hash_update(&ctx, buf, (size_t)read_len));
cl_assert_equal_i(0, read_len);
p_close(fd);
ret = git_hash_final(out, &ctx);
git_hash_ctx_cleanup(&ctx);
return ret;
}
void test_core_sha256__empty(void)
{
unsigned char expected[GIT_HASH_SHA256_SIZE] = {
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
};
unsigned char actual[GIT_HASH_SHA256_SIZE];
cl_git_pass(sha256_file(actual, FIXTURE_DIR "/empty"));
cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA256_SIZE));
}
void test_core_sha256__hello(void)
{
unsigned char expected[GIT_HASH_SHA256_SIZE] = {
0xaa, 0x32, 0x7f, 0xae, 0x5c, 0x91, 0x58, 0x3a,
0x4f, 0xb6, 0x54, 0xcc, 0xb6, 0xc2, 0xb1, 0x0c,
0x77, 0xd7, 0x49, 0xc9, 0x91, 0x2a, 0x8d, 0x6b,
0x47, 0x26, 0x13, 0xc0, 0xa0, 0x4b, 0x4d, 0xad
};
unsigned char actual[GIT_HASH_SHA256_SIZE];
cl_git_pass(sha256_file(actual, FIXTURE_DIR "/hello_c"));
cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA256_SIZE));
}
void test_core_sha256__pdf(void)
{
unsigned char expected[GIT_HASH_SHA256_SIZE] = {
0x2b, 0xb7, 0x87, 0xa7, 0x3e, 0x37, 0x35, 0x2f,
0x92, 0x38, 0x3a, 0xbe, 0x7e, 0x29, 0x02, 0x93,
0x6d, 0x10, 0x59, 0xad, 0x9f, 0x1b, 0xa6, 0xda,
0xaa, 0x9c, 0x1e, 0x58, 0xee, 0x69, 0x70, 0xd0
};
unsigned char actual[GIT_HASH_SHA256_SIZE];
cl_git_pass(sha256_file(actual, FIXTURE_DIR "/shattered-1.pdf"));
cl_assert_equal_i(0, memcmp(expected, actual, GIT_HASH_SHA256_SIZE));
}
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