Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Declare entry points as __cdecl; Add callback param; Allow multiple calls to SHA1DCFinal() #25

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 75 additions & 44 deletions lib/sha1.c
Original file line number Diff line number Diff line change
Expand Up @@ -1646,6 +1646,15 @@ static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
{
ctx->found_collision = 1;

if (ctx->callback != NULL)
{
#ifdef SHA1DC_CALLBACK_USES_PARAM
ctx->callback(ctx->callback_param, ctx->total - 64, ctx->ihv1, ctx->ihv2, ctx->m1, ctx->m2);
#else
ctx->callback(ctx->total - 64, ctx->ihv1, ctx->ihv2, ctx->m1, ctx->m2);
#endif
}

if (ctx->safe_hash)
{
sha1_compression_W(ctx->ihv, ctx->m1);
Expand All @@ -1660,7 +1669,7 @@ static void sha1_process(SHA1_CTX* ctx, const uint32_t block[16])
}
}

void SHA1DCInit(SHA1_CTX* ctx)
void SHA1DC_API SHA1DCInit(SHA1_CTX* ctx)
{
ctx->total = 0;
ctx->ihv[0] = 0x67452301;
Expand All @@ -1674,9 +1683,12 @@ void SHA1DCInit(SHA1_CTX* ctx)
ctx->detect_coll = 1;
ctx->reduced_round_coll = 0;
ctx->callback = NULL;
#ifdef SHA1DC_CALLBACK_USES_PARAM
ctx->callback_param = NULL;
#endif
}

void SHA1DCSetSafeHash(SHA1_CTX* ctx, int safehash)
void SHA1DC_API SHA1DCSetSafeHash(SHA1_CTX* ctx, int safehash)
{
if (safehash)
ctx->safe_hash = 1;
Expand All @@ -1685,36 +1697,48 @@ void SHA1DCSetSafeHash(SHA1_CTX* ctx, int safehash)
}


void SHA1DCSetUseUBC(SHA1_CTX* ctx, int ubc_check)
void SHA1DC_API SHA1DCSetUseUBC(SHA1_CTX* ctx, int ubc_check)
{
if (ubc_check)
ctx->ubc_check = 1;
else
ctx->ubc_check = 0;
}

void SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll)
void SHA1DC_API SHA1DCSetUseDetectColl(SHA1_CTX* ctx, int detect_coll)
{
if (detect_coll)
ctx->detect_coll = 1;
else
ctx->detect_coll = 0;
}

void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX* ctx, int reduced_round_coll)
void SHA1DC_API SHA1DCSetDetectReducedRoundCollision(SHA1_CTX* ctx, int reduced_round_coll)
{
if (reduced_round_coll)
ctx->reduced_round_coll = 1;
else
ctx->reduced_round_coll = 0;
}

void SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback)
{
ctx->callback = callback;
}
#ifdef SHA1DC_CALLBACK_USES_PARAM

void SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len)
void SHA1DC_API SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback, void* param)
{
ctx->callback = callback;
ctx->callback_param = param;
}

#else

void SHA1DC_API SHA1DCSetCallback(SHA1_CTX* ctx, collision_block_callback callback)
{
ctx->callback = callback;
}

#endif

void SHA1DC_API SHA1DCUpdate(SHA1_CTX* ctx, const char* buf, size_t len)
{
unsigned left, fill;
if (len == 0)
Expand Down Expand Up @@ -1754,43 +1778,50 @@ static const unsigned char sha1_padding[64] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

int SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx)
int SHA1DC_API SHA1DCFinal(unsigned char output[20], SHA1_CTX *ctx)
{
uint32_t last = ctx->total & 63;
SHA1_CTX context = *ctx; // Make a copy

uint32_t last = context.total & 63;
uint32_t padn = (last < 56) ? (56 - last) : (120 - last);
uint64_t total;
SHA1DCUpdate(ctx, (const char*)(sha1_padding), padn);

total = ctx->total - padn;
SHA1DCUpdate(&context, (const char*)(sha1_padding), padn);

total = context.total - padn;
total <<= 3;
ctx->buffer[56] = (unsigned char)(total >> 56);
ctx->buffer[57] = (unsigned char)(total >> 48);
ctx->buffer[58] = (unsigned char)(total >> 40);
ctx->buffer[59] = (unsigned char)(total >> 32);
ctx->buffer[60] = (unsigned char)(total >> 24);
ctx->buffer[61] = (unsigned char)(total >> 16);
ctx->buffer[62] = (unsigned char)(total >> 8);
ctx->buffer[63] = (unsigned char)(total);
sha1_process(ctx, (uint32_t*)(ctx->buffer));
output[0] = (unsigned char)(ctx->ihv[0] >> 24);
output[1] = (unsigned char)(ctx->ihv[0] >> 16);
output[2] = (unsigned char)(ctx->ihv[0] >> 8);
output[3] = (unsigned char)(ctx->ihv[0]);
output[4] = (unsigned char)(ctx->ihv[1] >> 24);
output[5] = (unsigned char)(ctx->ihv[1] >> 16);
output[6] = (unsigned char)(ctx->ihv[1] >> 8);
output[7] = (unsigned char)(ctx->ihv[1]);
output[8] = (unsigned char)(ctx->ihv[2] >> 24);
output[9] = (unsigned char)(ctx->ihv[2] >> 16);
output[10] = (unsigned char)(ctx->ihv[2] >> 8);
output[11] = (unsigned char)(ctx->ihv[2]);
output[12] = (unsigned char)(ctx->ihv[3] >> 24);
output[13] = (unsigned char)(ctx->ihv[3] >> 16);
output[14] = (unsigned char)(ctx->ihv[3] >> 8);
output[15] = (unsigned char)(ctx->ihv[3]);
output[16] = (unsigned char)(ctx->ihv[4] >> 24);
output[17] = (unsigned char)(ctx->ihv[4] >> 16);
output[18] = (unsigned char)(ctx->ihv[4] >> 8);
output[19] = (unsigned char)(ctx->ihv[4]);
return ctx->found_collision;

context.buffer[56] = (unsigned char)(total >> 56);
context.buffer[57] = (unsigned char)(total >> 48);
context.buffer[58] = (unsigned char)(total >> 40);
context.buffer[59] = (unsigned char)(total >> 32);
context.buffer[60] = (unsigned char)(total >> 24);
context.buffer[61] = (unsigned char)(total >> 16);
context.buffer[62] = (unsigned char)(total >> 8);
context.buffer[63] = (unsigned char)(total);

sha1_process(&context, (uint32_t*)(context.buffer));

output[0] = (unsigned char)(context.ihv[0] >> 24);
output[1] = (unsigned char)(context.ihv[0] >> 16);
output[2] = (unsigned char)(context.ihv[0] >> 8);
output[3] = (unsigned char)(context.ihv[0]);
output[4] = (unsigned char)(context.ihv[1] >> 24);
output[5] = (unsigned char)(context.ihv[1] >> 16);
output[6] = (unsigned char)(context.ihv[1] >> 8);
output[7] = (unsigned char)(context.ihv[1]);
output[8] = (unsigned char)(context.ihv[2] >> 24);
output[9] = (unsigned char)(context.ihv[2] >> 16);
output[10] = (unsigned char)(context.ihv[2] >> 8);
output[11] = (unsigned char)(context.ihv[2]);
output[12] = (unsigned char)(context.ihv[3] >> 24);
output[13] = (unsigned char)(context.ihv[3] >> 16);
output[14] = (unsigned char)(context.ihv[3] >> 8);
output[15] = (unsigned char)(context.ihv[3]);
output[16] = (unsigned char)(context.ihv[4] >> 24);
output[17] = (unsigned char)(context.ihv[4] >> 16);
output[18] = (unsigned char)(context.ihv[4] >> 8);
output[19] = (unsigned char)(context.ihv[4]);

return context.found_collision;
}
45 changes: 34 additions & 11 deletions lib/sha1.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@
#ifndef SHA1DC_SHA1_H
#define SHA1DC_SHA1_H

#ifdef _MSC_VER
#define SHA1DC_API __cdecl
#else
#define SHA1DC_API
#endif

#if defined(__cplusplus)
extern "C" {
#endif
Expand Down Expand Up @@ -40,8 +46,18 @@ typedef void(*sha1_recompression_type)(uint32_t*, uint32_t*, const uint32_t*, co
/* 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: */
/* 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*);

#ifdef SHA1DC_CALLBACK_USES_PARAM

// void collision_block_callback(void* param, 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(SHA1DC_API * collision_block_callback)(void* param, uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*);

#else

// 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(SHA1DC_API * collision_block_callback)(uint64_t, const uint32_t*, const uint32_t*, const uint32_t*, const uint32_t*);

#endif

/* the SHA-1 context */
typedef struct {
Expand All @@ -54,7 +70,9 @@ typedef struct {
int ubc_check;
int reduced_round_coll;
collision_block_callback callback;

#ifdef SHA1DC_CALLBACK_USES_PARAM
void* callback_param;
#endif
uint32_t ihv1[5];
uint32_t ihv2[5];
uint32_t m1[80];
Expand All @@ -63,7 +81,7 @@ typedef struct {
} SHA1_CTX;

/* initialize SHA-1 context */
void SHA1DCInit(SHA1_CTX*);
void SHA1DC_API SHA1DCInit(SHA1_CTX*);

/*
// function to enable safe SHA-1 hashing:
Expand All @@ -78,30 +96,35 @@ void SHA1DCInit(SHA1_CTX*);
// this will automatically invalidate SHA-1 based digital signature forgeries
// enabled by default
*/
void SHA1DCSetSafeHash(SHA1_CTX*, int);
void SHA1DC_API SHA1DCSetSafeHash(SHA1_CTX*, int);

/* function to disable or enable the use of Unavoidable Bitconditions (provides a significant speed up) */
/* enabled by default */
void SHA1DCSetUseUBC(SHA1_CTX*, int);
void SHA1DC_API SHA1DCSetUseUBC(SHA1_CTX*, int);

/* function to disable or enable the use of Collision Detection */
/* enabled by default */
void SHA1DCSetUseDetectColl(SHA1_CTX*, int);
void SHA1DC_API SHA1DCSetUseDetectColl(SHA1_CTX*, int);

/* function to disable or enable the detection of reduced-round SHA-1 collisions */
/* disabled by default */
void SHA1DCSetDetectReducedRoundCollision(SHA1_CTX*, int);
void SHA1DC_API SHA1DCSetDetectReducedRoundCollision(SHA1_CTX*, int);

/* function to set a callback function, pass NULL to disable */
/* by default no callback set */
void SHA1DCSetCallback(SHA1_CTX*, collision_block_callback);

#ifdef SHA1DC_CALLBACK_USES_PARAM
void SHA1DC_API SHA1DCSetCallback(SHA1_CTX*, collision_block_callback, void*);
#else
void SHA1DC_API SHA1DCSetCallback(SHA1_CTX*, collision_block_callback);
#endif

/* update SHA-1 context with buffer contents */
void SHA1DCUpdate(SHA1_CTX*, const char*, size_t);
void SHA1DC_API 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 SHA1DC_API SHA1DCFinal(unsigned char[20], SHA1_CTX*);

#if defined(__cplusplus)
}
Expand Down