Files
app-ethereum/src_features/stark_sign/cmd_stark_sign.c
pscott b646cf1b28 Fix compilation warnings (#159)
* Fix easy warnings for sdk 2.0

* Add attribute unused to bagl_elemt_t in callback functions

* Add attribute unused to io_event function

* Clang-format

* Use elfs from CI in tests (#167)

* Add Nano X build

* Use CI's build artifacts for CI's tests

* Add network display (#152)

* Add network name display instead of chainID

* Add display of correct ticker along with network

* Add FTM

* Clang-format

* Add comment in python script

* Rename SIZE_MAX to MAX_SIZE

* Change %u to %d in printf

* Remove needless PIC

* Update comment about get_chain_id()

* Update example script to follow EIP155

* Remove unused PIC calls

* Add whitespace between ticker and amount when using EIP155

* Remove decimal config per network, set back 18 everywhere

* Adapt u32_from_BE to swith cases

* Remove chainid from signTx.py

* Switch to switch in stead of if in get_chain_id

* Revert "Remove chainid from signTx.py"

This reverts commit 454e09f280ec3e3ec1c7d7cc0027247ef4390088.

* Change Ethereum chainid to 1

* Rename chainid_step to network_step

* Adapt finalizeParsing to new chainid for Ethereum

* Update snapshots

* clang-format

* Fix network display logic for clones

* Fix tests

* Add clone tests

Co-authored-by: TamtamHero <10632523+TamtamHero@users.noreply.github.com>

Co-authored-by: Jean P <10632523+TamtamHero@users.noreply.github.com>
2021-07-05 11:01:51 +02:00

260 lines
10 KiB
C

#ifdef HAVE_STARKWARE
#include "shared_context.h"
#include "apdu_constants.h"
#include "stark_utils.h"
#include "ui_flow.h"
#include "poorstream.h"
#include "ui_callbacks.h"
#define U8BE(buf, off) \
(uint64_t)((((uint64_t) U4BE(buf, off)) << 32) | (((uint64_t) U4BE(buf, off + 4)) & 0xFFFFFFFF))
#define TMP_OFFSET 140
void handleStarkwareSignMessage(uint8_t p1,
uint8_t p2,
uint8_t *dataBuffer,
uint16_t dataLength,
unsigned int *flags,
__attribute__((unused)) unsigned int *tx) {
uint8_t privateKeyData[INT256_LENGTH];
uint32_t i;
uint8_t bip32PathLength = *(dataBuffer);
uint8_t offset = 1;
cx_ecfp_private_key_t privateKey;
poorstream_t bitstream;
bool selfTransfer = false;
uint8_t order = 1;
uint8_t protocol = 2;
uint8_t preOffset, postOffset;
uint8_t zeroTest;
// Initial checks
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
switch (p1) {
case P1_STARK_ORDER:
protocol = 1;
break;
case P1_STARK_TRANSFER:
protocol = 1;
order = 0;
break;
case P1_STARK_ORDER_V2:
break;
case P1_STARK_TRANSFER_V2:
case P1_STARK_CONDITIONAL_TRANSFER:
order = 0;
break;
default:
THROW(0x6B00);
}
postOffset = (protocol == 2 ? 1 + 32 : 0);
preOffset = (protocol == 2 ? 1 : 0);
if (order) {
if (dataLength != (20 + 32 + 20 + 32 + 4 + 4 + 8 + 8 + 4 + 4 + 1 + 4 * bip32PathLength +
2 * postOffset)) {
THROW(0x6700);
}
} else {
if (dataLength != (20 + 32 + 32 + 4 + 4 + 8 + 4 + 4 + 1 + 4 * bip32PathLength + postOffset +
(p1 == P1_STARK_CONDITIONAL_TRANSFER ? 32 + 20 : 0))) {
THROW(0x6700);
}
}
if (p2 != 0) {
THROW(0x6B00);
}
tmpCtx.transactionContext.pathLength = bip32PathLength;
for (i = 0; i < bip32PathLength; i++) {
tmpCtx.transactionContext.bip32Path[i] = U4BE(dataBuffer, offset);
PRINTF("Storing path %d %d\n", i, tmpCtx.transactionContext.bip32Path[i]);
offset += 4;
}
// Discard the path to use part of dataBuffer as a temporary buffer
memmove(dataBuffer, dataBuffer + offset, dataLength - offset);
dataContext.starkContext.conditional = (p1 == P1_STARK_CONDITIONAL_TRANSFER);
if (dataContext.starkContext.conditional) {
memmove(dataContext.starkContext.fact,
dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4 + 8 + 4 + 4,
32);
memmove(dataContext.starkContext.conditionAddress,
dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4 + 8 + 4 + 4 + 32,
20);
PRINTF("Fact %.*H\n", 32, dataContext.starkContext.fact);
PRINTF("Address %.*H\n", 20, dataContext.starkContext.conditionAddress);
}
zeroTest = allzeroes(dataBuffer + preOffset, 20);
if (zeroTest && (protocol == 2) && (dataBuffer[0] != STARK_QUANTUM_ETH)) {
PRINTF("stark - unexpected quantum descriptor type for null first address %d\n",
dataBuffer[0]);
THROW(0x6A80);
}
if (!zeroTest && getKnownToken(dataBuffer + preOffset) == NULL) {
PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer + preOffset);
THROW(0x6A80);
}
if (order) {
zeroTest = allzeroes(dataBuffer + 20 + 32 + postOffset + preOffset, 20);
if (zeroTest && (protocol == 2) && (dataBuffer[1 + 20 + 32 + 32] != STARK_QUANTUM_ETH)) {
PRINTF("stark - unexpected quantum descriptor type for null second address %d\n",
dataBuffer[1 + 20 + 32 + 32]);
THROW(0x6A80);
}
if (!zeroTest && getKnownToken(dataBuffer + 20 + 32 + postOffset + preOffset) == NULL) {
PRINTF("stark - cannot process unknown token %.*H",
20,
dataBuffer + 20 + 32 + postOffset + preOffset);
THROW(0x6A80);
}
}
// Prepare the Stark parameters
io_seproxyhal_io_heartbeat();
compute_token_id(&global_sha3,
dataBuffer + preOffset,
(protocol == 2 ? dataBuffer[0] : STARK_QUANTUM_LEGACY),
dataBuffer + preOffset + 20,
(protocol == 2 ? dataBuffer + 1 + 20 + 32 : NULL),
false,
dataContext.starkContext.w1);
if (order) {
io_seproxyhal_io_heartbeat();
compute_token_id(&global_sha3,
dataBuffer + 20 + 32 + postOffset + preOffset,
(protocol == 2 ? dataBuffer[1 + 20 + 32 + 32] : STARK_QUANTUM_LEGACY),
dataBuffer + 20 + 32 + postOffset + preOffset + 20,
(protocol == 2 ? dataBuffer + 1 + 20 + 32 + 32 + 1 + 20 + 32 : NULL),
false,
dataContext.starkContext.w2);
offset = 20 + 32 + postOffset + 20 + 32 + postOffset;
} else {
memmove(dataContext.starkContext.w2, dataBuffer + 20 + 32 + postOffset, 32);
offset = 20 + 32 + postOffset + 32;
}
poorstream_init(&bitstream, dataContext.starkContext.w3);
poorstream_write_bits(&bitstream, 0, 11); // padding
poorstream_write_bits(
&bitstream,
(p1 == P1_STARK_CONDITIONAL_TRANSFER ? STARK_CONDITIONAL_TRANSFER_TYPE
: order ? STARK_ORDER_TYPE : STARK_TRANSFER_TYPE),
4);
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset), 31);
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset + 4), 31);
poorstream_write_bits(&bitstream, U8BE(dataBuffer, offset + 4 + 4), 63);
if (order) {
poorstream_write_bits(&bitstream, U8BE(dataBuffer, offset + 4 + 4 + 8), 63);
offset += 4 + 4 + 8 + 8;
} else {
poorstream_write_bits(&bitstream, 0, 63);
offset += 4 + 4 + 8;
}
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset), 31);
poorstream_write_bits(&bitstream, U4BE(dataBuffer, offset + 4), 22);
PRINTF("stark w1 %.*H\n", 32, dataContext.starkContext.w1);
PRINTF("stark w2 %.*H\n", 32, dataContext.starkContext.w2);
PRINTF("stark w3 %.*H\n", 32, dataContext.starkContext.w3);
if (dataContext.starkContext.conditional) {
cx_keccak_init(&global_sha3, 256);
cx_hash((cx_hash_t *) &global_sha3,
0,
dataContext.starkContext.conditionAddress,
20,
NULL,
0);
cx_hash((cx_hash_t *) &global_sha3,
CX_LAST,
dataContext.starkContext.fact,
32,
dataContext.starkContext.w4,
32);
dataContext.starkContext.w4[0] &= 0x03;
PRINTF("stark w4 %.*H\n", 32, dataContext.starkContext.w4);
}
// Prepare the UI
if (order) {
io_seproxyhal_io_heartbeat();
// amount to sell
stark_get_amount_string(dataBuffer + preOffset,
dataBuffer + preOffset + 20,
dataBuffer + 20 + 32 + postOffset + 20 + 32 + postOffset + 4 + 4,
(char *) (dataBuffer + TMP_OFFSET),
strings.common.fullAmount);
io_seproxyhal_io_heartbeat();
// amount to buy
stark_get_amount_string(
dataBuffer + 20 + 32 + postOffset + preOffset,
dataBuffer + 20 + 32 + postOffset + preOffset + 20,
dataBuffer + 20 + 32 + postOffset + 20 + 32 + postOffset + 4 + 4 + 8,
(char *) (dataBuffer + TMP_OFFSET),
strings.common.maxFee);
// src vault ID
snprintf(strings.common.fullAddress,
sizeof(strings.common.fullAddress),
"%d",
U4BE(dataBuffer, 20 + 32 + postOffset + 20 + 32 + postOffset));
} else {
cx_ecfp_public_key_t publicKey;
// Check if the transfer is a self transfer
io_seproxyhal_io_heartbeat();
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, bip32PathLength, privateKeyData);
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
io_seproxyhal_io_heartbeat();
cx_ecfp_generate_pair(CX_CURVE_Stark256, &publicKey, &privateKey, 1);
explicit_bzero(&privateKey, sizeof(privateKey));
explicit_bzero(privateKeyData, sizeof(privateKeyData));
io_seproxyhal_io_heartbeat();
selfTransfer = (memcmp(publicKey.W + 1, dataBuffer + 20 + 32 + postOffset, 32) == 0);
PRINTF("self transfer %d\n", selfTransfer);
io_seproxyhal_io_heartbeat();
// amount to transfer
stark_get_amount_string(dataBuffer + preOffset,
dataBuffer + preOffset + 20,
dataBuffer + 20 + 32 + postOffset + 32 + 4 + 4,
(char *) (dataBuffer + TMP_OFFSET),
tmpContent.tmp);
// dest vault ID
snprintf(strings.tmp.tmp2,
sizeof(strings.tmp.tmp2),
"%d",
U4BE(dataBuffer, 20 + 32 + postOffset + 32 + 4));
if (!selfTransfer) {
memmove(dataContext.starkContext.transferDestination,
dataBuffer + 20 + 32 + postOffset,
32);
snprintf(strings.tmp.tmp,
sizeof(strings.tmp.tmp),
"0x%.*H",
32,
dataBuffer + 20 + 32 + postOffset);
}
}
if (order) {
ux_flow_init(0, ux_stark_limit_order_flow, NULL);
} else {
if (selfTransfer) {
ux_flow_init(
0,
(dataContext.starkContext.conditional ? ux_stark_self_transfer_conditional_flow
: ux_stark_self_transfer_flow),
NULL);
} else {
ux_flow_init(0,
(dataContext.starkContext.conditional ? ux_stark_transfer_conditional_flow
: ux_stark_transfer_flow),
NULL);
}
}
*flags |= IO_ASYNCH_REPLY;
}
#endif