void fsm_msgGetPublicKey(GetPublicKey *msg) { RESP_INIT(PublicKey); if (!storage_is_initialized()) { fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); return; } if(!pin_protect_cached()) { go_home(); return; } const HDNode *node = fsm_getDerivedNode(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); } } resp->node.depth = node->depth; resp->node.fingerprint = node->fingerprint; resp->node.child_num = node->child_num; resp->node.chain_code.size = 32; memcpy(resp->node.chain_code.bytes, node->chain_code, 32); resp->node.has_private_key = false; resp->node.has_public_key = true; resp->node.public_key.size = 33; memcpy(resp->node.public_key.bytes, public_key, 33); resp->has_xpub = true; hdnode_serialize_public(node, resp->xpub, sizeof(resp->xpub)); if(msg->has_show_display && msg->show_display) { if(!confirm_xpub(resp->xpub)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Show extended public key cancelled"); go_home(); return; } } msg_write(MessageType_MessageType_PublicKey, resp); go_home(); }
/* * verify_exchange_address - verify address specified in exchange contract belongs to device. * * INPUT * coin - the CoinType * address_n_count - depth of node * address_n - pointer to node path * address_str - string representation of address * address_str_len - address length * root - root hd node * * OUTPUT * true/false - success/failure */ static bool verify_exchange_address(const CoinType *coin, size_t address_n_count, uint32_t *address_n, char *address_str, size_t address_str_len, const HDNode *root, bool is_token) { static CONFIDENTIAL HDNode node; memcpy(&node, root, sizeof(HDNode)); if (hdnode_private_ckd_cached(&node, address_n, address_n_count, NULL) == 0) { memzero(&node, sizeof(node)); return false; } if (isEthereumLike(coin->coin_name) || is_token) { char tx_out_address[sizeof(((ExchangeAddress *)NULL)->address)]; EthereumAddress_address_t ethereum_addr; ethereum_addr.size = 20; if (hdnode_get_ethereum_pubkeyhash(&node, ethereum_addr.bytes) == 0) { memzero(&node, sizeof(node)); return false; } data2hex((char *)ethereum_addr.bytes, 20, tx_out_address); return addresses_same(tx_out_address, sizeof(tx_out_address), address_str, address_str_len, true); } const curve_info *curve = get_curve_by_name(coin->curve_name); if (!curve) { memzero(&node, sizeof(node)); return false; } char tx_out_address[36]; hdnode_fill_public_key(&node); ecdsa_get_address(node.public_key, coin->address_type, curve->hasher_pubkey, curve->hasher_base58, tx_out_address, sizeof(tx_out_address)); memzero(&node, sizeof(node)); return strncmp(tx_out_address, address_str, sizeof(tx_out_address)) == 0; }
void fsm_msgGetPublicKey(GetPublicKey *msg) { RESP_INIT(PublicKey); if (!protectPin(true)) { layoutHome(); return; } const HDNode *node = fsm_getDerivedNode(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); } } resp->node.depth = node->depth; resp->node.fingerprint = node->fingerprint; resp->node.child_num = node->child_num; resp->node.chain_code.size = 32; memcpy(resp->node.chain_code.bytes, node->chain_code, 32); resp->node.has_private_key = false; resp->node.has_public_key = true; resp->node.public_key.size = 33; memcpy(resp->node.public_key.bytes, public_key, 33); resp->has_xpub = true; hdnode_serialize_public(node, resp->xpub, sizeof(resp->xpub)); msg_write(MessageType_MessageType_PublicKey, resp); layoutHome(); }
void fsm_msgSignIdentity(SignIdentity *msg) { RESP_INIT(SignedIdentity); layoutSignIdentity(&(msg->identity), msg->has_challenge_visual ? msg->challenge_visual : 0); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign identity cancelled"); layoutHome(); return; } if (!protectPin(true)) { layoutHome(); return; } uint8_t hash[32]; if (!msg->has_identity || cryptoIdentityFingerprint(&(msg->identity), hash) == 0) { fsm_sendFailure(FailureType_Failure_Other, "Invalid identity"); layoutHome(); return; } uint32_t address_n[5]; address_n[0] = 0x80000000 | 13; address_n[1] = 0x80000000 | hash[ 0] | (hash[ 1] << 8) | (hash[ 2] << 16) | (hash[ 3] << 24); address_n[2] = 0x80000000 | hash[ 4] | (hash[ 5] << 8) | (hash[ 6] << 16) | (hash[ 7] << 24); 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); 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; layoutProgressSwipe("Signing", 0); if (sign_ssh) { // SSH does not sign visual challenge result = sshMessageSign(msg->challenge_hidden.bytes, msg->challenge_hidden.size, node->private_key, resp->signature.bytes); } else { uint8_t digest[64]; sha256_Raw(msg->challenge_hidden.bytes, msg->challenge_hidden.size, digest); sha256_Raw((const uint8_t *)msg->challenge_visual, strlen(msg->challenge_visual), digest + 32); result = cryptoMessageSign(digest, 64, node->private_key, resp->signature.bytes); } if (result == 0) { if (sign_ssh) { resp->has_address = false; } else { resp->has_address = true; uint8_t addr_raw[21]; ecdsa_get_address_raw(node->public_key, 0x00, addr_raw); // hardcoded Bitcoin address type base58_encode_check(addr_raw, 21, resp->address, sizeof(resp->address)); } resp->has_public_key = true; resp->public_key.size = 33; memcpy(resp->public_key.bytes, public_key, 33); resp->has_signature = true; resp->signature.size = 65; msg_write(MessageType_MessageType_SignedIdentity, resp); } else { fsm_sendFailure(FailureType_Failure_Other, "Error signing identity"); } layoutHome(); }