From: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> Date: Thu, 16 Mar 2017 13:08:38 -0700 Subject: [PATCH 2/2] Integrate the sha1dc code with the git build This adds the proper magic to actually build the sha1dc code as part of git when USE_SHA1DC is enabled. This includes - adjusting the sha1dc include directives for git use - adding the proper USE_SHA1DC logic to the Makefile - adding the SHA1DC case to the "hash.h" header - adding the proper "git platform" wrappers for the SHA1 interface Much of this comes from Jeff King's previous integration effort, with modifications for the new world order of hash.h. Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx> --- Makefile | 10 ++++++++++ hash.h | 2 ++ sha1dc/sha1.c | 33 +++++++++++++++++++++++++-------- sha1dc/sha1.h | 18 ++++++++++++++++-- sha1dc/ubc_check.c | 4 ++-- sha1dc/ubc_check.h | 2 -- 6 files changed, 55 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index a5a11e721..186ce17f2 100644 --- a/Makefile +++ b/Makefile @@ -140,6 +140,10 @@ all:: # Define PPC_SHA1 environment variable when running make to make use of # a bundled SHA1 routine optimized for PowerPC. # +# Define USE_SHA1DC to unconditionally enable the collision-detecting sha1 +# algorithm. This is slower, but may detect attempted collision attacks. +# Takes priority over other *_SHA1 knobs. +# # Define SHA1_MAX_BLOCK_SIZE to limit the amount of data that will be hashed # in one call to the platform's SHA1_Update(). e.g. APPLE_COMMON_CRYPTO # wants 'SHA1_MAX_BLOCK_SIZE=1024L*1024L*1024L' defined. @@ -1383,6 +1387,11 @@ ifdef APPLE_COMMON_CRYPTO SHA1_MAX_BLOCK_SIZE = 1024L*1024L*1024L endif +ifdef USE_SHA1DC + LIB_OBJS += sha1dc/sha1.o + LIB_OBJS += sha1dc/ubc_check.o + BASIC_CFLAGS += -DSHA1DC +else ifdef BLK_SHA1 LIB_OBJS += block-sha1/sha1.o BASIC_CFLAGS += -DSHA1_BLK @@ -1400,6 +1409,7 @@ else endif endif endif +endif ifdef SHA1_MAX_BLOCK_SIZE LIB_OBJS += compat/sha1-chunked.o diff --git a/hash.h b/hash.h index f0d9ddd0c..b9e7e34fc 100644 --- a/hash.h +++ b/hash.h @@ -3,6 +3,8 @@ #if defined(SHA1_PPC) #include "ppc/sha1.h" +#elif defined(SHA1DC) +#include "sha1dc/sha1.h" #elif defined(SHA1_APPLE) #include <CommonCrypto/CommonDigest.h> #elif defined(SHA1_OPENSSL) diff --git a/sha1dc/sha1.c b/sha1dc/sha1.c index 8d12b832b..76a8d1a85 100644 --- a/sha1dc/sha1.c +++ b/sha1dc/sha1.c @@ -5,14 +5,9 @@ * https://opensource.org/licenses/MIT ***/ -#include <string.h> -#include <memory.h> -#include <stdio.h> -#include <stdlib.h> - -#include "sha1.h" -#include "ubc_check.h" - +#include "git-compat-util.h" +#include "sha1dc/sha1.h" +#include "sha1dc/ubc_check.h" /* Because Little-Endian architectures are most common, @@ -1790,3 +1785,25 @@ int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx) output[19] = (unsigned char)(ctx->ihv[4]); return ctx->found_collision; } + +static const char collision_message[] = +"The SHA1 computation detected evidence of a collision attack;\n" +"refusing to process the contents."; + +void git_SHA1DCFinal(unsigned char hash[20], SHA1_CTX *ctx) +{ + if (SHA1DCFinal(hash, ctx)) + die(collision_message); +} + +void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *vdata, unsigned long len) +{ + const char *data = vdata; + /* We expect an unsigned long, but sha1dc only takes an int */ + while (len > INT_MAX) { + SHA1DCUpdate(ctx, data, INT_MAX); + data += INT_MAX; + len -= INT_MAX; + } + SHA1DCUpdate(ctx, data, len); +} diff --git a/sha1dc/sha1.h b/sha1dc/sha1.h index e867724c0..37ee415da 100644 --- a/sha1dc/sha1.h +++ b/sha1dc/sha1.h @@ -9,8 +9,6 @@ extern "C" { #endif -#include <stdint.h> - /* uses SHA-1 message expansion to expand the first 16 words of W[] to 80 words */ /* void sha1_message_expansion(uint32_t W[80]); */ @@ -100,6 +98,22 @@ void SHA1DCUpdate(SHA1_CTX*, const char*, size_t); /* returns: 0 = no collision detected, otherwise = collision found => warn user for active attack */ int SHA1DCFinal(unsigned char[20], SHA1_CTX*); + +/* + * Same as SHA1DCFinal, but convert collision attack case into a verbose die(). + */ +void git_SHA1DCFinal(unsigned char [20], SHA1_CTX *); + +/* + * Same as SHA1DCUpdate, but adjust types to match git's usual interface. + */ +void git_SHA1DCUpdate(SHA1_CTX *ctx, const void *data, unsigned long len); + +#define platform_SHA_CTX SHA1_CTX +#define platform_SHA1_Init SHA1DCInit +#define platform_SHA1_Update git_SHA1DCUpdate +#define platform_SHA1_Final git_SHA1DCFinal + #if defined(__cplusplus) } #endif diff --git a/sha1dc/ubc_check.c b/sha1dc/ubc_check.c index 27d0976da..089dd4743 100644 --- a/sha1dc/ubc_check.c +++ b/sha1dc/ubc_check.c @@ -24,8 +24,8 @@ // ubc_check has been verified against ubc_check_verify using the 'ubc_check_test' program in the tools section */ -#include <stdint.h> -#include "ubc_check.h" +#include "git-compat-util.h" +#include "sha1dc/ubc_check.h" static const uint32_t DV_I_43_0_bit = (uint32_t)(1) << 0; static const uint32_t DV_I_44_0_bit = (uint32_t)(1) << 1; diff --git a/sha1dc/ubc_check.h b/sha1dc/ubc_check.h index b349bed92..b64c306d7 100644 --- a/sha1dc/ubc_check.h +++ b/sha1dc/ubc_check.h @@ -27,8 +27,6 @@ extern "C" { #endif -#include <stdint.h> - #define DVMASKSIZE 1 typedef struct { int dvType; int dvK; int dvB; int testt; int maski; int maskb; uint32_t dm[80]; } dv_info_t; extern dv_info_t sha1_dvs[]; -- 2.12.0.434.g76f8c11c1