Merge Starkware branch
This commit is contained in:
140
src_features/stark_sign/cmd_stark_sign.c
Normal file
140
src_features/stark_sign/cmd_stark_sign.c
Normal file
@@ -0,0 +1,140 @@
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
#include "shared_context.h"
|
||||
#include "apdu_constants.h"
|
||||
#include "stark_utils.h"
|
||||
#ifdef TARGET_BLUE
|
||||
#include "ui_blue.h"
|
||||
#endif
|
||||
#ifdef HAVE_UX_FLOW
|
||||
#include "ui_flow.h"
|
||||
#endif
|
||||
#include "poorstream.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
#define U8BE(buf, off) (uint64_t)((((uint64_t)U4BE(buf, off)) << 32) | (((uint64_t)U4BE(buf, off + 4)) & 0xFFFFFFFF))
|
||||
#define TMP_OFFSET 140
|
||||
|
||||
void handleStarkwareSignMessage(uint8_t p1, uint8_t p2, uint8_t *dataBuffer, uint16_t dataLength, unsigned int *flags, 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;
|
||||
// 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:
|
||||
if (dataLength != (20 + 32 + 20 + 32 + 4 + 4 + 8 + 8 + 4 + 4 + 1 + 4 * bip32PathLength)) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
break;
|
||||
case P1_STARK_TRANSFER:
|
||||
if (dataLength != (20 + 32 + 32 + 4 + 4 + 8 + 4 + 4 + 1 + 4 * bip32PathLength)) {
|
||||
THROW(0x6700);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
THROW(0x6B00);
|
||||
}
|
||||
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
|
||||
os_memmove(dataBuffer, dataBuffer + offset, dataLength - offset);
|
||||
// Fail immediately if the contract is unknown
|
||||
if (!allzeroes(dataBuffer, 20) && getKnownToken(dataBuffer) == NULL) {
|
||||
PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer);
|
||||
THROW(0x6A80);
|
||||
}
|
||||
if ((p1 == P1_STARK_ORDER) && (!allzeroes(dataBuffer + 20 + 32, 20) && getKnownToken(dataBuffer + 20 + 32) == NULL)) {
|
||||
PRINTF("stark - cannot process unknown token %.*H", 20, dataBuffer + 20 + 32);
|
||||
THROW(0x6A80);
|
||||
}
|
||||
// Prepare the Stark parameters
|
||||
io_seproxyhal_io_heartbeat();
|
||||
compute_token_id(&sha3, dataBuffer, dataBuffer + 20, dataContext.starkContext.w1);
|
||||
if (p1 == P1_STARK_ORDER) {
|
||||
io_seproxyhal_io_heartbeat();
|
||||
compute_token_id(&sha3, dataBuffer + 20 + 32, dataBuffer + 20 + 32 + 20, dataContext.starkContext.w2);
|
||||
offset = 20 + 32 + 20 + 32;
|
||||
}
|
||||
else {
|
||||
os_memmove(dataContext.starkContext.w2, dataBuffer + 20 + 32, 32);
|
||||
offset = 20 + 32 + 32;
|
||||
}
|
||||
poorstream_init(&bitstream, dataContext.starkContext.w3);
|
||||
poorstream_write_bits(&bitstream, 0, 11); // padding
|
||||
poorstream_write_bits(&bitstream, (p1 == P1_STARK_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 (p1 == P1_STARK_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);
|
||||
// Prepare the UI
|
||||
if (p1 == P1_STARK_ORDER) {
|
||||
io_seproxyhal_io_heartbeat();
|
||||
// amount to sell
|
||||
stark_get_amount_string(dataBuffer, dataBuffer + 20, dataBuffer + 20 + 32 + 20 + 32 + 4 + 4, (char*)(dataBuffer + TMP_OFFSET), strings.common.fullAmount);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
// amount to buy
|
||||
stark_get_amount_string(dataBuffer + 20 + 32, dataBuffer + 20 + 32 + 20, dataBuffer + 20 + 32 + 20 + 32 + 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 + 20 + 32));
|
||||
}
|
||||
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);
|
||||
os_memset(&privateKey, 0, sizeof(privateKey));
|
||||
os_memset(privateKeyData, 0, sizeof(privateKeyData));
|
||||
io_seproxyhal_io_heartbeat();
|
||||
selfTransfer = (os_memcmp(publicKey.W + 1, dataBuffer + 20 + 32, 32) == 0);
|
||||
PRINTF("self transfer %d\n", selfTransfer);
|
||||
io_seproxyhal_io_heartbeat();
|
||||
// amount to transfer
|
||||
stark_get_amount_string(dataBuffer, dataBuffer + 20, dataBuffer + 20 + 32 + 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 + 32 + 4));
|
||||
if (!selfTransfer) {
|
||||
snprintf(strings.tmp.tmp, sizeof(strings.tmp.tmp), "0x%.*H", 32, dataBuffer + 20 + 32);
|
||||
}
|
||||
}
|
||||
ux_flow_init(0, p1 == P1_STARK_ORDER ? ux_stark_limit_order_flow : selfTransfer ?
|
||||
ux_stark_self_transfer_flow : ux_stark_transfer_flow, NULL);
|
||||
|
||||
*flags |= IO_ASYNCH_REPLY;
|
||||
}
|
||||
|
||||
#endif
|
||||
28
src_features/stark_sign/ui_common_stark_sign.c
Normal file
28
src_features/stark_sign/ui_common_stark_sign.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
#include "shared_context.h"
|
||||
#include "stark_utils.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e) {
|
||||
uint8_t privateKeyData[32];
|
||||
uint8_t signature[72];
|
||||
uint32_t tx = 0;
|
||||
io_seproxyhal_io_heartbeat();
|
||||
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);
|
||||
G_io_apdu_buffer[0] = 0;
|
||||
format_signature_out(signature);
|
||||
tx = 65;
|
||||
G_io_apdu_buffer[tx++] = 0x90;
|
||||
G_io_apdu_buffer[tx++] = 0x00;
|
||||
reset_app_context();
|
||||
// Send back the response, do not restart the event loop
|
||||
io_exchange(CHANNEL_APDU | IO_RETURN_AFTER_TX, tx);
|
||||
// Display back the original UX
|
||||
ui_idle();
|
||||
return 0; // do not redraw the widget
|
||||
}
|
||||
|
||||
#endif
|
||||
165
src_features/stark_sign/ui_flow_stark_sign.c
Normal file
165
src_features/stark_sign/ui_flow_stark_sign.c
Normal file
@@ -0,0 +1,165 @@
|
||||
#ifdef HAVE_STARKWARE
|
||||
|
||||
#include "shared_context.h"
|
||||
#include "ui_callbacks.h"
|
||||
|
||||
unsigned int io_seproxyhal_touch_stark_ok(const bagl_element_t *e);
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_limit_order_1_step,
|
||||
pnn,
|
||||
{
|
||||
&C_icon_eye,
|
||||
"Review",
|
||||
"transaction",
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_limit_order_2_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Limit",
|
||||
.text = "Order"
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_limit_order_3_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Trading",
|
||||
.text = "Pair"
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_limit_order_4_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Sell",
|
||||
.text = strings.common.fullAmount
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_limit_order_5_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Buy",
|
||||
.text = strings.common.maxFee
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_limit_order_6_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Token Accont",
|
||||
.text = strings.common.fullAddress
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_VALID(
|
||||
ux_stark_limit_order_7_step,
|
||||
pbb,
|
||||
io_seproxyhal_touch_stark_ok(NULL),
|
||||
{
|
||||
&C_icon_validate_14,
|
||||
"Accept",
|
||||
"and send",
|
||||
});
|
||||
UX_FLOW_DEF_VALID(
|
||||
ux_stark_limit_order_8_step,
|
||||
pb,
|
||||
io_seproxyhal_touch_tx_cancel(NULL),
|
||||
{
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
|
||||
const ux_flow_step_t * const 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,
|
||||
FLOW_END_STEP,
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
UX_FLOW_DEF_NOCB(ux_stark_transfer_1_step,
|
||||
pnn,
|
||||
{
|
||||
&C_icon_eye,
|
||||
"Review",
|
||||
"transaction",
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_transfer_2_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Transfer",
|
||||
.text = " "
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_self_transfer_2_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Self",
|
||||
.text = "Transfer"
|
||||
});
|
||||
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_transfer_3_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Amount",
|
||||
.text = tmpContent.tmp
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_transfer_4_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Master Account",
|
||||
.text = strings.tmp.tmp
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_NOCB(ux_stark_transfer_5_step,
|
||||
bnnn_paging,
|
||||
{
|
||||
.title = "Token Accont",
|
||||
.text = strings.tmp.tmp2
|
||||
});
|
||||
|
||||
UX_FLOW_DEF_VALID(
|
||||
ux_stark_transfer_6_step,
|
||||
pbb,
|
||||
io_seproxyhal_touch_stark_ok(NULL),
|
||||
{
|
||||
&C_icon_validate_14,
|
||||
"Accept",
|
||||
"and send",
|
||||
});
|
||||
UX_FLOW_DEF_VALID(
|
||||
ux_stark_transfer_7_step,
|
||||
pb,
|
||||
io_seproxyhal_touch_tx_cancel(NULL),
|
||||
{
|
||||
&C_icon_crossmark,
|
||||
"Reject",
|
||||
});
|
||||
|
||||
const ux_flow_step_t * const 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,
|
||||
FLOW_END_STEP,
|
||||
};
|
||||
|
||||
const ux_flow_step_t * const 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,
|
||||
FLOW_END_STEP,
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user