sha2: import SHA1 implementation

pull/25/head
Saleem Rashid 8 years ago committed by Pavol Rusnak
parent 0acfb2cf28
commit d812c7209f

418
sha2.c

@ -92,6 +92,7 @@ typedef uint64_t sha2_word64; /* Exactly 8 bytes */
/*** SHA-256/384/512 Various Length Definitions ***********************/
/* NOTE: Most of these are in sha2.h */
#define SHA1_SHORT_BLOCK_LENGTH (SHA1_BLOCK_LENGTH - 8)
#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
@ -167,6 +168,22 @@ static void sha512_Last(SHA512_CTX*);
/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
/* Hash constant words K for SHA-1: */
#define K1_0_TO_19 0x5a827999UL
#define K1_20_TO_39 0x6ed9eba1UL
#define K1_40_TO_59 0x8f1bbcdcUL
#define K1_60_TO_79 0xca62c1d6UL
/* Initial hash value H for SHA-1: */
const sha2_word32 sha1_initial_hash_value[SHA1_DIGEST_LENGTH / sizeof(sha2_word32)] = {
0x67452301UL,
0xefcdab89UL,
0x98badcfeUL,
0x10325476UL,
0xc3d2e1f0UL
};
/* Hash constant words K for SHA-256: */
static const sha2_word32 K256[64] = {
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
@ -262,6 +279,407 @@ const sha2_word64 sha512_initial_hash_value[8] = {
static const char *sha2_hex_digits = "0123456789abcdef";
/*** SHA-1: ***********************************************************/
void sha1_Init(SHA1_CTX* context) {
MEMCPY_BCOPY(context->state, sha1_initial_hash_value, SHA1_DIGEST_LENGTH);
MEMSET_BZERO(context->buffer, SHA1_BLOCK_LENGTH);
context->bitcount = 0;
}
#ifdef SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-1 round macros: */
#if BYTE_ORDER == LITTLE_ENDIAN
#define ROUND1_0_TO_15(a,b,c,d,e) \
REVERSE32(*data++, W1[j]); \
(e) = ROTL32(5, (a)) + Ch((b), (c), (d)) + (e) + \
K1_0_TO_19 + W1[j]; \
(b) = ROTL32(30, (b)); \
j++;
#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND1_0_TO_15(a,b,c,d,e) \
(e) = ROTL32(5, (a)) + Ch((b), (c), (d)) + (e) + \
K1_0_TO_19 + ( W1[j] = *data++ ); \
(b) = ROTL32(30, (b)); \
j++;
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND1_16_TO_19(a,b,c,d,e) \
T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \
(e) = ROTL32(5, a) + Ch(b,c,d) + e + K1_0_TO_19 + ( W1[j&0x0f] = ROTL32(1, T1) ); \
(b) = ROTL32(30, b); \
j++;
#define ROUND1_20_TO_39(a,b,c,d,e) \
T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \
(e) = ROTL32(5, a) + Parity(b,c,d) + e + K1_20_TO_39 + ( W1[j&0x0f] = ROTL32(1, T1) ); \
(b) = ROTL32(30, b); \
j++;
#define ROUND1_40_TO_59(a,b,c,d,e) \
T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \
(e) = ROTL32(5, a) + Maj(b,c,d) + e + K1_40_TO_59 + ( W1[j&0x0f] = ROTL32(1, T1) ); \
(b) = ROTL32(30, b); \
j++;
#define ROUND1_60_TO_79(a,b,c,d,e) \
T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f]; \
(e) = ROTL32(5, a) + Parity(b,c,d) + e + K1_60_TO_79 + ( W1[j&0x0f] = ROTL32(1, T1) ); \
(b) = ROTL32(30, b); \
j++;
void sha1_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) {
sha2_word32 a, b, c, d, e;
sha2_word32 T1;
sha2_word32 W1[16];
int j;
/* Initialize registers with the prev. intermediate value */
a = state_in[0];
b = state_in[1];
c = state_in[2];
d = state_in[3];
e = state_in[4];
j = 0;
/* Rounds 0 to 15 unrolled: */
ROUND1_0_TO_15(a,b,c,d,e);
ROUND1_0_TO_15(e,a,b,c,d);
ROUND1_0_TO_15(d,e,a,b,c);
ROUND1_0_TO_15(c,d,e,a,b);
ROUND1_0_TO_15(b,c,d,e,a);
ROUND1_0_TO_15(a,b,c,d,e);
ROUND1_0_TO_15(e,a,b,c,d);
ROUND1_0_TO_15(d,e,a,b,c);
ROUND1_0_TO_15(c,d,e,a,b);
ROUND1_0_TO_15(b,c,d,e,a);
ROUND1_0_TO_15(a,b,c,d,e);
ROUND1_0_TO_15(e,a,b,c,d);
ROUND1_0_TO_15(d,e,a,b,c);
ROUND1_0_TO_15(c,d,e,a,b);
ROUND1_0_TO_15(b,c,d,e,a);
ROUND1_0_TO_15(a,b,c,d,e);
/* Rounds 16 to 19 unrolled: */
ROUND1_16_TO_19(e,a,b,c,d);
ROUND1_16_TO_19(d,e,a,b,c);
ROUND1_16_TO_19(c,d,e,a,b);
ROUND1_16_TO_19(b,c,d,e,a);
/* Rounds 20 to 39 unrolled: */
ROUND1_20_TO_39(a,b,c,d,e);
ROUND1_20_TO_39(e,a,b,c,d);
ROUND1_20_TO_39(d,e,a,b,c);
ROUND1_20_TO_39(c,d,e,a,b);
ROUND1_20_TO_39(b,c,d,e,a);
ROUND1_20_TO_39(a,b,c,d,e);
ROUND1_20_TO_39(e,a,b,c,d);
ROUND1_20_TO_39(d,e,a,b,c);
ROUND1_20_TO_39(c,d,e,a,b);
ROUND1_20_TO_39(b,c,d,e,a);
ROUND1_20_TO_39(a,b,c,d,e);
ROUND1_20_TO_39(e,a,b,c,d);
ROUND1_20_TO_39(d,e,a,b,c);
ROUND1_20_TO_39(c,d,e,a,b);
ROUND1_20_TO_39(b,c,d,e,a);
ROUND1_20_TO_39(a,b,c,d,e);
ROUND1_20_TO_39(e,a,b,c,d);
ROUND1_20_TO_39(d,e,a,b,c);
ROUND1_20_TO_39(c,d,e,a,b);
ROUND1_20_TO_39(b,c,d,e,a);
/* Rounds 40 to 59 unrolled: */
ROUND1_40_TO_59(a,b,c,d,e);
ROUND1_40_TO_59(e,a,b,c,d);
ROUND1_40_TO_59(d,e,a,b,c);
ROUND1_40_TO_59(c,d,e,a,b);
ROUND1_40_TO_59(b,c,d,e,a);
ROUND1_40_TO_59(a,b,c,d,e);
ROUND1_40_TO_59(e,a,b,c,d);
ROUND1_40_TO_59(d,e,a,b,c);
ROUND1_40_TO_59(c,d,e,a,b);
ROUND1_40_TO_59(b,c,d,e,a);
ROUND1_40_TO_59(a,b,c,d,e);
ROUND1_40_TO_59(e,a,b,c,d);
ROUND1_40_TO_59(d,e,a,b,c);
ROUND1_40_TO_59(c,d,e,a,b);
ROUND1_40_TO_59(b,c,d,e,a);
ROUND1_40_TO_59(a,b,c,d,e);
ROUND1_40_TO_59(e,a,b,c,d);
ROUND1_40_TO_59(d,e,a,b,c);
ROUND1_40_TO_59(c,d,e,a,b);
ROUND1_40_TO_59(b,c,d,e,a);
/* Rounds 60 to 79 unrolled: */
ROUND1_60_TO_79(a,b,c,d,e);
ROUND1_60_TO_79(e,a,b,c,d);
ROUND1_60_TO_79(d,e,a,b,c);
ROUND1_60_TO_79(c,d,e,a,b);
ROUND1_60_TO_79(b,c,d,e,a);
ROUND1_60_TO_79(a,b,c,d,e);
ROUND1_60_TO_79(e,a,b,c,d);
ROUND1_60_TO_79(d,e,a,b,c);
ROUND1_60_TO_79(c,d,e,a,b);
ROUND1_60_TO_79(b,c,d,e,a);
ROUND1_60_TO_79(a,b,c,d,e);
ROUND1_60_TO_79(e,a,b,c,d);
ROUND1_60_TO_79(d,e,a,b,c);
ROUND1_60_TO_79(c,d,e,a,b);
ROUND1_60_TO_79(b,c,d,e,a);
ROUND1_60_TO_79(a,b,c,d,e);
ROUND1_60_TO_79(e,a,b,c,d);
ROUND1_60_TO_79(d,e,a,b,c);
ROUND1_60_TO_79(c,d,e,a,b);
ROUND1_60_TO_79(b,c,d,e,a);
/* Compute the current intermediate hash value */
state_out[0] = state_in[0] + a;
state_out[1] = state_in[1] + b;
state_out[2] = state_in[2] + c;
state_out[3] = state_in[3] + d;
state_out[4] = state_in[4] + e;
/* Clean up */
a = b = c = d = e = T1 = 0;
}
#else /* SHA2_UNROLL_TRANSFORM */
void sha1_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) {
sha2_word32 a, b, c, d, e;
sha2_word32 T1;
sha2_word32 W1[16];
int j;
/* Initialize registers with the prev. intermediate value */
a = state_in[0];
b = state_in[1];
c = state_in[2];
d = state_in[3];
e = state_in[4];
j = 0;
do {
#if BYTE_ORDER == LITTLE_ENDIAN
T1 = data[j];
/* Copy data while converting to host byte order */
REVERSE32(*data++, W1[j]);
T1 = ROTL32(5, a) + Ch(b, c, d) + e + K1_0_TO_19 + W1[j];
#else /* BYTE_ORDER == LITTLE_ENDIAN */
T1 = ROTL32(5, a) + Ch(b, c, d) + e + K1_0_TO_19 + (W1[j] = *data++);
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
e = d;
d = c;
c = ROTL32(30, b);
b = a;
a = T1;
j++;
} while (j < 16);
do {
T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f];
T1 = ROTL32(5, a) + Ch(b,c,d) + e + K1_0_TO_19 + (W1[j&0x0f] = ROTL32(1, T1));
e = d;
d = c;
c = ROTL32(30, b);
b = a;
a = T1;
j++;
} while (j < 20);
do {
T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f];
T1 = ROTL32(5, a) + Parity(b,c,d) + e + K1_20_TO_39 + (W1[j&0x0f] = ROTL32(1, T1));
e = d;
d = c;
c = ROTL32(30, b);
b = a;
a = T1;
j++;
} while (j < 40);
do {
T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f];
T1 = ROTL32(5, a) + Maj(b,c,d) + e + K1_40_TO_59 + (W1[j&0x0f] = ROTL32(1, T1));
e = d;
d = c;
c = ROTL32(30, b);
b = a;
a = T1;
j++;
} while (j < 60);
do {
T1 = W1[(j+13)&0x0f] ^ W1[(j+8)&0x0f] ^ W1[(j+2)&0x0f] ^ W1[j&0x0f];
T1 = ROTL32(5, a) + Parity(b,c,d) + e + K1_60_TO_79 + (W1[j&0x0f] = ROTL32(1, T1));
e = d;
d = c;
c = ROTL32(30, b);
b = a;
a = T1;
j++;
} while (j < 80);
/* Compute the current intermediate hash value */
state_out[0] = state_in[0] + a;
state_out[1] = state_in[1] + b;
state_out[2] = state_in[2] + c;
state_out[3] = state_in[3] + d;
state_out[4] = state_in[4] + e;
/* Clean up */
a = b = c = d = e = T1 = 0;
}
#endif /* SHA2_UNROLL_TRANSFORM */
void sha1_Update(SHA1_CTX* context, const sha2_byte *data, size_t len) {
unsigned int freespace, usedspace;
if (len == 0) {
/* Calling with no data is valid - we do nothing */
return;
}
usedspace = (context->bitcount >> 3) % SHA1_BLOCK_LENGTH;
if (usedspace > 0) {
/* Calculate how much free space is available in the buffer */
freespace = SHA1_BLOCK_LENGTH - usedspace;
if (len >= freespace) {
/* Fill the buffer completely and process it */
MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, freespace);
context->bitcount += freespace << 3;
len -= freespace;
data += freespace;
sha1_Transform(context->state, context->buffer, context->state);
} else {
/* The buffer is not yet full */
MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, len);
context->bitcount += len << 3;
/* Clean up: */
usedspace = freespace = 0;
return;
}
}
while (len >= SHA1_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
sha1_Transform(context->state, (sha2_word32*)data, context->state);
context->bitcount += SHA1_BLOCK_LENGTH << 3;
len -= SHA1_BLOCK_LENGTH;
data += SHA1_BLOCK_LENGTH;
}
if (len > 0) {
/* There's left-overs, so save 'em */
MEMCPY_BCOPY(context->buffer, data, len);
context->bitcount += len << 3;
}
/* Clean up: */
usedspace = freespace = 0;
}
void sha1_Final(SHA1_CTX* context, sha2_byte digest[]) {
sha2_word32 *d = (sha2_word32*)digest;
unsigned int usedspace;
if (digest == (sha2_byte*)0) {
/*
* No digest buffer, so we can do nothing
* except clean up and go home
*/
MEMSET_BZERO(context, sizeof(context));
return;
}
usedspace = (context->bitcount >> 3) % SHA1_BLOCK_LENGTH;
if (usedspace == 0) {
/* Set-up for the last transform: */
MEMSET_BZERO(context->buffer, SHA1_SHORT_BLOCK_LENGTH);
/* Begin padding with a 1 bit: */
*context->buffer = 0x80;
} else {
/* Begin padding with a 1 bit: */
((uint8_t*)context->buffer)[usedspace++] = 0x80;
if (usedspace <= 56) {
/* Set-up for the last transform: */
MEMSET_BZERO(((uint8_t*)context->buffer) + usedspace, 56 - usedspace);
} else {
if (usedspace < 64) {
MEMSET_BZERO(((uint8_t*)context->buffer) + usedspace, 64 - usedspace);
}
/* Do second-to-last transform: */
sha1_Transform(context->state, context->buffer, context->state);
/* And set-up for the last transform: */
MEMSET_BZERO(context->buffer, 56);
}
/* Clean up: */
usedspace = 0;
}
/* Set the bit count: */
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert FROM host byte order */
REVERSE64(context->bitcount,context->bitcount);
#endif
context->buffer[SHA1_SHORT_BLOCK_LENGTH >> 2] = context->bitcount << 32;
context->buffer[SHA1_SHORT_BLOCK_LENGTH >> 2 | 1] = context->bitcount >> 32;
/* Final transform: */
sha1_Transform(context->state, context->buffer, context->state);
/* Save the hash data for output: */
#if BYTE_ORDER == LITTLE_ENDIAN
{
/* Convert TO host byte order */
int j;
for (j = 0; j < (SHA1_DIGEST_LENGTH >> 2); j++) {
REVERSE32(context->state[j],context->state[j]);
*d++ = context->state[j];
}
}
#else
MEMCPY_BCOPY(d, context->state, SHA1_DIGEST_LENGTH);
#endif
/* Clean up: */
MEMSET_BZERO(context, sizeof(context));
}
char *sha1_End(SHA1_CTX* context, char buffer[]) {
sha2_byte digest[SHA1_DIGEST_LENGTH], *d = digest;
int i;
if (buffer != (char*)0) {
sha1_Final(context, digest);
for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
*buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
*buffer++ = sha2_hex_digits[*d & 0x0f];
d++;
}
*buffer = (char)0;
} else {
MEMSET_BZERO(context, sizeof(context));
}
MEMSET_BZERO(digest, SHA1_DIGEST_LENGTH);
return buffer;
}
char* sha1_Data(const sha2_byte* data, size_t len, char digest[SHA1_DIGEST_STRING_LENGTH]) {
SHA1_CTX context;
sha1_Init(&context);
sha1_Update(&context, data, len);
return sha1_End(&context, digest);
}
/*** SHA-256: *********************************************************/
void sha256_Init(SHA256_CTX* context) {
if (context == (SHA256_CTX*)0) {

@ -34,6 +34,9 @@
#include <stdint.h>
#include <stddef.h>
#define SHA1_BLOCK_LENGTH 64
#define SHA1_DIGEST_LENGTH 20
#define SHA1_DIGEST_STRING_LENGTH (SHA1_DIGEST_LENGTH * 2 + 1)
#define SHA256_BLOCK_LENGTH 64
#define SHA256_DIGEST_LENGTH 32
#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
@ -41,6 +44,11 @@
#define SHA512_DIGEST_LENGTH 64
#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
typedef struct _SHA1_CTX {
uint32_t state[5];
uint64_t bitcount;
uint32_t buffer[SHA1_BLOCK_LENGTH/sizeof(uint32_t)];
} SHA1_CTX;
typedef struct _SHA256_CTX {
uint32_t state[8];
uint64_t bitcount;
@ -81,6 +89,14 @@ typedef struct _SHA512_CTX {
extern const uint32_t sha256_initial_hash_value[8];
extern const uint64_t sha512_initial_hash_value[8];
void sha1_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out);
void sha1_Init(SHA1_CTX *);
void sha1_Update(SHA1_CTX*, const uint8_t*, size_t);
void sha1_Final(SHA1_CTX*, uint8_t[SHA1_DIGEST_LENGTH]);
char* sha1_End(SHA1_CTX*, char[SHA1_DIGEST_STRING_LENGTH]);
void sha1_Raw(const uint8_t*, size_t, uint8_t[SHA1_DIGEST_LENGTH]);
char* sha1_Data(const uint8_t*, size_t, char[SHA1_DIGEST_STRING_LENGTH]);
void sha256_Transform(const uint32_t* state_in, const uint32_t* data, uint32_t* state_out);
void sha256_Init(SHA256_CTX *);
void sha256_Update(SHA256_CTX*, const uint8_t*, size_t);

Loading…
Cancel
Save