From 5cc906ee48cf8fdf25a39436eaf4c0e28759d4f3 Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 8 Oct 2024 21:09:15 +0300 Subject: [PATCH 01/56] Remove nanos --- .github/workflows/ci-workflow.yml | 10 +++------- .vscode/c_cpp_properties.json | 6 +++--- Makefile | 1 - README.md | 6 +++--- ledger_app.toml | 2 +- tests/README.md | 4 ++-- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 0a3c970..8d8ba80 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -4,13 +4,11 @@ on: [push, pull_request] jobs: job_build_nano_debug: - name: Build application for NanoS, X and S+ + name: Build application for NanoS+, X runs-on: ubuntu-latest strategy: matrix: include: - - SDK: "$NANOS_SDK" - artifact: ergo-app-debug-nanos - SDK: "$NANOX_SDK" artifact: ergo-app-debug-nanox - SDK: "$NANOSP_SDK" @@ -128,12 +126,10 @@ jobs: strategy: matrix: include: - - model: nanos - SDK: "2.1" # - model: nanox # SDK: "2.0.2" - # - model: nanosp - # SDK: "1.0.4" + - model: nanosp + SDK: "1.0.4" needs: job_build_nano_debug runs-on: ubuntu-latest diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 5e967a3..d8dc198 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,11 +1,11 @@ { "env": { - "BOLOS_SDK": "~/.ledger/nanos-sdk", + "BOLOS_SDK": "~/.ledger/nanosplus-sdk", "ARM_GCC": "~/.ledger/gcc-arm-none-eabi-13.2-2023.10" }, "configurations": [ { - "name": "Nano S", + "name": "Nano S+", "includePath": [ "${workspaceFolder}/src", "${workspaceFolder}/build/nanos/gen_src", @@ -17,7 +17,7 @@ "${env:BOLOS_SDK}/lib_standard_app/*" ], "defines": [ - "TARGET_NANOS", + "TARGET_NANOS2", "OS_IO_SEPROXYHAL", "HAVE_BAGL", "HAVE_ECC", diff --git a/Makefile b/Makefile index 6b78022..5011b91 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,6 @@ APP_SOURCE_PATH += src # Application icons following guidelines: # https://developers.ledger.com/docs/embedded-app/design-requirements/#device-icon -ICON_NANOS = icons/app_16px.gif ICON_NANOX = icons/app_14px.gif ICON_NANOSP = icons/app_14px.gif #ICON_STAX = icons/app_32px.gif diff --git a/README.md b/README.md index 50c0c65..f9f801a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Ledger Ergo Application -This is a Ergo application for the Ledger Nano S/X. +This is a Ergo application for the Ledger Nano S+/X. ## Prerequisite @@ -15,7 +15,7 @@ BOLOS_ENV=/opt/bolos-devenv and do the same with `BOLOS_SDK` environment variable ``` -BOLOS_SDK=/opt/bolos-sdk/nanos-secure-sdk +BOLOS_SDK=/opt/bolos-sdk/nanosplus-secure-sdk ``` ## Compilation @@ -42,7 +42,7 @@ the process outputs HTML and LaTeX documentations in `doc/html` and `doc/latex` The flow processed in [GitHub Actions](https://github.com/features/actions) is the following: - Code formatting with [clang-format](http://clang.llvm.org/docs/ClangFormat.html) -- Compilation of the application for Ledger Nano S in [ledger-app-builder](https://github.com/LedgerHQ/ledger-app-builder) +- Compilation of the application for Ledger Nano S+ in [ledger-app-builder](https://github.com/LedgerHQ/ledger-app-builder) - Unit tests of C functions with [cmocka](https://cmocka.org/) (see [unit-tests/](unit-tests/)) - End-to-end tests with [Speculos](https://github.com/LedgerHQ/speculos) emulator (see [tests/](tests/)) - Code coverage with [gcov](https://gcc.gnu.org/onlinedocs/gcc/Gcov.html)/[lcov](http://ltp.sourceforge.net/coverage/lcov.php) and upload to [codecov.io](https://about.codecov.io) diff --git a/ledger_app.toml b/ledger_app.toml index 7d77593..f3759d8 100644 --- a/ledger_app.toml +++ b/ledger_app.toml @@ -1,7 +1,7 @@ [app] build_directory = "./" sdk = "C" -devices = ["nanos", "nanox", "nanos+"] +devices = ["nanox", "nanos+"] [tests] unit_directory = "./unit-tests/" diff --git a/tests/README.md b/tests/README.md index 85d4a90..77eb807 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,6 +1,6 @@ # End-to-end tests -These tests are implemented in NodeJS and can be executed either using the [Speculos](https://github.com/LedgerHQ/speculos) emulator or a Ledger Nano S/X. +These tests are implemented in NodeJS and can be executed either using the [Speculos](https://github.com/LedgerHQ/speculos) emulator or a Ledger Nano S+/X. NodeJS dependencies are listed in [package.json](package.json), install them using `npm` or `yarn`. ``` @@ -21,7 +21,7 @@ then run npm run test ``` -### Launch with your Nano S/X +### Launch with your Nano S+/X Be sure to have you device connected through USB (without any other software interacting with it) and run From 4faa896531ba176647d045004c4143f5e9598541 Mon Sep 17 00:00:00 2001 From: Ivan Date: Tue, 8 Oct 2024 23:46:10 +0300 Subject: [PATCH 02/56] NBGL --- .vscode/c_cpp_properties.json | 3 +- .vscode/settings.json | 5 ++ Makefile | 3 +- glyphs/{app_logo.gif => app_logo_16px.gif} | Bin glyphs/app_logo_64px.gif | Bin 0 -> 187 bytes icons/app_32px.gif | Bin 0 -> 97 bytes icons/app_40px.gif | Bin 0 -> 63 bytes ledger_app.toml | 2 +- .../{ainpt_ui.c => ainpt_ui_bagl.c} | 6 +- src/commands/attestinput/ainpt_ui_nbgl.c | 9 +++ .../deriveaddress/{da_ui.c => da_ui_bagl.c} | 4 ++ src/commands/deriveaddress/da_ui_nbgl.c | 15 +++++ .../extpubkey/{epk_ui.c => epk_ui_bagl.c} | 4 ++ src/commands/extpubkey/epk_ui_nbgl.c | 57 ++++++++++++++++++ src/commands/signtx/operations/stx_op_p2pk.c | 3 + .../signtx/{stx_ui.c => stx_ui_bagl.c} | 4 ++ src/commands/signtx/stx_ui_nbgl.c | 48 +++++++++++++++ src/ui/ui_application_id.h | 6 +- ...lication_id.c => ui_application_id_bagl.c} | 4 +- src/ui/ui_application_id_nbgl.c | 6 ++ src/ui/ui_approve_reject.h | 5 +- ...rove_reject.c => ui_approve_reject_bagl.c} | 4 +- src/ui/ui_approve_reject_nbgl.c | 6 ++ src/ui/ui_bip32_path.h | 6 +- .../{ui_bip32_path.c => ui_bip32_path_bagl.c} | 6 +- src/ui/ui_bip32_path_nbgl.c | 6 ++ src/ui/ui_dynamic_flow.h | 6 +- ..._dynamic_flow.c => ui_dynamic_flow_bagl.c} | 4 ++ src/ui/ui_dynamic_flow_nbgl.c | 16 +++++ src/ui/{ui_main.c => ui_main_bagl.c} | 0 src/ui/{ui_menu.c => ui_menu_bagl.c} | 6 +- src/ui/ui_menu_nbgl.c | 39 ++++++++++++ 32 files changed, 271 insertions(+), 12 deletions(-) rename glyphs/{app_logo.gif => app_logo_16px.gif} (100%) create mode 100644 glyphs/app_logo_64px.gif create mode 100644 icons/app_32px.gif create mode 100644 icons/app_40px.gif rename src/commands/attestinput/{ainpt_ui.c => ainpt_ui_bagl.c} (98%) create mode 100644 src/commands/attestinput/ainpt_ui_nbgl.c rename src/commands/deriveaddress/{da_ui.c => da_ui_bagl.c} (99%) create mode 100644 src/commands/deriveaddress/da_ui_nbgl.c rename src/commands/extpubkey/{epk_ui.c => epk_ui_bagl.c} (99%) create mode 100644 src/commands/extpubkey/epk_ui_nbgl.c rename src/commands/signtx/{stx_ui.c => stx_ui_bagl.c} (99%) create mode 100644 src/commands/signtx/stx_ui_nbgl.c rename src/ui/{ui_application_id.c => ui_application_id_bagl.c} (96%) create mode 100644 src/ui/ui_application_id_nbgl.c rename src/ui/{ui_approve_reject.c => ui_approve_reject_bagl.c} (97%) create mode 100644 src/ui/ui_approve_reject_nbgl.c rename src/ui/{ui_bip32_path.c => ui_bip32_path_bagl.c} (98%) create mode 100644 src/ui/ui_bip32_path_nbgl.c rename src/ui/{ui_dynamic_flow.c => ui_dynamic_flow_bagl.c} (99%) create mode 100644 src/ui/ui_dynamic_flow_nbgl.c rename src/ui/{ui_main.c => ui_main_bagl.c} (100%) rename src/ui/{ui_menu.c => ui_menu_bagl.c} (94%) create mode 100644 src/ui/ui_menu_nbgl.c diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index d8dc198..6b4242f 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -13,13 +13,14 @@ "${env:ARM_GCC}/lib/gcc/arm-none-eabi/13.2.1/include/*", "${env:BOLOS_SDK}/include/*", "${env:BOLOS_SDK}/lib_ux/include/*", + "${env:BOLOS_SDK}/lib_nbgl/include/*", "${env:BOLOS_SDK}/lib_cxng/include/*", "${env:BOLOS_SDK}/lib_standard_app/*" ], "defines": [ "TARGET_NANOS2", "OS_IO_SEPROXYHAL", - "HAVE_BAGL", + "HAVE_NBGL", "HAVE_ECC", "HAVE_ECC_WEIERSTRASS", "HAVE_SECP_CURVES", diff --git a/.vscode/settings.json b/.vscode/settings.json index 4be05ef..b15a812 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,4 +6,9 @@ "editor.formatOnSave": false, "python.terminal.activateEnvironment": false, "git.ignoreLimitWarning": true, + "ledgerDevTools.appSettings": { + "selectedUseCase": "release", + "selectedDevice": "Stax", + "selectedVariant": "ergo" + }, } \ No newline at end of file diff --git a/Makefile b/Makefile index 5011b91..1632b15 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,8 @@ APP_SOURCE_PATH += src # https://developers.ledger.com/docs/embedded-app/design-requirements/#device-icon ICON_NANOX = icons/app_14px.gif ICON_NANOSP = icons/app_14px.gif -#ICON_STAX = icons/app_32px.gif +ICON_STAX = icons/app_32px.gif +ICON_FLEX = icons/app_40px.gif # Application allowed derivation curves. # Possibles curves are: secp256k1, secp256r1, ed25519 and bls12381g1 diff --git a/glyphs/app_logo.gif b/glyphs/app_logo_16px.gif similarity index 100% rename from glyphs/app_logo.gif rename to glyphs/app_logo_16px.gif diff --git a/glyphs/app_logo_64px.gif b/glyphs/app_logo_64px.gif new file mode 100644 index 0000000000000000000000000000000000000000..d7305978f6f08a742dd59f0082e0a232feb6878e GIT binary patch literal 187 zcmV;s07U;sNk%w1VL$*t0Du7i00030|Nkri0000$06+i$0-B7EsmtvTqnxzbi?iOm z`wxcVNR}ahrs~SJ?&rqx?9KL#*7*K*{J(+$f1;i#!#Zw~N=>l2%t51osZ(XeJhPS* zS1bKew&Do64Dq5T>UA3Hb}-|MIXz*&AM*OZx$hSSxFyyNcRZY=s0;7 p>BgrB$C$Y`M5Ob{6Do>BT55BODkHSYItUvpJ4;(@dn;Q206UiSSuFqn literal 0 HcmV?d00001 diff --git a/icons/app_32px.gif b/icons/app_32px.gif new file mode 100644 index 0000000000000000000000000000000000000000..44dc4994c6fbe9243994a4f06415968319006c41 GIT binary patch literal 97 zcmZ?wbhEHbRA5kGXkcUjg8%>j>wsvG2m_NtPyfo(Z}}I`+2Yl(`QFb@>nj%??MdmJ y>$iN7!|Oxb+R7!lOMWbTzx_`$YqWFd#}bv94bn0%es(!H?q2n^D_4|(!5RScfGGO_ literal 0 HcmV?d00001 diff --git a/icons/app_40px.gif b/icons/app_40px.gif new file mode 100644 index 0000000000000000000000000000000000000000..5d8d53b583d42d040b0731655213348fa5817884 GIT binary patch literal 63 zcmZ?wbh9u|6krfwXkcUjg8%>j>wsvG2m_N`Pyfo@5BNprEC^N8cgtJ;PI7^Ho@$v< N$d|R59LlT=)&LCC5?25K literal 0 HcmV?d00001 diff --git a/ledger_app.toml b/ledger_app.toml index f3759d8..a368963 100644 --- a/ledger_app.toml +++ b/ledger_app.toml @@ -1,7 +1,7 @@ [app] build_directory = "./" sdk = "C" -devices = ["nanox", "nanos+"] +devices = ["nanox", "nanos+", "stax", "flex"] [tests] unit_directory = "./unit-tests/" diff --git a/src/commands/attestinput/ainpt_ui.c b/src/commands/attestinput/ainpt_ui_bagl.c similarity index 98% rename from src/commands/attestinput/ainpt_ui.c rename to src/commands/attestinput/ainpt_ui_bagl.c index 7f99f07..8646788 100644 --- a/src/commands/attestinput/ainpt_ui.c +++ b/src/commands/attestinput/ainpt_ui_bagl.c @@ -1,3 +1,5 @@ +#ifdef HAVE_BAGL + #include #include #include @@ -48,4 +50,6 @@ int ui_display_access_token(uint32_t app_access_token, attest_input_ctx_t* conte ui_display_screens(&screen); return 0; -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/commands/attestinput/ainpt_ui_nbgl.c b/src/commands/attestinput/ainpt_ui_nbgl.c new file mode 100644 index 0000000..3632247 --- /dev/null +++ b/src/commands/attestinput/ainpt_ui_nbgl.c @@ -0,0 +1,9 @@ +#ifdef HAVE_NBGL + +#include "ainpt_ui.h" + +int ui_display_access_token(uint32_t app_access_token, attest_input_ctx_t* context) { + return 0; +} + +#endif \ No newline at end of file diff --git a/src/commands/deriveaddress/da_ui.c b/src/commands/deriveaddress/da_ui_bagl.c similarity index 99% rename from src/commands/deriveaddress/da_ui.c rename to src/commands/deriveaddress/da_ui_bagl.c index 8218d36..5e67143 100644 --- a/src/commands/deriveaddress/da_ui.c +++ b/src/commands/deriveaddress/da_ui_bagl.c @@ -1,3 +1,5 @@ +#ifdef HAVE_BAGL + #include #include #include @@ -117,3 +119,5 @@ int ui_display_address(derive_address_ctx_t* ctx, return 0; } + +#endif \ No newline at end of file diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c new file mode 100644 index 0000000..74ebf1f --- /dev/null +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -0,0 +1,15 @@ +#ifdef HAVE_NBGL + +#include "da_ui.h" + +int ui_display_address(derive_address_ctx_t* ctx, + bool send, + uint32_t app_access_token, + uint32_t* bip32_path, + uint8_t bip32_path_len, + uint8_t raw_address[static P2PK_ADDRESS_LEN]) +{ + return 0; +} + +#endif \ No newline at end of file diff --git a/src/commands/extpubkey/epk_ui.c b/src/commands/extpubkey/epk_ui_bagl.c similarity index 99% rename from src/commands/extpubkey/epk_ui.c rename to src/commands/extpubkey/epk_ui_bagl.c index c1e12f3..5f5ff48 100644 --- a/src/commands/extpubkey/epk_ui.c +++ b/src/commands/extpubkey/epk_ui_bagl.c @@ -1,3 +1,5 @@ +#ifdef HAVE_BAGL + #include #include #include @@ -85,3 +87,5 @@ int ui_display_account(extended_public_key_ctx_t* ctx, return 0; } + +#endif \ No newline at end of file diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c new file mode 100644 index 0000000..2361e07 --- /dev/null +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -0,0 +1,57 @@ +#ifdef HAVE_NBGL + +#include "epk_ui.h" +#include "../../helpers/response.h" +#include "../../sw.h" + +int ui_display_account(extended_public_key_ctx_t* ctx, + uint32_t app_access_token, + uint32_t* bip32_path, + uint8_t bip32_path_len, + uint8_t raw_pub_key[static PUBLIC_KEY_LEN], + uint8_t chain_code[static CHAIN_CODE_LEN]) { + if (!bip32_path_validate(bip32_path, + bip32_path_len, + BIP32_HARDENED(44), + BIP32_HARDENED(BIP32_ERGO_COIN), + BIP32_PATH_VALIDATE_ACCOUNT_GE3)) { + return res_error(SW_BIP32_BAD_PATH); + } + + uint8_t screen = 0; + UX_STEP_NOCB(ux_epk_display_confirm_ext_pubkey_step, pn, {&C_icon_warning, "Ext PubKey Export"}); + ui_add_screen(&ux_epk_display_confirm_ext_pubkey_step, &screen); + + const ux_flow_step_t* b32_step = + ui_bip32_path_screen(bip32_path, + bip32_path_len, + "Path", + ctx->bip32_path, + MEMBER_SIZE(extended_public_key_ctx_t, bip32_path), + NULL, + NULL); + if (b32_step == NULL) { + app_set_current_command(CMD_NONE); + return res_error(SW_BIP32_FORMATTING_FAILED); + } + ui_add_screen(b32_step, &screen); + + if (app_access_token != 0) { + ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_token), &screen); + } + + ui_approve_reject_screens(ui_action_get_extended_pubkey, + ctx, + ui_next_sreen_ptr(&screen), + ui_next_sreen_ptr(&screen)); + + ctx->app_token_value = app_access_token; + memmove(ctx->raw_public_key, raw_pub_key, PUBLIC_KEY_LEN); + memmove(ctx->chain_code, chain_code, CHAIN_CODE_LEN); + + ui_display_screens(&screen); + + return 0; +} + +#endif \ No newline at end of file diff --git a/src/commands/signtx/operations/stx_op_p2pk.c b/src/commands/signtx/operations/stx_op_p2pk.c index bc85891..5d2c4a0 100644 --- a/src/commands/signtx/operations/stx_op_p2pk.c +++ b/src/commands/signtx/operations/stx_op_p2pk.c @@ -331,8 +331,10 @@ static NOINLINE void ui_stx_operation_p2pk_approve_action(void *context) { uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2pk_ctx_t *ctx, uint32_t app_access_token, bool is_known_application, + void *sign_tx_ctx) { uint8_t screen = 0; + #ifdef HAVE_BAGL const ux_flow_step_t *b32_step = ui_bip32_path_screen( ctx->bip32.path, ctx->bip32.len, @@ -345,6 +347,7 @@ uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2 return SW_BIP32_FORMATTING_FAILED; } ui_add_screen(b32_step, &screen); + #endif if (!ui_stx_add_operation_approve_screens(&ctx->ui_approve.ui_approve, &screen, diff --git a/src/commands/signtx/stx_ui.c b/src/commands/signtx/stx_ui_bagl.c similarity index 99% rename from src/commands/signtx/stx_ui.c rename to src/commands/signtx/stx_ui_bagl.c index a8e26de..a3f0905 100644 --- a/src/commands/signtx/stx_ui.c +++ b/src/commands/signtx/stx_ui_bagl.c @@ -1,3 +1,5 @@ +#ifdef HAVE_BAGL + #include #include #include @@ -403,3 +405,5 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, bool ui_stx_display_screens(uint8_t screen_count) { return ui_display_screens(&screen_count); } + +#endif \ No newline at end of file diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c new file mode 100644 index 0000000..ef8b11c --- /dev/null +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -0,0 +1,48 @@ +#ifdef HAVE_NBGL + +#include "stx_ui.h" +/** + * Add application access_token and accept/reject screens to the UI. + * + * @return true if success, false if screens flow is full. + * + */ +bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, + uint8_t* screen, + uint32_t app_access_token, + bool is_known_application, + sign_transaction_ctx_t* sign_tx) { + return true; +} + + +bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, + uint8_t* screen, + const sign_transaction_output_info_ctx_t* output, + sign_transaction_bip32_path_t* last_approved_change, + uint8_t network_id) { + return true; +} + + +bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, + uint8_t* screen, + const sign_transaction_amounts_ctx_t* amounts, + uint8_t op_screen_count, + ui_sign_transaction_operation_show_screen_cb screen_cb, + ui_sign_transaction_operation_send_response_cb response_cb, + void* cb_context) { + return true; +} + + +bool ui_stx_display_screens(uint8_t screen_count) { + return true; +} + + +void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_ctx_t* ctx) { + +} + +#endif \ No newline at end of file diff --git a/src/ui/ui_application_id.h b/src/ui/ui_application_id.h index 83ac685..c966c86 100644 --- a/src/ui/ui_application_id.h +++ b/src/ui/ui_application_id.h @@ -5,5 +5,9 @@ #define APPLICATION_ID_STR_LEN 11 +#ifdef HAVE_BAGL + const ux_flow_step_t* ui_application_id_screen(uint32_t app_id, - char buffer[static APPLICATION_ID_STR_LEN]); \ No newline at end of file + char buffer[static APPLICATION_ID_STR_LEN]); + +#endif \ No newline at end of file diff --git a/src/ui/ui_application_id.c b/src/ui/ui_application_id_bagl.c similarity index 96% rename from src/ui/ui_application_id.c rename to src/ui/ui_application_id_bagl.c index 4d80866..c2921f2 100644 --- a/src/ui/ui_application_id.c +++ b/src/ui/ui_application_id_bagl.c @@ -1,3 +1,4 @@ +#ifdef HAVE_BAGL #include "ui_application_id.h" #include #include @@ -19,4 +20,5 @@ const ux_flow_step_t* ui_application_id_screen(uint32_t app_id, memset(buffer, 0, APPLICATION_ID_STR_LEN); snprintf(buffer, APPLICATION_ID_STR_LEN, "0x%08x", app_id); return &ux_app_token_step; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/ui/ui_application_id_nbgl.c b/src/ui/ui_application_id_nbgl.c new file mode 100644 index 0000000..691e442 --- /dev/null +++ b/src/ui/ui_application_id_nbgl.c @@ -0,0 +1,6 @@ +#ifdef HAVE_NBGL + +#include "ui_application_id.h" + + +#endif \ No newline at end of file diff --git a/src/ui/ui_approve_reject.h b/src/ui/ui_approve_reject.h index 9faed38..e30c881 100644 --- a/src/ui/ui_approve_reject.h +++ b/src/ui/ui_approve_reject.h @@ -3,9 +3,12 @@ #include #include +#ifdef HAVE_BAGL typedef void (*ui_approve_reject_callback)(bool, void*); void ui_approve_reject_screens(ui_approve_reject_callback cb, void* context, const ux_flow_step_t** approve, - const ux_flow_step_t** reject); \ No newline at end of file + const ux_flow_step_t** reject); + +#endif \ No newline at end of file diff --git a/src/ui/ui_approve_reject.c b/src/ui/ui_approve_reject_bagl.c similarity index 97% rename from src/ui/ui_approve_reject.c rename to src/ui/ui_approve_reject_bagl.c index 80bc1d4..283daed 100644 --- a/src/ui/ui_approve_reject.c +++ b/src/ui/ui_approve_reject_bagl.c @@ -1,3 +1,4 @@ +#ifdef HAVE_BAGL #include #include "ui_approve_reject.h" @@ -29,4 +30,5 @@ void ui_approve_reject_screens(ui_approve_reject_callback cb, G_ui_approve_reject_callback_context = context; *approve = &ux_approve_step; *reject = &ux_reject_step; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/ui/ui_approve_reject_nbgl.c b/src/ui/ui_approve_reject_nbgl.c new file mode 100644 index 0000000..ccdff5a --- /dev/null +++ b/src/ui/ui_approve_reject_nbgl.c @@ -0,0 +1,6 @@ +#ifdef HAVE_NBGL + +#include "ui_approve_reject.h" + + +#endif \ No newline at end of file diff --git a/src/ui/ui_bip32_path.h b/src/ui/ui_bip32_path.h index 88a61ed..2ad0ebc 100644 --- a/src/ui/ui_bip32_path.h +++ b/src/ui/ui_bip32_path.h @@ -3,6 +3,8 @@ #include #include +#ifdef HAVE_BAGL + typedef void (*ui_bip32_approve_callback)(void*); const ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, @@ -11,4 +13,6 @@ const ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, char* buffer, uint8_t buffer_len, ui_bip32_approve_callback cb, - void* cb_context); \ No newline at end of file + void* cb_context); + +#endif \ No newline at end of file diff --git a/src/ui/ui_bip32_path.c b/src/ui/ui_bip32_path_bagl.c similarity index 98% rename from src/ui/ui_bip32_path.c rename to src/ui/ui_bip32_path_bagl.c index f00a50d..58e1890 100644 --- a/src/ui/ui_bip32_path.c +++ b/src/ui/ui_bip32_path_bagl.c @@ -1,3 +1,5 @@ +#ifdef HAVE_BAGL + #include "ui_bip32_path.h" #include "../common/bip32_ext.h" @@ -42,4 +44,6 @@ const ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, G_ui_bip32_approve_callback = cb; G_ui_bip32_approve_callback_context = cb_context; return &ux_bip32_path_step; -} \ No newline at end of file +} + +#endif \ No newline at end of file diff --git a/src/ui/ui_bip32_path_nbgl.c b/src/ui/ui_bip32_path_nbgl.c new file mode 100644 index 0000000..0b025ab --- /dev/null +++ b/src/ui/ui_bip32_path_nbgl.c @@ -0,0 +1,6 @@ +#ifdef HAVE_NBGL + +#include "ui_bip32_path.h" + + +#endif \ No newline at end of file diff --git a/src/ui/ui_dynamic_flow.h b/src/ui/ui_dynamic_flow.h index 01e869c..cd005a0 100644 --- a/src/ui/ui_dynamic_flow.h +++ b/src/ui/ui_dynamic_flow.h @@ -4,7 +4,11 @@ #include #include + +#ifdef HAVE_BAGL + typedef uint16_t (*ui_dynamic_flow_show_screen_cb)(uint8_t, char *, char *, void *); +#endif // Global context pointer will be set to the dynamic flow context. Don't change it. bool ui_add_dynamic_flow_screens(uint8_t *screen, @@ -12,4 +16,4 @@ bool ui_add_dynamic_flow_screens(uint8_t *screen, char *title_storage, char *text_storage, ui_dynamic_flow_show_screen_cb show_cb, - void *cb_ctx); \ No newline at end of file + void *cb_ctx); diff --git a/src/ui/ui_dynamic_flow.c b/src/ui/ui_dynamic_flow_bagl.c similarity index 99% rename from src/ui/ui_dynamic_flow.c rename to src/ui/ui_dynamic_flow_bagl.c index 25b7b9e..d1088cd 100644 --- a/src/ui/ui_dynamic_flow.c +++ b/src/ui/ui_dynamic_flow_bagl.c @@ -1,3 +1,5 @@ +#ifdef HAVE_BAGL + #include "ui_dynamic_flow.h" #include "../constants.h" @@ -107,3 +109,5 @@ bool ui_add_dynamic_flow_screens(uint8_t *screen, return true; } + +#endif \ No newline at end of file diff --git a/src/ui/ui_dynamic_flow_nbgl.c b/src/ui/ui_dynamic_flow_nbgl.c new file mode 100644 index 0000000..bee4b82 --- /dev/null +++ b/src/ui/ui_dynamic_flow_nbgl.c @@ -0,0 +1,16 @@ +#ifdef HAVE_NBGL + +#include "ui_menu.h" +#include +#include + +bool ui_add_dynamic_flow_screens(uint8_t *screen, + uint8_t dynamic_screen_count, + char *title_storage, + char *text_storage, + ui_dynamic_flow_show_screen_cb show_cb, + void *cb_ctx) { + return true; +} + +#endif \ No newline at end of file diff --git a/src/ui/ui_main.c b/src/ui/ui_main_bagl.c similarity index 100% rename from src/ui/ui_main.c rename to src/ui/ui_main_bagl.c diff --git a/src/ui/ui_menu.c b/src/ui/ui_menu_bagl.c similarity index 94% rename from src/ui/ui_menu.c rename to src/ui/ui_menu_bagl.c index c11aaa5..e4439f9 100644 --- a/src/ui/ui_menu.c +++ b/src/ui/ui_menu_bagl.c @@ -15,6 +15,8 @@ * limitations under the License. *****************************************************************************/ +#ifdef HAVE_BAGL + #include #include #include @@ -22,7 +24,7 @@ #include "ui_menu.h" #include "ui_main.h" -UX_STEP_NOCB(ux_menu_ready_step, pnn, {&C_app_logo, APPNAME, "is ready"}); +UX_STEP_NOCB(ux_menu_ready_step, pnn, {&C_app_logo_16px, APPNAME, "is ready"}); UX_STEP_CB(ux_menu_about_step, pb, ui_menu_about(), {&C_icon_certificate, "About"}); UX_STEP_CB(ux_menu_exit_step, pb, os_sched_exit(-1), {&C_icon_dashboard_x, "Quit"}); @@ -53,3 +55,5 @@ void ui_menu_about() { app_set_ui_busy(false); } + +#endif \ No newline at end of file diff --git a/src/ui/ui_menu_nbgl.c b/src/ui/ui_menu_nbgl.c new file mode 100644 index 0000000..f9e7082 --- /dev/null +++ b/src/ui/ui_menu_nbgl.c @@ -0,0 +1,39 @@ +#ifdef HAVE_NBGL + +#include "ui_menu.h" +#include +#include + +#define APPTAGLINE "Ergo app for ledger" +#define APPCOPYRIGHT "Ergo App (c) 2024" + +#define SETTING_INFO_NB 2 +static const char* const INFO_TYPES[SETTING_INFO_NB] = {"Version", "Copyright"}; +static const char* const INFO_CONTENTS[SETTING_INFO_NB] = {APPVERSION, APPCOPYRIGHT}; +static const nbgl_contentInfoList_t infoList = { + .nbInfos = SETTING_INFO_NB, + .infoTypes = INFO_TYPES, + .infoContents = INFO_CONTENTS, +}; + +void app_quit(void) { + // exit app here + os_sched_exit(-1); +} + +void ui_menu_main() { + nbgl_useCaseHomeAndSettings(APPNAME, + &C_app_logo_64px, + APPTAGLINE, + INIT_HOME_PAGE, + NULL, + &infoList, + NULL, + app_quit); +} + +void ui_menu_about() { + +} + +#endif \ No newline at end of file From df024213fcb97d3d76ca59b1aff1f8e07dafc664 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 9 Oct 2024 05:18:57 +0300 Subject: [PATCH 03/56] More UI --- .vscode/c_cpp_properties.json | 1 + .vscode/settings.json | 2 +- src/commands/deriveaddress/da_ui.h | 10 ++- src/commands/deriveaddress/da_ui_bagl.c | 4 -- src/commands/deriveaddress/da_ui_nbgl.c | 82 +++++++++++++++++++++++++ src/commands/extpubkey/epk_ui_nbgl.c | 65 +++++++++++++------- src/ui/display.h | 31 ++++++++++ src/ui/ui_approve_reject_nbgl.c | 6 -- src/ui/ui_dynamic_flow.h | 4 +- src/ui/ui_dynamic_flow_nbgl.c | 4 +- 10 files changed, 171 insertions(+), 38 deletions(-) create mode 100644 src/ui/display.h delete mode 100644 src/ui/ui_approve_reject_nbgl.c diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 6b4242f..847fd47 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -21,6 +21,7 @@ "TARGET_NANOS2", "OS_IO_SEPROXYHAL", "HAVE_NBGL", + "HAVE_SE_TOUCH", "HAVE_ECC", "HAVE_ECC_WEIERSTRASS", "HAVE_SECP_CURVES", diff --git a/.vscode/settings.json b/.vscode/settings.json index b15a812..322a8d3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,7 +7,7 @@ "python.terminal.activateEnvironment": false, "git.ignoreLimitWarning": true, "ledgerDevTools.appSettings": { - "selectedUseCase": "release", + "selectedUseCase": "debug", "selectedDevice": "Stax", "selectedVariant": "ergo" }, diff --git a/src/commands/deriveaddress/da_ui.h b/src/commands/deriveaddress/da_ui.h index 4c03963..c45a973 100644 --- a/src/commands/deriveaddress/da_ui.h +++ b/src/commands/deriveaddress/da_ui.h @@ -4,6 +4,8 @@ #include // bool #include "da_context.h" #include "../../constants.h" +#include "../../context.h" +#include "../../helpers/response.h" /** * Display account on the device and ask confirmation to export. @@ -16,4 +18,10 @@ int ui_display_address(derive_address_ctx_t* ctx, uint32_t app_access_token, uint32_t* bip32_path, uint8_t bip32_path_len, - uint8_t raw_address[static P2PK_ADDRESS_LEN]); \ No newline at end of file + uint8_t raw_address[static P2PK_ADDRESS_LEN]); + + +static inline int send_error(uint16_t err) { + app_set_current_command(CMD_NONE); + return res_error(err); +} \ No newline at end of file diff --git a/src/commands/deriveaddress/da_ui_bagl.c b/src/commands/deriveaddress/da_ui_bagl.c index 5e67143..3849afc 100644 --- a/src/commands/deriveaddress/da_ui_bagl.c +++ b/src/commands/deriveaddress/da_ui_bagl.c @@ -51,10 +51,6 @@ static NOINLINE void ui_action_derive_address(bool approved, void* context) { ui_menu_main(); } -static inline int send_error(uint16_t err) { - app_set_current_command(CMD_NONE); - return res_error(err); -} // Display int ui_display_address(derive_address_ctx_t* ctx, diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index 74ebf1f..119f820 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -1,6 +1,30 @@ #ifdef HAVE_NBGL #include "da_ui.h" +#include +#include +#include +#include +#include +#include +#include "da_ui.h" +#include "da_response.h" +#include "da_context.h" +#include "../../sw.h" +#include "../../context.h" +#include "../../common/macros_ext.h" +#include "../../ergo/address.h" +#include "../../helpers/response.h" +#include "../../ui/ui_bip32_path.h" +#include "../../ui/ui_application_id.h" +#include "../../ui/ui_approve_reject.h" +#include "../../ui/ui_menu.h" +#include "../../ui/ui_main.h" +#include "../../ui/display.h" + +void ui_display_address_confirm(bool approved) { + set_flow_reseponse(approved); +} int ui_display_address(derive_address_ctx_t* ctx, bool send, @@ -9,6 +33,64 @@ int ui_display_address(derive_address_ctx_t* ctx, uint8_t bip32_path_len, uint8_t raw_address[static P2PK_ADDRESS_LEN]) { + if (!bip32_path_validate(bip32_path, + bip32_path_len, + BIP32_HARDENED(44), + BIP32_HARDENED(BIP32_ERGO_COIN), + BIP32_PATH_VALIDATE_ADDRESS_GE5)) { + return send_error(SW_BIP32_BAD_PATH); + } + + ctx->app_token_value = app_access_token; + ctx->send = send; + + + memset(ctx->address, 0, MEMBER_SIZE(derive_address_ctx_t, address)); + if (!send) { + int result = base58_encode(raw_address, + P2PK_ADDRESS_LEN, + ctx->address, + MEMBER_SIZE(derive_address_ctx_t, address)); + + if (result == -1 || result >= P2PK_ADDRESS_STRING_MAX_LEN) { + return send_error(SW_ADDRESS_FORMATTING_FAILED); + } + + } + + if (app_access_token != 0) { + // TO-DO + //ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_id), &screen); + } + + if(send) { + // Confirm Send Address + nbgl_useCaseAddressReview(ctx->address, NULL, &WHEEL_ICON, "Confirm Send Address", "", ui_display_address_confirm); + } else { + // Confirm Address + nbgl_useCaseAddressReview(ctx->address, NULL, &INFO_I_ICON, "Confirm Address", "", ui_display_address_confirm); + } + + memmove(ctx->raw_address, raw_address, P2PK_ADDRESS_LEN); + + + bool approved = io_ui_process(); + + if (approved) { + app_set_connected_app_id(ctx->app_token_value); + if (ctx->send) { + send_response_address(ctx->raw_address); + } else { + app_set_current_command(CMD_NONE); + res_ok(); + } + } else { + app_set_current_command(CMD_NONE); + res_deny(); + } + + ui_menu_main(); + return 0; } diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c index 2361e07..ee4da05 100644 --- a/src/commands/extpubkey/epk_ui_nbgl.c +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -3,6 +3,26 @@ #include "epk_ui.h" #include "../../helpers/response.h" #include "../../sw.h" +#include +#include +#include +#include +#include +#include "epk_response.h" +#include "../../context.h" +#include "../../common/bip32_ext.h" +#include "../../common/macros_ext.h" +#include "../../ui/ui_bip32_path.h" +#include "../../ui/ui_application_id.h" +#include "../../ui/ui_approve_reject.h" +#include "../../ui/ui_menu.h" +#include "../../ui/ui_main.h" +#include "../../ui/display.h" +#include + +void ui_display_account_confirm(bool approved) { + set_flow_reseponse(approved); +} int ui_display_account(extended_public_key_ctx_t* ctx, uint32_t app_access_token, @@ -18,38 +38,37 @@ int ui_display_account(extended_public_key_ctx_t* ctx, return res_error(SW_BIP32_BAD_PATH); } - uint8_t screen = 0; - UX_STEP_NOCB(ux_epk_display_confirm_ext_pubkey_step, pn, {&C_icon_warning, "Ext PubKey Export"}); - ui_add_screen(&ux_epk_display_confirm_ext_pubkey_step, &screen); - - const ux_flow_step_t* b32_step = - ui_bip32_path_screen(bip32_path, - bip32_path_len, - "Path", - ctx->bip32_path, - MEMBER_SIZE(extended_public_key_ctx_t, bip32_path), - NULL, - NULL); - if (b32_step == NULL) { - app_set_current_command(CMD_NONE); - return res_error(SW_BIP32_FORMATTING_FAILED); + uint path_size = MEMBER_SIZE(extended_public_key_ctx_t, bip32_path); + memset(ctx->bip32_path, 0, path_size); + if (!bip32_path_format(bip32_path, bip32_path_len, ctx->bip32_path, path_size)) { + return NULL; } - ui_add_screen(b32_step, &screen); + if (app_access_token != 0) { - ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_token), &screen); + // TO-DO + //ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_token), &screen); } - ui_approve_reject_screens(ui_action_get_extended_pubkey, - ctx, - ui_next_sreen_ptr(&screen), - ui_next_sreen_ptr(&screen)); - ctx->app_token_value = app_access_token; memmove(ctx->raw_public_key, raw_pub_key, PUBLIC_KEY_LEN); memmove(ctx->chain_code, chain_code, CHAIN_CODE_LEN); - ui_display_screens(&screen); + nbgl_useCaseChoice(&WARNING_ICON,"Ext PubKey Export", ctx->bip32_path, "Confirm", "Cancel", ui_display_account_confirm); + bool approved = io_ui_process(); + + if (approved) { + app_set_connected_app_id(ctx->app_token_value); + send_response_extended_pubkey(ctx->raw_public_key, ctx->chain_code); + explicit_bzero(ctx, sizeof(extended_public_key_ctx_t)); + } else { + explicit_bzero(ctx, sizeof(extended_public_key_ctx_t)); + res_deny(); + } + + app_set_current_command(CMD_NONE); + + ui_menu_main(); return 0; } diff --git a/src/ui/display.h b/src/ui/display.h new file mode 100644 index 0000000..fbc1d23 --- /dev/null +++ b/src/ui/display.h @@ -0,0 +1,31 @@ + +#pragma once + +#include +#include "../context.h" + +static bool flow_response = false; + +static void set_flow_reseponse(bool response) { + flow_response = response; + app_set_ui_busy(false); +} + +static bool io_ui_process() { + // We are not waiting for the client's input, nor we are doing computations on the device + //io_clear_processing_timeout(); + + app_set_ui_busy(true); + + io_seproxyhal_general_status(); + do { + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + io_seproxyhal_handle_event(); + io_seproxyhal_general_status(); + } while (io_seproxyhal_spi_is_status_sent() && G_app_context.is_ui_busy); + + // We're back at work, we want to show the "Processing..." screen when appropriate + //io_start_processing_timeout(); + + return flow_response; +} \ No newline at end of file diff --git a/src/ui/ui_approve_reject_nbgl.c b/src/ui/ui_approve_reject_nbgl.c deleted file mode 100644 index ccdff5a..0000000 --- a/src/ui/ui_approve_reject_nbgl.c +++ /dev/null @@ -1,6 +0,0 @@ -#ifdef HAVE_NBGL - -#include "ui_approve_reject.h" - - -#endif \ No newline at end of file diff --git a/src/ui/ui_dynamic_flow.h b/src/ui/ui_dynamic_flow.h index cd005a0..0af0215 100644 --- a/src/ui/ui_dynamic_flow.h +++ b/src/ui/ui_dynamic_flow.h @@ -8,7 +8,7 @@ #ifdef HAVE_BAGL typedef uint16_t (*ui_dynamic_flow_show_screen_cb)(uint8_t, char *, char *, void *); -#endif + // Global context pointer will be set to the dynamic flow context. Don't change it. bool ui_add_dynamic_flow_screens(uint8_t *screen, @@ -17,3 +17,5 @@ bool ui_add_dynamic_flow_screens(uint8_t *screen, char *text_storage, ui_dynamic_flow_show_screen_cb show_cb, void *cb_ctx); + +#endif \ No newline at end of file diff --git a/src/ui/ui_dynamic_flow_nbgl.c b/src/ui/ui_dynamic_flow_nbgl.c index bee4b82..666b5b1 100644 --- a/src/ui/ui_dynamic_flow_nbgl.c +++ b/src/ui/ui_dynamic_flow_nbgl.c @@ -4,13 +4,13 @@ #include #include -bool ui_add_dynamic_flow_screens(uint8_t *screen, +/*bool ui_add_dynamic_flow_screens(uint8_t *screen, uint8_t dynamic_screen_count, char *title_storage, char *text_storage, ui_dynamic_flow_show_screen_cb show_cb, void *cb_ctx) { return true; -} +}*/ #endif \ No newline at end of file From d544f0155838a0f1949b3e7ac6fd5e6688ae9910 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 9 Oct 2024 08:56:10 +0300 Subject: [PATCH 04/56] Cleanup --- src/ui/ui_dynamic_flow_nbgl.c | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 src/ui/ui_dynamic_flow_nbgl.c diff --git a/src/ui/ui_dynamic_flow_nbgl.c b/src/ui/ui_dynamic_flow_nbgl.c deleted file mode 100644 index 666b5b1..0000000 --- a/src/ui/ui_dynamic_flow_nbgl.c +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef HAVE_NBGL - -#include "ui_menu.h" -#include -#include - -/*bool ui_add_dynamic_flow_screens(uint8_t *screen, - uint8_t dynamic_screen_count, - char *title_storage, - char *text_storage, - ui_dynamic_flow_show_screen_cb show_cb, - void *cb_ctx) { - return true; -}*/ - -#endif \ No newline at end of file From e5285ab10532e54dd955dd3ae73ae26f131a1aca Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 9 Oct 2024 08:59:41 +0300 Subject: [PATCH 05/56] Lint --- src/commands/deriveaddress/da_ui.h | 1 - src/commands/deriveaddress/da_ui_bagl.c | 1 - src/commands/deriveaddress/da_ui_nbgl.c | 24 ++- src/commands/extpubkey/epk_ui_nbgl.c | 10 +- src/commands/signtx/operations/stx_op_p2pk.c | 6 +- src/commands/signtx/stx_ui_nbgl.c | 5 - src/ui/display.h | 4 +- src/ui/ui_application_id_nbgl.c | 1 - src/ui/ui_bip32_path_nbgl.c | 1 - src/ui/ui_dynamic_flow.h | 2 - src/ui/ui_menu_nbgl.c | 5 +- unit-tests/utils/base58.c | 26 ++- unit-tests/utils/bip32.c | 9 +- unit-tests/utils/bip32.h | 6 +- unit-tests/utils/blake2-impl.h | 166 ++++++++----------- unit-tests/utils/blake2b-ref.h | 104 ++++++------ unit-tests/utils/buffer.c | 42 ++--- unit-tests/utils/buffer.h | 6 +- unit-tests/utils/cx.c | 5 +- unit-tests/utils/cx.h | 2 +- unit-tests/utils/macro_helpers.h | 8 +- unit-tests/utils/read.c | 18 +- unit-tests/utils/varint.c | 9 +- unit-tests/utils/write.c | 18 +- 24 files changed, 215 insertions(+), 264 deletions(-) diff --git a/src/commands/deriveaddress/da_ui.h b/src/commands/deriveaddress/da_ui.h index c45a973..d6b660a 100644 --- a/src/commands/deriveaddress/da_ui.h +++ b/src/commands/deriveaddress/da_ui.h @@ -20,7 +20,6 @@ int ui_display_address(derive_address_ctx_t* ctx, uint8_t bip32_path_len, uint8_t raw_address[static P2PK_ADDRESS_LEN]); - static inline int send_error(uint16_t err) { app_set_current_command(CMD_NONE); return res_error(err); diff --git a/src/commands/deriveaddress/da_ui_bagl.c b/src/commands/deriveaddress/da_ui_bagl.c index 3849afc..67a2f30 100644 --- a/src/commands/deriveaddress/da_ui_bagl.c +++ b/src/commands/deriveaddress/da_ui_bagl.c @@ -51,7 +51,6 @@ static NOINLINE void ui_action_derive_address(bool approved, void* context) { ui_menu_main(); } - // Display int ui_display_address(derive_address_ctx_t* ctx, bool send, diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index 119f820..87a078a 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -31,8 +31,7 @@ int ui_display_address(derive_address_ctx_t* ctx, uint32_t app_access_token, uint32_t* bip32_path, uint8_t bip32_path_len, - uint8_t raw_address[static P2PK_ADDRESS_LEN]) -{ + uint8_t raw_address[static P2PK_ADDRESS_LEN]) { if (!bip32_path_validate(bip32_path, bip32_path_len, BIP32_HARDENED(44), @@ -44,7 +43,6 @@ int ui_display_address(derive_address_ctx_t* ctx, ctx->app_token_value = app_access_token; ctx->send = send; - memset(ctx->address, 0, MEMBER_SIZE(derive_address_ctx_t, address)); if (!send) { int result = base58_encode(raw_address, @@ -55,25 +53,33 @@ int ui_display_address(derive_address_ctx_t* ctx, if (result == -1 || result >= P2PK_ADDRESS_STRING_MAX_LEN) { return send_error(SW_ADDRESS_FORMATTING_FAILED); } - } if (app_access_token != 0) { // TO-DO - //ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_id), &screen); + // ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_id), &screen); } - if(send) { + if (send) { // Confirm Send Address - nbgl_useCaseAddressReview(ctx->address, NULL, &WHEEL_ICON, "Confirm Send Address", "", ui_display_address_confirm); + nbgl_useCaseAddressReview(ctx->address, + NULL, + &WHEEL_ICON, + "Confirm Send Address", + "", + ui_display_address_confirm); } else { // Confirm Address - nbgl_useCaseAddressReview(ctx->address, NULL, &INFO_I_ICON, "Confirm Address", "", ui_display_address_confirm); + nbgl_useCaseAddressReview(ctx->address, + NULL, + &INFO_I_ICON, + "Confirm Address", + "", + ui_display_address_confirm); } memmove(ctx->raw_address, raw_address, P2PK_ADDRESS_LEN); - bool approved = io_ui_process(); if (approved) { diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c index ee4da05..93bb1b8 100644 --- a/src/commands/extpubkey/epk_ui_nbgl.c +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -44,17 +44,21 @@ int ui_display_account(extended_public_key_ctx_t* ctx, return NULL; } - if (app_access_token != 0) { // TO-DO - //ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_token), &screen); + // ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_token), &screen); } ctx->app_token_value = app_access_token; memmove(ctx->raw_public_key, raw_pub_key, PUBLIC_KEY_LEN); memmove(ctx->chain_code, chain_code, CHAIN_CODE_LEN); - nbgl_useCaseChoice(&WARNING_ICON,"Ext PubKey Export", ctx->bip32_path, "Confirm", "Cancel", ui_display_account_confirm); + nbgl_useCaseChoice(&WARNING_ICON, + "Ext PubKey Export", + ctx->bip32_path, + "Confirm", + "Cancel", + ui_display_account_confirm); bool approved = io_ui_process(); if (approved) { diff --git a/src/commands/signtx/operations/stx_op_p2pk.c b/src/commands/signtx/operations/stx_op_p2pk.c index 5d2c4a0..30b475f 100644 --- a/src/commands/signtx/operations/stx_op_p2pk.c +++ b/src/commands/signtx/operations/stx_op_p2pk.c @@ -331,10 +331,10 @@ static NOINLINE void ui_stx_operation_p2pk_approve_action(void *context) { uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2pk_ctx_t *ctx, uint32_t app_access_token, bool is_known_application, - + void *sign_tx_ctx) { uint8_t screen = 0; - #ifdef HAVE_BAGL +#ifdef HAVE_BAGL const ux_flow_step_t *b32_step = ui_bip32_path_screen( ctx->bip32.path, ctx->bip32.len, @@ -347,7 +347,7 @@ uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2 return SW_BIP32_FORMATTING_FAILED; } ui_add_screen(b32_step, &screen); - #endif +#endif if (!ui_stx_add_operation_approve_screens(&ctx->ui_approve.ui_approve, &screen, diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index ef8b11c..2a67ee8 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -15,7 +15,6 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, return true; } - bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_output_info_ctx_t* output, @@ -24,7 +23,6 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, return true; } - bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_amounts_ctx_t* amounts, @@ -35,14 +33,11 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, return true; } - bool ui_stx_display_screens(uint8_t screen_count) { return true; } - void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_ctx_t* ctx) { - } #endif \ No newline at end of file diff --git a/src/ui/display.h b/src/ui/display.h index fbc1d23..739e3ba 100644 --- a/src/ui/display.h +++ b/src/ui/display.h @@ -13,7 +13,7 @@ static void set_flow_reseponse(bool response) { static bool io_ui_process() { // We are not waiting for the client's input, nor we are doing computations on the device - //io_clear_processing_timeout(); + // io_clear_processing_timeout(); app_set_ui_busy(true); @@ -25,7 +25,7 @@ static bool io_ui_process() { } while (io_seproxyhal_spi_is_status_sent() && G_app_context.is_ui_busy); // We're back at work, we want to show the "Processing..." screen when appropriate - //io_start_processing_timeout(); + // io_start_processing_timeout(); return flow_response; } \ No newline at end of file diff --git a/src/ui/ui_application_id_nbgl.c b/src/ui/ui_application_id_nbgl.c index 691e442..20494f5 100644 --- a/src/ui/ui_application_id_nbgl.c +++ b/src/ui/ui_application_id_nbgl.c @@ -2,5 +2,4 @@ #include "ui_application_id.h" - #endif \ No newline at end of file diff --git a/src/ui/ui_bip32_path_nbgl.c b/src/ui/ui_bip32_path_nbgl.c index 0b025ab..6369cdc 100644 --- a/src/ui/ui_bip32_path_nbgl.c +++ b/src/ui/ui_bip32_path_nbgl.c @@ -2,5 +2,4 @@ #include "ui_bip32_path.h" - #endif \ No newline at end of file diff --git a/src/ui/ui_dynamic_flow.h b/src/ui/ui_dynamic_flow.h index 0af0215..7d494c3 100644 --- a/src/ui/ui_dynamic_flow.h +++ b/src/ui/ui_dynamic_flow.h @@ -4,12 +4,10 @@ #include #include - #ifdef HAVE_BAGL typedef uint16_t (*ui_dynamic_flow_show_screen_cb)(uint8_t, char *, char *, void *); - // Global context pointer will be set to the dynamic flow context. Don't change it. bool ui_add_dynamic_flow_screens(uint8_t *screen, uint8_t dynamic_screen_count, diff --git a/src/ui/ui_menu_nbgl.c b/src/ui/ui_menu_nbgl.c index f9e7082..09ebc92 100644 --- a/src/ui/ui_menu_nbgl.c +++ b/src/ui/ui_menu_nbgl.c @@ -4,7 +4,7 @@ #include #include -#define APPTAGLINE "Ergo app for ledger" +#define APPTAGLINE "Ergo app for ledger" #define APPCOPYRIGHT "Ergo App (c) 2024" #define SETTING_INFO_NB 2 @@ -22,7 +22,7 @@ void app_quit(void) { } void ui_menu_main() { - nbgl_useCaseHomeAndSettings(APPNAME, + nbgl_useCaseHomeAndSettings(APPNAME, &C_app_logo_64px, APPTAGLINE, INIT_HOME_PAGE, @@ -33,7 +33,6 @@ void ui_menu_main() { } void ui_menu_about() { - } #endif \ No newline at end of file diff --git a/unit-tests/utils/base58.c b/unit-tests/utils/base58.c index b526269..05197a3 100644 --- a/unit-tests/utils/base58.c +++ b/unit-tests/utils/base58.c @@ -43,9 +43,8 @@ char const BASE58_ALPHABET[] = { 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' // }; -int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) -{ - uint8_t tmp[MAX_DEC_INPUT_SIZE] = {0}; +int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) { + uint8_t tmp[MAX_DEC_INPUT_SIZE] = {0}; uint8_t buffer[MAX_DEC_INPUT_SIZE] = {0}; uint8_t j; uint8_t start_at; @@ -73,15 +72,15 @@ int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) ++zero_count; } - j = in_len; + j = in_len; start_at = zero_count; while (start_at < in_len) { uint16_t remainder = 0; for (uint8_t div_loop = start_at; div_loop < in_len; div_loop++) { uint16_t digit256 = (uint16_t) (tmp[div_loop] & 0xFF); - uint16_t tmp_div = remainder * 58 + digit256; - tmp[div_loop] = (uint8_t) (tmp_div / 256); - remainder = tmp_div % 256; + uint16_t tmp_div = remainder * 58 + digit256; + tmp[div_loop] = (uint8_t) (tmp_div / 256); + remainder = tmp_div % 256; } if (tmp[start_at] == 0) { @@ -106,13 +105,12 @@ int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) return length; } -int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) -{ +int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) { uint8_t buffer[MAX_ENC_INPUT_SIZE * 138 / 100 + 1] = {0}; - size_t i, j; - size_t stop_at; - size_t zero_count = 0; - size_t output_size; + size_t i, j; + size_t stop_at; + size_t zero_count = 0; + size_t output_size; if (in_len > MAX_ENC_INPUT_SIZE) { return -1; @@ -123,7 +121,7 @@ int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) } output_size = (in_len - zero_count) * 138 / 100 + 1; - stop_at = output_size - 1; + stop_at = output_size - 1; for (size_t start_at = zero_count; start_at < in_len; start_at++) { int carry = in[start_at]; for (j = output_size - 1; (int) j >= 0; j--) { diff --git a/unit-tests/utils/bip32.c b/unit-tests/utils/bip32.c index 2f7ec96..5b305f0 100644 --- a/unit-tests/utils/bip32.c +++ b/unit-tests/utils/bip32.c @@ -23,8 +23,7 @@ #include "bip32.h" #include "read.h" -bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len) -{ +bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len) { if (out_len == 0 || out_len > MAX_BIP32_PATH) { return false; } @@ -42,8 +41,10 @@ bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out return true; } -bool bip32_path_format(const uint32_t *bip32_path, size_t bip32_path_len, char *out, size_t out_len) -{ +bool bip32_path_format(const uint32_t *bip32_path, + size_t bip32_path_len, + char *out, + size_t out_len) { if (bip32_path_len == 0 || bip32_path_len > MAX_BIP32_PATH) { return false; } diff --git a/unit-tests/utils/bip32.h b/unit-tests/utils/bip32.h index 734c766..0eb85a5 100644 --- a/unit-tests/utils/bip32.h +++ b/unit-tests/utils/bip32.h @@ -42,6 +42,6 @@ bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out * */ bool bip32_path_format(const uint32_t *bip32_path, - size_t bip32_path_len, - char *out, - size_t out_len); \ No newline at end of file + size_t bip32_path_len, + char *out, + size_t out_len); \ No newline at end of file diff --git a/unit-tests/utils/blake2-impl.h b/unit-tests/utils/blake2-impl.h index c1df82e..e281796 100644 --- a/unit-tests/utils/blake2-impl.h +++ b/unit-tests/utils/blake2-impl.h @@ -19,142 +19,120 @@ #include #if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) - #if defined(_MSC_VER) - #define BLAKE2_INLINE __inline - #elif defined(__GNUC__) - #define BLAKE2_INLINE __inline__ - #else - #define BLAKE2_INLINE - #endif +#if defined(_MSC_VER) +#define BLAKE2_INLINE __inline +#elif defined(__GNUC__) +#define BLAKE2_INLINE __inline__ #else - #define BLAKE2_INLINE inline +#define BLAKE2_INLINE +#endif +#else +#define BLAKE2_INLINE inline #endif -static BLAKE2_INLINE uint32_t load32( const void *src ) -{ +static BLAKE2_INLINE uint32_t load32(const void *src) { #if defined(NATIVE_LITTLE_ENDIAN) - uint32_t w; - memcpy(&w, src, sizeof w); - return w; + uint32_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = ( const uint8_t * )src; - return (( uint32_t )( p[0] ) << 0) | - (( uint32_t )( p[1] ) << 8) | - (( uint32_t )( p[2] ) << 16) | - (( uint32_t )( p[3] ) << 24) ; + const uint8_t *p = (const uint8_t *) src; + return ((uint32_t) (p[0]) << 0) | ((uint32_t) (p[1]) << 8) | ((uint32_t) (p[2]) << 16) | + ((uint32_t) (p[3]) << 24); #endif } -static BLAKE2_INLINE uint64_t load64( const void *src ) -{ +static BLAKE2_INLINE uint64_t load64(const void *src) { #if defined(NATIVE_LITTLE_ENDIAN) - uint64_t w; - memcpy(&w, src, sizeof w); - return w; + uint64_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = ( const uint8_t * )src; - return (( uint64_t )( p[0] ) << 0) | - (( uint64_t )( p[1] ) << 8) | - (( uint64_t )( p[2] ) << 16) | - (( uint64_t )( p[3] ) << 24) | - (( uint64_t )( p[4] ) << 32) | - (( uint64_t )( p[5] ) << 40) | - (( uint64_t )( p[6] ) << 48) | - (( uint64_t )( p[7] ) << 56) ; + const uint8_t *p = (const uint8_t *) src; + return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16) | + ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40) | + ((uint64_t) (p[6]) << 48) | ((uint64_t) (p[7]) << 56); #endif } -static BLAKE2_INLINE uint16_t load16( const void *src ) -{ +static BLAKE2_INLINE uint16_t load16(const void *src) { #if defined(NATIVE_LITTLE_ENDIAN) - uint16_t w; - memcpy(&w, src, sizeof w); - return w; + uint16_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = ( const uint8_t * )src; - return ( uint16_t )((( uint32_t )( p[0] ) << 0) | - (( uint32_t )( p[1] ) << 8)); + const uint8_t *p = (const uint8_t *) src; + return (uint16_t) (((uint32_t) (p[0]) << 0) | ((uint32_t) (p[1]) << 8)); #endif } -static BLAKE2_INLINE void store16( void *dst, uint16_t w ) -{ +static BLAKE2_INLINE void store16(void *dst, uint16_t w) { #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = ( uint8_t * )dst; - *p++ = ( uint8_t )w; w >>= 8; - *p++ = ( uint8_t )w; + uint8_t *p = (uint8_t *) dst; + *p++ = (uint8_t) w; + w >>= 8; + *p++ = (uint8_t) w; #endif } -static BLAKE2_INLINE void store32( void *dst, uint32_t w ) -{ +static BLAKE2_INLINE void store32(void *dst, uint32_t w) { #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = ( uint8_t * )dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) (w >> 0); + p[1] = (uint8_t) (w >> 8); + p[2] = (uint8_t) (w >> 16); + p[3] = (uint8_t) (w >> 24); #endif } -static BLAKE2_INLINE void store64( void *dst, uint64_t w ) -{ +static BLAKE2_INLINE void store64(void *dst, uint64_t w) { #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = ( uint8_t * )dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); - p[4] = (uint8_t)(w >> 32); - p[5] = (uint8_t)(w >> 40); - p[6] = (uint8_t)(w >> 48); - p[7] = (uint8_t)(w >> 56); + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) (w >> 0); + p[1] = (uint8_t) (w >> 8); + p[2] = (uint8_t) (w >> 16); + p[3] = (uint8_t) (w >> 24); + p[4] = (uint8_t) (w >> 32); + p[5] = (uint8_t) (w >> 40); + p[6] = (uint8_t) (w >> 48); + p[7] = (uint8_t) (w >> 56); #endif } -static BLAKE2_INLINE uint64_t load48( const void *src ) -{ - const uint8_t *p = ( const uint8_t * )src; - return (( uint64_t )( p[0] ) << 0) | - (( uint64_t )( p[1] ) << 8) | - (( uint64_t )( p[2] ) << 16) | - (( uint64_t )( p[3] ) << 24) | - (( uint64_t )( p[4] ) << 32) | - (( uint64_t )( p[5] ) << 40) ; +static BLAKE2_INLINE uint64_t load48(const void *src) { + const uint8_t *p = (const uint8_t *) src; + return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16) | + ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40); } -static BLAKE2_INLINE void store48( void *dst, uint64_t w ) -{ - uint8_t *p = ( uint8_t * )dst; - p[0] = (uint8_t)(w >> 0); - p[1] = (uint8_t)(w >> 8); - p[2] = (uint8_t)(w >> 16); - p[3] = (uint8_t)(w >> 24); - p[4] = (uint8_t)(w >> 32); - p[5] = (uint8_t)(w >> 40); +static BLAKE2_INLINE void store48(void *dst, uint64_t w) { + uint8_t *p = (uint8_t *) dst; + p[0] = (uint8_t) (w >> 0); + p[1] = (uint8_t) (w >> 8); + p[2] = (uint8_t) (w >> 16); + p[3] = (uint8_t) (w >> 24); + p[4] = (uint8_t) (w >> 32); + p[5] = (uint8_t) (w >> 40); } -static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) -{ - return ( w >> c ) | ( w << ( 32 - c ) ); +static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) { + return (w >> c) | (w << (32 - c)); } -static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) -{ - return ( w >> c ) | ( w << ( 64 - c ) ); +static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) { + return (w >> c) | (w << (64 - c)); } /* prevents compiler optimizing out memset() */ -static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) -{ - static void *(*const volatile memset_v)(void *, int, size_t) = &memset; - memset_v(v, 0, n); +static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) { + static void *(*const volatile memset_v)(void *, int, size_t) = &memset; + memset_v(v, 0, n); } #endif diff --git a/unit-tests/utils/blake2b-ref.h b/unit-tests/utils/blake2b-ref.h index 5eb9fe3..4b65282 100644 --- a/unit-tests/utils/blake2b-ref.h +++ b/unit-tests/utils/blake2b-ref.h @@ -28,62 +28,66 @@ extern "C" { #endif - enum blake2b_constant - { +enum blake2b_constant { BLAKE2B_BLOCKBYTES = 128, - BLAKE2B_OUTBYTES = 64, - BLAKE2B_KEYBYTES = 64, - BLAKE2B_SALTBYTES = 16, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, BLAKE2B_PERSONALBYTES = 16 - }; +}; - typedef struct blake2b_state__ - { +typedef struct blake2b_state__ { uint64_t h[8]; uint64_t t[2]; uint64_t f[2]; - uint8_t buf[BLAKE2B_BLOCKBYTES]; - size_t buflen; - size_t outlen; - uint8_t last_node; - } blake2b_state; - - - BLAKE2_PACKED(struct blake2b_param__ - { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint32_t leaf_length; /* 8 */ - uint32_t node_offset; /* 12 */ - uint32_t xof_length; /* 16 */ - uint8_t node_depth; /* 17 */ - uint8_t inner_length; /* 18 */ - uint8_t reserved[14]; /* 32 */ - uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ - uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ - }); - - typedef struct blake2b_param__ blake2b_param; - - /* Padded structs result in a compile-time error */ - enum { - BLAKE2_DUMMY_2 = 1/(int)(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) - }; - - /* Streaming API */ - int blake2b_ref_init( blake2b_state *S, size_t outlen ); - int blake2b_ref_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ); - int blake2b_ref_init_param( blake2b_state *S, const blake2b_param *P ); - int blake2b_ref_update( blake2b_state *S, const void *in, size_t inlen ); - int blake2b_ref_final( blake2b_state *S, void *out, size_t outlen ); - - /* Simple API */ - int blake2b_ref( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); - - /* This is simply an alias for blake2b */ - int blake2_ref( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + uint8_t buf[BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; +} blake2b_state; + +BLAKE2_PACKED(struct blake2b_param__ { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ +}); + +typedef struct blake2b_param__ blake2b_param; + +/* Padded structs result in a compile-time error */ +enum { BLAKE2_DUMMY_2 = 1 / (int) (sizeof(blake2b_param) == BLAKE2B_OUTBYTES) }; + +/* Streaming API */ +int blake2b_ref_init(blake2b_state *S, size_t outlen); +int blake2b_ref_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen); +int blake2b_ref_init_param(blake2b_state *S, const blake2b_param *P); +int blake2b_ref_update(blake2b_state *S, const void *in, size_t inlen); +int blake2b_ref_final(blake2b_state *S, void *out, size_t outlen); + +/* Simple API */ +int blake2b_ref(void *out, + size_t outlen, + const void *in, + size_t inlen, + const void *key, + size_t keylen); + +/* This is simply an alias for blake2b */ +int blake2_ref(void *out, + size_t outlen, + const void *in, + size_t inlen, + const void *key, + size_t keylen); #if defined(__cplusplus) } diff --git a/unit-tests/utils/buffer.c b/unit-tests/utils/buffer.c index 96071a2..9d97c07 100644 --- a/unit-tests/utils/buffer.c +++ b/unit-tests/utils/buffer.c @@ -24,13 +24,11 @@ #include "varint.h" #include "bip32.h" -bool buffer_can_read(const buffer_t *buffer, size_t n) -{ +bool buffer_can_read(const buffer_t *buffer, size_t n) { return buffer->size - buffer->offset >= n; } -bool buffer_seek_set(buffer_t *buffer, size_t offset) -{ +bool buffer_seek_set(buffer_t *buffer, size_t offset) { if (offset > buffer->size) { return false; } @@ -40,8 +38,7 @@ bool buffer_seek_set(buffer_t *buffer, size_t offset) return true; } -bool buffer_seek_cur(buffer_t *buffer, size_t offset) -{ +bool buffer_seek_cur(buffer_t *buffer, size_t offset) { if (buffer->offset + offset < buffer->offset || // overflow buffer->offset + offset > buffer->size) { // exceed buffer size return false; @@ -52,8 +49,7 @@ bool buffer_seek_cur(buffer_t *buffer, size_t offset) return true; } -bool buffer_seek_end(buffer_t *buffer, size_t offset) -{ +bool buffer_seek_end(buffer_t *buffer, size_t offset) { if (offset > buffer->size) { return false; } @@ -63,8 +59,7 @@ bool buffer_seek_end(buffer_t *buffer, size_t offset) return true; } -bool buffer_read_u8(buffer_t *buffer, uint8_t *value) -{ +bool buffer_read_u8(buffer_t *buffer, uint8_t *value) { if (!buffer_can_read(buffer, 1)) { *value = 0; @@ -77,8 +72,7 @@ bool buffer_read_u8(buffer_t *buffer, uint8_t *value) return true; } -bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) -{ +bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) { if (!buffer_can_read(buffer, 2)) { *value = 0; @@ -93,8 +87,7 @@ bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) return true; } -bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) -{ +bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) { if (!buffer_can_read(buffer, 4)) { *value = 0; @@ -109,8 +102,7 @@ bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) return true; } -bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) -{ +bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) { if (!buffer_can_read(buffer, 8)) { *value = 0; @@ -125,8 +117,7 @@ bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) return true; } -bool buffer_read_varint(buffer_t *buffer, uint64_t *value) -{ +bool buffer_read_varint(buffer_t *buffer, uint64_t *value) { int length = varint_read(buffer->ptr + buffer->offset, buffer->size - buffer->offset, value); if (length < 0) { @@ -138,10 +129,11 @@ bool buffer_read_varint(buffer_t *buffer, uint64_t *value) return buffer_seek_cur(buffer, (size_t) length); } -bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) -{ - if (!bip32_path_read( - buffer->ptr + buffer->offset, buffer->size - buffer->offset, out, out_len)) { +bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) { + if (!bip32_path_read(buffer->ptr + buffer->offset, + buffer->size - buffer->offset, + out, + out_len)) { return false; } @@ -150,8 +142,7 @@ bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) return true; } -bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) -{ +bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) { if (buffer->size - buffer->offset > out_len) { return false; } @@ -161,8 +152,7 @@ bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) return true; } -bool buffer_move(buffer_t *buffer, uint8_t *out, size_t out_len) -{ +bool buffer_move(buffer_t *buffer, uint8_t *out, size_t out_len) { if (!buffer_copy(buffer, out, out_len)) { return false; } diff --git a/unit-tests/utils/buffer.h b/unit-tests/utils/buffer.h index 6b31ab0..ae3e829 100644 --- a/unit-tests/utils/buffer.h +++ b/unit-tests/utils/buffer.h @@ -16,9 +16,9 @@ typedef enum { * Struct for buffer with size and offset. */ typedef struct { - const uint8_t *ptr; /// Pointer to byte buffer - size_t size; /// Size of byte buffer - size_t offset; /// Offset in byte buffer + const uint8_t *ptr; /// Pointer to byte buffer + size_t size; /// Size of byte buffer + size_t offset; /// Offset in byte buffer } buffer_t; /** diff --git a/unit-tests/utils/cx.c b/unit-tests/utils/cx.c index 929fbb9..f3ad975 100644 --- a/unit-tests/utils/cx.c +++ b/unit-tests/utils/cx.c @@ -61,10 +61,9 @@ cx_err_t cx_hash_no_throw(cx_hash_t *hash, } } -cx_err_t cx_blake2b_256_hash(const uint8_t* data, +cx_err_t cx_blake2b_256_hash(const uint8_t *data, size_t len, - uint8_t out[static CX_BLAKE2B_256_SIZE]) -{ + uint8_t out[static CX_BLAKE2B_256_SIZE]) { return blake2b_ref(out, CX_BLAKE2B_256_SIZE, data, len, NULL, 0); } diff --git a/unit-tests/utils/cx.h b/unit-tests/utils/cx.h index cf465b5..78acd01 100644 --- a/unit-tests/utils/cx.h +++ b/unit-tests/utils/cx.h @@ -45,7 +45,7 @@ cx_err_t cx_hash_no_throw(cx_hash_t *hash, uint8_t *out, size_t out_len); -cx_err_t cx_blake2b_256_hash(const uint8_t* data, +cx_err_t cx_blake2b_256_hash(const uint8_t *data, size_t len, uint8_t out[static CX_BLAKE2B_256_SIZE]); diff --git a/unit-tests/utils/macro_helpers.h b/unit-tests/utils/macro_helpers.h index a9bb897..2406153 100644 --- a/unit-tests/utils/macro_helpers.h +++ b/unit-tests/utils/macro_helpers.h @@ -2,14 +2,12 @@ #pragma once // UNUSED macro. Defined in the Makefile -#define UNUSED(x) (void)(x) - +#define UNUSED(x) (void) (x) #define BUFFER_FROM_ARRAY(_name, _array, _size) \ RW_BUFFER_FROM_ARRAY_FULL(__rw_##_name, _array, _size); \ buffer_t _name = __rw_##_name.read - -#define BUFFER_NEW_LOCAL_EMPTY(_name, _size) \ - RW_BUFFER_NEW_LOCAL_EMPTY(__rw_##_name, _size); \ +#define BUFFER_NEW_LOCAL_EMPTY(_name, _size) \ + RW_BUFFER_NEW_LOCAL_EMPTY(__rw_##_name, _size); \ buffer_t _name = __rw_##_name.read \ No newline at end of file diff --git a/unit-tests/utils/read.c b/unit-tests/utils/read.c index 09a7d71..dd1166e 100644 --- a/unit-tests/utils/read.c +++ b/unit-tests/utils/read.c @@ -19,22 +19,19 @@ #include "read.h" -uint16_t read_u16_be(const uint8_t *ptr, size_t offset) -{ +uint16_t read_u16_be(const uint8_t *ptr, size_t offset) { return (uint16_t) ptr[offset + 0] << 8 | // (uint16_t) ptr[offset + 1] << 0; } -uint32_t read_u32_be(const uint8_t *ptr, size_t offset) -{ +uint32_t read_u32_be(const uint8_t *ptr, size_t offset) { return (uint32_t) ptr[offset + 0] << 24 | // (uint32_t) ptr[offset + 1] << 16 | // (uint32_t) ptr[offset + 2] << 8 | // (uint32_t) ptr[offset + 3] << 0; } -uint64_t read_u64_be(const uint8_t *ptr, size_t offset) -{ +uint64_t read_u64_be(const uint8_t *ptr, size_t offset) { return (uint64_t) ptr[offset + 0] << 56 | // (uint64_t) ptr[offset + 1] << 48 | // (uint64_t) ptr[offset + 2] << 40 | // @@ -45,22 +42,19 @@ uint64_t read_u64_be(const uint8_t *ptr, size_t offset) (uint64_t) ptr[offset + 7] << 0; } -uint16_t read_u16_le(const uint8_t *ptr, size_t offset) -{ +uint16_t read_u16_le(const uint8_t *ptr, size_t offset) { return (uint16_t) ptr[offset + 0] << 0 | // (uint16_t) ptr[offset + 1] << 8; } -uint32_t read_u32_le(const uint8_t *ptr, size_t offset) -{ +uint32_t read_u32_le(const uint8_t *ptr, size_t offset) { return (uint32_t) ptr[offset + 0] << 0 | // (uint32_t) ptr[offset + 1] << 8 | // (uint32_t) ptr[offset + 2] << 16 | // (uint32_t) ptr[offset + 3] << 24; } -uint64_t read_u64_le(const uint8_t *ptr, size_t offset) -{ +uint64_t read_u64_le(const uint8_t *ptr, size_t offset) { return (uint64_t) ptr[offset + 0] << 0 | // (uint64_t) ptr[offset + 1] << 8 | // (uint64_t) ptr[offset + 2] << 16 | // diff --git a/unit-tests/utils/varint.c b/unit-tests/utils/varint.c index fb199f9..d04fbb2 100644 --- a/unit-tests/utils/varint.c +++ b/unit-tests/utils/varint.c @@ -22,8 +22,7 @@ #include "write.h" #include "read.h" -uint8_t varint_size(uint64_t value) -{ +uint8_t varint_size(uint64_t value) { if (value <= 0xFC) { return 1; } @@ -39,8 +38,7 @@ uint8_t varint_size(uint64_t value) return 9; // <= UINT64_MAX } -int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) -{ +int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) { if (in_len < 1) { return -1; } @@ -76,8 +74,7 @@ int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) return 1; } -int varint_write(uint8_t *out, size_t offset, uint64_t value) -{ +int varint_write(uint8_t *out, size_t offset, uint64_t value) { uint8_t varint_len = varint_size(value); switch (varint_len) { diff --git a/unit-tests/utils/write.c b/unit-tests/utils/write.c index b6ae4b7..7c4f3c5 100644 --- a/unit-tests/utils/write.c +++ b/unit-tests/utils/write.c @@ -19,22 +19,19 @@ #include "write.h" -void write_u16_be(uint8_t *ptr, size_t offset, uint16_t value) -{ +void write_u16_be(uint8_t *ptr, size_t offset, uint16_t value) { ptr[offset + 0] = (uint8_t) (value >> 8); ptr[offset + 1] = (uint8_t) (value >> 0); } -void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value) -{ +void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value) { ptr[offset + 0] = (uint8_t) (value >> 24); ptr[offset + 1] = (uint8_t) (value >> 16); ptr[offset + 2] = (uint8_t) (value >> 8); ptr[offset + 3] = (uint8_t) (value >> 0); } -void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) -{ +void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) { ptr[offset + 0] = (uint8_t) (value >> 56); ptr[offset + 1] = (uint8_t) (value >> 48); ptr[offset + 2] = (uint8_t) (value >> 40); @@ -45,22 +42,19 @@ void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) ptr[offset + 7] = (uint8_t) (value >> 0); } -void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value) -{ +void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value) { ptr[offset + 0] = (uint8_t) (value >> 0); ptr[offset + 1] = (uint8_t) (value >> 8); } -void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value) -{ +void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value) { ptr[offset + 0] = (uint8_t) (value >> 0); ptr[offset + 1] = (uint8_t) (value >> 8); ptr[offset + 2] = (uint8_t) (value >> 16); ptr[offset + 3] = (uint8_t) (value >> 24); } -void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value) -{ +void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value) { ptr[offset + 0] = (uint8_t) (value >> 0); ptr[offset + 1] = (uint8_t) (value >> 8); ptr[offset + 2] = (uint8_t) (value >> 16); From 483d7570cabb92d5e7d32c97de63e14a685b2668 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 9 Oct 2024 09:03:23 +0300 Subject: [PATCH 06/56] Attempt to fix lint workflow --- .github/workflows/lint-workflow.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint-workflow.yml b/.github/workflows/lint-workflow.yml index e613370..85e94ae 100644 --- a/.github/workflows/lint-workflow.yml +++ b/.github/workflows/lint-workflow.yml @@ -12,7 +12,7 @@ jobs: uses: actions/checkout@v4 - name: Lint - uses: DoozyX/clang-format-lint-action@v0.12 + uses: DoozyX/clang-format-lint-action@v0.18.2 with: source: './src' extensions: 'h,c' From 8ecbe687ba145df9a181d798f6b32940b12a9820 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 9 Oct 2024 09:37:58 +0300 Subject: [PATCH 07/56] Workflow fix attempt --- .github/workflows/ci-workflow.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 8d8ba80..8a56402 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -4,7 +4,7 @@ on: [push, pull_request] jobs: job_build_nano_debug: - name: Build application for NanoS+, X + name: Build application for NanoS+, X, Stax, Flex runs-on: ubuntu-latest strategy: matrix: @@ -13,6 +13,10 @@ jobs: artifact: ergo-app-debug-nanox - SDK: "$NANOSP_SDK" artifact: ergo-app-debug-nanosp + - SDK: "$STAX_SDK" + artifact: ergo-app-debug-nanosp + - SDK: "$FLEX_SDK" + artifact: ergo-app-debug-nanosp container: image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest @@ -126,10 +130,14 @@ jobs: strategy: matrix: include: - # - model: nanox - # SDK: "2.0.2" + - model: nanox + SDK: "2.0.2" - model: nanosp SDK: "1.0.4" + - model: stax + SDK: "2.0" + - model: flex + SDK: "2.0" needs: job_build_nano_debug runs-on: ubuntu-latest @@ -157,6 +165,7 @@ jobs: curl -fsSL https://deb.nodesource.com/setup_18.x | bash - apt-get install -qy nodejs export SEED=`cat tests/seed.txt` + python /speculos/speculos.py bin/app.elf --apdu-port 9999 --api-port 5000 --display headless --model=${{ matrix.model }} --sdk=${{ matrix.SDK }} --seed "${SEED}" nohup bash -c "python /speculos/speculos.py bin/app.elf --apdu-port 9999 --api-port 5000 --display headless --model=${{ matrix.model }} --sdk=${{ matrix.SDK }} --seed \"${SEED}\"" > speculos.log 2<&1 & cd tests && npm install until `nc -w5 -z -v 127.0.0.1 9999`; do sleep 1; done; From 0357e131e76523b8b3d59c297853bd80daf98a91 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 9 Oct 2024 09:41:18 +0300 Subject: [PATCH 08/56] Fix --- .github/workflows/ci-workflow.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 8a56402..4e781b5 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -14,9 +14,9 @@ jobs: - SDK: "$NANOSP_SDK" artifact: ergo-app-debug-nanosp - SDK: "$STAX_SDK" - artifact: ergo-app-debug-nanosp + artifact: ergo-app-debug-stax - SDK: "$FLEX_SDK" - artifact: ergo-app-debug-nanosp + artifact: ergo-app-debug-flex container: image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest From 33b892c544414c406eec7384b8ff97af644fd832 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 9 Oct 2024 09:47:54 +0300 Subject: [PATCH 09/56] Removed SDK parameter from speculos run --- .github/workflows/ci-workflow.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 4e781b5..50a1b91 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -131,13 +131,9 @@ jobs: matrix: include: - model: nanox - SDK: "2.0.2" - model: nanosp - SDK: "1.0.4" - model: stax - SDK: "2.0" - model: flex - SDK: "2.0" needs: job_build_nano_debug runs-on: ubuntu-latest @@ -165,8 +161,8 @@ jobs: curl -fsSL https://deb.nodesource.com/setup_18.x | bash - apt-get install -qy nodejs export SEED=`cat tests/seed.txt` - python /speculos/speculos.py bin/app.elf --apdu-port 9999 --api-port 5000 --display headless --model=${{ matrix.model }} --sdk=${{ matrix.SDK }} --seed "${SEED}" - nohup bash -c "python /speculos/speculos.py bin/app.elf --apdu-port 9999 --api-port 5000 --display headless --model=${{ matrix.model }} --sdk=${{ matrix.SDK }} --seed \"${SEED}\"" > speculos.log 2<&1 & + python /speculos/speculos.py bin/app.elf --apdu-port 9999 --api-port 5000 --display headless --model=${{ matrix.model }} --seed "${SEED}" + nohup bash -c "python /speculos/speculos.py bin/app.elf --apdu-port 9999 --api-port 5000 --display headless --model=${{ matrix.model }} --seed \"${SEED}\"" > speculos.log 2<&1 & cd tests && npm install until `nc -w5 -z -v 127.0.0.1 9999`; do sleep 1; done; npm --model=${{matrix.model}} --port=5000 run test From 9f203a60a0061ed6dc3197890268938ac8fc14d8 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 9 Oct 2024 09:50:31 +0300 Subject: [PATCH 10/56] Fix --- .github/workflows/ci-workflow.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 50a1b91..dfd9d00 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -161,7 +161,6 @@ jobs: curl -fsSL https://deb.nodesource.com/setup_18.x | bash - apt-get install -qy nodejs export SEED=`cat tests/seed.txt` - python /speculos/speculos.py bin/app.elf --apdu-port 9999 --api-port 5000 --display headless --model=${{ matrix.model }} --seed "${SEED}" nohup bash -c "python /speculos/speculos.py bin/app.elf --apdu-port 9999 --api-port 5000 --display headless --model=${{ matrix.model }} --seed \"${SEED}\"" > speculos.log 2<&1 & cd tests && npm install until `nc -w5 -z -v 127.0.0.1 9999`; do sleep 1; done; From 5d69e8a1c04759e19db56b8f52d20def8c2321b5 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 9 Oct 2024 10:07:03 +0300 Subject: [PATCH 11/56] Added flex and stax to test --- tests/helpers/hooks.js | 2 +- tests/package.json | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/helpers/hooks.js b/tests/helpers/hooks.js index c8c9f1f..22f31b9 100644 --- a/tests/helpers/hooks.js +++ b/tests/helpers/hooks.js @@ -17,7 +17,7 @@ exports.mochaHooks = { if (!this.model) { throw new Error("No model. Provide model with --model= parameter"); } - if (["nanos", "nanox", "nanosp", "hid"].indexOf(this.model) < 0) { + if (["nanox", "nanosp", "flex", "stax", "hid"].indexOf(this.model) < 0) { throw new Error("Unknown model: " + this.model + ", supports: nanos, nanox, nanosp, hid"); } if (this.model === "hid") { diff --git a/tests/package.json b/tests/package.json index 096e40c..d63db48 100644 --- a/tests/package.json +++ b/tests/package.json @@ -13,9 +13,9 @@ "mocha": "^10.1.0" }, "dependencies": { - "@ledgerhq/hw-transport-node-hid": "6.28.5", - "@ledgerhq/hw-transport-node-speculos-http": "6.28.5", - "ergo-lib-wasm-nodejs": "v0.26.0", - "ledger-ergo-js": "^0.1.14" + "@ledgerhq/hw-transport-node-hid": "6.29.5", + "@ledgerhq/hw-transport-node-speculos-http": "6.29.4", + "ergo-lib-wasm-nodejs": "v0.28.0", + "ledger-ergo-js": "^0.1.18" } } From 9559fc114b465b3c0a704427a599b189ae48f141 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 10 Oct 2024 12:59:36 +0300 Subject: [PATCH 12/56] Sign tx initial work --- src/commands/attestinput/ainpt_ui_nbgl.c | 48 ++++ src/commands/signtx/stx_ui_nbgl.c | 299 ++++++++++++++++++++++- 2 files changed, 341 insertions(+), 6 deletions(-) diff --git a/src/commands/attestinput/ainpt_ui_nbgl.c b/src/commands/attestinput/ainpt_ui_nbgl.c index 3632247..30972da 100644 --- a/src/commands/attestinput/ainpt_ui_nbgl.c +++ b/src/commands/attestinput/ainpt_ui_nbgl.c @@ -1,8 +1,56 @@ #ifdef HAVE_NBGL #include "ainpt_ui.h" +#include "../../helpers/response.h" +#include "../../sw.h" +#include +#include +#include +#include +#include +#include "epk_response.h" +#include "../../context.h" +#include "../../common/bip32_ext.h" +#include "../../common/macros_ext.h" +#include "../../ui/ui_bip32_path.h" +#include "../../ui/ui_application_id.h" +#include "../../ui/ui_approve_reject.h" +#include "../../ui/ui_menu.h" +#include "../../ui/ui_main.h" +#include "../../ui/display.h" +#include + +void ui_action_attest_input(bool approved) { + set_flow_reseponse(approved); +} int ui_display_access_token(uint32_t app_access_token, attest_input_ctx_t* context) { + context->ui.app_token_value = app_access_token; + + if (app_access_token != 0) { + // TO-DO + //ui_add_screen(ui_application_id_screen(app_access_token, context->ui.app_token), &screen); + } + + nbgl_useCaseChoice(&VALIDATE_ICON, + "Confirm Attest Input", + "", + "Confirm", + "Cancel", + ui_action_attest_input); + bool approved = io_ui_process(); + + if (approved) { + app_set_connected_app_id(context->ui.app_token_value); + context->state = ATTEST_INPUT_STATE_APPROVED; + send_response_attested_input_session_id(context->session); + } else { + app_set_current_command(CMD_NONE); + res_deny(); + } + + ui_menu_main(); + return 0; } diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index 2a67ee8..f2f66c6 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -1,25 +1,257 @@ #ifdef HAVE_NBGL #include "stx_ui.h" -/** - * Add application access_token and accept/reject screens to the UI. - * - * @return true if success, false if screens flow is full. - * - */ +#include "../../helpers/response.h" +#include "../../sw.h" +#include +#include +#include +#include +#include +#include "epk_response.h" +#include "../../context.h" +#include "../../common/bip32_ext.h" +#include "../../common/macros_ext.h" +#include "../../ui/ui_bip32_path.h" +#include "../../ui/ui_application_id.h" +#include "../../ui/ui_approve_reject.h" +#include "../../ui/ui_menu.h" +#include "../../ui/ui_main.h" +#include "../../ui/display.h" +#include + +#ifdef TARGET_NANOS +#define ERGO_ID_UI_CHARACTERS_HALF 7 +#else +#define ERGO_ID_UI_CHARACTERS_HALF 26 +#endif + +#define STRING_ADD_STATIC_TEXT(str, slen, text) \ + strncpy(str, text, slen); \ + slen -= sizeof(text) - 1; \ + str += sizeof(text) - 1 + +static inline void id_string_remove_middle(char* str, size_t len) { + if (len <= 2 * ERGO_ID_UI_CHARACTERS_HALF + 3) return; + str[ERGO_ID_UI_CHARACTERS_HALF] = str[ERGO_ID_UI_CHARACTERS_HALF + 1] = + str[ERGO_ID_UI_CHARACTERS_HALF + 2] = '.'; + memmove(str + ERGO_ID_UI_CHARACTERS_HALF + 3, + str + len - ERGO_ID_UI_CHARACTERS_HALF, + ERGO_ID_UI_CHARACTERS_HALF); + str[2 * ERGO_ID_UI_CHARACTERS_HALF + 3] = '\0'; +} + +static inline bool format_hex_id(const uint8_t* id, size_t id_len, char* out, size_t out_len) { + int len = format_hex(id, id_len, out, out_len); + if (len <= 0) return false; + id_string_remove_middle(out, len - 1); + return true; +} + +static inline bool format_b58_id(const uint8_t* id, size_t id_len, char* out, size_t out_len) { + int len = base58_encode(id, id_len, out, out_len); + if (len <= 0) return false; + return true; +} + +static inline bool format_erg_amount(uint64_t amount, char* out, size_t out_len) { + if (!format_fpu64(out, out_len, amount, ERGO_ERG_FRACTION_DIGIT_COUNT)) { + return false; + } + size_t out_bytes = strlen(out); + if (out_len < 5 || out_bytes > out_len - 5) return false; + out_len -= out_bytes; + out += out_bytes; + STRING_ADD_STATIC_TEXT(out, out_len, " ERG"); + return true; +} + +static NOINLINE void ui_stx_operation_approve_action(bool approved) { + set_flow_reseponse(approved); +} + bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, uint8_t* screen, uint32_t app_access_token, bool is_known_application, sign_transaction_ctx_t* sign_tx) { + if (MAX_NUMBER_OF_SCREENS - *screen < 3) return false; + + if (!is_known_application) { + // TO-DO + //ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_token), screen); + } + ctx->app_token_value = app_access_token; + ctx->sign_tx_context = sign_tx; + ctx->is_known_application = is_known_application; + + nbgl_useCaseChoice(&VALIDATE_ICON, + "Confirm operation", + "", + "Confirm", + "Cancel", + ui_stx_operation_approve_action); + bool approved = io_ui_process(); + + ui_stx_operation_approve_reject(approved, ctx); + return true; } +static inline uint16_t output_info_print_address(const sign_transaction_output_info_ctx_t* ctx, + uint8_t network_id, + char* title, + uint8_t title_len, + char* address, + uint8_t address_len) { + if (!stx_output_info_is_finished(ctx)) return SW_BAD_STATE; + switch (stx_output_info_type(ctx)) { + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_BIP32: { + strncpy(title, "Change", title_len); + if (!bip32_path_format(ctx->bip32_path.path, + ctx->bip32_path.len, + address, + address_len)) { + return SW_BIP32_FORMATTING_FAILED; + } + break; + } + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_ADDRESS: { + uint8_t raw_address[P2PK_ADDRESS_LEN]; + strncpy(title, "Address", title_len); + if (!ergo_address_from_compressed_pubkey(network_id, ctx->public_key, raw_address)) { + return SW_ADDRESS_GENERATION_FAILED; + } + if (!format_b58_id(raw_address, P2PK_ADDRESS_LEN, address, address_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + break; + } + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_SCRIPT: + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_SCRIPT_HASH: { + strncpy(title, "Script Hash", title_len); + uint8_t raw_address[P2SH_ADDRESS_LEN]; + if (!ergo_address_from_script_hash(network_id, ctx->tree_hash, raw_address)) { + return SW_ADDRESS_GENERATION_FAILED; + } + if (!format_b58_id(raw_address, P2SH_ADDRESS_LEN, address, address_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + break; + } + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_MINERS_FEE: { + strncpy(title, "Fee", title_len); + strncpy(address, "Miners Fee", address_len); + break; + } + default: + return SW_BAD_STATE; + } + return SW_OK; +} + +static NOINLINE uint16_t ui_stx_display_output_state(uint8_t screen, + char* title, + char* text, + void* context) { + sign_transaction_ui_output_confirm_ctx_t* ctx = + (sign_transaction_ui_output_confirm_ctx_t*) context; + uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, title); + uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, text); + memset(title, 0, title_len); + memset(text, 0, text_len); + + switch (screen) { + case 0: // Output Address Info + return output_info_print_address(ctx->output, + ctx->network_id, + title, + title_len, + text, + text_len); + case 1: { // Output Value + strncpy(title, "Output Value", title_len); + if (!format_erg_amount(ctx->output->value, text, text_len)) { + return SW_BUFFER_ERROR; + } + break; + } + default: { // Tokens + screen -= 2; // Decrease index for info screens + uint8_t token_idx = stx_output_info_used_token_index(ctx->output, screen / 2); + if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state + return SW_BAD_TOKEN_INDEX; + } + if (screen % 2 == 0) { // Token ID + snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); + if (!format_hex_id(ctx->output->tokens_table->tokens[token_idx], + ERGO_ID_LEN, + text, + text_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + } else { // Token Value + snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); + format_u64(text, text_len, ctx->output->tokens[token_idx]); + } + break; + } + } + return SW_OK; +} + bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_output_info_ctx_t* output, sign_transaction_bip32_path_t* last_approved_change, uint8_t network_id) { + if (MAX_NUMBER_OF_SCREENS - *screen < 6) return false; + + memset(ctx, 0, sizeof(sign_transaction_ui_output_confirm_ctx_t)); + memset(last_approved_change, 0, sizeof(sign_transaction_bip32_path_t)); + + uint8_t info_screen_count = 1; // Address screen + if (stx_output_info_type(output) != SIGN_TRANSACTION_OUTPUT_INFO_TYPE_BIP32) { + uint8_t tokens_count = stx_output_info_used_tokens_count(output); + info_screen_count += 1 + (2 * tokens_count); // value screen + tokens (2 for each) + } + + if (MAX_NUMBER_OF_SCREENS - *screen < 2) return false; + + ctx->network_id = network_id; + ctx->output = output; + ctx->last_approved_change = last_approved_change; + + ui_stx_display_output_state(*screen, ctx->title, ctx->text, (void*)ctx); + + nbgl_useCaseChoice(&WARNING_ICON, + ctx->title, + ctx->text, + "Confirm", + "Cancel", + ui_stx_operation_approve_action); + + bool approved = io_ui_process(); + + app_set_ui_busy(false); + + explicit_bzero(ctx->last_approved_change, sizeof(sign_transaction_bip32_path_t)); + + if (approved) { + // store last approved change address + if (stx_output_info_type(ctx->output) == SIGN_TRANSACTION_OUTPUT_INFO_TYPE_BIP32) { + memmove(ctx->last_approved_change, + &ctx->output->bip32_path, + sizeof(sign_transaction_bip32_path_t)); + } + res_ok(); + } else { + app_set_current_command(CMD_NONE); + res_deny(); + } + + ui_menu_main(); + return true; } @@ -30,14 +262,69 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, ui_sign_transaction_operation_show_screen_cb screen_cb, ui_sign_transaction_operation_send_response_cb response_cb, void* cb_context) { + if (MAX_NUMBER_OF_SCREENS - *screen < 6) return false; + + memset(ctx, 0, sizeof(sign_transaction_ui_sign_confirm_ctx_t)); + + uint8_t tokens_count = stx_amounts_non_zero_tokens_count(amounts); + + + + nbgl_useCaseChoice(&WARNING_ICON, + ctx->title, + ctx->text, + "Confirm", + "Cancel", + ui_stx_operation_approve_action); + + bool approved = io_ui_process(); + + ui_add_screen(&ux_stx_display_sign_confirm_step, screen); + + if (!ui_add_dynamic_flow_screens(screen, + op_screen_count + 2 + (2 * tokens_count), + "Approve signing",//ctx->title, + ctx->text, + &ui_stx_display_tx_state, + (void*) ctx)) + return false; + + if (MAX_NUMBER_OF_SCREENS - *screen < 2) return false; + + ui_approve_reject_screens(ui_stx_operation_execute_action, + ctx, + ui_next_sreen_ptr(screen), + ui_next_sreen_ptr(screen)); + + ctx->op_screen_count = op_screen_count; + ctx->op_screen_cb = screen_cb; + ctx->op_response_cb = response_cb; + ctx->op_cb_context = cb_context; + ctx->amounts = amounts; + return true; } bool ui_stx_display_screens(uint8_t screen_count) { + PRINTF("disp screens\n"); return true; } void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_ctx_t* ctx) { + sign_transaction_ctx_t* sign_tx = (sign_transaction_ctx_t*) ctx->sign_tx_context; + + app_set_ui_busy(false); + + if (approved) { + app_set_connected_app_id(ctx->app_token_value); + sign_tx->state = SIGN_TRANSACTION_STATE_APPROVED; + send_response_sign_transaction_session_id(sign_tx->session); + } else { + app_set_current_command(CMD_NONE); + res_deny(); + } + + ui_menu_main(); } #endif \ No newline at end of file From 9bd507736710576132ffb5347ef2f4523cf60a77 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 10 Oct 2024 15:16:12 +0300 Subject: [PATCH 13/56] Application id test --- .vscode/settings.json | 3 ++- src/commands/attestinput/ainpt_ui_nbgl.c | 29 +++++++++++++++++------- src/commands/signtx/stx_ui_nbgl.c | 4 ++-- src/ui/display.h | 9 +++++++- src/ui/ui_application_id.h | 8 +++++++ src/ui/ui_application_id_nbgl.c | 13 +++++++++++ 6 files changed, 54 insertions(+), 12 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 322a8d3..0d7a227 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,8 @@ { "files.associations": { "*.h": "c", - "format": "c" + "format": "c", + "cstdint": "c" }, "editor.formatOnSave": false, "python.terminal.activateEnvironment": false, diff --git a/src/commands/attestinput/ainpt_ui_nbgl.c b/src/commands/attestinput/ainpt_ui_nbgl.c index 30972da..ac86194 100644 --- a/src/commands/attestinput/ainpt_ui_nbgl.c +++ b/src/commands/attestinput/ainpt_ui_nbgl.c @@ -27,17 +27,30 @@ void ui_action_attest_input(bool approved) { int ui_display_access_token(uint32_t app_access_token, attest_input_ctx_t* context) { context->ui.app_token_value = app_access_token; + pairList.nbMaxLinesForValue = 2; + + int n_pairs = 0; + + pairs[n_pairs++] = (nbgl_layoutTagValue_t){ + .item = "Confirm Attest Input", + .value = ""}; + + pairs[n_pairs].item = "test"; + pairs[n_pairs].value = "test2"; + n_pairs++; + + pairs[n_pairs].item = "nest"; + pairs[n_pairs].value = "nest2"; + n_pairs++; + if (app_access_token != 0) { - // TO-DO - //ui_add_screen(ui_application_id_screen(app_access_token, context->ui.app_token), &screen); + pairs[n_pairs++] = ui_application_id_screen(app_access_token, context->ui.app_token); } - nbgl_useCaseChoice(&VALIDATE_ICON, - "Confirm Attest Input", - "", - "Confirm", - "Cancel", - ui_action_attest_input); + pairList.nbPairs = n_pairs; + pairList.pairs = pairs; + + nbgl_useCaseReview(TYPE_OPERATION, &pairList, &C_round_warning_64px, "Confirm Attest Input", NULL, "Confirm Attest Input", ui_action_attest_input); bool approved = io_ui_process(); if (approved) { diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index f2f66c6..f3f83c3 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -262,7 +262,7 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, ui_sign_transaction_operation_show_screen_cb screen_cb, ui_sign_transaction_operation_send_response_cb response_cb, void* cb_context) { - if (MAX_NUMBER_OF_SCREENS - *screen < 6) return false; + /*if (MAX_NUMBER_OF_SCREENS - *screen < 6) return false; memset(ctx, 0, sizeof(sign_transaction_ui_sign_confirm_ctx_t)); @@ -300,7 +300,7 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, ctx->op_screen_cb = screen_cb; ctx->op_response_cb = response_cb; ctx->op_cb_context = cb_context; - ctx->amounts = amounts; + ctx->amounts = amounts;*/ return true; } diff --git a/src/ui/display.h b/src/ui/display.h index 739e3ba..249fcba 100644 --- a/src/ui/display.h +++ b/src/ui/display.h @@ -28,4 +28,11 @@ static bool io_ui_process() { // io_start_processing_timeout(); return flow_response; -} \ No newline at end of file +} + +#if HAVE_NBGL +#define N_UX_PAIRS 13 + +static nbgl_layoutTagValue_t pairs[N_UX_PAIRS]; +static nbgl_layoutTagValueList_t pairList; +#endif \ No newline at end of file diff --git a/src/ui/ui_application_id.h b/src/ui/ui_application_id.h index c966c86..88a0275 100644 --- a/src/ui/ui_application_id.h +++ b/src/ui/ui_application_id.h @@ -10,4 +10,12 @@ const ux_flow_step_t* ui_application_id_screen(uint32_t app_id, char buffer[static APPLICATION_ID_STR_LEN]); +#endif + +#ifdef HAVE_NBGL +#include + +const nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, + char buffer[static APPLICATION_ID_STR_LEN]); + #endif \ No newline at end of file diff --git a/src/ui/ui_application_id_nbgl.c b/src/ui/ui_application_id_nbgl.c index 20494f5..fe155c7 100644 --- a/src/ui/ui_application_id_nbgl.c +++ b/src/ui/ui_application_id_nbgl.c @@ -2,4 +2,17 @@ #include "ui_application_id.h" +const nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, + char buffer[static APPLICATION_ID_STR_LEN]) { + + memset(buffer, 0, APPLICATION_ID_STR_LEN); + snprintf(buffer, APPLICATION_ID_STR_LEN, "0x%08x", app_id); + + nbgl_layoutTagValue_t tag = (nbgl_layoutTagValue_t){ + .item = "Application", + .value = buffer}; + + return tag; +} + #endif \ No newline at end of file From bf83d8ed1172ffb0b9bfdc3e1c240fe436692d98 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 10 Oct 2024 20:34:13 +0300 Subject: [PATCH 14/56] Tx sign flow --- src/commands/attestinput/ainpt_ui_nbgl.c | 37 ++-- src/commands/signtx/operations/stx_op_p2pk.c | 42 ++++ src/commands/signtx/stx_ui.h | 19 +- src/commands/signtx/stx_ui_nbgl.c | 211 +++++++++++++++---- src/context.h | 15 ++ src/ui/display.c | 6 + src/ui/display.h | 5 + src/ui/ui_application_id.h | 5 +- src/ui/ui_application_id_nbgl.c | 15 +- src/ui/ui_bip32_path.h | 8 + src/ui/ui_bip32_path_nbgl.c | 14 ++ 11 files changed, 300 insertions(+), 77 deletions(-) create mode 100644 src/ui/display.c diff --git a/src/commands/attestinput/ainpt_ui_nbgl.c b/src/commands/attestinput/ainpt_ui_nbgl.c index ac86194..2b2cee5 100644 --- a/src/commands/attestinput/ainpt_ui_nbgl.c +++ b/src/commands/attestinput/ainpt_ui_nbgl.c @@ -20,6 +20,9 @@ #include "../../ui/display.h" #include +#define APPLICATION_ID_SUBLEN APPLICATION_ID_STR_LEN + 13 +static char sub_message[APPLICATION_ID_SUBLEN]; + void ui_action_attest_input(bool approved) { set_flow_reseponse(approved); } @@ -27,42 +30,30 @@ void ui_action_attest_input(bool approved) { int ui_display_access_token(uint32_t app_access_token, attest_input_ctx_t* context) { context->ui.app_token_value = app_access_token; - pairList.nbMaxLinesForValue = 2; - - int n_pairs = 0; - - pairs[n_pairs++] = (nbgl_layoutTagValue_t){ - .item = "Confirm Attest Input", - .value = ""}; - - pairs[n_pairs].item = "test"; - pairs[n_pairs].value = "test2"; - n_pairs++; - - pairs[n_pairs].item = "nest"; - pairs[n_pairs].value = "nest2"; - n_pairs++; - if (app_access_token != 0) { - pairs[n_pairs++] = ui_application_id_screen(app_access_token, context->ui.app_token); + ui_application_id_screen(app_access_token, context->ui.app_token); + memset(sub_message, 0, APPLICATION_ID_SUBLEN); + snprintf(sub_message, APPLICATION_ID_SUBLEN, "Application: 0x%08x", app_access_token); } - pairList.nbPairs = n_pairs; - pairList.pairs = pairs; - - nbgl_useCaseReview(TYPE_OPERATION, &pairList, &C_round_warning_64px, "Confirm Attest Input", NULL, "Confirm Attest Input", ui_action_attest_input); + nbgl_useCaseReviewStreamingStart(TYPE_TRANSACTION, + &VALIDATE_ICON, + "Confirm Attest Input", + sub_message, + ui_action_attest_input); bool approved = io_ui_process(); if (approved) { app_set_connected_app_id(context->ui.app_token_value); context->state = ATTEST_INPUT_STATE_APPROVED; send_response_attested_input_session_id(context->session); + } else { app_set_current_command(CMD_NONE); res_deny(); - } - ui_menu_main(); + ui_menu_main(); + } return 0; } diff --git a/src/commands/signtx/operations/stx_op_p2pk.c b/src/commands/signtx/operations/stx_op_p2pk.c index 30b475f..ee7b848 100644 --- a/src/commands/signtx/operations/stx_op_p2pk.c +++ b/src/commands/signtx/operations/stx_op_p2pk.c @@ -10,6 +10,7 @@ #include "../../../ergo/network_id.h" #include "../stx_ui.h" #include "../../../ui/ui_main.h" +#include "../../../ui/display.h" #define COMMAND_ERROR_HANDLER handler_err #include "../../../helpers/cmd_macros.h" @@ -347,6 +348,26 @@ uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2 return SW_BIP32_FORMATTING_FAILED; } ui_add_screen(b32_step, &screen); +#elif HAVE_NBGL + if (app_is_sign_ready()) { + ui_stx_finilize_tx(&ctx->ui_approve.ui_approve, + app_access_token, + is_known_application, + sign_tx_ctx); + return SW_OK; + } + const res = ui_bip32_path_screen( + ctx->bip32.path, + ctx->bip32.len, + "P2PK Signing", + ctx->ui_approve.bip32_path, + MEMBER_SIZE(sign_transaction_operation_p2pk_ui_approve_data_ctx_t, bip32_path)); + if (!res) { + return SW_BIP32_FORMATTING_FAILED; + } + pairs_global[0].item = "P2PK Signing"; + pairs_global[0].value = ctx->ui_approve.bip32_path; + screen++; #endif if (!ui_stx_add_operation_approve_screens(&ctx->ui_approve.ui_approve, @@ -368,6 +389,15 @@ uint16_t ui_stx_operation_p2pk_show_output_confirm_screen( SIGN_TRANSACTION_OPERATION_P2PK_STATE_OUTPUTS_STARTED, SIGN_TRANSACTION_OPERATION_P2PK_STATE_TX_FINISHED); uint8_t screen = 0; + + if (app_is_sign_ready()) { + ui_stx_finilize_2nd_tx(&ctx->transaction.ui.ui, + &ctx->transaction.ui.output, + &ctx->transaction.last_approved_change, + ctx->network_id); + return SW_OK; + } + if (!ui_stx_add_output_screens(&ctx->transaction.ui.ui, &screen, &ctx->transaction.ui.output, @@ -434,6 +464,18 @@ uint16_t ui_stx_operation_p2pk_show_confirm_screen(sign_transaction_operation_p2 CHECK_PROPER_STATE(ctx, SIGN_TRANSACTION_OPERATION_P2PK_STATE_TX_FINISHED); ctx->state = SIGN_TRANSACTION_OPERATION_P2PK_STATE_FINALIZED; uint8_t screen = 0; + + if (app_is_sign_ready()) { + app_set_sign_ready(false); + ui_stx_finilize_3rd_tx(&ctx->ui_confirm, + &ctx->amounts, + 1, + ui_stx_operation_p2pk_show_tx_screen, + ui_stx_operation_p2pk_send_response, + (void *) ctx); + return SW_OK; + } + if (!ui_stx_add_transaction_screens(&ctx->ui_confirm, &screen, &ctx->amounts, diff --git a/src/commands/signtx/stx_ui.h b/src/commands/signtx/stx_ui.h index 6b632a7..3d488de 100644 --- a/src/commands/signtx/stx_ui.h +++ b/src/commands/signtx/stx_ui.h @@ -58,4 +58,21 @@ bool ui_stx_display_screens(uint8_t screen_count); * Approve or reject operation programmatically. * */ -void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_ctx_t* ctx); \ No newline at end of file +void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_ctx_t* ctx); + +#if HAVE_NBGL +void ui_stx_finilize_tx(sign_transaction_ui_aprove_ctx_t* ctx, + uint32_t app_access_token, + bool is_known_application, + sign_transaction_ctx_t* sign_tx); +void ui_stx_finilize_2nd_tx(sign_transaction_ui_output_confirm_ctx_t* ctx, + const sign_transaction_output_info_ctx_t* output, + sign_transaction_bip32_path_t* last_approved_change, + uint8_t network_id); +void ui_stx_finilize_3rd_tx(sign_transaction_ui_sign_confirm_ctx_t* ctx, + const sign_transaction_amounts_ctx_t* amounts, + uint8_t op_screen_count, + ui_sign_transaction_operation_show_screen_cb screen_cb, + ui_sign_transaction_operation_send_response_cb response_cb, + void* cb_context); +#endif \ No newline at end of file diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index f3f83c3..45caf7c 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -70,6 +70,17 @@ static NOINLINE void ui_stx_operation_approve_action(bool approved) { set_flow_reseponse(approved); } +void ui_stx_finilize_tx(sign_transaction_ui_aprove_ctx_t* ctx, + uint32_t app_access_token, + bool is_known_application, + sign_transaction_ctx_t* sign_tx) { + ctx->app_token_value = app_access_token; + ctx->sign_tx_context = sign_tx; + ctx->is_known_application = is_known_application; + ui_stx_operation_approve_reject(true, ctx); + ui_menu_main(); +} + bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, uint8_t* screen, uint32_t app_access_token, @@ -77,20 +88,22 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, sign_transaction_ctx_t* sign_tx) { if (MAX_NUMBER_OF_SCREENS - *screen < 3) return false; + int n_pairs = *screen; + if (!is_known_application) { - // TO-DO - //ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_token), screen); + ui_application_id_screen(app_access_token, ctx->app_token); + pairs_global[n_pairs++] = ui_application_id_screen(app_access_token, ctx->app_token); } + ctx->app_token_value = app_access_token; ctx->sign_tx_context = sign_tx; ctx->is_known_application = is_known_application; - nbgl_useCaseChoice(&VALIDATE_ICON, - "Confirm operation", - "", - "Confirm", - "Cancel", - ui_stx_operation_approve_action); + pairList.nbMaxLinesForValue = 0; + pairList.nbPairs = n_pairs; + pairList.pairs = pairs_global; + + nbgl_useCaseReviewStreamingContinue(&pairList, ui_stx_operation_approve_action); bool approved = io_ui_process(); ui_stx_operation_approve_reject(approved, ctx); @@ -200,6 +213,77 @@ static NOINLINE uint16_t ui_stx_display_output_state(uint8_t screen, return SW_OK; } +// Callback for TX UI rendering +static NOINLINE uint16_t ui_stx_display_tx_state(uint8_t screen, + char* title, + char* text, + void* context) { + sign_transaction_ui_sign_confirm_ctx_t* ctx = (sign_transaction_ui_sign_confirm_ctx_t*) context; + uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, title); + uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, text); + memset(title, 0, title_len); + memset(text, 0, text_len); + + if (screen < ctx->op_screen_count) { // Showing operation screen + return ctx->op_screen_cb(screen, title, title_len, text, text_len, ctx->op_cb_context); + } + screen -= ctx->op_screen_count; + switch (screen) { + case 0: { // TX Value + strncpy(title, "Transaction Amount", title_len); + if (!format_erg_amount(ctx->amounts->value, text, text_len)) { + return SW_BUFFER_ERROR; + } + break; + } + case 1: { // TX Fee + strncpy(title, "Transaction Fee", title_len); + if (!format_erg_amount(ctx->amounts->fee, text, text_len)) { + return SW_BUFFER_ERROR; + } + break; + } + default: { // Tokens + screen -= 2; // Decrease index for info screens + uint8_t token_idx = stx_amounts_non_zero_token_index(ctx->amounts, screen / 2); + if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state + return SW_BAD_TOKEN_INDEX; + } + if (screen % 2 == 0) { // Token ID + snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); + if (!format_hex_id(ctx->amounts->tokens_table.tokens[token_idx], + ERGO_ID_LEN, + text, + text_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + } else { // Token Value + snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); + int64_t value = ctx->amounts->tokens[token_idx]; + if (value < 0) { // output > inputs + STRING_ADD_STATIC_TEXT(text, text_len, "Minting: "); + format_u64(text, text_len, -value); + } else { // inputs > outputs + STRING_ADD_STATIC_TEXT(text, text_len, "Burning: "); + format_u64(text, text_len, value); + } + } + break; + } + } + return SW_OK; +} + +void ui_stx_finilize_2nd_tx(sign_transaction_ui_output_confirm_ctx_t* ctx, + const sign_transaction_output_info_ctx_t* output, + sign_transaction_bip32_path_t* last_approved_change, + uint8_t network_id) { + ctx->network_id = network_id; + ctx->output = output; + ctx->last_approved_change = last_approved_change; + res_ok(); +} + bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_output_info_ctx_t* output, @@ -222,14 +306,20 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, ctx->output = output; ctx->last_approved_change = last_approved_change; - ui_stx_display_output_state(*screen, ctx->title, ctx->text, (void*)ctx); + int n_pairs = *screen; + + for (int i = 0; i < info_screen_count; i++) { + pairs_global[n_pairs].item = pair_mem_title[i]; + pairs_global[n_pairs].value = pair_mem_text[i]; + ui_stx_display_output_state(i, pair_mem_title[i], pair_mem_text[i], (void*) ctx); + n_pairs++; + } + + pairList.nbMaxLinesForValue = 0; + pairList.nbPairs = n_pairs; + pairList.pairs = pairs_global; - nbgl_useCaseChoice(&WARNING_ICON, - ctx->title, - ctx->text, - "Confirm", - "Cancel", - ui_stx_operation_approve_action); + nbgl_useCaseReviewStreamingContinue(&pairList, ui_stx_operation_approve_action); bool approved = io_ui_process(); @@ -248,13 +338,29 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, } else { app_set_current_command(CMD_NONE); res_deny(); - } - ui_menu_main(); + ui_menu_main(); + } return true; } +void ui_stx_finilize_3rd_tx(sign_transaction_ui_sign_confirm_ctx_t* ctx, + const sign_transaction_amounts_ctx_t* amounts, + uint8_t op_screen_count, + ui_sign_transaction_operation_show_screen_cb screen_cb, + ui_sign_transaction_operation_send_response_cb response_cb, + void* cb_context) { + ctx->op_screen_count = op_screen_count; + ctx->op_screen_cb = screen_cb; + ctx->op_response_cb = response_cb; + ctx->op_cb_context = cb_context; + ctx->amounts = amounts; + ctx->op_response_cb(ctx->op_cb_context); + + ui_menu_main(); +} + bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_amounts_ctx_t* amounts, @@ -262,51 +368,64 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, ui_sign_transaction_operation_show_screen_cb screen_cb, ui_sign_transaction_operation_send_response_cb response_cb, void* cb_context) { - /*if (MAX_NUMBER_OF_SCREENS - *screen < 6) return false; + if (MAX_NUMBER_OF_SCREENS - *screen < 6) return false; memset(ctx, 0, sizeof(sign_transaction_ui_sign_confirm_ctx_t)); uint8_t tokens_count = stx_amounts_non_zero_tokens_count(amounts); + ctx->op_screen_count = op_screen_count; + ctx->op_screen_cb = screen_cb; + ctx->op_response_cb = response_cb; + ctx->op_cb_context = cb_context; + ctx->amounts = amounts; + int n_pairs = *screen; - nbgl_useCaseChoice(&WARNING_ICON, - ctx->title, - ctx->text, - "Confirm", - "Cancel", - ui_stx_operation_approve_action); + /*pairs_global[n_pairs++] = (nbgl_layoutTagValue_t) { + .item = ctx->title, + .value = ctx->text + };*/ - bool approved = io_ui_process(); + for (int i = 0; i < op_screen_count + 2 + (2 * tokens_count); i++) { + pairs_global[n_pairs].item = pair_mem_title[i]; + pairs_global[n_pairs].value = pair_mem_text[i]; + ui_stx_display_tx_state(i, pair_mem_title[i], pair_mem_text[i], (void*) ctx); + n_pairs++; + } - ui_add_screen(&ux_stx_display_sign_confirm_step, screen); + pairList.nbMaxLinesForValue = 0; + pairList.nbPairs = n_pairs; + pairList.pairs = pairs_global; - if (!ui_add_dynamic_flow_screens(screen, - op_screen_count + 2 + (2 * tokens_count), - "Approve signing",//ctx->title, - ctx->text, - &ui_stx_display_tx_state, - (void*) ctx)) - return false; + nbgl_useCaseReviewStreamingContinue(&pairList, ui_stx_operation_approve_action); + + bool approved = io_ui_process(); + if (!approved) { + res_deny(); + app_set_current_command(CMD_NONE); + ui_menu_main(); + } if (MAX_NUMBER_OF_SCREENS - *screen < 2) return false; - ui_approve_reject_screens(ui_stx_operation_execute_action, - ctx, - ui_next_sreen_ptr(screen), - ui_next_sreen_ptr(screen)); + nbgl_useCaseReviewStreamingFinish("Approve Signing", ui_stx_operation_approve_action); + approved = io_ui_process(); + + if (approved) { + app_set_sign_ready(true); + ctx->op_response_cb(ctx->op_cb_context); + } else { + res_deny(); + } + + app_set_current_command(CMD_NONE); + ui_menu_main(); - ctx->op_screen_count = op_screen_count; - ctx->op_screen_cb = screen_cb; - ctx->op_response_cb = response_cb; - ctx->op_cb_context = cb_context; - ctx->amounts = amounts;*/ - return true; } bool ui_stx_display_screens(uint8_t screen_count) { - PRINTF("disp screens\n"); return true; } @@ -322,9 +441,9 @@ void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_c } else { app_set_current_command(CMD_NONE); res_deny(); - } - ui_menu_main(); + ui_menu_main(); + } } #endif \ No newline at end of file diff --git a/src/context.h b/src/context.h index 88cda12..ff5b9db 100644 --- a/src/context.h +++ b/src/context.h @@ -14,6 +14,7 @@ typedef struct { uint8_t session_key[SESSION_KEY_LEN]; command_e current_command; /// current command bool is_ui_busy; + bool is_sign_ready; union { attest_input_ctx_t attest_input; sign_transaction_ctx_t sign_tx; @@ -27,6 +28,13 @@ typedef struct { */ extern app_ctx_t G_app_context; +/** + * Check is sign final step + */ +static inline bool app_is_sign_ready() { + return G_app_context.is_sign_ready; +} + /** * Check is ui busy */ @@ -41,6 +49,13 @@ static inline void app_set_ui_busy(bool is_busy) { G_app_context.is_ui_busy = is_busy; } +/** + * Set sign final step + */ +static inline void app_set_sign_ready(bool ready) { + G_app_context.is_sign_ready = ready; +} + /** * Get connected application id. */ diff --git a/src/ui/display.c b/src/ui/display.c new file mode 100644 index 0000000..5ddf889 --- /dev/null +++ b/src/ui/display.c @@ -0,0 +1,6 @@ +#include "display.h" + +#if HAVE_NBGL + +nbgl_layoutTagValue_t pairs_global[N_UX_PAIRS]; +#endif \ No newline at end of file diff --git a/src/ui/display.h b/src/ui/display.h index 249fcba..3f100e3 100644 --- a/src/ui/display.h +++ b/src/ui/display.h @@ -35,4 +35,9 @@ static bool io_ui_process() { static nbgl_layoutTagValue_t pairs[N_UX_PAIRS]; static nbgl_layoutTagValueList_t pairList; + +extern nbgl_layoutTagValue_t pairs_global[N_UX_PAIRS]; + +static char pair_mem_title[N_UX_PAIRS][20]; +static char pair_mem_text[N_UX_PAIRS][70]; #endif \ No newline at end of file diff --git a/src/ui/ui_application_id.h b/src/ui/ui_application_id.h index 88a0275..dd226e6 100644 --- a/src/ui/ui_application_id.h +++ b/src/ui/ui_application_id.h @@ -16,6 +16,9 @@ const ux_flow_step_t* ui_application_id_screen(uint32_t app_id, #include const nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, - char buffer[static APPLICATION_ID_STR_LEN]); + char buffer[static APPLICATION_ID_STR_LEN]); + +const void ui_application_id_screen_buf(uint32_t app_id, + char buffer[static APPLICATION_ID_STR_LEN]); #endif \ No newline at end of file diff --git a/src/ui/ui_application_id_nbgl.c b/src/ui/ui_application_id_nbgl.c index fe155c7..ec9f0d9 100644 --- a/src/ui/ui_application_id_nbgl.c +++ b/src/ui/ui_application_id_nbgl.c @@ -3,16 +3,19 @@ #include "ui_application_id.h" const nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, - char buffer[static APPLICATION_ID_STR_LEN]) { - + char buffer[static APPLICATION_ID_STR_LEN]) { memset(buffer, 0, APPLICATION_ID_STR_LEN); snprintf(buffer, APPLICATION_ID_STR_LEN, "0x%08x", app_id); - nbgl_layoutTagValue_t tag = (nbgl_layoutTagValue_t){ - .item = "Application", - .value = buffer}; - + nbgl_layoutTagValue_t tag = (nbgl_layoutTagValue_t){.item = "Application", .value = buffer}; + return tag; } +const void ui_application_id_screen_buf(uint32_t app_id, + char buffer[static APPLICATION_ID_STR_LEN]) { + memset(buffer, 0, APPLICATION_ID_STR_LEN); + snprintf(buffer, APPLICATION_ID_STR_LEN, "Application: 0x%08x", app_id); +} + #endif \ No newline at end of file diff --git a/src/ui/ui_bip32_path.h b/src/ui/ui_bip32_path.h index 2ad0ebc..f11ea8b 100644 --- a/src/ui/ui_bip32_path.h +++ b/src/ui/ui_bip32_path.h @@ -15,4 +15,12 @@ const ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, ui_bip32_approve_callback cb, void* cb_context); +#endif + +#ifdef HAVE_NBGL +const bool ui_bip32_path_screen(uint32_t* path, + uint8_t path_len, + const char* title, + char* buffer, + uint8_t buffer_len); #endif \ No newline at end of file diff --git a/src/ui/ui_bip32_path_nbgl.c b/src/ui/ui_bip32_path_nbgl.c index 6369cdc..03e6115 100644 --- a/src/ui/ui_bip32_path_nbgl.c +++ b/src/ui/ui_bip32_path_nbgl.c @@ -1,5 +1,19 @@ #ifdef HAVE_NBGL #include "ui_bip32_path.h" +#include "../common/bip32_ext.h" + +const bool ui_bip32_path_screen(uint32_t* path, + uint8_t path_len, + const char* title, + char* buffer, + uint8_t buffer_len) { + memset(buffer, 0, buffer_len); + if (!bip32_path_format(path, path_len, buffer, buffer_len)) { + return false; + } + + return true; +} #endif \ No newline at end of file From 9802ad5e67201dda4ae4759ff72c416e5bf368c6 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 10 Oct 2024 21:41:57 +0300 Subject: [PATCH 15/56] Fixed NanoSP --- src/commands/signtx/stx_ui_bagl.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/commands/signtx/stx_ui_bagl.c b/src/commands/signtx/stx_ui_bagl.c index a3f0905..ca12def 100644 --- a/src/commands/signtx/stx_ui_bagl.c +++ b/src/commands/signtx/stx_ui_bagl.c @@ -406,4 +406,22 @@ bool ui_stx_display_screens(uint8_t screen_count) { return ui_display_screens(&screen_count); } +void ui_stx_finilize_tx(sign_transaction_ui_aprove_ctx_t* ctx, + uint32_t app_access_token, + bool is_known_application, + sign_transaction_ctx_t* sign_tx) { +} +void ui_stx_finilize_2nd_tx(sign_transaction_ui_output_confirm_ctx_t* ctx, + const sign_transaction_output_info_ctx_t* output, + sign_transaction_bip32_path_t* last_approved_change, + uint8_t network_id) { +} +void ui_stx_finilize_3rd_tx(sign_transaction_ui_sign_confirm_ctx_t* ctx, + const sign_transaction_amounts_ctx_t* amounts, + uint8_t op_screen_count, + ui_sign_transaction_operation_show_screen_cb screen_cb, + ui_sign_transaction_operation_send_response_cb response_cb, + void* cb_context) { +} + #endif \ No newline at end of file From 35d7f6e9653589523149e9d55bfd19b143146882 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 10 Oct 2024 22:18:48 +0300 Subject: [PATCH 16/56] Fix tests --- .github/workflows/ci-workflow.yml | 4 ++-- tests/transaction-tests.js | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index dfd9d00..052e8bf 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -132,8 +132,8 @@ jobs: include: - model: nanox - model: nanosp - - model: stax - - model: flex + #- model: stax + #- model: flex needs: job_build_nano_debug runs-on: ubuntu-latest diff --git a/tests/transaction-tests.js b/tests/transaction-tests.js index 88f3cd2..b5b7589 100644 --- a/tests/transaction-tests.js +++ b/tests/transaction-tests.js @@ -76,12 +76,12 @@ describe("Transaction Tests", function () { expect(attestedBox.frames).to.have.length(1); const frame = attestedBox.frames[0]; expect(frame.boxId).to.exist; - expect(frame.framesCount).to.be.equal(1); - expect(frame.frameIndex).to.be.equal(0); + expect(frame.count).to.be.equal(1); + expect(frame.index).to.be.equal(0); expect(frame.amount).to.be.equal('1000000000'); expect(frame.tokens).to.be.empty; expect(frame.attestation).to.exist; - expect(frame.buffer).to.exist; + expect(frame.bytes).to.exist; }) .run(({test, unsignedBox}) => test.device.attestInput(unsignedBox)); From 9c6f953711ec3c85d6953a8d89c0eee28ea26985 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 15:01:09 +0300 Subject: [PATCH 17/56] UI fixes, token/amount display --- src/commands/attestinput/ainpt_ui_nbgl.c | 12 ++-- src/commands/deriveaddress/da_ui_nbgl.c | 2 +- src/commands/extpubkey/epk_ui_nbgl.c | 2 +- src/commands/signtx/operations/stx_op_p2pk.c | 55 ++++++++---------- src/commands/signtx/stx_ui.h | 19 +------ src/commands/signtx/stx_ui_nbgl.c | 59 ++++++-------------- src/context.h | 15 ++--- src/ui/display.c | 35 +++++++++++- src/ui/display.h | 30 ++-------- src/ui/ui_application_id.h | 7 +-- src/ui/ui_application_id_nbgl.c | 7 +-- src/ui/ui_bip32_path.h | 24 ++++---- src/ui/ui_bip32_path_nbgl.c | 10 ++-- 13 files changed, 115 insertions(+), 162 deletions(-) diff --git a/src/commands/attestinput/ainpt_ui_nbgl.c b/src/commands/attestinput/ainpt_ui_nbgl.c index 2b2cee5..fe141de 100644 --- a/src/commands/attestinput/ainpt_ui_nbgl.c +++ b/src/commands/attestinput/ainpt_ui_nbgl.c @@ -24,7 +24,7 @@ static char sub_message[APPLICATION_ID_SUBLEN]; void ui_action_attest_input(bool approved) { - set_flow_reseponse(approved); + set_flow_response(approved); } int ui_display_access_token(uint32_t app_access_token, attest_input_ctx_t* context) { @@ -36,11 +36,11 @@ int ui_display_access_token(uint32_t app_access_token, attest_input_ctx_t* conte snprintf(sub_message, APPLICATION_ID_SUBLEN, "Application: 0x%08x", app_access_token); } - nbgl_useCaseReviewStreamingStart(TYPE_TRANSACTION, - &VALIDATE_ICON, - "Confirm Attest Input", - sub_message, - ui_action_attest_input); + nbgl_useCaseConfirm("Confirm Attest Input", + sub_message, + "Confirm", + "Reject", + ui_action_attest_input); bool approved = io_ui_process(); if (approved) { diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index 87a078a..734843e 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -23,7 +23,7 @@ #include "../../ui/display.h" void ui_display_address_confirm(bool approved) { - set_flow_reseponse(approved); + set_flow_response(approved); } int ui_display_address(derive_address_ctx_t* ctx, diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c index 93bb1b8..eca79f1 100644 --- a/src/commands/extpubkey/epk_ui_nbgl.c +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -21,7 +21,7 @@ #include void ui_display_account_confirm(bool approved) { - set_flow_reseponse(approved); + set_flow_response(approved); } int ui_display_account(extended_public_key_ctx_t* ctx, diff --git a/src/commands/signtx/operations/stx_op_p2pk.c b/src/commands/signtx/operations/stx_op_p2pk.c index ee7b848..44ff1fc 100644 --- a/src/commands/signtx/operations/stx_op_p2pk.c +++ b/src/commands/signtx/operations/stx_op_p2pk.c @@ -323,16 +323,22 @@ bool stx_operation_p2pk_should_show_output_confirm_screen( // =========================== // UI - +#ifdef HAVE_BAGL static NOINLINE void ui_stx_operation_p2pk_approve_action(void *context) { sign_transaction_ui_aprove_ctx_t *ctx = (sign_transaction_ui_aprove_ctx_t *) context; ui_stx_operation_approve_reject(true, ctx); } +#endif + +#ifdef HAVE_NBGL +void p2pk_review(bool approved) { + set_flow_response(approved); +} +#endif uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2pk_ctx_t *ctx, uint32_t app_access_token, bool is_known_application, - void *sign_tx_ctx) { uint8_t screen = 0; #ifdef HAVE_BAGL @@ -349,14 +355,7 @@ uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2 } ui_add_screen(b32_step, &screen); #elif HAVE_NBGL - if (app_is_sign_ready()) { - ui_stx_finilize_tx(&ctx->ui_approve.ui_approve, - app_access_token, - is_known_application, - sign_tx_ctx); - return SW_OK; - } - const res = ui_bip32_path_screen( + bool res = ui_bip32_path_screen( ctx->bip32.path, ctx->bip32.len, "P2PK Signing", @@ -365,9 +364,20 @@ uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2 if (!res) { return SW_BIP32_FORMATTING_FAILED; } - pairs_global[0].item = "P2PK Signing"; - pairs_global[0].value = ctx->ui_approve.bip32_path; - screen++; + // pairs_global[0].item = "P2PK Signing"; + // pairs_global[0].value = ctx->ui_approve.bip32_path; + // screen++; + nbgl_useCaseReviewStreamingStart(TYPE_TRANSACTION, + &VALIDATE_ICON, + "P2PK Signing", + ctx->ui_approve.bip32_path, + p2pk_review); + bool approved = io_ui_process(); + if (!approved) { + res_deny(); + ui_menu_main(); + return SW_BIP32_FORMATTING_FAILED; + } #endif if (!ui_stx_add_operation_approve_screens(&ctx->ui_approve.ui_approve, @@ -390,14 +400,6 @@ uint16_t ui_stx_operation_p2pk_show_output_confirm_screen( SIGN_TRANSACTION_OPERATION_P2PK_STATE_TX_FINISHED); uint8_t screen = 0; - if (app_is_sign_ready()) { - ui_stx_finilize_2nd_tx(&ctx->transaction.ui.ui, - &ctx->transaction.ui.output, - &ctx->transaction.last_approved_change, - ctx->network_id); - return SW_OK; - } - if (!ui_stx_add_output_screens(&ctx->transaction.ui.ui, &screen, &ctx->transaction.ui.output, @@ -465,17 +467,6 @@ uint16_t ui_stx_operation_p2pk_show_confirm_screen(sign_transaction_operation_p2 ctx->state = SIGN_TRANSACTION_OPERATION_P2PK_STATE_FINALIZED; uint8_t screen = 0; - if (app_is_sign_ready()) { - app_set_sign_ready(false); - ui_stx_finilize_3rd_tx(&ctx->ui_confirm, - &ctx->amounts, - 1, - ui_stx_operation_p2pk_show_tx_screen, - ui_stx_operation_p2pk_send_response, - (void *) ctx); - return SW_OK; - } - if (!ui_stx_add_transaction_screens(&ctx->ui_confirm, &screen, &ctx->amounts, diff --git a/src/commands/signtx/stx_ui.h b/src/commands/signtx/stx_ui.h index 3d488de..6b632a7 100644 --- a/src/commands/signtx/stx_ui.h +++ b/src/commands/signtx/stx_ui.h @@ -58,21 +58,4 @@ bool ui_stx_display_screens(uint8_t screen_count); * Approve or reject operation programmatically. * */ -void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_ctx_t* ctx); - -#if HAVE_NBGL -void ui_stx_finilize_tx(sign_transaction_ui_aprove_ctx_t* ctx, - uint32_t app_access_token, - bool is_known_application, - sign_transaction_ctx_t* sign_tx); -void ui_stx_finilize_2nd_tx(sign_transaction_ui_output_confirm_ctx_t* ctx, - const sign_transaction_output_info_ctx_t* output, - sign_transaction_bip32_path_t* last_approved_change, - uint8_t network_id); -void ui_stx_finilize_3rd_tx(sign_transaction_ui_sign_confirm_ctx_t* ctx, - const sign_transaction_amounts_ctx_t* amounts, - uint8_t op_screen_count, - ui_sign_transaction_operation_show_screen_cb screen_cb, - ui_sign_transaction_operation_send_response_cb response_cb, - void* cb_context); -#endif \ No newline at end of file +void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_ctx_t* ctx); \ No newline at end of file diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index 45caf7c..a133220 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -67,18 +67,7 @@ static inline bool format_erg_amount(uint64_t amount, char* out, size_t out_len) } static NOINLINE void ui_stx_operation_approve_action(bool approved) { - set_flow_reseponse(approved); -} - -void ui_stx_finilize_tx(sign_transaction_ui_aprove_ctx_t* ctx, - uint32_t app_access_token, - bool is_known_application, - sign_transaction_ctx_t* sign_tx) { - ctx->app_token_value = app_access_token; - ctx->sign_tx_context = sign_tx; - ctx->is_known_application = is_known_application; - ui_stx_operation_approve_reject(true, ctx); - ui_menu_main(); + set_flow_response(approved); } bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, @@ -103,8 +92,11 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, pairList.nbPairs = n_pairs; pairList.pairs = pairs_global; - nbgl_useCaseReviewStreamingContinue(&pairList, ui_stx_operation_approve_action); - bool approved = io_ui_process(); + bool approved = true; + if (n_pairs > 0) { + nbgl_useCaseReviewStreamingContinue(&pairList, ui_stx_operation_approve_action); + approved = io_ui_process(); + } ui_stx_operation_approve_reject(approved, ctx); @@ -274,16 +266,6 @@ static NOINLINE uint16_t ui_stx_display_tx_state(uint8_t screen, return SW_OK; } -void ui_stx_finilize_2nd_tx(sign_transaction_ui_output_confirm_ctx_t* ctx, - const sign_transaction_output_info_ctx_t* output, - sign_transaction_bip32_path_t* last_approved_change, - uint8_t network_id) { - ctx->network_id = network_id; - ctx->output = output; - ctx->last_approved_change = last_approved_change; - res_ok(); -} - bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_output_info_ctx_t* output, @@ -312,6 +294,12 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, pairs_global[n_pairs].item = pair_mem_title[i]; pairs_global[n_pairs].value = pair_mem_text[i]; ui_stx_display_output_state(i, pair_mem_title[i], pair_mem_text[i], (void*) ctx); + // empty row (split screens for tokens) + if (n_pairs % 2 == 0) { + n_pairs++; + pairs_global[n_pairs].item = ""; + pairs_global[n_pairs].value = ""; + } n_pairs++; } @@ -345,22 +333,6 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, return true; } -void ui_stx_finilize_3rd_tx(sign_transaction_ui_sign_confirm_ctx_t* ctx, - const sign_transaction_amounts_ctx_t* amounts, - uint8_t op_screen_count, - ui_sign_transaction_operation_show_screen_cb screen_cb, - ui_sign_transaction_operation_send_response_cb response_cb, - void* cb_context) { - ctx->op_screen_count = op_screen_count; - ctx->op_screen_cb = screen_cb; - ctx->op_response_cb = response_cb; - ctx->op_cb_context = cb_context; - ctx->amounts = amounts; - ctx->op_response_cb(ctx->op_cb_context); - - ui_menu_main(); -} - bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_amounts_ctx_t* amounts, @@ -391,6 +363,12 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, pairs_global[n_pairs].item = pair_mem_title[i]; pairs_global[n_pairs].value = pair_mem_text[i]; ui_stx_display_tx_state(i, pair_mem_title[i], pair_mem_text[i], (void*) ctx); + // empty row (split screens for tokens) + if (n_pairs % 2 == 0) { + n_pairs++; + pairs_global[n_pairs].item = ""; + pairs_global[n_pairs].value = ""; + } n_pairs++; } @@ -413,7 +391,6 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, approved = io_ui_process(); if (approved) { - app_set_sign_ready(true); ctx->op_response_cb(ctx->op_cb_context); } else { res_deny(); diff --git a/src/context.h b/src/context.h index ff5b9db..42582cf 100644 --- a/src/context.h +++ b/src/context.h @@ -14,7 +14,7 @@ typedef struct { uint8_t session_key[SESSION_KEY_LEN]; command_e current_command; /// current command bool is_ui_busy; - bool is_sign_ready; + bool is_ui_nbgl_busy; union { attest_input_ctx_t attest_input; sign_transaction_ctx_t sign_tx; @@ -28,13 +28,6 @@ typedef struct { */ extern app_ctx_t G_app_context; -/** - * Check is sign final step - */ -static inline bool app_is_sign_ready() { - return G_app_context.is_sign_ready; -} - /** * Check is ui busy */ @@ -50,10 +43,10 @@ static inline void app_set_ui_busy(bool is_busy) { } /** - * Set sign final step + * Set UI (nbgl) busy */ -static inline void app_set_sign_ready(bool ready) { - G_app_context.is_sign_ready = ready; +static inline void app_set_nbgl_busy(bool is_busy) { + G_app_context.is_ui_nbgl_busy = is_busy; } /** diff --git a/src/ui/display.c b/src/ui/display.c index 5ddf889..e1c02f9 100644 --- a/src/ui/display.c +++ b/src/ui/display.c @@ -1,6 +1,37 @@ #include "display.h" +#include "../context.h" -#if HAVE_NBGL +#ifdef HAVE_NBGL nbgl_layoutTagValue_t pairs_global[N_UX_PAIRS]; -#endif \ No newline at end of file +#endif + +bool flow_response = false; + +void set_flow_response(bool response) { + flow_response = response; + app_set_nbgl_busy(false); +} + +void io_common_process() { + io_seproxyhal_general_status(); + do { + io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); + io_seproxyhal_handle_event(); + io_seproxyhal_general_status(); + } while (io_seproxyhal_spi_is_status_sent() && G_app_context.is_ui_nbgl_busy); +} + +bool io_ui_process() { + // We are not waiting for the client's input, nor we are doing computations on the device + // io_clear_processing_timeout(); + + app_set_nbgl_busy(true); + + io_common_process(); + + // We're back at work, we want to show the "Processing..." screen when appropriate + // io_start_processing_timeout(); + + return flow_response; +} \ No newline at end of file diff --git a/src/ui/display.h b/src/ui/display.h index 3f100e3..d8f8b13 100644 --- a/src/ui/display.h +++ b/src/ui/display.h @@ -4,33 +4,13 @@ #include #include "../context.h" -static bool flow_response = false; +extern bool flow_response; -static void set_flow_reseponse(bool response) { - flow_response = response; - app_set_ui_busy(false); -} +void set_flow_response(bool response); +void io_common_process(); +bool io_ui_process(); -static bool io_ui_process() { - // We are not waiting for the client's input, nor we are doing computations on the device - // io_clear_processing_timeout(); - - app_set_ui_busy(true); - - io_seproxyhal_general_status(); - do { - io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); - io_seproxyhal_handle_event(); - io_seproxyhal_general_status(); - } while (io_seproxyhal_spi_is_status_sent() && G_app_context.is_ui_busy); - - // We're back at work, we want to show the "Processing..." screen when appropriate - // io_start_processing_timeout(); - - return flow_response; -} - -#if HAVE_NBGL +#ifdef HAVE_NBGL #define N_UX_PAIRS 13 static nbgl_layoutTagValue_t pairs[N_UX_PAIRS]; diff --git a/src/ui/ui_application_id.h b/src/ui/ui_application_id.h index dd226e6..ae9b64a 100644 --- a/src/ui/ui_application_id.h +++ b/src/ui/ui_application_id.h @@ -15,10 +15,9 @@ const ux_flow_step_t* ui_application_id_screen(uint32_t app_id, #ifdef HAVE_NBGL #include -const nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, - char buffer[static APPLICATION_ID_STR_LEN]); +nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, + char buffer[static APPLICATION_ID_STR_LEN]); -const void ui_application_id_screen_buf(uint32_t app_id, - char buffer[static APPLICATION_ID_STR_LEN]); +void ui_application_id_screen_buf(uint32_t app_id, char buffer[static APPLICATION_ID_STR_LEN]); #endif \ No newline at end of file diff --git a/src/ui/ui_application_id_nbgl.c b/src/ui/ui_application_id_nbgl.c index ec9f0d9..3b1c281 100644 --- a/src/ui/ui_application_id_nbgl.c +++ b/src/ui/ui_application_id_nbgl.c @@ -2,8 +2,8 @@ #include "ui_application_id.h" -const nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, - char buffer[static APPLICATION_ID_STR_LEN]) { +nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, + char buffer[static APPLICATION_ID_STR_LEN]) { memset(buffer, 0, APPLICATION_ID_STR_LEN); snprintf(buffer, APPLICATION_ID_STR_LEN, "0x%08x", app_id); @@ -12,8 +12,7 @@ const nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, return tag; } -const void ui_application_id_screen_buf(uint32_t app_id, - char buffer[static APPLICATION_ID_STR_LEN]) { +void ui_application_id_screen_buf(uint32_t app_id, char buffer[static APPLICATION_ID_STR_LEN]) { memset(buffer, 0, APPLICATION_ID_STR_LEN); snprintf(buffer, APPLICATION_ID_STR_LEN, "Application: 0x%08x", app_id); } diff --git a/src/ui/ui_bip32_path.h b/src/ui/ui_bip32_path.h index f11ea8b..649f144 100644 --- a/src/ui/ui_bip32_path.h +++ b/src/ui/ui_bip32_path.h @@ -7,20 +7,20 @@ typedef void (*ui_bip32_approve_callback)(void*); -const ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, - uint8_t path_len, - const char* title, - char* buffer, - uint8_t buffer_len, - ui_bip32_approve_callback cb, - void* cb_context); +ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, + uint8_t path_len, + const char* title, + char* buffer, + uint8_t buffer_len, + ui_bip32_approve_callback cb, + void* cb_context); #endif #ifdef HAVE_NBGL -const bool ui_bip32_path_screen(uint32_t* path, - uint8_t path_len, - const char* title, - char* buffer, - uint8_t buffer_len); +bool ui_bip32_path_screen(uint32_t* path, + uint8_t path_len, + const char* title, + char* buffer, + uint8_t buffer_len); #endif \ No newline at end of file diff --git a/src/ui/ui_bip32_path_nbgl.c b/src/ui/ui_bip32_path_nbgl.c index 03e6115..1b4b1c7 100644 --- a/src/ui/ui_bip32_path_nbgl.c +++ b/src/ui/ui_bip32_path_nbgl.c @@ -3,11 +3,11 @@ #include "ui_bip32_path.h" #include "../common/bip32_ext.h" -const bool ui_bip32_path_screen(uint32_t* path, - uint8_t path_len, - const char* title, - char* buffer, - uint8_t buffer_len) { +bool ui_bip32_path_screen(uint32_t* path, + uint8_t path_len, + const char* title, + char* buffer, + uint8_t buffer_len) { memset(buffer, 0, buffer_len); if (!bip32_path_format(path, path_len, buffer, buffer_len)) { return false; From 1b0ff7b816e90c70f9f575067d1d58bf11523f9e Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 15:03:24 +0300 Subject: [PATCH 18/56] Revert --- src/ui/ui_bip32_path.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/ui_bip32_path.h b/src/ui/ui_bip32_path.h index 649f144..4e27840 100644 --- a/src/ui/ui_bip32_path.h +++ b/src/ui/ui_bip32_path.h @@ -7,7 +7,7 @@ typedef void (*ui_bip32_approve_callback)(void*); -ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, +const ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, uint8_t path_len, const char* title, char* buffer, From f864aeb568b0a1c8da3f8749d8779d2cafccadef Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 15:04:08 +0300 Subject: [PATCH 19/56] Lint --- src/ui/ui_bip32_path.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ui/ui_bip32_path.h b/src/ui/ui_bip32_path.h index 4e27840..cf33a96 100644 --- a/src/ui/ui_bip32_path.h +++ b/src/ui/ui_bip32_path.h @@ -8,12 +8,12 @@ typedef void (*ui_bip32_approve_callback)(void*); const ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, - uint8_t path_len, - const char* title, - char* buffer, - uint8_t buffer_len, - ui_bip32_approve_callback cb, - void* cb_context); + uint8_t path_len, + const char* title, + char* buffer, + uint8_t buffer_len, + ui_bip32_approve_callback cb, + void* cb_context); #endif From e71fc09854241b59db478016e468b329283c6b09 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 15:12:32 +0300 Subject: [PATCH 20/56] Removed unused code, workflow improvements --- .github/workflows/ci-workflow.yml | 9 +++++++-- src/commands/signtx/stx_ui_bagl.c | 18 ------------------ 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index 052e8bf..e941c01 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -104,6 +104,11 @@ jobs: job_scan_build: name: Clang Static Analyzer runs-on: ubuntu-latest + strategy: + matrix: + include: + - SDK: "$NANOSP_SDK" + - SDK: "$STAX_SDK" container: image: ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest @@ -114,7 +119,7 @@ jobs: - name: Build with Clang Static Analyzer run: | - make clean + make clean BOLOS_SDK=${{ matrix.SDK }} scan-build --use-cc=clang -analyze-headers -enable-checker security -enable-checker unix -enable-checker valist -o scan-build --status-bugs make default - name: Upload scan result @@ -167,7 +172,7 @@ jobs: npm --model=${{matrix.model}} --port=5000 run test - name: Upload Speculos log - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: speculos-${{matrix.model}}-log path: speculos.log diff --git a/src/commands/signtx/stx_ui_bagl.c b/src/commands/signtx/stx_ui_bagl.c index ca12def..a3f0905 100644 --- a/src/commands/signtx/stx_ui_bagl.c +++ b/src/commands/signtx/stx_ui_bagl.c @@ -406,22 +406,4 @@ bool ui_stx_display_screens(uint8_t screen_count) { return ui_display_screens(&screen_count); } -void ui_stx_finilize_tx(sign_transaction_ui_aprove_ctx_t* ctx, - uint32_t app_access_token, - bool is_known_application, - sign_transaction_ctx_t* sign_tx) { -} -void ui_stx_finilize_2nd_tx(sign_transaction_ui_output_confirm_ctx_t* ctx, - const sign_transaction_output_info_ctx_t* output, - sign_transaction_bip32_path_t* last_approved_change, - uint8_t network_id) { -} -void ui_stx_finilize_3rd_tx(sign_transaction_ui_sign_confirm_ctx_t* ctx, - const sign_transaction_amounts_ctx_t* amounts, - uint8_t op_screen_count, - ui_sign_transaction_operation_show_screen_cb screen_cb, - ui_sign_transaction_operation_send_response_cb response_cb, - void* cb_context) { -} - #endif \ No newline at end of file From 2559664753049895c0e29796bc62d66b12a50d3f Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 15:16:40 +0300 Subject: [PATCH 21/56] Fix attempt (enable clang analyzer for nanosp/stax) --- .github/workflows/ci-workflow.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index e941c01..72b4d6b 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -119,7 +119,8 @@ jobs: - name: Build with Clang Static Analyzer run: | - make clean BOLOS_SDK=${{ matrix.SDK }} + export BOLOS_SDK=${{ matrix.SDK }} + make clean scan-build --use-cc=clang -analyze-headers -enable-checker security -enable-checker unix -enable-checker valist -o scan-build --status-bugs make default - name: Upload scan result From a0339ae5361854983fd4ffe23bed3aea3d2843a8 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 15:54:26 +0300 Subject: [PATCH 22/56] Fix warnings --- src/commands/attestinput/ainpt_ui_nbgl.c | 12 +++++++----- src/commands/extpubkey/epk_ui_nbgl.c | 2 +- src/commands/signtx/operations/stx_op_p2pk.c | 8 +++++++- src/commands/signtx/stx_ui.h | 2 ++ src/commands/signtx/stx_ui_nbgl.c | 9 ++++----- src/ui/ui_bip32_path.h | 6 +----- src/ui/ui_bip32_path_nbgl.c | 6 +----- 7 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/commands/attestinput/ainpt_ui_nbgl.c b/src/commands/attestinput/ainpt_ui_nbgl.c index fe141de..342921c 100644 --- a/src/commands/attestinput/ainpt_ui_nbgl.c +++ b/src/commands/attestinput/ainpt_ui_nbgl.c @@ -9,6 +9,7 @@ #include #include #include "epk_response.h" +#include "ainpt_response.h" #include "../../context.h" #include "../../common/bip32_ext.h" #include "../../common/macros_ext.h" @@ -36,11 +37,12 @@ int ui_display_access_token(uint32_t app_access_token, attest_input_ctx_t* conte snprintf(sub_message, APPLICATION_ID_SUBLEN, "Application: 0x%08x", app_access_token); } - nbgl_useCaseConfirm("Confirm Attest Input", - sub_message, - "Confirm", - "Reject", - ui_action_attest_input); + nbgl_useCaseChoice(&VALIDATE_ICON, + "Confirm Attest Input", + sub_message, + "Confirm", + "Reject", + ui_action_attest_input); bool approved = io_ui_process(); if (approved) { diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c index eca79f1..3b24507 100644 --- a/src/commands/extpubkey/epk_ui_nbgl.c +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -41,7 +41,7 @@ int ui_display_account(extended_public_key_ctx_t* ctx, uint path_size = MEMBER_SIZE(extended_public_key_ctx_t, bip32_path); memset(ctx->bip32_path, 0, path_size); if (!bip32_path_format(bip32_path, bip32_path_len, ctx->bip32_path, path_size)) { - return NULL; + return res_error(SW_BIP32_BAD_PATH); } if (app_access_token != 0) { diff --git a/src/commands/signtx/operations/stx_op_p2pk.c b/src/commands/signtx/operations/stx_op_p2pk.c index 44ff1fc..1e8d350 100644 --- a/src/commands/signtx/operations/stx_op_p2pk.c +++ b/src/commands/signtx/operations/stx_op_p2pk.c @@ -11,6 +11,7 @@ #include "../stx_ui.h" #include "../../../ui/ui_main.h" #include "../../../ui/display.h" +#include "../../../ui/ui_menu.h" #define COMMAND_ERROR_HANDLER handler_err #include "../../../helpers/cmd_macros.h" @@ -358,7 +359,6 @@ uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2 bool res = ui_bip32_path_screen( ctx->bip32.path, ctx->bip32.len, - "P2PK Signing", ctx->ui_approve.bip32_path, MEMBER_SIZE(sign_transaction_operation_p2pk_ui_approve_data_ctx_t, bip32_path)); if (!res) { @@ -387,9 +387,11 @@ uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2 sign_tx_ctx)) { return SW_SCREENS_BUFFER_OVERFLOW; } +#ifdef HAVE_BAGL if (!ui_stx_display_screens(screen)) { return SW_SCREENS_BUFFER_OVERFLOW; } +#endif return SW_OK; } @@ -407,9 +409,11 @@ uint16_t ui_stx_operation_p2pk_show_output_confirm_screen( ctx->network_id)) { return SW_SCREENS_BUFFER_OVERFLOW; } +#ifdef HAVE_BAGL if (!ui_stx_display_screens(screen)) { return SW_SCREENS_BUFFER_OVERFLOW; } +#endif return SW_OK; } @@ -476,8 +480,10 @@ uint16_t ui_stx_operation_p2pk_show_confirm_screen(sign_transaction_operation_p2 (void *) ctx)) { return SW_SCREENS_BUFFER_OVERFLOW; } +#ifdef HAVE_BAGL if (!ui_stx_display_screens(screen)) { return SW_SCREENS_BUFFER_OVERFLOW; } +#endif return SW_OK; } diff --git a/src/commands/signtx/stx_ui.h b/src/commands/signtx/stx_ui.h index 6b632a7..4f60e22 100644 --- a/src/commands/signtx/stx_ui.h +++ b/src/commands/signtx/stx_ui.h @@ -46,6 +46,7 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, ui_sign_transaction_operation_send_response_cb response_cb, void* cb_context); +#ifdef HAVE_BAGL /** * Finalizes screen flow and pushes it to the screen. * @@ -53,6 +54,7 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, * */ bool ui_stx_display_screens(uint8_t screen_count); +#endif /** * Approve or reject operation programmatically. diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index a133220..26fb25c 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -8,7 +8,10 @@ #include #include #include -#include "epk_response.h" +#include +#include + +#include "stx_response.h" #include "../../context.h" #include "../../common/bip32_ext.h" #include "../../common/macros_ext.h" @@ -402,10 +405,6 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, return true; } -bool ui_stx_display_screens(uint8_t screen_count) { - return true; -} - void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_ctx_t* ctx) { sign_transaction_ctx_t* sign_tx = (sign_transaction_ctx_t*) ctx->sign_tx_context; diff --git a/src/ui/ui_bip32_path.h b/src/ui/ui_bip32_path.h index cf33a96..00d08ba 100644 --- a/src/ui/ui_bip32_path.h +++ b/src/ui/ui_bip32_path.h @@ -18,9 +18,5 @@ const ux_flow_step_t* ui_bip32_path_screen(uint32_t* path, #endif #ifdef HAVE_NBGL -bool ui_bip32_path_screen(uint32_t* path, - uint8_t path_len, - const char* title, - char* buffer, - uint8_t buffer_len); +bool ui_bip32_path_screen(uint32_t* path, uint8_t path_len, char* buffer, uint8_t buffer_len); #endif \ No newline at end of file diff --git a/src/ui/ui_bip32_path_nbgl.c b/src/ui/ui_bip32_path_nbgl.c index 1b4b1c7..1925dc2 100644 --- a/src/ui/ui_bip32_path_nbgl.c +++ b/src/ui/ui_bip32_path_nbgl.c @@ -3,11 +3,7 @@ #include "ui_bip32_path.h" #include "../common/bip32_ext.h" -bool ui_bip32_path_screen(uint32_t* path, - uint8_t path_len, - const char* title, - char* buffer, - uint8_t buffer_len) { +bool ui_bip32_path_screen(uint32_t* path, uint8_t path_len, char* buffer, uint8_t buffer_len) { memset(buffer, 0, buffer_len); if (!bip32_path_format(path, path_len, buffer, buffer_len)) { return false; From ccb3ccb76a0f56f1f9173778f896ee22f02777ca Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 16:20:18 +0300 Subject: [PATCH 23/56] Cleanup includes, minor refactoring --- .vscode/c_cpp_properties.json | 4 ++-- src/commands/attestinput/ainpt_ui_nbgl.c | 14 ++++---------- src/commands/deriveaddress/da_ui_nbgl.c | 4 +--- src/commands/extpubkey/epk_ui_nbgl.c | 11 +++++------ src/commands/signtx/stx_ui_nbgl.c | 14 +++++++------- ...i_approve_reject_bagl.c => ui_approve_reject.c} | 0 src/ui/ui_approve_reject.h | 3 +-- .../{ui_dynamic_flow_bagl.c => ui_dynamic_flow.c} | 0 src/ui/ui_dynamic_flow.h | 4 +--- src/ui/ui_menu_nbgl.c | 1 + 10 files changed, 22 insertions(+), 33 deletions(-) rename src/ui/{ui_approve_reject_bagl.c => ui_approve_reject.c} (100%) rename src/ui/{ui_dynamic_flow_bagl.c => ui_dynamic_flow.c} (100%) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 847fd47..5a740d1 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -8,7 +8,7 @@ "name": "Nano S+", "includePath": [ "${workspaceFolder}/src", - "${workspaceFolder}/build/nanos/gen_src", + "${workspaceFolder}/build/stax/gen_src", "${env:ARM_GCC}/arm-none-eabi/include/*", "${env:ARM_GCC}/lib/gcc/arm-none-eabi/13.2.1/include/*", "${env:BOLOS_SDK}/include/*", @@ -52,7 +52,7 @@ "PRINTF=screen_printf", "_DEFAULT_SOURCE" ], - "compilerPath": "${env:ARM_GCC}/bin/arm-none-eabi-gcc", + "compilerPath": "/usr/bin/gcc", "cStandard": "c11", "cppStandard": "c++17", "intelliSenseMode": "gcc-arm", diff --git a/src/commands/attestinput/ainpt_ui_nbgl.c b/src/commands/attestinput/ainpt_ui_nbgl.c index 342921c..66a0cde 100644 --- a/src/commands/attestinput/ainpt_ui_nbgl.c +++ b/src/commands/attestinput/ainpt_ui_nbgl.c @@ -1,25 +1,19 @@ #ifdef HAVE_NBGL -#include "ainpt_ui.h" -#include "../../helpers/response.h" -#include "../../sw.h" -#include -#include #include +#include #include #include -#include "epk_response.h" + +#include "ainpt_ui.h" #include "ainpt_response.h" #include "../../context.h" -#include "../../common/bip32_ext.h" #include "../../common/macros_ext.h" -#include "../../ui/ui_bip32_path.h" +#include "../../helpers/response.h" #include "../../ui/ui_application_id.h" -#include "../../ui/ui_approve_reject.h" #include "../../ui/ui_menu.h" #include "../../ui/ui_main.h" #include "../../ui/display.h" -#include #define APPLICATION_ID_SUBLEN APPLICATION_ID_STR_LEN + 13 static char sub_message[APPLICATION_ID_SUBLEN]; diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index 734843e..dcddab9 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -1,12 +1,10 @@ #ifdef HAVE_NBGL -#include "da_ui.h" #include -#include #include #include -#include #include + #include "da_ui.h" #include "da_response.h" #include "da_context.h" diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c index 3b24507..5c1a57e 100644 --- a/src/commands/extpubkey/epk_ui_nbgl.c +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -1,24 +1,23 @@ #ifdef HAVE_NBGL -#include "epk_ui.h" -#include "../../helpers/response.h" -#include "../../sw.h" -#include -#include #include +#include #include #include + +#include "epk_ui.h" #include "epk_response.h" #include "../../context.h" +#include "../../sw.h" #include "../../common/bip32_ext.h" #include "../../common/macros_ext.h" +#include "../../helpers/response.h" #include "../../ui/ui_bip32_path.h" #include "../../ui/ui_application_id.h" #include "../../ui/ui_approve_reject.h" #include "../../ui/ui_menu.h" #include "../../ui/ui_main.h" #include "../../ui/display.h" -#include void ui_display_account_confirm(bool approved) { set_flow_response(approved); diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index 26fb25c..27e5d31 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -1,27 +1,27 @@ #ifdef HAVE_NBGL -#include "stx_ui.h" -#include "../../helpers/response.h" -#include "../../sw.h" -#include -#include #include +#include #include #include #include #include +#include "stx_ui.h" #include "stx_response.h" + #include "../../context.h" #include "../../common/bip32_ext.h" #include "../../common/macros_ext.h" +#include "../../common/safeint.h" +#include "../../helpers/response.h" +#include "../../sw.h" +#include "../../ergo/address.h" #include "../../ui/ui_bip32_path.h" #include "../../ui/ui_application_id.h" -#include "../../ui/ui_approve_reject.h" #include "../../ui/ui_menu.h" #include "../../ui/ui_main.h" #include "../../ui/display.h" -#include #ifdef TARGET_NANOS #define ERGO_ID_UI_CHARACTERS_HALF 7 diff --git a/src/ui/ui_approve_reject_bagl.c b/src/ui/ui_approve_reject.c similarity index 100% rename from src/ui/ui_approve_reject_bagl.c rename to src/ui/ui_approve_reject.c diff --git a/src/ui/ui_approve_reject.h b/src/ui/ui_approve_reject.h index e30c881..350d2c3 100644 --- a/src/ui/ui_approve_reject.h +++ b/src/ui/ui_approve_reject.h @@ -1,9 +1,8 @@ #pragma once - +#ifdef HAVE_BAGL #include #include -#ifdef HAVE_BAGL typedef void (*ui_approve_reject_callback)(bool, void*); void ui_approve_reject_screens(ui_approve_reject_callback cb, diff --git a/src/ui/ui_dynamic_flow_bagl.c b/src/ui/ui_dynamic_flow.c similarity index 100% rename from src/ui/ui_dynamic_flow_bagl.c rename to src/ui/ui_dynamic_flow.c diff --git a/src/ui/ui_dynamic_flow.h b/src/ui/ui_dynamic_flow.h index 7d494c3..a4aeb0d 100644 --- a/src/ui/ui_dynamic_flow.h +++ b/src/ui/ui_dynamic_flow.h @@ -1,11 +1,9 @@ #pragma once - +#ifdef HAVE_BAGL #include #include #include -#ifdef HAVE_BAGL - typedef uint16_t (*ui_dynamic_flow_show_screen_cb)(uint8_t, char *, char *, void *); // Global context pointer will be set to the dynamic flow context. Don't change it. diff --git a/src/ui/ui_menu_nbgl.c b/src/ui/ui_menu_nbgl.c index 09ebc92..26d10af 100644 --- a/src/ui/ui_menu_nbgl.c +++ b/src/ui/ui_menu_nbgl.c @@ -3,6 +3,7 @@ #include "ui_menu.h" #include #include +#include #define APPTAGLINE "Ergo app for ledger" #define APPCOPYRIGHT "Ergo App (c) 2024" From 92c5dc911c5e8ce33a9df9bb9070da4b024b86c3 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 17:05:06 +0300 Subject: [PATCH 24/56] Application display where required --- src/commands/deriveaddress/da_ui_nbgl.c | 13 +++++++++---- src/commands/extpubkey/epk_ui_nbgl.c | 14 +++++++++++--- src/commands/signtx/stx_ui_nbgl.c | 1 - 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index dcddab9..b9e9968 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -53,15 +53,20 @@ int ui_display_address(derive_address_ctx_t* ctx, } } + int n_pairs = 0; + if (app_access_token != 0) { - // TO-DO - // ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_id), &screen); + pairs_global[n_pairs++] = ui_application_id_screen(app_access_token, ctx->app_id); } + pairList.nbMaxLinesForValue = 0; + pairList.nbPairs = n_pairs; + pairList.pairs = pairs_global; + if (send) { // Confirm Send Address nbgl_useCaseAddressReview(ctx->address, - NULL, + n_pairs == 0 ? NULL : &pairList, &WHEEL_ICON, "Confirm Send Address", "", @@ -69,7 +74,7 @@ int ui_display_address(derive_address_ctx_t* ctx, } else { // Confirm Address nbgl_useCaseAddressReview(ctx->address, - NULL, + n_pairs == 0 ? NULL : &pairList, &INFO_I_ICON, "Confirm Address", "", diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c index 5c1a57e..6a7ca2e 100644 --- a/src/commands/extpubkey/epk_ui_nbgl.c +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -23,6 +23,9 @@ void ui_display_account_confirm(bool approved) { set_flow_response(approved); } +#define PK_APPID_SIZE 255 +char pk_appid[PK_APPID_SIZE]; + int ui_display_account(extended_public_key_ctx_t* ctx, uint32_t app_access_token, uint32_t* bip32_path, @@ -43,9 +46,14 @@ int ui_display_account(extended_public_key_ctx_t* ctx, return res_error(SW_BIP32_BAD_PATH); } + memset(pk_appid, 0, PK_APPID_SIZE); + strncpy(pk_appid, ctx->bip32_path, MAX_BIP32_PATH); if (app_access_token != 0) { - // TO-DO - // ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_token), &screen); + pk_appid[MAX_BIP32_PATH] = '\n'; + snprintf(*(&pk_appid) + MAX_BIP32_PATH + 1, + APPLICATION_ID_STR_LEN + 13, + "Application: 0x%08x", + app_access_token); } ctx->app_token_value = app_access_token; @@ -54,7 +62,7 @@ int ui_display_account(extended_public_key_ctx_t* ctx, nbgl_useCaseChoice(&WARNING_ICON, "Ext PubKey Export", - ctx->bip32_path, + pk_appid, "Confirm", "Cancel", ui_display_account_confirm); diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index 27e5d31..517fdfd 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -83,7 +83,6 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, int n_pairs = *screen; if (!is_known_application) { - ui_application_id_screen(app_access_token, ctx->app_token); pairs_global[n_pairs++] = ui_application_id_screen(app_access_token, ctx->app_token); } From ee9d671b9f2d8b261a3dc7a0b67ea0d19621750a Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 17:08:37 +0300 Subject: [PATCH 25/56] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1632b15..9b59ddc 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ APPNAME = "Ergo" # Application version APPVERSION_M = 0 APPVERSION_N = 0 -APPVERSION_P = 5 +APPVERSION_P = 6 APPVERSION = "$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)" # Application source files From 7cad84415beb7f0a33a77e97b51c60114ce6ab65 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 13 Oct 2024 17:18:15 +0300 Subject: [PATCH 26/56] Cut buffer to required memory size --- src/commands/extpubkey/epk_ui_nbgl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c index 6a7ca2e..09d29d2 100644 --- a/src/commands/extpubkey/epk_ui_nbgl.c +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -23,7 +23,7 @@ void ui_display_account_confirm(bool approved) { set_flow_response(approved); } -#define PK_APPID_SIZE 255 +#define PK_APPID_SIZE MAX_BIP32_PATH + APPLICATION_ID_STR_LEN + 13 + 1 char pk_appid[PK_APPID_SIZE]; int ui_display_account(extended_public_key_ctx_t* ctx, From 5030da649b06739daf950c329015ee240f78ada0 Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 14 Oct 2024 20:04:25 +0300 Subject: [PATCH 27/56] Revert unit-tests formatting --- unit-tests/utils/base58.c | 26 ++--- unit-tests/utils/bip32.c | 9 +- unit-tests/utils/bip32.h | 6 +- unit-tests/utils/blake2-impl.h | 166 +++++++++++++++++-------------- unit-tests/utils/blake2b-ref.h | 104 ++++++++++--------- unit-tests/utils/buffer.c | 42 +++++--- unit-tests/utils/buffer.h | 6 +- unit-tests/utils/cx.c | 5 +- unit-tests/utils/cx.h | 2 +- unit-tests/utils/macro_helpers.h | 8 +- unit-tests/utils/read.c | 18 ++-- unit-tests/utils/varint.c | 9 +- unit-tests/utils/write.c | 18 ++-- 13 files changed, 233 insertions(+), 186 deletions(-) diff --git a/unit-tests/utils/base58.c b/unit-tests/utils/base58.c index 05197a3..b526269 100644 --- a/unit-tests/utils/base58.c +++ b/unit-tests/utils/base58.c @@ -43,8 +43,9 @@ char const BASE58_ALPHABET[] = { 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' // }; -int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) { - uint8_t tmp[MAX_DEC_INPUT_SIZE] = {0}; +int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) +{ + uint8_t tmp[MAX_DEC_INPUT_SIZE] = {0}; uint8_t buffer[MAX_DEC_INPUT_SIZE] = {0}; uint8_t j; uint8_t start_at; @@ -72,15 +73,15 @@ int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) { ++zero_count; } - j = in_len; + j = in_len; start_at = zero_count; while (start_at < in_len) { uint16_t remainder = 0; for (uint8_t div_loop = start_at; div_loop < in_len; div_loop++) { uint16_t digit256 = (uint16_t) (tmp[div_loop] & 0xFF); - uint16_t tmp_div = remainder * 58 + digit256; - tmp[div_loop] = (uint8_t) (tmp_div / 256); - remainder = tmp_div % 256; + uint16_t tmp_div = remainder * 58 + digit256; + tmp[div_loop] = (uint8_t) (tmp_div / 256); + remainder = tmp_div % 256; } if (tmp[start_at] == 0) { @@ -105,12 +106,13 @@ int base58_decode(const char *in, size_t in_len, uint8_t *out, size_t out_len) { return length; } -int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) { +int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) +{ uint8_t buffer[MAX_ENC_INPUT_SIZE * 138 / 100 + 1] = {0}; - size_t i, j; - size_t stop_at; - size_t zero_count = 0; - size_t output_size; + size_t i, j; + size_t stop_at; + size_t zero_count = 0; + size_t output_size; if (in_len > MAX_ENC_INPUT_SIZE) { return -1; @@ -121,7 +123,7 @@ int base58_encode(const uint8_t *in, size_t in_len, char *out, size_t out_len) { } output_size = (in_len - zero_count) * 138 / 100 + 1; - stop_at = output_size - 1; + stop_at = output_size - 1; for (size_t start_at = zero_count; start_at < in_len; start_at++) { int carry = in[start_at]; for (j = output_size - 1; (int) j >= 0; j--) { diff --git a/unit-tests/utils/bip32.c b/unit-tests/utils/bip32.c index 5b305f0..2f7ec96 100644 --- a/unit-tests/utils/bip32.c +++ b/unit-tests/utils/bip32.c @@ -23,7 +23,8 @@ #include "bip32.h" #include "read.h" -bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len) { +bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out_len) +{ if (out_len == 0 || out_len > MAX_BIP32_PATH) { return false; } @@ -41,10 +42,8 @@ bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out return true; } -bool bip32_path_format(const uint32_t *bip32_path, - size_t bip32_path_len, - char *out, - size_t out_len) { +bool bip32_path_format(const uint32_t *bip32_path, size_t bip32_path_len, char *out, size_t out_len) +{ if (bip32_path_len == 0 || bip32_path_len > MAX_BIP32_PATH) { return false; } diff --git a/unit-tests/utils/bip32.h b/unit-tests/utils/bip32.h index 0eb85a5..734c766 100644 --- a/unit-tests/utils/bip32.h +++ b/unit-tests/utils/bip32.h @@ -42,6 +42,6 @@ bool bip32_path_read(const uint8_t *in, size_t in_len, uint32_t *out, size_t out * */ bool bip32_path_format(const uint32_t *bip32_path, - size_t bip32_path_len, - char *out, - size_t out_len); \ No newline at end of file + size_t bip32_path_len, + char *out, + size_t out_len); \ No newline at end of file diff --git a/unit-tests/utils/blake2-impl.h b/unit-tests/utils/blake2-impl.h index e281796..c1df82e 100644 --- a/unit-tests/utils/blake2-impl.h +++ b/unit-tests/utils/blake2-impl.h @@ -19,120 +19,142 @@ #include #if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L) -#if defined(_MSC_VER) -#define BLAKE2_INLINE __inline -#elif defined(__GNUC__) -#define BLAKE2_INLINE __inline__ + #if defined(_MSC_VER) + #define BLAKE2_INLINE __inline + #elif defined(__GNUC__) + #define BLAKE2_INLINE __inline__ + #else + #define BLAKE2_INLINE + #endif #else -#define BLAKE2_INLINE -#endif -#else -#define BLAKE2_INLINE inline + #define BLAKE2_INLINE inline #endif -static BLAKE2_INLINE uint32_t load32(const void *src) { +static BLAKE2_INLINE uint32_t load32( const void *src ) +{ #if defined(NATIVE_LITTLE_ENDIAN) - uint32_t w; - memcpy(&w, src, sizeof w); - return w; + uint32_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = (const uint8_t *) src; - return ((uint32_t) (p[0]) << 0) | ((uint32_t) (p[1]) << 8) | ((uint32_t) (p[2]) << 16) | - ((uint32_t) (p[3]) << 24); + const uint8_t *p = ( const uint8_t * )src; + return (( uint32_t )( p[0] ) << 0) | + (( uint32_t )( p[1] ) << 8) | + (( uint32_t )( p[2] ) << 16) | + (( uint32_t )( p[3] ) << 24) ; #endif } -static BLAKE2_INLINE uint64_t load64(const void *src) { +static BLAKE2_INLINE uint64_t load64( const void *src ) +{ #if defined(NATIVE_LITTLE_ENDIAN) - uint64_t w; - memcpy(&w, src, sizeof w); - return w; + uint64_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = (const uint8_t *) src; - return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16) | - ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40) | - ((uint64_t) (p[6]) << 48) | ((uint64_t) (p[7]) << 56); + const uint8_t *p = ( const uint8_t * )src; + return (( uint64_t )( p[0] ) << 0) | + (( uint64_t )( p[1] ) << 8) | + (( uint64_t )( p[2] ) << 16) | + (( uint64_t )( p[3] ) << 24) | + (( uint64_t )( p[4] ) << 32) | + (( uint64_t )( p[5] ) << 40) | + (( uint64_t )( p[6] ) << 48) | + (( uint64_t )( p[7] ) << 56) ; #endif } -static BLAKE2_INLINE uint16_t load16(const void *src) { +static BLAKE2_INLINE uint16_t load16( const void *src ) +{ #if defined(NATIVE_LITTLE_ENDIAN) - uint16_t w; - memcpy(&w, src, sizeof w); - return w; + uint16_t w; + memcpy(&w, src, sizeof w); + return w; #else - const uint8_t *p = (const uint8_t *) src; - return (uint16_t) (((uint32_t) (p[0]) << 0) | ((uint32_t) (p[1]) << 8)); + const uint8_t *p = ( const uint8_t * )src; + return ( uint16_t )((( uint32_t )( p[0] ) << 0) | + (( uint32_t )( p[1] ) << 8)); #endif } -static BLAKE2_INLINE void store16(void *dst, uint16_t w) { +static BLAKE2_INLINE void store16( void *dst, uint16_t w ) +{ #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = (uint8_t *) dst; - *p++ = (uint8_t) w; - w >>= 8; - *p++ = (uint8_t) w; + uint8_t *p = ( uint8_t * )dst; + *p++ = ( uint8_t )w; w >>= 8; + *p++ = ( uint8_t )w; #endif } -static BLAKE2_INLINE void store32(void *dst, uint32_t w) { +static BLAKE2_INLINE void store32( void *dst, uint32_t w ) +{ #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = (uint8_t *) dst; - p[0] = (uint8_t) (w >> 0); - p[1] = (uint8_t) (w >> 8); - p[2] = (uint8_t) (w >> 16); - p[3] = (uint8_t) (w >> 24); + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); #endif } -static BLAKE2_INLINE void store64(void *dst, uint64_t w) { +static BLAKE2_INLINE void store64( void *dst, uint64_t w ) +{ #if defined(NATIVE_LITTLE_ENDIAN) - memcpy(dst, &w, sizeof w); + memcpy(dst, &w, sizeof w); #else - uint8_t *p = (uint8_t *) dst; - p[0] = (uint8_t) (w >> 0); - p[1] = (uint8_t) (w >> 8); - p[2] = (uint8_t) (w >> 16); - p[3] = (uint8_t) (w >> 24); - p[4] = (uint8_t) (w >> 32); - p[5] = (uint8_t) (w >> 40); - p[6] = (uint8_t) (w >> 48); - p[7] = (uint8_t) (w >> 56); + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); + p[6] = (uint8_t)(w >> 48); + p[7] = (uint8_t)(w >> 56); #endif } -static BLAKE2_INLINE uint64_t load48(const void *src) { - const uint8_t *p = (const uint8_t *) src; - return ((uint64_t) (p[0]) << 0) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16) | - ((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40); +static BLAKE2_INLINE uint64_t load48( const void *src ) +{ + const uint8_t *p = ( const uint8_t * )src; + return (( uint64_t )( p[0] ) << 0) | + (( uint64_t )( p[1] ) << 8) | + (( uint64_t )( p[2] ) << 16) | + (( uint64_t )( p[3] ) << 24) | + (( uint64_t )( p[4] ) << 32) | + (( uint64_t )( p[5] ) << 40) ; } -static BLAKE2_INLINE void store48(void *dst, uint64_t w) { - uint8_t *p = (uint8_t *) dst; - p[0] = (uint8_t) (w >> 0); - p[1] = (uint8_t) (w >> 8); - p[2] = (uint8_t) (w >> 16); - p[3] = (uint8_t) (w >> 24); - p[4] = (uint8_t) (w >> 32); - p[5] = (uint8_t) (w >> 40); +static BLAKE2_INLINE void store48( void *dst, uint64_t w ) +{ + uint8_t *p = ( uint8_t * )dst; + p[0] = (uint8_t)(w >> 0); + p[1] = (uint8_t)(w >> 8); + p[2] = (uint8_t)(w >> 16); + p[3] = (uint8_t)(w >> 24); + p[4] = (uint8_t)(w >> 32); + p[5] = (uint8_t)(w >> 40); } -static BLAKE2_INLINE uint32_t rotr32(const uint32_t w, const unsigned c) { - return (w >> c) | (w << (32 - c)); +static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 32 - c ) ); } -static BLAKE2_INLINE uint64_t rotr64(const uint64_t w, const unsigned c) { - return (w >> c) | (w << (64 - c)); +static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 64 - c ) ); } /* prevents compiler optimizing out memset() */ -static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) { - static void *(*const volatile memset_v)(void *, int, size_t) = &memset; - memset_v(v, 0, n); +static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n) +{ + static void *(*const volatile memset_v)(void *, int, size_t) = &memset; + memset_v(v, 0, n); } #endif diff --git a/unit-tests/utils/blake2b-ref.h b/unit-tests/utils/blake2b-ref.h index 4b65282..5eb9fe3 100644 --- a/unit-tests/utils/blake2b-ref.h +++ b/unit-tests/utils/blake2b-ref.h @@ -28,66 +28,62 @@ extern "C" { #endif -enum blake2b_constant { + enum blake2b_constant + { BLAKE2B_BLOCKBYTES = 128, - BLAKE2B_OUTBYTES = 64, - BLAKE2B_KEYBYTES = 64, - BLAKE2B_SALTBYTES = 16, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, BLAKE2B_PERSONALBYTES = 16 -}; + }; -typedef struct blake2b_state__ { + typedef struct blake2b_state__ + { uint64_t h[8]; uint64_t t[2]; uint64_t f[2]; - uint8_t buf[BLAKE2B_BLOCKBYTES]; - size_t buflen; - size_t outlen; - uint8_t last_node; -} blake2b_state; - -BLAKE2_PACKED(struct blake2b_param__ { - uint8_t digest_length; /* 1 */ - uint8_t key_length; /* 2 */ - uint8_t fanout; /* 3 */ - uint8_t depth; /* 4 */ - uint32_t leaf_length; /* 8 */ - uint32_t node_offset; /* 12 */ - uint32_t xof_length; /* 16 */ - uint8_t node_depth; /* 17 */ - uint8_t inner_length; /* 18 */ - uint8_t reserved[14]; /* 32 */ - uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ - uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ -}); - -typedef struct blake2b_param__ blake2b_param; - -/* Padded structs result in a compile-time error */ -enum { BLAKE2_DUMMY_2 = 1 / (int) (sizeof(blake2b_param) == BLAKE2B_OUTBYTES) }; - -/* Streaming API */ -int blake2b_ref_init(blake2b_state *S, size_t outlen); -int blake2b_ref_init_key(blake2b_state *S, size_t outlen, const void *key, size_t keylen); -int blake2b_ref_init_param(blake2b_state *S, const blake2b_param *P); -int blake2b_ref_update(blake2b_state *S, const void *in, size_t inlen); -int blake2b_ref_final(blake2b_state *S, void *out, size_t outlen); - -/* Simple API */ -int blake2b_ref(void *out, - size_t outlen, - const void *in, - size_t inlen, - const void *key, - size_t keylen); - -/* This is simply an alias for blake2b */ -int blake2_ref(void *out, - size_t outlen, - const void *in, - size_t inlen, - const void *key, - size_t keylen); + uint8_t buf[BLAKE2B_BLOCKBYTES]; + size_t buflen; + size_t outlen; + uint8_t last_node; + } blake2b_state; + + + BLAKE2_PACKED(struct blake2b_param__ + { + uint8_t digest_length; /* 1 */ + uint8_t key_length; /* 2 */ + uint8_t fanout; /* 3 */ + uint8_t depth; /* 4 */ + uint32_t leaf_length; /* 8 */ + uint32_t node_offset; /* 12 */ + uint32_t xof_length; /* 16 */ + uint8_t node_depth; /* 17 */ + uint8_t inner_length; /* 18 */ + uint8_t reserved[14]; /* 32 */ + uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ + uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ + }); + + typedef struct blake2b_param__ blake2b_param; + + /* Padded structs result in a compile-time error */ + enum { + BLAKE2_DUMMY_2 = 1/(int)(sizeof(blake2b_param) == BLAKE2B_OUTBYTES) + }; + + /* Streaming API */ + int blake2b_ref_init( blake2b_state *S, size_t outlen ); + int blake2b_ref_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen ); + int blake2b_ref_init_param( blake2b_state *S, const blake2b_param *P ); + int blake2b_ref_update( blake2b_state *S, const void *in, size_t inlen ); + int blake2b_ref_final( blake2b_state *S, void *out, size_t outlen ); + + /* Simple API */ + int blake2b_ref( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); + + /* This is simply an alias for blake2b */ + int blake2_ref( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ); #if defined(__cplusplus) } diff --git a/unit-tests/utils/buffer.c b/unit-tests/utils/buffer.c index 9d97c07..96071a2 100644 --- a/unit-tests/utils/buffer.c +++ b/unit-tests/utils/buffer.c @@ -24,11 +24,13 @@ #include "varint.h" #include "bip32.h" -bool buffer_can_read(const buffer_t *buffer, size_t n) { +bool buffer_can_read(const buffer_t *buffer, size_t n) +{ return buffer->size - buffer->offset >= n; } -bool buffer_seek_set(buffer_t *buffer, size_t offset) { +bool buffer_seek_set(buffer_t *buffer, size_t offset) +{ if (offset > buffer->size) { return false; } @@ -38,7 +40,8 @@ bool buffer_seek_set(buffer_t *buffer, size_t offset) { return true; } -bool buffer_seek_cur(buffer_t *buffer, size_t offset) { +bool buffer_seek_cur(buffer_t *buffer, size_t offset) +{ if (buffer->offset + offset < buffer->offset || // overflow buffer->offset + offset > buffer->size) { // exceed buffer size return false; @@ -49,7 +52,8 @@ bool buffer_seek_cur(buffer_t *buffer, size_t offset) { return true; } -bool buffer_seek_end(buffer_t *buffer, size_t offset) { +bool buffer_seek_end(buffer_t *buffer, size_t offset) +{ if (offset > buffer->size) { return false; } @@ -59,7 +63,8 @@ bool buffer_seek_end(buffer_t *buffer, size_t offset) { return true; } -bool buffer_read_u8(buffer_t *buffer, uint8_t *value) { +bool buffer_read_u8(buffer_t *buffer, uint8_t *value) +{ if (!buffer_can_read(buffer, 1)) { *value = 0; @@ -72,7 +77,8 @@ bool buffer_read_u8(buffer_t *buffer, uint8_t *value) { return true; } -bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) { +bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) +{ if (!buffer_can_read(buffer, 2)) { *value = 0; @@ -87,7 +93,8 @@ bool buffer_read_u16(buffer_t *buffer, uint16_t *value, endianness_t endianness) return true; } -bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) { +bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) +{ if (!buffer_can_read(buffer, 4)) { *value = 0; @@ -102,7 +109,8 @@ bool buffer_read_u32(buffer_t *buffer, uint32_t *value, endianness_t endianness) return true; } -bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) { +bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) +{ if (!buffer_can_read(buffer, 8)) { *value = 0; @@ -117,7 +125,8 @@ bool buffer_read_u64(buffer_t *buffer, uint64_t *value, endianness_t endianness) return true; } -bool buffer_read_varint(buffer_t *buffer, uint64_t *value) { +bool buffer_read_varint(buffer_t *buffer, uint64_t *value) +{ int length = varint_read(buffer->ptr + buffer->offset, buffer->size - buffer->offset, value); if (length < 0) { @@ -129,11 +138,10 @@ bool buffer_read_varint(buffer_t *buffer, uint64_t *value) { return buffer_seek_cur(buffer, (size_t) length); } -bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) { - if (!bip32_path_read(buffer->ptr + buffer->offset, - buffer->size - buffer->offset, - out, - out_len)) { +bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) +{ + if (!bip32_path_read( + buffer->ptr + buffer->offset, buffer->size - buffer->offset, out, out_len)) { return false; } @@ -142,7 +150,8 @@ bool buffer_read_bip32_path(buffer_t *buffer, uint32_t *out, size_t out_len) { return true; } -bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) { +bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) +{ if (buffer->size - buffer->offset > out_len) { return false; } @@ -152,7 +161,8 @@ bool buffer_copy(const buffer_t *buffer, uint8_t *out, size_t out_len) { return true; } -bool buffer_move(buffer_t *buffer, uint8_t *out, size_t out_len) { +bool buffer_move(buffer_t *buffer, uint8_t *out, size_t out_len) +{ if (!buffer_copy(buffer, out, out_len)) { return false; } diff --git a/unit-tests/utils/buffer.h b/unit-tests/utils/buffer.h index ae3e829..6b31ab0 100644 --- a/unit-tests/utils/buffer.h +++ b/unit-tests/utils/buffer.h @@ -16,9 +16,9 @@ typedef enum { * Struct for buffer with size and offset. */ typedef struct { - const uint8_t *ptr; /// Pointer to byte buffer - size_t size; /// Size of byte buffer - size_t offset; /// Offset in byte buffer + const uint8_t *ptr; /// Pointer to byte buffer + size_t size; /// Size of byte buffer + size_t offset; /// Offset in byte buffer } buffer_t; /** diff --git a/unit-tests/utils/cx.c b/unit-tests/utils/cx.c index f3ad975..929fbb9 100644 --- a/unit-tests/utils/cx.c +++ b/unit-tests/utils/cx.c @@ -61,9 +61,10 @@ cx_err_t cx_hash_no_throw(cx_hash_t *hash, } } -cx_err_t cx_blake2b_256_hash(const uint8_t *data, +cx_err_t cx_blake2b_256_hash(const uint8_t* data, size_t len, - uint8_t out[static CX_BLAKE2B_256_SIZE]) { + uint8_t out[static CX_BLAKE2B_256_SIZE]) +{ return blake2b_ref(out, CX_BLAKE2B_256_SIZE, data, len, NULL, 0); } diff --git a/unit-tests/utils/cx.h b/unit-tests/utils/cx.h index 78acd01..cf465b5 100644 --- a/unit-tests/utils/cx.h +++ b/unit-tests/utils/cx.h @@ -45,7 +45,7 @@ cx_err_t cx_hash_no_throw(cx_hash_t *hash, uint8_t *out, size_t out_len); -cx_err_t cx_blake2b_256_hash(const uint8_t *data, +cx_err_t cx_blake2b_256_hash(const uint8_t* data, size_t len, uint8_t out[static CX_BLAKE2B_256_SIZE]); diff --git a/unit-tests/utils/macro_helpers.h b/unit-tests/utils/macro_helpers.h index 2406153..a9bb897 100644 --- a/unit-tests/utils/macro_helpers.h +++ b/unit-tests/utils/macro_helpers.h @@ -2,12 +2,14 @@ #pragma once // UNUSED macro. Defined in the Makefile -#define UNUSED(x) (void) (x) +#define UNUSED(x) (void)(x) + #define BUFFER_FROM_ARRAY(_name, _array, _size) \ RW_BUFFER_FROM_ARRAY_FULL(__rw_##_name, _array, _size); \ buffer_t _name = __rw_##_name.read -#define BUFFER_NEW_LOCAL_EMPTY(_name, _size) \ - RW_BUFFER_NEW_LOCAL_EMPTY(__rw_##_name, _size); \ + +#define BUFFER_NEW_LOCAL_EMPTY(_name, _size) \ + RW_BUFFER_NEW_LOCAL_EMPTY(__rw_##_name, _size); \ buffer_t _name = __rw_##_name.read \ No newline at end of file diff --git a/unit-tests/utils/read.c b/unit-tests/utils/read.c index dd1166e..09a7d71 100644 --- a/unit-tests/utils/read.c +++ b/unit-tests/utils/read.c @@ -19,19 +19,22 @@ #include "read.h" -uint16_t read_u16_be(const uint8_t *ptr, size_t offset) { +uint16_t read_u16_be(const uint8_t *ptr, size_t offset) +{ return (uint16_t) ptr[offset + 0] << 8 | // (uint16_t) ptr[offset + 1] << 0; } -uint32_t read_u32_be(const uint8_t *ptr, size_t offset) { +uint32_t read_u32_be(const uint8_t *ptr, size_t offset) +{ return (uint32_t) ptr[offset + 0] << 24 | // (uint32_t) ptr[offset + 1] << 16 | // (uint32_t) ptr[offset + 2] << 8 | // (uint32_t) ptr[offset + 3] << 0; } -uint64_t read_u64_be(const uint8_t *ptr, size_t offset) { +uint64_t read_u64_be(const uint8_t *ptr, size_t offset) +{ return (uint64_t) ptr[offset + 0] << 56 | // (uint64_t) ptr[offset + 1] << 48 | // (uint64_t) ptr[offset + 2] << 40 | // @@ -42,19 +45,22 @@ uint64_t read_u64_be(const uint8_t *ptr, size_t offset) { (uint64_t) ptr[offset + 7] << 0; } -uint16_t read_u16_le(const uint8_t *ptr, size_t offset) { +uint16_t read_u16_le(const uint8_t *ptr, size_t offset) +{ return (uint16_t) ptr[offset + 0] << 0 | // (uint16_t) ptr[offset + 1] << 8; } -uint32_t read_u32_le(const uint8_t *ptr, size_t offset) { +uint32_t read_u32_le(const uint8_t *ptr, size_t offset) +{ return (uint32_t) ptr[offset + 0] << 0 | // (uint32_t) ptr[offset + 1] << 8 | // (uint32_t) ptr[offset + 2] << 16 | // (uint32_t) ptr[offset + 3] << 24; } -uint64_t read_u64_le(const uint8_t *ptr, size_t offset) { +uint64_t read_u64_le(const uint8_t *ptr, size_t offset) +{ return (uint64_t) ptr[offset + 0] << 0 | // (uint64_t) ptr[offset + 1] << 8 | // (uint64_t) ptr[offset + 2] << 16 | // diff --git a/unit-tests/utils/varint.c b/unit-tests/utils/varint.c index d04fbb2..fb199f9 100644 --- a/unit-tests/utils/varint.c +++ b/unit-tests/utils/varint.c @@ -22,7 +22,8 @@ #include "write.h" #include "read.h" -uint8_t varint_size(uint64_t value) { +uint8_t varint_size(uint64_t value) +{ if (value <= 0xFC) { return 1; } @@ -38,7 +39,8 @@ uint8_t varint_size(uint64_t value) { return 9; // <= UINT64_MAX } -int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) { +int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) +{ if (in_len < 1) { return -1; } @@ -74,7 +76,8 @@ int varint_read(const uint8_t *in, size_t in_len, uint64_t *value) { return 1; } -int varint_write(uint8_t *out, size_t offset, uint64_t value) { +int varint_write(uint8_t *out, size_t offset, uint64_t value) +{ uint8_t varint_len = varint_size(value); switch (varint_len) { diff --git a/unit-tests/utils/write.c b/unit-tests/utils/write.c index 7c4f3c5..b6ae4b7 100644 --- a/unit-tests/utils/write.c +++ b/unit-tests/utils/write.c @@ -19,19 +19,22 @@ #include "write.h" -void write_u16_be(uint8_t *ptr, size_t offset, uint16_t value) { +void write_u16_be(uint8_t *ptr, size_t offset, uint16_t value) +{ ptr[offset + 0] = (uint8_t) (value >> 8); ptr[offset + 1] = (uint8_t) (value >> 0); } -void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value) { +void write_u32_be(uint8_t *ptr, size_t offset, uint32_t value) +{ ptr[offset + 0] = (uint8_t) (value >> 24); ptr[offset + 1] = (uint8_t) (value >> 16); ptr[offset + 2] = (uint8_t) (value >> 8); ptr[offset + 3] = (uint8_t) (value >> 0); } -void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) { +void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) +{ ptr[offset + 0] = (uint8_t) (value >> 56); ptr[offset + 1] = (uint8_t) (value >> 48); ptr[offset + 2] = (uint8_t) (value >> 40); @@ -42,19 +45,22 @@ void write_u64_be(uint8_t *ptr, size_t offset, uint64_t value) { ptr[offset + 7] = (uint8_t) (value >> 0); } -void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value) { +void write_u16_le(uint8_t *ptr, size_t offset, uint16_t value) +{ ptr[offset + 0] = (uint8_t) (value >> 0); ptr[offset + 1] = (uint8_t) (value >> 8); } -void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value) { +void write_u32_le(uint8_t *ptr, size_t offset, uint32_t value) +{ ptr[offset + 0] = (uint8_t) (value >> 0); ptr[offset + 1] = (uint8_t) (value >> 8); ptr[offset + 2] = (uint8_t) (value >> 16); ptr[offset + 3] = (uint8_t) (value >> 24); } -void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value) { +void write_u64_le(uint8_t *ptr, size_t offset, uint64_t value) +{ ptr[offset + 0] = (uint8_t) (value >> 0); ptr[offset + 1] = (uint8_t) (value >> 8); ptr[offset + 2] = (uint8_t) (value >> 16); From 52cf579368aec21a2aaa1f0f5e955c7e60f654bd Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 14 Oct 2024 20:13:57 +0300 Subject: [PATCH 28/56] Fixed icon size --- icons/app_40px.gif | Bin 63 -> 118 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/app_40px.gif b/icons/app_40px.gif index 5d8d53b583d42d040b0731655213348fa5817884..ff3a62275f4b9d2b661087dc1b5d249a31c370ec 100644 GIT binary patch literal 118 zcmZ?wbh9u|)L_tHXkcUjg8%>j>wsvG2m@1SPyfo(Z}}I`*>bD9n03!@{<08{X~~^c zx0kzSy)OEoa(+UFeZ{>ue;)nT%sQmFv7$ne_f)DtWs6(4f8y8jqfFCIt~AYNwhVqE UESYLIdB>Y=zj^j>wsvG2m_N`Pyfo@5BNprEC^N8cgtJ;PI7^Ho@$v< N$d|R59LlT=)&LCC5?25K From 23e2b9efe681e33de1bfa6ae016b2b5c1c8e3a5a Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 14 Oct 2024 20:19:59 +0300 Subject: [PATCH 29/56] Removed unused code --- .vscode/settings.json | 8 +------- README.md | 2 +- src/ui/ui_application_id.h | 2 -- src/ui/ui_application_id_nbgl.c | 5 ----- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0d7a227..4be05ef 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,15 +1,9 @@ { "files.associations": { "*.h": "c", - "format": "c", - "cstdint": "c" + "format": "c" }, "editor.formatOnSave": false, "python.terminal.activateEnvironment": false, "git.ignoreLimitWarning": true, - "ledgerDevTools.appSettings": { - "selectedUseCase": "debug", - "selectedDevice": "Stax", - "selectedVariant": "ergo" - }, } \ No newline at end of file diff --git a/README.md b/README.md index f9f801a..0f3bac1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Ledger Ergo Application -This is a Ergo application for the Ledger Nano S+/X. +This is a Ergo application for the Ledger Nano S+/X/Stax/Flex. ## Prerequisite diff --git a/src/ui/ui_application_id.h b/src/ui/ui_application_id.h index ae9b64a..510316a 100644 --- a/src/ui/ui_application_id.h +++ b/src/ui/ui_application_id.h @@ -18,6 +18,4 @@ const ux_flow_step_t* ui_application_id_screen(uint32_t app_id, nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, char buffer[static APPLICATION_ID_STR_LEN]); -void ui_application_id_screen_buf(uint32_t app_id, char buffer[static APPLICATION_ID_STR_LEN]); - #endif \ No newline at end of file diff --git a/src/ui/ui_application_id_nbgl.c b/src/ui/ui_application_id_nbgl.c index 3b1c281..ee81c03 100644 --- a/src/ui/ui_application_id_nbgl.c +++ b/src/ui/ui_application_id_nbgl.c @@ -12,9 +12,4 @@ nbgl_layoutTagValue_t ui_application_id_screen(uint32_t app_id, return tag; } -void ui_application_id_screen_buf(uint32_t app_id, char buffer[static APPLICATION_ID_STR_LEN]) { - memset(buffer, 0, APPLICATION_ID_STR_LEN); - snprintf(buffer, APPLICATION_ID_STR_LEN, "Application: 0x%08x", app_id); -} - #endif \ No newline at end of file From c61262cf35ac06b94e93c1084972088f96ba039b Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 14 Oct 2024 20:21:01 +0300 Subject: [PATCH 30/56] Updated changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99cb5a1..296a5ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.0.6] - 2024-06-10 + +- Added Stax/Flex + ## [0.0.5] - 2024-06-10 - Updated to the latest Ledger SDK From 2c6117c56eaa8c60fe6f368271bd0fc334e37ef8 Mon Sep 17 00:00:00 2001 From: Ivan Date: Mon, 14 Oct 2024 20:29:25 +0300 Subject: [PATCH 31/56] Cleanup --- src/commands/deriveaddress/da_ui_nbgl.c | 10 +++++----- src/commands/signtx/stx_ui_nbgl.c | 24 ++++++++++++------------ src/ui/display.h | 4 +--- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index b9e9968..49cb279 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -59,14 +59,14 @@ int ui_display_address(derive_address_ctx_t* ctx, pairs_global[n_pairs++] = ui_application_id_screen(app_access_token, ctx->app_id); } - pairList.nbMaxLinesForValue = 0; - pairList.nbPairs = n_pairs; - pairList.pairs = pairs_global; + pair_list.nbMaxLinesForValue = 0; + pair_list.nbPairs = n_pairs; + pair_list.pairs = pairs_global; if (send) { // Confirm Send Address nbgl_useCaseAddressReview(ctx->address, - n_pairs == 0 ? NULL : &pairList, + n_pairs == 0 ? NULL : &pair_list, &WHEEL_ICON, "Confirm Send Address", "", @@ -74,7 +74,7 @@ int ui_display_address(derive_address_ctx_t* ctx, } else { // Confirm Address nbgl_useCaseAddressReview(ctx->address, - n_pairs == 0 ? NULL : &pairList, + n_pairs == 0 ? NULL : &pair_list, &INFO_I_ICON, "Confirm Address", "", diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index 517fdfd..bb142b7 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -90,13 +90,13 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, ctx->sign_tx_context = sign_tx; ctx->is_known_application = is_known_application; - pairList.nbMaxLinesForValue = 0; - pairList.nbPairs = n_pairs; - pairList.pairs = pairs_global; + pair_list.nbMaxLinesForValue = 0; + pair_list.nbPairs = n_pairs; + pair_list.pairs = pairs_global; bool approved = true; if (n_pairs > 0) { - nbgl_useCaseReviewStreamingContinue(&pairList, ui_stx_operation_approve_action); + nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); approved = io_ui_process(); } @@ -305,11 +305,11 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, n_pairs++; } - pairList.nbMaxLinesForValue = 0; - pairList.nbPairs = n_pairs; - pairList.pairs = pairs_global; + pair_list.nbMaxLinesForValue = 0; + pair_list.nbPairs = n_pairs; + pair_list.pairs = pairs_global; - nbgl_useCaseReviewStreamingContinue(&pairList, ui_stx_operation_approve_action); + nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); bool approved = io_ui_process(); @@ -374,11 +374,11 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, n_pairs++; } - pairList.nbMaxLinesForValue = 0; - pairList.nbPairs = n_pairs; - pairList.pairs = pairs_global; + pair_list.nbMaxLinesForValue = 0; + pair_list.nbPairs = n_pairs; + pair_list.pairs = pairs_global; - nbgl_useCaseReviewStreamingContinue(&pairList, ui_stx_operation_approve_action); + nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); bool approved = io_ui_process(); if (!approved) { diff --git a/src/ui/display.h b/src/ui/display.h index d8f8b13..e06e829 100644 --- a/src/ui/display.h +++ b/src/ui/display.h @@ -13,9 +13,7 @@ bool io_ui_process(); #ifdef HAVE_NBGL #define N_UX_PAIRS 13 -static nbgl_layoutTagValue_t pairs[N_UX_PAIRS]; -static nbgl_layoutTagValueList_t pairList; - +static nbgl_layoutTagValueList_t pair_list; extern nbgl_layoutTagValue_t pairs_global[N_UX_PAIRS]; static char pair_mem_title[N_UX_PAIRS][20]; From 68cd1d97e351b8f30d5ce6bcc642e6bee83a0489 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 16 Oct 2024 04:07:27 +0300 Subject: [PATCH 32/56] Update CHANGELOG.md Co-authored-by: Alison Oliveira <87387688+arobsn@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 296a5ae..f2eba04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.0.6] - 2024-06-10 - Added Stax/Flex - +- Removed Nano S ## [0.0.5] - 2024-06-10 - Updated to the latest Ledger SDK From b2696bf5d1f0e6775fcc802d4e8e908c16bfd615 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 16 Oct 2024 04:08:07 +0300 Subject: [PATCH 33/56] Fix changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2eba04..f434cb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added Stax/Flex - Removed Nano S + ## [0.0.5] - 2024-06-10 - Updated to the latest Ledger SDK From a194cd8baccf0c65376d091676c773deb88d6ea9 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 16 Oct 2024 04:11:09 +0300 Subject: [PATCH 34/56] Set TOKEN_MAX_COUNT to 100 --- src/constants.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants.h b/src/constants.h index cad8ad5..8f0290a 100644 --- a/src/constants.h +++ b/src/constants.h @@ -38,7 +38,7 @@ /** * Maximum number of tokens in TX. */ -#define TOKEN_MAX_COUNT 20 +#define TOKEN_MAX_COUNT 100 /** * Length of Session Key. From c9af358f8a84b67d0776f38988ba9807c0aa672f Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 16 Oct 2024 04:32:55 +0300 Subject: [PATCH 35/56] Updated UI to support more tokens --- src/commands/signtx/stx_ui_nbgl.c | 10 ++++++++++ src/ui/display.h | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index bb142b7..ab34768 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -293,6 +293,11 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, int n_pairs = *screen; for (int i = 0; i < info_screen_count; i++) { + if (n_pairs >= N_UX_PAIRS - 1 - (n_pairs % 2 == 0 ? 1 : 0)) { + pairs_global[n_pairs].item = "Too much outputs"; + pairs_global[n_pairs].value = "It's not possible to show other outputs"; + break; + } pairs_global[n_pairs].item = pair_mem_title[i]; pairs_global[n_pairs].value = pair_mem_text[i]; ui_stx_display_output_state(i, pair_mem_title[i], pair_mem_text[i], (void*) ctx); @@ -362,6 +367,11 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, };*/ for (int i = 0; i < op_screen_count + 2 + (2 * tokens_count); i++) { + if (n_pairs >= N_UX_PAIRS - 1 - (n_pairs % 2 == 0 ? 1 : 0)) { + pairs_global[n_pairs].item = "Too much outputs"; + pairs_global[n_pairs].value = "It's not possible to show other outputs"; + break; + } pairs_global[n_pairs].item = pair_mem_title[i]; pairs_global[n_pairs].value = pair_mem_text[i]; ui_stx_display_tx_state(i, pair_mem_title[i], pair_mem_text[i], (void*) ctx); diff --git a/src/ui/display.h b/src/ui/display.h index e06e829..5931d0e 100644 --- a/src/ui/display.h +++ b/src/ui/display.h @@ -3,6 +3,7 @@ #include #include "../context.h" +#include "../constants.h" extern bool flow_response; @@ -11,7 +12,9 @@ void io_common_process(); bool io_ui_process(); #ifdef HAVE_NBGL -#define N_UX_PAIRS 13 +#define N_UX_PAIRS \ + TOKEN_MAX_COUNT + TOKEN_MAX_COUNT / 2 + \ + 10 // 10 reserved for other info (ex. tx amount / tx fee) static nbgl_layoutTagValueList_t pair_list; extern nbgl_layoutTagValue_t pairs_global[N_UX_PAIRS]; From 41d03a9d6113a9a544bb474846d552d3f427920e Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 16 Oct 2024 04:43:37 +0300 Subject: [PATCH 36/56] Add required app permissions --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9b59ddc..b8f5f4c 100644 --- a/Makefile +++ b/Makefile @@ -79,8 +79,8 @@ endif # Application custom permissions # ######################################## # See SDK `include/appflags.h` for the purpose of each permission -#HAVE_APPLICATION_FLAG_DERIVE_MASTER = 1 -#HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1 +HAVE_APPLICATION_FLAG_DERIVE_MASTER = 1 +HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1 #HAVE_APPLICATION_FLAG_BOLOS_SETTINGS = 1 #HAVE_APPLICATION_FLAG_LIBRARY = 1 From 5b0ce37b91202607402624f4238258a81fd6dedb Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 16 Oct 2024 04:46:59 +0300 Subject: [PATCH 37/56] Revert permissions --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b8f5f4c..9b59ddc 100644 --- a/Makefile +++ b/Makefile @@ -79,8 +79,8 @@ endif # Application custom permissions # ######################################## # See SDK `include/appflags.h` for the purpose of each permission -HAVE_APPLICATION_FLAG_DERIVE_MASTER = 1 -HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1 +#HAVE_APPLICATION_FLAG_DERIVE_MASTER = 1 +#HAVE_APPLICATION_FLAG_GLOBAL_PIN = 1 #HAVE_APPLICATION_FLAG_BOLOS_SETTINGS = 1 #HAVE_APPLICATION_FLAG_LIBRARY = 1 From 83dd5164932d63b996c669954491c42122c75f36 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 16 Oct 2024 16:57:50 +0300 Subject: [PATCH 38/56] Dynamic UI allocation --- src/commands/signtx/stx_ui_nbgl.c | 104 ++++++++++++++---------------- src/ui/display.h | 4 +- 2 files changed, 49 insertions(+), 59 deletions(-) diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index ab34768..0b8bac3 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -291,34 +291,38 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, ctx->last_approved_change = last_approved_change; int n_pairs = *screen; + bool approved = false; for (int i = 0; i < info_screen_count; i++) { - if (n_pairs >= N_UX_PAIRS - 1 - (n_pairs % 2 == 0 ? 1 : 0)) { - pairs_global[n_pairs].item = "Too much outputs"; - pairs_global[n_pairs].value = "It's not possible to show other outputs"; - break; - } - pairs_global[n_pairs].item = pair_mem_title[i]; - pairs_global[n_pairs].value = pair_mem_text[i]; - ui_stx_display_output_state(i, pair_mem_title[i], pair_mem_text[i], (void*) ctx); + pairs_global[n_pairs].item = pair_mem_title[n_pairs]; + pairs_global[n_pairs].value = pair_mem_text[n_pairs]; + ui_stx_display_output_state(i, + pair_mem_title[n_pairs], + pair_mem_text[n_pairs], + (void*) ctx); // empty row (split screens for tokens) - if (n_pairs % 2 == 0) { + if ((n_pairs + 1) % 2 == 0) { n_pairs++; - pairs_global[n_pairs].item = ""; - pairs_global[n_pairs].value = ""; - } - n_pairs++; - } + pair_list.nbMaxLinesForValue = 0; + pair_list.nbPairs = n_pairs; + pair_list.pairs = pairs_global; - pair_list.nbMaxLinesForValue = 0; - pair_list.nbPairs = n_pairs; - pair_list.pairs = pairs_global; + nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); + approved = io_ui_process(); + app_set_ui_busy(false); - nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); + n_pairs = 0; - bool approved = io_ui_process(); - - app_set_ui_busy(false); + if (!approved) { + app_set_current_command(CMD_NONE); + res_deny(); + ui_menu_main(); + return true; + } + } else { + n_pairs++; + } + } explicit_bzero(ctx->last_approved_change, sizeof(sign_transaction_bip32_path_t)); @@ -330,11 +334,6 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, sizeof(sign_transaction_bip32_path_t)); } res_ok(); - } else { - app_set_current_command(CMD_NONE); - res_deny(); - - ui_menu_main(); } return true; @@ -360,41 +359,34 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, ctx->amounts = amounts; int n_pairs = *screen; - - /*pairs_global[n_pairs++] = (nbgl_layoutTagValue_t) { - .item = ctx->title, - .value = ctx->text - };*/ + bool approved = false; for (int i = 0; i < op_screen_count + 2 + (2 * tokens_count); i++) { - if (n_pairs >= N_UX_PAIRS - 1 - (n_pairs % 2 == 0 ? 1 : 0)) { - pairs_global[n_pairs].item = "Too much outputs"; - pairs_global[n_pairs].value = "It's not possible to show other outputs"; - break; - } - pairs_global[n_pairs].item = pair_mem_title[i]; - pairs_global[n_pairs].value = pair_mem_text[i]; - ui_stx_display_tx_state(i, pair_mem_title[i], pair_mem_text[i], (void*) ctx); + pairs_global[n_pairs].item = pair_mem_title[n_pairs]; + pairs_global[n_pairs].value = pair_mem_text[n_pairs]; + ui_stx_display_tx_state(i, pair_mem_title[n_pairs], pair_mem_text[n_pairs], (void*) ctx); // empty row (split screens for tokens) - if (n_pairs % 2 == 0) { + if ((n_pairs + 1) % 3 == 0) { n_pairs++; - pairs_global[n_pairs].item = ""; - pairs_global[n_pairs].value = ""; - } - n_pairs++; - } - - pair_list.nbMaxLinesForValue = 0; - pair_list.nbPairs = n_pairs; - pair_list.pairs = pairs_global; - - nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); + pair_list.nbMaxLinesForValue = 0; + pair_list.nbPairs = n_pairs; + pair_list.pairs = pairs_global; + + nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); + approved = io_ui_process(); + app_set_ui_busy(false); + + if (!approved) { + res_deny(); + app_set_current_command(CMD_NONE); + ui_menu_main(); + return true; + } - bool approved = io_ui_process(); - if (!approved) { - res_deny(); - app_set_current_command(CMD_NONE); - ui_menu_main(); + n_pairs = 0; + } else { + n_pairs++; + } } if (MAX_NUMBER_OF_SCREENS - *screen < 2) return false; diff --git a/src/ui/display.h b/src/ui/display.h index 5931d0e..c924075 100644 --- a/src/ui/display.h +++ b/src/ui/display.h @@ -12,9 +12,7 @@ void io_common_process(); bool io_ui_process(); #ifdef HAVE_NBGL -#define N_UX_PAIRS \ - TOKEN_MAX_COUNT + TOKEN_MAX_COUNT / 2 + \ - 10 // 10 reserved for other info (ex. tx amount / tx fee) +#define N_UX_PAIRS 10 static nbgl_layoutTagValueList_t pair_list; extern nbgl_layoutTagValue_t pairs_global[N_UX_PAIRS]; From 742251004e62020b3a2ae8e2ebf09eb9286eae87 Mon Sep 17 00:00:00 2001 From: Ivan Date: Wed, 16 Oct 2024 17:21:29 +0300 Subject: [PATCH 39/56] Fix tx fee display --- src/commands/signtx/stx_ui_nbgl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index 0b8bac3..dc7dfc0 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -366,7 +366,8 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, pairs_global[n_pairs].value = pair_mem_text[n_pairs]; ui_stx_display_tx_state(i, pair_mem_title[n_pairs], pair_mem_text[n_pairs], (void*) ctx); // empty row (split screens for tokens) - if ((n_pairs + 1) % 3 == 0) { + if (((n_pairs + 1) % 2 == 0 && i != 1) || + i == 2) { // first page should contain 3 rows, other 2 n_pairs++; pair_list.nbMaxLinesForValue = 0; pair_list.nbPairs = n_pairs; From 2362b6503b50330da609bc56bf37ada9b9304f41 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 17 Oct 2024 15:00:41 +0300 Subject: [PATCH 40/56] Remove TARGET_NANOS check --- src/commands/signtx/stx_ui.h | 6 ++++++ src/commands/signtx/stx_ui_bagl.c | 11 ----------- src/commands/signtx/stx_ui_nbgl.c | 11 ----------- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/commands/signtx/stx_ui.h b/src/commands/signtx/stx_ui.h index 4f60e22..f2d9685 100644 --- a/src/commands/signtx/stx_ui.h +++ b/src/commands/signtx/stx_ui.h @@ -8,6 +8,12 @@ #include "stx_types.h" #include "stx_context.h" +#define ERGO_ID_UI_CHARACTERS_HALF 26 +#define STRING_ADD_STATIC_TEXT(str, slen, text) \ + strncpy(str, text, slen); \ + slen -= sizeof(text) - 1; \ + str += sizeof(text) - 1 + /** * Add application access_token and accept/reject screens to the UI. * diff --git a/src/commands/signtx/stx_ui_bagl.c b/src/commands/signtx/stx_ui_bagl.c index a3f0905..bbd031e 100644 --- a/src/commands/signtx/stx_ui_bagl.c +++ b/src/commands/signtx/stx_ui_bagl.c @@ -20,17 +20,6 @@ #include "../../ui/ui_menu.h" #include "../../ui/ui_main.h" -#ifdef TARGET_NANOS -#define ERGO_ID_UI_CHARACTERS_HALF 7 -#else -#define ERGO_ID_UI_CHARACTERS_HALF 26 -#endif - -#define STRING_ADD_STATIC_TEXT(str, slen, text) \ - strncpy(str, text, slen); \ - slen -= sizeof(text) - 1; \ - str += sizeof(text) - 1 - static inline void id_string_remove_middle(char* str, size_t len) { if (len <= 2 * ERGO_ID_UI_CHARACTERS_HALF + 3) return; str[ERGO_ID_UI_CHARACTERS_HALF] = str[ERGO_ID_UI_CHARACTERS_HALF + 1] = diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index dc7dfc0..c47b7d6 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -23,17 +23,6 @@ #include "../../ui/ui_main.h" #include "../../ui/display.h" -#ifdef TARGET_NANOS -#define ERGO_ID_UI_CHARACTERS_HALF 7 -#else -#define ERGO_ID_UI_CHARACTERS_HALF 26 -#endif - -#define STRING_ADD_STATIC_TEXT(str, slen, text) \ - strncpy(str, text, slen); \ - slen -= sizeof(text) - 1; \ - str += sizeof(text) - 1 - static inline void id_string_remove_middle(char* str, size_t len) { if (len <= 2 * ERGO_ID_UI_CHARACTERS_HALF + 3) return; str[ERGO_ID_UI_CHARACTERS_HALF] = str[ERGO_ID_UI_CHARACTERS_HALF + 1] = From 42c5b014430a96788c2c3361ecbae7726cce0325 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 17 Oct 2024 15:18:03 +0300 Subject: [PATCH 41/56] Unify bagl/nbgl shared code --- src/commands/signtx/stx_ui.h | 6 - src/commands/signtx/stx_ui_bagl.c | 199 +------------------------- src/commands/signtx/stx_ui_common.h | 214 ++++++++++++++++++++++++++++ src/commands/signtx/stx_ui_nbgl.c | 199 +------------------------- 4 files changed, 216 insertions(+), 402 deletions(-) create mode 100644 src/commands/signtx/stx_ui_common.h diff --git a/src/commands/signtx/stx_ui.h b/src/commands/signtx/stx_ui.h index f2d9685..4f60e22 100644 --- a/src/commands/signtx/stx_ui.h +++ b/src/commands/signtx/stx_ui.h @@ -8,12 +8,6 @@ #include "stx_types.h" #include "stx_context.h" -#define ERGO_ID_UI_CHARACTERS_HALF 26 -#define STRING_ADD_STATIC_TEXT(str, slen, text) \ - strncpy(str, text, slen); \ - slen -= sizeof(text) - 1; \ - str += sizeof(text) - 1 - /** * Add application access_token and accept/reject screens to the UI. * diff --git a/src/commands/signtx/stx_ui_bagl.c b/src/commands/signtx/stx_ui_bagl.c index bbd031e..dc3ec34 100644 --- a/src/commands/signtx/stx_ui_bagl.c +++ b/src/commands/signtx/stx_ui_bagl.c @@ -7,6 +7,7 @@ #include #include "stx_ui.h" +#include "stx_ui_common.h" #include "stx_response.h" #include "../../context.h" @@ -20,41 +21,6 @@ #include "../../ui/ui_menu.h" #include "../../ui/ui_main.h" -static inline void id_string_remove_middle(char* str, size_t len) { - if (len <= 2 * ERGO_ID_UI_CHARACTERS_HALF + 3) return; - str[ERGO_ID_UI_CHARACTERS_HALF] = str[ERGO_ID_UI_CHARACTERS_HALF + 1] = - str[ERGO_ID_UI_CHARACTERS_HALF + 2] = '.'; - memmove(str + ERGO_ID_UI_CHARACTERS_HALF + 3, - str + len - ERGO_ID_UI_CHARACTERS_HALF, - ERGO_ID_UI_CHARACTERS_HALF); - str[2 * ERGO_ID_UI_CHARACTERS_HALF + 3] = '\0'; -} - -static inline bool format_hex_id(const uint8_t* id, size_t id_len, char* out, size_t out_len) { - int len = format_hex(id, id_len, out, out_len); - if (len <= 0) return false; - id_string_remove_middle(out, len - 1); - return true; -} - -static inline bool format_b58_id(const uint8_t* id, size_t id_len, char* out, size_t out_len) { - int len = base58_encode(id, id_len, out, out_len); - if (len <= 0) return false; - return true; -} - -static inline bool format_erg_amount(uint64_t amount, char* out, size_t out_len) { - if (!format_fpu64(out, out_len, amount, ERGO_ERG_FRACTION_DIGIT_COUNT)) { - return false; - } - size_t out_bytes = strlen(out); - if (out_len < 5 || out_bytes > out_len - 5) return false; - out_len -= out_bytes; - out += out_bytes; - STRING_ADD_STATIC_TEXT(out, out_len, " ERG"); - return true; -} - // ----- OPERATION APPROVE / REJECT FLOW void ui_stx_operation_approve_reject(bool approved, sign_transaction_ui_aprove_ctx_t* ctx) { @@ -106,108 +72,6 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, // Fist flow step with icon and text UX_STEP_NOCB(ux_stx_display_output_confirm_step, pn, {&C_icon_warning, "Confirm Output"}); -static inline uint16_t output_info_print_address(const sign_transaction_output_info_ctx_t* ctx, - uint8_t network_id, - char* title, - uint8_t title_len, - char* address, - uint8_t address_len) { - if (!stx_output_info_is_finished(ctx)) return SW_BAD_STATE; - switch (stx_output_info_type(ctx)) { - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_BIP32: { - strncpy(title, "Change", title_len); - if (!bip32_path_format(ctx->bip32_path.path, - ctx->bip32_path.len, - address, - address_len)) { - return SW_BIP32_FORMATTING_FAILED; - } - break; - } - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_ADDRESS: { - uint8_t raw_address[P2PK_ADDRESS_LEN]; - strncpy(title, "Address", title_len); - if (!ergo_address_from_compressed_pubkey(network_id, ctx->public_key, raw_address)) { - return SW_ADDRESS_GENERATION_FAILED; - } - if (!format_b58_id(raw_address, P2PK_ADDRESS_LEN, address, address_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - break; - } - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_SCRIPT: - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_SCRIPT_HASH: { - strncpy(title, "Script Hash", title_len); - uint8_t raw_address[P2SH_ADDRESS_LEN]; - if (!ergo_address_from_script_hash(network_id, ctx->tree_hash, raw_address)) { - return SW_ADDRESS_GENERATION_FAILED; - } - if (!format_b58_id(raw_address, P2SH_ADDRESS_LEN, address, address_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - break; - } - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_MINERS_FEE: { - strncpy(title, "Fee", title_len); - strncpy(address, "Miners Fee", address_len); - break; - } - default: - return SW_BAD_STATE; - } - return SW_OK; -} - -static NOINLINE uint16_t ui_stx_display_output_state(uint8_t screen, - char* title, - char* text, - void* context) { - sign_transaction_ui_output_confirm_ctx_t* ctx = - (sign_transaction_ui_output_confirm_ctx_t*) context; - uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, title); - uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, text); - memset(title, 0, title_len); - memset(text, 0, text_len); - - switch (screen) { - case 0: // Output Address Info - return output_info_print_address(ctx->output, - ctx->network_id, - title, - title_len, - text, - text_len); - case 1: { // Output Value - strncpy(title, "Output Value", title_len); - if (!format_erg_amount(ctx->output->value, text, text_len)) { - return SW_BUFFER_ERROR; - } - break; - } - default: { // Tokens - screen -= 2; // Decrease index for info screens - uint8_t token_idx = stx_output_info_used_token_index(ctx->output, screen / 2); - if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state - return SW_BAD_TOKEN_INDEX; - } - if (screen % 2 == 0) { // Token ID - snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); - if (!format_hex_id(ctx->output->tokens_table->tokens[token_idx], - ERGO_ID_LEN, - text, - text_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - } else { // Token Value - snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); - format_u64(text, text_len, ctx->output->tokens[token_idx]); - } - break; - } - } - return SW_OK; -} - static NOINLINE void ui_stx_operation_output_confirm_action(bool approved, void* context) { sign_transaction_ui_output_confirm_ctx_t* ctx = (sign_transaction_ui_output_confirm_ctx_t*) context; @@ -276,67 +140,6 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, // Fist flow step with icon and text UX_STEP_NOCB(ux_stx_display_sign_confirm_step, pn, {&C_icon_warning, "Approve Signing"}); -// Callback for TX UI rendering -static NOINLINE uint16_t ui_stx_display_tx_state(uint8_t screen, - char* title, - char* text, - void* context) { - sign_transaction_ui_sign_confirm_ctx_t* ctx = (sign_transaction_ui_sign_confirm_ctx_t*) context; - uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, title); - uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, text); - memset(title, 0, title_len); - memset(text, 0, text_len); - - if (screen < ctx->op_screen_count) { // Showing operation screen - return ctx->op_screen_cb(screen, title, title_len, text, text_len, ctx->op_cb_context); - } - screen -= ctx->op_screen_count; - switch (screen) { - case 0: { // TX Value - strncpy(title, "Transaction Amount", title_len); - if (!format_erg_amount(ctx->amounts->value, text, text_len)) { - return SW_BUFFER_ERROR; - } - break; - } - case 1: { // TX Fee - strncpy(title, "Transaction Fee", title_len); - if (!format_erg_amount(ctx->amounts->fee, text, text_len)) { - return SW_BUFFER_ERROR; - } - break; - } - default: { // Tokens - screen -= 2; // Decrease index for info screens - uint8_t token_idx = stx_amounts_non_zero_token_index(ctx->amounts, screen / 2); - if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state - return SW_BAD_TOKEN_INDEX; - } - if (screen % 2 == 0) { // Token ID - snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); - if (!format_hex_id(ctx->amounts->tokens_table.tokens[token_idx], - ERGO_ID_LEN, - text, - text_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - } else { // Token Value - snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); - int64_t value = ctx->amounts->tokens[token_idx]; - if (value < 0) { // output > inputs - STRING_ADD_STATIC_TEXT(text, text_len, "Minting: "); - format_u64(text, text_len, -value); - } else { // inputs > outputs - STRING_ADD_STATIC_TEXT(text, text_len, "Burning: "); - format_u64(text, text_len, value); - } - } - break; - } - } - return SW_OK; -} - // TX approve/reject callback static NOINLINE void ui_stx_operation_execute_action(bool approved, void* context) { app_set_ui_busy(false); diff --git a/src/commands/signtx/stx_ui_common.h b/src/commands/signtx/stx_ui_common.h new file mode 100644 index 0000000..533fce8 --- /dev/null +++ b/src/commands/signtx/stx_ui_common.h @@ -0,0 +1,214 @@ +#pragma once + +#include +#include +#include +#include + +#include "stx_ui.h" + +#include "../../ergo/address.h" + +#define ERGO_ID_UI_CHARACTERS_HALF 26 +#define STRING_ADD_STATIC_TEXT(str, slen, text) \ + strncpy(str, text, slen); \ + slen -= sizeof(text) - 1; \ + str += sizeof(text) - 1 + +static inline void id_string_remove_middle(char* str, size_t len) { + if (len <= 2 * ERGO_ID_UI_CHARACTERS_HALF + 3) return; + str[ERGO_ID_UI_CHARACTERS_HALF] = str[ERGO_ID_UI_CHARACTERS_HALF + 1] = + str[ERGO_ID_UI_CHARACTERS_HALF + 2] = '.'; + memmove(str + ERGO_ID_UI_CHARACTERS_HALF + 3, + str + len - ERGO_ID_UI_CHARACTERS_HALF, + ERGO_ID_UI_CHARACTERS_HALF); + str[2 * ERGO_ID_UI_CHARACTERS_HALF + 3] = '\0'; +} + +static inline bool format_hex_id(const uint8_t* id, size_t id_len, char* out, size_t out_len) { + int len = format_hex(id, id_len, out, out_len); + if (len <= 0) return false; + id_string_remove_middle(out, len - 1); + return true; +} + +static inline bool format_b58_id(const uint8_t* id, size_t id_len, char* out, size_t out_len) { + int len = base58_encode(id, id_len, out, out_len); + if (len <= 0) return false; + return true; +} + +static inline bool format_erg_amount(uint64_t amount, char* out, size_t out_len) { + if (!format_fpu64(out, out_len, amount, ERGO_ERG_FRACTION_DIGIT_COUNT)) { + return false; + } + size_t out_bytes = strlen(out); + if (out_len < 5 || out_bytes > out_len - 5) return false; + out_len -= out_bytes; + out += out_bytes; + STRING_ADD_STATIC_TEXT(out, out_len, " ERG"); + return true; +} + +static inline uint16_t output_info_print_address(const sign_transaction_output_info_ctx_t* ctx, + uint8_t network_id, + char* title, + uint8_t title_len, + char* address, + uint8_t address_len) { + if (!stx_output_info_is_finished(ctx)) return SW_BAD_STATE; + switch (stx_output_info_type(ctx)) { + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_BIP32: { + strncpy(title, "Change", title_len); + if (!bip32_path_format(ctx->bip32_path.path, + ctx->bip32_path.len, + address, + address_len)) { + return SW_BIP32_FORMATTING_FAILED; + } + break; + } + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_ADDRESS: { + uint8_t raw_address[P2PK_ADDRESS_LEN]; + strncpy(title, "Address", title_len); + if (!ergo_address_from_compressed_pubkey(network_id, ctx->public_key, raw_address)) { + return SW_ADDRESS_GENERATION_FAILED; + } + if (!format_b58_id(raw_address, P2PK_ADDRESS_LEN, address, address_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + break; + } + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_SCRIPT: + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_SCRIPT_HASH: { + strncpy(title, "Script Hash", title_len); + uint8_t raw_address[P2SH_ADDRESS_LEN]; + if (!ergo_address_from_script_hash(network_id, ctx->tree_hash, raw_address)) { + return SW_ADDRESS_GENERATION_FAILED; + } + if (!format_b58_id(raw_address, P2SH_ADDRESS_LEN, address, address_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + break; + } + case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_MINERS_FEE: { + strncpy(title, "Fee", title_len); + strncpy(address, "Miners Fee", address_len); + break; + } + default: + return SW_BAD_STATE; + } + return SW_OK; +} + +static NOINLINE uint16_t ui_stx_display_output_state(uint8_t screen, + char* title, + char* text, + void* context) { + sign_transaction_ui_output_confirm_ctx_t* ctx = + (sign_transaction_ui_output_confirm_ctx_t*) context; + uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, title); + uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, text); + memset(title, 0, title_len); + memset(text, 0, text_len); + + switch (screen) { + case 0: // Output Address Info + return output_info_print_address(ctx->output, + ctx->network_id, + title, + title_len, + text, + text_len); + case 1: { // Output Value + strncpy(title, "Output Value", title_len); + if (!format_erg_amount(ctx->output->value, text, text_len)) { + return SW_BUFFER_ERROR; + } + break; + } + default: { // Tokens + screen -= 2; // Decrease index for info screens + uint8_t token_idx = stx_output_info_used_token_index(ctx->output, screen / 2); + if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state + return SW_BAD_TOKEN_INDEX; + } + if (screen % 2 == 0) { // Token ID + snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); + if (!format_hex_id(ctx->output->tokens_table->tokens[token_idx], + ERGO_ID_LEN, + text, + text_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + } else { // Token Value + snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); + format_u64(text, text_len, ctx->output->tokens[token_idx]); + } + break; + } + } + return SW_OK; +} + +// Callback for TX UI rendering +static NOINLINE uint16_t ui_stx_display_tx_state(uint8_t screen, + char* title, + char* text, + void* context) { + sign_transaction_ui_sign_confirm_ctx_t* ctx = (sign_transaction_ui_sign_confirm_ctx_t*) context; + uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, title); + uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, text); + memset(title, 0, title_len); + memset(text, 0, text_len); + + if (screen < ctx->op_screen_count) { // Showing operation screen + return ctx->op_screen_cb(screen, title, title_len, text, text_len, ctx->op_cb_context); + } + screen -= ctx->op_screen_count; + switch (screen) { + case 0: { // TX Value + strncpy(title, "Transaction Amount", title_len); + if (!format_erg_amount(ctx->amounts->value, text, text_len)) { + return SW_BUFFER_ERROR; + } + break; + } + case 1: { // TX Fee + strncpy(title, "Transaction Fee", title_len); + if (!format_erg_amount(ctx->amounts->fee, text, text_len)) { + return SW_BUFFER_ERROR; + } + break; + } + default: { // Tokens + screen -= 2; // Decrease index for info screens + uint8_t token_idx = stx_amounts_non_zero_token_index(ctx->amounts, screen / 2); + if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state + return SW_BAD_TOKEN_INDEX; + } + if (screen % 2 == 0) { // Token ID + snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); + if (!format_hex_id(ctx->amounts->tokens_table.tokens[token_idx], + ERGO_ID_LEN, + text, + text_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + } else { // Token Value + snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); + int64_t value = ctx->amounts->tokens[token_idx]; + if (value < 0) { // output > inputs + STRING_ADD_STATIC_TEXT(text, text_len, "Minting: "); + format_u64(text, text_len, -value); + } else { // inputs > outputs + STRING_ADD_STATIC_TEXT(text, text_len, "Burning: "); + format_u64(text, text_len, value); + } + } + break; + } + } + return SW_OK; +} \ No newline at end of file diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index c47b7d6..deabf8b 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -8,6 +8,7 @@ #include #include "stx_ui.h" +#include "stx_ui_common.h" #include "stx_response.h" #include "../../context.h" @@ -23,41 +24,6 @@ #include "../../ui/ui_main.h" #include "../../ui/display.h" -static inline void id_string_remove_middle(char* str, size_t len) { - if (len <= 2 * ERGO_ID_UI_CHARACTERS_HALF + 3) return; - str[ERGO_ID_UI_CHARACTERS_HALF] = str[ERGO_ID_UI_CHARACTERS_HALF + 1] = - str[ERGO_ID_UI_CHARACTERS_HALF + 2] = '.'; - memmove(str + ERGO_ID_UI_CHARACTERS_HALF + 3, - str + len - ERGO_ID_UI_CHARACTERS_HALF, - ERGO_ID_UI_CHARACTERS_HALF); - str[2 * ERGO_ID_UI_CHARACTERS_HALF + 3] = '\0'; -} - -static inline bool format_hex_id(const uint8_t* id, size_t id_len, char* out, size_t out_len) { - int len = format_hex(id, id_len, out, out_len); - if (len <= 0) return false; - id_string_remove_middle(out, len - 1); - return true; -} - -static inline bool format_b58_id(const uint8_t* id, size_t id_len, char* out, size_t out_len) { - int len = base58_encode(id, id_len, out, out_len); - if (len <= 0) return false; - return true; -} - -static inline bool format_erg_amount(uint64_t amount, char* out, size_t out_len) { - if (!format_fpu64(out, out_len, amount, ERGO_ERG_FRACTION_DIGIT_COUNT)) { - return false; - } - size_t out_bytes = strlen(out); - if (out_len < 5 || out_bytes > out_len - 5) return false; - out_len -= out_bytes; - out += out_bytes; - STRING_ADD_STATIC_TEXT(out, out_len, " ERG"); - return true; -} - static NOINLINE void ui_stx_operation_approve_action(bool approved) { set_flow_response(approved); } @@ -94,169 +60,6 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, return true; } -static inline uint16_t output_info_print_address(const sign_transaction_output_info_ctx_t* ctx, - uint8_t network_id, - char* title, - uint8_t title_len, - char* address, - uint8_t address_len) { - if (!stx_output_info_is_finished(ctx)) return SW_BAD_STATE; - switch (stx_output_info_type(ctx)) { - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_BIP32: { - strncpy(title, "Change", title_len); - if (!bip32_path_format(ctx->bip32_path.path, - ctx->bip32_path.len, - address, - address_len)) { - return SW_BIP32_FORMATTING_FAILED; - } - break; - } - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_ADDRESS: { - uint8_t raw_address[P2PK_ADDRESS_LEN]; - strncpy(title, "Address", title_len); - if (!ergo_address_from_compressed_pubkey(network_id, ctx->public_key, raw_address)) { - return SW_ADDRESS_GENERATION_FAILED; - } - if (!format_b58_id(raw_address, P2PK_ADDRESS_LEN, address, address_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - break; - } - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_SCRIPT: - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_SCRIPT_HASH: { - strncpy(title, "Script Hash", title_len); - uint8_t raw_address[P2SH_ADDRESS_LEN]; - if (!ergo_address_from_script_hash(network_id, ctx->tree_hash, raw_address)) { - return SW_ADDRESS_GENERATION_FAILED; - } - if (!format_b58_id(raw_address, P2SH_ADDRESS_LEN, address, address_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - break; - } - case SIGN_TRANSACTION_OUTPUT_INFO_TYPE_MINERS_FEE: { - strncpy(title, "Fee", title_len); - strncpy(address, "Miners Fee", address_len); - break; - } - default: - return SW_BAD_STATE; - } - return SW_OK; -} - -static NOINLINE uint16_t ui_stx_display_output_state(uint8_t screen, - char* title, - char* text, - void* context) { - sign_transaction_ui_output_confirm_ctx_t* ctx = - (sign_transaction_ui_output_confirm_ctx_t*) context; - uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, title); - uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, text); - memset(title, 0, title_len); - memset(text, 0, text_len); - - switch (screen) { - case 0: // Output Address Info - return output_info_print_address(ctx->output, - ctx->network_id, - title, - title_len, - text, - text_len); - case 1: { // Output Value - strncpy(title, "Output Value", title_len); - if (!format_erg_amount(ctx->output->value, text, text_len)) { - return SW_BUFFER_ERROR; - } - break; - } - default: { // Tokens - screen -= 2; // Decrease index for info screens - uint8_t token_idx = stx_output_info_used_token_index(ctx->output, screen / 2); - if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state - return SW_BAD_TOKEN_INDEX; - } - if (screen % 2 == 0) { // Token ID - snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); - if (!format_hex_id(ctx->output->tokens_table->tokens[token_idx], - ERGO_ID_LEN, - text, - text_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - } else { // Token Value - snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); - format_u64(text, text_len, ctx->output->tokens[token_idx]); - } - break; - } - } - return SW_OK; -} - -// Callback for TX UI rendering -static NOINLINE uint16_t ui_stx_display_tx_state(uint8_t screen, - char* title, - char* text, - void* context) { - sign_transaction_ui_sign_confirm_ctx_t* ctx = (sign_transaction_ui_sign_confirm_ctx_t*) context; - uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, title); - uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, text); - memset(title, 0, title_len); - memset(text, 0, text_len); - - if (screen < ctx->op_screen_count) { // Showing operation screen - return ctx->op_screen_cb(screen, title, title_len, text, text_len, ctx->op_cb_context); - } - screen -= ctx->op_screen_count; - switch (screen) { - case 0: { // TX Value - strncpy(title, "Transaction Amount", title_len); - if (!format_erg_amount(ctx->amounts->value, text, text_len)) { - return SW_BUFFER_ERROR; - } - break; - } - case 1: { // TX Fee - strncpy(title, "Transaction Fee", title_len); - if (!format_erg_amount(ctx->amounts->fee, text, text_len)) { - return SW_BUFFER_ERROR; - } - break; - } - default: { // Tokens - screen -= 2; // Decrease index for info screens - uint8_t token_idx = stx_amounts_non_zero_token_index(ctx->amounts, screen / 2); - if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state - return SW_BAD_TOKEN_INDEX; - } - if (screen % 2 == 0) { // Token ID - snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); - if (!format_hex_id(ctx->amounts->tokens_table.tokens[token_idx], - ERGO_ID_LEN, - text, - text_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - } else { // Token Value - snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); - int64_t value = ctx->amounts->tokens[token_idx]; - if (value < 0) { // output > inputs - STRING_ADD_STATIC_TEXT(text, text_len, "Minting: "); - format_u64(text, text_len, -value); - } else { // inputs > outputs - STRING_ADD_STATIC_TEXT(text, text_len, "Burning: "); - format_u64(text, text_len, value); - } - } - break; - } - } - return SW_OK; -} - bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_output_info_ctx_t* output, From e84fade0a13f0db349b8268989977c2439286f2e Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 17 Oct 2024 15:23:20 +0300 Subject: [PATCH 42/56] Remove is_ui_nbgl_busy from state --- src/context.h | 8 -------- src/ui/display.c | 6 +++--- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/context.h b/src/context.h index 42582cf..88cda12 100644 --- a/src/context.h +++ b/src/context.h @@ -14,7 +14,6 @@ typedef struct { uint8_t session_key[SESSION_KEY_LEN]; command_e current_command; /// current command bool is_ui_busy; - bool is_ui_nbgl_busy; union { attest_input_ctx_t attest_input; sign_transaction_ctx_t sign_tx; @@ -42,13 +41,6 @@ static inline void app_set_ui_busy(bool is_busy) { G_app_context.is_ui_busy = is_busy; } -/** - * Set UI (nbgl) busy - */ -static inline void app_set_nbgl_busy(bool is_busy) { - G_app_context.is_ui_nbgl_busy = is_busy; -} - /** * Get connected application id. */ diff --git a/src/ui/display.c b/src/ui/display.c index e1c02f9..a0dd49a 100644 --- a/src/ui/display.c +++ b/src/ui/display.c @@ -10,7 +10,7 @@ bool flow_response = false; void set_flow_response(bool response) { flow_response = response; - app_set_nbgl_busy(false); + app_set_ui_busy(false); } void io_common_process() { @@ -19,14 +19,14 @@ void io_common_process() { io_seproxyhal_spi_recv(G_io_seproxyhal_spi_buffer, sizeof(G_io_seproxyhal_spi_buffer), 0); io_seproxyhal_handle_event(); io_seproxyhal_general_status(); - } while (io_seproxyhal_spi_is_status_sent() && G_app_context.is_ui_nbgl_busy); + } while (io_seproxyhal_spi_is_status_sent() && app_is_ui_busy()); } bool io_ui_process() { // We are not waiting for the client's input, nor we are doing computations on the device // io_clear_processing_timeout(); - app_set_nbgl_busy(true); + app_set_ui_busy(true); io_common_process(); From 7f336f50fe6d234a33540d75a9a03142da907977 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 17 Oct 2024 15:43:20 +0300 Subject: [PATCH 43/56] Show bip32 path on da ui --- src/commands/deriveaddress/da_ui_nbgl.c | 11 +++++++++-- src/commands/extpubkey/epk_ui_nbgl.c | 7 ++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index 49cb279..b38daa9 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -63,13 +63,20 @@ int ui_display_address(derive_address_ctx_t* ctx, pair_list.nbPairs = n_pairs; pair_list.pairs = pairs_global; + if (!ui_bip32_path_screen(bip32_path, + bip32_path_len, + ctx->bip32_path, + MEMBER_SIZE(derive_address_ctx_t, bip32_path))) { + return res_error(SW_BIP32_BAD_PATH); + } + if (send) { // Confirm Send Address nbgl_useCaseAddressReview(ctx->address, n_pairs == 0 ? NULL : &pair_list, &WHEEL_ICON, "Confirm Send Address", - "", + ctx->bip32_path, ui_display_address_confirm); } else { // Confirm Address @@ -77,7 +84,7 @@ int ui_display_address(derive_address_ctx_t* ctx, n_pairs == 0 ? NULL : &pair_list, &INFO_I_ICON, "Confirm Address", - "", + ctx->bip32_path, ui_display_address_confirm); } diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c index 09d29d2..83d0717 100644 --- a/src/commands/extpubkey/epk_ui_nbgl.c +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -40,9 +40,10 @@ int ui_display_account(extended_public_key_ctx_t* ctx, return res_error(SW_BIP32_BAD_PATH); } - uint path_size = MEMBER_SIZE(extended_public_key_ctx_t, bip32_path); - memset(ctx->bip32_path, 0, path_size); - if (!bip32_path_format(bip32_path, bip32_path_len, ctx->bip32_path, path_size)) { + if (!ui_bip32_path_screen(bip32_path, + bip32_path_len, + ctx->bip32_path, + MEMBER_SIZE(derive_address_ctx_t, bip32_path))) { return res_error(SW_BIP32_BAD_PATH); } From dace38239fb0f64a2e2df3a1df76fb300070c3f2 Mon Sep 17 00:00:00 2001 From: Ivan Date: Thu, 17 Oct 2024 16:19:12 +0300 Subject: [PATCH 44/56] Move ui_stx_display_output_state and ui_stx_display_tx_state to stx_ui_common.c --- src/commands/signtx/stx_ui_common.c | 113 +++++++++++++++++++++++++++ src/commands/signtx/stx_ui_common.h | 114 +--------------------------- 2 files changed, 117 insertions(+), 110 deletions(-) create mode 100644 src/commands/signtx/stx_ui_common.c diff --git a/src/commands/signtx/stx_ui_common.c b/src/commands/signtx/stx_ui_common.c new file mode 100644 index 0000000..8cdfb01 --- /dev/null +++ b/src/commands/signtx/stx_ui_common.c @@ -0,0 +1,113 @@ +#include +#include +#include +#include + +#include "stx_ui_common.h" + +#include "../../ergo/address.h" + +uint16_t ui_stx_display_output_state(uint8_t screen, char* title, char* text, void* context) { + sign_transaction_ui_output_confirm_ctx_t* ctx = + (sign_transaction_ui_output_confirm_ctx_t*) context; + uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, title); + uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, text); + memset(title, 0, title_len); + memset(text, 0, text_len); + + switch (screen) { + case 0: // Output Address Info + return output_info_print_address(ctx->output, + ctx->network_id, + title, + title_len, + text, + text_len); + case 1: { // Output Value + strncpy(title, "Output Value", title_len); + if (!format_erg_amount(ctx->output->value, text, text_len)) { + return SW_BUFFER_ERROR; + } + break; + } + default: { // Tokens + screen -= 2; // Decrease index for info screens + uint8_t token_idx = stx_output_info_used_token_index(ctx->output, screen / 2); + if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state + return SW_BAD_TOKEN_INDEX; + } + if (screen % 2 == 0) { // Token ID + snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); + if (!format_hex_id(ctx->output->tokens_table->tokens[token_idx], + ERGO_ID_LEN, + text, + text_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + } else { // Token Value + snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); + format_u64(text, text_len, ctx->output->tokens[token_idx]); + } + break; + } + } + return SW_OK; +} + +// Callback for TX UI rendering +uint16_t ui_stx_display_tx_state(uint8_t screen, char* title, char* text, void* context) { + sign_transaction_ui_sign_confirm_ctx_t* ctx = (sign_transaction_ui_sign_confirm_ctx_t*) context; + uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, title); + uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, text); + memset(title, 0, title_len); + memset(text, 0, text_len); + + if (screen < ctx->op_screen_count) { // Showing operation screen + return ctx->op_screen_cb(screen, title, title_len, text, text_len, ctx->op_cb_context); + } + screen -= ctx->op_screen_count; + switch (screen) { + case 0: { // TX Value + strncpy(title, "Transaction Amount", title_len); + if (!format_erg_amount(ctx->amounts->value, text, text_len)) { + return SW_BUFFER_ERROR; + } + break; + } + case 1: { // TX Fee + strncpy(title, "Transaction Fee", title_len); + if (!format_erg_amount(ctx->amounts->fee, text, text_len)) { + return SW_BUFFER_ERROR; + } + break; + } + default: { // Tokens + screen -= 2; // Decrease index for info screens + uint8_t token_idx = stx_amounts_non_zero_token_index(ctx->amounts, screen / 2); + if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state + return SW_BAD_TOKEN_INDEX; + } + if (screen % 2 == 0) { // Token ID + snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); + if (!format_hex_id(ctx->amounts->tokens_table.tokens[token_idx], + ERGO_ID_LEN, + text, + text_len)) { + return SW_ADDRESS_FORMATTING_FAILED; + } + } else { // Token Value + snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); + int64_t value = ctx->amounts->tokens[token_idx]; + if (value < 0) { // output > inputs + STRING_ADD_STATIC_TEXT(text, text_len, "Minting: "); + format_u64(text, text_len, -value); + } else { // inputs > outputs + STRING_ADD_STATIC_TEXT(text, text_len, "Burning: "); + format_u64(text, text_len, value); + } + } + break; + } + } + return SW_OK; +} \ No newline at end of file diff --git a/src/commands/signtx/stx_ui_common.h b/src/commands/signtx/stx_ui_common.h index 533fce8..847063e 100644 --- a/src/commands/signtx/stx_ui_common.h +++ b/src/commands/signtx/stx_ui_common.h @@ -5,10 +5,10 @@ #include #include -#include "stx_ui.h" - #include "../../ergo/address.h" +#include "stx_context.h" + #define ERGO_ID_UI_CHARACTERS_HALF 26 #define STRING_ADD_STATIC_TEXT(str, slen, text) \ strncpy(str, text, slen); \ @@ -102,113 +102,7 @@ static inline uint16_t output_info_print_address(const sign_transaction_output_i return SW_OK; } -static NOINLINE uint16_t ui_stx_display_output_state(uint8_t screen, - char* title, - char* text, - void* context) { - sign_transaction_ui_output_confirm_ctx_t* ctx = - (sign_transaction_ui_output_confirm_ctx_t*) context; - uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, title); - uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_output_confirm_ctx_t, text); - memset(title, 0, title_len); - memset(text, 0, text_len); - - switch (screen) { - case 0: // Output Address Info - return output_info_print_address(ctx->output, - ctx->network_id, - title, - title_len, - text, - text_len); - case 1: { // Output Value - strncpy(title, "Output Value", title_len); - if (!format_erg_amount(ctx->output->value, text, text_len)) { - return SW_BUFFER_ERROR; - } - break; - } - default: { // Tokens - screen -= 2; // Decrease index for info screens - uint8_t token_idx = stx_output_info_used_token_index(ctx->output, screen / 2); - if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state - return SW_BAD_TOKEN_INDEX; - } - if (screen % 2 == 0) { // Token ID - snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); - if (!format_hex_id(ctx->output->tokens_table->tokens[token_idx], - ERGO_ID_LEN, - text, - text_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - } else { // Token Value - snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); - format_u64(text, text_len, ctx->output->tokens[token_idx]); - } - break; - } - } - return SW_OK; -} +uint16_t ui_stx_display_output_state(uint8_t screen, char* title, char* text, void* context); // Callback for TX UI rendering -static NOINLINE uint16_t ui_stx_display_tx_state(uint8_t screen, - char* title, - char* text, - void* context) { - sign_transaction_ui_sign_confirm_ctx_t* ctx = (sign_transaction_ui_sign_confirm_ctx_t*) context; - uint8_t title_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, title); - uint8_t text_len = MEMBER_SIZE(sign_transaction_ui_sign_confirm_ctx_t, text); - memset(title, 0, title_len); - memset(text, 0, text_len); - - if (screen < ctx->op_screen_count) { // Showing operation screen - return ctx->op_screen_cb(screen, title, title_len, text, text_len, ctx->op_cb_context); - } - screen -= ctx->op_screen_count; - switch (screen) { - case 0: { // TX Value - strncpy(title, "Transaction Amount", title_len); - if (!format_erg_amount(ctx->amounts->value, text, text_len)) { - return SW_BUFFER_ERROR; - } - break; - } - case 1: { // TX Fee - strncpy(title, "Transaction Fee", title_len); - if (!format_erg_amount(ctx->amounts->fee, text, text_len)) { - return SW_BUFFER_ERROR; - } - break; - } - default: { // Tokens - screen -= 2; // Decrease index for info screens - uint8_t token_idx = stx_amounts_non_zero_token_index(ctx->amounts, screen / 2); - if (!IS_ELEMENT_FOUND(token_idx)) { // error. bad index state - return SW_BAD_TOKEN_INDEX; - } - if (screen % 2 == 0) { // Token ID - snprintf(title, title_len, "Token [%d]", (int) (screen / 2) + 1); - if (!format_hex_id(ctx->amounts->tokens_table.tokens[token_idx], - ERGO_ID_LEN, - text, - text_len)) { - return SW_ADDRESS_FORMATTING_FAILED; - } - } else { // Token Value - snprintf(title, title_len, "Token [%d] Value", (int) (screen / 2) + 1); - int64_t value = ctx->amounts->tokens[token_idx]; - if (value < 0) { // output > inputs - STRING_ADD_STATIC_TEXT(text, text_len, "Minting: "); - format_u64(text, text_len, -value); - } else { // inputs > outputs - STRING_ADD_STATIC_TEXT(text, text_len, "Burning: "); - format_u64(text, text_len, value); - } - } - break; - } - } - return SW_OK; -} \ No newline at end of file +uint16_t ui_stx_display_tx_state(uint8_t screen, char* title, char* text, void* context); \ No newline at end of file From ae5646cac365fd6aac997e26074e133e8aa46056 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 10:04:57 +0300 Subject: [PATCH 45/56] Do not show application id if it's zero --- src/commands/signtx/stx_ui_nbgl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index deabf8b..32be3b6 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -37,7 +37,7 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, int n_pairs = *screen; - if (!is_known_application) { + if (!is_known_application && app_access_token != 0) { pairs_global[n_pairs++] = ui_application_id_screen(app_access_token, ctx->app_token); } From 46aac6924af2746a10bfdc391ea5667bce304def Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 10:28:02 +0300 Subject: [PATCH 46/56] Rework da_ui (single screen) --- src/commands/deriveaddress/da_ui_nbgl.c | 54 +++++++++++++++---------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index b38daa9..cb7abf9 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -20,6 +20,10 @@ #include "../../ui/ui_main.h" #include "../../ui/display.h" +#define PK_APPID_ADDR_SIZE \ + MAX_BIP32_PATH + APPLICATION_ID_STR_LEN + 13 + 1 + P2PK_ADDRESS_STRING_MAX_LEN + 9 + 1 +char pk_appid_addr[PK_APPID_ADDR_SIZE]; + void ui_display_address_confirm(bool approved) { set_flow_response(approved); } @@ -53,16 +57,6 @@ int ui_display_address(derive_address_ctx_t* ctx, } } - int n_pairs = 0; - - if (app_access_token != 0) { - pairs_global[n_pairs++] = ui_application_id_screen(app_access_token, ctx->app_id); - } - - pair_list.nbMaxLinesForValue = 0; - pair_list.nbPairs = n_pairs; - pair_list.pairs = pairs_global; - if (!ui_bip32_path_screen(bip32_path, bip32_path_len, ctx->bip32_path, @@ -70,22 +64,38 @@ int ui_display_address(derive_address_ctx_t* ctx, return res_error(SW_BIP32_BAD_PATH); } + memset(pk_appid_addr, 0, PK_APPID_ADDR_SIZE); + strncpy(pk_appid_addr, ctx->bip32_path, MAX_BIP32_PATH); + int offset = 0; + if (app_access_token != 0) { + pk_appid_addr[MAX_BIP32_PATH] = '\n'; + offset += APPLICATION_ID_STR_LEN + 13; + snprintf(*(&pk_appid_addr) + MAX_BIP32_PATH + 1, + APPLICATION_ID_STR_LEN + 13, + "Application: 0x%08x", + app_access_token); + } + + pk_appid_addr[MAX_BIP32_PATH + offset] = '\n'; + strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1, "Address: ", 9); + strcpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1 + 9, ctx->address); + if (send) { // Confirm Send Address - nbgl_useCaseAddressReview(ctx->address, - n_pairs == 0 ? NULL : &pair_list, - &WHEEL_ICON, - "Confirm Send Address", - ctx->bip32_path, - ui_display_address_confirm); + nbgl_useCaseChoice(&WHEEL_ICON, + "Address Export", + pk_appid_addr, + "Confirm", + "Cancel", + ui_display_address_confirm); } else { // Confirm Address - nbgl_useCaseAddressReview(ctx->address, - n_pairs == 0 ? NULL : &pair_list, - &INFO_I_ICON, - "Confirm Address", - ctx->bip32_path, - ui_display_address_confirm); + nbgl_useCaseChoice(&INFO_I_ICON, + "Confirm Address", + pk_appid_addr, + "Confirm", + "Cancel", + ui_display_address_confirm); } memmove(ctx->raw_address, raw_address, P2PK_ADDRESS_LEN); From 7ca5ca9d783af9d2696018b0c6ccca4c824d7fac Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 10:33:54 +0300 Subject: [PATCH 47/56] Fix --- src/commands/deriveaddress/da_ui_nbgl.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index cb7abf9..0c1d9bc 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -76,9 +76,11 @@ int ui_display_address(derive_address_ctx_t* ctx, app_access_token); } - pk_appid_addr[MAX_BIP32_PATH + offset] = '\n'; - strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1, "Address: ", 9); - strcpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1 + 9, ctx->address); + if (!send) { + pk_appid_addr[MAX_BIP32_PATH + offset] = '\n'; + strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1, "Address: ", 9); + strcpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1 + 9, ctx->address); + } if (send) { // Confirm Send Address From 22ffb41eefa7cc4bd3a6793a16ef36a6e08d5a75 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 10:43:19 +0300 Subject: [PATCH 48/56] Reject/confirm notification UI --- src/commands/signtx/stx_ui_nbgl.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index 32be3b6..1cf7ea7 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -28,6 +28,10 @@ static NOINLINE void ui_stx_operation_approve_action(bool approved) { set_flow_response(approved); } +static NOINLINE void quit_callback(void) { + set_flow_response(true); +} + bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, uint8_t* screen, uint32_t app_access_token, @@ -189,11 +193,15 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, if (approved) { ctx->op_response_cb(ctx->op_cb_context); + app_set_current_command(CMD_NONE); + nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_SIGNED, quit_callback); } else { res_deny(); + app_set_current_command(CMD_NONE); + nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_REJECTED, quit_callback); } - app_set_current_command(CMD_NONE); + io_ui_process(); ui_menu_main(); return true; From b1f4350624adad0c16bbf892e9d4707df5b59e5d Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 10:44:47 +0300 Subject: [PATCH 49/56] Change review status type --- src/commands/signtx/stx_ui_nbgl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index 1cf7ea7..e860dd3 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -194,11 +194,11 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, if (approved) { ctx->op_response_cb(ctx->op_cb_context); app_set_current_command(CMD_NONE); - nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_SIGNED, quit_callback); + nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_SIGNED, quit_callback); } else { res_deny(); app_set_current_command(CMD_NONE); - nbgl_useCaseReviewStatus(STATUS_TYPE_MESSAGE_REJECTED, quit_callback); + nbgl_useCaseReviewStatus(STATUS_TYPE_TRANSACTION_REJECTED, quit_callback); } io_ui_process(); From c84b1b81174d02be7290d22dc733ea3fda0787e9 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 11:51:17 +0300 Subject: [PATCH 50/56] Change sign tx icon to app logo --- src/commands/signtx/operations/stx_op_p2pk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/signtx/operations/stx_op_p2pk.c b/src/commands/signtx/operations/stx_op_p2pk.c index 1e8d350..a2c61bd 100644 --- a/src/commands/signtx/operations/stx_op_p2pk.c +++ b/src/commands/signtx/operations/stx_op_p2pk.c @@ -368,7 +368,7 @@ uint16_t ui_stx_operation_p2pk_show_token_and_path(sign_transaction_operation_p2 // pairs_global[0].value = ctx->ui_approve.bip32_path; // screen++; nbgl_useCaseReviewStreamingStart(TYPE_TRANSACTION, - &VALIDATE_ICON, + &C_app_logo_64px, "P2PK Signing", ctx->ui_approve.bip32_path, p2pk_review); From 790361449c55cbec115d6c7aa7acfe4b98534766 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 12:48:47 +0300 Subject: [PATCH 51/56] Reworked streaming ui to allow back button in certain cases --- src/commands/signtx/stx_ui_nbgl.c | 132 ++++++++++++++++-------------- 1 file changed, 70 insertions(+), 62 deletions(-) diff --git a/src/commands/signtx/stx_ui_nbgl.c b/src/commands/signtx/stx_ui_nbgl.c index e860dd3..b0f454c 100644 --- a/src/commands/signtx/stx_ui_nbgl.c +++ b/src/commands/signtx/stx_ui_nbgl.c @@ -64,6 +64,25 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, return true; } +static nbgl_layoutTagValue_t pair; +static sign_transaction_ui_output_confirm_ctx_t* output_screen_ctx = NULL; + +static nbgl_layoutTagValue_t* getOutputPair(uint8_t index) { + if ((index + 1) % 3 == 0) { + pair.item = ""; + pair.value = ""; + } else { + pair.item = pair_mem_title[index]; + pair.value = pair_mem_text[index]; + + ui_stx_display_output_state(index - index / 3, + pair_mem_title[index], + pair_mem_text[index], + (void*) output_screen_ctx); + } + return &pair; +} + bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_output_info_ctx_t* output, @@ -86,38 +105,25 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, ctx->output = output; ctx->last_approved_change = last_approved_change; - int n_pairs = *screen; - bool approved = false; - - for (int i = 0; i < info_screen_count; i++) { - pairs_global[n_pairs].item = pair_mem_title[n_pairs]; - pairs_global[n_pairs].value = pair_mem_text[n_pairs]; - ui_stx_display_output_state(i, - pair_mem_title[n_pairs], - pair_mem_text[n_pairs], - (void*) ctx); - // empty row (split screens for tokens) - if ((n_pairs + 1) % 2 == 0) { - n_pairs++; - pair_list.nbMaxLinesForValue = 0; - pair_list.nbPairs = n_pairs; - pair_list.pairs = pairs_global; - - nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); - approved = io_ui_process(); - app_set_ui_busy(false); - - n_pairs = 0; - - if (!approved) { - app_set_current_command(CMD_NONE); - res_deny(); - ui_menu_main(); - return true; - } - } else { - n_pairs++; - } + pair_list.nbMaxLinesForValue = 0; + pair_list.pairs = NULL; + pair_list.nbPairs = info_screen_count + info_screen_count / 2; + pair_list.callback = getOutputPair; + pair_list.startIndex = 0; + + output_screen_ctx = ctx; + + nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); + + bool approved = io_ui_process(); + app_set_ui_busy(false); + output_screen_ctx = NULL; + + if (!approved) { + app_set_current_command(CMD_NONE); + res_deny(); + ui_menu_main(); + return true; } explicit_bzero(ctx->last_approved_change, sizeof(sign_transaction_bip32_path_t)); @@ -135,6 +141,19 @@ bool ui_stx_add_output_screens(sign_transaction_ui_output_confirm_ctx_t* ctx, return true; } +static sign_transaction_ui_sign_confirm_ctx_t* sign_confirm_screen_ctx = NULL; + +static nbgl_layoutTagValue_t* getSignConfirmPair(uint8_t index) { + pair.item = pair_mem_title[index]; + pair.value = pair_mem_text[index]; + + ui_stx_display_tx_state(index, + pair_mem_title[index], + pair_mem_text[index], + (void*) sign_confirm_screen_ctx); + return &pair; +} + bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, uint8_t* screen, const sign_transaction_amounts_ctx_t* amounts, @@ -154,36 +173,25 @@ bool ui_stx_add_transaction_screens(sign_transaction_ui_sign_confirm_ctx_t* ctx, ctx->op_cb_context = cb_context; ctx->amounts = amounts; - int n_pairs = *screen; - bool approved = false; - - for (int i = 0; i < op_screen_count + 2 + (2 * tokens_count); i++) { - pairs_global[n_pairs].item = pair_mem_title[n_pairs]; - pairs_global[n_pairs].value = pair_mem_text[n_pairs]; - ui_stx_display_tx_state(i, pair_mem_title[n_pairs], pair_mem_text[n_pairs], (void*) ctx); - // empty row (split screens for tokens) - if (((n_pairs + 1) % 2 == 0 && i != 1) || - i == 2) { // first page should contain 3 rows, other 2 - n_pairs++; - pair_list.nbMaxLinesForValue = 0; - pair_list.nbPairs = n_pairs; - pair_list.pairs = pairs_global; - - nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); - approved = io_ui_process(); - app_set_ui_busy(false); - - if (!approved) { - res_deny(); - app_set_current_command(CMD_NONE); - ui_menu_main(); - return true; - } - - n_pairs = 0; - } else { - n_pairs++; - } + pair_list.nbMaxLinesForValue = 0; + pair_list.pairs = NULL; + pair_list.nbPairs = op_screen_count + 2 + (2 * tokens_count); + pair_list.callback = getSignConfirmPair; + pair_list.startIndex = 0; + + sign_confirm_screen_ctx = ctx; + + nbgl_useCaseReviewStreamingContinue(&pair_list, ui_stx_operation_approve_action); + + bool approved = io_ui_process(); + app_set_ui_busy(false); + sign_confirm_screen_ctx = NULL; + + if (!approved) { + res_deny(); + app_set_current_command(CMD_NONE); + ui_menu_main(); + return true; } if (MAX_NUMBER_OF_SCREENS - *screen < 2) return false; From e19d4b40f947cf0cd2a78d2e1d7af8cad87615c9 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 12:53:00 +0300 Subject: [PATCH 52/56] CLang warning fix --- src/commands/deriveaddress/da_ui_nbgl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index 0c1d9bc..194ff10 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -79,7 +79,7 @@ int ui_display_address(derive_address_ctx_t* ctx, if (!send) { pk_appid_addr[MAX_BIP32_PATH + offset] = '\n'; strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1, "Address: ", 9); - strcpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1 + 9, ctx->address); + strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1 + 9, ctx->address, MEMBER_SIZE(derive_address_ctx_t, address)); } if (send) { From ce1b6e1e18e556ebb3b212350be30728b4260b64 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 12:53:10 +0300 Subject: [PATCH 53/56] Lint --- src/commands/deriveaddress/da_ui_nbgl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index 194ff10..902667a 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -79,7 +79,9 @@ int ui_display_address(derive_address_ctx_t* ctx, if (!send) { pk_appid_addr[MAX_BIP32_PATH + offset] = '\n'; strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1, "Address: ", 9); - strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1 + 9, ctx->address, MEMBER_SIZE(derive_address_ctx_t, address)); + strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1 + 9, + ctx->address, + MEMBER_SIZE(derive_address_ctx_t, address)); } if (send) { From b31060fba87a75553ca430d33f8cdaec95a4ac02 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 16:04:57 +0300 Subject: [PATCH 54/56] Fix: do not show app id if it's zero (bagl) --- src/commands/signtx/stx_ui_bagl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/signtx/stx_ui_bagl.c b/src/commands/signtx/stx_ui_bagl.c index dc3ec34..07c67c1 100644 --- a/src/commands/signtx/stx_ui_bagl.c +++ b/src/commands/signtx/stx_ui_bagl.c @@ -52,7 +52,7 @@ bool ui_stx_add_operation_approve_screens(sign_transaction_ui_aprove_ctx_t* ctx, sign_transaction_ctx_t* sign_tx) { if (MAX_NUMBER_OF_SCREENS - *screen < 3) return false; - if (!is_known_application) { + if (!is_known_application && app_access_token != 0) { ui_add_screen(ui_application_id_screen(app_access_token, ctx->app_token), screen); } ctx->app_token_value = app_access_token; From e2766d7468c55ccf53bc959ac002440bba818a7d Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 16:29:21 +0300 Subject: [PATCH 55/56] Fix test --- tests/transaction-tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/transaction-tests.js b/tests/transaction-tests.js index b5b7589..66f42e2 100644 --- a/tests/transaction-tests.js +++ b/tests/transaction-tests.js @@ -18,9 +18,9 @@ function signTxFlows({ device }, auth, from, to, change, tokens_to = undefined, flows[i++].push({ header: null, body: 'Approve' }, { header: null, body: 'Reject' }); // accept tx screen flows[i] = [{ header: 'P2PK Signing', body: removeMasterNode(from.path.toString()) }]; - if (!auth) { + /*if (!auth) { flows[i].push({ header: 'Application', body: '0x00000000' }); - } + }*/ flows[i++].push({ header: null, body: 'Approve' }, { header: null, body: 'Reject' }); // output screen if (to) { From fd44e8b2850f039f836b9a3fc9cf90ff716ddc54 Mon Sep 17 00:00:00 2001 From: Ivan Date: Fri, 18 Oct 2024 17:08:43 +0300 Subject: [PATCH 56/56] Fixed pk display on da/epk screens --- src/commands/deriveaddress/da_ui_nbgl.c | 16 +++++++++------- src/commands/extpubkey/epk_ui_nbgl.c | 10 ++++++---- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/commands/deriveaddress/da_ui_nbgl.c b/src/commands/deriveaddress/da_ui_nbgl.c index 902667a..f89fa96 100644 --- a/src/commands/deriveaddress/da_ui_nbgl.c +++ b/src/commands/deriveaddress/da_ui_nbgl.c @@ -21,7 +21,7 @@ #include "../../ui/display.h" #define PK_APPID_ADDR_SIZE \ - MAX_BIP32_PATH + APPLICATION_ID_STR_LEN + 13 + 1 + P2PK_ADDRESS_STRING_MAX_LEN + 9 + 1 + MAX_BIP32_STRING_LEN + APPLICATION_ID_STR_LEN + 13 + 1 + P2PK_ADDRESS_STRING_MAX_LEN + 9 + 1 char pk_appid_addr[PK_APPID_ADDR_SIZE]; void ui_display_address_confirm(bool approved) { @@ -64,22 +64,24 @@ int ui_display_address(derive_address_ctx_t* ctx, return res_error(SW_BIP32_BAD_PATH); } + int bip32_str_len = strlen(ctx->bip32_path); + memset(pk_appid_addr, 0, PK_APPID_ADDR_SIZE); - strncpy(pk_appid_addr, ctx->bip32_path, MAX_BIP32_PATH); + strncpy(pk_appid_addr, ctx->bip32_path, bip32_str_len); int offset = 0; if (app_access_token != 0) { - pk_appid_addr[MAX_BIP32_PATH] = '\n'; + pk_appid_addr[bip32_str_len] = '\n'; offset += APPLICATION_ID_STR_LEN + 13; - snprintf(*(&pk_appid_addr) + MAX_BIP32_PATH + 1, + snprintf(*(&pk_appid_addr) + bip32_str_len + 1, APPLICATION_ID_STR_LEN + 13, "Application: 0x%08x", app_access_token); } if (!send) { - pk_appid_addr[MAX_BIP32_PATH + offset] = '\n'; - strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1, "Address: ", 9); - strncpy(*(&pk_appid_addr) + MAX_BIP32_PATH + offset + 1 + 9, + pk_appid_addr[bip32_str_len + offset] = '\n'; + strncpy(*(&pk_appid_addr) + bip32_str_len + offset + 1, "Address: ", 9); + strncpy(*(&pk_appid_addr) + bip32_str_len + offset + 1 + 9, ctx->address, MEMBER_SIZE(derive_address_ctx_t, address)); } diff --git a/src/commands/extpubkey/epk_ui_nbgl.c b/src/commands/extpubkey/epk_ui_nbgl.c index 83d0717..3813081 100644 --- a/src/commands/extpubkey/epk_ui_nbgl.c +++ b/src/commands/extpubkey/epk_ui_nbgl.c @@ -23,7 +23,7 @@ void ui_display_account_confirm(bool approved) { set_flow_response(approved); } -#define PK_APPID_SIZE MAX_BIP32_PATH + APPLICATION_ID_STR_LEN + 13 + 1 +#define PK_APPID_SIZE MAX_BIP32_STRING_LEN + APPLICATION_ID_STR_LEN + 13 + 1 char pk_appid[PK_APPID_SIZE]; int ui_display_account(extended_public_key_ctx_t* ctx, @@ -47,11 +47,13 @@ int ui_display_account(extended_public_key_ctx_t* ctx, return res_error(SW_BIP32_BAD_PATH); } + int bip32_str_len = strlen(ctx->bip32_path); + memset(pk_appid, 0, PK_APPID_SIZE); - strncpy(pk_appid, ctx->bip32_path, MAX_BIP32_PATH); + strncpy(pk_appid, ctx->bip32_path, bip32_str_len); if (app_access_token != 0) { - pk_appid[MAX_BIP32_PATH] = '\n'; - snprintf(*(&pk_appid) + MAX_BIP32_PATH + 1, + pk_appid[bip32_str_len] = '\n'; + snprintf(*(&pk_appid) + bip32_str_len + 1, APPLICATION_ID_STR_LEN + 13, "Application: 0x%08x", app_access_token);