Skip to content

Commit

Permalink
Factored out UI seed module
Browse files Browse the repository at this point in the history
- Factored out seed operations
- Added unit tests for seed module
- Removed unused parameters from unlock and pin modules
  • Loading branch information
italo-sampaio committed Nov 1, 2022
1 parent 43b457d commit fe0dc79
Show file tree
Hide file tree
Showing 12 changed files with 495 additions and 54 deletions.
69 changes: 30 additions & 39 deletions ledger/src/ui/src/bolos_ux.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ void io_seproxyhal_display(const bagl_element_t *element) {
// Pin context shorthand
#define pin_ctx (G_bolos_ux_context.pin)

// Seed context shorthand
#define seed_ctx (G_bolos_ux_context.seed)

// Operation being currently executed
static unsigned char curr_cmd;

Expand All @@ -264,15 +267,26 @@ static void reset_if_starting(unsigned char cmd) {
reset_attestation(&attestation_ctx);
reset_signer_authorization(&sigaut_ctx);
reset_pin_ctx(&pin_ctx);
reset_seed_ctx(&seed_ctx);
}
}

/**
* Load pointers from G_bolos_ux_context to seed_ctx
*/
static void bolos_ux_init_seed_ctx() {
init_seed_ctx(&seed_ctx,
G_bolos_ux_context.words_buffer,
sizeof(G_bolos_ux_context.words_buffer),
G_bolos_ux_context.string_buffer,
sizeof(G_bolos_ux_context.string_buffer),
&bolos_ux_mnemonic_from_data);
}

static void sample_main(void) {
volatile unsigned int rx = 0;
volatile unsigned int tx = 0;
volatile unsigned int flags = 0;
volatile unsigned char pin = 0;
volatile int i = 0;
volatile unsigned char aux;

// Initialize current operation
Expand Down Expand Up @@ -312,10 +326,8 @@ static void sample_main(void) {
switch (APDU_CMD()) {
case RSK_SEED_CMD: // Send wordlist
reset_if_starting(RSK_META_CMD_UIOP);
pin = APDU_AT(2);
if ((pin >= 0) && ((unsigned int)(pin) <=
sizeof(G_bolos_ux_context.words_buffer)))
G_bolos_ux_context.words_buffer[pin] = APDU_AT(3);
bolos_ux_init_seed_ctx();
tx = update_words_buffer(rx, &seed_ctx);
THROW(APDU_OK);
break;
case RSK_PIN_CMD: // Send pin_buffer
Expand Down Expand Up @@ -344,6 +356,7 @@ static void sample_main(void) {
(void *)PIC(N_onboarded_ui), (void *)&aux, sizeof(aux));

init_pin_ctx(&pin_ctx, G_pin_buffer);
bolos_ux_init_seed_ctx();
#ifndef DEBUG_BUILD
if (!is_pin_valid(&pin_ctx)) {
THROW(ERR_INVALID_PIN);
Expand All @@ -354,39 +367,17 @@ static void sample_main(void) {
os_perso_wipe();
G_bolos_ux_context.onboarding_kind =
BOLOS_UX_ONBOARDING_NEW_24;
// Generate 32 bytes of random with onboard rng
cx_rng((unsigned char *)G_bolos_ux_context.string_buffer,
HASHSIZE);
// XOR with host-generated 32 bytes random
for (i = 0; i < HASHSIZE; i++) {
G_bolos_ux_context.string_buffer[i] ^=
G_bolos_ux_context.words_buffer[i];
}
// The seed is now in string_buffer, generate the mnemonic
os_memset(G_bolos_ux_context.words_buffer,
0,
sizeof(G_bolos_ux_context.words_buffer));
G_bolos_ux_context.words_buffer_length =
bolos_ux_mnemonic_from_data(
(unsigned char *)G_bolos_ux_context.string_buffer,
SEEDSIZE,
(unsigned char *)G_bolos_ux_context.words_buffer,
sizeof(G_bolos_ux_context.words_buffer));
// Clear the seed
explicit_bzero(G_bolos_ux_context.string_buffer,
sizeof(G_bolos_ux_context.string_buffer));
generate_mnemonic(&seed_ctx);
// Set seed from mnemonic
os_perso_derive_and_set_seed(
0,
NULL,
0,
NULL,
0,
G_bolos_ux_context.words_buffer,
strlen(G_bolos_ux_context.words_buffer));
os_perso_derive_and_set_seed(0,
NULL,
0,
NULL,
0,
seed_ctx.words_buffer,
strlen(seed_ctx.words_buffer));
// Clear the mnemonic
explicit_bzero(G_bolos_ux_context.words_buffer,
sizeof(G_bolos_ux_context.words_buffer));
clear_mnemonic(&seed_ctx);
// Set PIN
os_perso_set_pin(
0, GET_PIN(&pin_ctx), GET_PIN_LENGTH(&pin_ctx));
Expand Down Expand Up @@ -416,7 +407,7 @@ static void sample_main(void) {
THROW(ERR_INVALID_PIN);
}
#endif
tx = set_device_pin(rx, &pin_ctx);
tx = set_device_pin(&pin_ctx);
// Clear pin buffer
explicit_bzero(G_pin_buffer, sizeof(G_pin_buffer));
THROW(APDU_OK);
Expand Down Expand Up @@ -451,7 +442,7 @@ static void sample_main(void) {
case RSK_UNLOCK_CMD: // Unlock
reset_if_starting(RSK_META_CMD_UIOP);
init_pin_ctx(&pin_ctx, G_pin_buffer);
tx = unlock(rx, &pin_ctx);
tx = unlock(&pin_ctx);
// The pin value will also be used in
// BOLOS_UX_CONSENT_APP_ADD command, so we can't wipe the
// pin buffer here
Expand Down
8 changes: 7 additions & 1 deletion ledger/src/ui/src/bolos_ux.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "attestation.h"
#include "signer_authorization.h"
#include "pin.h"
#include "seed.h"

#ifdef HAVE_BOLOS_UX

Expand Down Expand Up @@ -160,7 +161,12 @@ typedef struct bolos_ux_context {
union {
att_t attestation;
sigaut_t sigaut;
pin_t pin;
// pin and seed are used in the same context, so they can't share
// the same memory region
struct {
pin_t pin;
seed_t seed;
};
};
};

Expand Down
6 changes: 1 addition & 5 deletions ledger/src/ui/src/pin.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,10 @@ unsigned int update_pin_buffer(volatile unsigned int rx, pin_t* pin_ctx) {
*
* Sets the device pin.
*
* @arg[in] rx number of received bytes from the Host
* @arg[in] pin_ctx pin context
* @ret number of transmited bytes to the host
*/
unsigned int set_device_pin(volatile unsigned int rx, pin_t* pin_ctx) {
// NEW_PIN command does not use any input from apdu buffer
UNUSED(rx);

unsigned int set_device_pin(pin_t* pin_ctx) {
#ifndef DEBUG_BUILD
if (!is_pin_valid(pin_ctx)) {
THROW(ERR_INVALID_PIN);
Expand Down
3 changes: 1 addition & 2 deletions ledger/src/ui/src/pin.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,10 @@ unsigned int update_pin_buffer(volatile unsigned int rx, pin_t* pin_ctx);
*
* Sets the device pin.
*
* @arg[in] rx number of received bytes from the Host
* @arg[in] pin_ctx pin context
* @ret number of transmited bytes to the host
*/
unsigned int set_device_pin(volatile unsigned int rx, pin_t* pin_ctx);
unsigned int set_device_pin(pin_t* pin_ctx);

// -----------------------------------------------------------------------
// Pin manipulation utilities
Expand Down
121 changes: 121 additions & 0 deletions ledger/src/ui/src/seed.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2021 RSK Labs Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#include <string.h>

#include "apdu.h"
#include "defs.h"
#include "err.h"
#include "os.h"
#include "seed.h"

/*
* Init the given seed context to point to a target buffer
*
* @arg[out] seed_ctx seed context
* @arg[in] words_buffer pointer to the words buffer
* @arg[in] words_buffer_size words_buffer size in bytes
* @arg[in] seed_buffer pointer to the seed buffer
* @arg[in] seed_buffer_size seed_buffer size in bytes
*/
void init_seed_ctx(seed_t* seed_ctx,
char* words_buffer,
size_t words_buffer_size,
char* seed_buffer,
size_t seed_buffer_size,
mnemonic_from_data_callback_t callback) {
seed_ctx->words_buffer = words_buffer;
seed_ctx->words_buffer_size = words_buffer_size;
seed_ctx->seed_buffer = seed_buffer;
seed_ctx->seed_buffer_size = seed_buffer_size;
seed_ctx->mnemonic_from_data_callback = callback;
}

/*
* Reset the given seed context
*
* @arg[out] seed_ctx seed context
*/
void reset_seed_ctx(seed_t* seed_ctx) {
explicit_bzero(seed_ctx, sizeof(seed_t));
}

/*
* Generates the mnemonic from an initial seed. The seed should be in
* words_buffer before calling this function. The mnemonic will be saved
* on words_buffer and words_buffer_size will be set accordingly
*
* @arg[out] seed_ctx seed context
*/
void generate_mnemonic(seed_t* seed_ctx) {
volatile int i;
// Generate 32 bytes of random with onboard rng
cx_rng((unsigned char*)seed_ctx->seed_buffer, HASHSIZE);
// XOR with host-generated 32 bytes random
for (i = 0; i < HASHSIZE; i++) {
seed_ctx->seed_buffer[i] ^= seed_ctx->words_buffer[i];
}
// The seed is now in seed_buffer, generate the mnemonic
os_memset(seed_ctx->words_buffer, 0, seed_ctx->seed_buffer_size);
seed_ctx->words_buffer_size = seed_ctx->mnemonic_from_data_callback(
(unsigned char*)seed_ctx->seed_buffer,
SEEDSIZE,
(unsigned char*)seed_ctx->words_buffer,
seed_ctx->words_buffer_size);
// Clear the seed
explicit_bzero(seed_ctx->seed_buffer, seed_ctx->seed_buffer_size);
}

/*
* Wipes the contents of words_buffer
*
* @arg[out] seed_ctx seed context
*/
void clear_mnemonic(seed_t* seed_ctx) {
explicit_bzero(seed_ctx->words_buffer, seed_ctx->words_buffer_size);
}

/*
* Implement the RSK SEED command.
*
* Receives one byte at a time and fills words_buffer in seed_ctx.
*
* @arg[in] rx number of received bytes from the Host
* @arg[out] seed_ctx seed context
* @ret number of transmited bytes to the host
*/
unsigned int update_words_buffer(volatile unsigned int rx, seed_t* seed_ctx) {
// Should receive 1 byte per call
if (APDU_DATA_SIZE(rx) != 1) {
THROW(PROT_INVALID);
}

unsigned char index = APDU_OP();
if ((index >= 0) && ((size_t)index <= seed_ctx->words_buffer_size)) {
seed_ctx->words_buffer[index] = APDU_AT(3);
}

// No bytes transmited to host
return 0;
}
91 changes: 91 additions & 0 deletions ledger/src/ui/src/seed.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* The MIT License (MIT)
*
* Copyright (c) 2021 RSK Labs Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/

#ifndef __SEED
#define __SEED

typedef unsigned int (*mnemonic_from_data_callback_t)(unsigned char* in,
unsigned int in_length,
unsigned char* out,
unsigned int out_length);

// Seed context
typedef struct {
// Buffer used to hold the initial seed and the generated mnemominc
char* words_buffer;
// words_buffer size in bytes
size_t words_buffer_size;
// Temporary buffer used in seed generation
char* seed_buffer;
// seed_buffer size in bytes
size_t seed_buffer_size;
// callback function for mnemonic generation
mnemonic_from_data_callback_t mnemonic_from_data_callback;
} seed_t;

/*
* Init the given seed context to point to a target buffer
*
* @arg[out] seed_ctx seed context
* @arg[in] words_buffer pointer to the words buffer
* @arg[in] words_buffer_size words_buffer size in bytes
* @arg[in] seed_buffer pointer to the seed buffer
* @arg[in] seed_buffer_size seed_buffer size in bytes
*/
void init_seed_ctx(seed_t* seed_ctx,
char* words_buffer,
size_t words_buffer_size,
char* string_buffer,
size_t string_buffer_size,
mnemonic_from_data_callback_t callback);

/*
* Reset the given seed context
*
* @arg[in] seed_ctx seed context
*/
void reset_seed_ctx(seed_t* seed_ctx);

/*
* Generates the mnemonic from an initial seed. The seed should be in
* words_buffer before calling this function. The mnemonic will be saved
* on words_buffer and words_buffer_size will be set accordingly
*
* @arg[out] seed_ctx seed context
*/
void generate_mnemonic(seed_t* seed_ctx);
void clear_mnemonic(seed_t* seed_ctx);

/*
* Implement the RSK SEED command.
*
* Receives one byte at a time and fills words_buffer in seed_ctx.
*
* @arg[in] rx number of received bytes from the Host
* @arg[out] seed_ctx seed context
* @ret number of transmited bytes to the host
*/
unsigned int update_words_buffer(volatile unsigned int rx, seed_t* seed_ctx);

#endif
Loading

0 comments on commit fe0dc79

Please sign in to comment.