Skip to content

Commit

Permalink
[add] Fetch seed from env at startup then stick with it
Browse files Browse the repository at this point in the history
  • Loading branch information
lpascal-ledger committed Dec 7, 2023
1 parent f9dfe87 commit 4652362
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 74 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.5.0] - 2023-??-??

### Added
- Seed is fetched from the environment during the Speculos launch and stored internally for further
use. This avoids several Speculos instances from messing up with each other's seeds.

## [0.4.0] - 2023-12-04

### Fixed
Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ add_library(emu
emulate_blue_2.2.5.c
emulate_lnsp_1.0.c
emulate_unified_sdk.c
seed.c
svc.c)

add_dependencies(emu openssl)
Expand Down
73 changes: 3 additions & 70 deletions src/bolos/os_bip32.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,23 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "os_bip32.h"

#include "bolos/exception.h"
#include "cx.h"
#include "cx_utils.h"
#include "emulate.h"
#include "seed.h"

#define BIP32_HARDEN_MASK 0x80000000
#define BIP32_SECP_SEED_LENGTH 12
#define MAX_SEED_SIZE 64

#define cx_ecfp_generate_pair sys_cx_ecfp_generate_pair
#define cx_ecfp_init_private_key sys_cx_ecfp_init_private_key
#define cx_ecdsa_init_private_key cx_ecfp_init_private_key

/* glory promote mansion idle axis finger extra february uncover one trip
* resource lawn turtle enact monster seven myth punch hobby comfort wild raise
* skin */
static uint8_t default_seed[MAX_SEED_SIZE] =
"\xb1\x19\x97\xfa\xff\x42\x0a\x33\x1b\xb4\xa4\xff\xdc\x8b\xdc\x8b\xa7\xc0"
"\x17\x32\xa9\x9a\x30\xd8\x3d\xbb\xeb\xd4\x69\x66\x6c\x84\xb4\x7d\x09\xd3"
"\xf5\xf4\x72\xb3\xb9\x38\x4a\xc6\x34\xbe\xba\x2a\x44\x0b\xa3\x6e\xc7\x66"
"\x11\x44\x13\x2f\x35\xe2\x06\x87\x35\x64";

static uint8_t const BIP32_SECP_SEED[] = { 'B', 'i', 't', 'c', 'o', 'i',
'n', ' ', 's', 'e', 'e', 'd' };

Expand Down Expand Up @@ -166,65 +158,6 @@ static void expand_seed(cx_curve_t curve, const uint8_t *sk, size_t sk_length,
}
}

int unhex(uint8_t *dst, size_t dst_size, const char *src, size_t src_size)
{
unsigned int i;
uint8_t acc;
int8_t c;

acc = 0;
for (i = 0; i < src_size && (i >> 1) < dst_size; i++) {
c = src[i];
switch (c) {
case '0' ... '9':
acc = (acc << 4) + c - '0';
break;
case 'a' ... 'f':
acc = (acc << 4) + c - 'a' + 10;
break;
case 'A' ... 'F':
acc = (acc << 4) + c - 'A' + 10;
break;
default:
return -1;
}

if (i % 2 != 0) {
dst[i >> 1] = acc;
acc = 0;
}
}

if (i != src_size) {
return -1;
}

return src_size / 2;
}

size_t get_seed_from_env(const char *name, uint8_t *seed, size_t max_size)
{
ssize_t seed_size;
char *p;

p = getenv(name);
if (p != NULL) {
seed_size = unhex(seed, max_size, p, strlen(p));
if (seed_size < 0) {
warnx("invalid seed passed through %s environment variable", name);
p = NULL;
}
}

if (p == NULL) {
warnx("using default seed");
memcpy(seed, default_seed, sizeof(default_seed));
seed_size = sizeof(default_seed);
}

return seed_size;
}

static int hdw_bip32_ed25519(extended_private_key *key, const uint32_t *path,
size_t length, uint8_t *private_key,
uint8_t *chain)
Expand Down Expand Up @@ -512,7 +445,7 @@ unsigned long sys_os_perso_derive_node_with_seed_key(
sk_length = seed_key_length;
}

seed_size = get_seed_from_env("SPECULOS_SEED", seed, sizeof(seed));
seed_size = get_seed(seed, sizeof(seed));

if (mode == HDW_SLIP21) {
ret = hdw_slip21(sk, sk_length, seed, seed_size, (const uint8_t *)path,
Expand Down
2 changes: 0 additions & 2 deletions src/bolos/os_bip32.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,3 @@ typedef struct {

void expand_seed_bip32(const cx_curve_domain_t *domain, uint8_t *seed,
unsigned int seed_length, extended_private_key *key);
int unhex(uint8_t *dst, size_t dst_size, const char *src, size_t src_size);
size_t get_seed_from_env(const char *name, uint8_t *seed, size_t max_size);
4 changes: 2 additions & 2 deletions src/bolos/os_eip2333.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "cx_utils.h"
#include "emulate.h"
#include "exception.h"
#include "os_bip32.h"
#include "seed.h"

#define MAX_SEED_SIZE 64
#define CX_SHA256_SIZE 32
Expand Down Expand Up @@ -142,7 +142,7 @@ unsigned long sys_os_perso_derive_eip2333(cx_curve_t curve,
THROW(EXCEPTION);
}

seed_size = get_seed_from_env("SPECULOS_SEED", seed, sizeof(seed));
seed_size = get_seed(seed, sizeof(seed));

cx_derive_master_sk(seed, seed_size, sk);
if (privateKey != NULL) {
Expand Down
2 changes: 2 additions & 0 deletions src/launcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "emulate.h"
#include "fonts.h"
#include "svc.h"
#include "seed.h"

#define LOAD_ADDR ((void *)0x40000000)
#define LINK_RAM_ADDR (0xda7a0000)
Expand Down Expand Up @@ -722,6 +723,7 @@ int main(int argc, char *argv[])
extra_rampage_size = 0;

fprintf(stderr, "[*] speculos launcher revision: " GIT_REVISION "\n");
init_seed();

while ((opt = getopt(argc, argv, "c:tr:s:m:k:a:f:")) != -1) {
switch (opt) {
Expand Down
94 changes: 94 additions & 0 deletions src/seed.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "seed.h"


/* glory promote mansion idle axis finger extra february uncover one trip
* resource lawn turtle enact monster seven myth punch hobby comfort wild raise
* skin */
static uint8_t default_seed[MAX_SEED_SIZE] =
"\xb1\x19\x97\xfa\xff\x42\x0a\x33\x1b\xb4\xa4\xff\xdc\x8b\xdc\x8b\xa7\xc0"
"\x17\x32\xa9\x9a\x30\xd8\x3d\xbb\xeb\xd4\x69\x66\x6c\x84\xb4\x7d\x09\xd3"
"\xf5\xf4\x72\xb3\xb9\x38\x4a\xc6\x34\xbe\xba\x2a\x44\x0b\xa3\x6e\xc7\x66"
"\x11\x44\x13\x2f\x35\xe2\x06\x87\x35\x64";

const char *SEED_ENV_NAME = "SPECULOS_SEED";
typedef struct {
size_t size;
uint8_t seed[MAX_SEED_SIZE];
} seed_t;
static seed_t actual_seed = {0};


static int unhex(uint8_t *dst, size_t dst_size, const char *src, size_t src_size)
{
unsigned int i;
uint8_t acc;
int8_t c;

acc = 0;
for (i = 0; i < src_size && (i >> 1) < dst_size; i++) {
c = src[i];
switch (c) {
case '0' ... '9':
acc = (acc << 4) + c - '0';
break;
case 'a' ... 'f':
acc = (acc << 4) + c - 'a' + 10;
break;
case 'A' ... 'F':
acc = (acc << 4) + c - 'A' + 10;
break;
default:
return -1;
}

if (i % 2 != 0) {
dst[i >> 1] = acc;
acc = 0;
}
}

if (i != src_size) {
return -1;
}

return src_size / 2;
}


void init_seed()
{
ssize_t size;
char *p;

p = getenv(SEED_ENV_NAME);
if (p != NULL) {
size = unhex(actual_seed.seed, sizeof(actual_seed.seed), p, strlen(p));
if (size < 0) {
warnx("invalid seed passed through %s environment variable", SEED_ENV_NAME);
p = NULL;
} else {
fprintf(stderr, "[*] Seed initialized from environment: '%s'\n", p);
}
}

if (p == NULL) {
warnx("using default seed");
memcpy(actual_seed.seed, default_seed, sizeof(default_seed));
size = sizeof(default_seed);
fprintf(stderr, "[*] Seed initialized from default value: '%s'\n", default_seed);
}
actual_seed.size = size;
}


size_t get_seed(uint8_t *seed, size_t max_size)
{
memcpy(seed, actual_seed.seed, max_size);
return (actual_seed.size < max_size) ? actual_seed.size : max_size;
}
9 changes: 9 additions & 0 deletions src/seed.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <stdint.h>

#define MAX_SEED_SIZE 64


size_t get_seed(uint8_t *seed, size_t max_size);
void init_seed();

0 comments on commit 4652362

Please sign in to comment.