Skip to content

Commit

Permalink
Make the app return all components of the extended full viewing key.
Browse files Browse the repository at this point in the history
  • Loading branch information
murisi committed Aug 29, 2024
1 parent d4a77b8 commit ef24321
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 29 deletions.
3 changes: 3 additions & 0 deletions app/rust/include/rslib.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ parser_error_t add_points(const uint8_t hash[32], const uint8_t value[32], const
void zip32_ovk(uint32_t zip32_account, uint8_t *ovk);
void zip32_child_ask_nsk(uint32_t account, uint8_t *ask, uint8_t *nsk);
void diversifier_find_valid(uint32_t zip32_account, uint8_t *default_diversifier);
void zip32_dk(uint32_t zip32_account, uint8_t *dk);
void zip32_chain_code(uint32_t zip32_account, uint8_t *chain_code);
void zip32_parent_fvk_tag(uint32_t zip32_account, uint8_t *fvk_tag);
1 change: 1 addition & 0 deletions app/rust/src/personalization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub const PRF_OCK_PERSONALIZATION: &[u8; 16] = b"MASP__Derive_ock";
pub const KDF_SAPLING_PERSONALIZATION: &[u8; 16] = b"MASP__SaplingKDF";
pub const CRH_IVK_PERSONALIZATION: &[u8; 8] = b"MASP_ivk";
pub const CRH_NF: &[u8; 8] = b"MASP__nf";
pub const ZIP32_SAPLING_FVFP_PERSONALIZATION: &[u8; 16] = b"MASP_SaplingFVFP";
pub const ZIP32_SAPLING_MASTER_PERSONALIZATION: &[u8; 16] = b"MASP_IP32Sapling";
pub const KEY_DIVERSIFICATION_PERSONALIZATION: &[u8; 8] = b"MASP__gd";
pub const REDJUBJUB_PERSONALIZATION: &[u8; 16] = b"MASP__RedJubjubH";
Expand Down
2 changes: 2 additions & 0 deletions app/rust/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub type DkBytes = [u8; 32];

pub type NfBytes = [u8; 32];

pub type FvkTagBytes = [u8; 4];

// This can be between 32 and 252 bytes
// FIXME: move to 64 to align with ed25519 private key?
pub type Zip32Seed = [u8; 32];
Expand Down
36 changes: 22 additions & 14 deletions app/rust/src/zip32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,24 @@ use log::debug;
use crate::bolos::aes::AesBOLOS;
use crate::bolos::blake2b;
use crate::bolos::blake2b::{
blake2b64_with_personalization, blake2b_expand_v4, blake2b_expand_vec_two,
blake2b32_with_personalization, blake2b64_with_personalization, blake2b_expand_v4,
blake2b_expand_vec_two,
};
use crate::bolos::c_check_app_canary;
use crate::constants::{DIV_DEFAULT_LIST_LEN, DIV_SIZE, ZIP32_COIN_TYPE, ZIP32_PURPOSE};
use crate::cryptoops::bytes_to_extended;
use crate::cryptoops::extended_to_bytes;
use crate::personalization::ZIP32_SAPLING_MASTER_PERSONALIZATION;
use crate::personalization::{
ZIP32_SAPLING_FVFP_PERSONALIZATION, ZIP32_SAPLING_MASTER_PERSONALIZATION,
};
use crate::sapling::{
sapling_aknk_to_ivk, sapling_ask_to_ak, sapling_asknsk_to_ivk, sapling_nsk_to_nk,
};
use crate::types::{
diversifier_zero, AskBytes, Diversifier, DiversifierList10, DiversifierList20,
DiversifierList4, DkBytes, FullViewingKey, IvkBytes, NskBytes, OvkBytes,
SaplingExpandedSpendingKey, SaplingKeyBundle, Zip32MasterKey, Zip32MasterSpendingKey,
Zip32Path, Zip32Seed,
DiversifierList4, DkBytes, FullViewingKey, FvkTagBytes, IvkBytes, NskBytes, OvkBytes,
SaplingExpandedSpendingKey, SaplingKeyBundle, Zip32MasterChainCode, Zip32MasterKey,
Zip32MasterSpendingKey, Zip32Path, Zip32Seed,
};
use crate::zip32_extern::diversifier_is_valid;
use crate::{cryptoops, zip32};
Expand Down Expand Up @@ -318,10 +321,11 @@ fn zip32_sapling_derive_child(
}

#[inline(never)]
pub fn zip32_sapling_derive(path: &Zip32Path) -> SaplingKeyBundle {
pub fn zip32_sapling_derive(path: &Zip32Path) -> (SaplingKeyBundle, Zip32MasterChainCode, FvkTagBytes) {
// ik as in capital I (https://zips.z.cash/zip-0032#sapling-child-key-derivation)
let mut ik = zip32_master_key_i();

let mut fvfp = [0u8; 4];
let mut key_bundle_i = SaplingKeyBundle::new(
zip32_sapling_ask_m(&ik.spending_key()),
zip32_sapling_nsk_m(&ik.spending_key()),
Expand All @@ -330,11 +334,15 @@ pub fn zip32_sapling_derive(path: &Zip32Path) -> SaplingKeyBundle {
);

for path_i in path.iter().copied() {
fvfp.copy_from_slice(&blake2b32_with_personalization(
ZIP32_SAPLING_FVFP_PERSONALIZATION,
zip32_sapling_fvk(&key_bundle_i).to_bytes(),
)[0..4]);
zip32_sapling_derive_child(&mut ik, path_i, &mut key_bundle_i);
c_check_app_canary();
}

key_bundle_i
(key_bundle_i, ik.chain_code(), fvfp)
}

#[inline(never)]
Expand Down Expand Up @@ -450,7 +458,7 @@ mod tests {

with_device_seed_context(seed, || {
let path = [];
let k = zip32_sapling_derive(&path);
let k = zip32_sapling_derive(&path).0;
let fvk = zip32_sapling_fvk(&k);

assert_eq!(
Expand Down Expand Up @@ -508,7 +516,7 @@ mod tests {
with_device_seed_context(seed, || {
let path = [1];

let k = zip32_sapling_derive(&path);
let k = zip32_sapling_derive(&path).0;
let fvk = zip32_sapling_fvk(&k);

assert_eq!(
Expand Down Expand Up @@ -568,7 +576,7 @@ mod tests {
with_device_seed_context(seed, || {
let path = [1 + ZIP32_HARDENED];

let k = zip32_sapling_derive(&path);
let k = zip32_sapling_derive(&path).0;
let fvk = zip32_sapling_fvk(&k);

assert_eq!(
Expand Down Expand Up @@ -628,7 +636,7 @@ mod tests {
with_device_seed_context(seed, || {
let path = [1, 2 + ZIP32_HARDENED];

let k = zip32_sapling_derive(&path);
let k = zip32_sapling_derive(&path).0;
let fvk = zip32_sapling_fvk(&k);

assert_eq!(
Expand Down Expand Up @@ -688,7 +696,7 @@ mod tests {
with_device_seed_context(seed, || {
let path = [1 + ZIP32_HARDENED, 2 + ZIP32_HARDENED];

let k = zip32_sapling_derive(&path);
let k = zip32_sapling_derive(&path).0;
let fvk = zip32_sapling_fvk(&k);

assert_eq!(
Expand Down Expand Up @@ -745,7 +753,7 @@ mod tests {

with_device_seed_context(seed, || {
let path = [ZIP32_PURPOSE, ZIP32_COIN_TYPE, 0x8000_0001];
let k = zip32_sapling_derive(&path);
let k = zip32_sapling_derive(&path).0;
let fvk = zip32_sapling_fvk(&k);

assert_eq!(
Expand Down Expand Up @@ -787,7 +795,7 @@ mod tests {

with_device_seed_context(seed, || {
let path = [ZIP32_PURPOSE, ZIP32_COIN_TYPE, 0x8000_1000];
let k = zip32_sapling_derive(&path);
let k = zip32_sapling_derive(&path).0;
let fvk = zip32_sapling_fvk(&k);

let ivk = sapling_aknk_to_ivk(&fvk.ak(), &fvk.nk());
Expand Down
61 changes: 50 additions & 11 deletions app/rust/src/zip32_extern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use crate::sapling::{
sapling_aknk_to_ivk, sapling_ask_to_ak, sapling_asknsk_to_ivk, sapling_nsk_to_nk,
};
use crate::types::{
diversifier_zero, Diversifier, DiversifierList10, DiversifierList20, DiversifierList4,
FullViewingKey, IvkBytes, NskBytes, Zip32Seed,
diversifier_zero, Zip32MasterChainCode, Diversifier, DiversifierList10, DiversifierList20,
DiversifierList4, DkBytes, FullViewingKey, FvkTagBytes, IvkBytes, NskBytes, Zip32Seed,
};
use crate::zip32::{diversifier_group_hash_light, zip32_sapling_derive, zip32_sapling_fvk};
use crate::{sapling, zip32};
Expand All @@ -19,7 +19,7 @@ pub extern "C" fn zip32_ivk(account: u32, ivk_ptr: *mut IvkBytes) {

crate::bolos::heartbeat();

let k = zip32_sapling_derive(&path);
let k = zip32_sapling_derive(&path).0;
let ak = sapling_ask_to_ak(&k.ask());
let nk = sapling_nsk_to_nk(&k.nsk());

Expand All @@ -35,7 +35,7 @@ pub extern "C" fn diversifier_find_valid(zip32_account: u32, div_ptr: *mut Diver
let path = [ZIP32_PURPOSE, ZIP32_COIN_TYPE, zip32_account];
let div_out = unsafe { &mut *div_ptr };

let key_bundle = zip32_sapling_derive(&path);
let key_bundle = zip32_sapling_derive(&path).0;
let dk = key_bundle.dk();

let start = diversifier_zero();
Expand All @@ -50,7 +50,7 @@ pub extern "C" fn zip32_ovk(account: u32, ovk_ptr: *mut [u8; 32]) {

crate::bolos::heartbeat();

let key_bundle = zip32_sapling_derive(&path);
let key_bundle = zip32_sapling_derive(&path).0;

ovk.copy_from_slice(&key_bundle.ovk());
}
Expand All @@ -61,7 +61,7 @@ pub extern "C" fn zip32_fvk(account: u32, fvk_ptr: *mut FullViewingKey) {
let path = [ZIP32_PURPOSE, ZIP32_COIN_TYPE, account];
let fvk_out = unsafe { &mut *fvk_ptr };

let key_bundle = zip32_sapling_derive(&path);
let key_bundle = zip32_sapling_derive(&path).0;

let fvk = zip32_sapling_fvk(&key_bundle);

Expand All @@ -78,7 +78,7 @@ pub extern "C" fn zip32_child_proof_key(
let ak = unsafe { &mut *ak_ptr };
let nsk = unsafe { &mut *nsk_ptr };

let k = zip32_sapling_derive(&path);
let k = zip32_sapling_derive(&path).0;

ak.copy_from_slice(&sapling_ask_to_ak(&k.ask()));
nsk.copy_from_slice(&k.nsk());
Expand All @@ -94,7 +94,7 @@ pub extern "C" fn zip32_child_ask_nsk(
let ask = unsafe { &mut *ask_ptr };
let nsk = unsafe { &mut *nsk_ptr };

let key_bundle = zip32_sapling_derive(&path);
let key_bundle = zip32_sapling_derive(&path).0;

ask.copy_from_slice(&key_bundle.ask());
nsk.copy_from_slice(&key_bundle.nsk());
Expand All @@ -105,7 +105,7 @@ pub extern "C" fn zip32_nsk(account: u32, nsk_ptr: *mut NskBytes) {
let path = [ZIP32_PURPOSE, ZIP32_COIN_TYPE, account];
let nsk = unsafe { &mut *nsk_ptr };

let key_bundle = zip32_sapling_derive(&path);
let key_bundle = zip32_sapling_derive(&path).0;

nsk.copy_from_slice(&key_bundle.nsk());
}
Expand All @@ -122,7 +122,7 @@ pub extern "C" fn diversifier_get_list(
let start = unsafe { &*start_index };
let diversifier = unsafe { &mut *diversifier_list_ptr };

let key_bundle = zip32_sapling_derive(&path);
let key_bundle = zip32_sapling_derive(&path).0;

zip32::diversifier_get_list_large(&key_bundle.dk(), start, diversifier);
}
Expand Down Expand Up @@ -155,7 +155,7 @@ pub extern "C" fn get_pkd_from_seed(
let start = unsafe { &mut *start_diversifier };
let div_out = unsafe { &mut *div_ptr };

let key_bundle = zip32_sapling_derive(&path);
let key_bundle = zip32_sapling_derive(&path).0;
let dk = key_bundle.dk();

div_out.copy_from_slice(&zip32::diversifier_find_valid(&dk, start));
Expand Down Expand Up @@ -193,3 +193,42 @@ pub extern "C" fn diversifier_is_valid(div_ptr: *const Diversifier) -> bool {
let div = unsafe { &*div_ptr };
diversifier_group_hash_light(div)
}

#[no_mangle]
pub extern "C" fn zip32_dk(
account: u32,
dk_ptr: *mut DkBytes,
) {
let path = [ZIP32_PURPOSE, ZIP32_COIN_TYPE, account];
let dk = unsafe { &mut *dk_ptr };

let key_bundle = zip32_sapling_derive(&path).0;

dk.copy_from_slice(&key_bundle.dk());
}

#[no_mangle]
pub extern "C" fn zip32_chain_code(
account: u32,
cc_ptr: *mut Zip32MasterChainCode,
) {
let path = [ZIP32_PURPOSE, ZIP32_COIN_TYPE, account];
let cc = unsafe { &mut *cc_ptr };

let chain_code = zip32_sapling_derive(&path).1;

cc.copy_from_slice(&chain_code);
}

#[no_mangle]
pub extern "C" fn zip32_parent_fvk_tag(
account: u32,
fvk_tag_ptr: *mut FvkTagBytes,
) {
let path = [ZIP32_PURPOSE, ZIP32_COIN_TYPE, account];
let fvk_tag = unsafe { &mut *fvk_tag_ptr };

let tag = zip32_sapling_derive(&path).2;

fvk_tag.copy_from_slice(&tag);
}
16 changes: 14 additions & 2 deletions app/src/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,15 @@ static zxerr_t computeKeys(keys_t * saplingKeys) {
// Compute diversifier
diversifier_find_valid(hdPath[2], saplingKeys->diversifier);

// Compute dk
zip32_dk(hdPath[2], saplingKeys->dk);

// Compute chain code
zip32_chain_code(hdPath[2], saplingKeys->chain_code);

// Compute parent full viewing key tag
zip32_parent_fvk_tag(hdPath[2], saplingKeys->parent_fvk_tag);

// Compute address
get_pkd(hdPath[2], saplingKeys->diversifier, saplingKeys->address);

Expand All @@ -519,13 +528,16 @@ __Z_INLINE zxerr_t copyKeys(keys_t *saplingKeys, key_kind_e requestedKeys, uint8
break;

case ViewKeys:
if (outputLen < 4 * KEY_LENGTH) {
if (outputLen < 6 * KEY_LENGTH + TAG_LENGTH) {
return zxerr_buffer_too_small;
}
memcpy(output, saplingKeys->ak, KEY_LENGTH);
memcpy(output + KEY_LENGTH, saplingKeys->nk, KEY_LENGTH);
memcpy(output + 2 * KEY_LENGTH, saplingKeys->ovk, KEY_LENGTH);
memcpy(output + 3 * KEY_LENGTH, saplingKeys->ivk, KEY_LENGTH);
memcpy(output + 4 * KEY_LENGTH, saplingKeys->dk, KEY_LENGTH);
memcpy(output + 5 * KEY_LENGTH, saplingKeys->chain_code, KEY_LENGTH);
memcpy(output + 6 * KEY_LENGTH, saplingKeys->parent_fvk_tag, TAG_LENGTH);
break;

case ProofGenerationKey:
Expand Down Expand Up @@ -604,7 +616,7 @@ zxerr_t crypto_fillMASP(uint8_t *buffer, uint16_t bufferLen, uint16_t *cmdRespon
break;

case ViewKeys:
*cmdResponseLen = 4 * KEY_LENGTH;
*cmdResponseLen = 6 * KEY_LENGTH + TAG_LENGTH;
break;

case ProofGenerationKey:
Expand Down
6 changes: 6 additions & 0 deletions app/src/keys_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ typedef enum {

#define RNG_LEN 80
#define KEY_LENGTH 32
#define TAG_LENGTH 4
#define ASSET_IDENTIFIER_LENGTH 32
#define EXTENDED_KEY_LENGTH 64
#define DIVERSIFIER_LENGTH 11
Expand All @@ -45,9 +46,11 @@ typedef uint8_t ak_t[KEY_LENGTH];
typedef uint8_t nk_t[KEY_LENGTH];

typedef uint8_t dk_t[KEY_LENGTH];
typedef uint8_t chain_code_t[KEY_LENGTH];
typedef uint8_t ivk_t[KEY_LENGTH];
typedef uint8_t ovk_t[KEY_LENGTH];
typedef uint8_t d_t[DIVERSIFIER_LENGTH];
typedef uint8_t fvk_tag_t[TAG_LENGTH];

typedef uint8_t public_address_t[KEY_LENGTH];

Expand All @@ -59,6 +62,9 @@ typedef struct {
ivk_t ivk;
ovk_t ovk;
d_t diversifier;
dk_t dk;
chain_code_t chain_code;
fvk_tag_t parent_fvk_tag;
public_address_t address;
} keys_t;

Expand Down
10 changes: 8 additions & 2 deletions rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use params::{
InstructionCode, KeyResponse, NamadaKeys, ADDRESS_LEN, CLA, ED25519_PUBKEY_LEN,
PK_LEN_PLUS_TAG, SIG_LEN_PLUS_TAG,
};
use params::{KEY_LEN, SALT_LEN};
use params::{KEY_LEN, SALT_LEN, TAG_LEN};
use utils::{
ResponseAddress, ResponseGetConvertRandomness, ResponseGetOutputRandomness,
ResponseGetSpendRandomness, ResponseMaspSign, ResponseProofGenKey, ResponsePubAddress,
Expand Down Expand Up @@ -371,11 +371,17 @@ where
NamadaKeys::ViewKey => {
let (view_key, rest) = response_data.split_at(2 * KEY_LEN);
let (ovk, rest) = rest.split_at(KEY_LEN);
let (ivk, _) = rest.split_at(KEY_LEN);
let (ivk, rest) = rest.split_at(KEY_LEN);
let (dk, rest) = rest.split_at(KEY_LEN);
let (chain_code, rest) = rest.split_at(KEY_LEN);
let (parent_fvk_tag, _) = rest.split_at(TAG_LEN);
Ok(KeyResponse::ViewKey(ResponseViewKey {
view_key: view_key.try_into().unwrap(),
ovk: ovk.try_into().unwrap(),
ivk: ivk.try_into().unwrap(),
dk: dk.try_into().unwrap(),
chain_code: chain_code.try_into().unwrap(),
parent_fvk_tag: parent_fvk_tag.try_into().unwrap(),
}))
}
NamadaKeys::ProofGenerationKey => {
Expand Down
2 changes: 2 additions & 0 deletions rs/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub const CLA: u8 = 0x57;

/// MASP keys len
pub const KEY_LEN: usize = 32;
/// MASP tag length
pub const TAG_LEN: usize = 4;
/// Public Key Length
pub const ED25519_PUBKEY_LEN: usize = 32;
/// Public Key + Tag Length
Expand Down
Loading

0 comments on commit ef24321

Please sign in to comment.