From c458fd181cdf2981aec42f355f31441eab2f4de3 Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 13:17:38 +0100 Subject: [PATCH 01/11] make sure we reject invalid value for special-tx --- app/src/common/app_main.c | 4 +++- app/src/parser_impl.c | 5 +++++ app/src/parser_txdef.h | 3 ++- tests/ui_tests.cpp | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/app/src/common/app_main.c b/app/src/common/app_main.c index 536f712c..de60bfd0 100644 --- a/app/src/common/app_main.c +++ b/app/src/common/app_main.c @@ -145,8 +145,10 @@ bool process_chunk(volatile uint32_t *tx, uint32_t rx) { tx_reset(); extractHDPath(rx, OFFSET_DATA); MEMZERO(&parser_tx_obj, sizeof(parser_tx_t)); - if(G_io_apdu_buffer[OFFSET_P2] == 1){ + if((G_io_apdu_buffer[OFFSET_P2] & 0x01) == 1){ parser_tx_obj.tx_fields.call.special_transfer_type = neuron_stake_transaction; + }else{ + parser_tx_obj.tx_fields.call.special_transfer_type = normal_transaction; } tx_initialized = true; return false; diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index b0d58da4..08b4a883 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -479,6 +479,11 @@ parser_error_t _validateTx(const parser_context_t *c, const parser_tx_t *v) { return parser_unexpected_value; } + if (v->tx_fields.call.special_transfer_type == invalid){ + zemu_log_stack("invalid transfer type"); + return parser_unexpected_value; + } + if (v->tx_fields.call.pbtype == pb_manageneuron){ ic_nns_governance_pb_v1_ManageNeuron *fields = &parser_tx_obj.tx_fields.call.pb_fields.ic_nns_governance_pb_v1_ManageNeuron; PARSER_ASSERT_OR_ERROR(fields->has_id ^ (fields->neuron_id_or_subaccount.neuron_id.id != 0), parser_unexepected_error); diff --git a/app/src/parser_txdef.h b/app/src/parser_txdef.h index 91289468..8cd49fdf 100644 --- a/app/src/parser_txdef.h +++ b/app/src/parser_txdef.h @@ -76,7 +76,8 @@ typedef enum { typedef enum { invalid = 0x00, - neuron_stake_transaction = 0x01, + normal_transaction = 0x01, + neuron_stake_transaction = 0x02, } special_transfer_e; typedef struct { diff --git a/tests/ui_tests.cpp b/tests/ui_tests.cpp index 07d2527d..e9de0ca9 100644 --- a/tests/ui_tests.cpp +++ b/tests/ui_tests.cpp @@ -122,7 +122,7 @@ void check_testcase(const testcase_t &tc, bool expert_mode) { ASSERT_NE(err, parser_ok) << parser_getErrorDescription(err); return; } - + parser_tx_obj.tx_fields.call.special_transfer_type = normal_transaction; err = parser_validate(&ctx); ASSERT_EQ(err, parser_ok) << parser_getErrorDescription(err); From 37501ed5a663ec22e773138cc78e9d2b91722e8a Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 15:03:24 +0100 Subject: [PATCH 02/11] wip api for combined_tx --- app/src/apdu_handler.c | 31 +++++++++++++++++++++++++++++++ app/src/common/actions.h | 15 +++++++++++++++ app/src/common/app_main.c | 8 ++++---- app/src/common/app_main.h | 1 + app/src/common/parser.h | 3 +++ app/src/common/tx.c | 20 ++++++++++++++++++++ app/src/common/tx.h | 3 +++ app/src/crypto.h | 4 ++++ app/src/parser.c | 30 +++++++++++++++++++++++++++--- app/src/parser_impl.c | 8 ++++---- app/src/parser_txdef.h | 4 ++-- tests/cbor_parser.cpp | 7 +++++-- tests/ui_tests.cpp | 2 +- 13 files changed, 120 insertions(+), 16 deletions(-) diff --git a/app/src/apdu_handler.c b/app/src/apdu_handler.c index e846a27e..13a27360 100644 --- a/app/src/apdu_handler.c +++ b/app/src/apdu_handler.c @@ -75,6 +75,29 @@ __Z_INLINE void handleSign(volatile uint32_t *flags, volatile uint32_t *tx, uint *flags |= IO_ASYNCH_REPLY; } +__Z_INLINE void handleSignCombined(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { + if (!process_chunk(tx, rx)) { + THROW(APDU_CODE_OK); + } + + CHECK_APP_CANARY() + + const char *error_msg = tx_parse_combined(); + CHECK_APP_CANARY() + + if (error_msg != NULL) { + int error_msg_length = strlen(error_msg); + MEMCPY(G_io_apdu_buffer, error_msg, error_msg_length); + *tx += (error_msg_length); + THROW(APDU_CODE_DATA_INVALID); + } + + CHECK_APP_CANARY() + view_review_init(tx_getItem, tx_getNumItems, app_sign_combined); + view_review_show(); + *flags |= IO_ASYNCH_REPLY; +} + void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { uint16_t sw = 0; @@ -112,6 +135,14 @@ void handleApdu(volatile uint32_t *flags, volatile uint32_t *tx, uint32_t rx) { break; } + case INS_SIGN_COMBINED: { + if (os_global_pin_is_validated() != BOLOS_UX_OK) { + THROW(APDU_CODE_COMMAND_NOT_ALLOWED); + } + handleSignCombined(flags, tx, rx); + break; + } + default: THROW(APDU_CODE_INS_NOT_SUPPORTED); } diff --git a/app/src/common/actions.h b/app/src/common/actions.h index 5eb28ccb..c69eefa9 100644 --- a/app/src/common/actions.h +++ b/app/src/common/actions.h @@ -40,6 +40,21 @@ __Z_INLINE void app_sign() { } } +__Z_INLINE void app_sign_combined() { + uint16_t replyLen = 0; + + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + zxerr_t err = crypto_sign(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, &replyLen); + + if (err != zxerr_ok || replyLen == 0) { + set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2); + } else { + set_code(G_io_apdu_buffer, replyLen, APDU_CODE_OK); + io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, replyLen + 2); + } +} + __Z_INLINE zxerr_t app_fill_address() { // Put data directly in the apdu buffer MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); diff --git a/app/src/common/app_main.c b/app/src/common/app_main.c index de60bfd0..f3af334d 100644 --- a/app/src/common/app_main.c +++ b/app/src/common/app_main.c @@ -136,7 +136,7 @@ bool process_chunk(volatile uint32_t *tx, uint32_t rx) { THROW(APDU_CODE_DATA_INVALID); } - bool is_stake_tx = parser_tx_obj.tx_fields.call.special_transfer_type == neuron_stake_transaction; + bool is_stake_tx = parser_tx_obj.special_transfer_type == neuron_stake_transaction; uint32_t added; switch (payloadType) { @@ -145,10 +145,10 @@ bool process_chunk(volatile uint32_t *tx, uint32_t rx) { tx_reset(); extractHDPath(rx, OFFSET_DATA); MEMZERO(&parser_tx_obj, sizeof(parser_tx_t)); - if((G_io_apdu_buffer[OFFSET_P2] & 0x01) == 1){ - parser_tx_obj.tx_fields.call.special_transfer_type = neuron_stake_transaction; + if(G_io_apdu_buffer[OFFSET_P2] == 1){ + parser_tx_obj.special_transfer_type = neuron_stake_transaction; }else{ - parser_tx_obj.tx_fields.call.special_transfer_type = normal_transaction; + parser_tx_obj.special_transfer_type = normal_transaction; } tx_initialized = true; return false; diff --git a/app/src/common/app_main.h b/app/src/common/app_main.h index f84439b4..c40bd619 100644 --- a/app/src/common/app_main.h +++ b/app/src/common/app_main.h @@ -33,6 +33,7 @@ #define INS_GET_VERSION 0x00 #define INS_GET_ADDR 0x01 #define INS_SIGN 0x02 +#define INS_SIGN_COMBINED 0x03 void app_init(); diff --git a/app/src/common/parser.h b/app/src/common/parser.h index 002159e2..7aec97f3 100644 --- a/app/src/common/parser.h +++ b/app/src/common/parser.h @@ -27,6 +27,9 @@ const char *parser_getErrorDescription(parser_error_t err); //// parses a tx buffer parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen); +/// parses a tx buffer of a combined transaction +parser_error_t parser_parse_combined(parser_context_t *ctx, const uint8_t *data, size_t dataLen); + //// verifies tx fields parser_error_t parser_validate(const parser_context_t *ctx); diff --git a/app/src/common/tx.c b/app/src/common/tx.c index 4a53da23..306403f5 100644 --- a/app/src/common/tx.c +++ b/app/src/common/tx.c @@ -89,6 +89,26 @@ const char *tx_parse() { return NULL; } +const char *tx_parse_combined() { + uint8_t err = parser_parse_combined( + &ctx_parsed_tx, + tx_get_buffer(), + tx_get_buffer_length()); + + if (err != parser_ok) { + return parser_getErrorDescription(err); + } + + err = parser_validate(&ctx_parsed_tx); + CHECK_APP_CANARY() + + if (err != parser_ok) { + return parser_getErrorDescription(err); + } + + return NULL; +} + zxerr_t tx_getNumItems(uint8_t *num_items) { parser_error_t err = parser_getNumItems(&ctx_parsed_tx, num_items); diff --git a/app/src/common/tx.h b/app/src/common/tx.h index b84b9151..82710da2 100644 --- a/app/src/common/tx.h +++ b/app/src/common/tx.h @@ -44,6 +44,9 @@ uint8_t *tx_get_buffer(); /// \return It returns NULL if data is valid or error message otherwise. const char *tx_parse(); +///Parses combined transaction message in transaction buffer +const char *tx_parse_combined(); + /// Return the number of items in the transaction zxerr_t tx_getNumItems(uint8_t *num_items); diff --git a/app/src/crypto.h b/app/src/crypto.h index 6bed8e7d..1f5ddbac 100644 --- a/app/src/crypto.h +++ b/app/src/crypto.h @@ -26,6 +26,8 @@ extern "C" { #include #include +#include "parser_txdef.h" + extern uint32_t hdPath[HDPATH_LEN_DEFAULT]; bool isTestnet(); @@ -54,6 +56,8 @@ zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, uint16_t *sigSize); +zxerr_t crypto_getDigest(uint8_t *digest, txtype_e txtype); + zxerr_t crypto_principalToStakeAccount(const uint8_t *principal, uint16_t principalLen, const uint64_t neuron_creation_memo, uint8_t *address, uint16_t maxoutLen); diff --git a/app/src/parser.c b/app/src/parser.c index ac193650..ddbe58a0 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -50,6 +50,30 @@ GEN_DEC_READFIX_UNSIGNED(32); GEN_DEC_READFIX_UNSIGNED(64); +parser_error_t parser_parse_combined(parser_context_t *ctx, const uint8_t *data, size_t dataLen) { + if (dataLen < 1) { + return parser_no_data; + } + zemu_log_stack("parser parse"); + //if combined_tx: + //split data in two transactions + //should start with checking status + //add one more check in validate + //define txtype + const size_t dataLen_state_read = (uint32_t *)&data; + const uint8_t *start_state_read_data = data + 4; + CHECK_PARSER_ERR(parser_init(ctx, start_state_read_data, dataLen_state_read)) + CHECK_PARSER_ERR(_readEnvelope(ctx, &parser_tx_obj)) + uint8_t state_read_digest[32]; + PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(state_read_digest, state_transaction_read), parser_unexepected_error) + + data += 4 + dataLen_state_read; + const size_t dataLen_request = (uint32_t *)&data; + const uint8_t *start_request_data = data + 4; + PARSER_ASSERT_OR_ERROR(dataLen == dataLen_request + dataLen_state_read + 8, parser_context_unexpected_size) + CHECK_PARSER_ERR(parser_init(ctx, start_request_data, dataLen_request)) + return _readEnvelope(ctx, &parser_tx_obj); +} parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen) { if (dataLen < 1) { @@ -330,7 +354,7 @@ parser_error_t parser_getItemTokenTransfer(const parser_context_t *ctx, return parser_no_data; } - const bool is_stake_tx = parser_tx_obj.tx_fields.call.special_transfer_type == neuron_stake_transaction; + const bool is_stake_tx = parser_tx_obj.special_transfer_type == neuron_stake_transaction; if (is_stake_tx) { return parser_unexepected_error; } @@ -432,7 +456,7 @@ parser_error_t parser_getItemStakeNeuron(const parser_context_t *ctx, return parser_no_data; } - const bool is_stake_tx = parser_tx_obj.tx_fields.call.special_transfer_type == neuron_stake_transaction; + const bool is_stake_tx = parser_tx_obj.special_transfer_type == neuron_stake_transaction; if (!is_stake_tx) { return parser_unexepected_error; } @@ -994,7 +1018,7 @@ parser_error_t parser_getItem(const parser_context_t *ctx, case call: { switch(parser_tx_obj.tx_fields.call.pbtype) { case pb_sendrequest : { - const bool is_stake_tx = parser_tx_obj.tx_fields.call.special_transfer_type == neuron_stake_transaction; + const bool is_stake_tx = parser_tx_obj.special_transfer_type == neuron_stake_transaction; if (is_stake_tx) { return parser_getItemStakeNeuron(ctx, displayIdx, diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 08b4a883..7d131772 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -303,7 +303,7 @@ parser_error_t getManageNeuronType(parser_tx_t *v){ parser_error_t readProtobuf(parser_tx_t *v, uint8_t *buffer, size_t bufferLen) { char *method = v->tx_fields.call.method_name.data; - if (strcmp(method, "send_pb") == 0 || v->tx_fields.call.special_transfer_type == neuron_stake_transaction) { + if (strcmp(method, "send_pb") == 0 ||v->special_transfer_type == neuron_stake_transaction) { v->tx_fields.call.pbtype = pb_sendrequest; return _parser_pb_SendRequest(v, buffer, bufferLen); } @@ -479,7 +479,7 @@ parser_error_t _validateTx(const parser_context_t *c, const parser_tx_t *v) { return parser_unexpected_value; } - if (v->tx_fields.call.special_transfer_type == invalid){ + if (v->special_transfer_type == invalid){ zemu_log_stack("invalid transfer type"); return parser_unexpected_value; } @@ -537,7 +537,7 @@ parser_error_t _validateTx(const parser_context_t *c, const parser_tx_t *v) { #endif - bool is_stake_tx = parser_tx_obj.tx_fields.call.special_transfer_type == neuron_stake_transaction; + bool is_stake_tx = parser_tx_obj.special_transfer_type == neuron_stake_transaction; if(is_stake_tx){ uint8_t to_hash[32]; PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_principalToStakeAccount(sender, DFINITY_PRINCIPAL_LEN, @@ -560,7 +560,7 @@ uint8_t _getNumItems(const parser_context_t *c, const parser_tx_t *v) { case call: { switch(v->tx_fields.call.pbtype) { case pb_sendrequest: { - const bool is_stake_tx = v->tx_fields.call.special_transfer_type == neuron_stake_transaction; + const bool is_stake_tx =v->special_transfer_type == neuron_stake_transaction; if (is_stake_tx) { return app_mode_expert() ? 7 : 5; diff --git a/app/src/parser_txdef.h b/app/src/parser_txdef.h index 8cd49fdf..77272272 100644 --- a/app/src/parser_txdef.h +++ b/app/src/parser_txdef.h @@ -127,8 +127,6 @@ typedef struct { uint64_t ingress_expiry; uint64_t neuron_creation_memo; - special_transfer_e special_transfer_type; - canister_t canister_id; sender_t sender; @@ -161,6 +159,8 @@ typedef struct { call_t call; state_read_t stateRead; } tx_fields; + + special_transfer_e special_transfer_type; } parser_tx_t; #ifdef __cplusplus diff --git a/tests/cbor_parser.cpp b/tests/cbor_parser.cpp index 4ba6bf6d..6d0d0ac7 100644 --- a/tests/cbor_parser.cpp +++ b/tests/cbor_parser.cpp @@ -33,6 +33,7 @@ namespace { TEST(TxTest, one_byte_accountid) { + parser_tx_obj.special_transfer_type = normal_transaction; uint8_t inBuffer[1000]; const char *tmp = "d9d9f7a167636f6e74656e74a6636172674c620210011a0612040a0211116b63616e69737465725f69644a000000000000000101016e696e67726573735f6578706972791b16a2cd02c5b2d1006b6d6574686f645f6e616d65706d616e6167655f6e6575726f6e5f70626c726571756573745f747970656463616c6c6673656e646572581d8a4aa4ffc7bc5ccdcd5a7a3d10c9bb06741063b02c7e908a624f721d02"; @@ -490,6 +491,7 @@ namespace { } TEST(CBORParserTest, TokenTransfer) { + parser_tx_obj.special_transfer_type = normal_transaction; uint8_t inBuffer[1000]; const char *tmp = "d9d9f7a367636f6e74656e74a76c726571756573745f747970656463616c6c656e6f6e636550f5390d960c6e52f489155a4309da03da6e696e67726573735f6578706972791b1674c5e29ec9c2106673656e646572581d19aa3d42c048dd7d14f0cfa0df69a1c1381780f6e9a137abaa6a82e3026b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758560a0012050a0308e8071a0308890122220a2001010101010101010101010101010101010101010101010101010101010101012a220a2035548ec29e9d85305850e87a2d2642fe7214ff4bb36334070deafc3345c3b1276d73656e6465725f7075626b657958583056301006072a8648ce3d020106052b8104000a03420004e1142e1fbc940344d9161709196bb8bd151f94379c48dd507ab99a0776109128b94b5303cf2b2d28e25a779da175b62f8a975599b20c63d5193202640576ec5e6a73656e6465725f7369675840de5bccbb0a0173c432cd58ea4495d4d1e122d6ce04e31dcf63217f3d3a9b73130dc9bbf3b10e61c8db8bf8800bb4649e27786e5bc9418838c95864be28487a6a"; auto inBufferLen = parseHexString(inBuffer, sizeof(inBuffer), tmp); @@ -504,6 +506,7 @@ namespace { } TEST(CBORParserTest, IncreaseNeuronTimer) { + parser_tx_obj.special_transfer_type = normal_transaction; uint8_t inBuffer[1000]; const char *tmp = "d9d9f7a167636f6e74656e74a6636172675839620a10a7d18aaad3a2a2c6131a2b0a0508959aef3a12220a2068d518e2fd2be6566e62c36611b9794dfcbc04eb4227eefb73ab3c7a2d0ae5776b63616e69737465725f69644a000000000000000101016e696e67726573735f6578706972791b169bc8985c330d006b6d6574686f645f6e616d65706d616e6167655f6e6575726f6e5f70626c726571756573745f747970656463616c6c6673656e646572581d8a4aa4ffc7bc5ccdcd5a7a3d10c9bb06741063b02c7e908a624f721d02"; @@ -518,7 +521,7 @@ namespace { } TEST(CBORParserTest, StakeTx) { - parser_tx_obj.tx_fields.call.special_transfer_type = neuron_stake_transaction; + parser_tx_obj.special_transfer_type = neuron_stake_transaction; uint8_t inBuffer[1000]; const char *tmp = "d9d9f7a167636f6e74656e74a663617267583e0a0a08f2d4a0eca697869f0812070a050880c2d72f1a0308904e2a220a20a8a1abecdb66f57eb6eba44c3b5f11a6c433fe932680a9519b064b80ca8794e16b63616e69737465725f69644a000000000000000201016e696e67726573735f6578706972791b16985a582755f1806b6d6574686f645f6e616d656773656e645f70626c726571756573745f747970656463616c6c6673656e646572581d19aa3d42c048dd7d14f0cfa0df69a1c1381780f6e9a137abaa6a82e302"; @@ -530,7 +533,7 @@ namespace { err = parser_validate(&ctx); EXPECT_EQ(err, parser_ok); - parser_tx_obj.tx_fields.call.special_transfer_type = invalid; + parser_tx_obj.special_transfer_type = invalid; } TEST(CBORParserTest, ClaimNeuron) { diff --git a/tests/ui_tests.cpp b/tests/ui_tests.cpp index e9de0ca9..60d049a0 100644 --- a/tests/ui_tests.cpp +++ b/tests/ui_tests.cpp @@ -122,7 +122,7 @@ void check_testcase(const testcase_t &tc, bool expert_mode) { ASSERT_NE(err, parser_ok) << parser_getErrorDescription(err); return; } - parser_tx_obj.tx_fields.call.special_transfer_type = normal_transaction; + parser_tx_obj.special_transfer_type = normal_transaction; err = parser_validate(&ctx); ASSERT_EQ(err, parser_ok) << parser_getErrorDescription(err); From 65dcda9258cd573a11c56b670db45091f847675a Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 15:54:44 +0100 Subject: [PATCH 03/11] sign two digests combined_tx --- app/src/common/actions.h | 3 +- app/src/crypto.c | 115 +++++++++++++++++++++++++++++++++++++++ app/src/crypto.h | 6 ++ app/src/parser.c | 30 +++++++--- 4 files changed, 144 insertions(+), 10 deletions(-) diff --git a/app/src/common/actions.h b/app/src/common/actions.h index c69eefa9..70c35cea 100644 --- a/app/src/common/actions.h +++ b/app/src/common/actions.h @@ -43,8 +43,7 @@ __Z_INLINE void app_sign() { __Z_INLINE void app_sign_combined() { uint16_t replyLen = 0; - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - zxerr_t err = crypto_sign(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3, &replyLen); + zxerr_t err = crypto_sign_combined(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE - 3,&G_io_apdu_buffer[0], &G_io_apdu_buffer[32], &replyLen); if (err != zxerr_ok || replyLen == 0) { set_code(G_io_apdu_buffer, 0, APDU_CODE_SIGN_VERIFY_ERROR); diff --git a/app/src/crypto.c b/app/src/crypto.c index e976f905..7d93420e 100644 --- a/app/src/crypto.c +++ b/app/src/crypto.c @@ -262,12 +262,127 @@ zxerr_t crypto_sign(uint8_t *signatureBuffer, return err; } +//Start: +//PREDIGEST_REQUEST || PREDIGEST_STATEREAD +//END: +//DIGEST_REQUEST || SIGNATURE_REQUEST || DIGEST_STATEREAD || SIGNATURE_STATEREAD + +zxerr_t crypto_sign_combined(uint8_t *signatureBuffer, + uint16_t signatureMaxlen, + uint8_t *predigest_request, + uint8_t *predigest_stateread, + uint16_t *sigSize) { + if (signatureMaxlen < SIGN_PREHASH_SIZE + CX_SHA256_SIZE + 2*64){ + return zxerr_buffer_too_small; + } + + uint8_t message_buffer[SIGN_PREFIX_SIZE + CX_SHA256_SIZE]; + MEMZERO(message_buffer, sizeof(message_buffer)); + + uint8_t message_digest[CX_SHA256_SIZE]; + MEMZERO(message_digest,sizeof(message_digest)); + + message_buffer[0] = 0x0a; + MEMCPY(&message_buffer[1], (uint8_t *)"ic-request",SIGN_PREFIX_SIZE - 1); + + MEMCPY(message_buffer + SIGN_PREFIX_SIZE, predigest_stateread, CX_SHA256_SIZE); + + CHECK_APP_CANARY() + + cx_hash_sha256(message_buffer, SIGN_PREHASH_SIZE, message_digest, CX_SHA256_SIZE); + MEMCPY(signatureBuffer + 32 + 64, message_digest, CX_SHA256_SIZE); + + + MEMCPY(message_buffer + SIGN_PREFIX_SIZE, predigest_request, CX_SHA256_SIZE); + cx_hash_sha256(message_buffer, SIGN_PREHASH_SIZE, message_digest, CX_SHA256_SIZE); + MEMCPY(signatureBuffer, message_digest, CX_SHA256_SIZE); + + CHECK_APP_CANARY() + + cx_ecfp_private_key_t cx_privateKey; + uint8_t privateKeyData[32]; + unsigned int info = 0; + int signatureLength = 0; + + signature_t sigma; + MEMZERO(&sigma, sizeof(signature_t)); + + zxerr_t err = zxerr_ok; + BEGIN_TRY + { + TRY + { + // Generate keys + os_perso_derive_node_bip32(CX_CURVE_SECP256K1, + hdPath, + HDPATH_LEN_DEFAULT, + privateKeyData, NULL); + + cx_ecfp_init_private_key(CX_CURVE_SECP256K1, privateKeyData, 32, &cx_privateKey); + + // Sign request + signatureLength = cx_ecdsa_sign(&cx_privateKey, + CX_RND_RFC6979 | CX_LAST, + CX_SHA256, + signatureBuffer, + CX_SHA256_SIZE, + sigma.der_signature, + sizeof_field(signature_t, der_signature), + &info); + + err_convert_e err_c = convertDERtoRSV(sigma.der_signature, info, sigma.r, sigma.s, &sigma.v); + if (err_c != no_error) { + MEMZERO(signatureBuffer, signatureMaxlen); + err = zxerr_unknown; + }else{ + MEMCPY(signatureBuffer + 32, sigma.r, 32); + MEMCPY(signatureBuffer + 64, sigma.s, 32); + + MEMZERO(&sigma, sizeof(signature_t)); + // Sign stateread + signatureLength = cx_ecdsa_sign(&cx_privateKey, + CX_RND_RFC6979 | CX_LAST, + CX_SHA256, + signatureBuffer + 32 + 64, + CX_SHA256_SIZE, + sigma.der_signature, + sizeof_field(signature_t, der_signature), + &info); + + err_convert_e err_c = convertDERtoRSV(sigma.der_signature, info, sigma.r, sigma.s, &sigma.v); + if (err_c != no_error) { + MEMZERO(signatureBuffer, signatureMaxlen); + err = zxerr_unknown; + }else{ + MEMCPY(signatureBuffer + 32 + 64 + 32, sigma.r, 32); + MEMCPY(signatureBuffer + 32 + 64 + 64, sigma.s, 32); + *sigSize = 32 + 64 + 32 + 64; + } + } + } + CATCH_ALL { + err = zxerr_ledger_api_error; + } + FINALLY { + MEMZERO(&cx_privateKey, sizeof(cx_privateKey)); + MEMZERO(privateKeyData, 32); + } + } + END_TRY; + + return err; +} + #else #include #include "picohash.h" +zxerr_t crypto_getDigest(uint8_t *digest, txtype_e txtype){ + return zxerr_ok; +} + zxerr_t cx_hash_sha256(uint8_t *input, uint16_t inputLen, uint8_t *output, uint16_t outputLen) { if (outputLen < 32) { return zxerr_invalid_crypto_settings; diff --git a/app/src/crypto.h b/app/src/crypto.h index 1f5ddbac..048abe83 100644 --- a/app/src/crypto.h +++ b/app/src/crypto.h @@ -56,6 +56,12 @@ zxerr_t crypto_sign(uint8_t *signature, uint16_t signatureMaxlen, uint16_t *sigSize); +zxerr_t crypto_sign_combined(uint8_t *signatureBuffer, + uint16_t signatureMaxlen, + uint8_t *predigest_request, + uint8_t *predigest_stateread, + uint16_t *sigSize); + zxerr_t crypto_getDigest(uint8_t *digest, txtype_e txtype); zxerr_t crypto_principalToStakeAccount(const uint8_t *principal, uint16_t principalLen, diff --git a/app/src/parser.c b/app/src/parser.c index ddbe58a0..8ab7d375 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -60,19 +60,33 @@ parser_error_t parser_parse_combined(parser_context_t *ctx, const uint8_t *data, //should start with checking status //add one more check in validate //define txtype - const size_t dataLen_state_read = (uint32_t *)&data; - const uint8_t *start_state_read_data = data + 4; - CHECK_PARSER_ERR(parser_init(ctx, start_state_read_data, dataLen_state_read)) + const uint8_t *start_state_read_data = data; + CHECK_PARSER_ERR(parser_init(ctx, start_state_read_data, dataLen)) + uint32_t dataLen_state_read; + CHECK_PARSER_ERR(_readUInt32(ctx, &dataLen_state_read)) + ctx->bufferLen = dataLen_state_read; + CHECK_PARSER_ERR(_readEnvelope(ctx, &parser_tx_obj)) - uint8_t state_read_digest[32]; - PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(state_read_digest, state_transaction_read), parser_unexepected_error) + PARSER_ASSERT_OR_ERROR(parser_tx_obj.txtype == state_transaction_read, parser_unexpected_type) + + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(G_io_apdu_buffer, state_transaction_read), parser_unexepected_error) data += 4 + dataLen_state_read; - const size_t dataLen_request = (uint32_t *)&data; - const uint8_t *start_request_data = data + 4; + const uint8_t *start_request_data = data; + CHECK_PARSER_ERR(parser_init(ctx, start_request_data, dataLen - 4 - dataLen_state_read)) + uint32_t dataLen_request; + CHECK_PARSER_ERR(_readUInt32(ctx, &dataLen_request)) + ctx->bufferLen = dataLen_request; + PARSER_ASSERT_OR_ERROR(dataLen == dataLen_request + dataLen_state_read + 8, parser_context_unexpected_size) + CHECK_PARSER_ERR(parser_init(ctx, start_request_data, dataLen_request)) - return _readEnvelope(ctx, &parser_tx_obj); + CHECK_PARSER_ERR(_readEnvelope(ctx, &parser_tx_obj)) + PARSER_ASSERT_OR_ERROR(parser_tx_obj.txtype == call, parser_unexpected_type) + + PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(G_io_apdu_buffer+32, call), parser_unexepected_error) + return parser_ok; } parser_error_t parser_parse(parser_context_t *ctx, const uint8_t *data, size_t dataLen) { From 4a7a577385cf9b5915235c0aec004f43787f043b Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 17:22:48 +0100 Subject: [PATCH 04/11] wip combined parser --- app/src/parser.c | 23 +++++++++++++++++------ tests/cbor_parser.cpp | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/app/src/parser.c b/app/src/parser.c index 8ab7d375..48ef7ded 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -64,28 +64,39 @@ parser_error_t parser_parse_combined(parser_context_t *ctx, const uint8_t *data, CHECK_PARSER_ERR(parser_init(ctx, start_state_read_data, dataLen)) uint32_t dataLen_state_read; CHECK_PARSER_ERR(_readUInt32(ctx, &dataLen_state_read)) - ctx->bufferLen = dataLen_state_read; + ctx->bufferLen = 4 + dataLen_state_read; CHECK_PARSER_ERR(_readEnvelope(ctx, &parser_tx_obj)) PARSER_ASSERT_OR_ERROR(parser_tx_obj.txtype == state_transaction_read, parser_unexpected_type) - MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(G_io_apdu_buffer, state_transaction_read), parser_unexepected_error) + uint8_t state_hash[32]; + MEMZERO(state_hash, sizeof(state_hash)); + PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(state_hash, state_transaction_read), parser_unexepected_error) data += 4 + dataLen_state_read; const uint8_t *start_request_data = data; CHECK_PARSER_ERR(parser_init(ctx, start_request_data, dataLen - 4 - dataLen_state_read)) uint32_t dataLen_request; CHECK_PARSER_ERR(_readUInt32(ctx, &dataLen_request)) - ctx->bufferLen = dataLen_request; + ctx->bufferLen = 4 + dataLen_request; PARSER_ASSERT_OR_ERROR(dataLen == dataLen_request + dataLen_state_read + 8, parser_context_unexpected_size) - CHECK_PARSER_ERR(parser_init(ctx, start_request_data, dataLen_request)) CHECK_PARSER_ERR(_readEnvelope(ctx, &parser_tx_obj)) PARSER_ASSERT_OR_ERROR(parser_tx_obj.txtype == call, parser_unexpected_type) - PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(G_io_apdu_buffer+32, call), parser_unexepected_error) + uint8_t request_hash[32]; + MEMZERO(request_hash, sizeof(request_hash)); + PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(request_hash, call), parser_unexepected_error) +#if defined(TARGET_NANOS) || defined(TARGET_NANOX) + MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + MEMCPY(G_io_apdu_buffer + 64, parser_tx_obj.tx_fields.stateRead.paths.paths[1].data, 32); + PARSER_ASSERT_OR_ERROR(memcmp(request_hash, G_io_apdu_buffer + 64, 32) == 0, parser_context_invalid_chars) + MEMCPY(G_io_apdu_buffer, request_hash, 32); + MEMCPY(G_io_apdu_buffer + 32, state_hash, 32); +#endif + + return parser_ok; } diff --git a/tests/cbor_parser.cpp b/tests/cbor_parser.cpp index 6d0d0ac7..baf24fa0 100644 --- a/tests/cbor_parser.cpp +++ b/tests/cbor_parser.cpp @@ -586,4 +586,22 @@ namespace { EXPECT_EQ(request.neuron_id_or_subaccount.neuron_id.id, 123); } + + TEST(CBORParserTest, CombinedTX) { + uint8_t inBuffer[1000]; + + const char *tmp = "d9d9f7a167636f6e74656e74a46e696e67726573735f6578706972791b16bc685267142b8065706174687381824e726571756573745f737461747573582038b344ba26f15444b4f989078c952ce99b559d3eb59e829c5a463a33812e32546c726571756573745f747970656a726561645f73746174656673656e646572581dd899978f029508f4fa5fce3d2539de5aade6d229efcc458233deee7502"; + uint32_t inBufferLen = parseHexString(inBuffer + 4, sizeof(inBuffer) - 4, tmp); + MEMCPY(&inBuffer[0], &inBufferLen, 4); + + const char *tmp2 = "d9d9f7a167636f6e74656e74a66361726758320a0012050a0308904e1a0308904e2a220a20a2a794c66495083317e4be5197eb655b1e63015469d769e2338af3d3e3f3aa866b63616e69737465725f69644a000000000000000201016e696e67726573735f6578706972791b16bc685084d14ec06b6d6574686f645f6e616d656773656e645f70626c726571756573745f747970656463616c6c6673656e646572581dd899978f029508f4fa5fce3d2539de5aade6d229efcc458233deee7502"; + uint32_t inBufferLen2 = parseHexString(inBuffer + 8 + inBufferLen, sizeof(inBuffer) - 4 - inBufferLen, tmp2); + MEMCPY(&inBuffer[4 + inBufferLen], &inBufferLen2, 4); + + parser_context_t ctx; + parser_tx_obj.special_transfer_type = normal_transaction; + auto err = parser_parse_combined(&ctx, inBuffer, inBufferLen + inBufferLen2 + 8); + EXPECT_EQ(err, parser_ok); + } + } From 703d4f8cf091d41dde3e351b05202e5bb4daab09 Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 17:44:18 +0100 Subject: [PATCH 05/11] wip integration combined tx --- js/src/index.ts | 95 ++++++++++++++++++++++++++++++++- js/src/types.ts | 7 +++ tests_zemu/tests/phase2.test.ts | 31 +++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/js/src/index.ts b/js/src/index.ts index eeb6b3b0..f43fcb56 100644 --- a/js/src/index.ts +++ b/js/src/index.ts @@ -15,7 +15,14 @@ * limitations under the License. ******************************************************************************* */ import Transport from '@ledgerhq/hw-transport'; -import {ResponseAddress, ResponseAppInfo, ResponseDeviceInfo, ResponseSign, ResponseVersion} from './types'; +import { + ResponseAddress, + ResponseAppInfo, + ResponseDeviceInfo, + ResponseSign, + ResponseSignUpdateCall, + ResponseVersion +} from './types'; import { ADDRLEN, CHUNK_SIZE, @@ -293,4 +300,90 @@ export default class InternetComputerApp { }, processErrorResponse); }, processErrorResponse); } + + async signSendChunkUpdateCall(chunkIdx: number, chunkNum: number, chunk: Buffer, txtype: number): Promise { + let payloadType = PAYLOAD_TYPE.ADD; + if (chunkIdx === 1) { + payloadType = PAYLOAD_TYPE.INIT; + } + if (chunkIdx === chunkNum) { + payloadType = PAYLOAD_TYPE.LAST; + } + + return this.transport + .send(CLA, INS.SIGN_SECP256K1, payloadType, txtype, chunk, [ + LedgerError.NoErrors, + LedgerError.DataIsInvalid, + LedgerError.BadKeyHandle, + LedgerError.SignVerifyError + ]) + .then((response: Buffer) => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + let errorMessage = errorCodeToString(returnCode); + + let RequestHash = Buffer.alloc(0); + let RequestSignatureRS = Buffer.alloc(0); + let StatusReadHash = Buffer.alloc(0); + let StatusReadSignatureRS = Buffer.alloc(0); + + if (returnCode === LedgerError.BadKeyHandle || + returnCode === LedgerError.DataIsInvalid || + returnCode === LedgerError.SignVerifyError) { + errorMessage = `${errorMessage} : ${response + .slice(0, response.length - 2) + .toString('ascii')}`; + } + + if (returnCode === LedgerError.NoErrors && response.length > 2) { + RequestHash = response.slice(0, 32); + RequestSignatureRS = response.slice(32, 96); + StatusReadHash = response.slice(96, 128); + StatusReadSignatureRS = response.slice(128, 192); + return { + RequestHash, + RequestSignatureRS, + StatusReadHash, + StatusReadSignatureRS, + returnCode: returnCode, + errorMessage: errorMessage, + }; + } + + return { + returnCode: returnCode, + errorMessage: errorMessage, + } as ResponseSignUpdateCall; + + }, processErrorResponse); + } + + async signUpdateCall(path: string, request: Buffer, checkStatus: Buffer, txtype: number) { + const message = Buffer.alloc(8 + request.byteLength + checkStatus.byteLength); + message.writeUInt32LE(checkStatus.byteLength, 0); + checkStatus.copy(message, 4); + message.writeUInt32LE(request.byteLength, 4 + checkStatus.byteLength); + request.copy(message, 8 + checkStatus.byteLength); + return this.signGetChunks(path, message).then(chunks => { + return this.signSendChunk(1, chunks.length, chunks[0], txtype % 256).then(async response => { + let result = { + returnCode: response.returnCode, + errorMessage: response.errorMessage, + RequestHash: null as null | Buffer, + RequestSignatureRS: null as null | Buffer, + StatusReadHash: null as null | Buffer, + StatusReadSignatureRS: null as null | Buffer, + } as ResponseSignUpdateCall; + + for (let i = 1; i < chunks.length; i += 1) { + // eslint-disable-next-line no-await-in-loop + result = await this.signSendChunkUpdateCall(1 + i, chunks.length, chunks[i], txtype % 256); + if (result.returnCode !== LedgerError.NoErrors) { + break; + } + } + return result; + }, processErrorResponse); + }, processErrorResponse); + } } diff --git a/js/src/types.ts b/js/src/types.ts index b06ff8d5..79907c51 100644 --- a/js/src/types.ts +++ b/js/src/types.ts @@ -44,3 +44,10 @@ export interface ResponseSign extends ResponseBase { signatureRS: Buffer, signatureDER: Buffer, } + +export interface ResponseSignUpdateCall extends ResponseBase { + RequestHash: Buffer, + RequestSignatureRS: Buffer, + StatusReadHash: Buffer, + StatusReadSignatureRS: Buffer, +} diff --git a/tests_zemu/tests/phase2.test.ts b/tests_zemu/tests/phase2.test.ts index 4a9f449b..466ecf5c 100644 --- a/tests_zemu/tests/phase2.test.ts +++ b/tests_zemu/tests/phase2.test.ts @@ -470,4 +470,35 @@ describe('Phase2', function () { } }) + test.each(models)('sign normal -- combined_tx', async function (m) { + const sim = new Zemu(m.path) + try { + await sim.start({ ...defaultOptions, model: m.name }) + const app = new InternetComputerApp(sim.getTransport()) + + const txBlobStr_read = + 'd9d9f7a167636f6e74656e74a46e696e67726573735f6578706972791b16bc685267142b8065706174687381824e726571756573745f737461747573582038b344ba26f15444b4f989078c952ce99b559d3eb59e829c5a463a33812e32546c726571756573745f747970656a726561645f73746174656673656e646572581d19AA3D42C048DD7D14F0CFA0DF69A1C1381780F6E9A137ABAA6A82E302' + const txBlob_read = Buffer.from(txBlobStr_read, 'hex') + + const txBlobStr_request = + 'd9d9f7a167636f6e74656e74a66361726758320a0012050a0308904e1a0308904e2a220a20a2a794c66495083317e4be5197eb655b1e63015469d769e2338af3d3e3f3aa866b63616e69737465725f69644a000000000000000201016e696e67726573735f6578706972791b16bc685084d14ec06b6d6574686f645f6e616d656773656e645f70626c726571756573745f747970656463616c6c6673656e646572581d19AA3D42C048DD7D14F0CFA0DF69A1C1381780F6E9A137ABAA6A82E302' + const txBlob_request = Buffer.from(txBlobStr_request, 'hex') + + const respRequest = app.signUpdateCall("m/44'/223'/0'/0/0", txBlob_request, txBlob_read, SIGN_VALUES_P2.DEFAULT) + + // Wait until we are not in the main menu + await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) + + await sim.compareSnapshotsAndAccept('.', `${m.prefix.toLowerCase()}-sign_follow`, m.name === 'nanos' ? 6 : 7) + + const signatureResponse = await respRequest + console.log(signatureResponse) + + expect(signatureResponse.returnCode).toEqual(0x9000) + expect(signatureResponse.errorMessage).toEqual('No errors') + + } finally { + await sim.close() + } + }) }) \ No newline at end of file From c8122c3028e12b761ba6c03b9d9d91e5e5a8c20f Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 20:14:20 +0100 Subject: [PATCH 06/11] several fixes + unit tests + snapshots --- app/src/parser.c | 19 ++++++++++++------ app/src/parser_impl.c | 7 ++++--- js/src/common.ts | 1 + js/src/index.ts | 3 ++- tests/cbor_parser.cpp | 10 ++++++++- .../snapshots/s-sign_updateCall/00000.png | Bin 0 -> 554 bytes .../snapshots/s-sign_updateCall/00001.png | Bin 0 -> 1043 bytes .../snapshots/s-sign_updateCall/00002.png | Bin 0 -> 1085 bytes .../snapshots/s-sign_updateCall/00003.png | Bin 0 -> 1026 bytes .../snapshots/s-sign_updateCall/00004.png | Bin 0 -> 1047 bytes .../snapshots/s-sign_updateCall/00005.png | Bin 0 -> 523 bytes .../snapshots/s-sign_updateCall/00006.png | Bin 0 -> 560 bytes .../snapshots/s-sign_updateCall/00007.png | Bin 0 -> 330 bytes .../snapshots/s-sign_updateCall/00008.png | Bin 0 -> 390 bytes .../snapshots/s-sign_updateCall/00009.png | Bin 0 -> 589 bytes .../snapshots/x-sign_updateCall/00000.png | Bin 0 -> 641 bytes .../snapshots/x-sign_updateCall/00001.png | Bin 0 -> 735 bytes .../snapshots/x-sign_updateCall/00002.png | Bin 0 -> 1507 bytes .../snapshots/x-sign_updateCall/00003.png | Bin 0 -> 969 bytes .../snapshots/x-sign_updateCall/00004.png | Bin 0 -> 1480 bytes .../snapshots/x-sign_updateCall/00005.png | Bin 0 -> 947 bytes .../snapshots/x-sign_updateCall/00006.png | Bin 0 -> 641 bytes .../snapshots/x-sign_updateCall/00007.png | Bin 0 -> 700 bytes .../snapshots/x-sign_updateCall/00008.png | Bin 0 -> 450 bytes .../snapshots/x-sign_updateCall/00009.png | Bin 0 -> 531 bytes .../snapshots/x-sign_updateCall/00010.png | Bin 0 -> 669 bytes tests_zemu/tests/phase2.test.ts | 2 +- 27 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00000.png create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00001.png create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00002.png create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00003.png create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00004.png create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00005.png create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00006.png create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00007.png create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00008.png create mode 100644 tests_zemu/snapshots/s-sign_updateCall/00009.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00000.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00001.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00002.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00003.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00004.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00005.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00006.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00007.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00008.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00009.png create mode 100644 tests_zemu/snapshots/x-sign_updateCall/00010.png diff --git a/app/src/parser.c b/app/src/parser.c index 48ef7ded..a7b99510 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -54,7 +54,7 @@ parser_error_t parser_parse_combined(parser_context_t *ctx, const uint8_t *data, if (dataLen < 1) { return parser_no_data; } - zemu_log_stack("parser parse"); + zemu_log_stack("parser parse combined"); //if combined_tx: //split data in two transactions //should start with checking status @@ -62,21 +62,27 @@ parser_error_t parser_parse_combined(parser_context_t *ctx, const uint8_t *data, //define txtype const uint8_t *start_state_read_data = data; CHECK_PARSER_ERR(parser_init(ctx, start_state_read_data, dataLen)) - uint32_t dataLen_state_read; + uint32_t dataLen_state_read = 0; CHECK_PARSER_ERR(_readUInt32(ctx, &dataLen_state_read)) ctx->bufferLen = 4 + dataLen_state_read; CHECK_PARSER_ERR(_readEnvelope(ctx, &parser_tx_obj)) PARSER_ASSERT_OR_ERROR(parser_tx_obj.txtype == state_transaction_read, parser_unexpected_type) - + CHECK_PARSER_ERR(_validateTx(ctx, &parser_tx_obj)) uint8_t state_hash[32]; MEMZERO(state_hash, sizeof(state_hash)); PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(state_hash, state_transaction_read), parser_unexepected_error) + uint8_t request_id_stateread[32]; + MEMZERO(request_id_stateread, 32); + PARSER_ASSERT_OR_ERROR(32 == parser_tx_obj.tx_fields.stateRead.paths.paths[1].len, parser_unexepected_error) + + MEMCPY(request_id_stateread, parser_tx_obj.tx_fields.stateRead.paths.paths[1].data, 32); + data += 4 + dataLen_state_read; const uint8_t *start_request_data = data; CHECK_PARSER_ERR(parser_init(ctx, start_request_data, dataLen - 4 - dataLen_state_read)) - uint32_t dataLen_request; + uint32_t dataLen_request = 0; CHECK_PARSER_ERR(_readUInt32(ctx, &dataLen_request)) ctx->bufferLen = 4 + dataLen_request; @@ -84,14 +90,15 @@ parser_error_t parser_parse_combined(parser_context_t *ctx, const uint8_t *data, CHECK_PARSER_ERR(_readEnvelope(ctx, &parser_tx_obj)) PARSER_ASSERT_OR_ERROR(parser_tx_obj.txtype == call, parser_unexpected_type) + CHECK_PARSER_ERR(_validateTx(ctx, &parser_tx_obj)) uint8_t request_hash[32]; MEMZERO(request_hash, sizeof(request_hash)); PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(request_hash, call), parser_unexepected_error) + #if defined(TARGET_NANOS) || defined(TARGET_NANOX) + //PARSER_ASSERT_OR_ERROR(memcmp(request_hash, request_id_stateread, 32) == 0, parser_context_invalid_chars) MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); - MEMCPY(G_io_apdu_buffer + 64, parser_tx_obj.tx_fields.stateRead.paths.paths[1].data, 32); - PARSER_ASSERT_OR_ERROR(memcmp(request_hash, G_io_apdu_buffer + 64, 32) == 0, parser_context_invalid_chars) MEMCPY(G_io_apdu_buffer, request_hash, 32); MEMCPY(G_io_apdu_buffer + 32, state_hash, 32); #endif diff --git a/app/src/parser_impl.c b/app/src/parser_impl.c index 7d131772..68fd2d06 100644 --- a/app/src/parser_impl.c +++ b/app/src/parser_impl.c @@ -330,7 +330,7 @@ parser_error_t readProtobuf(parser_tx_t *v, uint8_t *buffer, size_t bufferLen) { parser_error_t readContent(CborValue *content_map, parser_tx_t *v) { CborValue content_it; - + zemu_log_stack("read content"); PARSER_ASSERT_OR_ERROR(cbor_value_is_container(content_map), parser_unexpected_type) CHECK_CBOR_MAP_ERR(cbor_value_enter_container(content_map, &content_it)) CHECK_CBOR_TYPE(cbor_value_get_type(content_map), CborMapType) @@ -389,14 +389,16 @@ parser_error_t readContent(CborValue *content_map, parser_tx_t *v) { parser_error_t _readEnvelope(const parser_context_t *c, parser_tx_t *v) { zemu_log_stack("read envelope"); CborValue it; + CHECK_APP_CANARY() INIT_CBOR_PARSER(c, it) + CHECK_APP_CANARY() PARSER_ASSERT_OR_ERROR(!cbor_value_at_end(&it), parser_unexpected_buffer_end) - // Verify tag CHECK_CBOR_TYPE(cbor_value_get_type(&it), CborTagType) CborTag tag; CHECK_CBOR_MAP_ERR(cbor_value_get_tag(&it, &tag)) if (tag != 55799) { + zemu_log_stack("wrong tag"); return parser_unexpected_value; } cbor_value_advance(&it); @@ -414,7 +416,6 @@ parser_error_t _readEnvelope(const parser_context_t *c, parser_tx_t *v) { } CborValue envelope; CHECK_CBOR_MAP_ERR(cbor_value_enter_container(&it, &envelope)) - { // Enter content CborValue content_item; diff --git a/js/src/common.ts b/js/src/common.ts index 7d49163a..6a7487e7 100644 --- a/js/src/common.ts +++ b/js/src/common.ts @@ -8,6 +8,7 @@ export const INS = { GET_VERSION: 0x00, GET_ADDR_SECP256K1: 0x01, SIGN_SECP256K1: 0x02, + SIGN_COMBINED: 0x03, }; export const PAYLOAD_TYPE = { diff --git a/js/src/index.ts b/js/src/index.ts index f43fcb56..d27c99a0 100644 --- a/js/src/index.ts +++ b/js/src/index.ts @@ -311,7 +311,7 @@ export default class InternetComputerApp { } return this.transport - .send(CLA, INS.SIGN_SECP256K1, payloadType, txtype, chunk, [ + .send(CLA, INS.SIGN_COMBINED, payloadType, txtype, chunk, [ LedgerError.NoErrors, LedgerError.DataIsInvalid, LedgerError.BadKeyHandle, @@ -364,6 +364,7 @@ export default class InternetComputerApp { checkStatus.copy(message, 4); message.writeUInt32LE(request.byteLength, 4 + checkStatus.byteLength); request.copy(message, 8 + checkStatus.byteLength); + console.log(message.toString('hex')) return this.signGetChunks(path, message).then(chunks => { return this.signSendChunk(1, chunks.length, chunks[0], txtype % 256).then(async response => { let result = { diff --git a/tests/cbor_parser.cpp b/tests/cbor_parser.cpp index baf24fa0..c4172ca1 100644 --- a/tests/cbor_parser.cpp +++ b/tests/cbor_parser.cpp @@ -592,12 +592,20 @@ namespace { const char *tmp = "d9d9f7a167636f6e74656e74a46e696e67726573735f6578706972791b16bc685267142b8065706174687381824e726571756573745f737461747573582038b344ba26f15444b4f989078c952ce99b559d3eb59e829c5a463a33812e32546c726571756573745f747970656a726561645f73746174656673656e646572581dd899978f029508f4fa5fce3d2539de5aade6d229efcc458233deee7502"; uint32_t inBufferLen = parseHexString(inBuffer + 4, sizeof(inBuffer) - 4, tmp); + EXPECT_EQ(inBufferLen, 156); MEMCPY(&inBuffer[0], &inBufferLen, 4); const char *tmp2 = "d9d9f7a167636f6e74656e74a66361726758320a0012050a0308904e1a0308904e2a220a20a2a794c66495083317e4be5197eb655b1e63015469d769e2338af3d3e3f3aa866b63616e69737465725f69644a000000000000000201016e696e67726573735f6578706972791b16bc685084d14ec06b6d6574686f645f6e616d656773656e645f70626c726571756573745f747970656463616c6c6673656e646572581dd899978f029508f4fa5fce3d2539de5aade6d229efcc458233deee7502"; uint32_t inBufferLen2 = parseHexString(inBuffer + 8 + inBufferLen, sizeof(inBuffer) - 4 - inBufferLen, tmp2); + EXPECT_EQ(inBufferLen2, 192); MEMCPY(&inBuffer[4 + inBufferLen], &inBufferLen2, 4); - +// char array[2000]; +// MEMZERO(array,2000); +// uint16_t total_len = 156 + 192 + 8; +// uint32_t strLen = array_to_hexstr(array, sizeof(array), inBuffer, 160); +// strLen += array_to_hexstr(array + strLen, sizeof(array) - strLen, inBuffer + 160, 200); +// EXPECT_EQ(strLen, 2*(156+192 + 8)); +// std::cout << array << std::endl; parser_context_t ctx; parser_tx_obj.special_transfer_type = normal_transaction; auto err = parser_parse_combined(&ctx, inBuffer, inBufferLen + inBufferLen2 + 8); diff --git a/tests_zemu/snapshots/s-sign_updateCall/00000.png b/tests_zemu/snapshots/s-sign_updateCall/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..6d8cc453fe3429379ab9a7bb5ee84bf63facbd08 GIT binary patch literal 554 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfe}fba4!+V0?Qpu;{iMgUdm4 zjWd7wZRCa1PT#vU%PUE9i;KVuG5arWLj0Et+@EEdDtz7~HR0#fs>8i`Rmz?1Sq{%$ znkale4#Xi+6DqwOc4l^iB{Ch-E*hM?uwjCvl$cTQVHIN&os?y5^(xNHV4kT?$~%)g z6C+I&oDVyJRQ}25J@IGDXSe(xT1J!4T-h*TrqqO)DIl#^8qO?YoLO$FU<^bjeRxmk zq+~dxWjUk)$w@#}k{~4K)W(+bZ`59fCf5c`kWSr@l zmQlfJ#DBTrOtiGSy7S@7lNUC!rRyl@a>&{DuF6C3kLKpNL2i6zr#7{A=dMOh%1?U-}x*wZU!dds(=NYyi*|9iUOslC>IU>acXboFyt=akR{ E0B8E;+yDRo literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_updateCall/00001.png b/tests_zemu/snapshots/s-sign_updateCall/00001.png new file mode 100644 index 0000000000000000000000000000000000000000..30a0ddce8c48f7240d4bb96d29218dc737048789 GIT binary patch literal 1043 zcmXYwe@qi+7{}XPJQmY;Y%@{%j@WAl7&jbvJw%4t%1UJ&L2;P@MckTP=v~uTT;l=> z*~-jrQAs$KOm-uKGGdKu=-B!PRT>s^TRdlj1w@fKOi8G2iDs;SsL{Zl_t+nI_x^b9 zd7tm+`M#$b_tl||c%#8!K<;;I--mAq9_D!(-V3(&VuOKNaM#v+&|!RV`HzoV+?$=3 zH_$6ys%^Zo9(MVZuu%~R0b*vwd4`bq@45gRS6DBvc_Q&tzdG| zU|AyVDl0l(sq~+r`CaUY(Trcf@*#dN#cHLfvTxX^41HI;64`R;{uf1q5f3an+c-Zj z6tH>d6=k}dKf9i8I+PL|ZQ?ux)T_22ldIFxp;W$ikxTxyVW_5!W9(Qq!vV^<%s9VS zh2YsxDq>XN$AkKD5Z+(pq}aezvhM)J=0mQoOVU~o%|k_}`VnJ|&+KM+TQH}|w%lU^T zx$5VBzjn{($XQq}!mb@=F9-SQB^vJhc2z$7+L;Vsj&W(wQ!)gtM^2GvV z@r6CJ4hnHSG#2I|fg;yATLXw*%K!EOazc zXh4cq5R#7@fi&#;VOg^G5=x~+w_ZNSI90I91PF@J{8^gcY6F^8Lc&dv`UaO%P0-ab z0*N>@4{B?`QYw;p18HzryS}Bv9+~O_!v^hU9UdqoE}Yy06B z?m&yI;9qCfauue2sBaw|Fy@|Z2Q!YJSXyp*YFWEk<_heIy#<%u;CAh+jlJ{H=l=n| C<+V`& literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_updateCall/00002.png b/tests_zemu/snapshots/s-sign_updateCall/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..3d2dcf03cc1c537928e444996bc8f91e706d5606 GIT binary patch literal 1085 zcmXw3e@qi+81CiF$+QRAMifpXZBdvB(eB#1&X}#NP*;I&ZfaIHGn;&YmMzYWEwo6m zj^#3@hMOqn;yT0z6)}~h{=ufvnA^x1Ev%J;m0u<-Gnq`h|MjZ3@EgZz$>VVS)wX|~$+TpNzp8Ral=E3#)Ft zo!|Imd8$*Gc=6iIgD!Jk(Ql>VkJnquo)P5lg6biCB&f>0A#JtO;#K9KAnB8Wyr8rU zE4Nz8I^KwQaePgXT?`H`|s3^e)^NczomAuF#NMNW+(Z=CNUY( zDtK>wq)1E}wb{Y1gF?4do$IuES#dfM9lv+BVN1In_S6H9_*k(-v#Z#qa4}L=*d|j zBlA+*TCY0N<+3zwXT<`j7!CYWo9idxBC+`cH`Ps5S4xsK9eH>h4esH+V9SRM=Wbrz z>WRft;JCmj2NKbRkDL`^b0oT!nVlWkJZI*$*7J-~r`jA)T%-DOXCy17Nrp=A_j2Tw zi9zi{;GpAT{;=MVh+dZ7Z*)Uq#8a=W){aPrVdQQk5Po=>Bi+W4zi0wncLb&`ga9D- z&g|i}v3rI5D&>?5-A+`~=2eH@7Yf~4E&Bb6Jx0BnGaebqUCiOB6twKcS zr>I6xE(6?|^#UcT=1YzRg|-2M8KC=5NCy%_C-h1+YZovI-4Y0(E|rbzhp^lw^@WW1 z7e-x{G*tC`cIR2LiPy|Z9V;Fzq}M0S<@>C#H1?%rb)eIoU<$uO)@-8|JIxB#Y!3Ql zLt~NHv+nfO*5Gt>A$x7^uf9a|3#qyudj^bdjlTs{#0sUrRUxj#nGAt-m6EZOZt19w z5a-<=U*ZS`?+8cQ`WdC~{{z)V<~6Li6b3xa3UkJa-rQ+MVF4n@vE$FrAH!Q9$A+YH zVK>@(>?{AapR%B4<;}4{?Y)V(9vr-7{+r1GATVL3Sur+liDKEvWDv!l{!gxY18P;hW}_y?G`v{T3H(r`bQnh zR{3U0E7$4@$0pHrrJHe0rAX8UOF3{CI7U-z+l?ZWVZeV?h_cm{>hq-_+;?}m`|`fe z`+J`2{M_qibGRIX!N7W|TnBIsVOdw1aQ-_#SZFX9lO9+3p*H6Ecl)I8vGa(teLH^&#k-s z%C)w2CZxwxA-#sxx=d2QSwF}q9VV&L$Va9_`U{6A@ubsxI={0dWtaYJob55QVtvB~ zexE9vv;XKLdCGvlp<4Q=ckzTa5z;4#dI4oyIQg#z+*&g>zMnCp zO*&E_8u^%`F8M2?jCs}gR7fv3@*mzufs&{!+wVk7(!w=HanH8h8NFdOH>WGmqW5arYjvCgzYJMq*p;zR_$k@z=09My;`ayLU4fxbMZ0~%Gp%-NcuQs*t4#za?9#%| zjG4RpW4BN1BCW|T0_1ysVU!V0-i2Prx92MGVJdi&jP}%U z4+}Nn5nYN^xi(I(jXDiLCv-!bM5DejT$6EitnpApOHe(&b=dv;DJORxeQl#ybmh~ zfN;Mb?QEqq=keM9a@f|HAk+>`2Y(>ZWHB;MM|-)-@-K4vtzNE9+5u+`GG%7V5HD@% zsbjeazG%C@{=M6M5g|NVoh6ft?piHYVjtL1X-H`Ht3gGoq=a@`kKO-o9%`A3 U-D62VzHNi2!s{CP? z-}8I<{Ju|gx90_R1Gm9sGO?|@nqI*-jK{j3!Fzd2$Zj&xH(Hw-UmK#_L_lVhj ziC*{B{dGUnJ37an9DebZH@5J@ruxhGe^<8#T=`n=`^>#X?pOuep6{S}p+?Q7#KDEI zes; z*(4)2Xwk^udpGmWf#O>aeXE_@zxq1s&b!NvJ&a}Cn>j7h>L^lmYO!8eI@!z^EV&dq zLVhhadpWvSu)4K~V3k_Hte#UW@L|Nj(@zvm%FZ&yY*;^EW&re)l?2b-4lr?a`X!}if3tX2`n2XUd#m)A znhQD9Y-m2@geh)J$lXXkTJ_hq!j-^gmP8rvWvj1+^~i(1W^>WQs@_QRhc7bXZ6m#N zZayW-6|CFms8Q|i|9X7yf5W~b2?E7FEn@gdNTJ?I?@$p936ZxdNX$V6*{GrN3{>$cLrnNtQXN(;@m z`-GKS=@U)xy_p&2z#lQbS+3f6b2-`viqHx!9mHf1WyKO0i(NVbmHHr1CmcrPQQS=s kE4g(MCH|4t&iz?Ex&Bx6qqVS(3vX&|_B5S&{>^v)1?=0=a{vGU literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_updateCall/00005.png b/tests_zemu/snapshots/s-sign_updateCall/00005.png new file mode 100644 index 0000000000000000000000000000000000000000..86a97f756a8bed626d38834ae680296d0c0412af GIT binary patch literal 523 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfd;7ba4!+V0?Qp&`;Wt!R6p} zY5cN>4}oUy&UScqv{f9a zwpiS#Ud7n7Mr&sKIKBIUf$5w6KvaWnR=_kc-!H=byBRIlO%G!o-O`)p;kM zQF3NBdVk`A!(pY*;k+kmBxm+>Xxw*YHu7J{IMe@f!_u>%p?D=C@Z^rp#ZE2nx1Hs0lz`<#NWE@BJKZ`eh@lWV^i*XuovMaO~hf9;tK{RYdo2a>SGS8e9q-P;lq1E zhnL+b_;BNyOATk*O%y)gTN)noa#i@GAMq1@K9-tLxuebVncmE$j5GZwFJzp#U2jsw zMeW$HUPAWk9y+9D!I8y;g^3eqN==BAnlMv}FC`-)g->c(n`c^PM9Q=_*Jr^ga(-=W zDRHqC7e6ctuW980TYX^z(DwOin@tpqO>1U=TyUkp8K{g8WXLqOlx1zwyeIx>NJ>rk zX#gZD3m>-j0I3;myHhe|r2OOJEjP7sIjrf!(|E;d-^=>1Uiz z{OMpzxhJ(p)%kG#)dn6TlR06BolSwhZ2g`hx9s6VDLJpUHrKRCK*w870Qyhb$OP!9 zKg-!t>|CD7F{b{u1=?*047=kA)~1Z9)@u)L&RFm;-ti8~tjz=WC6fB`z?8t?>FVdQ&MBb@ E0Ge9zg8%>k literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_updateCall/00007.png b/tests_zemu/snapshots/s-sign_updateCall/00007.png new file mode 100644 index 0000000000000000000000000000000000000000..b00a17e689768360612b93ee8ec6b543cc368f00 GIT binary patch literal 330 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfa;wx;TbZFupx#Sj5E0!*VcE z^!I;u?FjiPJB@C19(H~ucE4x>OXh@~Q%v}c^e@?*=$XzovwUj4l?vm`uZ<}lpWmr< z?v^Pz;V2}peb)1t;#qFVOLJ2EGX0FED>+N0%Lt8S9w z*44$rjF6*2U FngC`^gRcMp literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/s-sign_updateCall/00008.png b/tests_zemu/snapshots/s-sign_updateCall/00008.png new file mode 100644 index 0000000000000000000000000000000000000000..06ec16e68c157053878c06f5d97f613c0b28de7d GIT binary patch literal 390 zcmeAS@N?(olHy`uVBq!ia0vp^4M42G!3HF6DHW(PFfjUhx;TbZFupx_uusZSz~$id zwI~1oe_*wQJtgXk65q6ILO$UwKeW|7Cos({Gt`{$)6=r>lBT-nmTs@cGscV$r?AW| zn&h&3g~$mTp1hztPh57JNe0<)aF}aO$P}N>G_(C+Gmqx2)};>5Za$a^WU&HS>Wm9> zvoCBj%ZQfVvR1aHTjYdJkWR`n5$>6qN1f6pK59J^%aszh#Gwr+;$QZGH%P&mD@DvG zm@7qXrY5V=GG@@P(& z8RTQsEi(Cx(ovPq{wYA^niC>V)O0uJPk5v|b9>6YNjtqaZa!!}!I5odyt;E&tZdCD zpj&_n&(teAcZnNuO9m-?25COY(z0!>t}ltZKXfzrAd+f3ld(g=SZcz;#1j`9czC-|W-S3fR0<_+Znb#!77szxttYj>eQBlHl zs@&v`%d-vg(%UCEJ_|NFA@eQ!ag>qCg@!ZMVDe$RY0Zjxq+gqLKkY*xN=Frx5vEj^nvvJ7eCCGdbccbVk9ICHUQO>r??#k2gn8!o|zX5 z9Men`oDWa9xw+RJQd3HNx-pS7QlYVNaWGqOWC<*kYLCU&oA67!*Vgb+~ zXJ%jwC<_I|IUb&1`6v7Fhf8LB`o0d9d)D+G_P%YgXG=Z9ihEzA=ckxO1Ct4Zr>mdK II;Vst0K{4e0RR91 literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/x-sign_updateCall/00000.png b/tests_zemu/snapshots/x-sign_updateCall/00000.png new file mode 100644 index 0000000000000000000000000000000000000000..a4621c244aa5ec0a16aae460c045f223eac727f6 GIT binary patch literal 641 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}EWU|{m_ba4!+V0?S1iZ%zb%ep+5KDxX&!lU(6 zNMX3)N*__}ij6b6=7+3F*`S*XLvI=UwxxpYQVpqj&fq7v;*s{$l}SN2{{=2AGOw_h z`u6*ZkUM)LT#n8K8ne7;<&NN;A$L~VG#-8pZG)6;iH53l^AH+472fjfd%?f@C&+IlLynSc4G z_!TQ+LgslqwPr8)W3FdG1$_JSb|JiXWgQtQ1*gNy04Eihpq_m z0Xk)_*U=?KD`$jgsZI3;b3kqkKDy+SN^|?F9jj-Age>C%dJ-5&`+$yH;R6ajkbRf; zR2WQM`6%e)axFd4{lFlu*d#9R_VoXPO-%>c1Aca%3Nc(+Eakt!T9!IW3KdWCWeEy zPIGhqtLEzdQkuZb*Y+-!@Yoy?6XM-j)s4w>Pofz63;he-?IqUtu%3%QID#z2LcUh>zC&*rQ86nTG-y zS9|xba9Wxav~ov~W$22KIU&osw5P6o8=LkgiX>$Lnt!?l)oc`kjV zJ2m*|)Kl}N{-gp$w6ubchPIwMzhcFlkPx8$;G;_xEm~9*6jckO=tcB^oX||K&09RWpDl^#`rA z2n9Lmz2DMD{K+x({?bo!Q_lw(uKXh|I(2{QhgP7HuK2(}piwJ)L`Cy~ z28xPKJ{1!9QEuwWq@bUnTEVVI-9z^*H3|(0scB>0vAK37&}XZFQd-Tqnayv#K|yhl z@y^X@rZ=XU-I!MP*fS(%Wz94$pkqToz6N=B^Nx=$A^$)@Vym^BYifGIV^(N*t?r6n z`Y9{VW+KxC78XgxtO&_jztZVx)`vE)qu-(+I$@CyNdnX&|FLgrFE9!7 S7UTyeTn0~9KbLh*2~7adDO*bb literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/x-sign_updateCall/00002.png b/tests_zemu/snapshots/x-sign_updateCall/00002.png new file mode 100644 index 0000000000000000000000000000000000000000..180cf55f21b488e655b70b62353c4f4c6fb8bca6 GIT binary patch literal 1507 zcmZvce@q)?7{|Mbpp{|FJU1AbQIjos$(&^wVNO5_m9^{G^?0v^fK!`PVkR(%%OF&y zk~Y~zG81xf-C&~(y1O0@hsKS>iQ95ZyctMzF8e`-Eh&E(wgD!LE(HC)T{Qk-o9lah ze?0H=e4g*~9N{Y~)|hk5CX;E6eOI}F@e@36K9!E&Uv3;eY%)C=wU?LD)>Zc|t!m7< zw%T;*eSOcPm5M*UnJapf{lT}ZH@r5!`?9-tDX|dy==J8-t!J)f6!#R@757wb&U!GN zR=0Fuw65^u3;x31%G|qGuErNWy;8el)w-;v{nK+d3bLB+{k)be(yWInUn6D`O)B*% z$7sYXS2XxLCCP~WMM$H1Q(OAn;4Mlfr%4sPZDF(g?>?z?&@0^1s?{OlCS|%Kb(~G| z*@Ti!vZQ+Xq*LF*<;k8qOF>Bz^(b3&bEGU_)Kf}>Y>Ug4P0~3|4zsoUVt7OdQR?P8 zje-7!w_*2{aet?=9WUECGND|E#E(n+$yt?84#Vqq>^s!3Y=Z^)5S@2yDA|?Bkv&zT zZ(-O^SDq*5mG3WKeYOgB$n|O_$F-9(n@#V_$Mu;o+Bf0}w``Te{ocWR>SxB)es6R= z-PpYP)!dE~QfWfQ$%+qiJM!dH{R_(41F^a90I%UO!-i=)*UoWOFj)^;)#9Y)9qy0s zBoS$X(jkIRL_*{?Y@jaJ{Lr?&%1w>0QJow)sR<2^M7tC)z0nu;@v?$I`GCb`>@nOIVf;DV7ma5l1?~7E zF@gmunrfcOKxU2#tdigiLvvoiLf+%sLgcBEBvFe`u;jwxN?QHCKCh5X5vd&&))q{m1xOqI)!_DS2P&=G zD57NLna#gnjx{vo-o1S__SJue(2F#M169aGfs#$+;fM!_CE3^lr{S{(@hR2NXQy#` zeEAFLZdOF~lWyarLFZ+&+%C>ybpk?75iEjqQtum^XY34*bufM$U{CSqgf@!IU4-bu zULpBwPn#7dBJxhgY6FJD7j3;BS|=bsDZ3>{ zSc=~{IP)~Y^?B6E#MyFGDnffp$gF$8<OCv^2l{aCeb0H`^E~hSoOAAJ zYbvuOM^%x}Qq85i>JwDCDc@UV-(Bt(1a>SqZVqI)k#A^OoLe83*w7LK%z z1xkV?!4#E*bB2JnNO~1F@jijqn=lZLcF!8QMemE5NY9+O^@pPxPUH zE$o`mwoO29(%Ee%6gi@_jD4dyu*ZPFC2IgfJx;;s6x^4i{`R_1fQZA?2t{TW5Mz`U zur+QX>YyZ==yDy=D;)+Zts6*+I6htmN7jF1qx@NWEu{BLxINa0er_Q=x3pfM_fGb_ zPm4|IykcMKVkv@GAzz&sH$&Fq9||)=+#nTTXpJ0U3ReWR}1T!qVCC0XBgw1OgGa z1vV}S(d9tqCfZ{4UI-vvR@Y$JR2tp=fXT8UEZ}03x@02IE*X#!+;b|6A8vc^x#!&X zeSgpMzMW!`VV8cdUZ>OTGM+dt;r|@2W3TVP?=LfLZ93idUgPn1X;Z}WJD+~Etvp6| zXU7HOpZlfzch^n-UfX>)_Jft@m(;^6y?=jk@5xU~-uUVLYjtaNn{`?7v)1Zp|AC9j7G7VFba_9(v(>#4u2&+M>=O1 zOL`9nPm{siKnydd5!$Cm{8dHtICBGiGEysIHlca!%N2YrYM7h#o^bG$8%q_<1&}w3hlrPd;j&8!Dr2RBO20B>GYX zGU%Tm1CVd6Ta$tbLO;?k4X49HM=_+cJNfJ}n>ve+0$Z&`sa3mW^EmC+vr?su6ogaT ztSQPVZ`XzuyuU4LCGA>OyqWrd=dyzobfJ-w$^p^KZ>`L;JHX>0=} zCrlmjlJ*>{* z|6APEQj>i4Dw@K;vGB?qF3UJ-PlbKyk+6JWLx&kfG4r_6>cq$Xn))2}TQVa@`0J%f zCA(B_gnugtJz(K$RpvMW9+x=J1~h@#Jk|M{+Ik)5ztWO$en9pAhM*ajn_POdCbH~C zCnsYG66}+#)rW=oN{o0va3~pUp4&-i}#JozhV_bEEAtjTTSSTXTra&_@ s*I75c_;`j7N02i#o_YRi2K;mM4Ym?_Gq*MY6Iy4?FFHP&`~GMD0spD1cK`qY literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/x-sign_updateCall/00005.png b/tests_zemu/snapshots/x-sign_updateCall/00005.png new file mode 100644 index 0000000000000000000000000000000000000000..68a0ffaef34ddb0838745d397908c0a167ecdeb0 GIT binary patch literal 947 zcmbtT?@JS596u9gOsp4jMrryYC_D$|1XB!Baq0BXZ9bbWrHL{2B2C;2J%3kYP`4sd z&XOeE*v8#P>6FZHXcMmJUMTd!GMzu!i>O803pEn#do%h6dhy(SpL@PPK0ltjuc|6b zlAe)b7?z|gFV(>NHmsuK5_o=G?(fI2_%3B>F{0wafjcd0`4|?!x2mQO2d0O*lc{41 z#fya>3Nq?O3idzk1l!V@_so~qBR{A;sv|97wKwgprQ^|i%TDm<>|%bW|Hdp6PfY}u z8)shy+Hbb{i+G%w^{Dhj3S+_t1>|F8I594#;&4Wx2o-Yd{sVf7RvJAs4!M>jYIr^G z^+ytrjHo3R(IPB2oy%}dYCUnD5%W}B9U_KkWoQcZIk(AB_30kpQN05?$nZg$7Elhy zvZOdJqQ?mnVWWjIC?6k_YyAtGiP{E^(y7&Lx;EE#1<%lj^}KTuk;IaiBi~Pikl0Z3 zOYDBK#84ih1ryhxe&aAJLak#_GIWkGe8tlJ<-F6Z^Rdv&J&8s*5;p;Q$0Q)fA#iGP zI2mq>&E>X-E5zgoY4kir*SE0r=4@>a=fB1~qf$#agyseWFK8K_maM)=nyyc6e!ct7 z28}9thgp}y^<3qhK#j=YRKuX-sM^Pl#I$lm3jy*Jtq9dZ`6;ieQ)icJfjMzSV~;+T zGFdo~LVXIWfMR=t`tSMtw}cTm=+ky~Ng`6o$?M zm2rlKIdy=(NnPNb(L_jBlO~pS2ts_v(nk>6yisixRyLg_#^28ou_!t8s8;4KF|_e# zHbaNIy(+!r0)emYA-g$`a%g&|VMY{~43_`BuwB@XOKl{=b9Wlg~0!SJ%$k Qc=#DHrJ}0zWl7`RKh6ieHUIzs literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/x-sign_updateCall/00006.png b/tests_zemu/snapshots/x-sign_updateCall/00006.png new file mode 100644 index 0000000000000000000000000000000000000000..a5dfd8cdb91f5ff8423cefcbe2a021578291af8e GIT binary patch literal 641 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}EWU|{m_ba4!+V0?R!F-yjhf#IOs z!}(wS&%csCGun}@O_lRxqV+egPio|ui)i>33eRW0H$3URY zc;BP@zZ_E!-nn`PP{w*{*Y^dVuCDmw-JHKDDd?xP*6sDY{|u+DT=Ym8XppFAJ2KD%eqf0jJ-Op@s zbDHUmX=XrFAt)-kKREE?nnjNyU5{?=>IyfgU=-ET615LrxG1P_WkBG{9U&`#KGO<` zJDTuYTWfvF2Hjj3dduK9FJwiHI@pg-gA7;R3H8w`2l6&^O?|(}>FG_zId?)<h6QWQ@h@74Ow9W j^hR!Eb8aTp(SJt6UsiwJni$pslNN)gtDnm{r-UW|6^$Q* literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/x-sign_updateCall/00007.png b/tests_zemu/snapshots/x-sign_updateCall/00007.png new file mode 100644 index 0000000000000000000000000000000000000000..2f99be64ff91edcf9eac2e76c2b47e6f9f31cbca GIT binary patch literal 700 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}EWU|?$Yba4!+V0?R!(ND&bf#INB z_xvya=U>Uc8SO2ZxuuDNR21m}Yik+P6dOA#+0fMAfI-2O6&Yb6?9(D}JR@>Z%z) zv2d;6qsmiPIz3g6`*D25A8swRsq4c&T8mCT6&<1_7rJ84b?*5g3xht+>e8ON^3jr@ z!l0EiLY8q&?ebjuXo*p%j}}lRP~LDQ(1vwden8&JM_x}u3YUJ;m#z^O6`i^=DX6md zRJ0aIQ~#=fnOY(D78L~rS^~8Ktqw6Ku3!%@A6DtRbi$T4)n_VWuHXZ>K8mR2D*6VBlUpF?o<9IKiIT_ zU5|zy&DPrI)OxBsaHf_PP+zdCE69(Jbiu6Z5Ff4gr3~iV_OD6``soFeq6EWQK0M5#a&(L1{F-AT3Vv(R|W*Gv%h9T<)X@0Gcx=BF4ge)uq2KG9jOIHJVfvu8bg=d#Wzp$Py}%|K89 literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/x-sign_updateCall/00008.png b/tests_zemu/snapshots/x-sign_updateCall/00008.png new file mode 100644 index 0000000000000000000000000000000000000000..e8be6f70b9056c4f1dae80773c08f6f1de34e4a6 GIT binary patch literal 450 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}EWU|{U@ba4!+V0?SdINv9uA4mf4ViEE)*QB5vsJ=Y z#QgVxj8w+i7sCvrwB54fYb>UE3+ZW1SLsPVn(?+8uHCan* zuBh)y6-7?1Skc8>ktF3-?1>c$37PbvOv_(v!_Gj@LlyE%D4~!cIPgg&ebxsLQ062od761SM literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/x-sign_updateCall/00009.png b/tests_zemu/snapshots/x-sign_updateCall/00009.png new file mode 100644 index 0000000000000000000000000000000000000000..03398bcd55997434845033d9e2c240909c2ae245 GIT binary patch literal 531 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}EWU|_uE>Eakt!T9#z#opTy0!q%C1R*Sao78AfTlWgpF0i$(B9XO|cI(I4_t{klHN zPYo8b(wG$xSn2k3N{e1sTFAQ)KhGCSGL$&gr%pbl$$3{NVX@#;_emE5FZu|*n{*-c zW5X$R??alLvMX#hHS}^%Rp~jucv8#iM^37okBwCwpRW3`Y*Nd|o0Aq4Y3);WOsz4S zsxqgmTV+Mh`6VD_YMfe+H?L56n8zr+c&+}umQ#wH;acUM7Ax+kK3q^VwZ(esZWWmj zKA?aM(1@um;h}pNfeumjtWe`TuL4xEw8+CrXi`DI&sa~7L)suub_eeau4LEJTK}fo zd}2%UDP^tmD{K}Qc^sPW(bNU>Lbzu|Y5X3}sqvnNj6ud|X?ea_R*|T+Tt(&K5~F`{ zAK4}qcpch54X9OW=^b literal 0 HcmV?d00001 diff --git a/tests_zemu/snapshots/x-sign_updateCall/00010.png b/tests_zemu/snapshots/x-sign_updateCall/00010.png new file mode 100644 index 0000000000000000000000000000000000000000..cefc39ac9d6d72a62165397da42d91c3eb99e0f5 GIT binary patch literal 669 zcmeAS@N?(olHy`uVBq!ia0vp^4M6O`!3HERU8}EWU|>q|ba4!+V0?R!F-zN=f#G80 z!`Wy4_M4>NjJm*@JZYOf=as%M_YU4axBIchjcY}7%J0aQKfhZjlk?i5Ve;xz(&6*j>uR|G^J zOc2x(oz6A2+w163r>EPcb=Ekgu8O#r;G7z2E*7{j$Z(~P=;Tu&hATtUCeAz$qX`aVNhY<%8F$`^MYn-g=ncw<(k^neQN0=pc><;;lT@yc<)8Do>HFL z-379Jg^%d;u5?kY^IB@6Q&&1YU9{*^mR5+KxmZBq${#(a_OIL#vS%{aRCjZ+#h-#h z?zy&}+I)~Hq^|3fbkFXX;EO{Ot6C=1$|t_mcQ(gvgrNLkIS|6L`CHT11n9FVdQ&MBb@0L)4^DgXcg literal 0 HcmV?d00001 diff --git a/tests_zemu/tests/phase2.test.ts b/tests_zemu/tests/phase2.test.ts index 466ecf5c..6b9373c8 100644 --- a/tests_zemu/tests/phase2.test.ts +++ b/tests_zemu/tests/phase2.test.ts @@ -489,7 +489,7 @@ describe('Phase2', function () { // Wait until we are not in the main menu await sim.waitUntilScreenIsNot(sim.getMainMenuSnapshot()) - await sim.compareSnapshotsAndAccept('.', `${m.prefix.toLowerCase()}-sign_follow`, m.name === 'nanos' ? 6 : 7) + await sim.compareSnapshotsAndAccept('.', `${m.prefix.toLowerCase()}-sign_updateCall`, m.name === 'nanos' ? 8 : 9) const signatureResponse = await respRequest console.log(signatureResponse) From 8254a1f9872944b1ae6136a7c6659231f07bdf42 Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 20:21:33 +0100 Subject: [PATCH 07/11] add signature verification --- tests_zemu/tests/phase2.test.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests_zemu/tests/phase2.test.ts b/tests_zemu/tests/phase2.test.ts index 6b9373c8..77b3c256 100644 --- a/tests_zemu/tests/phase2.test.ts +++ b/tests_zemu/tests/phase2.test.ts @@ -497,6 +497,22 @@ describe('Phase2', function () { expect(signatureResponse.returnCode).toEqual(0x9000) expect(signatureResponse.errorMessage).toEqual('No errors') + const pk = Uint8Array.from(Buffer.from("0410d34980a51af89d3331ad5fa80fe30d8868ad87526460b3b3e15596ee58e812422987d8589ba61098264df5bb9c2d3ff6fe061746b4b31a44ec26636632b835", 'hex')) + + const digest_request = Uint8Array.from(signatureResponse.RequestHash) + const signature_request = Uint8Array.from(signatureResponse.RequestSignatureRS) + expect(signature_request.byteLength).toEqual(64) + + const signatureOk = secp256k1.ecdsaVerify(signature_request, digest_request, pk) + expect(signatureOk).toEqual(true) + + const digest_statusread = Uint8Array.from(signatureResponse.StatusReadHash) + const signature_statusread = Uint8Array.from(signatureResponse.StatusReadSignatureRS) + expect(signature_request.byteLength).toEqual(64) + + const signatureOk_statusread = secp256k1.ecdsaVerify(signature_statusread, digest_statusread, pk) + expect(signatureOk_statusread).toEqual(true) + } finally { await sim.close() } From ebff2b0e074e32e1dd3a9d044cc6c6bdd9068d32 Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 20:34:08 +0100 Subject: [PATCH 08/11] fix request_id in path unit test --- app/src/parser.c | 2 +- tests_zemu/tests/phase2.test.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/parser.c b/app/src/parser.c index a7b99510..763fbd33 100644 --- a/app/src/parser.c +++ b/app/src/parser.c @@ -97,8 +97,8 @@ parser_error_t parser_parse_combined(parser_context_t *ctx, const uint8_t *data, PARSER_ASSERT_OR_ERROR(zxerr_ok == crypto_getDigest(request_hash, call), parser_unexepected_error) #if defined(TARGET_NANOS) || defined(TARGET_NANOX) - //PARSER_ASSERT_OR_ERROR(memcmp(request_hash, request_id_stateread, 32) == 0, parser_context_invalid_chars) MEMZERO(G_io_apdu_buffer, IO_APDU_BUFFER_SIZE); + PARSER_ASSERT_OR_ERROR(memcmp(request_hash, request_id_stateread, 32) == 0, parser_context_invalid_chars) MEMCPY(G_io_apdu_buffer, request_hash, 32); MEMCPY(G_io_apdu_buffer + 32, state_hash, 32); #endif diff --git a/tests_zemu/tests/phase2.test.ts b/tests_zemu/tests/phase2.test.ts index 77b3c256..a150b027 100644 --- a/tests_zemu/tests/phase2.test.ts +++ b/tests_zemu/tests/phase2.test.ts @@ -477,7 +477,7 @@ describe('Phase2', function () { const app = new InternetComputerApp(sim.getTransport()) const txBlobStr_read = - 'd9d9f7a167636f6e74656e74a46e696e67726573735f6578706972791b16bc685267142b8065706174687381824e726571756573745f737461747573582038b344ba26f15444b4f989078c952ce99b559d3eb59e829c5a463a33812e32546c726571756573745f747970656a726561645f73746174656673656e646572581d19AA3D42C048DD7D14F0CFA0DF69A1C1381780F6E9A137ABAA6A82E302' + 'd9d9f7a167636f6e74656e74a46e696e67726573735f6578706972791b16bc685267142b8065706174687381824e726571756573745f73746174757358208d304d294d3f611f992b3f2b184d32b9b3c058d918d7a7ab1946614b13ba0a496c726571756573745f747970656a726561645f73746174656673656e646572581d19AA3D42C048DD7D14F0CFA0DF69A1C1381780F6E9A137ABAA6A82E302' const txBlob_read = Buffer.from(txBlobStr_read, 'hex') const txBlobStr_request = From 73bf3805eec1133aec767ac407e2b3563df8d6e8 Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 20:45:12 +0100 Subject: [PATCH 09/11] define sizes --- app/src/crypto.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/app/src/crypto.c b/app/src/crypto.c index 7d93420e..30d334c7 100644 --- a/app/src/crypto.c +++ b/app/src/crypto.c @@ -40,6 +40,10 @@ uint8_t const DER_PREFIX[] = {0x30, 0x56, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x #define STAKEACCOUNT_PREFIX_SIZE 12u #define STAKEACCOUNT_PRINCIPAL_SIZE 10u +#define SIGNATURE_SIZE_R 32 +#define SIGNATURE_SIZE_S 32 +#define SIGNATURE_SIZE_RS 64 + #if defined(TARGET_NANOS) || defined(TARGET_NANOX) #include "cx.h" @@ -272,7 +276,7 @@ zxerr_t crypto_sign_combined(uint8_t *signatureBuffer, uint8_t *predigest_request, uint8_t *predigest_stateread, uint16_t *sigSize) { - if (signatureMaxlen < SIGN_PREHASH_SIZE + CX_SHA256_SIZE + 2*64){ + if (signatureMaxlen < 2*(CX_SHA256_SIZE + SIGNATURE_SIZE_RS)){ return zxerr_buffer_too_small; } @@ -290,7 +294,7 @@ zxerr_t crypto_sign_combined(uint8_t *signatureBuffer, CHECK_APP_CANARY() cx_hash_sha256(message_buffer, SIGN_PREHASH_SIZE, message_digest, CX_SHA256_SIZE); - MEMCPY(signatureBuffer + 32 + 64, message_digest, CX_SHA256_SIZE); + MEMCPY(signatureBuffer + CX_SHA256_SIZE + SIGNATURE_SIZE_RS, message_digest, CX_SHA256_SIZE); MEMCPY(message_buffer + SIGN_PREFIX_SIZE, predigest_request, CX_SHA256_SIZE); @@ -335,15 +339,15 @@ zxerr_t crypto_sign_combined(uint8_t *signatureBuffer, MEMZERO(signatureBuffer, signatureMaxlen); err = zxerr_unknown; }else{ - MEMCPY(signatureBuffer + 32, sigma.r, 32); - MEMCPY(signatureBuffer + 64, sigma.s, 32); + MEMCPY(signatureBuffer + CX_SHA256_SIZE, sigma.r, SIGNATURE_SIZE_R); + MEMCPY(signatureBuffer + CX_SHA256_SIZE + SIGNATURE_SIZE_R, sigma.s, SIGNATURE_SIZE_S); MEMZERO(&sigma, sizeof(signature_t)); // Sign stateread signatureLength = cx_ecdsa_sign(&cx_privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256, - signatureBuffer + 32 + 64, + signatureBuffer + CX_SHA256_SIZE + SIGNATURE_SIZE_RS, CX_SHA256_SIZE, sigma.der_signature, sizeof_field(signature_t, der_signature), @@ -354,9 +358,9 @@ zxerr_t crypto_sign_combined(uint8_t *signatureBuffer, MEMZERO(signatureBuffer, signatureMaxlen); err = zxerr_unknown; }else{ - MEMCPY(signatureBuffer + 32 + 64 + 32, sigma.r, 32); - MEMCPY(signatureBuffer + 32 + 64 + 64, sigma.s, 32); - *sigSize = 32 + 64 + 32 + 64; + MEMCPY(signatureBuffer + 2*CX_SHA256_SIZE + SIGNATURE_SIZE_RS, sigma.r, SIGNATURE_SIZE_R); + MEMCPY(signatureBuffer + 2*CX_SHA256_SIZE + SIGNATURE_SIZE_RS + SIGNATURE_SIZE_R, sigma.s, SIGNATURE_SIZE_S); + *sigSize = 2*(CX_SHA256_SIZE + SIGNATURE_SIZE_RS); } } } From dd747a1df488d0863d313f78311ea47590f54787 Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Wed, 15 Dec 2021 20:56:34 +0100 Subject: [PATCH 10/11] higher version number + fix snapshots --- app/Makefile | 4 ++-- tests_zemu/snapshots/s-mainmenu/00004.png | Bin 558 -> 564 bytes tests_zemu/snapshots/s-mainmenu/00011.png | Bin 558 -> 564 bytes tests_zemu/snapshots/x-mainmenu/00004.png | Bin 550 -> 558 bytes tests_zemu/snapshots/x-mainmenu/00011.png | Bin 550 -> 558 bytes 5 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Makefile b/app/Makefile index 087ed35b..a56498c9 100755 --- a/app/Makefile +++ b/app/Makefile @@ -54,8 +54,8 @@ ifndef COIN COIN=ICP endif -APPVERSION_M=1 -APPVERSION_N=2 +APPVERSION_M=2 +APPVERSION_N=0 APPVERSION_P=0 $(info COIN = [$(COIN)]) diff --git a/tests_zemu/snapshots/s-mainmenu/00004.png b/tests_zemu/snapshots/s-mainmenu/00004.png index 77d41e46bd4379ce4c6e17082a99faaee562f0db..64fbc39ec1272712f4588ac215a0da1df8d67c3e 100644 GIT binary patch delta 526 zcmZ3-vV~=WO8sw77srqa#l5c_vx5_lj2?Ez)8-^?z;RiJmsa*vXFlC--8>=k zUF;7|sk{?CY$+KMMkaSANb)+TUEeVIrm2GSVZUebTRy&#YU44QxJ00S|GPuR6BahM z&E?_U-PWG+&V*;CHE+Ar1k1_X@2`H)G?G{PtY&2LMruN2U#^YuO#X?E&lG1m8>Mgl zsFPA=WIgku12gaXtObp2ip3sjK+VQN0rwU^3{IK$eB(z+qZ2kN&1XLCF_X)zn99Rz zqEPJK#s)NMU*zG1ZPU&AOcd&!4=YMamGPcBaII)t+$OPz@e_K8VF&mkuWKeA;>9LcfIfVa!gun512BwpSf)JPVm2-Kc7$JUvgOv^r&oZS->h@?+_tZcHj!ii0#8>z K7nXHS2~7YoNa`H` delta 533 zcmdnOvW{hfO8r+)7srqa#g-e_^+^#TvJne9N? zj2#yn&iI!<6g_dl;jmv@TkK(HqjI45+%{+46LU_srkmDupP7E5ri+JnH(ScIWa;%j z&%9G6RC+v{aOP&t9fZtFVm3M*f30A}!?nH2K*tt%0BvSAvX+!8<2|8MKaq#mTxvpP z_TzHi6Fibqc1sy&Ufi&UK~l<%*=Yamiq(uWrHxE#W}W%ul#=1_tfS#mPn)9iVW792 z(@cQs+s;e}hKw_>HPDB7C+18A$IY4r{_8-A9}~`e+S41ZU@YYZG}H*_pnJ#sfjXx3=l)UQJzZ=T*Lnu1O+IVE!@e`U zY*N#z#pkJho&bP0l+XkKGiUNm diff --git a/tests_zemu/snapshots/s-mainmenu/00011.png b/tests_zemu/snapshots/s-mainmenu/00011.png index 77d41e46bd4379ce4c6e17082a99faaee562f0db..64fbc39ec1272712f4588ac215a0da1df8d67c3e 100644 GIT binary patch delta 526 zcmZ3-vV~=WO8sw77srqa#l5c_vx5_lj2?Ez)8-^?z;RiJmsa*vXFlC--8>=k zUF;7|sk{?CY$+KMMkaSANb)+TUEeVIrm2GSVZUebTRy&#YU44QxJ00S|GPuR6BahM z&E?_U-PWG+&V*;CHE+Ar1k1_X@2`H)G?G{PtY&2LMruN2U#^YuO#X?E&lG1m8>Mgl zsFPA=WIgku12gaXtObp2ip3sjK+VQN0rwU^3{IK$eB(z+qZ2kN&1XLCF_X)zn99Rz zqEPJK#s)NMU*zG1ZPU&AOcd&!4=YMamGPcBaII)t+$OPz@e_K8VF&mkuWKeA;>9LcfIfVa!gun512BwpSf)JPVm2-Kc7$JUvgOv^r&oZS->h@?+_tZcHj!ii0#8>z K7nXHS2~7YoNa`H` delta 533 zcmdnOvW{hfO8r+)7srqa#g-e_^+^#TvJne9N? zj2#yn&iI!<6g_dl;jmv@TkK(HqjI45+%{+46LU_srkmDupP7E5ri+JnH(ScIWa;%j z&%9G6RC+v{aOP&t9fZtFVm3M*f30A}!?nH2K*tt%0BvSAvX+!8<2|8MKaq#mTxvpP z_TzHi6Fibqc1sy&Ufi&UK~l<%*=Yamiq(uWrHxE#W}W%ul#=1_tfS#mPn)9iVW792 z(@cQs+s;e}hKw_>HPDB7C+18A$IY4r{_8-A9}~`e+S41ZU@YYZG}H*_pnJ#sfjXx3=l)UQJzZ=T*Lnu1O+IVE!@e`U zY*N#z#pkJho&bP0l+XkKGiUNm diff --git a/tests_zemu/snapshots/x-mainmenu/00004.png b/tests_zemu/snapshots/x-mainmenu/00004.png index 96eb52771306919999af92ec8789ddd2222ee246..c69a8f432affde0d503d01c02c788a0302e0530c 100644 GIT binary patch delta 443 zcmZ3+vW{hfO2}7F7srqa#YvI7xq7X8O*lhdvNgbcc?7;M`*u~T+pzhM0j zM=dQqQPKZPySid)4F9>Ls>k2)II2B0xYg^Z=h8=0Ppy2kq-f=i6){>NT6$XcCm*S4 z`Dtk_@A5vXuBCN*$W{TvJa!0y=ZYa;~Z2-R4@N zkK?pL?#Ui#mR`MMMa}X@OFqr*ntUo2Xp(Qpiao0XEJLB>or90qwC;uW+>gFv-QaZ; zXy~7NNy0$e&WlN}2#~D*denDC$ea*8pvY!@vw*@tpw2lVKz~o?nmQR6EKl`-!FuD` i{bfwv`O%K4dq)Zb5O})!xvX(d%i*!l1&Sl@&{iR#~i!(bChJ&Na2G`;`Bt9i3g1 zyH2fq6!fvL>r}axpVsoOa8WJ$tL*k2Uam)7mjWeZr>+Nz$A|6-URcB~f2ZfveV|z@ z18$yu#1`_8S9I$86?+yJiFcc8{aYVWucswGHQ3el==zY5kU1gu0xd)5gw!qSD(8D} zu$yaYp}nZqdNF;ikYlzhL-s_~tO}6)zAUIPvLPvzO|;GEhu`ILR&!cB{hF4Kw&4G95-fT*Zec_9P;v27C@)F$=| bi@i0!a^d4F*E^R^GXR07tDnm{r-UW|kO0he diff --git a/tests_zemu/snapshots/x-mainmenu/00011.png b/tests_zemu/snapshots/x-mainmenu/00011.png index 96eb52771306919999af92ec8789ddd2222ee246..c69a8f432affde0d503d01c02c788a0302e0530c 100644 GIT binary patch delta 443 zcmZ3+vW{hfO2}7F7srqa#YvI7xq7X8O*lhdvNgbcc?7;M`*u~T+pzhM0j zM=dQqQPKZPySid)4F9>Ls>k2)II2B0xYg^Z=h8=0Ppy2kq-f=i6){>NT6$XcCm*S4 z`Dtk_@A5vXuBCN*$W{TvJa!0y=ZYa;~Z2-R4@N zkK?pL?#Ui#mR`MMMa}X@OFqr*ntUo2Xp(Qpiao0XEJLB>or90qwC;uW+>gFv-QaZ; zXy~7NNy0$e&WlN}2#~D*denDC$ea*8pvY!@vw*@tpw2lVKz~o?nmQR6EKl`-!FuD` i{bfwv`O%K4dq)Zb5O})!xvX(d%i*!l1&Sl@&{iR#~i!(bChJ&Na2G`;`Bt9i3g1 zyH2fq6!fvL>r}axpVsoOa8WJ$tL*k2Uam)7mjWeZr>+Nz$A|6-URcB~f2ZfveV|z@ z18$yu#1`_8S9I$86?+yJiFcc8{aYVWucswGHQ3el==zY5kU1gu0xd)5gw!qSD(8D} zu$yaYp}nZqdNF;ikYlzhL-s_~tO}6)zAUIPvLPvzO|;GEhu`ILR&!cB{hF4Kw&4G95-fT*Zec_9P;v27C@)F$=| bi@i0!a^d4F*E^R^GXR07tDnm{r-UW|kO0he From 4444ddaedaff42ef372b449f2fc7acaf245138bb Mon Sep 17 00:00:00 2001 From: Leon Groot Bruinderink Date: Mon, 20 Dec 2021 11:03:20 +0100 Subject: [PATCH 11/11] fix cpp unit test --- tests/cbor_parser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/cbor_parser.cpp b/tests/cbor_parser.cpp index c4172ca1..a3f8da33 100644 --- a/tests/cbor_parser.cpp +++ b/tests/cbor_parser.cpp @@ -537,6 +537,7 @@ namespace { } TEST(CBORParserTest, ClaimNeuron) { + parser_tx_obj.special_transfer_type = normal_transaction; uint8_t inBuffer[1000]; const char *tmp = "d9d9f7a167636f6e74656e74a76c726571756573745f747970656463616c6c656e6f6e6365505833a6590c6d2b601e3a24557cfbb4336e696e67726573735f6578706972791b16bad506bb4ca0f06673656e646572581d2594dccb73ca0226c58299d4e21badbcee00d153deccb38fa20cd46e026b63616e69737465725f69644a000000000000000601016b6d6574686f645f6e616d656d636c61696d5f6e6575726f6e7363617267588b4449444c000171820130343139623066656363356639613164353162393033643262363234346430356531326134386661386233353731396538313262623635643966393035613365613965356137323362363537616665393136313236396431663134633164383034376530323230616461633434653731313630323531656364616662613064636535"; @@ -551,6 +552,7 @@ namespace { } TEST(CBORParserTest, JoinCommunityFund) { + parser_tx_obj.special_transfer_type = normal_transaction; uint8_t inBuffer[1000]; const char *tmp = "d9d9f7a167636f6e74656e74a663617267486202107b12023a006b63616e69737465725f69644a000000000000000101016e696e67726573735f6578706972791b16ba67d2b864bf406b6d6574686f645f6e616d65706d616e6167655f6e6575726f6e5f70626c726571756573745f747970656463616c6c6673656e646572581dd899978f029508f4fa5fce3d2539de5aade6d229efcc458233deee7502";