diff --git a/src/handler/sign_tx.c b/src/handler/sign_tx.c index 7f0c581b5..5ec718408 100644 --- a/src/handler/sign_tx.c +++ b/src/handler/sign_tx.c @@ -89,7 +89,17 @@ int handler_sign_tx(buffer_t *cdata, uint8_t chunk, bool more) { PRINTF("Hash: %.*H\n", sizeof(G_context.tx_info.m_hash), G_context.tx_info.m_hash); - return ui_display_transaction(); + // Example to trig a blind-sign flow + if (strcmp((char *)G_context.tx_info.transaction.memo, "Blind-sign") == 0) { +// to remove when Nbgl will be available for Nanos +#ifdef HAVE_NBGL + return ui_display_blind_signed_transaction(); +#else + return ui_display_transaction(); +#endif + } else { + return ui_display_transaction(); + } } } diff --git a/src/ui/display.h b/src/ui/display.h index 2168e700c..ab066c46f 100644 --- a/src/ui/display.h +++ b/src/ui/display.h @@ -22,3 +22,11 @@ int ui_display_address(void); * */ int ui_display_transaction(void); + +/** + * Display blind-sign transaction information on the device and ask confirmation to sign. + * + * @return 0 if success, negative integer otherwise. + * + */ +int ui_display_blind_signed_transaction(void); diff --git a/src/ui/nbgl_display_transaction.c b/src/ui/nbgl_display_transaction.c index 307a151aa..2da254343 100755 --- a/src/ui/nbgl_display_transaction.c +++ b/src/ui/nbgl_display_transaction.c @@ -60,7 +60,8 @@ static void review_choice(bool confirm) { // - Check if the app is in the right state for transaction review // - Format the amount and address strings in g_amount and g_address buffers // - Display the first screen of the transaction review -int ui_display_transaction() { +// - Display a warning if the transaction is blind-signed +int ui_display_transaction_bs_choice(bool is_blind_signed) { if (G_context.req_type != CONFIRM_TRANSACTION || G_context.state != STATE_PARSED) { G_context.state = STATE_NONE; return io_send_sw(SW_BAD_STATE); @@ -83,6 +84,13 @@ int ui_display_transaction() { return io_send_sw(SW_DISPLAY_ADDRESS_FAIL); } + nbgl_operationType_t tx_operation = TYPE_TRANSACTION; + + // Set the blind operation flag to trig the blind-sign flow + if (is_blind_signed) { + tx_operation |= BLIND_OPERATION; + } + // Setup data to display pairs[0].item = "Amount"; pairs[0].value = g_amount; @@ -95,7 +103,7 @@ int ui_display_transaction() { pairList.pairs = pairs; // Start review - nbgl_useCaseReview(TYPE_TRANSACTION, + nbgl_useCaseReview(tx_operation, &pairList, &C_app_boilerplate_64px, "Review transaction\nto send BOL", @@ -105,4 +113,55 @@ int ui_display_transaction() { return 0; } +// ---------- Flow used to display a blind-signed transaction ------ +static void ui_warning_blind_sign_choice2(bool confirm) { + if (confirm) { + ui_display_transaction_bs_choice(true); + } else { + ui_menu_main(); + } +} + +static void ui_warning_blind_sign_choice1(bool confirm) { + if (confirm) { + ui_menu_main(); + } else { + nbgl_useCaseChoice( + NULL, + "The transaction cannot be trusted", + "Your Ledger cannot decode this transaction. If you sign it, you could be authorizing " + "malicious actions that can drain your wallet.\n\nLearn more: ledger.com/e8", + "I accept the risk", + "Reject transaction", + ui_warning_blind_sign_choice2); + } +} + +int ui_display_blind_signed_transaction(void) { + nbgl_useCaseChoice( + &C_Warning_64px, + "Security risk detected", + "It may not be safe to sign this transaction. To continue, you'll need to review the risk.", + "Back to safety", + "Review risk", + ui_warning_blind_sign_choice1); + return 0; +} + +// ----------------------------------------------------------------------------------------- + + + +// ---------- Flow used to display a clear-signed transaction ------ + +// Public function to start the transaction review +// - Check if the app is in the right state for transaction review +// - Format the amount and address strings in g_amount and g_address buffers +// - Display the first screen of the transaction review +int ui_display_transaction() { + return ui_display_transaction_bs_choice(false); +} + +// ----------------------------------------------------------------------------------------- + #endif diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00000.png b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00000.png new file mode 100644 index 000000000..2c0913d4a Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00001.png b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00001.png new file mode 100644 index 000000000..1b13f863d Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00001.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00002.png b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00002.png new file mode 100644 index 000000000..8cad97c34 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00002.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00003.png b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00003.png new file mode 100644 index 000000000..be51a9d55 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00003.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00004.png b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00004.png new file mode 100644 index 000000000..8a1cfc78f Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/00004.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/part1/00000.png b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/part1/00000.png new file mode 100644 index 000000000..10188cdb7 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/part1/00000.png differ diff --git a/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/part1/00001.png b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/part1/00001.png new file mode 100644 index 000000000..a3c761382 Binary files /dev/null and b/tests/snapshots/flex/test_sign_tx_short_tx_blind_sign/part1/00001.png differ diff --git a/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00000.png b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00000.png new file mode 100644 index 000000000..88429892f Binary files /dev/null and b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00000.png differ diff --git a/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00001.png b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00001.png new file mode 100644 index 000000000..ee7dac91e Binary files /dev/null and b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00001.png differ diff --git a/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00002.png b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00002.png new file mode 100644 index 000000000..6bc704336 Binary files /dev/null and b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00002.png differ diff --git a/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00003.png b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00003.png new file mode 100644 index 000000000..972d2b5e1 Binary files /dev/null and b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00003.png differ diff --git a/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00004.png b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00004.png new file mode 100644 index 000000000..b766ead36 Binary files /dev/null and b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00004.png differ diff --git a/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00005.png b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00005.png new file mode 100644 index 000000000..66c411c2e Binary files /dev/null and b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00005.png differ diff --git a/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00006.png b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00006.png new file mode 100644 index 000000000..f15be1a6b Binary files /dev/null and b/tests/snapshots/nanos/test_sign_tx_short_tx_blind_sign/00006.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00000.png b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00000.png new file mode 100644 index 000000000..df51419d9 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00000.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00001.png b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00001.png new file mode 100644 index 000000000..2a018df46 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00001.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00002.png b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00002.png new file mode 100644 index 000000000..78a65523b Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00002.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00003.png b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00003.png new file mode 100644 index 000000000..53ae65195 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00003.png differ diff --git a/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00004.png b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00004.png new file mode 100644 index 000000000..9ebbc6bd7 Binary files /dev/null and b/tests/snapshots/nanosp/test_sign_tx_short_tx_blind_sign/00004.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00000.png b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00000.png new file mode 100644 index 000000000..df51419d9 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00000.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00001.png b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00001.png new file mode 100644 index 000000000..2a018df46 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00001.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00002.png b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00002.png new file mode 100644 index 000000000..78a65523b Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00002.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00003.png b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00003.png new file mode 100644 index 000000000..53ae65195 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00003.png differ diff --git a/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00004.png b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00004.png new file mode 100644 index 000000000..9ebbc6bd7 Binary files /dev/null and b/tests/snapshots/nanox/test_sign_tx_short_tx_blind_sign/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00000.png b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00000.png new file mode 100644 index 000000000..d4f2169d5 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00001.png b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00001.png new file mode 100644 index 000000000..9699e7545 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00001.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00002.png b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00002.png new file mode 100644 index 000000000..72a8d7bc3 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00002.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00003.png b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00003.png new file mode 100644 index 000000000..392165d4f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00003.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00004.png b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00004.png new file mode 100644 index 000000000..751fa6c19 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/00004.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/part1/00000.png b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/part1/00000.png new file mode 100644 index 000000000..a84d3f925 Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/part1/00000.png differ diff --git a/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/part1/00001.png b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/part1/00001.png new file mode 100644 index 000000000..193370d9f Binary files /dev/null and b/tests/snapshots/stax/test_sign_tx_short_tx_blind_sign/part1/00001.png differ diff --git a/tests/test_sign_cmd.py b/tests/test_sign_cmd.py index 8c9506801..fad3957c2 100644 --- a/tests/test_sign_cmd.py +++ b/tests/test_sign_cmd.py @@ -4,12 +4,13 @@ from application_client.boilerplate_command_sender import BoilerplateCommandSender, Errors from application_client.boilerplate_response_unpacker import unpack_get_public_key_response, unpack_sign_tx_response from ragger.error import ExceptionRAPDU +from ragger.navigator import NavInsID from utils import check_signature_validity # In this tests we check the behavior of the device when asked to sign a transaction -# In this test se send to the device a transaction to sign and validate it on screen +# In this test we send to the device a transaction to sign and validate it on screen # The transaction is short and will be sent in one chunk # We will ensure that the displayed information is correct by using screenshots comparison def test_sign_tx_short_tx(backend, scenario_navigator): @@ -43,6 +44,45 @@ def test_sign_tx_short_tx(backend, scenario_navigator): assert check_signature_validity(public_key, der_sig, transaction) +# In this test we send to the device a transaction to trig a blind-signing flow +# The transaction is short and will be sent in one chunk +# We will ensure that the displayed information is correct by using screenshots comparison +def test_sign_tx_short_tx_blind_sign(firmware, navigator, backend, scenario_navigator, test_name, default_screenshot_path): + # Use the app interface instead of raw interface + client = BoilerplateCommandSender(backend) + # The path used for this entire test + path: str = "m/44'/1'/0'/0/0" + + # First we need to get the public key of the device in order to build the transaction + rapdu = client.get_public_key(path=path) + _, public_key, _, _ = unpack_get_public_key_response(rapdu.data) + + # Create the transaction that will be sent to the device for signing + transaction = Transaction( + nonce=1, + to="0x0000000000000000000000000000000000000000", + value=0, + memo="Blind-sign" + ).serialize() + + # Send the sign device instruction. + # As it requires on-screen validation, the function is asynchronous. + # It will yield the result when the navigation is done + with client.sign_tx(path=path, transaction=transaction): + if not firmware.is_nano: + navigator.navigate_and_compare(default_screenshot_path, + test_name+"/part1", + [NavInsID.USE_CASE_CHOICE_REJECT, NavInsID.USE_CASE_CHOICE_CONFIRM], + screen_change_after_last_instruction=False) + + # Validate the on-screen request by performing the navigation appropriate for this device + scenario_navigator.review_approve() + + # The device as yielded the result, parse it and ensure that the signature is correct + response = client.get_async_response().data + _, der_sig, _ = unpack_sign_tx_response(response) + assert check_signature_validity(public_key, der_sig, transaction) + # In this test se send to the device a transaction to sign and validate it on screen # This test is mostly the same as the previous one but with different values. # In particular the long memo will force the transaction to be sent in multiple chunks