optimize hashDRBG internal state

This commit is contained in:
John Safranek
2015-03-10 18:16:44 -07:00
parent ab874d70db
commit b02622d1d0

View File

@@ -148,10 +148,8 @@ enum {
typedef struct DRBG { typedef struct DRBG {
Sha256 sha;
word32 reseedCtr; word32 reseedCtr;
word32 lastBlock; word32 lastBlock;
byte digest[SHA256_DIGEST_SIZE];
byte V[DRBG_SEED_LEN]; byte V[DRBG_SEED_LEN];
byte C[DRBG_SEED_LEN]; byte C[DRBG_SEED_LEN];
byte matchCount; byte matchCount;
@@ -168,7 +166,10 @@ static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type,
int i; int i;
int len; int len;
word32 bits = (outSz * 8); /* reverse byte order */ word32 bits = (outSz * 8); /* reverse byte order */
Sha256 sha;
byte digest[SHA256_DIGEST_SIZE];
(void)drbg;
#ifdef LITTLE_ENDIAN_ORDER #ifdef LITTLE_ENDIAN_ORDER
bits = ByteReverseWord32(bits); bits = ByteReverseWord32(bits);
#endif #endif
@@ -177,40 +178,41 @@ static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type,
for (i = 0, ctr = 1; i < len; i++, ctr++) for (i = 0, ctr = 1; i < len; i++, ctr++)
{ {
if (wc_InitSha256(&drbg->sha) != 0) if (wc_InitSha256(&sha) != 0)
return DRBG_FAILURE; return DRBG_FAILURE;
if (wc_Sha256Update(&drbg->sha, &ctr, sizeof(ctr)) != 0) if (wc_Sha256Update(&sha, &ctr, sizeof(ctr)) != 0)
return DRBG_FAILURE; return DRBG_FAILURE;
if (wc_Sha256Update(&drbg->sha, (byte*)&bits, sizeof(bits)) != 0) if (wc_Sha256Update(&sha, (byte*)&bits, sizeof(bits)) != 0)
return DRBG_FAILURE; return DRBG_FAILURE;
/* churning V is the only string that doesn't have /* churning V is the only string that doesn't have
* the type added */ * the type added */
if (type != drbgInitV) if (type != drbgInitV)
if (wc_Sha256Update(&drbg->sha, &type, sizeof(type)) != 0) if (wc_Sha256Update(&sha, &type, sizeof(type)) != 0)
return DRBG_FAILURE; return DRBG_FAILURE;
if (wc_Sha256Update(&drbg->sha, inA, inASz) != 0) if (wc_Sha256Update(&sha, inA, inASz) != 0)
return DRBG_FAILURE; return DRBG_FAILURE;
if (inB != NULL && inBSz > 0) if (inB != NULL && inBSz > 0)
if (wc_Sha256Update(&drbg->sha, inB, inBSz) != 0) if (wc_Sha256Update(&sha, inB, inBSz) != 0)
return DRBG_FAILURE; return DRBG_FAILURE;
if (wc_Sha256Final(&drbg->sha, drbg->digest) != 0) if (wc_Sha256Final(&sha, digest) != 0)
return DRBG_FAILURE; return DRBG_FAILURE;
if (outSz > OUTPUT_BLOCK_LEN) { if (outSz > OUTPUT_BLOCK_LEN) {
XMEMCPY(out, drbg->digest, OUTPUT_BLOCK_LEN); XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
outSz -= OUTPUT_BLOCK_LEN; outSz -= OUTPUT_BLOCK_LEN;
out += OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN;
} }
else { else {
XMEMCPY(out, drbg->digest, outSz); XMEMCPY(out, digest, outSz);
} }
} }
ForceZero(digest, sizeof(digest));
return DRBG_SUCCESS; return DRBG_SUCCESS;
} }
@@ -259,6 +261,8 @@ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V)
int i; int i;
int len; int len;
word32 checkBlock; word32 checkBlock;
Sha256 sha;
byte digest[SHA256_DIGEST_SIZE];
/* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for
* the continuous test. */ * the continuous test. */
@@ -269,14 +273,14 @@ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V)
XMEMCPY(data, V, sizeof(data)); XMEMCPY(data, V, sizeof(data));
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
if (wc_InitSha256(&drbg->sha) != 0 || if (wc_InitSha256(&sha) != 0 ||
wc_Sha256Update(&drbg->sha, data, sizeof(data)) != 0 || wc_Sha256Update(&sha, data, sizeof(data)) != 0 ||
wc_Sha256Final(&drbg->sha, drbg->digest) != 0) { wc_Sha256Final(&sha, digest) != 0) {
return DRBG_FAILURE; return DRBG_FAILURE;
} }
XMEMCPY(&checkBlock, drbg->digest, sizeof(word32)); XMEMCPY(&checkBlock, digest, sizeof(word32));
if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) { if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) {
if (drbg->matchCount == 1) { if (drbg->matchCount == 1) {
return DRBG_CONT_FAILURE; return DRBG_CONT_FAILURE;
@@ -294,13 +298,13 @@ static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V)
} }
if (outSz >= OUTPUT_BLOCK_LEN) { if (outSz >= OUTPUT_BLOCK_LEN) {
XMEMCPY(out, drbg->digest, OUTPUT_BLOCK_LEN); XMEMCPY(out, digest, OUTPUT_BLOCK_LEN);
outSz -= OUTPUT_BLOCK_LEN; outSz -= OUTPUT_BLOCK_LEN;
out += OUTPUT_BLOCK_LEN; out += OUTPUT_BLOCK_LEN;
array_add_one(data, DRBG_SEED_LEN); array_add_one(data, DRBG_SEED_LEN);
} }
else if (out != NULL && outSz != 0) { else if (out != NULL && outSz != 0) {
XMEMCPY(out, drbg->digest, outSz); XMEMCPY(out, digest, outSz);
outSz = 0; outSz = 0;
} }
} }
@@ -337,6 +341,8 @@ static INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen)
static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz) static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz)
{ {
int ret = DRBG_NEED_RESEED; int ret = DRBG_NEED_RESEED;
Sha256 sha;
byte digest[SHA256_DIGEST_SIZE];
if (drbg->reseedCtr != RESEED_INTERVAL) { if (drbg->reseedCtr != RESEED_INTERVAL) {
byte type = drbgGenerateH; byte type = drbgGenerateH;
@@ -344,16 +350,15 @@ static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz)
ret = Hash_gen(drbg, out, outSz, drbg->V); ret = Hash_gen(drbg, out, outSz, drbg->V);
if (ret == DRBG_SUCCESS) { if (ret == DRBG_SUCCESS) {
if (wc_InitSha256(&drbg->sha) != 0 || if (wc_InitSha256(&sha) != 0 ||
wc_Sha256Update(&drbg->sha, &type, sizeof(type)) != 0 || wc_Sha256Update(&sha, &type, sizeof(type)) != 0 ||
wc_Sha256Update(&drbg->sha, drbg->V, sizeof(drbg->V)) != 0 || wc_Sha256Update(&sha, drbg->V, sizeof(drbg->V)) != 0 ||
wc_Sha256Final(&drbg->sha, drbg->digest) != 0) { wc_Sha256Final(&sha, digest) != 0) {
ret = DRBG_FAILURE; ret = DRBG_FAILURE;
} }
else { else {
array_add(drbg->V, sizeof(drbg->V), array_add(drbg->V, sizeof(drbg->V), digest, sizeof(digest));
drbg->digest, sizeof(drbg->digest));
array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C)); array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C));
#ifdef LITTLE_ENDIAN_ORDER #ifdef LITTLE_ENDIAN_ORDER
reseedCtr = ByteReverseWord32(reseedCtr); reseedCtr = ByteReverseWord32(reseedCtr);
@@ -365,6 +370,7 @@ static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz)
drbg->reseedCtr++; drbg->reseedCtr++;
} }
} }
ForceZero(digest, sizeof(digest));
return ret; return ret;
} }