1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-18 12:28:09 +00:00

Merge pull request #62 from jhoenicke/pbkdf2_fast

Faster PBKDF2
This commit is contained in:
Pavol Rusnak 2016-07-19 16:43:49 +02:00 committed by GitHub
commit 4d6d9fe8ba
8 changed files with 560 additions and 255 deletions

View File

@ -226,10 +226,10 @@ void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed
if (progress_callback) {
progress_callback(0, BIP39_PBKDF2_ROUNDS);
}
for (int i = 0; i < 8; i++) {
pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 8);
for (int i = 0; i < 16; i++) {
pbkdf2_hmac_sha512_Update(&pctx, BIP39_PBKDF2_ROUNDS / 16);
if (progress_callback) {
progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 8, BIP39_PBKDF2_ROUNDS);
progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 16, BIP39_PBKDF2_ROUNDS);
}
}
pbkdf2_hmac_sha512_Final(&pctx, seed);

56
hmac.c
View File

@ -69,6 +69,34 @@ void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
hmac_sha256_Final(&hctx, hmac);
}
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest)
{
int i;
uint32_t buf[SHA256_BLOCK_LENGTH/sizeof(uint32_t)];
uint32_t o_key_pad[16], i_key_pad[16];
memset(buf, 0, SHA256_BLOCK_LENGTH);
if (keylen > SHA256_BLOCK_LENGTH) {
sha256_Raw(key, keylen, (uint8_t*) buf);
} else {
memcpy(buf, key, keylen);
}
for (i = 0; i < 16; i++) {
uint32_t data;
#if BYTE_ORDER == LITTLE_ENDIAN
REVERSE32(buf[i], data);
#else
data = buf[i];
#endif
o_key_pad[i] = data ^ 0x5c5c5c5c;
i_key_pad[i] = data ^ 0x36363636;
}
sha256_Transform(sha256_initial_hash_value, o_key_pad, opad_digest);
sha256_Transform(sha256_initial_hash_value, i_key_pad, ipad_digest);
}
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen)
{
uint8_t i_key_pad[SHA512_BLOCK_LENGTH];
@ -111,3 +139,31 @@ void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg,
hmac_sha512_Update(&hctx, msg, msglen);
hmac_sha512_Final(&hctx, hmac);
}
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest)
{
int i;
uint64_t buf[SHA512_BLOCK_LENGTH/sizeof(uint64_t)];
uint64_t o_key_pad[16], i_key_pad[16];
memset(buf, 0, SHA512_BLOCK_LENGTH);
if (keylen > SHA512_BLOCK_LENGTH) {
sha512_Raw(key, keylen, (uint8_t*)buf);
} else {
memcpy(buf, key, keylen);
}
for (i = 0; i < 16; i++) {
uint64_t data;
#if BYTE_ORDER == LITTLE_ENDIAN
REVERSE64(buf[i], data);
#else
data = buf[i];
#endif
o_key_pad[i] = data ^ 0x5c5c5c5c5c5c5c5c;
i_key_pad[i] = data ^ 0x3636363636363636;
}
sha512_Transform(sha512_initial_hash_value, o_key_pad, opad_digest);
sha512_Transform(sha512_initial_hash_value, i_key_pad, ipad_digest);
}

2
hmac.h
View File

@ -41,10 +41,12 @@ void hmac_sha256_Init(HMAC_SHA256_CTX *hctx, const uint8_t *key, const uint32_t
void hmac_sha256_Update(HMAC_SHA256_CTX *hctx, const uint8_t *msg, const uint32_t msglen);
void hmac_sha256_Final(HMAC_SHA256_CTX *hctx, uint8_t *hmac);
void hmac_sha256(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac);
void hmac_sha256_prepare(const uint8_t *key, const uint32_t keylen, uint32_t *opad_digest, uint32_t *ipad_digest);
void hmac_sha512_Init(HMAC_SHA512_CTX *hctx, const uint8_t *key, const uint32_t keylen);
void hmac_sha512_Update(HMAC_SHA512_CTX *hctx, const uint8_t *msg, const uint32_t msglen);
void hmac_sha512_Final(HMAC_SHA512_CTX *hctx, uint8_t *hmac);
void hmac_sha512(const uint8_t *key, const uint32_t keylen, const uint8_t *msg, const uint32_t msglen, uint8_t *hmac);
void hmac_sha512_prepare(const uint8_t *key, const uint32_t keylen, uint64_t *opad_digest, uint64_t *ipad_digest);
#endif

View File

@ -24,26 +24,43 @@
#include <string.h>
#include "pbkdf2.h"
#include "hmac.h"
#include "sha2.h"
#include "macros.h"
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen)
{
HMAC_SHA256_CTX hctx;
hmac_sha256_Init(&hctx, pass, passlen);
hmac_sha256_Update(&hctx, salt, saltlen);
hmac_sha256_Update(&hctx, (const uint8_t *)"\x00\x00\x00\x01", 4);
hmac_sha256_Final(&hctx, pctx->g);
SHA256_CTX ctx;
uint32_t blocknr = 1;
#if BYTE_ORDER == LITTLE_ENDIAN
REVERSE32(blocknr, blocknr);
#endif
hmac_sha256_prepare(pass, passlen, pctx->odig, pctx->idig);
memset(pctx->g, 0, sizeof(pctx->g));
pctx->g[8] = 0x80000000;
pctx->g[15] = (SHA256_BLOCK_LENGTH + SHA256_DIGEST_LENGTH) * 8;
memcpy (ctx.state, pctx->idig, sizeof(pctx->idig));
ctx.bitcount = SHA256_BLOCK_LENGTH * 8;
sha256_Update(&ctx, salt, saltlen);
sha256_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr));
sha256_Final(&ctx, (uint8_t*)pctx->g);
#if BYTE_ORDER == LITTLE_ENDIAN
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH / sizeof(uint32_t); k++) {
REVERSE32(pctx->g[k], pctx->g[k]);
}
#endif
sha256_Transform(pctx->odig, pctx->g, pctx->g);
memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH);
pctx->pass = pass;
pctx->passlen = passlen;
pctx->first = 1;
}
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations)
{
for (uint32_t i = pctx->first; i < iterations; i++) {
hmac_sha256(pctx->pass, pctx->passlen, pctx->g, SHA256_DIGEST_LENGTH, pctx->g);
for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH; j++) {
sha256_Transform(pctx->idig, pctx->g, pctx->g);
sha256_Transform(pctx->odig, pctx->g, pctx->g);
for (uint32_t j = 0; j < SHA256_DIGEST_LENGTH/sizeof(uint32_t); j++) {
pctx->f[j] ^= pctx->g[j];
}
}
@ -52,6 +69,11 @@ void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key)
{
#if BYTE_ORDER == LITTLE_ENDIAN
for (uint32_t k = 0; k < SHA256_DIGEST_LENGTH/sizeof(uint32_t); k++) {
REVERSE32(pctx->f[k], pctx->f[k]);
}
#endif
memcpy(key, pctx->f, SHA256_DIGEST_LENGTH);
MEMSET_BZERO(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX));
}
@ -66,22 +88,39 @@ void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, const uint8_t *salt, i
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, const uint8_t *salt, int saltlen)
{
HMAC_SHA512_CTX hctx;
hmac_sha512_Init(&hctx, pass, passlen);
hmac_sha512_Update(&hctx, salt, saltlen);
hmac_sha512_Update(&hctx, (const uint8_t *)"\x00\x00\x00\x01", 4);
hmac_sha512_Final(&hctx, pctx->g);
SHA512_CTX ctx;
uint32_t blocknr = 1;
#if BYTE_ORDER == LITTLE_ENDIAN
REVERSE32(blocknr, blocknr);
#endif
hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig);
memset(pctx->g, 0, sizeof(pctx->g));
pctx->g[8] = 0x8000000000000000;
pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8;
memcpy (ctx.state, pctx->idig, sizeof(pctx->idig));
ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8;
ctx.bitcount[1] = 0;
sha512_Update(&ctx, salt, saltlen);
sha512_Update(&ctx, (uint8_t*)&blocknr, sizeof(blocknr));
sha512_Final(&ctx, (uint8_t*)pctx->g);
#if BYTE_ORDER == LITTLE_ENDIAN
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
REVERSE64(pctx->g[k], pctx->g[k]);
}
#endif
sha512_Transform(pctx->odig, pctx->g, pctx->g);
memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH);
pctx->pass = pass;
pctx->passlen = passlen;
pctx->first = 1;
}
void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations)
{
for (uint32_t i = pctx->first; i < iterations; i++) {
hmac_sha512(pctx->pass, pctx->passlen, pctx->g, SHA512_DIGEST_LENGTH, pctx->g);
for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH; j++) {
sha512_Transform(pctx->idig, pctx->g, pctx->g);
sha512_Transform(pctx->odig, pctx->g, pctx->g);
for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) {
pctx->f[j] ^= pctx->g[j];
}
}
@ -90,6 +129,11 @@ void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx, uint32_t iterations
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key)
{
#if BYTE_ORDER == LITTLE_ENDIAN
for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH/sizeof(uint64_t); k++) {
REVERSE64(pctx->f[k], pctx->f[k]);
}
#endif
memcpy(key, pctx->f, SHA512_DIGEST_LENGTH);
MEMSET_BZERO(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX));
}

View File

@ -28,18 +28,18 @@
#include "sha2.h"
typedef struct _PBKDF2_HMAC_SHA256_CTX {
uint8_t f[SHA256_DIGEST_LENGTH];
uint8_t g[SHA256_DIGEST_LENGTH];
const uint8_t *pass;
int passlen;
uint32_t odig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
uint32_t idig[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
uint32_t f[SHA256_DIGEST_LENGTH / sizeof(uint32_t)];
uint32_t g[SHA256_BLOCK_LENGTH / sizeof(uint32_t)];
char first;
} PBKDF2_HMAC_SHA256_CTX;
typedef struct _PBKDF2_HMAC_SHA512_CTX {
uint8_t f[SHA512_DIGEST_LENGTH];
uint8_t g[SHA512_DIGEST_LENGTH];
const uint8_t *pass;
int passlen;
uint64_t odig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
uint64_t idig[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
uint64_t f[SHA512_DIGEST_LENGTH / sizeof(uint64_t)];
uint64_t g[SHA512_BLOCK_LENGTH / sizeof(uint64_t)];
char first;
} PBKDF2_HMAC_SHA512_CTX;

403
sha2.c
View File

@ -82,15 +82,6 @@
* made).
*/
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#define BIG_ENDIAN 4321
#endif
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
#endif
@ -104,24 +95,6 @@ typedef uint64_t sha2_word64; /* Exactly 8 bytes */
#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
/*** ENDIAN REVERSAL MACROS *******************************************/
#if BYTE_ORDER == LITTLE_ENDIAN
#define REVERSE32(w,x) { \
sha2_word32 tmp = (w); \
tmp = (tmp >> 16) | (tmp << 16); \
(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
}
#define REVERSE64(w,x) { \
sha2_word64 tmp = (w); \
tmp = (tmp >> 32) | (tmp << 32); \
tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
((tmp & 0x00ff00ff00ff00ffULL) << 8); \
(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
((tmp & 0x0000ffff0000ffffULL) << 16); \
}
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
/*
* Macro for incrementally adding the unsigned 64-bit integer n to the
* unsigned 128-bit integer (represented using a two-element array of
@ -174,9 +147,7 @@ typedef uint64_t sha2_word64; /* Exactly 8 bytes */
* library -- they are intended for private internal visibility/use
* only.
*/
void sha512_Last(SHA512_CTX*);
void sha256_Transform(SHA256_CTX*, const sha2_word32*);
void sha512_Transform(SHA512_CTX*, const sha2_word64*);
static void sha512_Last(SHA512_CTX*);
/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
@ -201,7 +172,7 @@ static const sha2_word32 K256[64] = {
};
/* Initial hash value H for SHA-256: */
static const sha2_word32 sha256_initial_hash_value[8] = {
const sha2_word32 sha256_initial_hash_value[8] = {
0x6a09e667UL,
0xbb67ae85UL,
0x3c6ef372UL,
@ -257,7 +228,7 @@ static const sha2_word64 K512[80] = {
};
/* Initial hash value H for SHA-512 */
static const sha2_word64 sha512_initial_hash_value[8] = {
const sha2_word64 sha512_initial_hash_value[8] = {
0x6a09e667f3bcc908ULL,
0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL,
@ -292,7 +263,7 @@ void sha256_Init(SHA256_CTX* context) {
#if BYTE_ORDER == LITTLE_ENDIAN
#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
REVERSE32(*data++, W256[j]); \
W256[j] = *data++; \
T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
K256[j] + W256[j]; \
(d) += T1; \
@ -322,22 +293,21 @@ void sha256_Init(SHA256_CTX* context) {
(h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
j++
void sha256_Transform(SHA256_CTX* context, const sha2_word32* data) {
void sha256_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) {
sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
sha2_word32 T1, *W256;
sha2_word32 T1;
sha2_word32 W256[16];
int j;
W256 = (sha2_word32*)context->buffer;
/* Initialize registers with the prev. intermediate value */
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
a = state_in[0];
b = state_in[1];
c = state_in[2];
d = state_in[3];
e = state_in[4];
f = state_in[5];
g = state_in[6];
h = state_in[7];
j = 0;
do {
@ -365,14 +335,14 @@ void sha256_Transform(SHA256_CTX* context, const sha2_word32* data) {
} while (j < 64);
/* Compute the current intermediate hash value */
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
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;
state_out[5] = state_in[5] + f;
state_out[6] = state_in[6] + g;
state_out[7] = state_in[7] + h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = 0;
@ -380,34 +350,25 @@ void sha256_Transform(SHA256_CTX* context, const sha2_word32* data) {
#else /* SHA2_UNROLL_TRANSFORM */
void sha256_Transform(SHA256_CTX* context, const sha2_word32* data) {
void sha256_Transform(const sha2_word32* state_in, const sha2_word32* data, sha2_word32* state_out) {
sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
sha2_word32 T1, T2, *W256;
sha2_word32 T1, T2, W256[16];
int j;
W256 = (sha2_word32*)(void*)context->buffer;
/* Initialize registers with the prev. intermediate value */
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
a = state_in[0];
b = state_in[1];
c = state_in[2];
d = state_in[3];
e = state_in[4];
f = state_in[5];
g = state_in[6];
h = state_in[7];
j = 0;
do {
#if BYTE_ORDER == LITTLE_ENDIAN
/* Copy data while converting to host byte order */
REVERSE32(*data++,W256[j]);
/* Apply the SHA-256 compression function to update a..h */
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
#else /* BYTE_ORDER == LITTLE_ENDIAN */
/* Apply the SHA-256 compression function to update a..h with copy */
T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
T2 = Sigma0_256(a) + Maj(a, b, c);
h = g;
g = f;
@ -445,14 +406,14 @@ void sha256_Transform(SHA256_CTX* context, const sha2_word32* data) {
} while (j < 64);
/* Compute the current intermediate hash value */
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
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;
state_out[5] = state_in[5] + f;
state_out[6] = state_in[6] + g;
state_out[7] = state_in[7] + h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = T2 = 0;
@ -475,14 +436,20 @@ void sha256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
if (len >= freespace) {
/* Fill the buffer completely and process it */
MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, freespace);
context->bitcount += freespace << 3;
len -= freespace;
data += freespace;
sha256_Transform(context, (sha2_word32*)(void*)context->buffer);
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
for (int j = 0; j < 16; j++) {
REVERSE32(context->buffer[j],context->buffer[j]);
}
#endif
sha256_Transform(context->state, context->buffer, context->state);
} else {
/* The buffer is not yet full */
MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, len);
context->bitcount += len << 3;
/* Clean up: */
usedspace = freespace = 0;
@ -491,7 +458,14 @@ void sha256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
}
while (len >= SHA256_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
sha256_Transform(context, (sha2_word32*)(void*)data);
MEMCPY_BCOPY(context->buffer, data, SHA256_BLOCK_LENGTH);
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
for (int j = 0; j < 16; j++) {
REVERSE32(context->buffer[j],context->buffer[j]);
}
#endif
sha256_Transform(context->state, context->buffer, context->state);
context->bitcount += SHA256_BLOCK_LENGTH << 3;
len -= SHA256_BLOCK_LENGTH;
data += SHA256_BLOCK_LENGTH;
@ -512,53 +486,49 @@ void sha256_Final(SHA256_CTX* context, sha2_byte digest[]) {
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != (sha2_byte*)0) {
usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert FROM host byte order */
REVERSE64(context->bitcount,context->bitcount);
#endif
if (usedspace > 0) {
/* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
/* Set-up for the last transform: */
MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
} else {
if (usedspace < SHA256_BLOCK_LENGTH) {
MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
sha256_Transform(context, (sha2_word32*)(void*)context->buffer);
/* And set-up for the last transform: */
MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
}
} else {
/* Begin padding with a 1 bit: */
((uint8_t*)context->buffer)[usedspace++] = 0x80;
if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
/* Set-up for the last transform: */
MEMSET_BZERO(((uint8_t*)context->buffer) + usedspace, SHA256_SHORT_BLOCK_LENGTH - usedspace);
} else {
if (usedspace < SHA256_BLOCK_LENGTH) {
MEMSET_BZERO(((uint8_t*)context->buffer) + usedspace, SHA256_BLOCK_LENGTH - usedspace);
}
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
for (int j = 0; j < 16; j++) {
REVERSE32(context->buffer[j],context->buffer[j]);
}
#endif
/* Do second-to-last transform: */
sha256_Transform(context->state, context->buffer, context->state);
/* And set-up for the last transform: */
MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
/* Begin padding with a 1 bit: */
*context->buffer = 0x80;
}
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
for (int j = 0; j < 14; j++) {
REVERSE32(context->buffer[j],context->buffer[j]);
}
#endif
/* Set the bit count: */
sha2_word64 *t = (sha2_word64 *)(void*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH];
*t = context->bitcount;
context->buffer[14] = context->bitcount >> 32;
context->buffer[15] = context->bitcount & 0xffffffff;
/* Final transform: */
sha256_Transform(context, (sha2_word32*)(void*)context->buffer);
sha256_Transform(context->state, context->buffer, context->state);
#if BYTE_ORDER == LITTLE_ENDIAN
{
/* Convert TO host byte order */
int j;
for (j = 0; j < 8; j++) {
REVERSE32(context->state[j],context->state[j]);
*d++ = context->state[j];
}
/* Convert FROM host byte order */
for (int j = 0; j < 8; j++) {
REVERSE32(context->state[j],context->state[j]);
}
#else
MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH);
#endif
MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH);
}
/* Clean up state data: */
@ -615,19 +585,6 @@ void sha512_Init(SHA512_CTX* context) {
#ifdef SHA2_UNROLL_TRANSFORM
/* Unrolled SHA-512 round macros: */
#if BYTE_ORDER == LITTLE_ENDIAN
#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
REVERSE64(*data++, W512[j]); \
T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
K512[j] + W512[j]; \
(d) += T1, \
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
j++
#else /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
K512[j] + (W512[j] = *data++); \
@ -635,8 +592,6 @@ void sha512_Init(SHA512_CTX* context) {
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
j++
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#define ROUND512(a,b,c,d,e,f,g,h) \
s0 = W512[(j+1)&0x0f]; \
s0 = sigma0_512(s0); \
@ -648,20 +603,20 @@ void sha512_Init(SHA512_CTX* context) {
(h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
j++
void sha512_Transform(SHA512_CTX* context, const sha2_word64* data) {
void sha512_Transform(const sha2_word64* state_in, const sha2_word64* data, sha2_word64* state_out) {
sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
sha2_word64 T1, *W512 = (sha2_word64*)context->buffer;
sha2_word64 T1, W512[16];
int j;
/* Initialize registers with the prev. intermediate value */
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
a = state_in[0];
b = state_in[1];
c = state_in[2];
d = state_in[3];
e = state_in[4];
f = state_in[5];
g = state_in[6];
h = state_in[7];
j = 0;
do {
@ -688,14 +643,14 @@ void sha512_Transform(SHA512_CTX* context, const sha2_word64* data) {
} while (j < 80);
/* Compute the current intermediate hash value */
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
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;
state_out[5] = state_in[5] + f;
state_out[6] = state_in[6] + g;
state_out[7] = state_in[7] + h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = 0;
@ -703,32 +658,25 @@ void sha512_Transform(SHA512_CTX* context, const sha2_word64* data) {
#else /* SHA2_UNROLL_TRANSFORM */
void sha512_Transform(SHA512_CTX* context, const sha2_word64* data) {
void sha512_Transform(const sha2_word64* state_in, const sha2_word64* data, sha2_word64* state_out) {
sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
sha2_word64 T1, T2, *W512 = (sha2_word64*)(void*)context->buffer;
sha2_word64 T1, T2, W512[16];
int j;
/* Initialize registers with the prev. intermediate value */
a = context->state[0];
b = context->state[1];
c = context->state[2];
d = context->state[3];
e = context->state[4];
f = context->state[5];
g = context->state[6];
h = context->state[7];
a = state_in[0];
b = state_in[1];
c = state_in[2];
d = state_in[3];
e = state_in[4];
f = state_in[5];
g = state_in[6];
h = state_in[7];
j = 0;
do {
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
REVERSE64(*data++, W512[j]);
/* Apply the SHA-512 compression function to update a..h */
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
#else /* BYTE_ORDER == LITTLE_ENDIAN */
/* Apply the SHA-512 compression function to update a..h with copy */
T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
T2 = Sigma0_512(a) + Maj(a, b, c);
h = g;
g = f;
@ -766,14 +714,14 @@ void sha512_Transform(SHA512_CTX* context, const sha2_word64* data) {
} while (j < 80);
/* Compute the current intermediate hash value */
context->state[0] += a;
context->state[1] += b;
context->state[2] += c;
context->state[3] += d;
context->state[4] += e;
context->state[5] += f;
context->state[6] += g;
context->state[7] += h;
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;
state_out[5] = state_in[5] + f;
state_out[6] = state_in[6] + g;
state_out[7] = state_in[7] + h;
/* Clean up */
a = b = c = d = e = f = g = h = T1 = T2 = 0;
@ -796,14 +744,20 @@ void sha512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
if (len >= freespace) {
/* Fill the buffer completely and process it */
MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, freespace);
ADDINC128(context->bitcount, freespace << 3);
len -= freespace;
data += freespace;
sha512_Transform(context, (sha2_word64*)(void*)context->buffer);
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
for (int j = 0; j < 16; j++) {
REVERSE64(context->buffer[j],context->buffer[j]);
}
#endif
sha512_Transform(context->state, context->buffer, context->state);
} else {
/* The buffer is not yet full */
MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
MEMCPY_BCOPY(((uint8_t*)context->buffer) + usedspace, data, len);
ADDINC128(context->bitcount, len << 3);
/* Clean up: */
usedspace = freespace = 0;
@ -812,7 +766,14 @@ void sha512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
}
while (len >= SHA512_BLOCK_LENGTH) {
/* Process as many complete blocks as we can */
sha512_Transform(context, (sha2_word64*)(void*)data);
MEMCPY_BCOPY(context->buffer, data, SHA512_BLOCK_LENGTH);
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
for (int j = 0; j < 16; j++) {
REVERSE64(((sha2_word64*)data)[j],context->buffer[j]);
}
#endif
sha512_Transform(context->state, context->buffer, context->state);
ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
len -= SHA512_BLOCK_LENGTH;
data += SHA512_BLOCK_LENGTH;
@ -826,48 +787,47 @@ void sha512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
usedspace = freespace = 0;
}
void sha512_Last(SHA512_CTX* context) {
static void sha512_Last(SHA512_CTX* context) {
unsigned int usedspace;
usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert FROM host byte order */
REVERSE64(context->bitcount[0],context->bitcount[0]);
REVERSE64(context->bitcount[1],context->bitcount[1]);
#endif
if (usedspace > 0) {
/* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
/* Set-up for the last transform: */
MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
} else {
if (usedspace < SHA512_BLOCK_LENGTH) {
MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
sha512_Transform(context, (sha2_word64*)(void*)context->buffer);
/* And set-up for the last transform: */
MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
}
/* Begin padding with a 1 bit: */
((uint8_t*)context->buffer)[usedspace++] = 0x80;
if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
/* Set-up for the last transform: */
MEMSET_BZERO(((uint8_t*)context->buffer) + usedspace, SHA512_SHORT_BLOCK_LENGTH - usedspace);
} else {
/* Prepare for final transform: */
MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
if (usedspace < SHA512_BLOCK_LENGTH) {
MEMSET_BZERO(((uint8_t*)context->buffer) + usedspace, SHA512_BLOCK_LENGTH - usedspace);
}
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
for (int j = 0; j < 16; j++) {
REVERSE64(context->buffer[j],context->buffer[j]);
}
#endif
/* Do second-to-last transform: */
sha512_Transform(context->state, context->buffer, context->state);
/* Begin padding with a 1 bit: */
*context->buffer = 0x80;
/* And set-up for the last transform: */
MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
}
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert TO host byte order */
for (int j = 0; j < 16; j++) {
REVERSE64(context->buffer[j],context->buffer[j]);
}
#endif
/* Store the length of input data (in bits): */
sha2_word64 *t;
t = (sha2_word64 *)(void*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH];
*t = context->bitcount[1];
t = (sha2_word64 *)(void*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8];
*t = context->bitcount[0];
t = &context->buffer[SHA512_SHORT_BLOCK_LENGTH/sizeof(sha2_word64)];
t[0] = context->bitcount[1];
t[1] = context->bitcount[0];
/* Final transform: */
sha512_Transform(context, (sha2_word64*)(void*)context->buffer);
sha512_Transform(context->state, context->buffer, context->state);
}
void sha512_Final(SHA512_CTX* context, sha2_byte digest[]) {
@ -879,17 +839,12 @@ void sha512_Final(SHA512_CTX* context, sha2_byte digest[]) {
/* Save the hash data for output: */
#if BYTE_ORDER == LITTLE_ENDIAN
{
/* Convert TO host byte order */
int j;
for (j = 0; j < 8; j++) {
REVERSE64(context->state[j],context->state[j]);
*d++ = context->state[j];
}
/* Convert FROM host byte order */
for (int j = 0; j < 8; j++) {
REVERSE64(context->state[j],context->state[j]);
}
#else
MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH);
#endif
MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH);
}
/* Zero out state data */

35
sha2.h
View File

@ -44,14 +44,44 @@
typedef struct _SHA256_CTX {
uint32_t state[8];
uint64_t bitcount;
uint8_t buffer[SHA256_BLOCK_LENGTH];
uint32_t buffer[SHA256_BLOCK_LENGTH/sizeof(uint32_t)];
} SHA256_CTX;
typedef struct _SHA512_CTX {
uint64_t state[8];
uint64_t bitcount[2];
uint8_t buffer[SHA512_BLOCK_LENGTH];
uint64_t buffer[SHA512_BLOCK_LENGTH/sizeof(uint64_t)];
} SHA512_CTX;
/*** ENDIAN REVERSAL MACROS *******************************************/
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#define BIG_ENDIAN 4321
#endif
#ifndef BYTE_ORDER
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
#define REVERSE32(w,x) { \
uint32_t tmp = (w); \
tmp = (tmp >> 16) | (tmp << 16); \
(x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
}
#define REVERSE64(w,x) { \
uint64_t tmp = (w); \
tmp = (tmp >> 32) | (tmp << 32); \
tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
((tmp & 0x00ff00ff00ff00ffULL) << 8); \
(x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
((tmp & 0x0000ffff0000ffffULL) << 16); \
}
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
extern const uint32_t sha256_initial_hash_value[8];
extern const uint64_t sha512_initial_hash_value[8];
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);
void sha256_Final(SHA256_CTX*, uint8_t[SHA256_DIGEST_LENGTH]);
@ -59,6 +89,7 @@ char* sha256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
void sha256_Raw(const uint8_t*, size_t, uint8_t[SHA256_DIGEST_LENGTH]);
char* sha256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
void sha512_Transform(const uint64_t* state_in, const uint64_t* data, uint64_t* state_out);
void sha512_Init(SHA512_CTX*);
void sha512_Update(SHA512_CTX*, const uint8_t*, size_t);
void sha512_Final(SHA512_CTX*, uint8_t[SHA512_DIGEST_LENGTH]);

217
tests.c
View File

@ -1268,6 +1268,215 @@ START_TEST(test_aes)
}
END_TEST
#define TEST1 "abc"
#define TEST2_1 \
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
#define TEST2_2a \
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
#define TEST2_2b \
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
#define TEST2_2 TEST2_2a TEST2_2b
#define TEST3 "a" /* times 1000000 */
#define TEST4a "01234567012345670123456701234567"
#define TEST4b "01234567012345670123456701234567"
/* an exact multiple of 512 bits */
#define TEST4 TEST4a TEST4b /* times 10 */
#define TEST7_1 \
"\x49\xb2\xae\xc2\x59\x4b\xbe\x3a\x3b\x11\x75\x42\xd9\x4a\xc8"
#define TEST8_1 \
"\x9a\x7d\xfd\xf1\xec\xea\xd0\x6e\xd6\x46\xaa\x55\xfe\x75\x71\x46"
#define TEST9_1 \
"\x65\xf9\x32\x99\x5b\xa4\xce\x2c\xb1\xb4\xa2\xe7\x1a\xe7\x02\x20" \
"\xaa\xce\xc8\x96\x2d\xd4\x49\x9c\xbd\x7c\x88\x7a\x94\xea\xaa\x10" \
"\x1e\xa5\xaa\xbc\x52\x9b\x4e\x7e\x43\x66\x5a\x5a\xf2\xcd\x03\xfe" \
"\x67\x8e\xa6\xa5\x00\x5b\xba\x3b\x08\x22\x04\xc2\x8b\x91\x09\xf4" \
"\x69\xda\xc9\x2a\xaa\xb3\xaa\x7c\x11\xa1\xb3\x2a"
#define TEST10_1 \
"\xf7\x8f\x92\x14\x1b\xcd\x17\x0a\xe8\x9b\x4f\xba\x15\xa1\xd5\x9f" \
"\x3f\xd8\x4d\x22\x3c\x92\x51\xbd\xac\xbb\xae\x61\xd0\x5e\xd1\x15" \
"\xa0\x6a\x7c\xe1\x17\xb7\xbe\xea\xd2\x44\x21\xde\xd9\xc3\x25\x92" \
"\xbd\x57\xed\xea\xe3\x9c\x39\xfa\x1f\xe8\x94\x6a\x84\xd0\xcf\x1f" \
"\x7b\xee\xad\x17\x13\xe2\xe0\x95\x98\x97\x34\x7f\x67\xc8\x0b\x04" \
"\x00\xc2\x09\x81\x5d\x6b\x10\xa6\x83\x83\x6f\xd5\x56\x2a\x56\xca" \
"\xb1\xa2\x8e\x81\xb6\x57\x66\x54\x63\x1c\xf1\x65\x66\xb8\x6e\x3b" \
"\x33\xa1\x08\xb0\x53\x07\xc0\x0a\xff\x14\xa7\x68\xed\x73\x50\x60" \
"\x6a\x0f\x85\xe6\xa9\x1d\x39\x6f\x5b\x5c\xbe\x57\x7f\x9b\x38\x80" \
"\x7c\x7d\x52\x3d\x6d\x79\x2f\x6e\xbc\x24\xa4\xec\xf2\xb3\xa4\x27" \
"\xcd\xbb\xfb"
#define TEST7_256 \
"\xbe\x27\x46\xc6\xdb\x52\x76\x5f\xdb\x2f\x88\x70\x0f\x9a\x73"
#define TEST8_256 \
"\xe3\xd7\x25\x70\xdc\xdd\x78\x7c\xe3\x88\x7a\xb2\xcd\x68\x46\x52"
#define TEST9_256 \
"\x3e\x74\x03\x71\xc8\x10\xc2\xb9\x9f\xc0\x4e\x80\x49\x07\xef\x7c" \
"\xf2\x6b\xe2\x8b\x57\xcb\x58\xa3\xe2\xf3\xc0\x07\x16\x6e\x49\xc1" \
"\x2e\x9b\xa3\x4c\x01\x04\x06\x91\x29\xea\x76\x15\x64\x25\x45\x70" \
"\x3a\x2b\xd9\x01\xe1\x6e\xb0\xe0\x5d\xeb\xa0\x14\xeb\xff\x64\x06" \
"\xa0\x7d\x54\x36\x4e\xff\x74\x2d\xa7\x79\xb0\xb3"
#define TEST10_256 \
"\x83\x26\x75\x4e\x22\x77\x37\x2f\x4f\xc1\x2b\x20\x52\x7a\xfe\xf0" \
"\x4d\x8a\x05\x69\x71\xb1\x1a\xd5\x71\x23\xa7\xc1\x37\x76\x00\x00" \
"\xd7\xbe\xf6\xf3\xc1\xf7\xa9\x08\x3a\xa3\x9d\x81\x0d\xb3\x10\x77" \
"\x7d\xab\x8b\x1e\x7f\x02\xb8\x4a\x26\xc7\x73\x32\x5f\x8b\x23\x74" \
"\xde\x7a\x4b\x5a\x58\xcb\x5c\x5c\xf3\x5b\xce\xe6\xfb\x94\x6e\x5b" \
"\xd6\x94\xfa\x59\x3a\x8b\xeb\x3f\x9d\x65\x92\xec\xed\xaa\x66\xca" \
"\x82\xa2\x9d\x0c\x51\xbc\xf9\x33\x62\x30\xe5\xd7\x84\xe4\xc0\xa4" \
"\x3f\x8d\x79\xa3\x0a\x16\x5c\xba\xbe\x45\x2b\x77\x4b\x9c\x71\x09" \
"\xa9\x7d\x13\x8f\x12\x92\x28\x96\x6f\x6c\x0a\xdc\x10\x6a\xad\x5a" \
"\x9f\xdd\x30\x82\x57\x69\xb2\xc6\x71\xaf\x67\x59\xdf\x28\xeb\x39" \
"\x3d\x54\xd6"
#define length(x) (sizeof(x)-1)
// test vectors from rfc-4634
START_TEST(test_sha256)
{
struct {
const char* test;
int length;
int repeatcount;
int extrabits;
int numberExtrabits;
const char* result;
} tests[] = {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0, "BA7816BF8F01CFEA4141"
"40DE5DAE2223B00361A396177A9CB410FF61F20015AD" },
/* 2 */ { TEST2_1, length(TEST2_1), 1, 0, 0, "248D6A61D20638B8"
"E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1" },
/* 3 */ { TEST3, length(TEST3), 1000000, 0, 0, "CDC76E5C9914FB92"
"81A1C7E284D73E67F1809A48A497200E046D39CCC7112CD0" },
/* 4 */ { TEST4, length(TEST4), 10, 0, 0, "594847328451BDFA"
"85056225462CC1D867D877FB388DF0CE35F25AB5562BFBB5" },
/* 5 */ { "", 0, 0, 0x68, 5, "D6D3E02A31A84A8CAA9718ED6C2057BE"
"09DB45E7823EB5079CE7A573A3760F95" },
/* 6 */ { "\x19", 1, 1, 0, 0, "68AA2E2EE5DFF96E3355E6C7EE373E3D"
"6A4E17F75F9518D843709C0C9BC3E3D4" },
/* 7 */ { TEST7_256, length(TEST7_256), 1, 0x60, 3, "77EC1DC8"
"9C821FF2A1279089FA091B35B8CD960BCAF7DE01C6A7680756BEB972" },
/* 8 */ { TEST8_256, length(TEST8_256), 1, 0, 0, "175EE69B02BA"
"9B58E2B0A5FD13819CEA573F3940A94F825128CF4209BEABB4E8" },
/* 9 */ { TEST9_256, length(TEST9_256), 1, 0xA0, 3, "3E9AD646"
"8BBBAD2AC3C2CDC292E018BA5FD70B960CF1679777FCE708FDB066E9" },
/* 10 */ { TEST10_256, length(TEST10_256), 1, 0, 0, "97DBCA7D"
"F46D62C8A422C941DD7E835B8AD3361763F7E9B2D95F4F0DA6E1CCBC" },
};
for (int i = 0; i < 10; i++) {
SHA256_CTX ctx;
uint8_t digest[SHA256_DIGEST_LENGTH];
sha256_Init(&ctx);
/* extra bits are not supported */
if (tests[i].numberExtrabits)
continue;
for (int j = 0; j < tests[i].repeatcount; j++) {
sha256_Update(&ctx, (const uint8_t*) tests[i].test, tests[i].length);
}
sha256_Final(&ctx, digest);
ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA256_DIGEST_LENGTH);
}
}
END_TEST
#define TEST7_512 \
"\x08\xec\xb5\x2e\xba\xe1\xf7\x42\x2d\xb6\x2b\xcd\x54\x26\x70"
#define TEST8_512 \
"\x8d\x4e\x3c\x0e\x38\x89\x19\x14\x91\x81\x6e\x9d\x98\xbf\xf0\xa0"
#define TEST9_512 \
"\x3a\xdd\xec\x85\x59\x32\x16\xd1\x61\x9a\xa0\x2d\x97\x56\x97\x0b" \
"\xfc\x70\xac\xe2\x74\x4f\x7c\x6b\x27\x88\x15\x10\x28\xf7\xb6\xa2" \
"\x55\x0f\xd7\x4a\x7e\x6e\x69\xc2\xc9\xb4\x5f\xc4\x54\x96\x6d\xc3" \
"\x1d\x2e\x10\xda\x1f\x95\xce\x02\xbe\xb4\xbf\x87\x65\x57\x4c\xbd" \
"\x6e\x83\x37\xef\x42\x0a\xdc\x98\xc1\x5c\xb6\xd5\xe4\xa0\x24\x1b" \
"\xa0\x04\x6d\x25\x0e\x51\x02\x31\xca\xc2\x04\x6c\x99\x16\x06\xab" \
"\x4e\xe4\x14\x5b\xee\x2f\xf4\xbb\x12\x3a\xab\x49\x8d\x9d\x44\x79" \
"\x4f\x99\xcc\xad\x89\xa9\xa1\x62\x12\x59\xed\xa7\x0a\x5b\x6d\xd4" \
"\xbd\xd8\x77\x78\xc9\x04\x3b\x93\x84\xf5\x49\x06"
#define TEST10_512 \
"\xa5\x5f\x20\xc4\x11\xaa\xd1\x32\x80\x7a\x50\x2d\x65\x82\x4e\x31" \
"\xa2\x30\x54\x32\xaa\x3d\x06\xd3\xe2\x82\xa8\xd8\x4e\x0d\xe1\xde" \
"\x69\x74\xbf\x49\x54\x69\xfc\x7f\x33\x8f\x80\x54\xd5\x8c\x26\xc4" \
"\x93\x60\xc3\xe8\x7a\xf5\x65\x23\xac\xf6\xd8\x9d\x03\xe5\x6f\xf2" \
"\xf8\x68\x00\x2b\xc3\xe4\x31\xed\xc4\x4d\xf2\xf0\x22\x3d\x4b\xb3" \
"\xb2\x43\x58\x6e\x1a\x7d\x92\x49\x36\x69\x4f\xcb\xba\xf8\x8d\x95" \
"\x19\xe4\xeb\x50\xa6\x44\xf8\xe4\xf9\x5e\xb0\xea\x95\xbc\x44\x65" \
"\xc8\x82\x1a\xac\xd2\xfe\x15\xab\x49\x81\x16\x4b\xbb\x6d\xc3\x2f" \
"\x96\x90\x87\xa1\x45\xb0\xd9\xcc\x9c\x67\xc2\x2b\x76\x32\x99\x41" \
"\x9c\xc4\x12\x8b\xe9\xa0\x77\xb3\xac\xe6\x34\x06\x4e\x6d\x99\x28" \
"\x35\x13\xdc\x06\xe7\x51\x5d\x0d\x73\x13\x2e\x9a\x0d\xc6\xd3\xb1" \
"\xf8\xb2\x46\xf1\xa9\x8a\x3f\xc7\x29\x41\xb1\xe3\xbb\x20\x98\xe8" \
"\xbf\x16\xf2\x68\xd6\x4f\x0b\x0f\x47\x07\xfe\x1e\xa1\xa1\x79\x1b" \
"\xa2\xf3\xc0\xc7\x58\xe5\xf5\x51\x86\x3a\x96\xc9\x49\xad\x47\xd7" \
"\xfb\x40\xd2"
// test vectors from rfc-4634
START_TEST(test_sha512)
{
struct {
const char* test;
int length;
int repeatcount;
int extrabits;
int numberExtrabits;
const char* result;
} tests[] = {
/* 1 */ { TEST1, length(TEST1), 1, 0, 0,
"DDAF35A193617ABACC417349AE20413112E6FA4E89A97EA2"
"0A9EEEE64B55D39A2192992A274FC1A836BA3C23A3FEEBBD"
"454D4423643CE80E2A9AC94FA54CA49F" },
/* 2 */ { TEST2_2, length(TEST2_2), 1, 0, 0,
"8E959B75DAE313DA8CF4F72814FC143F8F7779C6EB9F7FA1"
"7299AEADB6889018501D289E4900F7E4331B99DEC4B5433A"
"C7D329EEB6DD26545E96E55B874BE909" },
/* 3 */ { TEST3, length(TEST3), 1000000, 0, 0,
"E718483D0CE769644E2E42C7BC15B4638E1F98B13B204428"
"5632A803AFA973EBDE0FF244877EA60A4CB0432CE577C31B"
"EB009C5C2C49AA2E4EADB217AD8CC09B" },
/* 4 */ { TEST4, length(TEST4), 10, 0, 0,
"89D05BA632C699C31231DED4FFC127D5A894DAD412C0E024"
"DB872D1ABD2BA8141A0F85072A9BE1E2AA04CF33C765CB51"
"0813A39CD5A84C4ACAA64D3F3FB7BAE9" },
/* 5 */ { "", 0, 0, 0xB0, 5,
"D4EE29A9E90985446B913CF1D1376C836F4BE2C1CF3CADA0"
"720A6BF4857D886A7ECB3C4E4C0FA8C7F95214E41DC1B0D2"
"1B22A84CC03BF8CE4845F34DD5BDBAD4" },
/* 6 */ { "\xD0", 1, 1, 0, 0,
"9992202938E882E73E20F6B69E68A0A7149090423D93C81B"
"AB3F21678D4ACEEEE50E4E8CAFADA4C85A54EA8306826C4A"
"D6E74CECE9631BFA8A549B4AB3FBBA15" },
/* 7 */ { TEST7_512, length(TEST7_512), 1, 0x80, 3,
"ED8DC78E8B01B69750053DBB7A0A9EDA0FB9E9D292B1ED71"
"5E80A7FE290A4E16664FD913E85854400C5AF05E6DAD316B"
"7359B43E64F8BEC3C1F237119986BBB6" },
/* 8 */ { TEST8_512, length(TEST8_512), 1, 0, 0,
"CB0B67A4B8712CD73C9AABC0B199E9269B20844AFB75ACBD"
"D1C153C9828924C3DDEDAAFE669C5FDD0BC66F630F677398"
"8213EB1B16F517AD0DE4B2F0C95C90F8" },
/* 9 */ { TEST9_512, length(TEST9_512), 1, 0x80, 3,
"32BA76FC30EAA0208AEB50FFB5AF1864FDBF17902A4DC0A6"
"82C61FCEA6D92B783267B21080301837F59DE79C6B337DB2"
"526F8A0A510E5E53CAFED4355FE7C2F1" },
/* 10 */ { TEST10_512, length(TEST10_512), 1, 0, 0,
"C665BEFB36DA189D78822D10528CBF3B12B3EEF726039909"
"C1A16A270D48719377966B957A878E720584779A62825C18"
"DA26415E49A7176A894E7510FD1451F5" }
};
for (int i = 0; i < 10; i++) {
SHA512_CTX ctx;
uint8_t digest[SHA512_DIGEST_LENGTH];
sha512_Init(&ctx);
/* extra bits are not supported */
if (tests[i].numberExtrabits)
continue;
for (int j = 0; j < tests[i].repeatcount; j++) {
sha512_Update(&ctx, (const uint8_t*) tests[i].test, tests[i].length);
}
sha512_Final(&ctx, digest);
ck_assert_mem_eq(digest, fromhex(tests[i].result), SHA512_DIGEST_LENGTH);
}
}
END_TEST
// test vectors from https://stackoverflow.com/questions/5130513/pbkdf2-hmac-sha2-test-vectors
START_TEST(test_pbkdf2_hmac_sha256)
{
@ -2143,6 +2352,14 @@ Suite *test_suite(void)
tcase_add_test(tc, test_aes);
suite_add_tcase(s, tc);
tc = tcase_create("sha256");
tcase_add_test(tc, test_sha256);
suite_add_tcase(s, tc);
tc = tcase_create("sha512");
tcase_add_test(tc, test_sha512);
suite_add_tcase(s, tc);
tc = tcase_create("pbkdf2");
tcase_add_test(tc, test_pbkdf2_hmac_sha256);
tcase_add_test(tc, test_pbkdf2_hmac_sha512);