Skip to content

Commit

Permalink
Merge pull request #81 from obsidiansystems/develop
Browse files Browse the repository at this point in the history
2.1.0
  • Loading branch information
3noch authored Aug 26, 2019
2 parents f87b649 + 10b4d93 commit 091e74e
Show file tree
Hide file tree
Showing 29 changed files with 445 additions and 218 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ GIT_DESCRIBE ?= $(shell git describe --tags --abbrev=8 --always --long --dirty 2

VERSION_TAG ?= $(shell echo "$(GIT_DESCRIBE)" | cut -f1 -d-)
APPVERSION_M=2
APPVERSION_N=0
APPVERSION_P=1
APPVERSION_N=1
APPVERSION_P=0
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)

# Only warn about version tags if specified/inferred
Expand Down
39 changes: 28 additions & 11 deletions default.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{ pkgs ? import nix/nixpkgs.nix {}, gitDescribe ? null, nanoXSdk ? throw "No NanoX SDK", ... }:
{ pkgs ? import nix/nixpkgs.nix {}, gitDescribe ? null, nanoXSdk ? null, ... }:
let

fetchThunk = p:
if builtins.pathExists (p + /git.json)
then pkgs.fetchgit { inherit (builtins.fromJSON (builtins.readFile (p + /git.json))) url rev sha256; }
Expand All @@ -19,14 +18,32 @@ let
sdk = fetchThunk nix/dep/nanos-secure-sdk;
env = pkgs.callPackage nix/bolos-env.nix { clangVersion = 4; };
target = "TARGET_NANOS";
targetId = "0x31100004";
fhsWith = fhs (_: [env.clang]);
iconHex = pkgs.runCommand "nano-s-icon-hex" {} ''
'${fhsWith "python"}' ${sdk + /icon.py} '${icons/nano-s-tezos.gif}' hexbitmaponly > "$out"
'';
nvramDataSize = appDir: pkgs.runCommand "${name}-nvram-data-size" {} ''
grep _nvram_data_size '${appDir + /debug/app.map}' | tr -s ' ' | cut -f2 -d' ' > "$out"
'';
};
x = rec {
name = "x";
sdk = nanoXSdk;
sdk = if nanoXSdk == null
then throw "No NanoX SDK"
else assert builtins.typeOf nanoXSdk == "path"; nanoXSdk;
env = pkgs.callPackage nix/bolos-env.nix { clangVersion = 7; };
target = "TARGET_NANOX";
targetId = "0x33000004";
fhsWith = fhs (_: [env.clang]);
iconHex = pkgs.runCommand "${name}-icon-hex" {} ''
'${fhsWith "python3"}' '${sdk + /icon3.py}' --hexbitmaponly '${icons/nano-x-tezos.gif}' > "$out"
'';
nvramDataSize = appDir: pkgs.runCommand "${name}-nvram-data-size" {} ''
envram_data="0x$(cat | grep _envram_data '${appDir + /debug/app.map}' | cut -f1 -d' ')"
nvram_data="0x$(grep _nvram_data '${appDir + /debug/app.map}' | cut -f1 -d' ')"
echo "$(($envram_data - $nvram_data))" > "$out"
'';
};
};

Expand All @@ -46,6 +63,7 @@ let
export BOLOS_ENV='${bolos.env}'
export APP='${if bakingApp then "tezos_baking" else "tezos_wallet"}'
export GIT_DESCRIBE='${gitDescribe}'
export TARGET='${bolos.target}'
make clean
make all
EOF
Expand All @@ -66,25 +84,24 @@ let
cat > "$out/app.manifest" <<EOF
name='${name}'
nvram_size=$(grep _nvram_data_size '${appDir + /debug/app.map}' | tr -s ' ' | cut -f2 -d' ')
nvram_size=$(cat '${bolos.nvramDataSize appDir}')
target='nano_${bolos.name}'
target_id=0x31100004
target_id=${bolos.targetId}
version=$(echo '${gitDescribe}' | cut -f1 -d- | cut -f2 -dv)
icon_hex=$(cat '${bolos.iconHex}')
EOF
cp '${dist/icon.hex}' "$out/icon.hex"
'';

walletApp = app false;
bakingApp = app true;
in {
wallet = walletApp;
baking = if bolos.name == "x" then null else bakingApp;
baking = bakingApp;

release = rec {
wallet = mkRelease "wallet" "Tezos Wallet" walletApp;
baking = if bolos.name == "x" then null else mkRelease "baking" "Tezos Baking" bakingApp;
all = if bolos.name == "x" then null else pkgs.runCommand "release.tar.gz" {} ''
baking = mkRelease "baking" "Tezos Baking" bakingApp;
all = pkgs.runCommand "${bolos.name}-release.tar.gz" {} ''
cp -r '${wallet}' wallet
cp -r '${baking}' baking
cp '${./release-installer.sh}' install.sh
Expand Down Expand Up @@ -203,7 +220,7 @@ in rec {
};

clangAnalysis = mkTargets (bolos: {
baking = if bolos.name == "x" then null else runClangStaticAnalyzer true bolos;
baking = runClangStaticAnalyzer true bolos;
wallet = runClangStaticAnalyzer false bolos;
});

Expand Down
1 change: 0 additions & 1 deletion dist/icon.hex

This file was deleted.

8 changes: 5 additions & 3 deletions nix/install.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
#!/usr/bin/env bash
set -Eeuo pipefail

export target="${1:?Please specify target, either 's' for Nano S or 'x' for Nano X}"
shift

root="$(git rev-parse --show-toplevel)"
export root

install() {
local release_file
release_file=$("$root/nix/build.sh" -A "nano.s.release.$1")
release_file=$("$root/nix/build.sh" -A "nano.${target}.release.$1")
bash "$root/release-installer.sh" "$release_file"
}

export root
export -f install

nix-shell "$root/nix/ledgerblue.nix" -A shell --run "$(cat <<EOF
Expand Down
6 changes: 3 additions & 3 deletions nix/setup-vscode.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ set -Eeuo pipefail
root="$(git rev-parse --show-toplevel)"
cd "$root"

cp -f "$(nix-build -A env.ide.config.vscode --no-out-link)" "vscode.code-workspace"
cp -f "$(nix-build -A env.s.ide.config.vscode --no-out-link)" "vscode.code-workspace"
chmod +w "vscode.code-workspace"

cd "$root"
bear="$(nix-build -E '(import nix/nixpkgs.nix {}).bear' --no-out-link)/bin/bear"
nix/env.sh "make clean && \"$bear\" make; make clean"
# c.f. https://github.com/rizsotto/Bear/issues/182
nix/env.sh s "export LANG=C.UTF-8; export LC_CTYPE=C.UTF-8; make clean && \"$bear\" make; make clean"
4 changes: 2 additions & 2 deletions release-installer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ for arg in "$@"; do
--curve prime256r1 \
--targetId "${target_id:?manifest file is missing field}" \
--delete \
--path 44"'"/1729"'" \
--path "44'/1729'" \
--fileName "$app_dir/app.hex" \
--appName "$name" \
--appVersion "$version" \
--icon "$(cat "$app_dir/icon.hex")" \
--icon "${icon_hex:?manifest file is missing field}" \
--targetVersion ""
done
2 changes: 2 additions & 0 deletions src/apdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <string.h>

size_t provide_pubkey(uint8_t *const io_buffer, cx_ecfp_public_key_t const *const pubkey) {
check_null(io_buffer);
check_null(pubkey);
size_t tx = 0;
io_buffer[tx++] = pubkey->W_len;
memmove(io_buffer + tx, pubkey->W, pubkey->W_len);
Expand Down
5 changes: 1 addition & 4 deletions src/apdu_baking.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,10 @@ size_t handle_apdu_query_auth_key(__attribute__((unused)) uint8_t instruction) {
}

size_t handle_apdu_query_auth_key_with_curve(__attribute__((unused)) uint8_t instruction) {
uint8_t const curve_code = curve_to_curve_code(N_data.baking_key.curve);
if (curve_code == TEZOS_NO_CURVE) THROW(EXC_REFERENCED_DATA_NOT_FOUND);

uint8_t const length = N_data.baking_key.bip32_path.length;

size_t tx = 0;
G_io_apdu_buffer[tx++] = curve_code;
G_io_apdu_buffer[tx++] = unparse_derivation_type(N_data.baking_key.derivation_type);
G_io_apdu_buffer[tx++] = length;
for (uint8_t i = 0; i < length; ++i) {
tx = send_word_big_endian(tx, N_data.baking_key.bip32_path.components[i]);
Expand Down
13 changes: 8 additions & 5 deletions src/apdu_hmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "apdu_hmac.h"

#include "globals.h"
#include "key_macros.h"
#include "keys.h"
#include "protocol.h"

Expand All @@ -27,10 +28,12 @@ static inline size_t hmac(
0x5a, 0x90, 0x47, 0x5e, 0xc0, 0xdb, 0xdb, 0x9f };

// Deterministically sign the SHA256 value to get something directly tied to the secret key.
size_t const signed_hmac_key_size = sign(
state->signed_hmac_key, sizeof(state->signed_hmac_key),
&state->key,
key_sha256, sizeof(key_sha256));
size_t const signed_hmac_key_size = WITH_KEY_PAIR(state->key, key_pair, size_t, ({
sign(
state->signed_hmac_key, sizeof(state->signed_hmac_key),
state->key.derivation_type, key_pair,
key_sha256, sizeof(key_sha256));
}));

// Hash the signed value with SHA512 to get a 64-byte key for HMAC.
cx_hash_sha512(
Expand All @@ -52,7 +55,7 @@ size_t handle_apdu_hmac(__attribute__((unused)) uint8_t instruction) {

memset(&G, 0, sizeof(G));

G.key.curve = curve_code_to_curve(
G.key.derivation_type = parse_derivation_type(
READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_CURVE]));

size_t consumed = 0;
Expand Down
7 changes: 3 additions & 4 deletions src/apdu_pubkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ static bool pubkey_ok(void) {

#ifdef BAKING_APP
static bool baking_ok(void) {
authorize_baking(G.key.curve, &G.key.bip32_path);
authorize_baking(G.key.derivation_type, &G.key.bip32_path);
pubkey_ok();
return true;
}
Expand Down Expand Up @@ -76,8 +76,7 @@ size_t handle_apdu_get_public_key(uint8_t instruction) {
// do not expose pks without prompt over U2F (browser support)
if (instruction == INS_GET_PUBLIC_KEY) require_hid();

uint8_t const curve_code = READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_CURVE]);
G.key.curve = curve_code_to_curve(curve_code);
G.key.derivation_type = parse_derivation_type(READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_CURVE]));

size_t const cdata_size = READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_LC]);

Expand All @@ -91,7 +90,7 @@ size_t handle_apdu_get_public_key(uint8_t instruction) {
if (G.key.bip32_path.length == 0) THROW(EXC_WRONG_LENGTH_FOR_INS);
}
#endif
generate_public_key(&G.public_key, G.key.curve, &G.key.bip32_path);
generate_public_key(&G.public_key, G.key.derivation_type, &G.key.bip32_path);

if (instruction == INS_GET_PUBLIC_KEY) {
return provide_pubkey(G_io_apdu_buffer, &G.public_key);
Expand Down
5 changes: 2 additions & 3 deletions src/apdu_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ static bool ok(void) {
});

cx_ecfp_public_key_t const *const pubkey = generate_public_key_return_global(
G.key.curve, &G.key.bip32_path);
G.key.derivation_type, &G.key.bip32_path);
delayed_send(provide_pubkey(G_io_apdu_buffer, pubkey));
return true;
}
Expand Down Expand Up @@ -72,8 +72,7 @@ __attribute__((noreturn)) size_t handle_apdu_setup(__attribute__((unused)) uint8
uint32_t const buff_size = READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_LC]);
if (buff_size < sizeof(struct setup_wire)) THROW(EXC_WRONG_LENGTH_FOR_INS);

uint8_t const curve_code = READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_CURVE]);
G.key.curve = curve_code_to_curve(curve_code);
G.key.derivation_type = parse_derivation_type(READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_CURVE]));

{
struct setup_wire const *const buff_as_setup = (struct setup_wire const *)&G_io_apdu_buffer[OFFSET_CDATA];
Expand Down
15 changes: 9 additions & 6 deletions src/apdu_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "base58.h"
#include "blake2.h"
#include "globals.h"
#include "key_macros.h"
#include "keys.h"
#include "memory.h"
#include "protocol.h"
Expand Down Expand Up @@ -107,7 +108,7 @@ static bool parse_allowed_operations(
// TODO: Add still other operations
# endif

return parse_operations(out, in, in_size, key->curve, &key->bip32_path, allowed);
return parse_operations(out, in, in_size, key->derivation_type, &key->bip32_path, allowed);
}

#ifdef BAKING_APP // ----------------------------------------------------------
Expand Down Expand Up @@ -304,7 +305,7 @@ bool prompt_transaction(

char const *const *prompts;
bool const delegatable = ops->operation.flags & ORIGINATION_FLAG_DELEGATABLE;
bool const has_delegate = ops->operation.delegate.curve_code != TEZOS_NO_CURVE;
bool const has_delegate = ops->operation.delegate.signature_type != SIGNATURE_TYPE_UNSET;
if (delegatable && has_delegate) {
prompts = origination_prompts_delegatable;
register_ui_callback(DELEGATE_INDEX, parsed_contract_to_string,
Expand Down Expand Up @@ -358,8 +359,8 @@ bool prompt_transaction(

REGISTER_STATIC_UI_VALUE(TYPE_INDEX, "Delegation");

bool withdrawal = ops->operation.destination.originated == 0 &&
ops->operation.destination.curve_code == TEZOS_NO_CURVE;
bool const withdrawal = ops->operation.destination.originated == 0 &&
ops->operation.destination.signature_type == SIGNATURE_TYPE_UNSET;

ui_prompt(withdrawal ? withdrawal_prompts : delegation_prompts, ok, cxl);
}
Expand Down Expand Up @@ -494,7 +495,7 @@ static size_t handle_apdu(bool const enable_hashing, bool const enable_parsing,
case P1_FIRST:
clear_data();
read_bip32_path(&G.key.bip32_path, buff, buff_size);
G.key.curve = curve_code_to_curve(READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_CURVE]));
G.key.derivation_type = parse_derivation_type(READ_UNALIGNED_BIG_ENDIAN(uint8_t, &G_io_apdu_buffer[OFFSET_CURVE]));
return finalize_successful_send(0);
#ifndef BAKING_APP
case P1_HASH_ONLY_NEXT:
Expand Down Expand Up @@ -602,7 +603,9 @@ static int perform_signature(bool const on_hash, bool const send_hash) {

uint8_t const *const data = on_hash ? G.final_hash : G.message_data;
size_t const data_length = on_hash ? sizeof(G.final_hash) : G.message_data_length;
tx += sign(&G_io_apdu_buffer[tx], MAX_SIGNATURE_SIZE, &G.key, data, data_length);
tx += WITH_KEY_PAIR(G.key, key_pair, size_t, ({
sign(&G_io_apdu_buffer[tx], MAX_SIGNATURE_SIZE, G.key.derivation_type, key_pair, data, data_length);
}));

clear_data();
return finalize_successful_send(tx);
Expand Down
17 changes: 9 additions & 8 deletions src/baking_auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,26 @@ void write_high_water_mark(parsed_baking_data_t const *const in) {
if (!is_valid_level(in->level)) THROW(EXC_WRONG_VALUES);
UPDATE_NVRAM(ram, {
// If the chain matches the main chain *or* the main chain is not set, then use 'main' HWM.
high_watermark_t *const dest = select_hwm_by_chain(in->chain_id, ram);
high_watermark_t volatile *const dest = select_hwm_by_chain(in->chain_id, ram);
dest->highest_level = MAX(in->level, dest->highest_level);
dest->had_endorsement = in->is_endorsement;
});
}

void authorize_baking(cx_curve_t const curve, bip32_path_t const *const bip32_path) {
void authorize_baking(derivation_type_t const derivation_type, bip32_path_t const *const bip32_path) {
check_null(bip32_path);
if (bip32_path->length > NUM_ELEMENTS(N_data.baking_key.bip32_path.components) || bip32_path->length == 0) return;

UPDATE_NVRAM(ram, {
ram->baking_key.curve = curve;
ram->baking_key.derivation_type = derivation_type;
copy_bip32_path(&ram->baking_key.bip32_path, bip32_path);
});
}

static bool is_level_authorized(parsed_baking_data_t const *const baking_info) {
check_null(baking_info);
if (!is_valid_level(baking_info->level)) return false;
high_watermark_t const *const hwm = select_hwm_by_chain(baking_info->chain_id, &N_data);
high_watermark_t volatile const *const hwm = select_hwm_by_chain(baking_info->chain_id, &N_data);
return baking_info->level > hwm->highest_level

// Levels are tied. In order for this to be OK, this must be an endorsement, and we must not
Expand All @@ -51,18 +51,19 @@ static bool is_level_authorized(parsed_baking_data_t const *const baking_info) {
&& baking_info->is_endorsement && !hwm->had_endorsement);
}

bool is_path_authorized(cx_curve_t curve, bip32_path_t const *const bip32_path) {
bool is_path_authorized(derivation_type_t const derivation_type, bip32_path_t const *const bip32_path) {
check_null(bip32_path);
return
curve == N_data.baking_key.curve &&
derivation_type != 0 &&
derivation_type == N_data.baking_key.derivation_type &&
bip32_path->length > 0 &&
bip32_paths_eq(bip32_path, &N_data.baking_key.bip32_path);
bip32_paths_eq(bip32_path, (const bip32_path_t *)&N_data.baking_key.bip32_path);
}

void guard_baking_authorized(parsed_baking_data_t const *const baking_info, bip32_path_with_curve_t const *const key) {
check_null(baking_info);
check_null(key);
if (!is_path_authorized(key->curve, &key->bip32_path)) THROW(EXC_SECURITY);
if (!is_path_authorized(key->derivation_type, &key->bip32_path)) THROW(EXC_SECURITY);
if (!is_level_authorized(baking_info)) THROW(EXC_WRONG_VALUES);
}

Expand Down
4 changes: 2 additions & 2 deletions src/baking_auth.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
#include <stdbool.h>
#include <stdint.h>

void authorize_baking(cx_curve_t const curve, bip32_path_t const *const bip32_path);
void authorize_baking(derivation_type_t const derivation_type, bip32_path_t const *const bip32_path);
void guard_baking_authorized(parsed_baking_data_t const *const baking_data, bip32_path_with_curve_t const *const key);
bool is_path_authorized(cx_curve_t curve, bip32_path_t const *const bip32_path);
bool is_path_authorized(derivation_type_t const derivation_type, bip32_path_t const *const bip32_path);
bool is_valid_level(level_t level);
void write_high_water_mark(parsed_baking_data_t const *const in);

Expand Down
2 changes: 1 addition & 1 deletion src/exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#define EXC_MEMORY_ERROR 0x9200

// Crashes can be harder to debug than exceptions and latency isn't a big concern
static inline void check_null(const void *ptr) {
static inline void check_null(void volatile const *const ptr) {
if (ptr == NULL) {
THROW(EXC_MEMORY_ERROR);
}
Expand Down
Loading

0 comments on commit 091e74e

Please sign in to comment.