Added curve type to HD node.

Create a different root node for every curve type to separate the key
space.
pull/25/head
Jochen Hoenicke 8 years ago
parent d8aeb63854
commit 56238e63fc

@ -282,7 +282,7 @@ uint8_t *cryptoHDNodePathToPubkey(const HDNodePathType *hdnodepath)
{
if (!hdnodepath->node.has_public_key || hdnodepath->node.public_key.size != 33) return 0;
static HDNode node;
if (hdnode_from_xpub(hdnodepath->node.depth, hdnodepath->node.fingerprint, hdnodepath->node.child_num, hdnodepath->node.chain_code.bytes, hdnodepath->node.public_key.bytes, &node) == 0) {
if (hdnode_from_xpub(hdnodepath->node.depth, hdnodepath->node.fingerprint, hdnodepath->node.child_num, hdnodepath->node.chain_code.bytes, hdnodepath->node.public_key.bytes, SECP256K1_NAME, &node) == 0) {
return 0;
}
layoutProgressUpdate(true);

@ -93,10 +93,10 @@ const CoinType *fsm_getCoin(const char *name)
return coin;
}
const HDNode *fsm_getDerivedNode(uint32_t *address_n, size_t address_n_count)
const HDNode *fsm_getDerivedNode(const char *curve, uint32_t *address_n, size_t address_n_count)
{
static HDNode node;
if (!storage_getRootNode(&node)) {
if (!storage_getRootNode(&node, curve)) {
fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized or passphrase request cancelled");
layoutHome();
return 0;
@ -292,20 +292,16 @@ void fsm_msgGetPublicKey(GetPublicKey *msg)
return;
}
const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
const char *curve = SECP256K1_NAME;
if (msg->has_ecdsa_curve_name) {
curve = msg->ecdsa_curve_name;
}
const HDNode *node = fsm_getDerivedNode(curve, msg->address_n, msg->address_n_count);
if (!node) return;
uint8_t public_key[33]; // copy public key to temporary buffer
memcpy(public_key, node->public_key, sizeof(public_key));
if (msg->has_ecdsa_curve_name) {
const ecdsa_curve *curve = get_curve_by_name(msg->ecdsa_curve_name);
if (curve) {
// correct public key (since fsm_getDerivedNode uses secp256k1 curve)
ecdsa_get_public_key33(curve, node->private_key, public_key);
}
}
if (msg->has_show_display && msg->show_display) {
layoutPublicKey(public_key);
if (!protectButton(ButtonRequestType_ButtonRequest_PublicKey, true)) {
@ -401,7 +397,7 @@ void fsm_msgSignTx(SignTx *msg)
const CoinType *coin = fsm_getCoin(msg->coin_name);
if (!coin) return;
const HDNode *node = fsm_getDerivedNode(0, 0);
const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, 0, 0);
if (!node) return;
signing_init(msg->inputs_count, msg->outputs_count, coin, node, msg->version, msg->lock_time);
@ -445,7 +441,7 @@ void fsm_msgCipherKeyValue(CipherKeyValue *msg)
layoutHome();
return;
}
const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count);
if (!node) return;
bool encrypt = msg->has_encrypt && msg->encrypt;
@ -566,7 +562,7 @@ void fsm_msgGetAddress(GetAddress *msg)
const CoinType *coin = fsm_getCoin(msg->coin_name);
if (!coin) return;
const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count);
if (!node) return;
if (msg->has_multisig) {
@ -646,7 +642,7 @@ void fsm_msgSignMessage(SignMessage *msg)
const CoinType *coin = fsm_getCoin(msg->coin_name);
if (!coin) return;
const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count);
if (!node) return;
layoutProgressSwipe("Signing", 0);
@ -724,20 +720,16 @@ void fsm_msgSignIdentity(SignIdentity *msg)
address_n[3] = 0x80000000 | hash[ 8] | (hash[ 9] << 8) | (hash[10] << 16) | (hash[11] << 24);
address_n[4] = 0x80000000 | hash[12] | (hash[13] << 8) | (hash[14] << 16) | (hash[15] << 24);
const HDNode *node = fsm_getDerivedNode(address_n, 5);
const char *curve = SECP256K1_NAME;
if (msg->has_ecdsa_curve_name) {
curve = msg->ecdsa_curve_name;
}
const HDNode *node = fsm_getDerivedNode(curve, address_n, 5);
if (!node) return;
uint8_t public_key[33]; // copy public key to temporary buffer
memcpy(public_key, node->public_key, sizeof(public_key));
if (msg->has_ecdsa_curve_name) {
const ecdsa_curve *curve = get_curve_by_name(msg->ecdsa_curve_name);
if (curve) {
// correct public key (since fsm_getDerivedNode uses secp256k1 curve)
ecdsa_get_public_key33(curve, node->private_key, public_key);
}
}
bool sign_ssh = msg->identity.has_proto && (strcmp(msg->identity.proto, "ssh") == 0);
int result = 0;
@ -807,7 +799,7 @@ void fsm_msgEncryptMessage(EncryptMessage *msg)
layoutHome();
return;
}
node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count);
if (!node) return;
uint8_t public_key[33];
ecdsa_get_public_key33(&secp256k1, node->private_key, public_key);
@ -859,7 +851,7 @@ void fsm_msgDecryptMessage(DecryptMessage *msg)
layoutHome();
return;
}
const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count);
const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count);
if (!node) return;
layoutProgressSwipe("Decrypting", 0);

@ -45,8 +45,8 @@ Storage storage;
uint8_t storage_uuid[12];
char storage_uuid_str[25];
static bool sessionRootNodeCached;
static HDNode sessionRootNode;
static bool sessionSeedCached;
static uint8_t sessionSeed[64];
static bool sessionPinCached;
@ -126,8 +126,10 @@ void storage_reset(void)
void session_clear(bool clear_pin)
{
sessionRootNodeCached = false; memset(&sessionRootNode, 0, sizeof(sessionRootNode));
sessionPassphraseCached = false; memset(&sessionPassphrase, 0, sizeof(sessionPassphrase));
sessionSeedCached = false;
memset(&sessionSeed, 0, sizeof(sessionSeed));
sessionPassphraseCached = false;
memset(&sessionPassphrase, 0, sizeof(sessionPassphrase));
if (clear_pin) {
sessionPinCached = false;
}
@ -186,14 +188,14 @@ void storage_loadDevice(LoadDevice *msg)
storage.has_node = true;
storage.has_mnemonic = false;
memcpy(&storage.node, &(msg->node), sizeof(HDNodeType));
sessionRootNodeCached = false;
memset(&sessionRootNode, 0, sizeof(sessionRootNode));
sessionSeedCached = false;
memset(&sessionSeed, 0, sizeof(sessionSeed));
} else if (msg->has_mnemonic) {
storage.has_mnemonic = true;
storage.has_node = false;
strlcpy(storage.mnemonic, msg->mnemonic, sizeof(storage.mnemonic));
sessionRootNodeCached = false;
memset(&sessionRootNode, 0, sizeof(sessionRootNode));
sessionSeedCached = false;
memset(&sessionSeed, 0, sizeof(sessionSeed));
}
if (msg->has_language) {
@ -224,7 +226,7 @@ void storage_setLanguage(const char *lang)
void storage_setPassphraseProtection(bool passphrase_protection)
{
sessionRootNodeCached = false;
sessionSeedCached = false;
sessionPassphraseCached = false;
storage.has_passphrase_protection = true;
@ -249,20 +251,34 @@ void get_root_node_callback(uint32_t iter, uint32_t total)
layoutProgress("Waking up", 1000 * iter / total);
}
bool storage_getRootNode(HDNode *node)
const uint8_t *storage_getSeed(void)
{
// root node is properly cached
if (sessionRootNodeCached) {
memcpy(node, &sessionRootNode, sizeof(HDNode));
return true;
if (sessionSeedCached) {
return sessionSeed;
}
// if storage has mnemonic, convert it to node and use it
if (storage.has_mnemonic) {
if (!protectPassphrase()) {
return NULL;
}
mnemonic_to_seed(storage.mnemonic, sessionPassphrase, sessionSeed, get_root_node_callback); // BIP-0039
sessionSeedCached = true;
return sessionSeed;
}
return NULL;
}
bool storage_getRootNode(HDNode *node, const char *curve)
{
// if storage has node, decrypt and use it
if (storage.has_node) {
if (storage.has_node && strcmp(curve, "secp256k1") == 0) {
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) {
if (hdnode_from_xprv(storage.node.depth, storage.node.fingerprint, storage.node.child_num, storage.node.chain_code.bytes, storage.node.private_key.bytes, curve, node) == 0) {
return false;
}
if (storage.has_passphrase_protection && storage.passphrase_protection && sessionPassphraseCached && strlen(sessionPassphrase) > 0) {
@ -273,30 +289,18 @@ bool storage_getRootNode(HDNode *node)
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);
aes_cbc_decrypt(node->chain_code, node->chain_code, 32, secret + 32, &ctx);
aes_cbc_decrypt(node->private_key, node->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];
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;
const uint8_t *seed = storage_getSeed();
if (seed == NULL) {
return false;
}
return false;
return hdnode_from_seed(seed, 64, curve, node);
}
const char *storage_getLabel(void)

@ -33,7 +33,9 @@ void session_clear(bool clear_pin);
void storage_loadDevice(LoadDevice *msg);
bool storage_getRootNode(HDNode *node);
const uint8_t *storage_getSeed(void);
bool storage_getRootNode(HDNode *node, const char *curve);
const char *storage_getLabel(void);
void storage_setLabel(const char *label);

@ -1 +1 @@
Subproject commit f4dd151eb9ef989b88dc79218a2b0115934e4268
Subproject commit c983afd72f40a8c65355af076afd9c132878e8a5
Loading…
Cancel
Save