Commit 3a8801ae by Edward Thomson Committed by GitHub

Merge pull request #4258 from pks-t/pks/sha1dc-update

SHA1DC update
parents 3bc95cfe db1abffa
......@@ -296,6 +296,9 @@ ENDIF()
# Specify sha1 implementation
IF (USE_SHA1DC)
ADD_DEFINITIONS(-DGIT_SHA1_COLLISIONDETECT)
ADD_DEFINITIONS(-DSHA1DC_NO_STANDARD_INCLUDES=1)
ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_SHA1_C=\"common.h\")
ADD_DEFINITIONS(-DSHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C=\"common.h\")
FILE(GLOB SRC_SHA1 src/hash/hash_collisiondetect.c src/hash/sha1dc/*)
ELSEIF (WIN32 AND NOT MINGW)
ADD_DEFINITIONS(-DGIT_SHA1_WIN32)
......
......@@ -5,31 +5,75 @@
* https://opensource.org/licenses/MIT
***/
#ifndef SHA1DC_NO_STANDARD_INCLUDES
#include <string.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#endif
#ifdef SHA1DC_CUSTOM_INCLUDE_SHA1_C
#include SHA1DC_CUSTOM_INCLUDE_SHA1_C
#endif
#ifndef SHA1DC_INIT_SAFE_HASH_DEFAULT
#define SHA1DC_INIT_SAFE_HASH_DEFAULT 1
#endif
#include "sha1.h"
#include "ubc_check.h"
/*
/*
Because Little-Endian architectures are most common,
we only set BIGENDIAN if one of these conditions is met.
we only set SHA1DC_BIGENDIAN if one of these conditions is met.
Note that all MSFT platforms are little endian,
so none of these will be defined under the MSC compiler.
If you are compiling on a big endian platform and your compiler does not define one of these,
you will have to add whatever macros your tool chain defines to indicate Big-Endianness.
*/
#if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || \
(defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)) || \
defined(__BIG_ENDIAN__) || defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__)
#ifdef SHA1DC_BIGENDIAN
#undef SHA1DC_BIGENDIAN
#endif
#if (defined(_BYTE_ORDER) || defined(__BYTE_ORDER) || defined(__BYTE_ORDER__))
#if ((defined(_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN)) || \
(defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || \
(defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__)) )
#define SHA1DC_BIGENDIAN
#endif
#else
#if (defined(_BIG_ENDIAN) || defined(__BIG_ENDIAN) || defined(__BIG_ENDIAN__) || \
defined(__ARMEB__) || defined(__THUMBEB__) || defined(__AARCH64EB__) || \
defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || \
defined(__sparc))
#define SHA1DC_BIGENDIAN
#endif
#endif
#if (defined(SHA1DC_FORCE_LITTLEENDIAN) && defined(SHA1DC_BIGENDIAN))
#undef SHA1DC_BIGENDIAN
#endif
#if (defined(SHA1DC_FORCE_BIGENDIAN) && !defined(SHA1DC_BIGENDIAN))
#define SHA1DC_BIGENDIAN
#endif
/*ENDIANNESS SELECTION*/
#if (defined SHA1DC_FORCE_UNALIGNED_ACCESS || \
defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || \
defined(__i586__) || defined(__i686__) || defined(_M_IX86) || defined(__X86__) || \
defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__) || \
defined(__386) || defined(_M_X64) || defined(_M_AMD64))
#define SHA1DC_ALLOW_UNALIGNED_ACCESS
#define BIGENDIAN (1)
#endif /*UNALIGNMENT DETECTION*/
#endif /*ENDIANNESS SELECTION*/
#define rotate_right(x,n) (((x)>>(n))|((x)<<(32-(n))))
#define rotate_left(x,n) (((x)<<(n))|((x)>>(32-(n))))
......@@ -39,11 +83,11 @@
#define sha1_mix(W, t) (rotate_left(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1))
#if defined(BIGENDIAN)
#ifdef SHA1DC_BIGENDIAN
#define sha1_load(m, t, temp) { temp = m[t]; }
#else
#define sha1_load(m, t, temp) { temp = m[t]; sha1_bswap32(temp); }
#endif /*define(BIGENDIAN)*/
#endif
#define sha1_store(W, t, x) *(volatile uint32_t *)&W[t] = x
......@@ -872,6 +916,11 @@ static void sha1recompress_fast_ ## t (uint32_t ihvin[5], uint32_t ihvout[5], co
ihvout[0] = ihvin[0] + a; ihvout[1] = ihvin[1] + b; ihvout[2] = ihvin[2] + c; ihvout[3] = ihvin[3] + d; ihvout[4] = ihvin[4] + e; \
}
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4127) /* Complier complains about the checks in the above macro being constant. */
#endif
#ifdef DOSTORESTATE0
SHA1_RECOMPRESS(0)
#endif
......@@ -1192,6 +1241,10 @@ SHA1_RECOMPRESS(78)
SHA1_RECOMPRESS(79)
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
static void sha1_recompression_step(uint32_t step, uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5])
{
switch (step)
......@@ -1609,7 +1662,7 @@ static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
unsigned i, j;
uint32_t ubc_dv_mask[DVMASKSIZE] = { 0xFFFFFFFF };
uint32_t ihvtmp[5];
ctx->ihv1[0] = ctx->ihv[0];
ctx->ihv1[1] = ctx->ihv[1];
ctx->ihv1[2] = ctx->ihv[2];
......@@ -1665,7 +1718,7 @@ void SHA1DCInit(SHA1_CTX* ctx)
ctx->ihv[3] = 0x10325476;
ctx->ihv[4] = 0xC3D2E1F0;
ctx->found_collision = 0;
ctx->safe_hash = 1;
ctx->safe_hash = SHA1DC_INIT_SAFE_HASH_DEFAULT;
ctx->ubc_check = 1;
ctx->detect_coll = 1;
ctx->reduced_round_coll = 0;
......@@ -1713,6 +1766,7 @@ void SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback)
void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len)
{
unsigned left, fill;
if (len == 0)
return;
......@@ -1731,7 +1785,13 @@ void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len)
while (len >= 64)
{
ctx->total += 64;
#if defined(SHA1DC_ALLOW_UNALIGNED_ACCESS)
sha1_process(ctx, (uint32_t*)(buf));
#else
memcpy(ctx->buffer, buf, 64);
sha1_process(ctx, (uint32_t*)(ctx->buffer));
#endif /* defined(SHA1DC_ALLOW_UNALIGNED_ACCESS) */
buf += 64;
len -= 64;
}
......@@ -1790,3 +1850,7 @@ int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx)
output[19] = (unsigned char)(ctx->ihv[4]);
return ctx->found_collision;
}
#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C
#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_C
#endif
......@@ -5,42 +5,37 @@
* https://opensource.org/licenses/MIT
***/
#ifndef SHA1DC_SHA1_H
#define SHA1DC_SHA1_H
#if defined(__cplusplus)
extern "C" {
#endif
#ifndef SHA1DC_NO_STANDARD_INCLUDES
#include <stdint.h>
#endif
/* uses SHA-1 message expansion to expand the first 16 words of W[] to 80 words */
/* void sha1_message_expansion(uint32_t W[80]); */
/* sha-1 compression function; first version takes a message block pre-parsed as 16 32-bit integers, second version takes an already expanded message) */
/* void sha1_compression(uint32_t ihv[5], const uint32_t m[16]);
void sha1_compression_W(uint32_t ihv[5], const uint32_t W[80]); */
/* same as sha1_compression_W, but additionally store intermediate states */
/* sha-1 compression function that takes an already expanded message, and additionally store intermediate states */
/* only stores states ii (the state between step ii-1 and step ii) when DOSTORESTATEii is defined in ubc_check.h */
void sha1_compression_states(uint32_t[5], const uint32_t[16], uint32_t[80], uint32_t[80][5]);
/*
// function type for sha1_recompression_step_T (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5])
// where 0 <= T < 80
// me2 is an expanded message (the expansion of an original message block XOR'ed with a disturbance vector's message block difference)
// state is the internal state (a,b,c,d,e) before step T of the SHA-1 compression function while processing the original message block
// the function will return:
// ihvin: the reconstructed input chaining value
// ihvout: the reconstructed output chaining value
// Function type for sha1_recompression_step_T (uint32_t ihvin[5], uint32_t ihvout[5], const uint32_t me2[80], const uint32_t state[5]).
// Where 0 <= T < 80
// me2 is an expanded message (the expansion of an original message block XOR'ed with a disturbance vector's message block difference.)
// state is the internal state (a,b,c,d,e) before step T of the SHA-1 compression function while processing the original message block.
// The function will return:
// ihvin: The reconstructed input chaining value.
// ihvout: The reconstructed output chaining value.
*/
typedef void(*sha1_recompression_type)(uint32_t*, uint32_t*, const uint32_t*, const uint32_t*);
/* table of sha1_recompression_step_0, ... , sha1_recompression_step_79 */
/* extern sha1_recompression_type sha1_recompression_step[80];*/
/* a callback function type that can be set to be called when a collision block has been found: */
/* A callback function type that can be set to be called when a collision block has been found: */
/* void collision_block_callback(uint64_t byteoffset, const uint32_t ihvin1[5], const uint32_t ihvin2[5], const uint32_t m1[80], const uint32_t m2[80]) */
typedef void(*collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*);
/* the SHA-1 context */
/* The SHA-1 context. */
typedef struct {
uint64_t total;
uint32_t ihv[5];
......@@ -59,30 +54,34 @@ typedef struct {
uint32_t states[80][5];
} SHA1_CTX;
/* initialize SHA-1 context */
/* Initialize SHA-1 context. */
void SHA1DCInit(SHA1_CTX*);
/*
// function to enable safe SHA-1 hashing:
// collision attacks are thwarted by hashing a detected near-collision block 3 times
// think of it as extending SHA-1 from 80-steps to 240-steps for such blocks:
// the best collision attacks against SHA-1 have complexity about 2^60,
// thus for 240-steps an immediate lower-bound for the best cryptanalytic attacks would 2^180
// an attacker would be better off using a generic birthday search of complexity 2^80
//
// enabling safe SHA-1 hashing will result in the correct SHA-1 hash for messages where no collision attack was detected
// but it will result in a different SHA-1 hash for messages where a collision attack was detected
// this will automatically invalidate SHA-1 based digital signature forgeries
// enabled by default
Function to enable safe SHA-1 hashing:
Collision attacks are thwarted by hashing a detected near-collision block 3 times.
Think of it as extending SHA-1 from 80-steps to 240-steps for such blocks:
The best collision attacks against SHA-1 have complexity about 2^60,
thus for 240-steps an immediate lower-bound for the best cryptanalytic attacks would be 2^180.
An attacker would be better off using a generic birthday search of complexity 2^80.
Enabling safe SHA-1 hashing will result in the correct SHA-1 hash for messages where no collision attack was detected,
but it will result in a different SHA-1 hash for messages where a collision attack was detected.
This will automatically invalidate SHA-1 based digital signature forgeries.
Enabled by default.
*/
void SHA1DCSetSafeHash(SHA1_CTX*, int);
/* function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up) */
/* enabled by default */
/*
Function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up).
Enabled by default
*/
void SHA1DCSetUseUBC(SHA1_CTX*, int);
/* function to disable or enable the use of Collision Detection */
/* enabled by default */
/*
Function to disable or enable the use of Collision Detection.
Enabled by default.
*/
void SHA1DCSetUseDetectColl(SHA1_CTX*, int);
/* function to disable or enable the detection of reduced-round SHA-1 collisions */
......@@ -98,8 +97,14 @@ void SHA1DCUpdate(SHA1_CTX*, const char*, size_t);
/* obtain SHA-1 hash from SHA-1 context */
/* returns: 0 = no collision detected, otherwise = collision found => warn user for active attack */
int SHA1DCFinal(unsigned char[20], SHA1_CTX*);
int SHA1DCFinal(unsigned char[20], SHA1_CTX*);
#if defined(__cplusplus)
}
#endif
#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H
#include SHA1DC_CUSTOM_TRAILING_INCLUDE_SHA1_H
#endif
#endif
......@@ -24,7 +24,12 @@
// ubc_check has been verified against ubc_check_verify using the 'ubc_check_test' program in the tools section
*/
#ifndef SHA1DC_NO_STANDARD_INCLUDES
#include <stdint.h>
#endif
#ifdef SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C
#include SHA1DC_CUSTOM_INCLUDE_UBC_CHECK_C
#endif
#include "ubc_check.h"
static const uint32_t DV_I_43_0_bit = (uint32_t)(1) << 0;
......@@ -361,3 +366,7 @@ if (mask) {
dvmask[0]=mask;
}
#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C
#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_C
#endif
......@@ -20,14 +20,16 @@
// thus one needs to do the recompression check for each DV that has its bit set
*/
#ifndef UBC_CHECK_H
#define UBC_CHECK_H
#ifndef SHA1DC_UBC_CHECK_H
#define SHA1DC_UBC_CHECK_H
#if defined(__cplusplus)
extern "C" {
#endif
#ifndef SHA1DC_NO_STANDARD_INCLUDES
#include <stdint.h>
#endif
#define DVMASKSIZE 1
typedef struct { int dvType; int dvK; int dvB; int testt; int maski; int maskb; uint32_t dm[80]; } dv_info_t;
......@@ -43,4 +45,8 @@ void ubc_check(const uint32_t W[80], uint32_t dvmask[DVMASKSIZE]);
}
#endif
#endif /* UBC_CHECK_H */
#ifdef SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H
#include SHA1DC_CUSTOM_TRAILING_INCLUDE_UBC_CHECK_H
#endif
#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