Apply clang-format

This commit is contained in:
TamtamHero
2020-12-01 16:20:13 +01:00
parent 1421a74be5
commit 17bd07a346
80 changed files with 8859 additions and 5091 deletions

View File

@@ -1,6 +1,7 @@
#include "shared_context.h"
#include "ui_callbacks.h"
// clang-format off
UX_STEP_NOCB(ux_approval_allowance_1_step,
pnn,
{
@@ -59,14 +60,13 @@ UX_STEP_CB(
&C_icon_crossmark,
"Reject",
});
// clang-format on
UX_FLOW(ux_approval_allowance_flow,
&ux_approval_allowance_1_step,
&ux_approval_allowance_2_step,
&ux_approval_allowance_3_step,
&ux_approval_allowance_4_step,
&ux_approval_allowance_5_step,
&ux_approval_allowance_6_step,
&ux_approval_allowance_7_step
);
&ux_approval_allowance_1_step,
&ux_approval_allowance_2_step,
&ux_approval_allowance_3_step,
&ux_approval_allowance_4_step,
&ux_approval_allowance_5_step,
&ux_approval_allowance_6_step,
&ux_approval_allowance_7_step);

View File

@@ -3,24 +3,28 @@
#include "ui_flow.h"
void handleGetAppConfiguration(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
UNUSED(p1);
UNUSED(p2);
UNUSED(workBuffer);
UNUSED(dataLength);
UNUSED(flags);
G_io_apdu_buffer[0] = (N_storage.dataAllowed ? APP_FLAG_DATA_ALLOWED : 0x00);
void handleGetAppConfiguration(uint8_t p1,
uint8_t p2,
uint8_t *workBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
UNUSED(p1);
UNUSED(p2);
UNUSED(workBuffer);
UNUSED(dataLength);
UNUSED(flags);
G_io_apdu_buffer[0] = (N_storage.dataAllowed ? APP_FLAG_DATA_ALLOWED : 0x00);
#ifndef HAVE_TOKENS_LIST
G_io_apdu_buffer[0] |= APP_FLAG_EXTERNAL_TOKEN_NEEDED;
G_io_apdu_buffer[0] |= APP_FLAG_EXTERNAL_TOKEN_NEEDED;
#endif
#ifdef HAVE_STARKWARE
G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE;
G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE_V2;
G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE;
G_io_apdu_buffer[0] |= APP_FLAG_STARKWARE_V2;
#endif
G_io_apdu_buffer[1] = LEDGER_MAJOR_VERSION;
G_io_apdu_buffer[2] = LEDGER_MINOR_VERSION;
G_io_apdu_buffer[3] = LEDGER_PATCH_VERSION;
*tx = 4;
THROW(0x9000);
G_io_apdu_buffer[1] = LEDGER_MAJOR_VERSION;
G_io_apdu_buffer[2] = LEDGER_MINOR_VERSION;
G_io_apdu_buffer[3] = LEDGER_PATCH_VERSION;
*tx = 4;
THROW(0x9000);
}

View File

@@ -6,75 +6,81 @@
#include "ui_flow.h"
#include "feature_getEth2PublicKey.h"
static const uint8_t BLS12_381_FIELD_MODULUS[] = { 0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b, 0xac, 0xd7, 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0, 0xf6, 0xb0, 0xf6, 0x24, 0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xab };
static const uint8_t BLS12_381_FIELD_MODULUS[] = {
0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b, 0xac, 0xd7,
0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0, 0xf6, 0xb0, 0xf6, 0x24,
0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xab};
void getEth2PublicKey(uint32_t *bip32Path, uint8_t bip32PathLength, uint8_t *out) {
uint8_t privateKeyData[32];
cx_ecfp_256_extended_private_key_t privateKey;
cx_ecfp_384_public_key_t publicKey;
uint8_t yFlag = 0;
uint8_t tmp[96];
uint8_t privateKeyData[32];
cx_ecfp_256_extended_private_key_t privateKey;
cx_ecfp_384_public_key_t publicKey;
uint8_t yFlag = 0;
uint8_t tmp[96];
io_seproxyhal_io_heartbeat();
os_perso_derive_eip2333(CX_CURVE_BLS12_381_G1, bip32Path, bip32PathLength, privateKeyData);
io_seproxyhal_io_heartbeat();
memset(tmp, 0, 48);
memmove(tmp + 16, privateKeyData, 32);
cx_ecfp_init_private_key(CX_CURVE_BLS12_381_G1, tmp, 48, &privateKey);
cx_ecfp_generate_pair(CX_CURVE_BLS12_381_G1, &publicKey, &privateKey, 1);
explicit_bzero(tmp, 96);
explicit_bzero((void*)&privateKey, sizeof(cx_ecfp_256_extended_private_key_t));
tmp[47] = 2;
cx_math_mult(tmp, publicKey.W + 1 + 48, tmp, 48);
if (cx_math_cmp(tmp + 48, BLS12_381_FIELD_MODULUS, 48) > 0) {
yFlag = 0x20;
}
publicKey.W[1] &= 0x1f;
publicKey.W[1] |= 0x80 | yFlag;
memmove(out, publicKey.W + 1, 48);
io_seproxyhal_io_heartbeat();
os_perso_derive_eip2333(CX_CURVE_BLS12_381_G1, bip32Path, bip32PathLength, privateKeyData);
io_seproxyhal_io_heartbeat();
memset(tmp, 0, 48);
memmove(tmp + 16, privateKeyData, 32);
cx_ecfp_init_private_key(CX_CURVE_BLS12_381_G1, tmp, 48, &privateKey);
cx_ecfp_generate_pair(CX_CURVE_BLS12_381_G1, &publicKey, &privateKey, 1);
explicit_bzero(tmp, 96);
explicit_bzero((void *) &privateKey, sizeof(cx_ecfp_256_extended_private_key_t));
tmp[47] = 2;
cx_math_mult(tmp, publicKey.W + 1 + 48, tmp, 48);
if (cx_math_cmp(tmp + 48, BLS12_381_FIELD_MODULUS, 48) > 0) {
yFlag = 0x20;
}
publicKey.W[1] &= 0x1f;
publicKey.W[1] |= 0x80 | yFlag;
memmove(out, publicKey.W + 1, 48);
}
void handleGetEth2PublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
UNUSED(dataLength);
uint32_t bip32Path[MAX_BIP32_PATH];
uint32_t i;
uint8_t bip32PathLength = *(dataBuffer++);
void handleGetEth2PublicKey(uint8_t p1,
uint8_t p2,
uint8_t *dataBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
UNUSED(dataLength);
uint32_t bip32Path[MAX_BIP32_PATH];
uint32_t i;
uint8_t bip32PathLength = *(dataBuffer++);
if(!called_from_swap){
reset_app_context();
}
if ((bip32PathLength < 0x01) ||
(bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
THROW(0x6B00);
}
if (p2 != 0) {
THROW(0x6B00);
}
for (i = 0; i < bip32PathLength; i++) {
bip32Path[i] = U4BE(dataBuffer, 0);
dataBuffer += 4;
}
getEth2PublicKey(bip32Path, bip32PathLength, tmpCtx.publicKeyContext.publicKey.W);
if (!called_from_swap) {
reset_app_context();
}
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
THROW(0x6B00);
}
if (p2 != 0) {
THROW(0x6B00);
}
for (i = 0; i < bip32PathLength; i++) {
bip32Path[i] = U4BE(dataBuffer, 0);
dataBuffer += 4;
}
getEth2PublicKey(bip32Path, bip32PathLength, tmpCtx.publicKeyContext.publicKey.W);
#ifndef NO_CONSENT
if (p1 == P1_NON_CONFIRM)
#endif // NO_CONSENT
{
*tx = set_result_get_eth2_publicKey();
THROW(0x9000);
}
if (p1 == P1_NON_CONFIRM)
#endif // NO_CONSENT
{
*tx = set_result_get_eth2_publicKey();
THROW(0x9000);
}
#ifndef NO_CONSENT
else
{
ux_flow_init(0, ux_display_public_eth2_flow, NULL);
else {
ux_flow_init(0, ux_display_public_eth2_flow, NULL);
*flags |= IO_ASYNCH_REPLY;
}
#endif // NO_CONSENT
*flags |= IO_ASYNCH_REPLY;
}
#endif // NO_CONSENT
}
#endif

View File

@@ -1,4 +1,3 @@
#include "shared_context.h"
uint32_t set_result_get_eth2_publicKey(void);

View File

@@ -10,4 +10,3 @@ uint32_t set_result_get_eth2_publicKey() {
}
#endif

View File

@@ -13,7 +13,7 @@ unsigned int io_seproxyhal_touch_eth2_address_ok(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}
#if 0

View File

@@ -4,9 +4,10 @@
#include "ui_callbacks.h"
void prepare_eth2_public_key() {
snprintf(strings.tmp.tmp, 100, "0x%.*H", 48, tmpCtx.publicKeyContext.publicKey.W);
snprintf(strings.tmp.tmp, 100, "0x%.*H", 48, tmpCtx.publicKeyContext.publicKey.W);
}
// clang-format off
UX_STEP_NOCB(
ux_display_public_eth2_flow_1_step,
pnn,
@@ -39,12 +40,12 @@ UX_STEP_CB(
&C_icon_crossmark,
"Reject",
});
// clang-format on
UX_FLOW(ux_display_public_eth2_flow,
&ux_display_public_eth2_flow_1_step,
&ux_display_public_eth2_flow_2_step,
&ux_display_public_eth2_flow_3_step,
&ux_display_public_eth2_flow_4_step
);
&ux_display_public_eth2_flow_1_step,
&ux_display_public_eth2_flow_2_step,
&ux_display_public_eth2_flow_3_step,
&ux_display_public_eth2_flow_4_step);
#endif

View File

@@ -4,56 +4,70 @@
#include "ui_flow.h"
#include "feature_getPublicKey.h"
void handleGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
UNUSED(dataLength);
uint8_t privateKeyData[32];
uint32_t bip32Path[MAX_BIP32_PATH];
uint32_t i;
uint8_t bip32PathLength = *(dataBuffer++);
cx_ecfp_private_key_t privateKey;
if(!called_from_swap){
reset_app_context();
}
if ((bip32PathLength < 0x01) ||
(bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
THROW(0x6B00);
}
if ((p2 != P2_CHAINCODE) && (p2 != P2_NO_CHAINCODE)) {
THROW(0x6B00);
}
for (i = 0; i < bip32PathLength; i++) {
bip32Path[i] = U4BE(dataBuffer, 0);
dataBuffer += 4;
}
tmpCtx.publicKeyContext.getChaincode = (p2 == P2_CHAINCODE);
io_seproxyhal_io_heartbeat();
os_perso_derive_node_bip32(CX_CURVE_256K1, bip32Path, bip32PathLength, privateKeyData, (tmpCtx.publicKeyContext.getChaincode ? tmpCtx.publicKeyContext.chainCode : NULL));
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
io_seproxyhal_io_heartbeat();
cx_ecfp_generate_pair(CX_CURVE_256K1, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1);
explicit_bzero(&privateKey, sizeof(privateKey));
explicit_bzero(privateKeyData, sizeof(privateKeyData));
io_seproxyhal_io_heartbeat();
getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey, tmpCtx.publicKeyContext.address, &global_sha3, chainConfig);
void handleGetPublicKey(uint8_t p1,
uint8_t p2,
uint8_t *dataBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
UNUSED(dataLength);
uint8_t privateKeyData[32];
uint32_t bip32Path[MAX_BIP32_PATH];
uint32_t i;
uint8_t bip32PathLength = *(dataBuffer++);
cx_ecfp_private_key_t privateKey;
if (!called_from_swap) {
reset_app_context();
}
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
THROW(0x6B00);
}
if ((p2 != P2_CHAINCODE) && (p2 != P2_NO_CHAINCODE)) {
THROW(0x6B00);
}
for (i = 0; i < bip32PathLength; i++) {
bip32Path[i] = U4BE(dataBuffer, 0);
dataBuffer += 4;
}
tmpCtx.publicKeyContext.getChaincode = (p2 == P2_CHAINCODE);
io_seproxyhal_io_heartbeat();
os_perso_derive_node_bip32(
CX_CURVE_256K1,
bip32Path,
bip32PathLength,
privateKeyData,
(tmpCtx.publicKeyContext.getChaincode ? tmpCtx.publicKeyContext.chainCode : NULL));
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
io_seproxyhal_io_heartbeat();
cx_ecfp_generate_pair(CX_CURVE_256K1, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1);
explicit_bzero(&privateKey, sizeof(privateKey));
explicit_bzero(privateKeyData, sizeof(privateKeyData));
io_seproxyhal_io_heartbeat();
getEthAddressStringFromKey(&tmpCtx.publicKeyContext.publicKey,
tmpCtx.publicKeyContext.address,
&global_sha3,
chainConfig);
#ifndef NO_CONSENT
if (p1 == P1_NON_CONFIRM)
#endif // NO_CONSENT
{
*tx = set_result_get_publicKey();
THROW(0x9000);
}
if (p1 == P1_NON_CONFIRM)
#endif // NO_CONSENT
{
*tx = set_result_get_publicKey();
THROW(0x9000);
}
#ifndef NO_CONSENT
else
{
snprintf(strings.common.fullAddress, sizeof(strings.common.fullAddress), "0x%.*s", 40, tmpCtx.publicKeyContext.address);
ux_flow_init(0, ux_display_public_flow, NULL);
else {
snprintf(strings.common.fullAddress,
sizeof(strings.common.fullAddress),
"0x%.*s",
40,
tmpCtx.publicKeyContext.address);
ux_flow_init(0, ux_display_public_flow, NULL);
*flags |= IO_ASYNCH_REPLY;
}
#endif // NO_CONSENT
*flags |= IO_ASYNCH_REPLY;
}
#endif // NO_CONSENT
}

View File

@@ -1,4 +1,3 @@
#include "shared_context.h"
uint32_t set_result_get_publicKey(void);

View File

@@ -9,9 +9,8 @@ uint32_t set_result_get_publicKey() {
memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.address, 40);
tx += 40;
if (tmpCtx.publicKeyContext.getChaincode) {
memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.chainCode, 32);
tx += 32;
memmove(G_io_apdu_buffer + tx, tmpCtx.publicKeyContext.chainCode, 32);
tx += 32;
}
return tx;
}

View File

@@ -11,7 +11,7 @@ unsigned int io_seproxyhal_touch_address_ok(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}
unsigned int io_seproxyhal_touch_address_cancel(const bagl_element_t *e) {
@@ -22,6 +22,5 @@ unsigned int io_seproxyhal_touch_address_cancel(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}

View File

@@ -1,6 +1,7 @@
#include "shared_context.h"
#include "ui_callbacks.h"
// clang-format off
UX_STEP_NOCB(
ux_display_public_flow_1_step,
pnn,
@@ -32,10 +33,10 @@ UX_STEP_CB(
&C_icon_crossmark,
"Reject",
});
// clang-format on
UX_FLOW(ux_display_public_flow,
&ux_display_public_flow_1_step,
&ux_display_public_flow_2_step,
&ux_display_public_flow_3_step,
&ux_display_public_flow_4_step
);
&ux_display_public_flow_1_step,
&ux_display_public_flow_2_step,
&ux_display_public_flow_3_step,
&ux_display_public_flow_4_step);

View File

@@ -3,172 +3,212 @@
#include "ui_flow.h"
static const uint8_t const TOKEN_SIGNATURE_PUBLIC_KEY[] = {
// production key 2019-01-11 03:07PM (erc20signer)
0x04,
// production key 2019-01-11 03:07PM (erc20signer)
0x04,
0x5e,0x6c,0x10,0x20,0xc1,0x4d,0xc4,0x64,
0x42,0xfe,0x89,0xf9,0x7c,0x0b,0x68,0xcd,
0xb1,0x59,0x76,0xdc,0x24,0xf2,0x4c,0x31,
0x6e,0x7b,0x30,0xfe,0x4e,0x8c,0xc7,0x6b,
0x5e, 0x6c, 0x10, 0x20, 0xc1, 0x4d, 0xc4, 0x64, 0x42, 0xfe, 0x89, 0xf9, 0x7c, 0x0b, 0x68, 0xcd,
0xb1, 0x59, 0x76, 0xdc, 0x24, 0xf2, 0x4c, 0x31, 0x6e, 0x7b, 0x30, 0xfe, 0x4e, 0x8c, 0xc7, 0x6b,
0x14,0x89,0x15,0x0c,0x21,0x51,0x4e,0xbf,
0x44,0x0f,0xf5,0xde,0xa5,0x39,0x3d,0x83,
0xde,0x53,0x58,0xcd,0x09,0x8f,0xce,0x8f,
0xd0,0xf8,0x1d,0xaa,0x94,0x97,0x91,0x83
};
0x14, 0x89, 0x15, 0x0c, 0x21, 0x51, 0x4e, 0xbf, 0x44, 0x0f, 0xf5, 0xde, 0xa5, 0x39, 0x3d, 0x83,
0xde, 0x53, 0x58, 0xcd, 0x09, 0x8f, 0xce, 0x8f, 0xd0, 0xf8, 0x1d, 0xaa, 0x94, 0x97, 0x91, 0x83};
#ifdef HAVE_CONTRACT_NAME_IN_DESCRIPTOR
void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
UNUSED(p1);
UNUSED(p2);
UNUSED(flags);
uint32_t offset = 0;
uint8_t tickerLength, contractNameLength;
uint32_t chainId;
uint8_t hash[32];
cx_sha256_t sha256;
cx_ecfp_public_key_t tokenKey;
void handleProvideErc20TokenInformation(uint8_t p1,
uint8_t p2,
uint8_t *workBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
UNUSED(p1);
UNUSED(p2);
UNUSED(flags);
uint32_t offset = 0;
uint8_t tickerLength, contractNameLength;
uint32_t chainId;
uint8_t hash[32];
cx_sha256_t sha256;
cx_ecfp_public_key_t tokenKey;
cx_sha256_init(&sha256);
cx_sha256_init(&sha256);
tmpCtx.transactionContext.currentTokenIndex = (tmpCtx.transactionContext.currentTokenIndex + 1) % MAX_TOKEN;
tokenDefinition_t* token = &tmpCtx.transactionContext.tokens[tmpCtx.transactionContext.currentTokenIndex];
tmpCtx.transactionContext.currentTokenIndex =
(tmpCtx.transactionContext.currentTokenIndex + 1) % MAX_TOKEN;
tokenDefinition_t *token =
&tmpCtx.transactionContext.tokens[tmpCtx.transactionContext.currentTokenIndex];
if (dataLength < 1) {
THROW(0x6A80);
}
tickerLength = workBuffer[offset++];
dataLength--;
if ((tickerLength + 2) >= sizeof(token->ticker)) { // +2 because ' \0' is appended to ticker
THROW(0x6A80);
}
if (dataLength < tickerLength + 1) {
THROW(0x6A80);
}
cx_hash((cx_hash_t*)&sha256, 0, workBuffer + offset, tickerLength, NULL, 0);
memmove(token->ticker, workBuffer + offset, tickerLength);
token->ticker[tickerLength] = ' ';
token->ticker[tickerLength + 1] = '\0';
offset += tickerLength;
dataLength -= tickerLength;
if (dataLength < 1) {
THROW(0x6A80);
}
tickerLength = workBuffer[offset++];
dataLength--;
if ((tickerLength + 2) >= sizeof(token->ticker)) { // +2 because ' \0' is appended to ticker
THROW(0x6A80);
}
if (dataLength < tickerLength + 1) {
THROW(0x6A80);
}
cx_hash((cx_hash_t *) &sha256, 0, workBuffer + offset, tickerLength, NULL, 0);
memmove(token->ticker, workBuffer + offset, tickerLength);
token->ticker[tickerLength] = ' ';
token->ticker[tickerLength + 1] = '\0';
offset += tickerLength;
dataLength -= tickerLength;
contractNameLength = workBuffer[offset++];
dataLength--;
if (dataLength < contractNameLength + 20 + 4 + 4) {
THROW(0x6A80);
}
cx_hash((cx_hash_t*)&sha256, CX_LAST, workBuffer + offset, contractNameLength + 20 + 4 + 4, hash, 32);
memmove(token->contractName, workBuffer + offset, MIN(contractNameLength, sizeof(token->contractName)-1));
token->contractName[MIN(contractNameLength, sizeof(token->contractName)-1)] = '\0';
offset += contractNameLength;
dataLength -= contractNameLength;
contractNameLength = workBuffer[offset++];
dataLength--;
if (dataLength < contractNameLength + 20 + 4 + 4) {
THROW(0x6A80);
}
cx_hash((cx_hash_t *) &sha256,
CX_LAST,
workBuffer + offset,
contractNameLength + 20 + 4 + 4,
hash,
32);
memmove(token->contractName,
workBuffer + offset,
MIN(contractNameLength, sizeof(token->contractName) - 1));
token->contractName[MIN(contractNameLength, sizeof(token->contractName) - 1)] = '\0';
offset += contractNameLength;
dataLength -= contractNameLength;
memmove(token->address, workBuffer + offset, 20);
offset += 20;
dataLength -= 20;
token->decimals = U4BE(workBuffer, offset);
offset += 4;
dataLength -= 4;
chainId = U4BE(workBuffer, offset);
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
PRINTF("ChainId token mismatch\n");
THROW(0x6A80);
}
offset += 4;
dataLength -= 4;
cx_ecfp_init_public_key(CX_CURVE_256K1, TOKEN_SIGNATURE_PUBLIC_KEY, sizeof(TOKEN_SIGNATURE_PUBLIC_KEY), &tokenKey);
if (!cx_ecdsa_verify(&tokenKey, CX_LAST, CX_SHA256, hash, 32, workBuffer + offset, dataLength)) {
PRINTF("Invalid token signature\n");
THROW(0x6A80);
}
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentTokenIndex] = 1;
THROW(0x9000);
memmove(token->address, workBuffer + offset, 20);
offset += 20;
dataLength -= 20;
token->decimals = U4BE(workBuffer, offset);
offset += 4;
dataLength -= 4;
chainId = U4BE(workBuffer, offset);
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
PRINTF("ChainId token mismatch\n");
THROW(0x6A80);
}
offset += 4;
dataLength -= 4;
cx_ecfp_init_public_key(CX_CURVE_256K1,
TOKEN_SIGNATURE_PUBLIC_KEY,
sizeof(TOKEN_SIGNATURE_PUBLIC_KEY),
&tokenKey);
if (!cx_ecdsa_verify(&tokenKey,
CX_LAST,
CX_SHA256,
hash,
32,
workBuffer + offset,
dataLength)) {
PRINTF("Invalid token signature\n");
THROW(0x6A80);
}
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentTokenIndex] = 1;
THROW(0x9000);
}
#else
void handleProvideErc20TokenInformation(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
UNUSED(p1);
UNUSED(p2);
UNUSED(flags);
uint32_t offset = 0;
uint8_t tickerLength;
uint32_t chainId;
uint8_t hash[32];
cx_ecfp_public_key_t tokenKey;
void handleProvideErc20TokenInformation(uint8_t p1,
uint8_t p2,
uint8_t *workBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
UNUSED(p1);
UNUSED(p2);
UNUSED(flags);
uint32_t offset = 0;
uint8_t tickerLength;
uint32_t chainId;
uint8_t hash[32];
cx_ecfp_public_key_t tokenKey;
tmpCtx.transactionContext.currentTokenIndex =
(tmpCtx.transactionContext.currentTokenIndex + 1) % MAX_TOKEN;
tokenDefinition_t *token =
&tmpCtx.transactionContext.tokens[tmpCtx.transactionContext.currentTokenIndex];
tmpCtx.transactionContext.currentTokenIndex = (tmpCtx.transactionContext.currentTokenIndex + 1) % MAX_TOKEN;
tokenDefinition_t* token = &tmpCtx.transactionContext.tokens[tmpCtx.transactionContext.currentTokenIndex];
PRINTF("Provisioning currentTokenIndex %d\n", tmpCtx.transactionContext.currentTokenIndex);
PRINTF("Provisioning currentTokenIndex %d\n", tmpCtx.transactionContext.currentTokenIndex);
if (dataLength < 1) {
THROW(0x6A80);
}
tickerLength = workBuffer[offset++];
dataLength--;
if ((tickerLength + 1) >= sizeof(token->ticker)) {
THROW(0x6A80);
}
if (dataLength < tickerLength + 20 + 4 + 4) {
THROW(0x6A80);
}
cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
memmove(token->ticker, workBuffer + offset, tickerLength);
token->ticker[tickerLength] = ' ';
token->ticker[tickerLength + 1] = '\0';
offset += tickerLength;
dataLength -= tickerLength;
memmove(token->address, workBuffer + offset, 20);
offset += 20;
dataLength -= 20;
token->decimals = U4BE(workBuffer, offset);
offset += 4;
dataLength -= 4;
chainId = U4BE(workBuffer, offset);
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
PRINTF("ChainId token mismatch\n");
THROW(0x6A80);
}
offset += 4;
dataLength -= 4;
if (dataLength < 1) {
THROW(0x6A80);
}
tickerLength = workBuffer[offset++];
dataLength--;
if ((tickerLength + 1) >= sizeof(token->ticker)) {
THROW(0x6A80);
}
if (dataLength < tickerLength + 20 + 4 + 4) {
THROW(0x6A80);
}
cx_hash_sha256(workBuffer + offset, tickerLength + 20 + 4 + 4, hash, 32);
memmove(token->ticker, workBuffer + offset, tickerLength);
token->ticker[tickerLength] = ' ';
token->ticker[tickerLength + 1] = '\0';
offset += tickerLength;
dataLength -= tickerLength;
memmove(token->address, workBuffer + offset, 20);
offset += 20;
dataLength -= 20;
token->decimals = U4BE(workBuffer, offset);
offset += 4;
dataLength -= 4;
chainId = U4BE(workBuffer, offset);
if ((chainConfig->chainId != 0) && (chainConfig->chainId != chainId)) {
PRINTF("ChainId token mismatch\n");
THROW(0x6A80);
}
offset += 4;
dataLength -= 4;
#ifdef HAVE_TOKENS_EXTRA_LIST
tokenDefinition_t *currentToken = NULL;
uint32_t index;
for (index=0; index < NUM_TOKENS_EXTRA; index++) {
currentToken = (tokenDefinition_t *)PIC(&TOKENS_EXTRA[index]);
if (memcmp(currentToken->address, token->address, 20) == 0) {
strcpy((char*)token->ticker, (char*)currentToken->ticker);
token->decimals = currentToken->decimals;
break;
}
for (index = 0; index < NUM_TOKENS_EXTRA; index++) {
currentToken = (tokenDefinition_t *) PIC(&TOKENS_EXTRA[index]);
if (memcmp(currentToken->address, token->address, 20) == 0) {
strcpy((char *) token->ticker, (char *) currentToken->ticker);
token->decimals = currentToken->decimals;
break;
}
}
if (index < NUM_TOKENS_EXTRA) {
PRINTF("Descriptor whitelisted\n");
}
else {
cx_ecfp_init_public_key(CX_CURVE_256K1, TOKEN_SIGNATURE_PUBLIC_KEY, sizeof(TOKEN_SIGNATURE_PUBLIC_KEY), &tokenKey);
if (!cx_ecdsa_verify(&tokenKey, CX_LAST, CX_SHA256, hash, 32, workBuffer + offset, dataLength)) {
PRINTF("Invalid token signature\n");
THROW(0x6A80);
}
PRINTF("Descriptor whitelisted\n");
} else {
cx_ecfp_init_public_key(CX_CURVE_256K1,
TOKEN_SIGNATURE_PUBLIC_KEY,
sizeof(TOKEN_SIGNATURE_PUBLIC_KEY),
&tokenKey);
if (!cx_ecdsa_verify(&tokenKey,
CX_LAST,
CX_SHA256,
hash,
32,
workBuffer + offset,
dataLength)) {
PRINTF("Invalid token signature\n");
THROW(0x6A80);
}
}
#else
cx_ecfp_init_public_key(CX_CURVE_256K1, TOKEN_SIGNATURE_PUBLIC_KEY, sizeof(TOKEN_SIGNATURE_PUBLIC_KEY), &tokenKey);
if (!cx_ecdsa_verify(&tokenKey, CX_LAST, CX_SHA256, hash, 32, workBuffer + offset, dataLength)) {
PRINTF("Invalid token signature\n");
THROW(0x6A80);
}
cx_ecfp_init_public_key(CX_CURVE_256K1,
TOKEN_SIGNATURE_PUBLIC_KEY,
sizeof(TOKEN_SIGNATURE_PUBLIC_KEY),
&tokenKey);
if (!cx_ecdsa_verify(&tokenKey,
CX_LAST,
CX_SHA256,
hash,
32,
workBuffer + offset,
dataLength)) {
PRINTF("Invalid token signature\n");
THROW(0x6A80);
}
#endif
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentTokenIndex] = 1;
THROW(0x9000);
tmpCtx.transactionContext.tokenSet[tmpCtx.transactionContext.currentTokenIndex] = 1;
THROW(0x9000);
}
#endif

View File

@@ -3,19 +3,23 @@
#include "shared_context.h"
#include "apdu_constants.h"
void handleSetEth2WithdrawalIndex(uint8_t p1,
uint8_t p2,
uint8_t *dataBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
if (dataLength != 4) {
THROW(0x6700);
}
void handleSetEth2WithdrawalIndex(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
if (dataLength != 4) {
THROW(0x6700);
}
if ((p1 != 0) || (p2 != 0)) {
THROW(0x6B00);
}
if ((p1 != 0) || (p2 != 0)) {
THROW(0x6B00);
}
eth2WithdrawalIndex = U4BE(dataBuffer, 0);
eth2WithdrawalIndex = U4BE(dataBuffer, 0);
THROW(0x9000);
THROW(0x9000);
}
#endif

View File

@@ -3,94 +3,113 @@
#include "utils.h"
#include "ui_flow.h"
static const char const SIGN_MAGIC[] = "\x19"
"Ethereum Signed Message:\n";
static const char const SIGN_MAGIC[] =
"\x19"
"Ethereum Signed Message:\n";
void handleSignPersonalMessage(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
UNUSED(tx);
uint8_t hashMessage[32];
if (p1 == P1_FIRST) {
char tmp[11];
uint32_t index;
uint32_t base = 10;
uint8_t pos = 0;
uint32_t i;
if (dataLength < 1) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
appState = APP_STATE_SIGNING_MESSAGE;
tmpCtx.messageSigningContext.pathLength = workBuffer[0];
if ((tmpCtx.messageSigningContext.pathLength < 0x01) ||
(tmpCtx.messageSigningContext.pathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
workBuffer++;
dataLength--;
for (i = 0; i < tmpCtx.messageSigningContext.pathLength; i++) {
if (dataLength < 4) {
PRINTF("Invalid data\n");
THROW(0x6a80);
void handleSignPersonalMessage(uint8_t p1,
uint8_t p2,
uint8_t *workBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
UNUSED(tx);
uint8_t hashMessage[32];
if (p1 == P1_FIRST) {
char tmp[11];
uint32_t index;
uint32_t base = 10;
uint8_t pos = 0;
uint32_t i;
if (dataLength < 1) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
tmpCtx.messageSigningContext.bip32Path[i] = U4BE(workBuffer, 0);
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
appState = APP_STATE_SIGNING_MESSAGE;
tmpCtx.messageSigningContext.pathLength = workBuffer[0];
if ((tmpCtx.messageSigningContext.pathLength < 0x01) ||
(tmpCtx.messageSigningContext.pathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
workBuffer++;
dataLength--;
for (i = 0; i < tmpCtx.messageSigningContext.pathLength; i++) {
if (dataLength < 4) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
tmpCtx.messageSigningContext.bip32Path[i] = U4BE(workBuffer, 0);
workBuffer += 4;
dataLength -= 4;
}
if (dataLength < 4) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
tmpCtx.messageSigningContext.remainingLength = U4BE(workBuffer, 0);
workBuffer += 4;
dataLength -= 4;
}
if (dataLength < 4) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
tmpCtx.messageSigningContext.remainingLength = U4BE(workBuffer, 0);
workBuffer += 4;
dataLength -= 4;
// Initialize message header + length
cx_keccak_init(&global_sha3, 256);
cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)SIGN_MAGIC, sizeof(SIGN_MAGIC) - 1, NULL, 0);
for (index = 1; (((index * base) <= tmpCtx.messageSigningContext.remainingLength) &&
// Initialize message header + length
cx_keccak_init(&global_sha3, 256);
cx_hash((cx_hash_t *) &global_sha3,
0,
(uint8_t *) SIGN_MAGIC,
sizeof(SIGN_MAGIC) - 1,
NULL,
0);
for (index = 1; (((index * base) <= tmpCtx.messageSigningContext.remainingLength) &&
(((index * base) / base) == index));
index *= base);
for (; index; index /= base) {
tmp[pos++] = '0' + ((tmpCtx.messageSigningContext.remainingLength / index) % base);
index *= base)
;
for (; index; index /= base) {
tmp[pos++] = '0' + ((tmpCtx.messageSigningContext.remainingLength / index) % base);
}
tmp[pos] = '\0';
cx_hash((cx_hash_t *) &global_sha3, 0, (uint8_t *) tmp, pos, NULL, 0);
cx_sha256_init(&tmpContent.sha2);
} else if (p1 != P1_MORE) {
THROW(0x6B00);
}
tmp[pos] = '\0';
cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)tmp, pos, NULL, 0);
cx_sha256_init(&tmpContent.sha2);
}
else if (p1 != P1_MORE) {
THROW(0x6B00);
}
if (p2 != 0) {
THROW(0x6B00);
}
if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_MESSAGE)) {
PRINTF("Signature not initialized\n");
THROW(0x6985);
}
if (dataLength > tmpCtx.messageSigningContext.remainingLength) {
THROW(0x6A80);
}
cx_hash((cx_hash_t *)&global_sha3, 0, workBuffer, dataLength, NULL, 0);
cx_hash((cx_hash_t *)&tmpContent.sha2, 0, workBuffer, dataLength, NULL, 0);
tmpCtx.messageSigningContext.remainingLength -= dataLength;
if (tmpCtx.messageSigningContext.remainingLength == 0) {
cx_hash((cx_hash_t *)&global_sha3, CX_LAST, workBuffer, 0, tmpCtx.messageSigningContext.hash, 32);
cx_hash((cx_hash_t *)&tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage, 32);
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "%.*H", sizeof(hashMessage), hashMessage);
if (p2 != 0) {
THROW(0x6B00);
}
if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_MESSAGE)) {
PRINTF("Signature not initialized\n");
THROW(0x6985);
}
if (dataLength > tmpCtx.messageSigningContext.remainingLength) {
THROW(0x6A80);
}
cx_hash((cx_hash_t *) &global_sha3, 0, workBuffer, dataLength, NULL, 0);
cx_hash((cx_hash_t *) &tmpContent.sha2, 0, workBuffer, dataLength, NULL, 0);
tmpCtx.messageSigningContext.remainingLength -= dataLength;
if (tmpCtx.messageSigningContext.remainingLength == 0) {
cx_hash((cx_hash_t *) &global_sha3,
CX_LAST,
workBuffer,
0,
tmpCtx.messageSigningContext.hash,
32);
cx_hash((cx_hash_t *) &tmpContent.sha2, CX_LAST, workBuffer, 0, hashMessage, 32);
snprintf(strings.tmp.tmp,
sizeof(strings.tmp.tmp),
"%.*H",
sizeof(hashMessage),
hashMessage);
#ifdef NO_CONSENT
io_seproxyhal_touch_signMessage_ok(NULL);
#else //NO_CONSENT
ux_flow_init(0, ux_sign_flow, NULL);
#endif // NO_CONSENT
io_seproxyhal_touch_signMessage_ok(NULL);
#else // NO_CONSENT
ux_flow_init(0, ux_sign_flow, NULL);
#endif // NO_CONSENT
*flags |= IO_ASYNCH_REPLY;
*flags |= IO_ASYNCH_REPLY;
} else {
THROW(0x9000);
}
} else {
THROW(0x9000);
}
}

View File

@@ -8,25 +8,31 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) {
cx_ecfp_private_key_t privateKey;
uint32_t tx = 0;
io_seproxyhal_io_heartbeat();
os_perso_derive_node_bip32(
CX_CURVE_256K1, tmpCtx.messageSigningContext.bip32Path,
tmpCtx.messageSigningContext.pathLength, privateKeyData, NULL);
os_perso_derive_node_bip32(CX_CURVE_256K1,
tmpCtx.messageSigningContext.bip32Path,
tmpCtx.messageSigningContext.pathLength,
privateKeyData,
NULL);
io_seproxyhal_io_heartbeat();
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
explicit_bzero(privateKeyData, sizeof(privateKeyData));
unsigned int info = 0;
io_seproxyhal_io_heartbeat();
signatureLength =
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
tmpCtx.messageSigningContext.hash,
sizeof(tmpCtx.messageSigningContext.hash), signature, sizeof(signature), &info);
signatureLength = cx_ecdsa_sign(&privateKey,
CX_RND_RFC6979 | CX_LAST,
CX_SHA256,
tmpCtx.messageSigningContext.hash,
sizeof(tmpCtx.messageSigningContext.hash),
signature,
sizeof(signature),
&info);
explicit_bzero(&privateKey, sizeof(privateKey));
G_io_apdu_buffer[0] = 27;
if (info & CX_ECCINFO_PARITY_ODD) {
G_io_apdu_buffer[0]++;
G_io_apdu_buffer[0]++;
}
if (info & CX_ECCINFO_xGTn) {
G_io_apdu_buffer[0] += 2;
G_io_apdu_buffer[0] += 2;
}
format_signature_out(signature);
tx = 65;
@@ -37,7 +43,7 @@ unsigned int io_seproxyhal_touch_signMessage_ok(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}
unsigned int io_seproxyhal_touch_signMessage_cancel(const bagl_element_t *e) {
@@ -48,6 +54,5 @@ unsigned int io_seproxyhal_touch_signMessage_cancel(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}

View File

@@ -1,6 +1,7 @@
#include "shared_context.h"
#include "ui_callbacks.h"
// clang-format off
UX_STEP_NOCB(
ux_sign_flow_1_step,
pnn,
@@ -34,11 +35,10 @@ UX_STEP_CB(
"Cancel",
"signature",
});
// clang-format on
UX_FLOW(ux_sign_flow,
&ux_sign_flow_1_step,
&ux_sign_flow_2_step,
&ux_sign_flow_3_step,
&ux_sign_flow_4_step
);
&ux_sign_flow_1_step,
&ux_sign_flow_2_step,
&ux_sign_flow_3_step,
&ux_sign_flow_4_step);

View File

@@ -3,52 +3,58 @@
#include "utils.h"
#include "ui_flow.h"
static const char const SIGN_MAGIC[] = "\x19"
"Ethereum Signed Message:\n";
static const char const SIGN_MAGIC[] =
"\x19"
"Ethereum Signed Message:\n";
void handleSignEIP712Message(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
uint8_t i;
void handleSignEIP712Message(uint8_t p1,
uint8_t p2,
uint8_t *workBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
uint8_t i;
UNUSED(tx);
if ((p1 != 00) || (p2 != 00)) {
THROW(0x6B00);
}
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
if (dataLength < 1) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
tmpCtx.messageSigningContext712.pathLength = workBuffer[0];
if ((tmpCtx.messageSigningContext712.pathLength < 0x01) ||
(tmpCtx.messageSigningContext712.pathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
workBuffer++;
dataLength--;
for (i = 0; i < tmpCtx.messageSigningContext712.pathLength; i++) {
if (dataLength < 4) {
PRINTF("Invalid data\n");
THROW(0x6a80);
UNUSED(tx);
if ((p1 != 00) || (p2 != 00)) {
THROW(0x6B00);
}
tmpCtx.messageSigningContext712.bip32Path[i] = U4BE(workBuffer, 0);
workBuffer += 4;
dataLength -= 4;
}
if (dataLength < 32 + 32) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
memmove(tmpCtx.messageSigningContext712.domainHash, workBuffer, 32);
memmove(tmpCtx.messageSigningContext712.messageHash, workBuffer + 32, 32);
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
if (dataLength < 1) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
tmpCtx.messageSigningContext712.pathLength = workBuffer[0];
if ((tmpCtx.messageSigningContext712.pathLength < 0x01) ||
(tmpCtx.messageSigningContext712.pathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
workBuffer++;
dataLength--;
for (i = 0; i < tmpCtx.messageSigningContext712.pathLength; i++) {
if (dataLength < 4) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
tmpCtx.messageSigningContext712.bip32Path[i] = U4BE(workBuffer, 0);
workBuffer += 4;
dataLength -= 4;
}
if (dataLength < 32 + 32) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
memmove(tmpCtx.messageSigningContext712.domainHash, workBuffer, 32);
memmove(tmpCtx.messageSigningContext712.messageHash, workBuffer + 32, 32);
#ifdef NO_CONSENT
io_seproxyhal_touch_signMessage_ok(NULL);
#else //NO_CONSENT
#else // NO_CONSENT
ux_flow_init(0, ux_sign_712_v0_flow, NULL);
#endif // NO_CONSENT
#endif // NO_CONSENT
*flags |= IO_ASYNCH_REPLY;
}

View File

@@ -1,7 +1,7 @@
#include "shared_context.h"
#include "ui_callbacks.h"
static const uint8_t const EIP_712_MAGIC[] = { 0x19, 0x01 };
static const uint8_t const EIP_712_MAGIC[] = {0x19, 0x01};
unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) {
uint8_t privateKeyData[32];
@@ -12,32 +12,51 @@ unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) {
uint32_t tx = 0;
io_seproxyhal_io_heartbeat();
cx_keccak_init(&global_sha3, 256);
cx_hash((cx_hash_t *)&global_sha3, 0, (uint8_t*)EIP_712_MAGIC, sizeof(EIP_712_MAGIC), NULL, 0);
cx_hash((cx_hash_t *)&global_sha3, 0, tmpCtx.messageSigningContext712.domainHash,
sizeof(tmpCtx.messageSigningContext712.domainHash), NULL, 0);
cx_hash((cx_hash_t *)&global_sha3, CX_LAST, tmpCtx.messageSigningContext712.messageHash,
sizeof(tmpCtx.messageSigningContext712.messageHash), hash, sizeof(hash));
cx_hash((cx_hash_t *) &global_sha3,
0,
(uint8_t *) EIP_712_MAGIC,
sizeof(EIP_712_MAGIC),
NULL,
0);
cx_hash((cx_hash_t *) &global_sha3,
0,
tmpCtx.messageSigningContext712.domainHash,
sizeof(tmpCtx.messageSigningContext712.domainHash),
NULL,
0);
cx_hash((cx_hash_t *) &global_sha3,
CX_LAST,
tmpCtx.messageSigningContext712.messageHash,
sizeof(tmpCtx.messageSigningContext712.messageHash),
hash,
sizeof(hash));
PRINTF("EIP712 hash to sign %.*H\n", 32, hash);
io_seproxyhal_io_heartbeat();
os_perso_derive_node_bip32(
CX_CURVE_256K1, tmpCtx.messageSigningContext712.bip32Path,
tmpCtx.messageSigningContext712.pathLength, privateKeyData, NULL);
os_perso_derive_node_bip32(CX_CURVE_256K1,
tmpCtx.messageSigningContext712.bip32Path,
tmpCtx.messageSigningContext712.pathLength,
privateKeyData,
NULL);
io_seproxyhal_io_heartbeat();
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
explicit_bzero(privateKeyData, sizeof(privateKeyData));
unsigned int info = 0;
io_seproxyhal_io_heartbeat();
signatureLength =
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
hash,
sizeof(hash), signature, sizeof(signature), &info);
signatureLength = cx_ecdsa_sign(&privateKey,
CX_RND_RFC6979 | CX_LAST,
CX_SHA256,
hash,
sizeof(hash),
signature,
sizeof(signature),
&info);
explicit_bzero(&privateKey, sizeof(privateKey));
G_io_apdu_buffer[0] = 27;
if (info & CX_ECCINFO_PARITY_ODD) {
G_io_apdu_buffer[0]++;
G_io_apdu_buffer[0]++;
}
if (info & CX_ECCINFO_xGTn) {
G_io_apdu_buffer[0] += 2;
G_io_apdu_buffer[0] += 2;
}
format_signature_out(signature);
tx = 65;
@@ -48,7 +67,7 @@ unsigned int io_seproxyhal_touch_signMessage712_v0_ok(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}
unsigned int io_seproxyhal_touch_signMessage712_v0_cancel(const bagl_element_t *e) {
@@ -59,6 +78,5 @@ unsigned int io_seproxyhal_touch_signMessage712_v0_cancel(const bagl_element_t *
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}

View File

@@ -2,13 +2,14 @@
#include "ui_callbacks.h"
void prepare_domain_hash_v0() {
snprintf(strings.tmp.tmp, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.domainHash);
snprintf(strings.tmp.tmp, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.domainHash);
}
void prepare_message_hash_v0() {
snprintf(strings.tmp.tmp, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.messageHash);
snprintf(strings.tmp.tmp, 70, "0x%.*H", 32, tmpCtx.messageSigningContext712.messageHash);
}
// clang-format off
UX_STEP_NOCB(
ux_sign_712_v0_flow_1_step,
pnn,
@@ -51,12 +52,11 @@ UX_STEP_CB(
"Cancel",
"signature",
});
// clang-format on
UX_FLOW(ux_sign_712_v0_flow,
&ux_sign_712_v0_flow_1_step,
&ux_sign_712_v0_flow_2_step,
&ux_sign_712_v0_flow_3_step,
&ux_sign_712_v0_flow_4_step,
&ux_sign_712_v0_flow_5_step
);
&ux_sign_712_v0_flow_1_step,
&ux_sign_712_v0_flow_2_step,
&ux_sign_712_v0_flow_3_step,
&ux_sign_712_v0_flow_4_step,
&ux_sign_712_v0_flow_5_step);

View File

@@ -3,74 +3,79 @@
#include "ui_flow.h"
#include "feature_signTx.h"
void handleSign(uint8_t p1, uint8_t p2, uint8_t *workBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
UNUSED(tx);
parserStatus_e txResult;
uint32_t i;
if (p1 == P1_FIRST) {
if (dataLength < 1) {
PRINTF("Invalid data\n");
THROW(0x6a80);
void handleSign(uint8_t p1,
uint8_t p2,
uint8_t *workBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
UNUSED(tx);
parserStatus_e txResult;
uint32_t i;
if (p1 == P1_FIRST) {
if (dataLength < 1) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
appState = APP_STATE_SIGNING_TX;
tmpCtx.transactionContext.pathLength = workBuffer[0];
if ((tmpCtx.transactionContext.pathLength < 0x01) ||
(tmpCtx.transactionContext.pathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
workBuffer++;
dataLength--;
for (i = 0; i < tmpCtx.transactionContext.pathLength; i++) {
if (dataLength < 4) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
tmpCtx.transactionContext.bip32Path[i] = U4BE(workBuffer, 0);
workBuffer += 4;
dataLength -= 4;
}
dataPresent = false;
dataContext.tokenContext.pluginAvailable = 0;
initTx(&txContext, &global_sha3, &tmpContent.txContent, customProcessor, NULL);
} else if (p1 != P1_MORE) {
THROW(0x6B00);
}
if (appState != APP_STATE_IDLE) {
reset_app_context();
if (p2 != 0) {
THROW(0x6B00);
}
appState = APP_STATE_SIGNING_TX;
tmpCtx.transactionContext.pathLength = workBuffer[0];
if ((tmpCtx.transactionContext.pathLength < 0x01) ||
(tmpCtx.transactionContext.pathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_TX)) {
PRINTF("Signature not initialized\n");
THROW(0x6985);
}
workBuffer++;
dataLength--;
for (i = 0; i < tmpCtx.transactionContext.pathLength; i++) {
if (dataLength < 4) {
PRINTF("Invalid data\n");
THROW(0x6a80);
}
tmpCtx.transactionContext.bip32Path[i] = U4BE(workBuffer, 0);
workBuffer += 4;
dataLength -= 4;
if (txContext.currentField == TX_RLP_NONE) {
PRINTF("Parser not initialized\n");
THROW(0x6985);
}
txResult = processTx(&txContext,
workBuffer,
dataLength,
(chainConfig->kind == CHAIN_KIND_WANCHAIN ? TX_FLAG_TYPE : 0));
switch (txResult) {
case USTREAM_SUSPENDED:
break;
case USTREAM_FINISHED:
break;
case USTREAM_PROCESSING:
THROW(0x9000);
case USTREAM_FAULT:
THROW(0x6A80);
default:
PRINTF("Unexpected parser status\n");
THROW(0x6A80);
}
dataPresent = false;
dataContext.tokenContext.pluginAvailable = 0;
initTx(&txContext, &global_sha3, &tmpContent.txContent, customProcessor, NULL);
}
else
if (p1 != P1_MORE) {
THROW(0x6B00);
}
if (p2 != 0) {
THROW(0x6B00);
}
if ((p1 == P1_MORE) && (appState != APP_STATE_SIGNING_TX)) {
PRINTF("Signature not initialized\n");
THROW(0x6985);
}
if (txContext.currentField == TX_RLP_NONE) {
PRINTF("Parser not initialized\n");
THROW(0x6985);
}
txResult = processTx(&txContext, workBuffer, dataLength, (chainConfig->kind == CHAIN_KIND_WANCHAIN ? TX_FLAG_TYPE : 0));
switch (txResult) {
case USTREAM_SUSPENDED:
break;
case USTREAM_FINISHED:
break;
case USTREAM_PROCESSING:
THROW(0x9000);
case USTREAM_FAULT:
THROW(0x6A80);
default:
PRINTF("Unexpected parser status\n");
THROW(0x6A80);
}
if (txResult == USTREAM_FINISHED) {
finalizeParsing(false);
}
if (txResult == USTREAM_FINISHED) {
finalizeParsing(false);
}
*flags |= IO_ASYNCH_REPLY;
*flags |= IO_ASYNCH_REPLY;
}

View File

@@ -2,4 +2,3 @@
customStatus_e customProcessor(txContext_t *context);
void finalizeParsing(bool direct);

View File

@@ -11,7 +11,7 @@
uint32_t splitBinaryParameterPart(char *result, uint8_t *parameter) {
uint32_t i;
for (i=0; i<8; i++) {
for (i = 0; i < 8; i++) {
if (parameter[i] != 0x00) {
break;
}
@@ -21,16 +21,14 @@ uint32_t splitBinaryParameterPart(char *result, uint8_t *parameter) {
result[1] = '0';
result[2] = '\0';
return 2;
}
else {
} else {
array_hexstr(result, parameter + i, 8 - i);
return ((8 - i) * 2);
}
}
customStatus_e customProcessor(txContext_t *context) {
if ((context->currentField == TX_RLP_DATA) &&
(context->currentFieldLength != 0)) {
if ((context->currentField == TX_RLP_DATA) && (context->currentFieldLength != 0)) {
dataPresent = true;
// If handling a new contract rather than a function call, abort immediately
if (tmpContent.txContent.destinationLength == 0) {
@@ -38,320 +36,341 @@ customStatus_e customProcessor(txContext_t *context) {
}
if (context->currentFieldPos == 0) {
ethPluginInitContract_t pluginInit;
// If handling the beginning of the data field, assume that the function selector is present
// If handling the beginning of the data field, assume that the function selector is
// present
if (context->commandLength < 4) {
PRINTF("Missing function selector\n");
return CUSTOM_FAULT;
}
eth_plugin_prepare_init(&pluginInit, context->workBuffer, context->currentFieldLength);
dataContext.tokenContext.pluginAvailable = eth_plugin_perform_init(tmpContent.txContent.destination, &pluginInit);
dataContext.tokenContext.pluginAvailable =
eth_plugin_perform_init(tmpContent.txContent.destination, &pluginInit);
PRINTF("pluginAvailable %d\n", dataContext.tokenContext.pluginAvailable);
if (dataContext.tokenContext.pluginAvailable) {
dataContext.tokenContext.fieldIndex = 0;
dataContext.tokenContext.fieldOffset = 0;
copyTxData(context, NULL, 4);
if (context->currentFieldLength == 4) {
return CUSTOM_NOT_HANDLED;
}
dataContext.tokenContext.fieldIndex = 0;
dataContext.tokenContext.fieldOffset = 0;
copyTxData(context, NULL, 4);
if (context->currentFieldLength == 4) {
return CUSTOM_NOT_HANDLED;
}
}
}
uint32_t blockSize;
uint32_t copySize;
uint32_t fieldPos = context->currentFieldPos;
if (fieldPos == 0) { // not reached if a plugin is available
if (!N_storage.dataAllowed) {
uint32_t blockSize;
uint32_t copySize;
uint32_t fieldPos = context->currentFieldPos;
if (fieldPos == 0) { // not reached if a plugin is available
if (!N_storage.dataAllowed) {
PRINTF("Data field forbidden\n");
return CUSTOM_FAULT;
}
if (!N_storage.contractDetails) {
}
if (!N_storage.contractDetails) {
return CUSTOM_NOT_HANDLED;
}
dataContext.tokenContext.fieldIndex = 0;
dataContext.tokenContext.fieldOffset = 0;
blockSize = 4;
}
else {
if (!N_storage.contractDetails && !dataContext.tokenContext.pluginAvailable) {
}
dataContext.tokenContext.fieldIndex = 0;
dataContext.tokenContext.fieldOffset = 0;
blockSize = 4;
} else {
if (!N_storage.contractDetails && !dataContext.tokenContext.pluginAvailable) {
return CUSTOM_NOT_HANDLED;
}
blockSize = 32 - (dataContext.tokenContext.fieldOffset % 32);
}
}
blockSize = 32 - (dataContext.tokenContext.fieldOffset % 32);
}
// Sanity check
if ((context->currentFieldLength - fieldPos) < blockSize) {
PRINTF("Unconsistent data\n");
return CUSTOM_FAULT;
}
// Sanity check
if ((context->currentFieldLength - fieldPos) < blockSize) {
PRINTF("Unconsistent data\n");
return CUSTOM_FAULT;
}
copySize = (context->commandLength < blockSize ? context->commandLength : blockSize);
copySize = (context->commandLength < blockSize ? context->commandLength : blockSize);
PRINTF("currentFieldPos %d copySize %d\n", context->currentFieldPos, copySize);
PRINTF("currentFieldPos %d copySize %d\n", context->currentFieldPos, copySize);
copyTxData(context,
dataContext.tokenContext.data + dataContext.tokenContext.fieldOffset,
copySize);
copyTxData(context,
dataContext.tokenContext.data + dataContext.tokenContext.fieldOffset,
copySize);
if (context->currentFieldPos == context->currentFieldLength) {
context->currentField++;
context->processingField = false;
}
if (context->currentFieldPos == context->currentFieldLength) {
context->currentField++;
context->processingField = false;
}
dataContext.tokenContext.fieldOffset += copySize;
dataContext.tokenContext.fieldOffset += copySize;
if (copySize == blockSize) {
// Can process or display
if (dataContext.tokenContext.pluginAvailable) {
if (copySize == blockSize) {
// Can process or display
if (dataContext.tokenContext.pluginAvailable) {
ethPluginProvideParameter_t pluginProvideParameter;
eth_plugin_prepare_provide_parameter(&pluginProvideParameter,
dataContext.tokenContext.data,
dataContext.tokenContext.fieldIndex * 32 + 4);
if (!eth_plugin_call(NULL, ETH_PLUGIN_PROVIDE_PARAMETER, (void*)&pluginProvideParameter)) {
PRINTF("Plugin parameter call failed\n");
return CUSTOM_FAULT;
eth_plugin_prepare_provide_parameter(&pluginProvideParameter,
dataContext.tokenContext.data,
dataContext.tokenContext.fieldIndex * 32 + 4);
if (!eth_plugin_call(NULL,
ETH_PLUGIN_PROVIDE_PARAMETER,
(void *) &pluginProvideParameter)) {
PRINTF("Plugin parameter call failed\n");
return CUSTOM_FAULT;
}
dataContext.tokenContext.fieldIndex++;
dataContext.tokenContext.fieldOffset = 0;
return CUSTOM_HANDLED;
}
}
if (fieldPos != 0) {
dataContext.tokenContext.fieldIndex++;
}
dataContext.tokenContext.fieldOffset = 0;
if (fieldPos == 0) {
array_hexstr(strings.tmp.tmp, dataContext.tokenContext.data, 4);
ux_flow_init(0, ux_confirm_selector_flow, NULL);
}
else {
uint32_t offset = 0;
uint32_t i;
snprintf(strings.tmp.tmp2, sizeof(strings.tmp.tmp2), "Field %d", dataContext.tokenContext.fieldIndex);
for (i=0; i<4; i++) {
offset += splitBinaryParameterPart(strings.tmp.tmp + offset, dataContext.tokenContext.data + 8 * i);
if (i != 3) {
strings.tmp.tmp[offset++] = ':';
}
}
ux_flow_init(0, ux_confirm_parameter_flow, NULL);
}
}
else {
return CUSTOM_HANDLED;
}
if (fieldPos != 0) {
dataContext.tokenContext.fieldIndex++;
}
dataContext.tokenContext.fieldOffset = 0;
if (fieldPos == 0) {
array_hexstr(strings.tmp.tmp, dataContext.tokenContext.data, 4);
ux_flow_init(0, ux_confirm_selector_flow, NULL);
} else {
uint32_t offset = 0;
uint32_t i;
snprintf(strings.tmp.tmp2,
sizeof(strings.tmp.tmp2),
"Field %d",
dataContext.tokenContext.fieldIndex);
for (i = 0; i < 4; i++) {
offset += splitBinaryParameterPart(strings.tmp.tmp + offset,
dataContext.tokenContext.data + 8 * i);
if (i != 3) {
strings.tmp.tmp[offset++] = ':';
}
}
ux_flow_init(0, ux_confirm_parameter_flow, NULL);
}
} else {
return CUSTOM_HANDLED;
}
return CUSTOM_SUSPENDED;
return CUSTOM_SUSPENDED;
}
return CUSTOM_NOT_HANDLED;
}
void to_uppercase(char* str, unsigned char size){
for (unsigned char i = 0; i < size && str[i] != 0; i++)
{
void to_uppercase(char *str, unsigned char size) {
for (unsigned char i = 0; i < size && str[i] != 0; i++) {
str[i] = str[i] >= 'a' ? str[i] - ('a' - 'A') : str[i];
}
}
void compareOrCopy(char* preapproved_string, char* parsed_string, bool silent_mode){
if(silent_mode){
/* ETH address are not fundamentally case sensitive but might
have some for checksum purpose, so let's get rid of these diffs */
to_uppercase(preapproved_string, strlen(preapproved_string));
to_uppercase(parsed_string, strlen(parsed_string));
if(memcmp(preapproved_string, parsed_string, strlen(preapproved_string))){
THROW(ERR_SILENT_MODE_CHECK_FAILED);
void compareOrCopy(char *preapproved_string, char *parsed_string, bool silent_mode) {
if (silent_mode) {
/* ETH address are not fundamentally case sensitive but might
have some for checksum purpose, so let's get rid of these diffs */
to_uppercase(preapproved_string, strlen(preapproved_string));
to_uppercase(parsed_string, strlen(parsed_string));
if (memcmp(preapproved_string, parsed_string, strlen(preapproved_string))) {
THROW(ERR_SILENT_MODE_CHECK_FAILED);
}
} else {
strcpy(preapproved_string, parsed_string);
}
}
else{
strcpy(preapproved_string, parsed_string);
}
}
void reportFinalizeError(bool direct) {
reset_app_context();
if (direct) {
THROW(0x6A80);
}
else {
io_seproxyhal_send_status(0x6A80);
ui_idle();
}
reset_app_context();
if (direct) {
THROW(0x6A80);
} else {
io_seproxyhal_send_status(0x6A80);
ui_idle();
}
}
void computeFees(char *displayBuffer, uint32_t displayBufferSize) {
uint256_t gasPrice, startGas, uint256;
uint8_t *feeTicker = (uint8_t *)PIC(chainConfig->coinName);
uint8_t tickerOffset = 0;
uint32_t i;
uint256_t gasPrice, startGas, uint256;
uint8_t *feeTicker = (uint8_t *) PIC(chainConfig->coinName);
uint8_t tickerOffset = 0;
uint32_t i;
PRINTF("Max fee\n");
PRINTF("Gasprice %.*H\n", tmpContent.txContent.gasprice.length, tmpContent.txContent.gasprice.value);
PRINTF("Startgas %.*H\n", tmpContent.txContent.startgas.length, tmpContent.txContent.startgas.value);
convertUint256BE(tmpContent.txContent.gasprice.value, tmpContent.txContent.gasprice.length, &gasPrice);
convertUint256BE(tmpContent.txContent.startgas.value, tmpContent.txContent.startgas.length, &startGas);
mul256(&gasPrice, &startGas, &uint256);
tostring256(&uint256, 10, (char *)(G_io_apdu_buffer + 100), 100);
i = 0;
while (G_io_apdu_buffer[100 + i]) {
i++;
}
adjustDecimals((char *)(G_io_apdu_buffer + 100), i, (char *)G_io_apdu_buffer, 100, WEI_TO_ETHER);
i = 0;
tickerOffset=0;
memset(displayBuffer, 0, displayBufferSize);
while (feeTicker[tickerOffset]) {
displayBuffer[tickerOffset] = feeTicker[tickerOffset];
tickerOffset++;
}
while (G_io_apdu_buffer[i]) {
displayBuffer[tickerOffset + i] = G_io_apdu_buffer[i];
i++;
}
displayBuffer[tickerOffset + i] = '\0';
PRINTF("Max fee\n");
PRINTF("Gasprice %.*H\n",
tmpContent.txContent.gasprice.length,
tmpContent.txContent.gasprice.value);
PRINTF("Startgas %.*H\n",
tmpContent.txContent.startgas.length,
tmpContent.txContent.startgas.value);
convertUint256BE(tmpContent.txContent.gasprice.value,
tmpContent.txContent.gasprice.length,
&gasPrice);
convertUint256BE(tmpContent.txContent.startgas.value,
tmpContent.txContent.startgas.length,
&startGas);
mul256(&gasPrice, &startGas, &uint256);
tostring256(&uint256, 10, (char *) (G_io_apdu_buffer + 100), 100);
i = 0;
while (G_io_apdu_buffer[100 + i]) {
i++;
}
adjustDecimals((char *) (G_io_apdu_buffer + 100),
i,
(char *) G_io_apdu_buffer,
100,
WEI_TO_ETHER);
i = 0;
tickerOffset = 0;
memset(displayBuffer, 0, displayBufferSize);
while (feeTicker[tickerOffset]) {
displayBuffer[tickerOffset] = feeTicker[tickerOffset];
tickerOffset++;
}
while (G_io_apdu_buffer[i]) {
displayBuffer[tickerOffset + i] = G_io_apdu_buffer[i];
i++;
}
displayBuffer[tickerOffset + i] = '\0';
}
void finalizeParsing(bool direct) {
char displayBuffer[50];
uint8_t decimals = WEI_TO_ETHER;
uint8_t *ticker = (uint8_t *)PIC(chainConfig->coinName);
ethPluginFinalize_t pluginFinalize;
tokenDefinition_t *token1 = NULL, *token2 = NULL;
bool genericUI = true;
void finalizeParsing(bool direct) {
char displayBuffer[50];
uint8_t decimals = WEI_TO_ETHER;
uint8_t *ticker = (uint8_t *) PIC(chainConfig->coinName);
ethPluginFinalize_t pluginFinalize;
tokenDefinition_t *token1 = NULL, *token2 = NULL;
bool genericUI = true;
// Verify the chain
if (chainConfig->chainId != 0) {
uint32_t v = getV(&tmpContent.txContent);
if (chainConfig->chainId != v) {
reset_app_context();
PRINTF("Invalid chainId %d expected %d\n", v, chainConfig->chainId);
reportFinalizeError(direct);
if (!direct) {
return;
}
}
}
// Store the hash
cx_hash((cx_hash_t *)&global_sha3, CX_LAST, tmpCtx.transactionContext.hash, 0, tmpCtx.transactionContext.hash, 32);
// Finalize the plugin handling
if (dataContext.tokenContext.pluginAvailable) {
genericUI = false;
eth_plugin_prepare_finalize(&pluginFinalize);
if (!eth_plugin_call(NULL, ETH_PLUGIN_FINALIZE, (void*)&pluginFinalize)) {
PRINTF("Plugin finalize call failed\n");
reportFinalizeError(direct);
if (!direct) {
return;
}
}
// Lookup tokens if requested
if (pluginFinalize.tokenLookup1 != NULL) {
ethPluginProvideToken_t pluginProvideToken;
token1 = getKnownToken(pluginFinalize.tokenLookup1);
if (pluginFinalize.tokenLookup2 != NULL) {
token2 = getKnownToken(pluginFinalize.tokenLookup2);
}
eth_plugin_prepare_provide_token(&pluginProvideToken, token1, token2);
if (!eth_plugin_call(NULL, ETH_PLUGIN_PROVIDE_TOKEN, (void*)&pluginProvideToken)) {
PRINTF("Plugin provide token call failed\n");
reportFinalizeError(direct);
if (!direct) {
return;
}
}
pluginFinalize.result = pluginProvideToken.result;
}
if (pluginFinalize.result != ETH_PLUGIN_RESULT_FALLBACK) {
// Handle the right interface
switch(pluginFinalize.uiType) {
case ETH_UI_TYPE_GENERIC:
dataPresent = false;
dataContext.tokenContext.pluginUiMaxItems = pluginFinalize.numScreens;
break;
case ETH_UI_TYPE_AMOUNT_ADDRESS:
genericUI = true;
dataPresent = false;
if ((pluginFinalize.amount == NULL) || (pluginFinalize.address == NULL)) {
PRINTF("Incorrect amount/address set by plugin\n");
// Verify the chain
if (chainConfig->chainId != 0) {
uint32_t v = getV(&tmpContent.txContent);
if (chainConfig->chainId != v) {
reset_app_context();
PRINTF("Invalid chainId %d expected %d\n", v, chainConfig->chainId);
reportFinalizeError(direct);
if (!direct) {
return;
}
}
memmove(tmpContent.txContent.value.value, pluginFinalize.amount, 32);
tmpContent.txContent.value.length = 32;
memmove(tmpContent.txContent.destination, pluginFinalize.address, 20);
tmpContent.txContent.destinationLength = 20;
if (token1 != NULL) {
decimals = token1->decimals;
ticker = token1->ticker;
}
break;
default:
PRINTF("ui type %d not supported\n", pluginFinalize.uiType);
reportFinalizeError(direct);
if (!direct) {
return;
}
}
}
// Store the hash
cx_hash((cx_hash_t *) &global_sha3,
CX_LAST,
tmpCtx.transactionContext.hash,
0,
tmpCtx.transactionContext.hash,
32);
// Finalize the plugin handling
if (dataContext.tokenContext.pluginAvailable) {
genericUI = false;
eth_plugin_prepare_finalize(&pluginFinalize);
if (!eth_plugin_call(NULL, ETH_PLUGIN_FINALIZE, (void *) &pluginFinalize)) {
PRINTF("Plugin finalize call failed\n");
reportFinalizeError(direct);
if (!direct) {
return;
}
}
// Lookup tokens if requested
if (pluginFinalize.tokenLookup1 != NULL) {
ethPluginProvideToken_t pluginProvideToken;
token1 = getKnownToken(pluginFinalize.tokenLookup1);
if (pluginFinalize.tokenLookup2 != NULL) {
token2 = getKnownToken(pluginFinalize.tokenLookup2);
}
eth_plugin_prepare_provide_token(&pluginProvideToken, token1, token2);
if (!eth_plugin_call(NULL, ETH_PLUGIN_PROVIDE_TOKEN, (void *) &pluginProvideToken)) {
PRINTF("Plugin provide token call failed\n");
reportFinalizeError(direct);
if (!direct) {
return;
}
}
pluginFinalize.result = pluginProvideToken.result;
}
if (pluginFinalize.result != ETH_PLUGIN_RESULT_FALLBACK) {
// Handle the right interface
switch (pluginFinalize.uiType) {
case ETH_UI_TYPE_GENERIC:
dataPresent = false;
dataContext.tokenContext.pluginUiMaxItems = pluginFinalize.numScreens;
break;
case ETH_UI_TYPE_AMOUNT_ADDRESS:
genericUI = true;
dataPresent = false;
if ((pluginFinalize.amount == NULL) || (pluginFinalize.address == NULL)) {
PRINTF("Incorrect amount/address set by plugin\n");
reportFinalizeError(direct);
if (!direct) {
return;
}
}
memmove(tmpContent.txContent.value.value, pluginFinalize.amount, 32);
tmpContent.txContent.value.length = 32;
memmove(tmpContent.txContent.destination, pluginFinalize.address, 20);
tmpContent.txContent.destinationLength = 20;
if (token1 != NULL) {
decimals = token1->decimals;
ticker = token1->ticker;
}
break;
default:
PRINTF("ui type %d not supported\n", pluginFinalize.uiType);
reportFinalizeError(direct);
if (!direct) {
return;
}
}
} else {
genericUI = true;
}
}
if (dataPresent && !N_storage.dataAllowed) {
PRINTF("Data field forbidden\n");
reportFinalizeError(direct);
if (!direct) {
return;
}
}
}
}
else {
genericUI = true;
// Prepare destination address to display
if (genericUI) {
if (tmpContent.txContent.destinationLength != 0) {
displayBuffer[0] = '0';
displayBuffer[1] = 'x';
getEthAddressStringFromBinary(tmpContent.txContent.destination,
(uint8_t *) displayBuffer + 2,
&global_sha3,
chainConfig);
compareOrCopy(strings.common.fullAddress, displayBuffer, called_from_swap);
} else {
strcpy(strings.common.fullAddress, "Contract");
}
}
// Prepare amount to display
if (genericUI) {
amountToString(tmpContent.txContent.value.value,
tmpContent.txContent.value.length,
decimals,
(char *) ticker,
displayBuffer,
sizeof(displayBuffer));
compareOrCopy(strings.common.fullAmount, displayBuffer, called_from_swap);
}
// Compute maximum fee
if (genericUI) {
computeFees(displayBuffer, sizeof(displayBuffer));
compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap);
}
}
if (dataPresent && !N_storage.dataAllowed) {
PRINTF("Data field forbidden\n");
reportFinalizeError(direct);
if (!direct) {
return;
}
}
// Prepare destination address to display
if (genericUI) {
if (tmpContent.txContent.destinationLength != 0) {
displayBuffer[0] = '0';
displayBuffer[1] = 'x';
getEthAddressStringFromBinary(tmpContent.txContent.destination, (uint8_t*)displayBuffer+2, &global_sha3, chainConfig);
compareOrCopy(strings.common.fullAddress, displayBuffer, called_from_swap);
}
else
{
strcpy(strings.common.fullAddress, "Contract");
}
}
// Prepare amount to display
if (genericUI) {
amountToString(tmpContent.txContent.value.value, tmpContent.txContent.value.length, decimals, (char*)ticker, displayBuffer, sizeof(displayBuffer));
compareOrCopy(strings.common.fullAmount, displayBuffer, called_from_swap);
}
// Compute maximum fee
if (genericUI) {
computeFees(displayBuffer, sizeof(displayBuffer));
compareOrCopy(strings.common.maxFee, displayBuffer, called_from_swap);
}
bool no_consent = false;
bool no_consent = false;
no_consent = called_from_swap;
no_consent = called_from_swap;
#ifdef NO_CONSENT
no_consent = true;
#endif // NO_CONSENT
no_consent = true;
#endif // NO_CONSENT
if(no_consent){
io_seproxyhal_touch_tx_ok(NULL);
}
else{
if (genericUI) {
ux_flow_init(0,
((dataPresent && !N_storage.contractDetails) ? ux_approval_tx_data_warning_flow : ux_approval_tx_flow),
NULL);
if (no_consent) {
io_seproxyhal_touch_tx_ok(NULL);
} else {
if (genericUI) {
ux_flow_init(
0,
((dataPresent && !N_storage.contractDetails) ? ux_approval_tx_data_warning_flow
: ux_approval_tx_flow),
NULL);
} else {
plugin_ui_start();
}
}
else {
plugin_ui_start();
}
}
}

View File

@@ -10,34 +10,38 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) {
uint32_t tx = 0;
uint32_t v = getV(&tmpContent.txContent);
io_seproxyhal_io_heartbeat();
os_perso_derive_node_bip32(CX_CURVE_256K1, tmpCtx.transactionContext.bip32Path,
os_perso_derive_node_bip32(CX_CURVE_256K1,
tmpCtx.transactionContext.bip32Path,
tmpCtx.transactionContext.pathLength,
privateKeyData, NULL);
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32,
&privateKey);
privateKeyData,
NULL);
cx_ecfp_init_private_key(CX_CURVE_256K1, privateKeyData, 32, &privateKey);
explicit_bzero(privateKeyData, sizeof(privateKeyData));
unsigned int info = 0;
io_seproxyhal_io_heartbeat();
signatureLength =
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
tmpCtx.transactionContext.hash,
sizeof(tmpCtx.transactionContext.hash), signature, sizeof(signature), &info);
signatureLength = cx_ecdsa_sign(&privateKey,
CX_RND_RFC6979 | CX_LAST,
CX_SHA256,
tmpCtx.transactionContext.hash,
sizeof(tmpCtx.transactionContext.hash),
signature,
sizeof(signature),
&info);
explicit_bzero(&privateKey, sizeof(privateKey));
// Parity is present in the sequence tag in the legacy API
if (tmpContent.txContent.vLength == 0) {
// Legacy API
G_io_apdu_buffer[0] = 27;
}
else {
// New API
// Note that this is wrong for a large v, but the client can always recover
G_io_apdu_buffer[0] = (v * 2) + 35;
// Legacy API
G_io_apdu_buffer[0] = 27;
} else {
// New API
// Note that this is wrong for a large v, but the client can always recover
G_io_apdu_buffer[0] = (v * 2) + 35;
}
if (info & CX_ECCINFO_PARITY_ODD) {
G_io_apdu_buffer[0]++;
G_io_apdu_buffer[0]++;
}
if (info & CX_ECCINFO_xGTn) {
G_io_apdu_buffer[0] += 2;
G_io_apdu_buffer[0] += 2;
}
format_signature_out(signature);
tx = 65;
@@ -45,13 +49,13 @@ unsigned int io_seproxyhal_touch_tx_ok(const bagl_element_t *e) {
G_io_apdu_buffer[tx++] = 0x00;
// Send back the response, do not restart the event loop
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
if(called_from_swap){
if (called_from_swap) {
os_sched_exit(0);
}
reset_app_context();
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}
unsigned int io_seproxyhal_touch_tx_cancel(const bagl_element_t *e) {
@@ -62,31 +66,31 @@ unsigned int io_seproxyhal_touch_tx_cancel(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, 2);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}
unsigned int io_seproxyhal_touch_data_ok(const bagl_element_t *e) {
parserStatus_e txResult = USTREAM_FINISHED;
txResult = continueTx(&txContext);
switch (txResult) {
case USTREAM_SUSPENDED:
break;
case USTREAM_FINISHED:
break;
case USTREAM_PROCESSING:
io_seproxyhal_send_status(0x9000);
ui_idle();
break;
case USTREAM_FAULT:
reset_app_context();
io_seproxyhal_send_status(0x6A80);
ui_idle();
break;
default:
PRINTF("Unexpected parser status\n");
reset_app_context();
io_seproxyhal_send_status(0x6A80);
ui_idle();
case USTREAM_SUSPENDED:
break;
case USTREAM_FINISHED:
break;
case USTREAM_PROCESSING:
io_seproxyhal_send_status(0x9000);
ui_idle();
break;
case USTREAM_FAULT:
reset_app_context();
io_seproxyhal_send_status(0x6A80);
ui_idle();
break;
default:
PRINTF("Unexpected parser status\n");
reset_app_context();
io_seproxyhal_send_status(0x6A80);
ui_idle();
}
if (txResult == USTREAM_FINISHED) {
@@ -101,6 +105,5 @@ unsigned int io_seproxyhal_touch_data_cancel(const bagl_element_t *e) {
io_seproxyhal_send_status(0x6985);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}

View File

@@ -1,6 +1,7 @@
#include "shared_context.h"
#include "ui_callbacks.h"
// clang-format off
UX_STEP_NOCB(
ux_confirm_selector_flow_1_step,
pnn,
@@ -33,15 +34,16 @@ UX_STEP_CB(
&C_icon_crossmark,
"Reject",
});
// clang-format on
UX_FLOW(ux_confirm_selector_flow,
&ux_confirm_selector_flow_1_step,
&ux_confirm_selector_flow_2_step,
&ux_confirm_selector_flow_3_step,
&ux_confirm_selector_flow_4_step
);
UX_FLOW(ux_confirm_selector_flow,
&ux_confirm_selector_flow_1_step,
&ux_confirm_selector_flow_2_step,
&ux_confirm_selector_flow_3_step,
&ux_confirm_selector_flow_4_step);
//////////////////////////////////////////////////////////////////////
// clang-format off
UX_STEP_NOCB(
ux_confirm_parameter_flow_1_step,
pnn,
@@ -73,15 +75,16 @@ UX_STEP_CB(
&C_icon_crossmark,
"Reject",
});
// clang-format on
UX_FLOW(ux_confirm_parameter_flow,
&ux_confirm_parameter_flow_1_step,
&ux_confirm_parameter_flow_2_step,
&ux_confirm_parameter_flow_3_step,
&ux_confirm_parameter_flow_4_step
);
&ux_confirm_parameter_flow_1_step,
&ux_confirm_parameter_flow_2_step,
&ux_confirm_parameter_flow_3_step,
&ux_confirm_parameter_flow_4_step);
//////////////////////////////////////////////////////////////////////
// clang-format off
UX_STEP_NOCB(ux_approval_tx_1_step,
pnn,
{
@@ -135,23 +138,21 @@ UX_STEP_NOCB(ux_approval_tx_data_warning_step,
"Data",
"Present",
});
// clang-format on
UX_FLOW(ux_approval_tx_flow,
&ux_approval_tx_1_step,
&ux_approval_tx_2_step,
&ux_approval_tx_3_step,
&ux_approval_tx_4_step,
&ux_approval_tx_5_step,
&ux_approval_tx_6_step
);
&ux_approval_tx_1_step,
&ux_approval_tx_2_step,
&ux_approval_tx_3_step,
&ux_approval_tx_4_step,
&ux_approval_tx_5_step,
&ux_approval_tx_6_step);
UX_FLOW(ux_approval_tx_data_warning_flow,
&ux_approval_tx_1_step,
&ux_approval_tx_data_warning_step,
&ux_approval_tx_2_step,
&ux_approval_tx_3_step,
&ux_approval_tx_4_step,
&ux_approval_tx_5_step,
&ux_approval_tx_6_step
);
&ux_approval_tx_1_step,
&ux_approval_tx_data_warning_step,
&ux_approval_tx_2_step,
&ux_approval_tx_3_step,
&ux_approval_tx_4_step,
&ux_approval_tx_5_step,
&ux_approval_tx_6_step);

View File

@@ -6,55 +6,61 @@
#include "feature_stark_getPublicKey.h"
#include "ui_flow.h"
void handleStarkwareGetPublicKey(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
UNUSED(dataLength);
uint8_t privateKeyData[32];
uint32_t bip32Path[MAX_BIP32_PATH];
uint32_t i;
uint8_t bip32PathLength = *(dataBuffer++);
cx_ecfp_private_key_t privateKey;
reset_app_context();
if ((bip32PathLength < 0x01) ||
(bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
THROW(0x6B00);
}
if (p2 != 0) {
THROW(0x6B00);
}
for (i = 0; i < bip32PathLength; i++) {
bip32Path[i] = U4BE(dataBuffer, 0);
dataBuffer += 4;
}
io_seproxyhal_io_heartbeat();
starkDerivePrivateKey(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, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1);
explicit_bzero(&privateKey, sizeof(privateKey));
explicit_bzero(privateKeyData, sizeof(privateKeyData));
io_seproxyhal_io_heartbeat();
void handleStarkwareGetPublicKey(uint8_t p1,
uint8_t p2,
uint8_t *dataBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
UNUSED(dataLength);
uint8_t privateKeyData[32];
uint32_t bip32Path[MAX_BIP32_PATH];
uint32_t i;
uint8_t bip32PathLength = *(dataBuffer++);
cx_ecfp_private_key_t privateKey;
reset_app_context();
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
if ((p1 != P1_CONFIRM) && (p1 != P1_NON_CONFIRM)) {
THROW(0x6B00);
}
if (p2 != 0) {
THROW(0x6B00);
}
for (i = 0; i < bip32PathLength; i++) {
bip32Path[i] = U4BE(dataBuffer, 0);
dataBuffer += 4;
}
io_seproxyhal_io_heartbeat();
starkDerivePrivateKey(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, &tmpCtx.publicKeyContext.publicKey, &privateKey, 1);
explicit_bzero(&privateKey, sizeof(privateKey));
explicit_bzero(privateKeyData, sizeof(privateKeyData));
io_seproxyhal_io_heartbeat();
#ifndef NO_CONSENT
if (p1 == P1_NON_CONFIRM)
#endif // NO_CONSENT
{
*tx = set_result_get_stark_publicKey();
THROW(0x9000);
}
if (p1 == P1_NON_CONFIRM)
#endif // NO_CONSENT
{
*tx = set_result_get_stark_publicKey();
THROW(0x9000);
}
#ifndef NO_CONSENT
else
{
// prepare for a UI based reply
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, tmpCtx.publicKeyContext.publicKey.W + 1);
ux_flow_init(0, ux_display_stark_public_flow, NULL);
else {
// prepare for a UI based reply
snprintf(strings.tmp.tmp,
sizeof(strings.tmp.tmp),
"0x%.*H",
32,
tmpCtx.publicKeyContext.publicKey.W + 1);
ux_flow_init(0, ux_display_stark_public_flow, NULL);
*flags |= IO_ASYNCH_REPLY;
}
#endif // NO_CONSENT
*flags |= IO_ASYNCH_REPLY;
}
#endif // NO_CONSENT
}
#endif

View File

@@ -1,4 +1,3 @@
#include "shared_context.h"
uint32_t set_result_get_stark_publicKey(void);

View File

@@ -11,5 +11,3 @@ uint32_t set_result_get_stark_publicKey() {
}
#endif

View File

@@ -13,8 +13,7 @@ unsigned int io_seproxyhal_touch_stark_pubkey_ok(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}
#endif

View File

@@ -5,6 +5,7 @@
unsigned int io_seproxyhal_touch_stark_pubkey_ok(const bagl_element_t *e);
// clang-format off
UX_STEP_NOCB(
ux_display_stark_public_flow_1_step,
pnn,
@@ -36,13 +37,12 @@ UX_STEP_CB(
&C_icon_crossmark,
"Reject",
});
// clang-format on
UX_FLOW(ux_display_stark_public_flow,
&ux_display_stark_public_flow_1_step,
&ux_display_stark_public_flow_2_step,
&ux_display_stark_public_flow_3_step,
&ux_display_stark_public_flow_4_step
);
&ux_display_stark_public_flow_1_step,
&ux_display_stark_public_flow_2_step,
&ux_display_stark_public_flow_3_step,
&ux_display_stark_public_flow_4_step);
#endif

View File

@@ -4,56 +4,61 @@
#include "apdu_constants.h"
#include "ui_flow.h"
void handleStarkwareProvideQuantum(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
size_t i = 0;
uint8_t expectedDataSize = 20 + 32;
uint8_t addressZero = 0;
tokenDefinition_t *currentToken = NULL;
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
switch(p1) {
case STARK_QUANTUM_LEGACY:
break;
case STARK_QUANTUM_ETH:
case STARK_QUANTUM_ERC20:
case STARK_QUANTUM_ERC721:
case STARK_QUANTUM_MINTABLE_ERC20:
case STARK_QUANTUM_MINTABLE_ERC721:
expectedDataSize += 32;
break;
default:
THROW(0x6B00);
}
if (dataLength != expectedDataSize) {
THROW(0x6700);
}
if (p1 == STARK_QUANTUM_LEGACY) {
addressZero = allzeroes(dataBuffer, 20);
}
if ((p1 != STARK_QUANTUM_ETH) && !addressZero) {
for(i=0; i<MAX_TOKEN; i++){
currentToken = &tmpCtx.transactionContext.tokens[i];
if (tmpCtx.transactionContext.tokenSet[i] && (memcmp(currentToken->address, dataBuffer, 20) == 0)) {
break;
}
void handleStarkwareProvideQuantum(uint8_t p1,
uint8_t p2,
uint8_t *dataBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
size_t i = 0;
uint8_t expectedDataSize = 20 + 32;
uint8_t addressZero = 0;
tokenDefinition_t *currentToken = NULL;
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
if (i == MAX_TOKEN) {
PRINTF("Associated token not found\n");
THROW(0x6A80);
switch (p1) {
case STARK_QUANTUM_LEGACY:
break;
case STARK_QUANTUM_ETH:
case STARK_QUANTUM_ERC20:
case STARK_QUANTUM_ERC721:
case STARK_QUANTUM_MINTABLE_ERC20:
case STARK_QUANTUM_MINTABLE_ERC721:
expectedDataSize += 32;
break;
default:
THROW(0x6B00);
}
}
else {
i = MAX_TOKEN;
}
memmove(dataContext.tokenContext.quantum, dataBuffer + 20, 32);
if (p1 != STARK_QUANTUM_LEGACY) {
memmove(dataContext.tokenContext.mintingBlob, dataBuffer + 20 + 32, 32);
}
dataContext.tokenContext.quantumIndex = i;
dataContext.tokenContext.quantumType = p1;
quantumSet = true;
THROW(0x9000);
if (dataLength != expectedDataSize) {
THROW(0x6700);
}
if (p1 == STARK_QUANTUM_LEGACY) {
addressZero = allzeroes(dataBuffer, 20);
}
if ((p1 != STARK_QUANTUM_ETH) && !addressZero) {
for (i = 0; i < MAX_TOKEN; i++) {
currentToken = &tmpCtx.transactionContext.tokens[i];
if (tmpCtx.transactionContext.tokenSet[i] &&
(memcmp(currentToken->address, dataBuffer, 20) == 0)) {
break;
}
}
if (i == MAX_TOKEN) {
PRINTF("Associated token not found\n");
THROW(0x6A80);
}
} else {
i = MAX_TOKEN;
}
memmove(dataContext.tokenContext.quantum, dataBuffer + 20, 32);
if (p1 != STARK_QUANTUM_LEGACY) {
memmove(dataContext.tokenContext.mintingBlob, dataBuffer + 20 + 32, 32);
}
dataContext.tokenContext.quantumIndex = i;
dataContext.tokenContext.quantumType = p1;
quantumSet = true;
THROW(0x9000);
}
#endif

View File

@@ -7,208 +7,253 @@
#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 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, unsigned int *tx) {
uint8_t privateKeyData[32];
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);
void handleStarkwareSignMessage(uint8_t p1,
uint8_t p2,
uint8_t *dataBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
uint8_t privateKeyData[32];
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 (!zeroTest && getKnownToken(dataBuffer + 20 + 32 + postOffset + preOffset) == NULL) {
PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer + 20 + 32 + postOffset + preOffset);
THROW(0x6A80);
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
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);
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);
}
}
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);
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);
}
}
else {
ux_flow_init(0, (dataContext.starkContext.conditional ? ux_stark_transfer_conditional_flow :
ux_stark_transfer_flow), NULL);
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);
}
}
*flags |= IO_ASYNCH_REPLY;
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

View File

@@ -9,12 +9,17 @@ unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e) {
uint8_t signature[72];
uint32_t tx = 0;
io_seproxyhal_io_heartbeat();
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, tmpCtx.transactionContext.pathLength, privateKeyData);
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path,
tmpCtx.transactionContext.pathLength,
privateKeyData);
io_seproxyhal_io_heartbeat();
stark_sign(signature, privateKeyData, dataContext.starkContext.w1, dataContext.starkContext.w2,
dataContext.starkContext.w3,
(dataContext.starkContext.conditional ? dataContext.starkContext.w4 : NULL));
G_io_apdu_buffer[0] = 0;
stark_sign(signature,
privateKeyData,
dataContext.starkContext.w1,
dataContext.starkContext.w2,
dataContext.starkContext.w3,
(dataContext.starkContext.conditional ? dataContext.starkContext.w4 : NULL));
G_io_apdu_buffer[0] = 0;
format_signature_out(signature);
tx = 65;
G_io_apdu_buffer[tx++] = 0x90;
@@ -24,7 +29,7 @@ unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}
#endif

View File

@@ -6,20 +6,28 @@
unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e);
void stark_sign_display_master_account() {
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.transferDestination);
snprintf(strings.tmp.tmp,
sizeof(strings.tmp.tmp),
"0x%.*H",
32,
dataContext.starkContext.transferDestination);
}
void stark_sign_display_condition_address() {
strings.tmp.tmp[0] = '0';
strings.tmp.tmp[1] = 'x';
getEthAddressStringFromBinary(dataContext.starkContext.conditionAddress, (uint8_t*)(strings.tmp.tmp + 2), &global_sha3, chainConfig);
strings.tmp.tmp[42] = '\0';
}
void stark_sign_display_condition_fact() {
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.fact);
strings.tmp.tmp[0] = '0';
strings.tmp.tmp[1] = 'x';
getEthAddressStringFromBinary(dataContext.starkContext.conditionAddress,
(uint8_t *) (strings.tmp.tmp + 2),
&global_sha3,
chainConfig);
strings.tmp.tmp[42] = '\0';
}
void stark_sign_display_condition_fact() {
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.fact);
}
// clang-format off
UX_STEP_NOCB(ux_stark_limit_order_1_step,
pnn,
{
@@ -80,19 +88,20 @@ UX_STEP_CB(
&C_icon_crossmark,
"Reject",
});
// clang-format on
UX_FLOW(ux_stark_limit_order_flow,
&ux_stark_limit_order_1_step,
&ux_stark_limit_order_2_step,
&ux_stark_limit_order_3_step,
&ux_stark_limit_order_4_step,
&ux_stark_limit_order_5_step,
&ux_stark_limit_order_6_step,
&ux_stark_limit_order_7_step,
&ux_stark_limit_order_8_step
);
&ux_stark_limit_order_1_step,
&ux_stark_limit_order_2_step,
&ux_stark_limit_order_3_step,
&ux_stark_limit_order_4_step,
&ux_stark_limit_order_5_step,
&ux_stark_limit_order_6_step,
&ux_stark_limit_order_7_step,
&ux_stark_limit_order_8_step);
//////////////////////////////////////////////////////////////////////
// clang-format off
UX_STEP_NOCB(ux_stark_transfer_1_step,
pnn,
{
@@ -194,47 +203,44 @@ UX_STEP_NOCB_INIT(
.title = "Cond. Fact",
.text = strings.tmp.tmp
});
// clang-format on
UX_FLOW(ux_stark_transfer_flow,
&ux_stark_transfer_1_step,
&ux_stark_transfer_2_step,
&ux_stark_transfer_3_step,
&ux_stark_transfer_4_step,
&ux_stark_transfer_5_step,
&ux_stark_transfer_6_step,
&ux_stark_transfer_7_step
);
&ux_stark_transfer_1_step,
&ux_stark_transfer_2_step,
&ux_stark_transfer_3_step,
&ux_stark_transfer_4_step,
&ux_stark_transfer_5_step,
&ux_stark_transfer_6_step,
&ux_stark_transfer_7_step);
UX_FLOW(ux_stark_self_transfer_flow,
&ux_stark_transfer_1_step,
&ux_stark_self_transfer_2_step,
&ux_stark_transfer_3_step,
&ux_stark_transfer_5_step,
&ux_stark_transfer_6_step,
&ux_stark_transfer_7_step
);
&ux_stark_transfer_1_step,
&ux_stark_self_transfer_2_step,
&ux_stark_transfer_3_step,
&ux_stark_transfer_5_step,
&ux_stark_transfer_6_step,
&ux_stark_transfer_7_step);
UX_FLOW(ux_stark_transfer_conditional_flow,
&ux_stark_transfer_1_step,
&ux_stark_conditional_transfer_2_step,
&ux_stark_transfer_3_step,
&ux_stark_conditional_transfer_4_step,
&ux_stark_transfer_5_step,
&ux_stark_conditional_transfer_8_step,
&ux_stark_conditional_transfer_9_step,
&ux_stark_transfer_6_step,
&ux_stark_transfer_7_step
);
&ux_stark_transfer_1_step,
&ux_stark_conditional_transfer_2_step,
&ux_stark_transfer_3_step,
&ux_stark_conditional_transfer_4_step,
&ux_stark_transfer_5_step,
&ux_stark_conditional_transfer_8_step,
&ux_stark_conditional_transfer_9_step,
&ux_stark_transfer_6_step,
&ux_stark_transfer_7_step);
UX_FLOW(ux_stark_self_transfer_conditional_flow,
&ux_stark_transfer_1_step,
&ux_stark_self_conditional_transfer_2_step,
&ux_stark_transfer_3_step,
&ux_stark_transfer_5_step,
&ux_stark_conditional_transfer_8_step,
&ux_stark_conditional_transfer_9_step,
&ux_stark_transfer_6_step,
&ux_stark_transfer_7_step
);
&ux_stark_transfer_1_step,
&ux_stark_self_conditional_transfer_2_step,
&ux_stark_transfer_3_step,
&ux_stark_transfer_5_step,
&ux_stark_conditional_transfer_8_step,
&ux_stark_conditional_transfer_9_step,
&ux_stark_transfer_6_step,
&ux_stark_transfer_7_step);
#endif

View File

@@ -6,49 +6,53 @@
#include "ui_flow.h"
#include "ui_callbacks.h"
void handleStarkwareUnsafeSign(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, unsigned int *tx) {
uint32_t i;
uint8_t privateKeyData[32];
cx_ecfp_public_key_t publicKey;
cx_ecfp_private_key_t privateKey;
uint8_t bip32PathLength = *(dataBuffer);
uint8_t offset = 1;
// Initial checks
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
if ((bip32PathLength < 0x01) ||
(bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
if ((p1 != 0) || (p2 != 0)) {
THROW(0x6B00);
}
void handleStarkwareUnsafeSign(uint8_t p1,
uint8_t p2,
uint8_t *dataBuffer,
uint16_t dataLength,
unsigned int *flags,
unsigned int *tx) {
uint32_t i;
uint8_t privateKeyData[32];
cx_ecfp_public_key_t publicKey;
cx_ecfp_private_key_t privateKey;
uint8_t bip32PathLength = *(dataBuffer);
uint8_t offset = 1;
// Initial checks
if (appState != APP_STATE_IDLE) {
reset_app_context();
}
if ((bip32PathLength < 0x01) || (bip32PathLength > MAX_BIP32_PATH)) {
PRINTF("Invalid path\n");
THROW(0x6a80);
}
if ((p1 != 0) || (p2 != 0)) {
THROW(0x6B00);
}
if (dataLength != 32 + 4 * bip32PathLength + 1) {
THROW(0x6700);
}
if (dataLength != 32 + 4 * bip32PathLength + 1) {
THROW(0x6700);
}
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;
}
memmove(dataContext.starkContext.w2, dataBuffer + offset, 32);
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();
memmove(dataContext.starkContext.w1, publicKey.W + 1, 32);
ux_flow_init(0, ux_stark_unsafe_sign_flow, NULL);
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;
}
memmove(dataContext.starkContext.w2, dataBuffer + offset, 32);
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();
memmove(dataContext.starkContext.w1, publicKey.W + 1, 32);
ux_flow_init(0, ux_stark_unsafe_sign_flow, NULL);
*flags |= IO_ASYNCH_REPLY;
*flags |= IO_ASYNCH_REPLY;
}
#endif

View File

@@ -11,11 +11,19 @@ unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(const bagl_element_t *e) {
unsigned int info = 0;
uint32_t tx = 0;
io_seproxyhal_io_heartbeat();
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path, tmpCtx.transactionContext.pathLength, privateKeyData);
starkDerivePrivateKey(tmpCtx.transactionContext.bip32Path,
tmpCtx.transactionContext.pathLength,
privateKeyData);
io_seproxyhal_io_heartbeat();
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
cx_ecdsa_sign(&privateKey, CX_RND_RFC6979 | CX_LAST, CX_SHA256,
dataContext.starkContext.w2, sizeof(dataContext.starkContext.w2), signature, sizeof(signature), &info);
cx_ecdsa_sign(&privateKey,
CX_RND_RFC6979 | CX_LAST,
CX_SHA256,
dataContext.starkContext.w2,
sizeof(dataContext.starkContext.w2),
signature,
sizeof(signature),
&info);
G_io_apdu_buffer[0] = 0;
format_signature_out(signature);
tx = 65;
@@ -26,7 +34,7 @@ unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(const bagl_element_t *e) {
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
// Display back the original UX
ui_idle();
return 0; // do not redraw the widget
return 0; // do not redraw the widget
}
#endif

View File

@@ -6,13 +6,14 @@
unsigned int io_seproxyhal_touch_stark_unsafe_sign_ok(const bagl_element_t *e);
void stark_unsafe_sign_display_account() {
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w1);
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w1);
}
void stark_unsafe_sign_display_hash() {
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w2);
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataContext.starkContext.w2);
}
// clang-format off
UX_STEP_NOCB(ux_stark_unsafe_sign_1_step,
pnn,
{
@@ -57,13 +58,13 @@ UX_STEP_CB(
&C_icon_crossmark,
"Reject",
});
// clang-format on
UX_FLOW(ux_stark_unsafe_sign_flow,
&ux_stark_unsafe_sign_1_step,
&ux_stark_unsafe_sign_2_step,
&ux_stark_unsafe_sign_3_step,
&ux_stark_unsafe_sign_4_step,
&ux_stark_unsafe_sign_5_step
);
&ux_stark_unsafe_sign_1_step,
&ux_stark_unsafe_sign_2_step,
&ux_stark_unsafe_sign_3_step,
&ux_stark_unsafe_sign_4_step,
&ux_stark_unsafe_sign_5_step);
#endif