246 lines
9.3 KiB
C
246 lines
9.3 KiB
C
#ifdef HAVE_STARKWARE
|
|
|
|
#include "stark_crypto.h"
|
|
#include "shared_context.h"
|
|
#include "ethUtils.h"
|
|
#include "uint256.h"
|
|
|
|
#include "os_io_seproxyhal.h"
|
|
|
|
#define SIGNATURE_MAX_LEN (72)
|
|
|
|
static const ECPoint PEDERSEN_SHIFT[] = {{
|
|
0x04,
|
|
|
|
0x04, 0x9e, 0xe3, 0xeb, 0xa8, 0xc1, 0x60, 0x07, 0x00, 0xee, 0x1b, 0x87, 0xeb, 0x59, 0x9f, 0x16,
|
|
0x71, 0x6b, 0x0b, 0x10, 0x22, 0x94, 0x77, 0x33, 0x55, 0x1f, 0xde, 0x40, 0x50, 0xca, 0x68, 0x04,
|
|
|
|
0x03, 0xca, 0x0c, 0xfe, 0x4b, 0x3b, 0xc6, 0xdd, 0xf3, 0x46, 0xd4, 0x9d, 0x06, 0xea, 0x0e, 0xd3,
|
|
0x4e, 0x62, 0x10, 0x62, 0xc0, 0xe0, 0x56, 0xc1, 0xd0, 0x40, 0x5d, 0x26, 0x6e, 0x10, 0x26, 0x8a,
|
|
}};
|
|
|
|
static const ECPoint PEDERSEN_POINTS[4] = {
|
|
{
|
|
0x04,
|
|
|
|
0x02, 0x34, 0x28, 0x7d, 0xcb, 0xaf, 0xfe, 0x7f, 0x96, 0x9c, 0x74,
|
|
0x86, 0x55, 0xfc, 0xa9, 0xe5, 0x8f, 0xa8, 0x12, 0x0b, 0x6d, 0x56,
|
|
0xeb, 0x0c, 0x10, 0x80, 0xd1, 0x79, 0x57, 0xeb, 0xe4, 0x7b,
|
|
|
|
0x03, 0xb0, 0x56, 0xf1, 0x00, 0xf9, 0x6f, 0xb2, 0x1e, 0x88, 0x95,
|
|
0x27, 0xd4, 0x1f, 0x4e, 0x39, 0x94, 0x01, 0x35, 0xdd, 0x7a, 0x6c,
|
|
0x94, 0xcc, 0x6e, 0xd0, 0x26, 0x8e, 0xe8, 0x9e, 0x56, 0x15,
|
|
},
|
|
{
|
|
0x04,
|
|
|
|
0x04, 0xfa, 0x56, 0xf3, 0x76, 0xc8, 0x3d, 0xb3, 0x3f, 0x9d, 0xab,
|
|
0x26, 0x56, 0x55, 0x8f, 0x33, 0x99, 0x09, 0x9e, 0xc1, 0xde, 0x5e,
|
|
0x30, 0x18, 0xb7, 0xa6, 0x93, 0x2d, 0xba, 0x8a, 0xa3, 0x78,
|
|
|
|
0x03, 0xfa, 0x09, 0x84, 0xc9, 0x31, 0xc9, 0xe3, 0x81, 0x13, 0xe0,
|
|
0xc0, 0xe4, 0x7e, 0x44, 0x01, 0x56, 0x27, 0x61, 0xf9, 0x2a, 0x7a,
|
|
0x23, 0xb4, 0x51, 0x68, 0xf4, 0xe8, 0x0f, 0xf5, 0xb5, 0x4d,
|
|
},
|
|
{
|
|
0x04,
|
|
|
|
0x04, 0xba, 0x4c, 0xc1, 0x66, 0xbe, 0x8d, 0xec, 0x76, 0x49, 0x10,
|
|
0xf7, 0x5b, 0x45, 0xf7, 0x4b, 0x40, 0xc6, 0x90, 0xc7, 0x47, 0x09,
|
|
0xe9, 0x0f, 0x3a, 0xa3, 0x72, 0xf0, 0xbd, 0x2d, 0x69, 0x97,
|
|
|
|
0x00, 0x40, 0x30, 0x1c, 0xf5, 0xc1, 0x75, 0x1f, 0x4b, 0x97, 0x1e,
|
|
0x46, 0xc4, 0xed, 0xe8, 0x5f, 0xca, 0xc5, 0xc5, 0x9a, 0x5c, 0xe5,
|
|
0xae, 0x7c, 0x48, 0x15, 0x1f, 0x27, 0xb2, 0x4b, 0x21, 0x9c,
|
|
},
|
|
{
|
|
0x04,
|
|
|
|
0x05, 0x43, 0x02, 0xdc, 0xb0, 0xe6, 0xcc, 0x1c, 0x6e, 0x44, 0xcc,
|
|
0xa8, 0xf6, 0x1a, 0x63, 0xbb, 0x2c, 0xa6, 0x50, 0x48, 0xd5, 0x3f,
|
|
0xb3, 0x25, 0xd3, 0x6f, 0xf1, 0x2c, 0x49, 0xa5, 0x82, 0x02,
|
|
|
|
0x01, 0xb7, 0x7b, 0x3e, 0x37, 0xd1, 0x35, 0x04, 0xb3, 0x48, 0x04,
|
|
0x62, 0x68, 0xd8, 0xae, 0x25, 0xce, 0x98, 0xad, 0x78, 0x3c, 0x25,
|
|
0x56, 0x1a, 0x87, 0x9d, 0xcc, 0x77, 0xe9, 0x9c, 0x24, 0x26,
|
|
}};
|
|
|
|
void accum_ec_mul(ECPoint *hash, uint8_t *buf, int len, int pedersen_idx) {
|
|
ECPoint tmp;
|
|
if (!allzeroes(buf, len)) {
|
|
uint8_t pad[32];
|
|
memcpy(tmp, PEDERSEN_POINTS[pedersen_idx], sizeof(ECPoint));
|
|
io_seproxyhal_io_heartbeat();
|
|
memset(pad, 0, sizeof(pad));
|
|
memmove(pad + 32 - len, buf, len);
|
|
cx_ecfp_scalar_mult(CX_CURVE_Stark256, tmp, sizeof(ECPoint), pad, sizeof(pad));
|
|
io_seproxyhal_io_heartbeat();
|
|
cx_ecfp_add_point(CX_CURVE_Stark256, *hash, *hash, tmp, sizeof(ECPoint));
|
|
}
|
|
}
|
|
|
|
void pedersen(FieldElement res, /* out */
|
|
FieldElement a,
|
|
FieldElement b) {
|
|
ECPoint hash;
|
|
|
|
memcpy(hash, PEDERSEN_SHIFT, sizeof(hash));
|
|
|
|
accum_ec_mul(&hash, a, 1, 1);
|
|
accum_ec_mul(&hash, a + 1, FIELD_ELEMENT_SIZE - 1, 0);
|
|
accum_ec_mul(&hash, b, 1, 3);
|
|
accum_ec_mul(&hash, b + 1, FIELD_ELEMENT_SIZE - 1, 2);
|
|
|
|
memcpy(res, hash + 1, FIELD_ELEMENT_SIZE);
|
|
}
|
|
|
|
void shift_stark_hash(FieldElement hash) {
|
|
uint256_t hash256, final_hash256;
|
|
readu256BE(hash, &hash256);
|
|
uint32_t bits_count = bits256(&hash256);
|
|
if (bits_count < 248) {
|
|
return;
|
|
} else if (bits_count >= 248 && bits_count % 8 >= 1 && bits_count % 8 <= 4) {
|
|
shiftl256(&hash256, 4, &final_hash256);
|
|
write_u64_be(hash, UPPER(UPPER_P((&final_hash256))));
|
|
write_u64_be(hash + 8, LOWER(UPPER_P((&final_hash256))));
|
|
write_u64_be(hash + 16, UPPER(LOWER_P((&final_hash256))));
|
|
write_u64_be(hash + 24, LOWER(LOWER_P((&final_hash256))));
|
|
return;
|
|
} else {
|
|
THROW(0x6A80);
|
|
}
|
|
}
|
|
|
|
int stark_sign(uint8_t *signature, /* out */
|
|
uint8_t *privateKeyData,
|
|
FieldElement token1,
|
|
FieldElement token2,
|
|
FieldElement msg,
|
|
FieldElement condition) {
|
|
unsigned int info = 0;
|
|
FieldElement hash;
|
|
cx_ecfp_private_key_t privateKey;
|
|
PRINTF("Stark sign msg w1 %.*H\n", 32, token1);
|
|
PRINTF("Stark sign msg w2 %.*H\n", 32, token2);
|
|
PRINTF("Stark sign w3 %.*H\n", 32, msg);
|
|
if (condition != NULL) {
|
|
PRINTF("Stark sign w4 %.*H\n", 32, condition);
|
|
}
|
|
pedersen(hash, token1, token2);
|
|
PRINTF("Pedersen hash 1 %.*H\n", 32, hash);
|
|
if (condition != NULL) {
|
|
pedersen(hash, hash, condition);
|
|
PRINTF("Pedersen hash condition %.*H\n", 32, hash);
|
|
}
|
|
pedersen(hash, hash, msg);
|
|
PRINTF("Pedersen hash 2 %.*H\n", 32, hash);
|
|
shift_stark_hash(hash);
|
|
cx_ecfp_init_private_key(CX_CURVE_Stark256, privateKeyData, 32, &privateKey);
|
|
io_seproxyhal_io_heartbeat();
|
|
int signatureLength = cx_ecdsa_sign(&privateKey,
|
|
CX_RND_RFC6979 | CX_LAST,
|
|
CX_SHA256,
|
|
hash,
|
|
sizeof(hash),
|
|
signature,
|
|
SIGNATURE_MAX_LEN,
|
|
&info);
|
|
PRINTF("Stark signature %.*H\n", signatureLength, signature);
|
|
return signatureLength;
|
|
}
|
|
|
|
// ERC20Token(address)
|
|
static const uint8_t ERC20_SELECTOR[] = {0xf4, 0x72, 0x61, 0xb0};
|
|
// ETH()
|
|
static const uint8_t ETH_SELECTOR[] = {0x83, 0x22, 0xff, 0xf2};
|
|
// ERC721Token(address, uint256)
|
|
static const uint8_t ERC721_SELECTOR[] = {0x02, 0x57, 0x17, 0x92};
|
|
// MintableERC20Token(address)
|
|
static const uint8_t MINTABLE_ERC20_SELECTOR[] = {0x68, 0x64, 0x6e, 0x2d};
|
|
// MintableERC721Token(address,uint256)
|
|
static const uint8_t MINTABLE_ERC721_SELECTOR[] = {0xb8, 0xb8, 0x66, 0x72};
|
|
static const char NFT_ASSET_ID_PREFIX[] = {'N', 'F', 'T', ':', 0};
|
|
static const char MINTABLE_ASSET_ID_PREFIX[] = {'M', 'I', 'N', 'T', 'A', 'B', 'L', 'E', ':', 0};
|
|
|
|
void compute_token_id(cx_sha3_t *sha3,
|
|
uint8_t *contractAddress,
|
|
uint8_t quantumType,
|
|
uint8_t *quantum,
|
|
uint8_t *mintingBlob,
|
|
bool assetTypeOnly,
|
|
uint8_t *output) {
|
|
uint8_t tmp[36];
|
|
cx_keccak_init(sha3, 256);
|
|
if ((contractAddress != NULL) && (!allzeroes(contractAddress, 20))) {
|
|
const uint8_t *selector = NULL;
|
|
switch (quantumType) {
|
|
case STARK_QUANTUM_ERC20:
|
|
case STARK_QUANTUM_LEGACY:
|
|
selector = ERC20_SELECTOR;
|
|
break;
|
|
case STARK_QUANTUM_ERC721:
|
|
selector = ERC721_SELECTOR;
|
|
break;
|
|
case STARK_QUANTUM_MINTABLE_ERC20:
|
|
selector = MINTABLE_ERC20_SELECTOR;
|
|
break;
|
|
case STARK_QUANTUM_MINTABLE_ERC721:
|
|
selector = MINTABLE_ERC721_SELECTOR;
|
|
break;
|
|
default:
|
|
PRINTF("Unsupported quantum type %d\n", quantumType);
|
|
return;
|
|
}
|
|
PRINTF("compute_token_id for %.*H\n", 20, contractAddress);
|
|
memset(tmp, 0, sizeof(tmp));
|
|
memmove(tmp, selector, 4);
|
|
memmove(tmp + 16, contractAddress, 20);
|
|
cx_hash((cx_hash_t *) sha3, 0, tmp, sizeof(tmp), NULL, 0);
|
|
} else {
|
|
PRINTF("compute_token_id for ETH\n");
|
|
cx_hash((cx_hash_t *) sha3, 0, ETH_SELECTOR, sizeof(ETH_SELECTOR), NULL, 0);
|
|
}
|
|
if ((quantumType == STARK_QUANTUM_ERC721) || (quantumType == STARK_QUANTUM_MINTABLE_ERC721)) {
|
|
memset(tmp, 0, 32);
|
|
tmp[31] = 1;
|
|
PRINTF("compute_token_id quantum %.*H\n", 32, tmp);
|
|
cx_hash((cx_hash_t *) sha3, CX_LAST, tmp, 32, output, 32);
|
|
} else {
|
|
PRINTF("compute_token_id quantum %.*H\n", 32, quantum);
|
|
cx_hash((cx_hash_t *) sha3, CX_LAST, quantum, 32, output, 32);
|
|
}
|
|
if (!assetTypeOnly &&
|
|
((quantumType != STARK_QUANTUM_LEGACY) && (quantumType != STARK_QUANTUM_ETH) &&
|
|
(quantumType != STARK_QUANTUM_ERC20))) {
|
|
const char *prefix = NULL;
|
|
output[0] &= 0x03;
|
|
cx_keccak_init(sha3, 256);
|
|
switch (quantumType) {
|
|
case STARK_QUANTUM_ERC721:
|
|
prefix = NFT_ASSET_ID_PREFIX;
|
|
break;
|
|
case STARK_QUANTUM_MINTABLE_ERC20:
|
|
case STARK_QUANTUM_MINTABLE_ERC721:
|
|
prefix = MINTABLE_ASSET_ID_PREFIX;
|
|
break;
|
|
default:
|
|
PRINTF("Unsupported non default quantum type %d\n", quantumType);
|
|
return;
|
|
}
|
|
cx_hash((cx_hash_t *) sha3, 0, (const uint8_t *) prefix, strlen(prefix), NULL, 0);
|
|
cx_hash((cx_hash_t *) sha3, 0, output, 32, NULL, 0);
|
|
cx_hash((cx_hash_t *) sha3, CX_LAST, mintingBlob, 32, output, 32);
|
|
}
|
|
if (!assetTypeOnly && ((quantumType == STARK_QUANTUM_MINTABLE_ERC20) ||
|
|
(quantumType == STARK_QUANTUM_MINTABLE_ERC721))) {
|
|
output[0] = 0x04;
|
|
output[1] = 0x00;
|
|
} else {
|
|
output[0] &= 0x03;
|
|
}
|
|
PRINTF("compute_token_id computed token %.*H\n", 32, output);
|
|
}
|
|
|
|
#endif // HAVE_STARK
|