diff --git a/bip39.c b/bip39.c index 1fc8c61d5c..42ef82798e 100644 --- a/bip39.c +++ b/bip39.c @@ -11,11 +11,11 @@ const char *mnemonic_generate(int strength) { - int i; - static uint32_t data[16]; if (strength % 32 || strength < 128 || strength > 256) { return 0; } + int i; + static uint32_t data[16]; for (i = 0; i < 16; i++) { data[i] = random32(); } @@ -24,23 +24,21 @@ const char *mnemonic_generate(int strength) const char *mnemonic_from_data(const uint8_t *data, int len) { - int i, j; - static uint8_t hash[32]; - static char bits[256 + 8]; - static char mnemo[24 * 10]; - if (len % 4 || len < 16 || len > 32) { return 0; } - sha256_Raw((const uint8_t *)data, len, hash); - + int i, j; + char bits[256 + 8]; for (i = 0; i < len; i++) { for (j = 0; j < 8; j++) { bits[8 * i + j] = (data[i] & (1 << (7 - j))) > 0; } } + uint8_t hash[32]; + sha256_Raw((const uint8_t *)data, len, hash); + char hlen = len / 4; for (i = 0; i < hlen; i++) { char c = (hash[0] & (1 << (7 - i))) > 0; @@ -48,6 +46,7 @@ const char *mnemonic_from_data(const uint8_t *data, int len) } int mlen = len * 3 / 4; + static char mnemo[24 * 10]; char *p = mnemo; for (i = 0; i < mlen; i++) { @@ -64,14 +63,21 @@ const char *mnemonic_from_data(const uint8_t *data, int len) return mnemo; } -void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8]) +int mnemonic_check(const char *mnemonic) +{ + // TODO: add proper check + (void)mnemonic; + return 1; +} + +void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total)) { static uint8_t salt[8 + 256 + 4]; int saltlen = strlen(passphrase); memcpy(salt, "mnemonic", 8); memcpy(salt + 8, passphrase, saltlen); saltlen += 8; - pbkdf2((const uint8_t *)mnemonic, strlen(mnemonic), salt, saltlen, PBKDF2_ROUNDS, seed, 512 / 8); + pbkdf2((const uint8_t *)mnemonic, strlen(mnemonic), salt, saltlen, PBKDF2_ROUNDS, seed, 512 / 8, progress_callback); } const char **mnemonic_wordlist(void) diff --git a/bip39.h b/bip39.h index b9cbcf4f1e..1f77c84962 100644 --- a/bip39.h +++ b/bip39.h @@ -7,7 +7,9 @@ const char *mnemonic_generate(int strength); // strength in bits const char *mnemonic_from_data(const uint8_t *data, int len); -void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8]); +int mnemonic_check(const char *mnemonic); + +void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total)); const char **mnemonic_wordlist(void); diff --git a/pbkdf2.c b/pbkdf2.c index 6001b1f1be..3e7a4f79c7 100644 --- a/pbkdf2.c +++ b/pbkdf2.c @@ -5,7 +5,7 @@ #define HMACFUNC hmac_sha512 #define HMACLEN (512/8) -void pbkdf2(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen) +void pbkdf2(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)) { uint32_t i, j, k; uint8_t f[HMACLEN], g[HMACLEN]; @@ -25,6 +25,9 @@ void pbkdf2(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32 for (k = 0; k < HMACLEN; k++) { f[k] ^= g[k]; } + if (progress_callback && j % 256 == 255) { + progress_callback(j + 1, iterations); + } } if (i == blocks - 1 && (keylen & (HMACLEN - 1))) { memcpy(key + HMACLEN * (i - 1), f, keylen & (HMACLEN - 1)); diff --git a/pbkdf2.h b/pbkdf2.h index 05121467f9..48526d472b 100644 --- a/pbkdf2.h +++ b/pbkdf2.h @@ -4,6 +4,6 @@ #include // salt needs to have 4 extra bytes available beyond saltlen -void pbkdf2(const uint8_t *pass, int passlen, uint8_t *salt, int saltlen, uint32_t iterations, uint8_t *key, int keylen); +void pbkdf2(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)); #endif diff --git a/tests.c b/tests.c index 9d92fead4b..ba2b4271da 100644 --- a/tests.c +++ b/tests.c @@ -345,19 +345,19 @@ START_TEST(test_pbkdf2) uint8_t k[64], s[64]; strcpy((char *)s, "salt"); - pbkdf2((uint8_t *)"password", 8, s, 4, 1, k, 64); + pbkdf2((uint8_t *)"password", 8, s, 4, 1, k, 64, 0); ck_assert_mem_eq(k, fromhex("867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce"), 64); strcpy((char *)s, "salt"); - pbkdf2((uint8_t *)"password", 8, s, 4, 2, k, 64); + pbkdf2((uint8_t *)"password", 8, s, 4, 2, k, 64, 0); ck_assert_mem_eq(k, fromhex("e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e"), 64); strcpy((char *)s, "salt"); - pbkdf2((uint8_t *)"password", 8, s, 4, 4096, k, 64); + pbkdf2((uint8_t *)"password", 8, s, 4, 4096, k, 64, 0); ck_assert_mem_eq(k, fromhex("d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5"), 64); strcpy((char *)s, "saltSALTsaltSALTsaltSALTsaltSALTsalt"); - pbkdf2((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k, 64); + pbkdf2((uint8_t *)"passwordPASSWORDpassword", 3*8, s, 9*4, 4096, k, 64, 0); ck_assert_mem_eq(k, fromhex("8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8"), 64); } END_TEST @@ -451,7 +451,7 @@ START_TEST(test_mnemonic) while (*a && *b && *c) { m = mnemonic_from_data(fromhex(*a), strlen(*a) / 2); ck_assert_str_eq(m, *b); - mnemonic_to_seed(m, "TREZOR", seed); + mnemonic_to_seed(m, "TREZOR", seed, 0); ck_assert_mem_eq(seed, fromhex(*c), strlen(*c) / 2); a += 3; b += 3; c += 3; }