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

simplify pbkdf2 (support only klen == hashlen) and split it

This commit is contained in:
Pavol Rusnak 2016-05-01 00:50:12 +02:00
parent b8ec5567ba
commit 242a5de275
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
4 changed files with 117 additions and 83 deletions

18
bip39.c
View File

@ -168,8 +168,7 @@ void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed
int mnemoniclen = strlen(mnemonic);
// check cache
if (mnemoniclen < 256 && passphraselen < 64) {
int i;
for (i = 0; i < BIP39_CACHE_SIZE; i++) {
for (int i = 0; i < BIP39_CACHE_SIZE; i++) {
if (!bip39_cache[i].set) continue;
if (strcmp(bip39_cache[i].mnemonic, mnemonic) != 0) continue;
if (strcmp(bip39_cache[i].passphrase, passphrase) != 0) continue;
@ -179,10 +178,21 @@ void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed
}
}
#endif
uint8_t salt[8 + 256 + 4];
uint8_t salt[8 + 256];
memcpy(salt, "mnemonic", 8);
memcpy(salt + 8, passphrase, passphraselen);
pbkdf2_hmac_sha512((const uint8_t *)mnemonic, strlen(mnemonic), salt, passphraselen + 8, BIP39_PBKDF2_ROUNDS, seed, 512 / 8, progress_callback);
PBKDF2_HMAC_SHA512_CTX pctx;
pbkdf2_hmac_sha512_Init(&pctx, (const uint8_t *)mnemonic, strlen(mnemonic), salt, passphraselen + 8);
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);
if (progress_callback) {
progress_callback((i + 1) * BIP39_PBKDF2_ROUNDS / 8, BIP39_PBKDF2_ROUNDS);
}
}
pbkdf2_hmac_sha512_Final(&pctx, seed);
#if USE_BIP39_CACHE
// store to cache
if (mnemoniclen < 256 && passphraselen < 64) {

136
pbkdf2.c
View File

@ -26,78 +26,78 @@
#include "hmac.h"
#include "macros.h"
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen, void (*progress_callback)(uint32_t current, uint32_t total))
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, uint8_t *salt, int saltlen)
{
const uint32_t HMACLEN = 256/8;
uint8_t f[HMACLEN], g[HMACLEN];
uint32_t blocks = keylen / HMACLEN;
if (keylen & (HMACLEN - 1)) {
blocks++;
}
for (uint32_t i = 1; i <= blocks; i++) {
HMAC_SHA256_CTX hctx;
hmac_sha256_Init(&hctx, pass, passlen);
hmac_sha256_Update(&hctx, salt, saltlen);
uint32_t ii = ((i & 0xFF000000) >> 24) | ((i & 0x00FF0000) >> 8) | ((i & 0x0000FF00) << 8) | ((i & 0x000000FF) << 24);
hmac_sha256_Update(&hctx, (const uint8_t *)&ii, sizeof(uint32_t));
hmac_sha256_Final(&hctx, g);
memcpy(f, g, HMACLEN);
if (progress_callback) {
progress_callback(0, iterations);
}
for (uint32_t j = 1; j < iterations; j++) {
hmac_sha256(pass, passlen, g, HMACLEN, g);
for (uint32_t k = 0; k < HMACLEN; k++) {
f[k] ^= g[k];
}
if (progress_callback && (j % 256 == 255)) {
progress_callback(j + 1, iterations);
}
}
if (i == blocks && (keylen & (HMACLEN - 1))) {
memcpy(key + HMACLEN * (i - 1), f, keylen & (HMACLEN - 1));
} else {
memcpy(key + HMACLEN * (i - 1), f, HMACLEN);
}
}
MEMSET_BZERO(f, sizeof(f));
MEMSET_BZERO(g, sizeof(g));
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);
memcpy(pctx->f, pctx->g, SHA256_DIGEST_LENGTH);
pctx->pass = pass;
pctx->passlen = passlen;
pctx->first = 1;
}
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen, void (*progress_callback)(uint32_t current, uint32_t total))
void pbkdf2_hmac_sha256_Update(PBKDF2_HMAC_SHA256_CTX *pctx, uint32_t iterations)
{
const uint32_t HMACLEN = 512/8;
uint8_t f[HMACLEN], g[HMACLEN];
uint32_t blocks = keylen / HMACLEN;
if (keylen & (HMACLEN - 1)) {
blocks++;
}
for (uint32_t i = 1; i <= blocks; i++) {
HMAC_SHA512_CTX hctx;
hmac_sha512_Init(&hctx, pass, passlen);
hmac_sha512_Update(&hctx, salt, saltlen);
uint32_t ii = ((i & 0xFF000000) >> 24) | ((i & 0x00FF0000) >> 8) | ((i & 0x0000FF00) << 8) | ((i & 0x000000FF) << 24);
hmac_sha512_Update(&hctx, (const uint8_t *)&ii, sizeof(uint32_t));
hmac_sha512_Final(&hctx, g);
memcpy(f, g, HMACLEN);
if (progress_callback) {
progress_callback(0, iterations);
}
for (uint32_t j = 1; j < iterations; j++) {
hmac_sha512(pass, passlen, g, HMACLEN, g);
for (uint32_t k = 0; k < HMACLEN; k++) {
f[k] ^= g[k];
}
if (progress_callback && (j % 256 == 255)) {
progress_callback(j + 1, iterations);
}
}
if (i == blocks && (keylen & (HMACLEN - 1))) {
memcpy(key + HMACLEN * (i - 1), f, keylen & (HMACLEN - 1));
} else {
memcpy(key + HMACLEN * (i - 1), f, HMACLEN);
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++) {
pctx->f[j] ^= pctx->g[j];
}
}
MEMSET_BZERO(f, sizeof(f));
MEMSET_BZERO(g, sizeof(g));
pctx->first = 0;
}
void pbkdf2_hmac_sha256_Final(PBKDF2_HMAC_SHA256_CTX *pctx, uint8_t *key)
{
memcpy(key, pctx->f, SHA256_DIGEST_LENGTH);
MEMSET_BZERO(pctx, sizeof(PBKDF2_HMAC_SHA256_CTX));
}
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key)
{
PBKDF2_HMAC_SHA256_CTX pctx;
pbkdf2_hmac_sha256_Init(&pctx, pass, passlen, salt, saltlen);
pbkdf2_hmac_sha256_Update(&pctx, iterations);
pbkdf2_hmac_sha256_Final(&pctx, key);
}
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, 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);
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++) {
pctx->f[j] ^= pctx->g[j];
}
}
pctx->first = 0;
}
void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key)
{
memcpy(key, pctx->f, SHA512_DIGEST_LENGTH);
MEMSET_BZERO(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX));
}
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key)
{
PBKDF2_HMAC_SHA512_CTX pctx;
pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen);
pbkdf2_hmac_sha512_Update(&pctx, iterations);
pbkdf2_hmac_sha512_Final(&pctx, key);
}

View File

@ -25,8 +25,32 @@
#define __PBKDF2_H__
#include <stdint.h>
#include "sha2.h"
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen, void (*progress_callback)(uint32_t current, uint32_t total));
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen, void (*progress_callback)(uint32_t current, uint32_t total));
typedef struct _PBKDF2_HMAC_SHA256_CTX {
uint8_t f[SHA256_DIGEST_LENGTH];
uint8_t g[SHA256_DIGEST_LENGTH];
const uint8_t *pass;
int passlen;
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;
char first;
} PBKDF2_HMAC_SHA512_CTX;
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass, int passlen, uint8_t *salt, int saltlen);
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);
void pbkdf2_hmac_sha256(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key);
void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass, int passlen, uint8_t *salt, int saltlen);
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);
void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key);
#endif

18
tests.c
View File

@ -1169,20 +1169,20 @@ START_TEST(test_pbkdf2_hmac_sha256)
uint8_t k[40], s[40];
strcpy((char *)s, "salt");
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 1, k, 32, 0);
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 1, k);
ck_assert_mem_eq(k, fromhex("120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b"), 32);
strcpy((char *)s, "salt");
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 2, k, 32, 0);
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 2, k);
ck_assert_mem_eq(k, fromhex("ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43"), 32);
strcpy((char *)s, "salt");
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 4096, k, 32, 0);
pbkdf2_hmac_sha256((uint8_t *)"password", 8, s, 4, 4096, k);
ck_assert_mem_eq(k, fromhex("c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a"), 32);
strcpy((char *)s, "saltSALTsaltSALTsaltSALTsaltSALTsalt");
pbkdf2_hmac_sha256((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k, 40, 0);
ck_assert_mem_eq(k, fromhex("348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9"), 40);
pbkdf2_hmac_sha256((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k);
ck_assert_mem_eq(k, fromhex("348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1"), 32);
}
END_TEST
@ -1192,19 +1192,19 @@ START_TEST(test_pbkdf2_hmac_sha512)
uint8_t k[64], s[40];
strcpy((char *)s, "salt");
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 1, k, 64, 0);
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 1, k);
ck_assert_mem_eq(k, fromhex("867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce"), 64);
strcpy((char *)s, "salt");
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 2, k, 64, 0);
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 2, k);
ck_assert_mem_eq(k, fromhex("e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e"), 64);
strcpy((char *)s, "salt");
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 4096, k, 64, 0);
pbkdf2_hmac_sha512((uint8_t *)"password", 8, s, 4, 4096, k);
ck_assert_mem_eq(k, fromhex("d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5"), 64);
strcpy((char *)s, "saltSALTsaltSALTsaltSALTsaltSALTsalt");
pbkdf2_hmac_sha512((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k, 64, 0);
pbkdf2_hmac_sha512((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k);
ck_assert_mem_eq(k, fromhex("8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8"), 64);
}
END_TEST