// passphrase must be at most 256 characters or code may crash void mnemonic_to_seed(const char *mnemonic, const char *passphrase, uint8_t seed[512 / 8], void (*progress_callback)(uint32_t current, uint32_t total)) { int passphraselen = strlen(passphrase); #if USE_BIP39_CACHE int mnemoniclen = strlen(mnemonic); // check cache if (mnemoniclen < 256 && passphraselen < 64) { int i; for (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; // found the correct entry memcpy(seed, bip39_cache[i].seed, 512 / 8); return; } } #endif uint8_t salt[8 + 256 + 4]; 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); #if USE_BIP39_CACHE // store to cache if (mnemoniclen < 256 && passphraselen < 64) { bip39_cache[bip39_cache_index].set = true; strcpy(bip39_cache[bip39_cache_index].mnemonic, mnemonic); strcpy(bip39_cache[bip39_cache_index].passphrase, passphrase); memcpy(bip39_cache[bip39_cache_index].seed, seed, 512 / 8); bip39_cache_index = (bip39_cache_index + 1) % BIP39_CACHE_SIZE; } #endif }
bool storage_getRootNode(HDNode *node) { // root node is properly cached if (sessionRootNodeCached) { memcpy(node, &sessionRootNode, sizeof(HDNode)); return true; } // if storage has node, decrypt and use it if (storage.has_node) { if (!protectPassphrase()) { return false; } if (hdnode_from_xprv(storage.node.depth, storage.node.fingerprint, storage.node.child_num, storage.node.chain_code.bytes, storage.node.private_key.bytes, &sessionRootNode) == 0) { return false; } if (storage.has_passphrase_protection && storage.passphrase_protection && strlen(sessionPassphrase)) { // decrypt hd node uint8_t secret[64]; uint8_t salt[12]; memcpy(salt, "TREZORHD", 8); layoutProgressSwipe("Waking up", 0); pbkdf2_hmac_sha512((const uint8_t *)sessionPassphrase, strlen(sessionPassphrase), salt, 8, BIP39_PBKDF2_ROUNDS, secret, 64, get_root_node_callback); aes_decrypt_ctx ctx; aes_decrypt_key256(secret, &ctx); aes_cbc_decrypt(sessionRootNode.chain_code, sessionRootNode.chain_code, 32, secret + 32, &ctx); aes_cbc_decrypt(sessionRootNode.private_key, sessionRootNode.private_key, 32, secret + 32, &ctx); } memcpy(node, &sessionRootNode, sizeof(HDNode)); sessionRootNodeCached = true; return true; } // if storage has mnemonic, convert it to node and use it if (storage.has_mnemonic) { if (!protectPassphrase()) { return false; } uint8_t seed[64]; layoutProgressSwipe("Waking up", 0); mnemonic_to_seed(storage.mnemonic, sessionPassphrase, seed, get_root_node_callback); // BIP-0039 if (hdnode_from_seed(seed, sizeof(seed), &sessionRootNode) == 0) { return false; } memcpy(node, &sessionRootNode, sizeof(HDNode)); sessionRootNodeCached = true; return true; } return false; }
int main() { uint8_t check[64]; int i; /* test pbkdf2 */ for (i = 0; i < tablenum; i++) { pbkdf2_hmac_sha512(check, 64, (uint8_t*)table[i].passwd, strlen(table[i].passwd), (uint8_t*)table[i].salt, strlen(table[i].salt), table[i].c); if (memcmp(check, table[i].dk, 64) != 0) { printf("test nr. %d failed\n", i+1); printvec("is", check, 64); printvec("should", table[i].dk, 64); return 1; } } return 0; }
/* * storage_get_root_node() - Returns root node of device * * INPUT * - node: where to put the node that is found * OUTPUT * true/false whether root node was found */ bool storage_get_root_node(HDNode *node) { // root node is properly cached if(sessionRootNodeCached) { memcpy(node, &sessionRootNode, sizeof(HDNode)); return true; } // if storage has node, decrypt and use it if(shadow_config.storage.has_node) { if(!passphrase_protect()) { return false; } layout_loading(); if(hdnode_from_xprv(shadow_config.storage.node.depth, shadow_config.storage.node.fingerprint, shadow_config.storage.node.child_num, shadow_config.storage.node.chain_code.bytes, shadow_config.storage.node.private_key.bytes, &sessionRootNode) == 0) { return false; } if(shadow_config.storage.has_passphrase_protection && shadow_config.storage.passphrase_protection && strlen(sessionPassphrase)) { // decrypt hd node uint8_t secret[64]; /* Length of salt + 4 bytes are needed as workspace by pbkdf2_hmac_sha512 */ uint8_t salt[strlen(PBKDF2_HMAC_SHA512_SALT) + 4]; memcpy((char *)salt, PBKDF2_HMAC_SHA512_SALT, strlen(PBKDF2_HMAC_SHA512_SALT)); animating_progress_handler(); pbkdf2_hmac_sha512((const uint8_t *)sessionPassphrase, strlen(sessionPassphrase), salt, strlen(PBKDF2_HMAC_SHA512_SALT), BIP39_PBKDF2_ROUNDS, secret, 64, get_root_node_callback); aes_decrypt_ctx ctx; aes_decrypt_key256(secret, &ctx); aes_cbc_decrypt(sessionRootNode.chain_code, sessionRootNode.chain_code, 32, secret + 32, &ctx); aes_cbc_decrypt(sessionRootNode.private_key, sessionRootNode.private_key, 32, secret + 32, &ctx); } memcpy(node, &sessionRootNode, sizeof(HDNode)); sessionRootNodeCached = true; return true; } // if storage has mnemonic, convert it to node and use it if(shadow_config.storage.has_mnemonic) { if(!passphrase_protect()) { return false; } if(storage_get_root_node_cache(node)) { return true; } layout_loading(); uint8_t seed[64]; animating_progress_handler(); mnemonic_to_seed(shadow_config.storage.mnemonic, sessionPassphrase, seed, get_root_node_callback); // BIP-0039 if(hdnode_from_seed(seed, sizeof(seed), &sessionRootNode) == 0) { return false; } storage_set_root_node_cache(&sessionRootNode); memcpy(node, &sessionRootNode, sizeof(HDNode)); sessionRootNodeCached = true; return true; } return false; }