mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 20:38:10 +00:00
commit
4d6d9fe8ba
6
bip39.c
6
bip39.c
@ -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
56
hmac.c
@ -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
2
hmac.h
@ -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
|
||||
|
80
pbkdf2.c
80
pbkdf2.c
@ -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));
|
||||
}
|
||||
|
16
pbkdf2.h
16
pbkdf2.h
@ -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;
|
||||
|
||||
|
365
sha2.c
365
sha2.c
@ -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;
|
||||
((uint8_t*)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);
|
||||
MEMSET_BZERO(((uint8_t*)context->buffer) + usedspace, SHA256_SHORT_BLOCK_LENGTH - usedspace);
|
||||
} else {
|
||||
if (usedspace < SHA256_BLOCK_LENGTH) {
|
||||
MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
|
||||
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, (sha2_word32*)(void*)context->buffer);
|
||||
sha256_Transform(context->state, context->buffer, context->state);
|
||||
|
||||
/* And set-up for the last transform: */
|
||||
MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
|
||||
}
|
||||
} else {
|
||||
/* Set-up for the last transform: */
|
||||
MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
|
||||
|
||||
/* Begin padding with a 1 bit: */
|
||||
*context->buffer = 0x80;
|
||||
}
|
||||
/* Set the bit count: */
|
||||
sha2_word64 *t = (sha2_word64 *)(void*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH];
|
||||
*t = context->bitcount;
|
||||
|
||||
/* Final transform: */
|
||||
sha256_Transform(context, (sha2_word32*)(void*)context->buffer);
|
||||
|
||||
#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];
|
||||
for (int j = 0; j < 14; j++) {
|
||||
REVERSE32(context->buffer[j],context->buffer[j]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH);
|
||||
#endif
|
||||
/* Set the bit count: */
|
||||
context->buffer[14] = context->bitcount >> 32;
|
||||
context->buffer[15] = context->bitcount & 0xffffffff;
|
||||
|
||||
/* Final transform: */
|
||||
sha256_Transform(context->state, context->buffer, context->state);
|
||||
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
/* Convert FROM host byte order */
|
||||
for (int j = 0; j < 8; j++) {
|
||||
REVERSE32(context->state[j],context->state[j]);
|
||||
}
|
||||
#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;
|
||||
((uint8_t*)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);
|
||||
MEMSET_BZERO(((uint8_t*)context->buffer) + usedspace, SHA512_SHORT_BLOCK_LENGTH - usedspace);
|
||||
} else {
|
||||
if (usedspace < SHA512_BLOCK_LENGTH) {
|
||||
MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
|
||||
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, (sha2_word64*)(void*)context->buffer);
|
||||
sha512_Transform(context->state, context->buffer, context->state);
|
||||
|
||||
/* And set-up for the last transform: */
|
||||
MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
|
||||
}
|
||||
} else {
|
||||
/* Prepare for final transform: */
|
||||
MEMSET_BZERO(context->buffer, SHA512_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 < 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++) {
|
||||
/* Convert FROM host byte order */
|
||||
for (int j = 0; j < 8; j++) {
|
||||
REVERSE64(context->state[j],context->state[j]);
|
||||
*d++ = 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
35
sha2.h
@ -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
217
tests.c
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user