diff --git a/firmware/ethereum.c b/firmware/ethereum.c index 9715de9..7db5352 100644 --- a/firmware/ethereum.c +++ b/firmware/ethereum.c @@ -30,6 +30,7 @@ #include "secp256k1.h" #include "sha3.h" #include "util.h" +#include "gettext.h" #include "ethereum_tokens.h" static bool ethereum_signing = false; @@ -135,7 +136,7 @@ static void send_request_chunk(void) int progress = 1000 - (data_total > 1000000 ? data_left / (data_total/800) : data_left * 800 / data_total); - layoutProgress("Signing", progress); + layoutProgress(_("Signing"), progress); resp.has_data_length = true; resp.data_length = data_left <= 1024 ? data_left : 1024; msg_write(MessageType_MessageType_EthereumTxRequest, &resp); @@ -151,7 +152,7 @@ static void send_signature(void) { uint8_t hash[32], sig[64]; uint8_t v; - layoutProgress("Signing", 1000); + layoutProgress(_("Signing"), 1000); /* eip-155 replay protection */ if (chain_id != 0) { @@ -163,7 +164,7 @@ static void send_signature(void) keccak_Final(&keccak_ctx, hash); if (ecdsa_sign_digest(&secp256k1, privkey, hash, sig, &v, ethereum_is_canonic) != 0) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Signing failed"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing failed")); ethereum_signing_abort(); return; } @@ -236,7 +237,7 @@ static void layoutEthereumConfirmTx(const uint8_t *to, uint32_t to_len, const ui char amount[32]; if (token == NULL) { if (bn_is_zero(&val)) { - strcpy(amount, "message"); + strcpy(amount, _("message")); } else { ethereumFormatAmount(&val, NULL, amount, sizeof(amount)); } @@ -249,22 +250,22 @@ static void layoutEthereumConfirmTx(const uint8_t *to, uint32_t to_len, const ui static char _to3[17] = {0}; if (to_len) { - strcpy(_to1, "to "); + strcpy(_to1, _("to ")); data2hex(to, 6, _to1 + 3); data2hex(to + 6, 7, _to2); data2hex(to + 13, 7, _to3); _to3[14] = '?'; _to3[15] = 0; } else { - strlcpy(_to1, "to new contract?", sizeof(_to1)); + strlcpy(_to1, _("to new contract?"), sizeof(_to1)); strlcpy(_to2, "", sizeof(_to2)); strlcpy(_to3, "", sizeof(_to3)); } layoutDialogSwipe(&bmp_icon_question, - "Cancel", - "Confirm", + _("Cancel"), + _("Confirm"), NULL, - "Send", + _("Send"), amount, _to1, _to2, @@ -300,10 +301,10 @@ static void layoutEthereumData(const uint8_t *data, uint32_t len, uint32_t total summarystart = summary + 4; layoutDialogSwipe(&bmp_icon_question, - "Cancel", - "Confirm", + _("Cancel"), + _("Confirm"), NULL, - "Transaction data:", + _("Transaction data:"), hexdata[0], hexdata[1], hexdata[2], @@ -338,20 +339,20 @@ static void layoutEthereumFee(const uint8_t *value, uint32_t value_len, bn_read_be(pad_val, &val); if (bn_is_zero(&val)) { - strcpy(tx_value, is_token ? "token" : "message"); + strcpy(tx_value, is_token ? _("token") : _("message")); } else { ethereumFormatAmount(&val, NULL, tx_value, sizeof(tx_value)); } layoutDialogSwipe(&bmp_icon_question, - "Cancel", - "Confirm", + _("Cancel"), + _("Confirm"), NULL, - "Really send", + _("Really send"), tx_value, - "paying up to", + _("paying up to"), gas_value, - "for gas?", + _("for gas?"), NULL ); } @@ -409,7 +410,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) /* eip-155 chain id */ if (msg->has_chain_id) { if (msg->chain_id < 1 || msg->chain_id > 109) { - fsm_sendFailure(FailureType_Failure_DataError, "Chain Id out of bounds"); + fsm_sendFailure(FailureType_Failure_DataError, _("Chain Id out of bounds")); ethereum_signing_abort(); return; } @@ -420,7 +421,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) if (msg->has_data_length && msg->data_length > 0) { if (!msg->has_data_initial_chunk || msg->data_initial_chunk.size == 0) { - fsm_sendFailure(FailureType_Failure_DataError, "Data length provided, but no initial chunk"); + fsm_sendFailure(FailureType_Failure_DataError, _("Data length provided, but no initial chunk")); ethereum_signing_abort(); return; } @@ -428,7 +429,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) * prevent exceeding the limit we use a stricter limit on data length. */ if (msg->data_length > 16000000) { - fsm_sendFailure(FailureType_Failure_DataError, "Data length exceeds limit"); + fsm_sendFailure(FailureType_Failure_DataError, _("Data length exceeds limit")); ethereum_signing_abort(); return; } @@ -437,14 +438,14 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) data_total = 0; } if (msg->data_initial_chunk.size > data_total) { - fsm_sendFailure(FailureType_Failure_DataError, "Invalid size of initial chunk"); + fsm_sendFailure(FailureType_Failure_DataError, _("Invalid size of initial chunk")); ethereum_signing_abort(); return; } // safety checks if (!ethereum_signing_check(msg)) { - fsm_sendFailure(FailureType_Failure_DataError, "Safety check failed"); + fsm_sendFailure(FailureType_Failure_DataError, _("Safety check failed")); ethereum_signing_abort(); return; } @@ -464,7 +465,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) } if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); ethereum_signing_abort(); return; } @@ -472,7 +473,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) if (token == NULL && data_total > 0) { layoutEthereumData(msg->data_initial_chunk.bytes, msg->data_initial_chunk.size, data_total); if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); ethereum_signing_abort(); return; } @@ -482,7 +483,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) msg->gas_price.bytes, msg->gas_price.size, msg->gas_limit.bytes, msg->gas_limit.size, token != NULL); if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); ethereum_signing_abort(); return; } @@ -490,7 +491,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) /* Stage 1: Calculate total RLP length */ uint32_t rlp_length = 0; - layoutProgress("Signing", 0); + layoutProgress(_("Signing"), 0); rlp_length += rlp_calculate_length(msg->nonce.size, msg->nonce.bytes[0]); rlp_length += rlp_calculate_length(msg->gas_price.size, msg->gas_price.bytes[0]); @@ -507,7 +508,7 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) /* Stage 2: Store header fields */ hash_rlp_list_length(rlp_length); - layoutProgress("Signing", 100); + layoutProgress(_("Signing"), 100); hash_rlp_field(msg->nonce.bytes, msg->nonce.size); hash_rlp_field(msg->gas_price.bytes, msg->gas_price.size); @@ -530,19 +531,19 @@ void ethereum_signing_init(EthereumSignTx *msg, const HDNode *node) void ethereum_signing_txack(EthereumTxAck *tx) { if (!ethereum_signing) { - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Ethereum signing mode"); + fsm_sendFailure(FailureType_Failure_UnexpectedMessage, _("Not in Ethereum signing mode")); layoutHome(); return; } if (tx->data_chunk.size > data_left) { - fsm_sendFailure(FailureType_Failure_DataError, "Too much data"); + fsm_sendFailure(FailureType_Failure_DataError, _("Too much data")); ethereum_signing_abort(); return; } if (data_left > 0 && (!tx->has_data_chunk || tx->data_chunk.size == 0)) { - fsm_sendFailure(FailureType_Failure_DataError, "Empty data chunk received"); + fsm_sendFailure(FailureType_Failure_DataError, _("Empty data chunk received")); ethereum_signing_abort(); return; } diff --git a/firmware/fsm.c b/firmware/fsm.c index cb2c7d1..f1d807b 100644 --- a/firmware/fsm.c +++ b/firmware/fsm.c @@ -50,6 +50,7 @@ #include "secp256k1.h" #include #include "ethereum.h" +#include "gettext.h" // message methods @@ -62,13 +63,13 @@ static uint8_t msg_resp[MSG_OUT_SIZE] __attribute__ ((aligned)); #define CHECK_INITIALIZED \ if (!storage_isInitialized()) { \ - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized"); \ + fsm_sendFailure(FailureType_Failure_NotInitialized, NULL); \ return; \ } #define CHECK_NOT_INITIALIZED \ if (storage_isInitialized()) { \ - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Device is already initialized. Use Wipe first."); \ + fsm_sendFailure(FailureType_Failure_UnexpectedMessage, _("Device is already initialized. Use Wipe first.")); \ return; \ } @@ -111,6 +112,46 @@ void fsm_sendFailure(FailureType code, const char *text) RESP_INIT(Failure); resp->has_code = true; resp->code = code; + if (!text) { + switch (code) { + case FailureType_Failure_UnexpectedMessage: + text = _("Unexpected message"); + break; + case FailureType_Failure_ButtonExpected: + text = _("Button expected"); + break; + case FailureType_Failure_DataError: + text = _("Data error"); + break; + case FailureType_Failure_ActionCancelled: + text = _("Action cancelled by user"); + break; + case FailureType_Failure_PinExpected: + text = _("PIN expected"); + break; + case FailureType_Failure_PinCancelled: + text = _("PIN cancelled"); + break; + case FailureType_Failure_PinInvalid: + text = _("PIN invalid"); + break; + case FailureType_Failure_InvalidSignature: + text = _("Invalid signature"); + break; + case FailureType_Failure_ProcessError: + text = _("Process error"); + break; + case FailureType_Failure_NotEnoughFunds: + text = _("Not enough funds"); + break; + case FailureType_Failure_NotInitialized: + text = _("Device not initialized"); + break; + case FailureType_Failure_FirmwareError: + text = _("Firmware error"); + break; + } + } if (text) { resp->has_message = true; strlcpy(resp->message, text, sizeof(resp->message)); @@ -127,7 +168,7 @@ const CoinType *fsm_getCoin(bool has_name, const char *name) coin = coinByName("Bitcoin"); } if (!coin) { - fsm_sendFailure(FailureType_Failure_DataError, "Invalid coin name"); + fsm_sendFailure(FailureType_Failure_DataError, _("Invalid coin name")); layoutHome(); return 0; } @@ -138,7 +179,7 @@ HDNode *fsm_getDerivedNode(const char *curve, uint32_t *address_n, size_t addres { static HDNode node; if (!storage_getRootNode(&node, curve, true)) { - fsm_sendFailure(FailureType_Failure_NotInitialized, "Device not initialized or passphrase request cancelled or unsupported curve"); + fsm_sendFailure(FailureType_Failure_NotInitialized, _("Device not initialized or passphrase request cancelled or unsupported curve")); layoutHome(); return 0; } @@ -146,7 +187,7 @@ HDNode *fsm_getDerivedNode(const char *curve, uint32_t *address_n, size_t addres return &node; } if (hdnode_private_ckd_cached(&node, address_n, address_n_count, NULL) == 0) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to derive private key"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to derive private key")); layoutHome(); return 0; } @@ -201,9 +242,9 @@ void fsm_msgPing(Ping *msg) RESP_INIT(Success); if (msg->has_button_protection && msg->button_protection) { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "answer to ping?", NULL, NULL, NULL, NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -215,7 +256,7 @@ void fsm_msgPing(Ping *msg) if (msg->has_passphrase_protection && msg->passphrase_protection) { if (!protectPassphrase()) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); return; } } @@ -233,20 +274,20 @@ void fsm_msgChangePin(ChangePin *msg) bool removal = msg->has_remove && msg->remove; if (removal) { if (storage_hasPin()) { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "remove current PIN?", NULL, NULL, NULL, NULL); + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL, _("Do you really want to"), _("remove current PIN?"), NULL, NULL, NULL, NULL); } else { - fsm_sendSuccess("PIN removed"); + fsm_sendSuccess(_("PIN removed")); return; } } else { if (storage_hasPin()) { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "change current PIN?", NULL, NULL, NULL, NULL); + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL, _("Do you really want to"), _("change current PIN?"), NULL, NULL, NULL, NULL); } else { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "set new PIN?", NULL, NULL, NULL, NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -255,12 +296,12 @@ void fsm_msgChangePin(ChangePin *msg) if (removal) { storage_setPin(0); - fsm_sendSuccess("PIN removed"); + fsm_sendSuccess(_("PIN removed")); } else { if (protectChangePin()) { - fsm_sendSuccess("PIN changed"); + fsm_sendSuccess(_("PIN changed")); } else { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); } } layoutHome(); @@ -269,9 +310,9 @@ void fsm_msgChangePin(ChangePin *msg) void fsm_msgWipeDevice(WipeDevice *msg) { (void)msg; - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "wipe the device?", NULL, "All data will be lost.", NULL, NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -281,15 +322,15 @@ void fsm_msgWipeDevice(WipeDevice *msg) storage_clearPinArea(); // 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"); + fsm_sendSuccess(_("Device wiped")); layoutHome(); } void fsm_msgGetEntropy(GetEntropy *msg) { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "send entropy?", NULL, NULL, NULL, NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -338,7 +379,7 @@ void fsm_msgGetPublicKey(GetPublicKey *msg) if (msg->has_show_display && msg->show_display) { layoutPublicKey(node->public_key); if (!protectButton(ButtonRequestType_ButtonRequest_PublicKey, true)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -367,16 +408,16 @@ void fsm_msgLoadDevice(LoadDevice *msg) { CHECK_NOT_INITIALIZED - layoutDialogSwipe(&bmp_icon_question, "Cancel", "I take the risk", NULL, "Loading private seed", "is not recommended.", "Continue only if you", "know what you are", "doing!", NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } if (msg->has_mnemonic && !(msg->has_skip_checksum && msg->skip_checksum) ) { if (!mnemonic_check(msg->mnemonic)) { - fsm_sendFailure(FailureType_Failure_DataError, "Mnemonic with wrong checksum provided"); + fsm_sendFailure(FailureType_Failure_DataError, _("Mnemonic with wrong checksum provided")); layoutHome(); return; } @@ -384,7 +425,7 @@ void fsm_msgLoadDevice(LoadDevice *msg) storage_loadDevice(msg); storage_commit(); - fsm_sendSuccess("Device loaded"); + fsm_sendSuccess(_("Device loaded")); layoutHome(); } @@ -392,7 +433,7 @@ void fsm_msgResetDevice(ResetDevice *msg) { CHECK_NOT_INITIALIZED - CHECK_PARAM(!msg->has_strength || msg->strength == 128 || msg->strength == 192 || msg->strength == 256, "Invalid seed strength"); + CHECK_PARAM(!msg->has_strength || msg->strength == 128 || msg->strength == 192 || msg->strength == 256, _("Invalid seed strength")); reset_init( msg->has_display_random && msg->display_random, @@ -409,8 +450,8 @@ void fsm_msgSignTx(SignTx *msg) { CHECK_INITIALIZED - CHECK_PARAM(msg->inputs_count > 0, "Transaction must have at least one input"); - CHECK_PARAM(msg->outputs_count > 0, "Transaction must have at least one output"); + CHECK_PARAM(msg->inputs_count > 0, _("Transaction must have at least one input")); + CHECK_PARAM(msg->outputs_count > 0, _("Transaction must have at least one output")); CHECK_PIN @@ -424,7 +465,7 @@ void fsm_msgSignTx(SignTx *msg) void fsm_msgTxAck(TxAck *msg) { - CHECK_PARAM(msg->has_tx, "No transaction provided"); + CHECK_PARAM(msg->has_tx, _("No transaction provided")); signing_txack(&(msg->tx)); } @@ -435,7 +476,7 @@ void fsm_msgCancel(Cancel *msg) recovery_abort(); signing_abort(); ethereum_signing_abort(); - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); } void fsm_msgEthereumSignTx(EthereumSignTx *msg) @@ -459,9 +500,9 @@ void fsm_msgCipherKeyValue(CipherKeyValue *msg) { CHECK_INITIALIZED - CHECK_PARAM(msg->has_key, "No key provided"); - CHECK_PARAM(msg->has_value, "No value provided"); - CHECK_PARAM(msg->value.size % 16 == 0, "Value length must be a multiple of 16"); + CHECK_PARAM(msg->has_key, _("No key provided")); + CHECK_PARAM(msg->has_value, _("No value provided")); + CHECK_PARAM(msg->value.size % 16 == 0, _("Value length must be a multiple of 16")); CHECK_PIN @@ -474,7 +515,7 @@ void fsm_msgCipherKeyValue(CipherKeyValue *msg) if ((encrypt && ask_on_encrypt) || (!encrypt && ask_on_decrypt)) { layoutCipherKeyValue(encrypt, msg->key); if (!protectButton(ButtonRequestType_ButtonRequest_Other, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -508,43 +549,43 @@ void fsm_msgClearSession(ClearSession *msg) (void)msg; session_clear(true); // clear PIN as well layoutScreensaver(); - fsm_sendSuccess("Session cleared"); + fsm_sendSuccess(_("Session cleared")); } void fsm_msgApplySettings(ApplySettings *msg) { - CHECK_PARAM(msg->has_label || msg->has_language || msg->has_use_passphrase || msg->has_homescreen, "No setting provided"); + CHECK_PARAM(msg->has_label || msg->has_language || msg->has_use_passphrase || msg->has_homescreen, _("No setting provided")); CHECK_PIN if (msg->has_label) { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "change label to", msg->label, "?", NULL, NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } } if (msg->has_language) { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "change language to", msg->language, "?", NULL, NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } } if (msg->has_use_passphrase) { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", msg->use_passphrase ? "enable passphrase" : "disable passphrase", "encryption?", NULL, NULL, NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } } if (msg->has_homescreen) { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you really want to", "change the home", "screen ?", NULL, NULL, NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -563,7 +604,7 @@ void fsm_msgApplySettings(ApplySettings *msg) storage_setHomescreen(msg->homescreen.bytes, msg->homescreen.size); } storage_commit(); - fsm_sendSuccess("Settings applied"); + fsm_sendSuccess(_("Settings applied")); layoutHome(); } @@ -581,9 +622,9 @@ void fsm_msgGetAddress(GetAddress *msg) if (!node) return; hdnode_fill_public_key(node); - layoutProgress("Computing address", 0); + layoutProgress(_("Computing address"), 0); if (!compute_address(coin, msg->script_type, node, msg->has_multisig, &msg->multisig, resp->address)) { - fsm_sendFailure(FailureType_Failure_DataError, "Can't encode address"); + fsm_sendFailure(FailureType_Failure_DataError, _("Can't encode address")); } if (msg->has_show_display && msg->show_display) { @@ -597,11 +638,11 @@ void fsm_msgGetAddress(GetAddress *msg) desc[11] = (n < 10) ? ' ': ('0' + (n / 10)); desc[12] = '0' + (n % 10); } else { - strlcpy(desc, "Address:", sizeof(desc)); + strlcpy(desc, _("Address:"), sizeof(desc)); } layoutAddress(resp->address, desc); if (!protectButton(ButtonRequestType_ButtonRequest_Address, true)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -636,7 +677,7 @@ void fsm_msgEthereumGetAddress(EthereumGetAddress *msg) layoutAddress(address, desc); if (!protectButton(ButtonRequestType_ButtonRequest_Address, true)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -663,7 +704,7 @@ void fsm_msgSignMessage(SignMessage *msg) layoutSignMessage(msg->message.bytes, msg->message.size); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -675,7 +716,7 @@ void fsm_msgSignMessage(SignMessage *msg) HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count); if (!node) return; - layoutProgressSwipe("Signing", 0); + layoutProgressSwipe(_("Signing"), 0); if (cryptoMessageSign(coin, node, msg->message.bytes, msg->message.size, resp->signature.bytes) == 0) { resp->has_address = true; hdnode_get_address(node, coin->address_type, resp->address, sizeof(resp->address)); @@ -683,41 +724,41 @@ void fsm_msgSignMessage(SignMessage *msg) resp->signature.size = 65; msg_write(MessageType_MessageType_MessageSignature, resp); } else { - fsm_sendFailure(FailureType_Failure_ProcessError, "Error signing message"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Error signing message")); } layoutHome(); } void fsm_msgVerifyMessage(VerifyMessage *msg) { - CHECK_PARAM(msg->has_address, "No address provided"); - CHECK_PARAM(msg->has_message, "No message provided"); + CHECK_PARAM(msg->has_address, _("No address provided")); + CHECK_PARAM(msg->has_message, _("No message provided")); const CoinType *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name); if (!coin) return; uint8_t addr_raw[MAX_ADDR_RAW_SIZE]; uint32_t address_type; if (!coinExtractAddressType(coin, msg->address, &address_type) || !ecdsa_address_decode(msg->address, address_type, addr_raw)) { - fsm_sendFailure(FailureType_Failure_DataError, "Invalid address"); + fsm_sendFailure(FailureType_Failure_DataError, _("Invalid address")); return; } - layoutProgressSwipe("Verifying", 0); + layoutProgressSwipe(_("Verifying"), 0); if (msg->signature.size == 65 && cryptoMessageVerify(coin, msg->message.bytes, msg->message.size, address_type, addr_raw, msg->signature.bytes) == 0) { layoutVerifyAddress(msg->address); if (!protectButton(ButtonRequestType_ButtonRequest_Other, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } layoutVerifyMessage(msg->message.bytes, msg->message.size); if (!protectButton(ButtonRequestType_ButtonRequest_Other, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } - fsm_sendSuccess("Message verified"); + fsm_sendSuccess(_("Message verified")); } else { - fsm_sendFailure(FailureType_Failure_DataError, "Invalid signature"); + fsm_sendFailure(FailureType_Failure_DataError, _("Invalid signature")); } layoutHome(); } @@ -730,7 +771,7 @@ void fsm_msgSignIdentity(SignIdentity *msg) layoutSignIdentity(&(msg->identity), msg->has_challenge_visual ? msg->challenge_visual : 0); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -739,7 +780,7 @@ void fsm_msgSignIdentity(SignIdentity *msg) uint8_t hash[32]; if (!msg->has_identity || cryptoIdentityFingerprint(&(msg->identity), hash) == 0) { - fsm_sendFailure(FailureType_Failure_DataError, "Invalid identity"); + fsm_sendFailure(FailureType_Failure_DataError, _("Invalid identity")); layoutHome(); return; } @@ -762,7 +803,7 @@ void fsm_msgSignIdentity(SignIdentity *msg) bool sign_gpg = msg->identity.has_proto && (strcmp(msg->identity.proto, "gpg") == 0); int result = 0; - layoutProgressSwipe("Signing", 0); + layoutProgressSwipe(_("Signing"), 0); if (sign_ssh) { // SSH does not sign visual challenge result = sshMessageSign(node, msg->challenge_hidden.bytes, msg->challenge_hidden.size, resp->signature.bytes); } else if (sign_gpg) { // GPG should sign a message digest @@ -793,7 +834,7 @@ void fsm_msgSignIdentity(SignIdentity *msg) resp->signature.size = 65; msg_write(MessageType_MessageType_SignedIdentity, resp); } else { - fsm_sendFailure(FailureType_Failure_ProcessError, "Error signing identity"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Error signing identity")); } layoutHome(); } @@ -806,7 +847,7 @@ void fsm_msgGetECDHSessionKey(GetECDHSessionKey *msg) layoutDecryptIdentity(&msg->identity); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -815,7 +856,7 @@ void fsm_msgGetECDHSessionKey(GetECDHSessionKey *msg) uint8_t hash[32]; if (!msg->has_identity || cryptoIdentityFingerprint(&(msg->identity), hash) == 0) { - fsm_sendFailure(FailureType_Failure_DataError, "Invalid identity"); + fsm_sendFailure(FailureType_Failure_DataError, _("Invalid identity")); layoutHome(); return; } @@ -841,7 +882,7 @@ void fsm_msgGetECDHSessionKey(GetECDHSessionKey *msg) resp->session_key.size = result_size; msg_write(MessageType_MessageType_ECDHSessionKey, resp); } else { - fsm_sendFailure(FailureType_Failure_ProcessError, "Error getting ECDH session key"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Error getting ECDH session key")); } layoutHome(); } @@ -851,11 +892,11 @@ void fsm_msgEncryptMessage(EncryptMessage *msg) { CHECK_INITIALIZED - CHECK_PARAM(msg->has_pubkey, "No public key provided"); - CHECK_PARAM(msg->has_message, "No message provided"); - CHECK_PARAM(msg->pubkey.size == 33, "Invalid public key provided"); + CHECK_PARAM(msg->has_pubkey, _("No public key provided")); + CHECK_PARAM(msg->has_message, _("No message provided")); + CHECK_PARAM(msg->pubkey.size == 33, _("Invalid public key provided")); curve_point pubkey; - CHECK_PARAM(ecdsa_read_pubkey(&secp256k1, msg->pubkey.bytes, &pubkey) == 1, "Invalid public key provided"); + CHECK_PARAM(ecdsa_read_pubkey(&secp256k1, msg->pubkey.bytes, &pubkey) == 1, _("Invalid public key provided")); bool display_only = msg->has_display_only && msg->display_only; bool signing = msg->address_n_count > 0; @@ -874,13 +915,13 @@ void fsm_msgEncryptMessage(EncryptMessage *msg) } layoutEncryptMessage(msg->message.bytes, msg->message.size, signing); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } - layoutProgressSwipe("Encrypting", 0); + 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_ProcessError, "Error encrypting message"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Error encrypting message")); layoutHome(); return; } @@ -895,26 +936,26 @@ void fsm_msgDecryptMessage(DecryptMessage *msg) { CHECK_INITIALIZED - CHECK_PARAM(msg->has_nonce, "No nonce provided"); - CHECK_PARAM(msg->has_message, "No message provided"); - CHECK_PARAM(msg->has_hmac, "No message hmac provided"); + CHECK_PARAM(msg->has_nonce, _("No nonce provided")); + CHECK_PARAM(msg->has_message, _("No message provided")); + CHECK_PARAM(msg->has_hmac, _("No message hmac provided")); - CHECK_PARAM(msg->nonce.size == 33, "Invalid nonce key provided"); + CHECK_PARAM(msg->nonce.size == 33, _("Invalid nonce key provided")); curve_point nonce_pubkey; - CHECK_PARAM(ecdsa_read_pubkey(&secp256k1, msg->nonce.bytes, &nonce_pubkey) == 1, "Invalid nonce provided"); + CHECK_PARAM(ecdsa_read_pubkey(&secp256k1, msg->nonce.bytes, &nonce_pubkey) == 1, _("Invalid nonce provided")); CHECK_PIN const HDNode *node = fsm_getDerivedNode(SECP256K1_NAME, msg->address_n, msg->address_n_count); if (!node) return; - layoutProgressSwipe("Decrypting", 0); + layoutProgressSwipe(_("Decrypting"), 0); RESP_INIT(DecryptedMessage); bool display_only = false; bool signing = false; uint8_t address_raw[MAX_ADDR_RAW_SIZE]; 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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -949,7 +990,7 @@ void fsm_msgRecoveryDevice(RecoveryDevice *msg) { CHECK_NOT_INITIALIZED - CHECK_PARAM(!msg->has_word_count || msg->word_count == 12 || msg->word_count == 18 || msg->word_count == 24, "Invalid word count"); + CHECK_PARAM(!msg->has_word_count || msg->word_count == 12 || msg->word_count == 18 || msg->word_count == 24, _("Invalid word count")); recovery_init( msg->has_word_count ? msg->word_count : 12, @@ -970,14 +1011,14 @@ void fsm_msgWordAck(WordAck *msg) void fsm_msgSetU2FCounter(SetU2FCounter *msg) { - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", NULL, "Do you want to set", "the U2F counter?", NULL, NULL, NULL, NULL); + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), NULL, _("Do you want to set"), _("the U2F counter?"), NULL, NULL, NULL, NULL); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } storage_setU2FCounter(msg->u2f_counter); - fsm_sendSuccess("U2F counter set"); + fsm_sendSuccess(_("U2F counter set")); layoutHome(); } diff --git a/firmware/gettext.h b/firmware/gettext.h new file mode 100644 index 0000000..c663dfb --- /dev/null +++ b/firmware/gettext.h @@ -0,0 +1,25 @@ +/* + * This file is part of the TREZOR project. + * + * Copyright (C) 2017 Pavol Rusnak + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef __GETTEXT_H__ +#define __GETTEXT_H__ + +#define _(X) (X) + +#endif diff --git a/firmware/layout2.c b/firmware/layout2.c index 0611b3c..64a8fa2 100644 --- a/firmware/layout2.c +++ b/firmware/layout2.c @@ -30,6 +30,7 @@ #include "qr_encode.h" #include "timer.h" #include "bignum.h" +#include "gettext.h" void *layoutLast = layoutHome; @@ -66,7 +67,7 @@ void layoutHome(void) oledSwipeLeft(); } layoutLast = layoutHome; - const char *label = storage_isInitialized() ? storage_getLabel() : "Go to trezor.io/start"; + const char *label = storage_isInitialized() ? storage_getLabel() : _("Go to trezor.io/start"); const uint8_t *homescreen = storage_getHomescreen(); if (homescreen) { BITMAP b; @@ -97,12 +98,12 @@ void layoutConfirmOutput(const CoinType *coin, const TxOutputType *out) static char first_half[17 + 1]; strlcpy(first_half, out->address, sizeof(first_half)); layoutDialogSwipe(&bmp_icon_question, - "Cancel", - "Confirm", + _("Cancel"), + _("Confirm"), NULL, - "Confirm sending", + _("Confirm sending"), str_out, - "to", + _("to"), first_half, out->address + 17, NULL @@ -118,13 +119,13 @@ void layoutConfirmTx(const CoinType *coin, uint64_t amount_out, uint64_t amount_ bn_read_uint64(amount_fee, &amnt); bn_format(&amnt, NULL, coin->has_coin_shortcut ? coin->coin_shortcut : NULL, 8, str_fee, sizeof(str_fee)); layoutDialogSwipe(&bmp_icon_question, - "Cancel", - "Confirm", + _("Cancel"), + _("Confirm"), NULL, - "Really send", + _("Really send"), str_out, - "from your wallet?", - "Fee included:", + _("from your wallet?"), + _("Fee included:"), str_fee, NULL ); @@ -137,14 +138,14 @@ void layoutFeeOverThreshold(const CoinType *coin, uint64_t fee) bn_read_uint64(fee, &amnt); bn_format(&amnt, NULL, coin->has_coin_shortcut ? coin->coin_shortcut : NULL, 8, str_fee, sizeof(str_fee)); layoutDialogSwipe(&bmp_icon_question, - "Cancel", - "Confirm", + _("Cancel"), + _("Confirm"), NULL, - "Fee", + _("Fee"), str_fee, - "is unexpectedly high.", + _("is unexpectedly high."), NULL, - "Send anyway?", + _("Send anyway?"), NULL ); } @@ -174,49 +175,49 @@ const char **split_message(const uint8_t *msg, uint32_t len, uint32_t rowlen) void layoutSignMessage(const uint8_t *msg, uint32_t len) { const char **str = split_message(msg, len, 16); - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", - "Sign message?", + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), + _("Sign message?"), str[0], str[1], str[2], str[3], NULL, NULL); } void layoutVerifyAddress(const char *address) { const char **str = split_message((const uint8_t *)address, strlen(address), 17); - layoutDialogSwipe(&bmp_icon_info, "Cancel", "Confirm", - "Confirm address?", - "Message signed by:", + layoutDialogSwipe(&bmp_icon_info, _("Cancel"), _("Confirm"), + _("Confirm address?"), + _("Message signed by:"), NULL, str[0], str[1], str[2], NULL); } void layoutVerifyMessage(const uint8_t *msg, uint32_t len) { const char **str = split_message(msg, len, 16); - layoutDialogSwipe(&bmp_icon_info, "Cancel", "Confirm", - "Verified message", + layoutDialogSwipe(&bmp_icon_info, _("Cancel"), _("Confirm"), + _("Verified message"), str[0], str[1], str[2], str[3], NULL, NULL); } void layoutCipherKeyValue(bool encrypt, const char *key) { const char **str = split_message((const uint8_t *)key, strlen(key), 16); - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", - encrypt ? "Encode value of this key?" : "Decode value of this key?", + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), + encrypt ? _("Encode value of this key?") : _("Decode value of this key?"), str[0], str[1], str[2], str[3], NULL, NULL); } void layoutEncryptMessage(const uint8_t *msg, uint32_t len, bool signing) { const char **str = split_message(msg, len, 16); - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", - signing ? "Encrypt+Sign message?" : "Encrypt message?", + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), + signing ? _("Encrypt+Sign message?") : _("Encrypt message?"), str[0], str[1], str[2], str[3], NULL, NULL); } void layoutDecryptMessage(const uint8_t *msg, uint32_t len, const char *address) { const char **str = split_message(msg, len, 16); - layoutDialogSwipe(&bmp_icon_info, NULL, "OK", - address ? "Decrypted signed message" : "Decrypted message", + layoutDialogSwipe(&bmp_icon_info, NULL, _("OK"), + address ? _("Decrypted signed message") : _("Decrypted message"), str[0], str[1], str[2], str[3], NULL, NULL); } @@ -273,7 +274,7 @@ void layoutAddress(const char *address, const char *desc) oledDrawString(startx, (i+1) * 9 + 4, str[i]); } - static const char *btnYes = "Continue"; + static const char *btnYes = _("Continue"); oledDrawString(OLED_WIDTH - fontCharWidth('\x06') - 1, OLED_HEIGHT - 8, "\x06"); oledDrawString(OLED_WIDTH - oledStringWidth(btnYes) - fontCharWidth('\x06') - 3, OLED_HEIGHT - 8, btnYes); oledInvert(OLED_WIDTH - oledStringWidth(btnYes) - fontCharWidth('\x06') - 4, OLED_HEIGHT - 9, OLED_WIDTH - 1, OLED_HEIGHT - 1); @@ -288,7 +289,7 @@ void layoutPublicKey(const uint8_t *pubkey) data2hex(pubkey, 1, desc + 12); data2hex(pubkey + 1, 32, hex); const char **str = split_message((const uint8_t *)hex, 32*2, 16); - layoutDialogSwipe(&bmp_icon_question, NULL, "Continue", NULL, + layoutDialogSwipe(&bmp_icon_question, NULL, _("Continue"), NULL, desc, str[0], str[1], str[2], str[3], NULL); } @@ -302,17 +303,17 @@ void layoutSignIdentity(const IdentityType *identity, const char *challenge) if (identity->has_proto && identity->proto[0]) { if (strcmp(identity->proto, "https") == 0) { - strlcpy(row_proto, "Web sign in to:", sizeof(row_proto)); + strlcpy(row_proto, _("Web sign in to:"), sizeof(row_proto)); } else if (is_gpg) { - strlcpy(row_proto, "GPG sign for:", sizeof(row_proto)); + strlcpy(row_proto, _("GPG sign for:"), sizeof(row_proto)); } else { strlcpy(row_proto, identity->proto, sizeof(row_proto)); char *p = row_proto; while (*p) { *p = toupper((int)*p); p++; } - strlcat(row_proto, " login to:", sizeof(row_proto)); + strlcat(row_proto, _(" login to:"), sizeof(row_proto)); } } else { - strlcpy(row_proto, "Login to:", sizeof(row_proto)); + strlcpy(row_proto, _("Login to:"), sizeof(row_proto)); } if (identity->has_host && identity->host[0]) { @@ -326,7 +327,7 @@ void layoutSignIdentity(const IdentityType *identity, const char *challenge) } if (identity->has_user && identity->user[0]) { - strlcpy(row_user, "user: ", sizeof(row_user)); + strlcpy(row_user, _("user: "), sizeof(row_user)); strlcat(row_user, identity->user, sizeof(row_user)); } else { row_user[0] = 0; @@ -347,8 +348,8 @@ void layoutSignIdentity(const IdentityType *identity, const char *challenge) } } - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", - "Do you want to sign in?", + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), + _("Do you want to sign in?"), row_proto[0] ? row_proto : NULL, row_hostport[0] ? row_hostport : NULL, row_user[0] ? row_user : NULL, @@ -367,9 +368,9 @@ void layoutDecryptIdentity(const IdentityType *identity) strlcpy(row_proto, identity->proto, sizeof(row_proto)); char *p = row_proto; while (*p) { *p = toupper((int)*p); p++; } - strlcat(row_proto, " decrypt for:", sizeof(row_proto)); + strlcat(row_proto, _(" decrypt for:"), sizeof(row_proto)); } else { - strlcpy(row_proto, "Decrypt for:", sizeof(row_proto)); + strlcpy(row_proto, _("Decrypt for:"), sizeof(row_proto)); } if (identity->has_host && identity->host[0]) { @@ -383,14 +384,14 @@ void layoutDecryptIdentity(const IdentityType *identity) } if (identity->has_user && identity->user[0]) { - strlcpy(row_user, "user: ", sizeof(row_user)); + strlcpy(row_user, _("user: "), sizeof(row_user)); strlcat(row_user, identity->user, sizeof(row_user)); } else { row_user[0] = 0; } - layoutDialogSwipe(&bmp_icon_question, "Cancel", "Confirm", - "Do you want to decrypt?", + layoutDialogSwipe(&bmp_icon_question, _("Cancel"), _("Confirm"), + _("Do you want to decrypt?"), row_proto[0] ? row_proto : NULL, row_hostport[0] ? row_hostport : NULL, row_user[0] ? row_user : NULL, @@ -403,5 +404,5 @@ void layoutU2FDialog(const char *verb, const char *appname, const BITMAP *appico if (!appicon) { appicon = &bmp_icon_question; } - layoutDialog(appicon, NULL, verb, NULL, verb, "U2F security key?", NULL, appname, NULL, NULL); + layoutDialog(appicon, NULL, verb, NULL, verb, _("U2F security key?"), NULL, appname, NULL, NULL); } diff --git a/firmware/messages.c b/firmware/messages.c index dcdee40..1e15251 100644 --- a/firmware/messages.c +++ b/firmware/messages.c @@ -24,6 +24,7 @@ #include "debug.h" #include "fsm.h" #include "util.h" +#include "gettext.h" #include "pb_decode.h" #include "pb_encode.h" @@ -254,11 +255,11 @@ void msg_read_common(char type, const uint8_t *buf, int len) fields = MessageFields(type, 'i', msg_id); if (!fields) { // unknown message - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Unknown message"); + fsm_sendFailure(FailureType_Failure_UnexpectedMessage, _("Unknown message")); return; } if (msg_size > MSG_IN_SIZE) { // message is too big :( - fsm_sendFailure(FailureType_Failure_DataError, "Message too big"); + fsm_sendFailure(FailureType_Failure_DataError, _("Message too big")); return; } @@ -357,7 +358,7 @@ void msg_read_tiny(const uint8_t *buf, int len) msg_tiny_id = 0xFFFF; } } else { - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Unknown message"); + fsm_sendFailure(FailureType_Failure_UnexpectedMessage, _("Unknown message")); msg_tiny_id = 0xFFFF; } } diff --git a/firmware/protect.c b/firmware/protect.c index d47e581..01e44f0 100644 --- a/firmware/protect.c +++ b/firmware/protect.c @@ -28,6 +28,7 @@ #include "layout2.h" #include "util.h" #include "debug.h" +#include "gettext.h" bool protectAbortedByInitialize = false; @@ -152,7 +153,7 @@ bool protectPin(bool use_cached) while (wait > 0) { // convert wait to secstr string char secstrbuf[20]; - strlcpy(secstrbuf, "________0 seconds", sizeof(secstrbuf)); + strlcpy(secstrbuf, _("________0 seconds"), sizeof(secstrbuf)); char *secstr = secstrbuf + 9; uint32_t secs = wait; while (secs > 0 && secstr >= secstrbuf) { @@ -163,23 +164,23 @@ bool protectPin(bool use_cached) if (wait == 1) { secstrbuf[16] = 0; } - layoutDialog(&bmp_icon_info, NULL, NULL, NULL, "Wrong PIN entered", NULL, "Please wait", secstr, "to continue ...", NULL); + layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Wrong PIN entered"), NULL, _("Please wait"), secstr, _("to continue ..."), NULL); // wait one second usbSleep(1000); if (msg_tiny_id == MessageType_MessageType_Initialize) { protectAbortedByInitialize = true; msg_tiny_id = 0xFFFF; usbTiny(0); - fsm_sendFailure(FailureType_Failure_PinCancelled, "PIN cancelled"); + fsm_sendFailure(FailureType_Failure_PinCancelled, NULL); return false; } wait--; } usbTiny(0); const char *pin; - pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_Current, "Please enter current PIN:"); + pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_Current, _("Please enter current PIN:")); if (!pin) { - fsm_sendFailure(FailureType_Failure_PinCancelled, "PIN cancelled"); + fsm_sendFailure(FailureType_Failure_PinCancelled, NULL); return false; } if (storage_increasePinFails(fails) && storage_isPinCorrect(pin)) { @@ -187,7 +188,7 @@ bool protectPin(bool use_cached) storage_resetPinFails(fails); return true; } else { - fsm_sendFailure(FailureType_Failure_PinInvalid, "PIN invalid"); + fsm_sendFailure(FailureType_Failure_PinInvalid, NULL); return false; } } @@ -196,12 +197,12 @@ bool protectChangePin(void) { const char *pin; char pin1[17], pin2[17]; - pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_NewFirst, "Please enter new PIN:"); + pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_NewFirst, _("Please enter new PIN:")); if (!pin) { return false; } strlcpy(pin1, pin, sizeof(pin1)); - pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_NewSecond, "Please re-enter new PIN:"); + pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_NewSecond, _("Please re-enter new PIN:")); if (!pin) { return false; } @@ -225,7 +226,7 @@ bool protectPassphrase(void) usbTiny(1); msg_write(MessageType_MessageType_PassphraseRequest, &resp); - layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, "Please enter your", "passphrase using", "the computer's", "keyboard.", NULL, NULL); + layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, _("Please enter your"), _("passphrase using"), _("the computer's"), _("keyboard."), NULL, NULL); bool result; for (;;) { diff --git a/firmware/recovery.c b/firmware/recovery.c index a12328c..da0a698 100644 --- a/firmware/recovery.c +++ b/firmware/recovery.c @@ -30,6 +30,7 @@ #include "bip39.h" #include "oled.h" #include "usb.h" +#include "gettext.h" #include "types.pb.h" #include "recovery-table.h" @@ -138,10 +139,10 @@ static void recovery_done(void) { storage.imported = true; } storage_commit(); - fsm_sendSuccess("Device recovered"); + fsm_sendSuccess(_("Device recovered")); } else { storage_reset(); - fsm_sendFailure(FailureType_Failure_DataError, "Invalid mnemonic, are words in correct order?"); + fsm_sendFailure(FailureType_Failure_DataError, _("Invalid mnemonic, are words in correct order?")); } awaiting_word = 0; layoutHome(); @@ -212,7 +213,7 @@ static void display_choices(bool twoColumn, char choices[9][12], int num) char desc[] = "##th word"; int nr = (word_index / 4) + 1; format_number(desc, nr); - layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, "Please enter the", (nr < 10 ? desc + 1 : desc), "of your mnemonic", NULL, NULL, NULL); + layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, _("Please enter the"), (nr < 10 ? desc + 1 : desc), _("of your mnemonic"), NULL, NULL, NULL); } else { oledBox(0, 27, 127, 63, false); } @@ -358,12 +359,12 @@ void next_word(void) { if (word_pos == 0) { const char * const *wl = mnemonic_wordlist(); strlcpy(fake_word, wl[random_uniform(2048)], sizeof(fake_word)); - layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, "Please enter the word", NULL, fake_word, NULL, "on your computer", NULL); + layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, _("Please enter the word"), NULL, fake_word, NULL, _("on your computer"), NULL); } else { fake_word[0] = 0; char desc[] = "##th word"; format_number(desc, word_pos); - layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, "Please enter the", NULL, (word_pos < 10 ? desc + 1 : desc), NULL, "of your mnemonic", NULL); + layoutDialogSwipe(&bmp_icon_info, NULL, NULL, NULL, _("Please enter the"), NULL, (word_pos < 10 ? desc + 1 : desc), NULL, _("of your mnemonic"), NULL); } recovery_request(); } @@ -376,7 +377,7 @@ void recovery_init(uint32_t _word_count, bool passphrase_protection, bool pin_pr enforce_wordlist = _enforce_wordlist; if (pin_protection && !protectChangePin()) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -411,7 +412,7 @@ static void recovery_scrambledword(const char *word) if (word_pos == 0) { // fake word if (strcmp(word, fake_word) != 0) { storage_reset(); - fsm_sendFailure(FailureType_Failure_ProcessError, "Wrong word retyped"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Wrong word retyped")); layoutHome(); return; } @@ -428,7 +429,7 @@ static void recovery_scrambledword(const char *word) } if (!found) { storage_reset(); - fsm_sendFailure(FailureType_Failure_DataError, "Word not found in a wordlist"); + fsm_sendFailure(FailureType_Failure_DataError, _("Word not found in a wordlist")); layoutHome(); return; } @@ -457,7 +458,7 @@ void recovery_word(const char *word) recovery_scrambledword(word); break; default: - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Recovery mode"); + fsm_sendFailure(FailureType_Failure_UnexpectedMessage, _("Not in Recovery mode")); break; } } diff --git a/firmware/reset.c b/firmware/reset.c index f10ecd2..4428753 100644 --- a/firmware/reset.c +++ b/firmware/reset.c @@ -28,6 +28,7 @@ #include "protect.h" #include "bip39.h" #include "util.h" +#include "gettext.h" static uint32_t strength; static uint8_t int_entropy[32]; @@ -48,16 +49,16 @@ void reset_init(bool display_random, uint32_t _strength, bool passphrase_protect data2hex(int_entropy + 24, 8, ent_str[3]); if (display_random) { - layoutDialogSwipe(&bmp_icon_info, "Cancel", "Continue", NULL, "Internal entropy:", ent_str[0], ent_str[1], ent_str[2], ent_str[3], NULL); + layoutDialogSwipe(&bmp_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, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } } if (pin_protection && !protectChangePin()) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); layoutHome(); return; } @@ -79,7 +80,7 @@ static char current_word[10], current_word_display[11]; void reset_entropy(const uint8_t *ext_entropy, uint32_t len) { if (!awaiting_entropy) { - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Reset mode"); + fsm_sendFailure(FailureType_Failure_UnexpectedMessage, _("Not in Reset mode")); return; } SHA256_CTX ctx; @@ -126,21 +127,21 @@ void reset_entropy(const uint8_t *ext_entropy, uint32_t len) current_word_display[j + 1] = 0; if (word_pos == (int)strength/32*3) { // last word if (pass == 1) { - layoutDialogSwipe(&bmp_icon_info, NULL, "Finish", NULL, "Please check the seed", NULL, (word_pos < 10 ? desc + 1 : desc), current_word_display, NULL, NULL); + layoutDialogSwipe(&bmp_icon_info, NULL, _("Finish"), NULL, _("Please check the seed"), NULL, (word_pos < 10 ? desc + 1 : desc), current_word_display, NULL, NULL); } else { - layoutDialogSwipe(&bmp_icon_info, NULL, "Again", NULL, "Write down the seed", NULL, (word_pos < 10 ? desc + 1 : desc), current_word_display, NULL, NULL); + layoutDialogSwipe(&bmp_icon_info, NULL, _("Again"), NULL, _("Write down the seed"), NULL, (word_pos < 10 ? desc + 1 : desc), current_word_display, NULL, NULL); } } else { if (pass == 1) { - layoutDialogSwipe(&bmp_icon_info, NULL, "Next", NULL, "Please check the seed", NULL, (word_pos < 10 ? desc + 1 : desc), current_word_display, NULL, NULL); + layoutDialogSwipe(&bmp_icon_info, NULL, _("Next"), NULL, _("Please check the seed"), NULL, (word_pos < 10 ? desc + 1 : desc), current_word_display, NULL, NULL); } else { - layoutDialogSwipe(&bmp_icon_info, NULL, "Next", NULL, "Write down the seed", NULL, (word_pos < 10 ? desc + 1 : desc), current_word_display, NULL, NULL); + layoutDialogSwipe(&bmp_icon_info, NULL, _("Next"), NULL, _("Write down the seed"), NULL, (word_pos < 10 ? desc + 1 : desc), current_word_display, NULL, NULL); } } if (!protectButton(ButtonRequestType_ButtonRequest_ConfirmWord, true)) { storage_reset(); layoutHome(); - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); return; } } @@ -148,7 +149,7 @@ void reset_entropy(const uint8_t *ext_entropy, uint32_t len) storage.has_mnemonic = true; storage_commit(); - fsm_sendSuccess("Device reset"); + fsm_sendSuccess(_("Device reset")); layoutHome(); } diff --git a/firmware/signing.c b/firmware/signing.c index 5501b41..96e4147 100644 --- a/firmware/signing.c +++ b/firmware/signing.c @@ -26,6 +26,7 @@ #include "protect.h" #include "crypto.h" #include "secp256k1.h" +#include "gettext.h" static uint32_t inputs_count; static uint32_t outputs_count; @@ -441,7 +442,7 @@ void signing_init(uint32_t _inputs_count, uint32_t _outputs_count, const CoinTyp sha256_Init(&hashers[1]); sha256_Init(&hashers[2]); - layoutProgressSwipe("Signing transaction", 0); + layoutProgressSwipe(_("Signing transaction"), 0); send_req_1_input(); } @@ -455,7 +456,7 @@ static bool signing_check_input(TxInputType *txinput) { && txinput->script_type == InputScriptType_SPENDMULTISIG) { uint8_t h[32]; if (cryptoMultisigFingerprint(&txinput->multisig, h) == 0) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Error computing multisig fingerprint"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Error computing multisig fingerprint")); signing_abort(); return false; } @@ -487,7 +488,7 @@ static bool signing_check_prevtx_hash(void) { uint8_t hash[32]; tx_hash_final(&tp, hash, true); if (memcmp(hash, input.prev_hash.bytes, 32) != 0) { - fsm_sendFailure(FailureType_Failure_DataError, "Encountered invalid prevhash"); + fsm_sendFailure(FailureType_Failure_DataError, _("Encountered invalid prevhash")); signing_abort(); return false; } @@ -504,7 +505,7 @@ static bool signing_check_output(TxOutputType *txoutput) { bool is_change = false; if (txoutput->address_n_count > 0) { if (txoutput->has_address) { - fsm_sendFailure(FailureType_Failure_DataError, "Address in change output"); + fsm_sendFailure(FailureType_Failure_DataError, _("Address in change output")); signing_abort(); return false; } @@ -528,28 +529,28 @@ static bool signing_check_output(TxOutputType *txoutput) { if (change_spend == 0) { // not set change_spend = txoutput->amount; } else { - fsm_sendFailure(FailureType_Failure_DataError, "Only one change output allowed"); + fsm_sendFailure(FailureType_Failure_DataError, _("Only one change output allowed")); signing_abort(); return false; } } if (spending + txoutput->amount < spending) { - fsm_sendFailure(FailureType_Failure_DataError, "Value overflow"); + fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow")); signing_abort(); return false; } spending += txoutput->amount; int co = compile_output(coin, root, txoutput, &bin_output, !is_change); if (!is_change) { - layoutProgress("Signing transaction", progress); + layoutProgress(_("Signing transaction"), progress); } if (co < 0) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); signing_abort(); return false; } else if (co == 0) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to compile output"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile output")); signing_abort(); return false; } @@ -561,7 +562,7 @@ static bool signing_check_output(TxOutputType *txoutput) { static bool signing_check_fee(void) { // check fees if (spending > to_spend) { - fsm_sendFailure(FailureType_Failure_NotEnoughFunds, "Not enough funds"); + fsm_sendFailure(FailureType_Failure_NotEnoughFunds, _("Not enough funds")); signing_abort(); return false; } @@ -570,16 +571,16 @@ static bool signing_check_fee(void) { if (fee > tx_est_size_kb * coin->maxfee_kb) { layoutFeeOverThreshold(coin, fee); if (!protectButton(ButtonRequestType_ButtonRequest_FeeOverThreshold, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); signing_abort(); return false; } - layoutProgress("Signing transaction", progress); + layoutProgress(_("Signing transaction"), progress); } // last confirmation layoutConfirmTx(coin, to_spend - change_spend, fee); if (!protectButton(ButtonRequestType_ButtonRequest_SignTx, false)) { - fsm_sendFailure(FailureType_Failure_ActionCancelled, "Action cancelled by user"); + fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); signing_abort(); return false; } @@ -598,7 +599,7 @@ static void phase1_request_next_output(void) { } // Everything was checked, now phase 2 begins and the transaction is signed. progress_meta_step = progress_step / (inputs_count + outputs_count); - layoutProgress("Signing transaction", progress); + layoutProgress(_("Signing transaction"), progress); idx1 = 0; phase2_request_next_input(); } @@ -609,7 +610,7 @@ static bool signing_sign_input(void) { sha256_Final(&hashers[0], hash); sha256_Raw(hash, 32, hash); if (memcmp(hash, hash_outputs, 32) != 0) { - fsm_sendFailure(FailureType_Failure_DataError, "Transaction has changed during signing"); + fsm_sendFailure(FailureType_Failure_DataError, _("Transaction has changed during signing")); signing_abort(); return false; } @@ -620,7 +621,7 @@ static bool signing_sign_input(void) { resp.serialized.has_signature = true; resp.serialized.has_serialized_tx = true; if (ecdsa_sign_digest(&secp256k1, privkey, hash, sig, NULL, NULL) != 0) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Signing failed"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing failed")); signing_abort(); return false; } @@ -630,7 +631,7 @@ static bool signing_sign_input(void) { // fill in the signature int pubkey_idx = cryptoMultisigPubkeyIndex(&(input.multisig), pubkey); if (pubkey_idx < 0) { - fsm_sendFailure(FailureType_Failure_DataError, "Pubkey not found in multisig script"); + fsm_sendFailure(FailureType_Failure_DataError, _("Pubkey not found in multisig script")); signing_abort(); return false; } @@ -638,7 +639,7 @@ static bool signing_sign_input(void) { input.multisig.signatures[pubkey_idx].size = resp.serialized.signature.size; input.script_sig.size = serialize_script_multisig(&(input.multisig), input.script_sig.bytes); if (input.script_sig.size == 0) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to serialize multisig script"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to serialize multisig script")); signing_abort(); return false; } @@ -658,17 +659,17 @@ static bool signing_sign_segwit_input(TxInputType *txinput) { || txinput->script_type == InputScriptType_SPENDP2SHWITNESS) { // disable native segwit for now if (txinput->script_type == InputScriptType_SPENDWITNESS) { - fsm_sendFailure(FailureType_Failure_DataError, "Native segwit is disabled"); + fsm_sendFailure(FailureType_Failure_DataError, _("Native segwit is disabled")); signing_abort(); return false; } if (!compile_input_script_sig(txinput)) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to compile input"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile input")); signing_abort(); return false; } if (txinput->amount > segwit_to_spend) { - fsm_sendFailure(FailureType_Failure_DataError, "Transaction has changed during signing"); + fsm_sendFailure(FailureType_Failure_DataError, _("Transaction has changed during signing")); signing_abort(); return false; } @@ -694,7 +695,7 @@ static bool signing_sign_segwit_input(TxInputType *txinput) { resp.serialized.has_signature = true; resp.serialized.has_serialized_tx = true; if (ecdsa_sign_digest(&secp256k1, node.private_key, hash, sig, NULL, NULL) != 0) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Signing failed"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing failed")); signing_abort(); return false; } @@ -706,7 +707,7 @@ static bool signing_sign_segwit_input(TxInputType *txinput) { // fill in the signature int pubkey_idx = cryptoMultisigPubkeyIndex(&(txinput->multisig), node.public_key); if (pubkey_idx < 0) { - fsm_sendFailure(FailureType_Failure_DataError, "Pubkey not found in multisig script"); + fsm_sendFailure(FailureType_Failure_DataError, _("Pubkey not found in multisig script")); signing_abort(); return false; } @@ -760,14 +761,14 @@ static bool signing_sign_segwit_input(TxInputType *txinput) { void signing_txack(TransactionType *tx) { if (!signing) { - fsm_sendFailure(FailureType_Failure_UnexpectedMessage, "Not in Signing mode"); + fsm_sendFailure(FailureType_Failure_UnexpectedMessage, _("Not in Signing mode")); layoutHome(); return; } static int update_ctr = 0; if (update_ctr++ == 20) { - layoutProgress("Signing transaction", progress); + layoutProgress(_("Signing transaction"), progress); update_ctr = 0; } @@ -786,7 +787,7 @@ void signing_txack(TransactionType *tx) #if !ENABLE_SEGWIT_NONSEGWIT_MIXING // don't mix segwit and non-segwit inputs if (idx1 > 0 && to.is_segwit == true) { - fsm_sendFailure(FailureType_Failure_DataError, "Mixing segwit and non-segwit inputs is not allowed"); + fsm_sendFailure(FailureType_Failure_DataError, _("Mixing segwit and non-segwit inputs is not allowed")); signing_abort(); return; } @@ -795,23 +796,23 @@ void signing_txack(TransactionType *tx) } else if (tx->inputs[0].script_type == InputScriptType_SPENDWITNESS || tx->inputs[0].script_type == InputScriptType_SPENDP2SHWITNESS) { if (!coin->has_segwit || !coin->segwit) { - fsm_sendFailure(FailureType_Failure_DataError, "Segwit not enabled on this coin"); + fsm_sendFailure(FailureType_Failure_DataError, _("Segwit not enabled on this coin")); signing_abort(); return; } // disable native segwit for now if (tx->inputs[0].script_type == InputScriptType_SPENDWITNESS) { - fsm_sendFailure(FailureType_Failure_DataError, "Native segwit is disabled"); + fsm_sendFailure(FailureType_Failure_DataError, _("Native segwit is disabled")); signing_abort(); return; } if (!tx->inputs[0].has_amount) { - fsm_sendFailure(FailureType_Failure_DataError, "Segwit input without amount"); + fsm_sendFailure(FailureType_Failure_DataError, _("Segwit input without amount")); signing_abort(); return; } if (to_spend + tx->inputs[0].amount < to_spend) { - fsm_sendFailure(FailureType_Failure_DataError, "Value overflow"); + fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow")); signing_abort(); return; } @@ -820,7 +821,7 @@ void signing_txack(TransactionType *tx) if (idx1 == 0) { to.is_segwit = true; } else if (to.is_segwit == false) { - fsm_sendFailure(FailureType_Failure_DataError, "Mixing segwit and non-segwit inputs is not allowed"); + fsm_sendFailure(FailureType_Failure_DataError, _("Mixing segwit and non-segwit inputs is not allowed")); signing_abort(); return; } @@ -831,7 +832,7 @@ void signing_txack(TransactionType *tx) segwit_to_spend += tx->inputs[0].amount; phase1_request_next_input(); } else { - fsm_sendFailure(FailureType_Failure_DataError, "Wrong input script type"); + fsm_sendFailure(FailureType_Failure_DataError, _("Wrong input script type")); signing_abort(); return; } @@ -850,7 +851,7 @@ void signing_txack(TransactionType *tx) case STAGE_REQUEST_2_PREV_INPUT: progress = (idx1 * progress_step + idx2 * progress_meta_step) >> PROGRESS_PRECISION; if (!tx_serialize_input_hash(&tp, tx->inputs)) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to serialize input"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to serialize input")); signing_abort(); return; } @@ -865,13 +866,13 @@ void signing_txack(TransactionType *tx) case STAGE_REQUEST_2_PREV_OUTPUT: progress = (idx1 * progress_step + (tp.inputs_len + idx2) * progress_meta_step) >> PROGRESS_PRECISION; if (!tx_serialize_output_hash(&tp, tx->bin_outputs)) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to serialize output"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to serialize output")); signing_abort(); return; } if (idx2 == input.prev_index) { if (to_spend + tx->bin_outputs[0].amount < to_spend) { - fsm_sendFailure(FailureType_Failure_DataError, "Value overflow"); + fsm_sendFailure(FailureType_Failure_DataError, _("Value overflow")); signing_abort(); return; } @@ -891,7 +892,7 @@ void signing_txack(TransactionType *tx) return; case STAGE_REQUEST_2_PREV_EXTRADATA: if (!tx_serialize_extra_data_hash(&tp, tx->extra_data.bytes, tx->extra_data.size)) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to serialize extra data"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to serialize extra data")); signing_abort(); return; } @@ -918,7 +919,7 @@ void signing_txack(TransactionType *tx) sha256_Update(&hashers[0], &tx->inputs[0].script_type, sizeof(&tx->inputs[0].script_type)); if (idx2 == idx1) { if (!compile_input_script_sig(&tx->inputs[0])) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to compile input"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile input")); signing_abort(); return; } @@ -934,7 +935,7 @@ void signing_txack(TransactionType *tx) tx->inputs[0].script_sig.size = 0; } if (!tx_serialize_input_hash(&ti, tx->inputs)) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to serialize input"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to serialize input")); signing_abort(); return; } @@ -945,7 +946,7 @@ void signing_txack(TransactionType *tx) uint8_t hash[32]; sha256_Final(&hashers[0], hash); if (memcmp(hash, hash_check, 32) != 0) { - fsm_sendFailure(FailureType_Failure_DataError, "Transaction has changed during signing"); + fsm_sendFailure(FailureType_Failure_DataError, _("Transaction has changed during signing")); signing_abort(); return; } @@ -957,14 +958,14 @@ void signing_txack(TransactionType *tx) case STAGE_REQUEST_4_OUTPUT: progress = 500 + ((signatures * progress_step + (inputs_count + idx2) * progress_meta_step) >> PROGRESS_PRECISION); if (compile_output(coin, root, tx->outputs, &bin_output, false) <= 0) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to compile output"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile output")); signing_abort(); return; } // check hashOutputs tx_output_hash(&hashers[0], &bin_output); if (!tx_serialize_output_hash(&ti, &bin_output)) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to serialize output"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to serialize output")); signing_abort(); return; } @@ -978,7 +979,7 @@ void signing_txack(TransactionType *tx) // since this took a longer time, update progress signatures++; progress = 500 + ((signatures * progress_step) >> PROGRESS_PRECISION); - layoutProgress("Signing transaction", progress); + layoutProgress(_("Signing transaction"), progress); update_ctr = 0; if (idx1 < inputs_count - 1) { idx1++; @@ -998,7 +999,7 @@ void signing_txack(TransactionType *tx) if (tx->inputs[0].script_type == InputScriptType_SPENDP2SHWITNESS && !tx->inputs[0].has_multisig) { if (!compile_input_script_sig(&tx->inputs[0])) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to compile input"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile input")); signing_abort(); return; } @@ -1017,7 +1018,7 @@ void signing_txack(TransactionType *tx) tx->inputs[0].script_sig.bytes[2] = 0x20; // push 32 bytes (digest) // compute digest of multisig script if (!compile_script_multisig_hash(&tx->inputs[0].multisig, tx->inputs[0].script_sig.bytes + 3)) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to compile input"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile input")); signing_abort(); return; } @@ -1038,7 +1039,7 @@ void signing_txack(TransactionType *tx) case STAGE_REQUEST_5_OUTPUT: if (compile_output(coin, root, tx->outputs, &bin_output,false) <= 0) { - fsm_sendFailure(FailureType_Failure_ProcessError, "Failed to compile output"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Failed to compile output")); signing_abort(); return; } @@ -1063,7 +1064,7 @@ void signing_txack(TransactionType *tx) } signatures++; progress = 500 + ((signatures * progress_step) >> PROGRESS_PRECISION); - layoutProgress("Signing transaction", progress); + layoutProgress(_("Signing transaction"), progress); update_ctr = 0; if (idx1 < inputs_count - 1) { idx1++; @@ -1075,7 +1076,7 @@ void signing_txack(TransactionType *tx) return; } - fsm_sendFailure(FailureType_Failure_ProcessError, "Signing error"); + fsm_sendFailure(FailureType_Failure_ProcessError, _("Signing error")); signing_abort(); } diff --git a/firmware/storage.c b/firmware/storage.c index 97f5f6a..ec85cda 100644 --- a/firmware/storage.c +++ b/firmware/storage.c @@ -40,6 +40,7 @@ #include "protect.h" #include "layout2.h" #include "usb.h" +#include "gettext.h" Storage storage; @@ -105,7 +106,7 @@ static char sessionPassphrase[51]; void storage_show_error(void) { - layoutDialog(&bmp_icon_error, NULL, NULL, NULL, "Storage failure", "detected.", NULL, "Please unplug", "the device.", NULL); + layoutDialog(&bmp_icon_error, NULL, NULL, NULL, _("Storage failure"), _("detected."), NULL, _("Please unplug"), _("the device."), NULL); system_halt(); } @@ -339,7 +340,7 @@ void storage_setHomescreen(const uint8_t *data, uint32_t size) void get_root_node_callback(uint32_t iter, uint32_t total) { usbSleep(1); - layoutProgress("Waking up", 1000 * iter / total); + layoutProgress(_("Waking up"), 1000 * iter / total); } const uint8_t *storage_getSeed(bool usePassphrase) diff --git a/firmware/u2f.c b/firmware/u2f.c index 6c24617..7c4a6b8 100644 --- a/firmware/u2f.c +++ b/firmware/u2f.c @@ -17,7 +17,6 @@ * along with this library. If not, see . */ - #include #include @@ -34,6 +33,7 @@ #include "hmac.h" #include "util.h" #include "macros.h" +#include "gettext.h" #include "u2f/u2f.h" #include "u2f/u2f_hid.h" @@ -564,12 +564,12 @@ void u2f_register(const APDU *a) // error: testof-user-presence is required buttonUpdate(); // Clear button state if (0 == memcmp(req->appId, BOGUS_APPID, U2F_APPID_SIZE)) { - layoutDialog(&bmp_icon_warning, NULL, "OK", NULL, "Another U2F device", "was used to register", "in this application.", NULL, NULL, NULL); + layoutDialog(&bmp_icon_warning, NULL, _("OK"), NULL, _("Another U2F device"), _("was used to register"), _("in this application."), NULL, NULL, NULL); } else { const char *appname; const BITMAP *appicon; getReadableAppId(req->appId, &appname, &appicon); - layoutU2FDialog("Register", appname, appicon); + layoutU2FDialog(_("Register"), appname, appicon); } last_req_state = REG; } @@ -704,7 +704,7 @@ void u2f_authenticate(const APDU *a) const char *appname; const BITMAP *appicon; getReadableAppId(req->appId, &appname, &appicon); - layoutU2FDialog("Authenticate", appname, appicon); + layoutU2FDialog(_("Authenticate"), appname, appicon); last_req_state = AUTH; }