Skip to content

Commit

Permalink
added some abstraction for the used protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
shufps committed May 3, 2022
1 parent c38c771 commit 3dc24e5
Show file tree
Hide file tree
Showing 17 changed files with 578 additions and 93 deletions.
2 changes: 1 addition & 1 deletion fuzz/fuzztest.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
API_CTX api = {0};
memcpy(api.data.buffer, Data, API_BUFFER_SIZE_BYTES);
// api.essence.has_remainder = 1;
essence_parse_and_validate(&api);
essence_parse_and_validate_chrysalis(&api);
}
return 0;
}
42 changes: 19 additions & 23 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "os.h"
#include "ui/ui.h"

#include "abstraction.h"

#include "iota/constants.h"
#include "iota/essence.h"
#include "iota/blindsigning.h"
Expand Down Expand Up @@ -33,38 +35,42 @@ void api_initialize(APP_MODE_TYPE app_mode)
api.bip32_signing_path[0] = 0x8000002c;

switch (app_mode) {
case APP_MODE_IOTA:
case APP_MODE_IOTA_CHRYSALIS:
// iota
api.bip32_path[BIP32_COIN_INDEX] = COIN_IOTA;
api.bip32_signing_path[BIP32_COIN_INDEX] = COIN_IOTA;
api.bip32_path[BIP32_COIN_INDEX] = BIP32_COIN_IOTA;
api.bip32_signing_path[BIP32_COIN_INDEX] = BIP32_COIN_IOTA;
api.protocol = PROTOCOL_CHRYSALIS;
api.coin = COIN_IOTA;
break;
case APP_MODE_IOTA_STARDUST:
// iota
api.bip32_path[BIP32_COIN_INDEX] = COIN_IOTA;
api.bip32_signing_path[BIP32_COIN_INDEX] = COIN_IOTA;
api.protocol = PROTOCOL_CHRYSALIS;
api.bip32_path[BIP32_COIN_INDEX] = BIP32_COIN_IOTA;
api.bip32_signing_path[BIP32_COIN_INDEX] = BIP32_COIN_IOTA;
api.protocol = PROTOCOL_STARDUST;
api.coin = COIN_IOTA;
break;
case APP_MODE_CLAIM_SHIMMER:
// primary shimmer
api.bip32_path[BIP32_COIN_INDEX] = COIN_SHIMMER;
api.bip32_path[BIP32_COIN_INDEX] = BIP32_COIN_SHIMMER;
// bip path for claiming SMR from IOTA addresses is different
api.bip32_signing_path[BIP32_COIN_INDEX] = COIN_IOTA;
api.bip32_signing_path[BIP32_COIN_INDEX] = BIP32_COIN_IOTA;
api.protocol = PROTOCOL_STARDUST;
api.coin = COIN_SHIMMER;
break;
case APP_MODE_SHIMMER:
// shimmer
api.bip32_path[BIP32_COIN_INDEX] = COIN_SHIMMER;
api.bip32_signing_path[BIP32_COIN_INDEX] = COIN_SHIMMER;
api.bip32_path[BIP32_COIN_INDEX] = BIP32_COIN_SHIMMER;
api.bip32_signing_path[BIP32_COIN_INDEX] = BIP32_COIN_SHIMMER;
api.protocol = PROTOCOL_STARDUST;
api.coin = COIN_SHIMMER;
break;
default:
THROW(SW_ACCOUNT_NOT_VALID);
}
#ifdef APP_DEBUG
// overwrite paths if in debug mode
api.bip32_path[BIP32_COIN_INDEX] = COIN_TESTNET;
api.bip32_signing_path[BIP32_COIN_INDEX] = COIN_TESTNET;
api.bip32_path[BIP32_COIN_INDEX] = BIP32_COIN_TESTNET;
api.bip32_signing_path[BIP32_COIN_INDEX] = BIP32_COIN_TESTNET;
#endif

api.app_mode = app_mode;
Expand Down Expand Up @@ -189,7 +195,7 @@ uint32_t api_get_app_config(uint8_t is_locked)
uint32_t api_reset()
{
// also resets the account index
api_initialize(APP_MODE_IOTA);
api_initialize(APP_MODE_IOTA_CHRYSALIS);

ui_reset();

Expand Down Expand Up @@ -348,17 +354,7 @@ uint32_t api_generate_address(uint8_t show_on_screen, const uint8_t *data,
return 0;
}

// use api buffer and essence to show new address on the screen
// buffer is free after index 32
// writing to the buffer from external is not allowed, so data
// can't be changed after the flow is started
SIG_LOCKED_SINGLE_OUTPUT *tmp =
(SIG_LOCKED_SINGLE_OUTPUT *)&api.data.buffer[64];
memcpy(&tmp->address_type, api.data.buffer,
ADDRESS_WITH_TYPE_SIZE_BYTES);

api.essence.outputs_count = 1;
api.essence.outputs = tmp;
api.essence.remainder_bip32.bip32_index = req.bip32_index;
api.essence.remainder_bip32.bip32_change = req.bip32_change;
api.essence.remainder_index = 0;
Expand Down
57 changes: 54 additions & 3 deletions src/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,22 @@ typedef enum {
} DATA_TYPE;

typedef enum {
APP_MODE_IOTA = 0,
APP_MODE_IOTA_CHRYSALIS = 0,
APP_MODE_IOTA_STARDUST = 1,
APP_MODE_CLAIM_SHIMMER = 2,
APP_MODE_SHIMMER = 3
} APP_MODE_TYPE;

typedef enum {
PROTOCOL_CHRYSALIS = 0,
PROTOCOL_STARDUST = 0
PROTOCOL_STARDUST = 1
} PROTOCOL_TYPE;

typedef enum {
COIN_IOTA = 0,
COIN_SHIMMER = 1
} COIN_TYPE;

typedef IO_STRUCT
{
uint8_t input_type;
Expand All @@ -43,13 +48,56 @@ UTXO_INPUT;

typedef IO_STRUCT
{
// 0 enforced in validation
uint8_t output_type;

// 0 enorced in validation
uint8_t address_type;

uint8_t address[ADDRESS_SIZE_BYTES];

uint64_t amount;
}
SIG_LOCKED_SINGLE_OUTPUT;

typedef IO_STRUCT
{
// 3 enforced in validation
uint8_t output_type;

uint64_t amount;

// 0 enforced in validation
uint8_t native_tokens_count;

// "none" enforced in validation
// NATIVE_TOKENS native_tokens

// 1 enforced in validation
uint8_t unlock_conditions_count;

// 0 enforced in validation
// (Address Unlock Condition)
uint8_t unlock_condition_type;

// 0 enforced in validation
// (Ed25519 Address)
uint8_t address_type;

uint8_t pubkey_hash[ADDRESS_SIZE_BYTES];

// 0 enforced in validation
uint8_t blocks_count;

// "none" enforced in validation
// BLOCKS blocks;
}
BASIC_OUTPUT;





// used for blindisning
typedef IO_STRUCT
{
Expand Down Expand Up @@ -142,7 +190,7 @@ typedef struct {

// pointer to outputs
// don't use this directly because data is unaligned to save space
SIG_LOCKED_SINGLE_OUTPUT *outputs;
uint8_t *outputs;

// pointer to BIP32 array for input addresses
// don't use this directly because data is unaligned to save space
Expand Down Expand Up @@ -186,6 +234,9 @@ typedef struct {
// protocol version
PROTOCOL_TYPE protocol;

// coin type
COIN_TYPE coin;

// buffer for api
API_DATA data;

Expand Down
110 changes: 110 additions & 0 deletions src/iota/abstraction.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// methods that abstract from the used protocol

#include <stdbool.h>
#include <stdint.h>
#include <string.h>

#include "os.h"

#include "essence.h"
#include "abstraction.h"

#include "api.h"
#include "iota_io.h"
#include "iota/address.h"

// gcc doesn't know this and ledger's SDK cannot be compiled with Werror!
//#pragma GCC diagnostic error "-Werror"
#pragma GCC diagnostic error "-Wpedantic"
#pragma GCC diagnostic error "-Wall"
#pragma GCC diagnostic error "-Wextra"
#pragma GCC diagnostic error "-Wmissing-prototypes"

extern API_CTX api;


uint8_t *get_output_address(const API_CTX *api, uint8_t index)
{
MUST(index < api->essence.outputs_count);

uint8_t *ret = 0;

switch (api->protocol) {
case PROTOCOL_STARDUST: {
BASIC_OUTPUT *tmp = (BASIC_OUTPUT *)api->essence.outputs;
ret = &tmp[index].address_type;
}
case PROTOCOL_CHRYSALIS: {
SIG_LOCKED_SINGLE_OUTPUT *tmp =
(SIG_LOCKED_SINGLE_OUTPUT *)api->essence.outputs;
ret = &tmp[index].address_type;
}
default:
THROW(SW_UNKNOWN);
break;
}
return ret;
}

uint64_t get_output_amount(const API_CTX *api, uint8_t index)
{
MUST(index < api->essence.outputs_count);

uint64_t amount = 0;

switch (api->protocol) {
case PROTOCOL_STARDUST: {
BASIC_OUTPUT *tmp = (BASIC_OUTPUT *)api->essence.outputs;
memcpy(&amount, &tmp[index].amount, sizeof(uint64_t));
break;
}
case PROTOCOL_CHRYSALIS: {
SIG_LOCKED_SINGLE_OUTPUT *tmp =
(SIG_LOCKED_SINGLE_OUTPUT *)api->essence.outputs;
memcpy(&amount, &tmp[index].amount, sizeof(uint64_t));
break;
}
default:
THROW(SW_UNKNOWN);
break;
}
return amount;
}

uint8_t address_encode_bech32(const uint8_t *addr_with_type, char *bech32,
uint32_t bech32_max_length)
{
switch (api.coin) {
case COIN_IOTA: {
MUST(address_encode_bech32_hrp(addr_with_type, bech32, bech32_max_length, COIN_HRP_IOTA, strlen(COIN_HRP_IOTA)));
break;
}
case COIN_SHIMMER: {
MUST(address_encode_bech32_hrp(addr_with_type, bech32, bech32_max_length, COIN_HRP_SHIMMER, strlen(COIN_HRP_SHIMMER)));
break;
}
default:
THROW(SW_UNKNOWN);
break;
}
return 1;
}


uint8_t essence_parse_and_validate(API_CTX *api)
{
switch (api->protocol) {
case PROTOCOL_STARDUST: {
MUST(essence_parse_and_validate_stardust(api));
break;
}
case PROTOCOL_CHRYSALIS: {
MUST(essence_parse_and_validate_chryslis(api));
break;
}
default:
THROW(SW_UNKNOWN);
break;
}
return 1;
}
37 changes: 37 additions & 0 deletions src/iota/abstraction.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <stdbool.h>
#include <stdint.h>

#include "api.h"
#include "constants.h"

#define IO_STRUCT struct __attribute__((packed, may_alias))

#define MUST(c) \
{ \
if (!(c)) { \
return 0; \
} \
}


typedef IO_STRUCT
{
// amount first for better data alignment
// we can keep the struct packed but amount and address_type are
// aligned on 32bits
uint64_t amount;
uint8_t address_type;
uint8_t address[ADDRESS_SIZE_BYTES];
}
ABS_OUTPUT;

uint8_t *get_output_address(const API_CTX *api, uint8_t index);

uint64_t get_output_amount(const API_CTX *api, uint8_t index);

uint8_t address_encode_bech32(const uint8_t *addr_with_type, char *bech32,
uint32_t bech32_max_length);

uint8_t essence_parse_and_validate(API_CTX *api);
6 changes: 3 additions & 3 deletions src/iota/address.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
}


uint8_t address_encode_bech32(const uint8_t *addr_with_type, char *bech32,
uint32_t bech32_max_length)
uint8_t address_encode_bech32_hrp(const uint8_t *addr_with_type, char *bech32,
uint32_t bech32_max_length, const char* hrp, const size_t hrp_len)
{
// at least this space is needed - bech32_encode adds a zero-terminator
// byte!
Expand All @@ -50,7 +50,7 @@ uint8_t address_encode_bech32(const uint8_t *addr_with_type, char *bech32,

// and encode base32 to bech32
uint32_t bech32_length = bech32_max_length;
ret = bech32_encode(bech32, &bech32_length, ADDRESS_HRP, ADDRESS_HRP_LENGTH,
ret = bech32_encode(bech32, &bech32_length, hrp, hrp_len,
base32, base32_length);
MUST(ret);

Expand Down
4 changes: 2 additions & 2 deletions src/iota/address.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#include "api.h"
#include "constants.h"

uint8_t address_encode_bech32(const uint8_t *addr, char *bech32,
uint32_t bech32_max_length);
uint8_t address_encode_bech32_hrp(const uint8_t *addr, char *bech32,
uint32_t bech32_max_length, const char* hrp, const size_t hrp_len);

uint8_t address_generate(uint32_t *bip32_path, uint32_t bip32_path_length,
uint8_t *addr);
Expand Down
Loading

0 comments on commit 3dc24e5

Please sign in to comment.