void fsm_msgApplySettings(ApplySettings *msg) { if (msg->has_label) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "change label to", msg->label, "?", NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Apply settings cancelled"); layoutHome(); return; } } if (msg->has_language) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "change language to", msg->language, "?", NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Apply settings cancelled"); layoutHome(); return; } } if (msg->has_use_passphrase) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", msg->use_passphrase ? "enable passphrase" : "disable passphrase", "encryption?", NULL, NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Apply settings cancelled"); layoutHome(); return; } } if (msg->has_homescreen) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "change the home", "screen ?", NULL, NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Apply settings cancelled"); layoutHome(); return; } } if (!msg->has_label && !msg->has_language && !msg->has_use_passphrase && !msg->has_homescreen) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No setting provided"); return; } if (!protectPin(true)) { layoutHome(); return; } if (msg->has_label) { storage_setLabel(msg->label); } if (msg->has_language) { storage_setLanguage(msg->language); } if (msg->has_use_passphrase) { storage_setPassphraseProtection(msg->use_passphrase); } if (msg->has_homescreen) { storage_setHomescreen(msg->homescreen.bytes, msg->homescreen.size); } storage_commit(); fsm_sendSuccess("Settings applied"); layoutHome(); }
void fsm_msgGetAddress(GetAddress *msg) { RESP_INIT(Address); HDNode *node = fsm_getRootNode(); if (!node) return; const CoinType *coin = coinByName(msg->coin_name); if (!coin) { fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); layoutHome(); return; } fsm_deriveKey(node, msg->address_n, msg->address_n_count); ecdsa_get_address(node->public_key, coin->address_type, resp->address); if (msg->has_show_display && msg->show_display) { layoutAddress(resp->address); if (!protectButton(ButtonRequestType_ButtonRequest_Address, true)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Show address cancelled"); layoutHome(); return; } } msg_write(MessageType_MessageType_Address, resp); layoutHome(); }
void fsm_msgPing(Ping *msg) { RESP_INIT(Success); if (msg->has_button_protection && msg->button_protection) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "answer to ping?", NULL, NULL, NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Ping cancelled"); layoutHome(); return; } } if (msg->has_pin_protection && msg->pin_protection) { if (!protectPin(true)) { layoutHome(); return; } } if (msg->has_passphrase_protection && msg->passphrase_protection) { if (!protectPassphrase()) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Ping cancelled"); return; } } if (msg->has_message) { resp->has_message = true; memcpy(&(resp->message), &(msg->message), sizeof(resp->message)); } msg_write(MessageType_MessageType_Success, resp); layoutHome(); }
void lisk_sign_message(const HDNode *node, const LiskSignMessage *msg, LiskMessageSignature *resp) { layoutSignMessage(msg->message.bytes, msg->message.size); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } layoutProgressSwipe(_("Signing"), 0); uint8_t signature[64]; uint8_t hash[32]; lisk_message_hash(msg->message.bytes, msg->message.size, hash); ed25519_sign(hash, 32, node->private_key, &node->public_key[1], signature); memcpy(resp->signature.bytes, signature, sizeof(signature)); memcpy(resp->public_key.bytes, &node->public_key[1], 32); resp->has_signature = true; resp->signature.size = 64; resp->has_public_key = true; resp->public_key.size = 32; }
void fsm_msgSignMessage(SignMessage *msg) { RESP_INIT(MessageSignature); layoutSignMessage(msg->message.bytes, msg->message.size); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign message cancelled"); layoutHome(); return; } if (!protectPin(true)) { layoutHome(); return; } const CoinType *coin = fsm_getCoin(msg->coin_name); if (!coin) return; const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count); if (!node) return; layoutProgressSwipe("Signing", 0); if (cryptoMessageSign(msg->message.bytes, msg->message.size, node->private_key, resp->signature.bytes) == 0) { resp->has_address = true; uint8_t addr_raw[21]; ecdsa_get_address_raw(node->public_key, coin->address_type, addr_raw); base58_encode_check(addr_raw, 21, resp->address, sizeof(resp->address)); resp->has_signature = true; resp->signature.size = 65; msg_write(MessageType_MessageType_MessageSignature, resp); } else { fsm_sendFailure(FailureType_Failure_Other, "Error signing message"); } layoutHome(); }
void fsm_msgLoadDevice(LoadDevice *msg) { if (storage_isInitialized()) { fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Device is already initialized. Use Wipe first."); return; } layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "I take the risk", NULL, "Loading private seed", "is not recommended.", "Continue only if you", "know what you are", "doing!", NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Load cancelled"); layoutHome(); return; } if (msg->has_mnemonic && !(msg->has_skip_checksum && msg->skip_checksum) ) { if (!mnemonic_check(msg->mnemonic)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Mnemonic with wrong checksum provided"); layoutHome(); return; } } storage_loadDevice(msg); storage_commit(); fsm_sendSuccess("Device loaded"); layoutHome(); }
void fsm_msgApplySettings(ApplySettings *msg) { if (msg->has_label && msg->has_language) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "change label to", msg->label, "and language to", msg->language, "?"); } else if (msg->has_label) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "change label to", msg->label, "?", NULL, NULL); } else if (msg->has_language) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "change language to", msg->language, "?", NULL, NULL); } else { fsm_sendFailure(FailureType_Failure_SyntaxError, "No setting provided"); return; } if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Apply settings cancelled"); layoutHome(); return; } if (!protectPin(true)) { layoutHome(); return; } if (msg->has_label) { storage_setLabel(msg->label); } if (msg->has_language) { storage_setLanguage(msg->language); } storage_commit(); fsm_sendSuccess("Settings applied"); layoutHome(); }
void fsm_msgGetAddress(GetAddress *msg) { RESP_INIT(Address); if (!protectPin(true)) { layoutHome(); return; } const CoinType *coin = fsm_getCoin(msg->coin_name); if (!coin) return; const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count); if (!node) return; if (msg->has_multisig) { layoutProgressSwipe("Preparing", 0); if (cryptoMultisigPubkeyIndex(&(msg->multisig), node->public_key) < 0) { fsm_sendFailure(FailureType_Failure_Other, "Pubkey not found in multisig script"); layoutHome(); return; } uint8_t buf[32]; if (compile_script_multisig_hash(&(msg->multisig), buf) == 0) { fsm_sendFailure(FailureType_Failure_Other, "Invalid multisig script"); layoutHome(); return; } ripemd160(buf, 32, buf + 1); buf[0] = coin->address_type_p2sh; // multisig cointype base58_encode_check(buf, 21, resp->address, sizeof(resp->address)); } else { ecdsa_get_address(node->public_key, coin->address_type, resp->address, sizeof(resp->address)); } if (msg->has_show_display && msg->show_display) { char desc[16]; if (msg->has_multisig) { strlcpy(desc, "Msig __ of __:", sizeof(desc)); const uint32_t m = msg->multisig.m; const uint32_t n = msg->multisig.pubkeys_count; desc[5] = (m < 10) ? ' ': ('0' + (m / 10)); desc[6] = '0' + (m % 10); desc[11] = (n < 10) ? ' ': ('0' + (n / 10)); desc[12] = '0' + (n % 10); } else { strlcpy(desc, "Address:", sizeof(desc)); } layoutAddress(resp->address, desc); if (!protectButton(ButtonRequestType_ButtonRequest_Address, true)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Show address cancelled"); layoutHome(); return; } } msg_write(MessageType_MessageType_Address, resp); layoutHome(); }
void fsm_msgCipherKeyValue(CipherKeyValue *msg) { if (!msg->has_key) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No key provided"); return; } if (!msg->has_value) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No value provided"); return; } if (msg->value.size % 16) { fsm_sendFailure(FailureType_Failure_SyntaxError, "Value length must be a multiple of 16"); return; } if (!protectPin(true)) { layoutHome(); return; } HDNode *node = fsm_getRootNode(); if (!node) return; fsm_deriveKey(node, msg->address_n, msg->address_n_count); bool encrypt = msg->has_encrypt && msg->encrypt; bool ask_on_encrypt = msg->has_ask_on_encrypt && msg->ask_on_encrypt; bool ask_on_decrypt = msg->has_ask_on_decrypt && msg->ask_on_decrypt; if ((encrypt && ask_on_encrypt) || (!encrypt && ask_on_decrypt)) { layoutCipherKeyValue(encrypt, msg->key); if (!protectButton(ButtonRequestType_ButtonRequest_Other, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "CipherKeyValue cancelled"); layoutHome(); return; } } uint8_t data[256 + 4]; strlcpy((char *)data, msg->key, sizeof(data)); strlcat((char *)data, ask_on_encrypt ? "E1" : "E0", sizeof(data)); strlcat((char *)data, ask_on_decrypt ? "D1" : "D0", sizeof(data)); hmac_sha512(node->private_key, 32, data, strlen((char *)data), data); RESP_INIT(Success); if (encrypt) { aes_encrypt_ctx ctx; aes_encrypt_key256(data, &ctx); aes_cbc_encrypt(msg->value.bytes, resp->payload.bytes, msg->value.size, data + 32, &ctx); } else { aes_decrypt_ctx ctx; aes_decrypt_key256(data, &ctx); aes_cbc_decrypt(msg->value.bytes, resp->payload.bytes, msg->value.size, data + 32, &ctx); } resp->has_payload = true; resp->payload.size = msg->value.size; msg_write(MessageType_MessageType_Success, resp); layoutHome(); }
void fsm_msgEncryptMessage(EncryptMessage *msg) { if (!msg->has_pubkey) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No public key provided"); return; } if (!msg->has_message) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No message provided"); return; } curve_point pubkey; if (msg->pubkey.size != 33 || ecdsa_read_pubkey(&secp256k1, msg->pubkey.bytes, &pubkey) == 0) { fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid public key provided"); return; } bool display_only = msg->has_display_only && msg->display_only; bool signing = msg->address_n_count > 0; RESP_INIT(EncryptedMessage); const CoinType *coin = 0; const HDNode *node = 0; uint8_t address_raw[21]; if (signing) { coin = coinByName(msg->coin_name); if (!coin) { fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); return; } if (!protectPin(true)) { layoutHome(); return; } node = fsm_getDerivedNode(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); ecdsa_get_address_raw(public_key, coin->address_type, address_raw); } layoutEncryptMessage(msg->message.bytes, msg->message.size, signing); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Encrypt message cancelled"); layoutHome(); return; } layoutProgressSwipe("Encrypting", 0); if (cryptoMessageEncrypt(&pubkey, msg->message.bytes, msg->message.size, display_only, resp->nonce.bytes, &(resp->nonce.size), resp->message.bytes, &(resp->message.size), resp->hmac.bytes, &(resp->hmac.size), signing ? node->private_key : 0, signing ? address_raw : 0) != 0) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Error encrypting message"); layoutHome(); return; } resp->has_nonce = true; resp->has_message = true; resp->has_hmac = true; msg_write(MessageType_MessageType_EncryptedMessage, resp); layoutHome(); }
void fsm_msgDecryptMessage(DecryptMessage *msg) { if (!msg->has_nonce) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No nonce provided"); return; } if (!msg->has_message) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No message provided"); return; } if (!msg->has_hmac) { fsm_sendFailure(FailureType_Failure_SyntaxError, "No message hmac provided"); return; } curve_point nonce_pubkey; if (msg->nonce.size != 33 || ecdsa_read_pubkey(&secp256k1, msg->nonce.bytes, &nonce_pubkey) == 0) { fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid nonce provided"); return; } if (!protectPin(true)) { layoutHome(); return; } const HDNode *node = fsm_getDerivedNode(msg->address_n, msg->address_n_count); if (!node) return; layoutProgressSwipe("Decrypting", 0); RESP_INIT(DecryptedMessage); bool display_only = false; bool signing = false; uint8_t address_raw[21]; if (cryptoMessageDecrypt(&nonce_pubkey, msg->message.bytes, msg->message.size, msg->hmac.bytes, msg->hmac.size, node->private_key, resp->message.bytes, &(resp->message.size), &display_only, &signing, address_raw) != 0) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Error decrypting message"); layoutHome(); return; } if (signing) { base58_encode_check(address_raw, 21, resp->address, sizeof(resp->address)); } layoutDecryptMessage(resp->message.bytes, resp->message.size, signing ? resp->address : 0); protectButton(ButtonRequestType_ButtonRequest_Other, true); if (display_only) { resp->has_address = false; resp->has_message = false; memset(resp->address, 0, sizeof(resp->address)); memset(&(resp->message), 0, sizeof(resp->message)); } else { resp->has_address = signing; resp->has_message = true; } msg_write(MessageType_MessageType_DecryptedMessage, resp); layoutHome(); }
void fsm_msgVerifyMessage(VerifyMessage *msg) { const char *address = msg->has_address ? msg->address : 0; layoutProgressSwipe("Verifying", 0, 0); if (msg->signature.size == 65 && transactionMessageVerify(msg->message.bytes, msg->message.size, msg->signature.bytes, address)) { layoutVerifyMessage(msg->message.bytes, msg->message.size); protectButton(ButtonRequestType_ButtonRequest_Other, true); fsm_sendSuccess("Message verified"); } else { fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid signature"); } layoutHome(); }
void fsm_msgWipeDevice(WipeDevice *msg) { (void)msg; layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "wipe the device?", NULL, "All data will be lost.", NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_WipeDevice, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Wipe cancelled"); layoutHome(); return; } storage_reset(); storage_reset_uuid(); storage_commit(); // the following does not work on Mac anyway :-/ Linux/Windows are fine, so it is not needed // usbReconnect(); // force re-enumeration because of the serial number change fsm_sendSuccess("Device wiped"); layoutHome(); }
void fsm_msgGetEntropy(GetEntropy *msg) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "send entropy?", NULL, NULL, NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Entropy cancelled"); layoutHome(); return; } RESP_INIT(Entropy); uint32_t len = msg->size; if (len > 1024) { len = 1024; } resp->entropy.size = len; random_buffer(resp->entropy.bytes, len); msg_write(MessageType_MessageType_Entropy, resp); layoutHome(); }
void reset_init(bool display_random, uint32_t _strength, bool passphrase_protection, bool pin_protection, const char *language, const char *label) { if (_strength != 128 && _strength != 192 && _strength != 256) { fsm_sendFailure(FailureType_Failure_SyntaxError, "Invalid strength (has to be 128, 192 or 256 bits)"); layoutHome(); return; } strength = _strength; random_buffer(int_entropy, 32); char ent_str[4][17]; data2hex(int_entropy , 8, ent_str[0]); data2hex(int_entropy + 8, 8, ent_str[1]); data2hex(int_entropy + 16, 8, ent_str[2]); data2hex(int_entropy + 24, 8, ent_str[3]); if (display_random) { layoutDialogSwipe(DIALOG_ICON_INFO, "Cancel", "Continue", NULL, "Internal entropy:", ent_str[0], ent_str[1], ent_str[2], ent_str[3], NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ResetDevice, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Reset cancelled"); layoutHome(); return; } } if (pin_protection && !protectChangePin()) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "PIN change failed"); layoutHome(); return; } storage.has_passphrase_protection = true; storage.passphrase_protection = passphrase_protection; storage_setLanguage(language); storage_setLabel(label); EntropyRequest resp; memset(&resp, 0, sizeof(EntropyRequest)); msg_write(MessageType_MessageType_EntropyRequest, &resp); awaiting_entropy = true; }
static bool fsm_layoutAddress(const char *address, const char *desc, bool ignorecase, size_t prefixlen, const uint32_t *address_n, size_t address_n_count) { bool qrcode = false; for (;;) { const char* display_addr = address; if (prefixlen && !qrcode) { display_addr += prefixlen; } layoutAddress(display_addr, desc, qrcode, ignorecase, address_n, address_n_count); if (protectButton(ButtonRequest_ButtonRequestType_ButtonRequest_Address, false)) { return true; } if (protectAbortedByCancel || protectAbortedByInitialize) { fsm_sendFailure(Failure_FailureType_Failure_ActionCancelled, NULL); layoutHome(); return false; } qrcode = !qrcode; } }
void fsm_msgSignMessage(SignMessage *msg) { RESP_INIT(MessageSignature); layoutSignMessage(msg->message.bytes, msg->message.size); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Sign message cancelled"); layoutHome(); return; } if (!protectPin(true)) { layoutHome(); return; } HDNode *node = fsm_getRootNode(); if (!node) return; const CoinType *coin = coinByName(msg->coin_name); if (!coin) { fsm_sendFailure(FailureType_Failure_Other, "Invalid coin name"); layoutHome(); return; } fsm_deriveKey(node, msg->address_n, msg->address_n_count); ecdsa_get_address(node->public_key, coin->address_type, resp->address); layoutProgressSwipe("Signing", 0, 0); if (transactionMessageSign(msg->message.bytes, msg->message.size, node->private_key, resp->address, resp->signature.bytes)) { resp->has_address = true; resp->has_signature = true; resp->signature.size = 65; msg_write(MessageType_MessageType_MessageSignature, resp); } else { fsm_sendFailure(FailureType_Failure_Other, "Error signing message"); } layoutHome(); }
void fsm_msgChangePin(ChangePin *msg) { bool removal = msg->has_remove && msg->remove; if (removal) { if (storage_hasPin()) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "remove current PIN?", NULL, NULL, NULL, NULL); } else { fsm_sendSuccess("PIN removed"); return; } } else { if (storage_hasPin()) { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "change current PIN?", NULL, NULL, NULL, NULL); } else { layoutDialogSwipe(DIALOG_ICON_QUESTION, "Cancel", "Confirm", NULL, "Do you really want to", "set new PIN?", NULL, NULL, NULL, NULL); } } if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, removal ? "PIN removal cancelled" : "PIN change cancelled"); layoutHome(); return; } if (!protectPin(false)) { layoutHome(); return; } if (removal) { storage_setPin(0); fsm_sendSuccess("PIN removed"); } else { if (protectChangePin()) { fsm_sendSuccess("PIN changed"); } else { fsm_sendFailure(FailureType_Failure_ActionCancelled, "PIN change failed"); } } layoutHome(); }
void fsm_msgVerifyMessage(VerifyMessage *msg) { if (!msg->has_address) { fsm_sendFailure(FailureType_Failure_Other, "No address provided"); return; } if (!msg->has_message) { fsm_sendFailure(FailureType_Failure_Other, "No message provided"); return; } layoutProgressSwipe("Verifying", 0); uint8_t addr_raw[21]; if (!ecdsa_address_decode(msg->address, addr_raw)) { fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid address"); } if (msg->signature.size == 65 && cryptoMessageVerify(msg->message.bytes, msg->message.size, addr_raw, msg->signature.bytes) == 0) { layoutVerifyMessage(msg->message.bytes, msg->message.size); protectButton(ButtonRequestType_ButtonRequest_Other, true); fsm_sendSuccess("Message verified"); } else { fsm_sendFailure(FailureType_Failure_InvalidSignature, "Invalid signature"); } layoutHome(); }
void lisk_sign_tx(const HDNode *node, LiskSignTx *msg, LiskSignedTx *resp) { lisk_update_raw_tx(node, msg); if (msg->has_transaction) { SHA256_CTX ctx; sha256_Init(&ctx); switch (msg->transaction.type) { case LiskTransactionType_Transfer: layoutRequireConfirmTx(msg->transaction.recipient_id, msg->transaction.amount); break; case LiskTransactionType_RegisterDelegate: layoutRequireConfirmDelegateRegistration(&msg->transaction.asset); break; case LiskTransactionType_CastVotes: layoutRequireConfirmCastVotes(&msg->transaction.asset); break; case LiskTransactionType_RegisterSecondPassphrase: layoutLiskPublicKey(msg->transaction.asset.signature.public_key.bytes); break; case LiskTransactionType_RegisterMultisignatureAccount: layoutRequireConfirmMultisig(&msg->transaction.asset); break; default: fsm_sendFailure(FailureType_Failure_DataError, _("Invalid transaction type")); layoutHome(); break; } if (!protectButton((msg->transaction.type == LiskTransactionType_RegisterSecondPassphrase ? ButtonRequestType_ButtonRequest_PublicKey : ButtonRequestType_ButtonRequest_SignTx), false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Signing cancelled"); layoutHome(); return; } layoutRequireConfirmFee(msg->transaction.fee, msg->transaction.amount); if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmOutput, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, "Signing cancelled"); layoutHome(); return; } layoutProgressSwipe(_("Signing transaction"), 0); sha256_Update(&ctx, (const uint8_t *)&msg->transaction.type, 1); lisk_hashupdate_uint32(&ctx, msg->transaction.timestamp); sha256_Update(&ctx, msg->transaction.sender_public_key.bytes, 32); if (msg->transaction.has_requester_public_key) { sha256_Update(&ctx, msg->transaction.requester_public_key.bytes, msg->transaction.requester_public_key.size); } uint64_t recipient_id = 0; if (msg->transaction.has_recipient_id && msg->transaction.recipient_id[0] != 0) { // parse integer from lisk address ("123L" -> 123) for (size_t i = 0; i < strlen(msg->transaction.recipient_id) - 1; i++) { if (msg->transaction.recipient_id[i] < '0' || msg->transaction.recipient_id[i] > '9') { fsm_sendFailure(FailureType_Failure_DataError, _("Invalid recipient_id")); layoutHome(); return; } recipient_id *= 10; recipient_id += (msg->transaction.recipient_id[i] - '0'); } } lisk_hashupdate_uint64_be(&ctx, recipient_id); lisk_hashupdate_uint64_le(&ctx, msg->transaction.amount); lisk_hashupdate_asset(&ctx, msg->transaction.type, &msg->transaction.asset); // if signature exist calculate second signature if (msg->transaction.has_signature) { sha256_Update(&ctx, msg->transaction.signature.bytes, msg->transaction.signature.size); } uint8_t hash[32]; sha256_Final(&ctx, hash); ed25519_sign(hash, 32, node->private_key, &node->public_key[1], resp->signature.bytes); resp->has_signature = true; resp->signature.size = 64; } }
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(); }
void reset_entropy(const uint8_t *ext_entropy, uint32_t len) { if (!awaiting_entropy) { fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Reset mode"); return; } SHA256_CTX ctx; sha256_Init(&ctx); sha256_Update(&ctx, int_entropy, 32); sha256_Update(&ctx, ext_entropy, len); sha256_Final(int_entropy, &ctx); strlcpy(storage.mnemonic, mnemonic_from_data(int_entropy, strength / 8), sizeof(storage.mnemonic)); memset(int_entropy, 0, 32); awaiting_entropy = false; int pass, word_pos, i = 0, j; for (pass = 0; pass < 2; pass++) { i = 0; for (word_pos = 1; word_pos <= (int)strength/32*3; word_pos++) { // copy current_word j = 0; while (storage.mnemonic[i] != ' ' && storage.mnemonic[i] != 0 && j + 1 < (int)sizeof(current_word)) { current_word[j] = storage.mnemonic[i]; i++; j++; } current_word[j] = 0; if (storage.mnemonic[i] != 0) i++; char desc[] = "##th word is:"; if (word_pos < 10) { desc[0] = ' '; } else { desc[0] = '0' + word_pos / 10; } desc[1] = '0' + word_pos % 10; if (word_pos == 1 || word_pos == 21) { desc[2] = 's'; desc[3] = 't'; } else if (word_pos == 2 || word_pos == 22) { desc[2] = 'n'; desc[3] = 'd'; } else if (word_pos == 3 || word_pos == 23) { desc[2] = 'r'; desc[3] = 'd'; } if (word_pos == (int)strength/32*3) { // last word if (pass == 1) { layoutDialogSwipe(DIALOG_ICON_INFO, NULL, "Finish", NULL, "Please check the seed", NULL, (word_pos < 10 ? desc + 1 : desc), NULL, current_word, NULL); } else { layoutDialogSwipe(DIALOG_ICON_INFO, NULL, "Again", NULL, "Write down the seed", NULL, (word_pos < 10 ? desc + 1 : desc), NULL, current_word, NULL); } } else { if (pass == 1) { layoutDialogSwipe(DIALOG_ICON_INFO, NULL, "Next", NULL, "Please check the seed", NULL, (word_pos < 10 ? desc + 1 : desc), NULL, current_word, NULL); } else { layoutDialogSwipe(DIALOG_ICON_INFO, NULL, "Next", NULL, "Write down the seed", NULL, (word_pos < 10 ? desc + 1 : desc), NULL, current_word, NULL); } } if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmWord, true)) { storage_reset(); layoutHome(); return; } } } storage.has_mnemonic = true; storage_commit(); fsm_sendSuccess("Device reset"); layoutHome(); }