From 9883d3fdfef17d30534b5cf1a13d1149e2ec67eb Mon Sep 17 00:00:00 2001 From: Aido Date: Mon, 13 Nov 2023 19:58:32 +0000 Subject: [PATCH] Tidy up code that sets 'Processing' screen on Nano devices Fixes #10 Signed-off-by: Aido --- CHANGELOG.md | 10 ++- Makefile | 6 +- TODO.md | 1 + icons/seed_tool.png | Bin 8597 -> 7666 bytes src/bc-sskr/bc-shamir/shamir.c | 6 +- src/bc-sskr/bc-shamir/shamir.h | 4 +- src/bc-sskr/sskr.c | 119 ++++++++++++++------------- src/bc-sskr/sskr.h | 34 ++++---- src/main.c | 4 +- src/nano/nanos_enter_phrase.c | 16 ++-- src/nano/nanox_enter_phrase.c | 10 ++- src/nano/ux_nano.h | 8 +- src/nano/ux_nano_bip39.c | 10 +-- src/nano/ux_nano_sskr.c | 24 +++--- src/ux_common/onboarding_seed_sskr.c | 12 ++- tests/unit/tests/roundtrip.c | 10 +-- tests/unit/tests/shamir.c | 12 +-- tests/unit/tests/sskr.c | 32 +++---- 18 files changed, 170 insertions(+), 148 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b2fd99e..ff106bf8 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,17 @@ # Change log -## [1.5.2] - 2023-11-10 +## [1.5.2] - 2023-11-13 ### Added - ### Changed -- - -### Fixed - Save memory by setting the SSKR word buffer to a sensible size - There is just enough memory available on Nano S to hold the phrases for 10 shares. Other devices can hold the full 16 shares. +- Tidy up code that sets 'Processing' screen on Nano devices + + +### Fixed +- Fix screen freezing at 'Processing' screen on Nano devices ## [1.5.1] - 2023-11-09 ### Added diff --git a/Makefile b/Makefile index 764030a3..da9d8769 100755 --- a/Makefile +++ b/Makefile @@ -35,12 +35,10 @@ APP_LOAD_PARAMS = --appFlags 0x10 $(COMMON_LOAD_PARAMS) --curve secp256k1 --path ifeq ($(TARGET_NAME), TARGET_NANOS) ICONNAME=glyphs/seed_nanos.gif -else ifeq ($(TARGET_NAME), TARGET_NANOX) - ICONNAME=glyphs/seed_nanox.gif -else ifeq ($(TARGET_NAME), TARGET_NANOS2) - ICONNAME=glyphs/seed_nanox.gif else ifeq ($(TARGET_NAME), TARGET_STAX) ICONNAME=glyphs/seed_stax_32px.gif +else + ICONNAME=glyphs/seed_nanox.gif endif # Build configuration diff --git a/TODO.md b/TODO.md index c6e3f1de..75d0f43a 100755 --- a/TODO.md +++ b/TODO.md @@ -6,6 +6,7 @@ - [ ] There is just enough memory available on Nano S to hold the phrases for 10 shares. Maybe just store SSKR Bytewords as shorter two letter minimal Bytewords rather than a 4 letter Byteword plus space for each share. Convert minimal ByteWords back to four letter Bytewords just prior to display. - [ ] If/when the `cx_bn_gf2_n_mul()` syscall is available on Ledger Nano S change all Galois Field functionality to use syscalls. - See [gf_syscalls](https://github.com/aido/app-seed-tool/tree/gf_syscalls) branch of repo. +- Remove all variable length arrays ### In Progress diff --git a/icons/seed_tool.png b/icons/seed_tool.png index ef43a64fbec980b63eb5a492b1de6f4067062880..87a7685741631a8d6ce2c83be60de437e7aea035 100644 GIT binary patch delta 1011 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 SHAMIR_MAX_SHARE_COUNT) { return SHAMIR_ERROR_TOO_MANY_SHARES; } else if (threshold < 1 || threshold > share_count) { @@ -49,7 +49,7 @@ static int32_t validate_parameters(uint8_t threshold, uint8_t share_count, uint8 ////////////////////////////////////////////////// // shamir sharing -int32_t shamir_split_secret(uint8_t threshold, +int16_t shamir_split_secret(uint8_t threshold, uint8_t share_count, const uint8_t *secret, uint8_t secret_length, @@ -110,7 +110,7 @@ int32_t shamir_split_secret(uint8_t threshold, // returns the number of bytes written to the secret array, or a negative value if there was an // error -int32_t shamir_recover_secret(uint8_t threshold, +int16_t shamir_recover_secret(uint8_t threshold, const uint8_t *x, const uint8_t **shares, uint8_t share_length, diff --git a/src/bc-sskr/bc-shamir/shamir.h b/src/bc-sskr/bc-shamir/shamir.h index 2e758c12..a1024d38 100644 --- a/src/bc-sskr/bc-shamir/shamir.h +++ b/src/bc-sskr/bc-shamir/shamir.h @@ -46,7 +46,7 @@ uint8_t *create_digest(const uint8_t *random_data, * secret secret_length: length of the secret array. must be >= 16, <= 32 and even. result: place to * store the resulting shares. Must be able to hold share_count * secret_length bytes */ -int32_t shamir_split_secret(uint8_t threshold, +int16_t shamir_split_secret(uint8_t threshold, uint8_t share_count, const uint8_t *secret, uint8_t secret_length, @@ -65,7 +65,7 @@ int32_t shamir_split_secret(uint8_t threshold, * share_length: number of bytes in each y value array * secret: array for writing results (must be at least share_length long) */ -int32_t shamir_recover_secret(uint8_t threshold, +int16_t shamir_recover_secret(uint8_t threshold, const uint8_t *x, const uint8_t **shares, uint8_t share_length, diff --git a/src/bc-sskr/sskr.c b/src/bc-sskr/sskr.c index db6fc620..7bbb6501 100644 --- a/src/bc-sskr/sskr.c +++ b/src/bc-sskr/sskr.c @@ -15,7 +15,7 @@ #define memzero(...) explicit_bzero(__VA_ARGS__) -static int check_secret_length(uint8_t len) { +static int16_t check_secret_length(uint8_t len) { if (len < SSKR_MIN_STRENGTH_BYTES) { return SSKR_ERROR_SECRET_TOO_SHORT; } @@ -28,7 +28,9 @@ static int check_secret_length(uint8_t len) { return 0; } -static int serialize_shard(const sskr_shard *shard, uint8_t *destination, size_t destination_len) { +static int16_t serialize_shard(const sskr_shard *shard, + uint8_t *destination, + uint16_t destination_len) { if (destination_len < SSKR_METADATA_LENGTH_BYTES + shard->value_len) { return SSKR_ERROR_INSUFFICIENT_SPACE; } @@ -66,7 +68,7 @@ static int serialize_shard(const sskr_shard *shard, uint8_t *destination, size_t return shard->value_len + SSKR_METADATA_LENGTH_BYTES; } -static int deserialize_shard(const uint8_t *source, size_t source_len, sskr_shard *shard) { +static int16_t deserialize_shard(const uint8_t *source, uint16_t source_len, sskr_shard *shard) { if (source_len < SSKR_MIN_SERIALIZED_LENGTH_BYTES) { return SSKR_ERROR_NOT_ENOUGH_SERIALIZED_BYTES; } @@ -91,16 +93,16 @@ static int deserialize_shard(const uint8_t *source, size_t source_len, sskr_shar shard->value_len = source_len - SSKR_METADATA_LENGTH_BYTES; memcpy(shard->value, source + SSKR_METADATA_LENGTH_BYTES, shard->value_len); - int err = check_secret_length(shard->value_len); + int16_t err = check_secret_length(shard->value_len); if (err) { return err; } return shard->value_len; } -int sskr_count_shards(uint8_t group_threshold, - const sskr_group_descriptor *groups, - uint8_t groups_len) { +int16_t sskr_count_shards(uint8_t group_threshold, + const sskr_group_descriptor *groups, + uint8_t groups_len) { uint8_t shard_count = 0; if (groups_len < 1) { @@ -130,21 +132,21 @@ int sskr_count_shards(uint8_t group_threshold, ////////////////////////////////////////////////// // generate shards // -static int generate_shards(uint8_t group_threshold, - const sskr_group_descriptor *groups, - uint8_t groups_len, - const uint8_t *master_secret, - size_t master_secret_len, - sskr_shard *shards, - uint16_t shards_size, - unsigned char *(*random_generator)(uint8_t *, size_t)) { - int err = check_secret_length(master_secret_len); +static int16_t generate_shards(uint8_t group_threshold, + const sskr_group_descriptor *groups, + uint8_t groups_len, + const uint8_t *master_secret, + uint16_t master_secret_len, + sskr_shard *shards, + uint16_t shards_size, + unsigned char *(*random_generator)(uint8_t *, size_t)) { + int16_t err = check_secret_length(master_secret_len); if (err) { return err; } // Figure out how many shards we are dealing with - int total_shards = sskr_count_shards(group_threshold, groups, groups_len); + int16_t total_shards = sskr_count_shards(group_threshold, groups, groups_len); if (total_shards < 0) { return total_shards; } @@ -172,7 +174,7 @@ static int generate_shards(uint8_t group_threshold, uint8_t *group_share = group_shares; - unsigned int shards_count = 0; + uint16_t shards_count = 0; sskr_shard *shard; for (uint8_t i = 0; i < groups_len; ++i, group_share += master_secret_len) { @@ -215,34 +217,34 @@ static int generate_shards(uint8_t group_threshold, ////////////////////////////////////////////////// // generate mnemonics // -int sskr_generate(uint8_t group_threshold, - const sskr_group_descriptor *groups, - uint8_t groups_len, - const uint8_t *master_secret, - size_t master_secret_len, - uint8_t *shard_len, - uint8_t *output, - size_t buffer_size, - unsigned char *(*random_generator)(uint8_t *, size_t)) { - int err = check_secret_length(master_secret_len); +int16_t sskr_generate(uint8_t group_threshold, + const sskr_group_descriptor *groups, + uint8_t groups_len, + const uint8_t *master_secret, + uint16_t master_secret_len, + uint8_t *shard_len, + uint8_t *output, + uint16_t buffer_size, + unsigned char *(*random_generator)(uint8_t *, size_t)) { + int16_t err = check_secret_length(master_secret_len); if (err) { return err; } // Figure out how many shards we are dealing with - int total_shards = sskr_count_shards(group_threshold, groups, groups_len); + int16_t total_shards = sskr_count_shards(group_threshold, groups, groups_len); if (total_shards < 0) { return total_shards; } // figure out how much space we need to store all of the mnemonics // and make sure that we were provided with sufficient resources - size_t shard_length = SSKR_METADATA_LENGTH_BYTES + master_secret_len; + uint16_t shard_length = SSKR_METADATA_LENGTH_BYTES + master_secret_len; if (buffer_size < shard_length * total_shards) { return SSKR_ERROR_INSUFFICIENT_SPACE; } - int error = 0; + int16_t error = 0; // allocate space for shard representations sskr_shard shards[total_shards]; @@ -262,11 +264,11 @@ int sskr_generate(uint8_t group_threshold, } uint8_t *cur_output = output; - unsigned int remaining_buffer = buffer_size; - unsigned int byte_count = 0; + uint16_t remaining_buffer = buffer_size; + uint16_t byte_count = 0; - for (size_t i = 0; !error && i < (unsigned int) total_shards; ++i) { - int bytes = serialize_shard(&shards[i], cur_output, remaining_buffer); + for (uint16_t i = 0; !error && i < (uint16_t) total_shards; ++i) { + int16_t bytes = serialize_shard(&shards[i], cur_output, remaining_buffer); if (bytes < 0) { error = bytes; break; @@ -287,9 +289,9 @@ int sskr_generate(uint8_t group_threshold, } typedef struct sskr_group_struct { - size_t group_index; - size_t member_threshold; - size_t count; + uint8_t group_index; + uint8_t member_threshold; + uint8_t count; uint8_t member_index[16]; const uint8_t *value[16]; } sskr_group; @@ -299,12 +301,13 @@ typedef struct sskr_group_struct { * in place, so it is for internal use only, however it provides the implementation * for both combine_shards and sskr_combine. */ -static int combine_shards_internal(sskr_shard *shards, // array of shard structures - uint8_t shards_count, // number of shards in array - uint8_t *buffer, // working space, and place to return secret - size_t buffer_len // total amount of working space +static int16_t combine_shards_internal( + sskr_shard *shards, // array of shard structures + uint8_t shards_count, // number of shards in array + uint8_t *buffer, // working space, and place to return secret + uint16_t buffer_len // total amount of working space ) { - int error = 0; + int16_t error = 0; uint16_t identifier = 0; uint8_t group_threshold = 0; uint8_t group_count = 0; @@ -315,7 +318,7 @@ static int combine_shards_internal(sskr_shard *shards, // array of shard stru uint8_t next_group = 0; sskr_group groups[16]; - size_t secret_len = 0; + uint8_t secret_len = 0; for (uint8_t i = 0; i < shards_count; ++i) { sskr_shard *shard = &shards[i]; @@ -389,11 +392,11 @@ static int combine_shards_internal(sskr_shard *shards, // array of shard stru break; } - int recovery = shamir_recover_secret(g->member_threshold, - g->member_index, - g->value, - secret_len, - group_share); + int16_t recovery = shamir_recover_secret(g->member_threshold, + g->member_index, + g->value, + secret_len, + group_share); if (recovery < 0) { error = recovery; @@ -404,7 +407,7 @@ static int combine_shards_internal(sskr_shard *shards, // array of shard stru group_share += recovery; } - int recovery = 0; + int16_t recovery = 0; if (!error) { recovery = shamir_recover_secret(group_threshold, gx, gy, secret_len, group_share); } @@ -434,13 +437,13 @@ static int combine_shards_internal(sskr_shard *shards, // array of shard stru ///////////////////////////////////////////////// // sskr_combine -int sskr_combine(const uint8_t **input_shards, // array of pointers to 10-bit words - uint8_t shard_len, // number of bytes in each serialized shard - uint8_t shards_count, // total number of shards - uint8_t *buffer, // working space, and place to return secret - size_t buffer_len // total amount of working space +int16_t sskr_combine(const uint8_t **input_shards, // array of pointers to 10-bit words + uint8_t shard_len, // number of bytes in each serialized shard + uint8_t shards_count, // total number of shards + uint8_t *buffer, // working space, and place to return secret + uint16_t buffer_len // total amount of working space ) { - int result = 0; + int16_t result = 0; if (shards_count == 0) { return SSKR_ERROR_EMPTY_SHARD_SET; @@ -448,10 +451,10 @@ int sskr_combine(const uint8_t **input_shards, // array of pointers to 10-bit w sskr_shard shards[shards_count]; - for (unsigned int i = 0; !result && i < shards_count; ++i) { + for (uint16_t i = 0; !result && i < shards_count; ++i) { shards[i].value_len = 32; - int bytes = deserialize_shard(input_shards[i], shard_len, &shards[i]); + int16_t bytes = deserialize_shard(input_shards[i], shard_len, &shards[i]); if (bytes < 0) { result = bytes; diff --git a/src/bc-sskr/sskr.h b/src/bc-sskr/sskr.h index 678a0c30..26491c46 100644 --- a/src/bc-sskr/sskr.h +++ b/src/bc-sskr/sskr.h @@ -14,9 +14,9 @@ #include "sskr-constants.h" #include "group.h" -int sskr_count_shards(uint8_t group_threshold, - const sskr_group_descriptor *groups, - uint8_t groups_len); +int16_t sskr_count_shards(uint8_t group_threshold, + const sskr_group_descriptor *groups, + uint8_t groups_len); /** * generate a set of shards that can be used to reconstruct a secret @@ -39,15 +39,15 @@ int sskr_count_shards(uint8_t group_threshold, * output[i*shard_len]..output[(i+1)*shard_len -1] * buffer_size: maximum number of bytes to write to the output array */ -int sskr_generate(uint8_t group_threshold, - const sskr_group_descriptor *groups, - uint8_t groups_length, - const uint8_t *master_secret, - size_t master_secret_length, - uint8_t *shard_len, - uint8_t *output, - size_t buffer_size, - unsigned char *(*random_generator)(uint8_t *, size_t)); +int16_t sskr_generate(uint8_t group_threshold, + const sskr_group_descriptor *groups, + uint8_t groups_length, + const uint8_t *master_secret, + uint16_t master_secret_length, + uint8_t *shard_len, + uint8_t *output, + uint16_t buffer_size, + unsigned char *(*random_generator)(uint8_t *, size_t)); /** * combine a set of serialized shards to reconstruct a secret @@ -61,11 +61,11 @@ int sskr_generate(uint8_t group_threshold, * buffer: location to store the result * buffer_length: maximum space available in buffer */ -int sskr_combine(const uint8_t **input_shards, // an array of pointers to serialized shards - uint8_t shard_len, // number of bytes in each serialized shard - uint8_t shards_count, // total number of shards - uint8_t *buffer, // working space, and place to return secret - size_t buffer_length // total amount of working space +int16_t sskr_combine(const uint8_t **input_shards, // an array of pointers to serialized shards + uint8_t shard_len, // number of bytes in each serialized shard + uint8_t shards_count, // total number of shards + uint8_t *buffer, // working space, and place to return secret + uint16_t buffer_length // total amount of working space ); #endif /* SSKR_H */ diff --git a/src/main.c b/src/main.c index 271e5e3b..9c0f7134 100644 --- a/src/main.c +++ b/src/main.c @@ -93,8 +93,10 @@ unsigned char io_event(unsigned char channel __attribute__((unused))) { (os_seph_features() & SEPROXYHAL_TAG_SESSION_START_EVENT_FEATURE_SCREEN_BIG)) { UX_REDISPLAY(); } else { - if (G_bolos_ux_context.processing == 1) { + if (G_bolos_ux_context.processing == PROCESSING_COMPARE_RECOVERY_PHRASE) { UX_DISPLAYED_EVENT(compare_recovery_phrase();); + } else if (G_bolos_ux_context.processing == PROCESSING_GENERATE_SSKR) { + UX_DISPLAYED_EVENT(generate_sskr();); } else { UX_DISPLAYED_EVENT(); } diff --git a/src/nano/nanos_enter_phrase.c b/src/nano/nanos_enter_phrase.c index 6bc770f0..284d8033 100644 --- a/src/nano/nanos_enter_phrase.c +++ b/src/nano/nanos_enter_phrase.c @@ -418,7 +418,7 @@ const bagl_element_t* screen_onboarding_restore_word_before_element_display_call } void compare_recovery_phrase(void) { - G_bolos_ux_context.processing = 0; + G_bolos_ux_context.processing = PROCESSING_COMPLETE; io_seproxyhal_general_status(); // convert mnemonic to hex-seed @@ -448,8 +448,14 @@ void compare_recovery_phrase(void) { // get rootkey from device's seed uint8_t buffer_device[64]; - if (os_derive_bip32_no_throw(CX_CURVE_256K1, NULL, 0, buffer_device, buffer_device + 32) != - CX_OK) { + // os_derive_bip32* do not accept NULL path, even with a size of 0, so we provide an empty path + const unsigned int empty_path = 0; + + if (os_derive_bip32_no_throw(CX_CURVE_256K1, + &empty_path, + 0, + buffer_device, + buffer_device + 32) != CX_OK) { PRINTF("An error occurred while comparing the recovery phrase\n"); return; } @@ -555,7 +561,7 @@ void screen_onboarding_restore_word_validate(void) { // alright, the recovery phrase looks ok, finish onboarding // Display processing warning to user screen_processing_init(); - G_bolos_ux_context.processing = 1; + G_bolos_ux_context.processing = PROCESSING_COMPARE_RECOVERY_PHRASE; } } else { // add a space before next word @@ -588,7 +594,7 @@ void screen_onboarding_restore_word_validate(void) { // alright, the recovery phrase looks ok, finish onboarding // Display processing warning to user screen_processing_init(); - G_bolos_ux_context.processing = 1; + G_bolos_ux_context.processing = PROCESSING_COMPARE_RECOVERY_PHRASE; } } } else { diff --git a/src/nano/nanox_enter_phrase.c b/src/nano/nanox_enter_phrase.c index 613ac217..e945ef91 100644 --- a/src/nano/nanox_enter_phrase.c +++ b/src/nano/nanox_enter_phrase.c @@ -490,8 +490,14 @@ static uint8_t compare_recovery_phrase(void) { // get rootkey from device's seed uint8_t buffer_device[64]; - if (os_derive_bip32_no_throw(CX_CURVE_256K1, NULL, 0, buffer_device, buffer_device + 32) != - CX_OK) { + // os_derive_bip32* do not accept NULL path, even with a size of 0, so we provide an empty path + const unsigned int empty_path = 0; + + if (os_derive_bip32_no_throw(CX_CURVE_256K1, + &empty_path, + 0, + buffer_device, + buffer_device + 32) != CX_OK) { PRINTF("An error occurred while comparing the recovery phrase\n"); return 0; } diff --git a/src/nano/ux_nano.h b/src/nano/ux_nano.h index 15acfea5..7562a23b 100644 --- a/src/nano/ux_nano.h +++ b/src/nano/ux_nano.h @@ -24,8 +24,11 @@ #endif */ #if defined(TARGET_NANOS) -#define BIP39_ICON C_bip39_nanos -#define SSKR_ICON C_sskr_nanos +#define BIP39_ICON C_bip39_nanos +#define SSKR_ICON C_sskr_nanos +#define PROCESSING_COMPLETE 0 +#define PROCESSING_COMPARE_RECOVERY_PHRASE 1 +#define PROCESSING_GENERATE_SSKR 2 #elif defined(TARGET_NANOX) || defined(TARGET_NANOS2) #define BIP39_ICON C_bip39_nanox #define SSKR_ICON C_sskr_nanox @@ -121,6 +124,7 @@ void clean_exit(bolos_task_status_t exit_code); #if defined(TARGET_NANOS) extern const bagl_element_t screen_onboarding_word_list_elements[9]; void compare_recovery_phrase(void); +void generate_sskr(void); #else // to be included into all flow that needs to go back to the dashboard extern const ux_flow_step_t ux_ob_goto_dashboard_step; diff --git a/src/nano/ux_nano_bip39.c b/src/nano/ux_nano_bip39.c index 219b18d7..f595c791 100644 --- a/src/nano/ux_nano_bip39.c +++ b/src/nano/ux_nano_bip39.c @@ -30,15 +30,7 @@ UX_STEP_CB(step_bip39_clean_exit, pb, clean_exit(0), {&C_icon_dashboard_x, "Quit UX_FLOW(display_bip39_flow, &step_display_bip39, &step_bip39_clean_exit, FLOW_LOOP); void generate_bip39(void) { -#if defined(TARGET_NANOS) - // Display processing warning to user - screen_processing_init(); - G_bolos_ux_context.processing = 1; -#endif -// BIP39 phrase should already be in G_bolos_ux_context.words_buffer so just need to display it -#if defined(TARGET_NANOS) - G_bolos_ux_context.processing = 0; -#endif + // BIP39 phrase should already be in G_bolos_ux_context.words_buffer so just need to display it ux_flow_init(0, display_bip39_flow, NULL); } diff --git a/src/nano/ux_nano_sskr.c b/src/nano/ux_nano_sskr.c index b7ef14e1..89d441ea 100644 --- a/src/nano/ux_nano_sskr.c +++ b/src/nano/ux_nano_sskr.c @@ -14,6 +14,8 @@ * limitations under the License. ********************************************************************************/ +#include + #include "constants.h" #include "ui.h" @@ -112,15 +114,14 @@ UX_FLOW(dynamic_flow, FLOW_LOOP); void generate_sskr(void) { - PRINTF("generate_sskr threshold: %d\n", G_bolos_ux_context.sskr_group_descriptor[0][0]); - PRINTF("generate_sskr sskr number: %d\n", G_bolos_ux_context.sskr_group_descriptor[0][1]); - #if defined(TARGET_NANOS) - // Display processing warning to user - screen_processing_init(); - G_bolos_ux_context.processing = 1; + G_bolos_ux_context.processing = PROCESSING_COMPLETE; + io_seproxyhal_general_status(); #endif + PRINTF("generate_sskr threshold: %d\n", G_bolos_ux_context.sskr_group_descriptor[0][0]); + PRINTF("generate_sskr sskr number: %d\n", G_bolos_ux_context.sskr_group_descriptor[0][1]); + G_bolos_ux_context.sskr_share_count = 0; G_bolos_ux_context.sskr_words_buffer_length = 0; @@ -132,10 +133,6 @@ void generate_sskr(void) { (unsigned char*) G_bolos_ux_context.sskr_words_buffer, &G_bolos_ux_context.sskr_words_buffer_length); -#if defined(TARGET_NANOS) - G_bolos_ux_context.processing = 0; -#endif - if (G_bolos_ux_context.sskr_share_count > 0) { PRINTF("SSKR share_count from generate_sskr(): \n%d\n", G_bolos_ux_context.sskr_share_count); @@ -182,7 +179,14 @@ const char* sskr_threshold_getter(unsigned int idx) { void sskr_threshold_selector(unsigned int idx) { G_bolos_ux_context.sskr_group_descriptor[0][0] = idx + 1; + +#if defined(TARGET_NANOS) + // Display processing warning to user + screen_processing_init(); + G_bolos_ux_context.processing = PROCESSING_GENERATE_SSKR; +#else generate_sskr(); +#endif } UX_STEP_NOCB(ux_threshold_instruction_step, nn, {"Select", "threshold"}); diff --git a/src/ux_common/onboarding_seed_sskr.c b/src/ux_common/onboarding_seed_sskr.c index 334aad7b..f14d3fe5 100644 --- a/src/ux_common/onboarding_seed_sskr.c +++ b/src/ux_common/onboarding_seed_sskr.c @@ -51,8 +51,11 @@ unsigned int bolos_ux_sskr_hex_decode(unsigned char *mnemonic_hex, mnemonic_hex + (i * mnemonic_length / sskr_shares_count) + 4 + (sskr_share_len > 23); } - int output_len = - sskr_combine(ptr_sskr_shares, sskr_share_len, (uint8_t) sskr_shares_count, output, 32); + uint16_t output_len = sskr_combine(ptr_sskr_shares, + sskr_share_len, + (uint8_t) sskr_shares_count, + output, + SSKR_MAX_STRENGTH_BYTES); if (output_len < 1) { memzero(mnemonic_hex, mnemonic_length); @@ -71,7 +74,7 @@ void bolos_ux_sskr_hex_to_seed(unsigned char *mnemonic_hex, unsigned char *seed) { PRINTF("SSKR mnemonic in hex:\n %.*H\n", mnemonic_length, mnemonic_hex); - uint8_t seed_buffer[32] = {0}; + uint8_t seed_buffer[SSKR_MAX_STRENGTH_BYTES] = {0}; uint8_t seed_buffer_len = bolos_ux_sskr_hex_decode(mnemonic_hex, mnemonic_length, sskr_shares_count, seed_buffer); @@ -99,7 +102,8 @@ unsigned int bolos_ux_sskr_generate(uint8_t groups_threshold, groups[i].count = *(group_descriptor + 1 + i * 2); } - if (!(16 <= seed_len && seed_len <= 32) || (seed_len % 2 != 0)) { + if (!(SSKR_MIN_STRENGTH_BYTES <= seed_len && seed_len <= SSKR_MAX_STRENGTH_BYTES) || + (seed_len % 2 != 0)) { return 0; } diff --git a/tests/unit/tests/roundtrip.c b/tests/unit/tests/roundtrip.c index 4a1d02ff..a4ea9d91 100644 --- a/tests/unit/tests/roundtrip.c +++ b/tests/unit/tests/roundtrip.c @@ -129,15 +129,15 @@ static void test_sskr_to_bip39(void **state) { sskr_group_descriptor[0], seed_buffer); unsigned char bip39_word_buffer[sizeof(bip39_mnemonic)]; - unsigned int bip39_word_buffer_len = sizeof(bip39_word_buffer); + int16_t bip39_word_buffer_len = sizeof(bip39_word_buffer); assert_int_equal(seed_buffer_len, sizeof(seed_buffer)); assert_memory_equal(seed_buffer, bip39_hex, seed_buffer_len); - size_t buf_len = bolos_ux_bip39_mnemonic_encode(seed_buffer, - sizeof(seed_buffer), - bip39_word_buffer, - bip39_word_buffer_len); + int16_t buf_len = bolos_ux_bip39_mnemonic_encode(seed_buffer, + sizeof(seed_buffer), + bip39_word_buffer, + bip39_word_buffer_len); assert_int_equal(buf_len, bip39_word_buffer_len - 1); assert_memory_equal(bip39_mnemonic, bip39_word_buffer, buf_len); } diff --git a/tests/unit/tests/shamir.c b/tests/unit/tests/shamir.c index 5b792ef6..2c85f67f 100644 --- a/tests/unit/tests/shamir.c +++ b/tests/unit/tests/shamir.c @@ -91,11 +91,11 @@ static void test_shamir_recover(void **state) { const uint8_t *shares[] = {share1_1, share1_2}; - int recovery = shamir_recover_secret(threshold, - member_indexs, - shares, - share_length, - secret); + int16_t recovery = shamir_recover_secret(threshold, + member_indexs, + shares, + share_length, + secret); assert_int_equal(recovery, share_length); assert_memory_equal(secret, seed, share_length); @@ -220,7 +220,7 @@ static void test_shamir_split(void **state) { const uint8_t seed_length = sizeof(seed); uint8_t result[seed_length * share_count]; - int32_t ret_val = shamir_split_secret(threshold, + int16_t ret_val = shamir_split_secret(threshold, share_count, seed, seed_length, diff --git a/tests/unit/tests/sskr.c b/tests/unit/tests/sskr.c index b09ac9de..1225c085 100644 --- a/tests/unit/tests/sskr.c +++ b/tests/unit/tests/sskr.c @@ -84,23 +84,23 @@ static void test_sskr_generate(void **state) { 0x57, 0xA8, 0x4C, 0x9F, 0x21, 0xAA, 0xF5, 0x56, 0x49, 0x91, 0x30, 0xCF, 0xAD, 0x2E, 0xBA}; - const size_t groups_threshold = 1; + const uint8_t groups_threshold = 1; const sskr_group_descriptor groups[] = { { .threshold = 2, .count = 3 } }; - const size_t groups_len = 1; - const size_t seed_len = sizeof(seed); - const size_t share_buffer_len = (seed_len + SSKR_METADATA_LENGTH_BYTES) * groups[0].count; + const uint8_t groups_len = 1; + const uint8_t seed_len = sizeof(seed); + const uint16_t share_buffer_len = (seed_len + SSKR_METADATA_LENGTH_BYTES) * groups[0].count; uint8_t share_buffer[share_buffer_len]; uint8_t share_len; - int share_count = sskr_generate(groups_threshold, - groups, - groups_len, - seed, - seed_len, - &share_len, - share_buffer, - share_buffer_len, - cx_rng); + int16_t share_count = sskr_generate(groups_threshold, + groups, + groups_len, + seed, + seed_len, + &share_len, + share_buffer, + share_buffer_len, + cx_rng); assert_int_equal(share_count, groups[0].count); assert_int_equal(share_len, share_buffer_len / groups[0].count); @@ -126,12 +126,12 @@ static void test_sskr_combine(void **state) { 0x48, 0xF1, 0x90, 0x65, 0x36, 0x21, 0xB9, 0xE8, 0xA6, 0x02, 0xDD, 0x13, 0x2A}; - size_t share_len = sizeof(share1_1); + uint8_t share_len = sizeof(share1_1); const uint8_t *shares[] = {share1_1, share1_2}; - size_t share_count = 2; + uint8_t share_count = 2; uint8_t output[sizeof(seed)]; - int output_len = sskr_combine(shares, share_len, share_count, output, sizeof(output)); + int16_t output_len = sskr_combine(shares, share_len, share_count, output, sizeof(output)); assert_int_equal(output_len, sizeof(seed)); assert_memory_equal(output, seed, output_len);