Add zeroize crate and implement zeroing of sensitive data
What changed, and why it matters
This commit is a defensive security hardening patch for the Keystone 3 hardware wallet firmware. It adds the `zeroize` Rust crate and explicitly clears sensitive memory buffers (mnemonics, seeds, passwords, RSA seeds, entropy, SLIP39 shares) after use. It also replaces many unsafe `strcpy`/`strcat`/`memcpy` calls with safer bounded versions, removes several `unwrap()` panic points in Rust FFI code, and tightens error handling in wallet creation and recovery flows. The changes reduce the risk that secret material remains in RAM after operations, and reduce the chance that malformed input crashes the device or leaks secrets through panic paths.
Treat this as a security hardening patch and include it in the next firmware release. Review that all newly introduced `ASSERT` calls do not create denial-of-service vectors on benign SE communication glitches. Verify that `zeroize` is configured without std where needed and that compiler optimizations do not elide the new `memset_s`/zeroize calls. Continue auditing remaining C code for additional unsafe buffer operations and missing secret clearing.
Security signals we found
Sensitive memory zeroization added for seeds, mnemonics, passwords, RSA seeds, entropy, and SLIP39 shares
Unsafe C string/buffer operations replaced with bounded _s variants
Rust FFI panic paths removed and replaced with error-return paths in arweave module
Input validation added for TON mnemonic word count, password length, SLIP39 parameters, dice-roll characters
Error handling tightened in entropy generation, mnemonic generation, and account creation flows
SE operation results now asserted instead of silently returned
Dead/commented code removed from slip39 pbkdf2 implementation
Evidence from the diff
The patch is a broad hardening change across Rust and C firmware code. Key technical changes: (1) Adds zeroize dependency and uses Zeroize on TON seed and RSA seed in Rust. (2) Replaces many memset/memcpy/strcpy/strcat calls with memset_s/memcpy_s/strcpy_s/strcat_s in C, especially in secret_cache.c, slip39.c, keystore.c, hash_and_salt.c, and UI code. (3) Adds explicit clearing of entropy, seed, mnemonic, passwordHash, accountSecret, slip39Ems, and temporary buffers in multiple functions. (4) Converts several Rust extern "C" functions from safe-but-unsafe internally to unsafe extern "C" and replaces raw pointer slice::from_raw_parts with extract_array!, and removes .unwrap() in favor of error-return paths in arweave/mod.rs. (5) Adds bounds/validity checks for TON mnemonic word counts, password length, SLIP39 parameters, and dice-roll input characters. (6) Replaces assert() with ASSERT() macro in several places and adds ASSERT on SE operation results. (7) Fixes a typo rename ENTORPY_TYPE_DICE_ROLLS to ENTROPY_TYPE_DICE_ROLLS. (8) Adds new failure UI signals for mnemonic generation and RSA key write failures. No CVE or vendor security advisory is present in the supplied materials.
Changed components
rust/apps/ton/src/mnemonic.rsrust/keystore/src/algorithms/rsa/mod.rsrust/rust_c/src/arweave/mod.rssrc/crypto/account_public_info.csrc/crypto/bips/bip39.csrc/crypto/secret_cache.csrc/crypto/slip39/slip39.csrc/crypto/slip39/slip39.hsrc/crypto/slip39/trezor-crypto/pbkdf2.csrc/crypto/utils/hash_and_salt.csrc/hardware_interface/se_interface.csrc/managers/keystore.csrc/managers/keystore.hsrc/ui/gui_components/gui_mnemonic_input.csrc/ui/gui_model/gui_model.csrc/ui/gui_views/gui_views.hsrc/ui/gui_widgets/gui_create_wallet_widgets.hsrc/ui/gui_widgets/gui_dice_rolls_widgets.csrc/ui/gui_widgets/gui_forget_pass_widgets.csrc/ui/gui_widgets/gui_forget_pass_widgets.hInspect captured patch +726 / −495
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index f8fb87e..51cbf68 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -403,6 +403,7 @@ dependencies = [
"sha2 0.10.9",
"thiserror-core",
"urlencoding",
+ "zeroize",
]
[[package]]
@@ -2463,6 +2464,7 @@ dependencies = [
"sha2 0.10.9",
"thiserror-core",
"zcash_vendor",
+ "zeroize",
]
[[package]]
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 05be213..2a5833c 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -115,4 +115,5 @@ num-traits = { version = "0.2.19", default-features = false }
blake2b_simd = { version = "1.0.2", default-features = false }
getrandom = "0.2"
minicbor = { version = "0.19", features = ["alloc"] }
+zeroize = { version = "^1.5", default-features = false }
# third party dependencies end
diff --git a/rust/apps/ton/Cargo.toml b/rust/apps/ton/Cargo.toml
index 43c7047..50e2f15 100644
--- a/rust/apps/ton/Cargo.toml
+++ b/rust/apps/ton/Cargo.toml
@@ -25,6 +25,7 @@ serde = { workspace = true }
rust_tools = { workspace = true }
itertools = { workspace = true }
thiserror = { workspace = true }
+zeroize = { workspace = true }
[dev-dependencies]
diff --git a/rust/apps/ton/src/mnemonic.rs b/rust/apps/ton/src/mnemonic.rs
index 2dc323f..c6deb16 100644
--- a/rust/apps/ton/src/mnemonic.rs
+++ b/rust/apps/ton/src/mnemonic.rs
@@ -8,8 +8,11 @@ use cryptoxide::hmac::Hmac;
use cryptoxide::mac::Mac;
use cryptoxide::pbkdf2::pbkdf2;
use cryptoxide::sha2::Sha512;
+use zeroize::Zeroize;
const PBKDF_ITERATIONS: u32 = 100000;
+const TON_MNEMONIC_24_WORDS: usize = 24;
+const TON_MNEMONIC_12_WORDS: usize = 12;
pub fn ton_mnemonic_to_entropy(
normalized_words: &Vec<String>,
@@ -26,12 +29,17 @@ pub fn ton_mnemonic_validate(
normalized_words: &Vec<String>,
password: &Option<String>,
) -> Result<()> {
+ if normalized_words.len() != TON_MNEMONIC_24_WORDS && normalized_words.len() != TON_MNEMONIC_12_WORDS {
+ return Err(MnemonicError::UnexpectedWordCount(normalized_words.len()).into());
+ }
+
let entropy = ton_mnemonic_to_entropy(normalized_words, &None);
+ let mut seed: [u8; 64] = [0; 64];
match password {
Some(s) if !s.is_empty() => {
- let mut seed: [u8; 64] = [0; 64];
pbkdf2_sha512(&entropy, "TON fast seed version".as_bytes(), 1, &mut seed);
if seed[0] != 1 {
+ seed.zeroize();
return Err(MnemonicError::InvalidFirstByte(seed[0]).into());
}
let entropy = ton_mnemonic_to_entropy(normalized_words, password);
@@ -42,11 +50,11 @@ pub fn ton_mnemonic_validate(
&mut seed,
);
if seed[0] == 0 {
+ seed.zeroize();
return Err(MnemonicError::InvalidFirstByte(seed[0]).into());
}
}
_ => {
- let mut seed: [u8; 64] = [0; 64];
pbkdf2_sha512(
&entropy,
"TON seed version".as_bytes(),
@@ -54,10 +62,12 @@ pub fn ton_mnemonic_validate(
&mut seed,
);
if seed[0] != 0 {
+ seed.zeroize();
return Err(MnemonicError::InvalidPasswordlessMenmonicFirstByte(seed[0]).into());
}
}
}
+ seed.zeroize();
Ok(())
}
@@ -77,7 +87,7 @@ pub fn ton_mnemonic_to_master_seed(
words: Vec<String>,
password: Option<String>,
) -> Result<[u8; 64]> {
- if words.len() != 24 {
+ if words.len() != TON_MNEMONIC_24_WORDS && words.len() != TON_MNEMONIC_12_WORDS {
return Err(MnemonicError::UnexpectedWordCount(words.len()).into());
}
let normalized_words: Vec<String> = words.iter().map(|w| w.trim().to_lowercase()).collect();
diff --git a/rust/keystore/Cargo.toml b/rust/keystore/Cargo.toml
index 25b5059..c186779 100644
--- a/rust/keystore/Cargo.toml
+++ b/rust/keystore/Cargo.toml
@@ -21,6 +21,7 @@ bitcoin = { workspace = true }
hex = { workspace = true }
rsa = { workspace = true }
zcash_vendor = { workspace = true }
+zeroize = { workspace = true }
[features]
default = ["std"]
diff --git a/rust/keystore/src/algorithms/rsa/mod.rs b/rust/keystore/src/algorithms/rsa/mod.rs
index 114ffff..24e1069 100644
--- a/rust/keystore/src/algorithms/rsa/mod.rs
+++ b/rust/keystore/src/algorithms/rsa/mod.rs
@@ -5,6 +5,7 @@ use alloc::vec::Vec;
use arrayref::array_ref;
use rand_chacha::ChaCha20Rng;
use rand_core::{OsRng, SeedableRng};
+use zeroize::Zeroize;
use num_bigint_dig::traits::ModInverse;
use num_bigint_dig::BigUint;
@@ -33,10 +34,11 @@ fn get_rsa_seed(seed: &[u8]) -> Result<[u8; 32]> {
}
pub fn get_rsa_secret_from_seed(seed: &[u8]) -> Result<RsaPrivateKey> {
- let rsa_seed = get_rsa_seed(seed)?;
+ let mut rsa_seed = get_rsa_seed(seed)?;
let mut rng = ChaCha20Rng::from_seed(rsa_seed);
- let private_key = RsaPrivateKey::new(&mut rng, MODULUS_LENGTH).map_err(|_| {
- KeystoreError::GenerateSigningKeyError("generate rsa private key failed".to_string())
+ rsa_seed.zeroize();
+ let private_key = RsaPrivateKey::new(&mut rng, MODULUS_LENGTH).map_err(|e| {
+ KeystoreError::GenerateSigningKeyError(format!("generate rsa private key failed: {}", e))
})?;
Ok(private_key)
}
diff --git a/rust/rust_c/src/arweave/mod.rs b/rust/rust_c/src/arweave/mod.rs
index d91bb38..1d23656 100644
--- a/rust/rust_c/src/arweave/mod.rs
+++ b/rust/rust_c/src/arweave/mod.rs
@@ -28,26 +28,40 @@ use ur_registry::arweave::arweave_sign_request::{ArweaveSignRequest, SaltLen, Si
use ur_registry::arweave::arweave_signature::ArweaveSignature;
use ur_registry::traits::RegistryItem;
-fn generate_aes_key_iv(seed: &[u8]) -> ([u8; 32], [u8; 16]) {
+fn generate_aes_key_iv(seed: &[u8]) -> Result<([u8; 32], [u8; 16]), RustCError> {
// The number 1557192335 is derived from the ASCII representation of "keystone" hashed with SHA-256, taking the first 32 bits with the highest bit set to 0.
- let key_path = "m/44'/1557192335'/0'/0'/0'".to_string();
- let iv_path = "m/44'/1557192335'/0'/1'/0'".to_string();
- let key = get_private_key_by_seed(seed, &key_path).unwrap();
+ const KEY_PATH: &str = "m/44'/1557192335'/0'/0'/0'";
+ const IV_PATH: &str = "m/44'/1557192335'/0'/1'/0'";
+
+ let key = get_private_key_by_seed(seed, &KEY_PATH.to_string())
+ .map_err(|_| RustCError::InvalidData("get private key error".to_string()))?;
let (_, key_bytes) = cryptoxide::ed25519::keypair(&key);
- let iv = get_private_key_by_seed(seed, &iv_path).unwrap();
- let (_, iv) = cryptoxide::ed25519::keypair(&iv);
- let mut iv_bytes: [u8; 16] = [0; 16];
- iv_bytes.copy_from_slice(&iv[..16]);
- (key_bytes, iv_bytes)
+
+ let ivk = get_private_key_by_seed(seed, &IV_PATH.to_string())
+ .map_err(|_| RustCError::InvalidData("get private key error".to_string()))?;
+ let (_, iv_pub) = cryptoxide::ed25519::keypair(&ivk);
+ if iv_pub.len() < 16 {
+ return Err(RustCError::InvalidData("invalid iv pub key".to_string()));
+ }
+
+ let mut iv = [0u8; 16];
+ iv.copy_from_slice(&iv_pub[..16]);
+ Ok((key_bytes, iv))
}
#[no_mangle]
-pub extern "C" fn generate_arweave_secret(
+pub unsafe extern "C" fn generate_arweave_secret(
seed: PtrBytes,
seed_len: u32,
) -> *mut SimpleResponse<u8> {
- let seed = unsafe { slice::from_raw_parts(seed, seed_len as usize) };
- let secret = generate_secret(seed).unwrap();
+ let seed = extract_array!(seed, u8, seed_len as usize);
+ let secret = match generate_secret(seed) {
+ Ok(s) => s,
+ Err(_) => {
+ return SimpleResponse::from(RustCError::InvalidData("get secret error".to_string()))
+ .simple_c_ptr()
+ }
+ };
let mut secret_bytes: [u8; 512] = [0; 512];
secret_bytes[..256].copy_from_slice(&secret.primes()[0].to_bytes_be());
secret_bytes[256..].copy_from_slice(&secret.primes()[1].to_bytes_be());
@@ -56,55 +70,76 @@ pub extern "C" fn generate_arweave_secret(
}
#[no_mangle]
-pub extern "C" fn generate_arweave_public_key_from_primes(
+pub unsafe extern "C" fn generate_arweave_public_key_from_primes(
p: PtrBytes,
p_len: u32,
q: PtrBytes,
q_len: u32,
) -> *mut SimpleResponse<u8> {
- let p = unsafe { slice::from_raw_parts(p, p_len as usize) };
- let q = unsafe { slice::from_raw_parts(q, q_len as usize) };
- let public = generate_public_key_from_primes(p, q).unwrap();
- SimpleResponse::success(Box::into_raw(Box::new(public)) as *mut u8).simple_c_ptr()
+ let p = extract_array!(p, u8, p_len as usize);
+ let q = extract_array!(q, u8, q_len as usize);
+ match generate_public_key_from_primes(p, q) {
+ Ok(public) => {
+ SimpleResponse::success(Box::into_raw(Box::new(public)) as *mut u8).simple_c_ptr()
+ }
+ Err(e) => SimpleResponse::from(e).simple_c_ptr(),
+ }
}
#[no_mangle]
-pub extern "C" fn generate_rsa_public_key(
+pub unsafe extern "C" fn generate_rsa_public_key(
p: PtrBytes,
p_len: u32,
q: PtrBytes,
q_len: u32,
) -> *mut SimpleResponse<c_char> {
- let p = unsafe { slice::from_raw_parts(p, p_len as usize) };
- let q = unsafe { slice::from_raw_parts(q, q_len as usize) };
- let public = generate_public_key_from_primes(p, q).unwrap();
- SimpleResponse::success(convert_c_char(hex::encode(public))).simple_c_ptr()
+ let p = extract_array!(p, u8, p_len as usize);
+ let q = extract_array!(q, u8, q_len as usize);
+ match generate_public_key_from_primes(p, q) {
+ Ok(public) => SimpleResponse::success(convert_c_char(hex::encode(public))).simple_c_ptr(),
+ Err(e) => SimpleResponse::from(e).simple_c_ptr(),
+ }
}
#[no_mangle]
-pub extern "C" fn aes256_encrypt_primes(
+pub unsafe extern "C" fn aes256_encrypt_primes(
seed: PtrBytes,
seed_len: u32,
data: PtrBytes,
) -> *mut SimpleResponse<u8> {
- let seed = unsafe { slice::from_raw_parts(seed, seed_len as usize) };
- let data = unsafe { slice::from_raw_parts(data, 512) };
- let (key, iv) = generate_aes_key_iv(seed);
- let encrypted_data = aes256_encrypt(&key, &iv, data).unwrap();
+ let seed = extract_array!(seed, u8, seed_len as usize);
+ let data = extract_array!(data, u8, 512);
+ let (key, iv) = match generate_aes_key_iv(seed) {
+ Ok(v) => v,
+ Err(_) => {
+ return SimpleResponse::from(RustCError::InvalidData("get aes key error".to_string()))
+ .simple_c_ptr()
+ }
+ };
+ let encrypted_data = match aes256_encrypt(&key, &iv, data) {
+ Ok(v) => v,
+ Err(e) => return SimpleResponse::from(e).simple_c_ptr(),
+ };
let mut result_bytes: [u8; 528] = [0; 528];
result_bytes.copy_from_slice(&encrypted_data);
SimpleResponse::success(Box::into_raw(Box::new(result_bytes)) as *mut u8).simple_c_ptr()
}
#[no_mangle]
-pub extern "C" fn aes256_decrypt_primes(
+pub unsafe extern "C" fn aes256_decrypt_primes(
seed: PtrBytes,
seed_len: u32,
data: PtrBytes,
) -> *mut SimpleResponse<u8> {
- let seed = unsafe { slice::from_raw_parts(seed, seed_len as usize) };
- let data = unsafe { slice::from_raw_parts(data, 528) };
- let (key, iv) = generate_aes_key_iv(seed);
+ let seed = extract_array!(seed, u8, seed_len as usize);
+ let data = extract_array!(data, u8, 528);
+ let (key, iv) = match generate_aes_key_iv(seed) {
+ Ok(v) => v,
+ Err(_) => {
+ return SimpleResponse::from(RustCError::InvalidData("get aes key error".to_string()))
+ .simple_c_ptr()
+ }
+ };
match aes256_decrypt(&key, &iv, data) {
Ok(decrypted_data) => {
if decrypted_data.len() != 512 {
@@ -122,8 +157,17 @@ pub extern "C" fn aes256_decrypt_primes(
#[no_mangle]
pub unsafe extern "C" fn arweave_get_address(xpub: PtrString) -> *mut SimpleResponse<c_char> {
let xpub = recover_c_char(xpub);
- let address = app_arweave::generate_address(hex::decode(xpub).unwrap()).unwrap();
- SimpleResponse::success(convert_c_char(address)).simple_c_ptr()
+ let bytes = match hex::decode(xpub) {
+ Ok(v) => v,
+ Err(_) => {
+ return SimpleResponse::from(RustCError::InvalidData("invalid hex".to_string()))
+ .simple_c_ptr()
+ }
+ };
+ match app_arweave::generate_address(bytes) {
+ Ok(address) => SimpleResponse::success(convert_c_char(address)).simple_c_ptr(),
+ Err(e) => SimpleResponse::from(e).simple_c_ptr(),
+ }
}
#[no_mangle]
@@ -188,9 +232,9 @@ pub unsafe extern "C" fn ar_message_parse(
}
fn get_value(raw_json: &Value, key: &str) -> String {
- raw_json["formatted_json"][key.to_string()]
+ raw_json["formatted_json"][key]
.as_str()
- .unwrap()
+ .unwrap_or("")
.to_string()
}
@@ -198,8 +242,16 @@ fn get_value(raw_json: &Value, key: &str) -> String {
pub unsafe extern "C" fn ar_parse(ptr: PtrUR) -> PtrT<TransactionParseResult<DisplayArweaveTx>> {
let sign_request = extract_ptr_with_type!(ptr, ArweaveSignRequest);
let sign_data = sign_request.get_sign_data();
- let raw_tx = parse(&sign_data).unwrap();
- let raw_json: Value = serde_json::from_str(&raw_tx).unwrap();
+ let raw_tx = match parse(&sign_data) {
+ Ok(v) => v,
+ Err(e) => return TransactionParseResult::from(e).c_ptr(),
+ };
+ let raw_json: Value = match serde_json::from_str(&raw_tx) {
+ Ok(v) => v,
+ Err(e) => {
+ return TransactionParseResult::from(RustCError::InvalidData(e.to_string())).c_ptr()
+ }
+ };
let value = get_value(&raw_json, "quantity");
let fee = get_value(&raw_json, "reward");
let from = get_value(&raw_json, "from");
@@ -222,11 +274,22 @@ unsafe fn parse_sign_data(ptr: PtrUR) -> Result<Vec<u8>, ArweaveError> {
match sign_request.get_sign_type() {
SignType::Transaction => {
let raw_tx = parse(&sign_data)?;
- let raw_json: Value = serde_json::from_str(&raw_tx).unwrap();
- let signature_data = raw_json["formatted_json"]["signature_data"]
- .as_str()
- .unwrap();
- let signature_data = hex::decode(signature_data).unwrap();
+ let raw_json: Value = match serde_json::from_str(&raw_tx) {
+ Ok(v) => v,
+ Err(e) => return Err(ArweaveError::KeystoreError(e.to_string())),
+ };
+ let signature_data = match raw_json["formatted_json"]["signature_data"].as_str() {
+ Some(s) => s,
+ None => {
+ return Err(ArweaveError::KeystoreError(
+ "missing signature_data".to_string(),
+ ))
+ }
+ };
+ let signature_data = match hex::decode(signature_data) {
+ Ok(v) => v,
+ Err(e) => return Err(ArweaveError::KeystoreError(e.to_string())),
+ };
Ok(signature_data)
}
SignType::DataItem => {
@@ -317,7 +380,7 @@ mod tests {
let data = hex::decode("cfbe18586b3ed63813e05ba65f606a6bf936c358285162dae3c123fb657f3327284ceacada59cf64c1bf9b8f55a96575815b6904dda565a786a7222d563f3e70729a3cc6d46a3916083b6dd4c97ab67a599a8d5b382a6d7d4ea04bedb37fa8856bdcc871ca1a6ed0916de02eb6b200ca150ed730cbb73ce31eac3f84a3e10e208195df9c33d933bebb64a42ccec3744dd9a9fbde484a993ac17cb027acbc0c2948af4a3c3cce1f64ed724fbcc9360cadfa3bbcc73f2798ea95ed6994a7c9c76ae112a96f75040dcceabf49b6546a0ca869a08a58a9befcc82fc7d973cb8e8a0c8f9659c66b3de614d5ff531a130a1d4e3e06a3c4f8957b612913d9597f6a12a5f794c6cd8a066b819c537fd9cc2a79de7d39069d9fd1ad79652e199845ae4cea68350c06e0af43bd71b302a1d578a9df7c9a351d5d23d5104deef986f326cac564628f4e8fbc2b83be05b288434eb99cfdf0e57b755714b93b16ee1eab7ae2cb4cdec24ec350fa8a2d20a71feb3a7b1ceaecda03479cbd1a1614c64bc2e4d09586204dde7525a077a00632c71fa1771a8f8164beed3d02bb4f47a53733a9540b4a1cd0e7aabe09b1d3b1d331004533aaac75e48e12ba3b1bc2f6e5fec9fb6942da3d113eeb8ac3b67f6ca67fc4f5be98d19f8551ab25af29ac0c0ba5790d930515a76878bf2dbd34653b3311ce2fdcd4ea74ffe1cea687bf45ee7baab1987aaf").unwrap();
let encoded_data_test = hex::decode("85113aedb4f44eb56cf113557fecf91afe908a9869cca1ab4c22b50eb01fcb7081e6d687533617d9451c062f15ab32fac5558fe4f56e4fd66415cb2904e82fd207f206fd2067c4c553b05bdd663523209e1940e8ffdee3621c2c79ae0e3c1eece83824f22565eb8112063dc23d0f0609ef4669c59ae117c0c4fb2136bc74d98f29e7903d59e520106f4d0281025afeba9ea2ebfdde99d7ac8bdb22eedc569e867f18629a5639fd51d46b0caa798ee6b84c20e4c15a112bc7005a433bc8850d83df2ca10588930b8151200fe68c43183b16a64d76bd4b46c429bf3e45f954efa28040e3edfaf942f7ddcdf573c10f0952ca0f7b8d932f5ddf6f5ce4d0092e399dfa485cfdd19fcd118bb814d6d321bd114a1e8c2314926c41b1d0fcaec33222c53b02b24081dce8cbe25154f9d9ad195955ab7dada82ca3642afc39a746dcb0fa2647334533272d2abe6d99f400451a2b1f1dfc6341b45fedf0d68abaa210c0203233fb0aa7e6503d3c6e385c64299277005316f8bca38fc1bc8d82b2575ff80d24d8ed2efd07179219143c3acba5a2df1778228aaeb2f44d5f03b25cdc51c08e76039dae0b33f1aa23f48a27a6a5342259e5b90ee3927d07e9982ac46ebe66fe416d7745a3ba15931aa7f1ce0a2ef0a1aee9f2f6d3bf1b7485889d55305e7ccbbc5b0fc33a8843f4c1a3518c659275009c47fb2d3cd53bd4c9feba630816bc9f96101d9cd94087d7392674b735d379c2").unwrap();
assert_eq!(encoded_data_test.len(), 528);
- let (key, iv) = generate_aes_key_iv(&seed);
+ let (key, iv) = generate_aes_key_iv(&seed).unwrap();
let encrypted_data = aes256_encrypt(&key, &iv, &data).unwrap();
let decrypted_data = aes256_decrypt(&key, &iv, &encrypted_data).unwrap();
assert_eq!(data, decrypted_data);
diff --git a/src/crypto/account_public_info.c b/src/crypto/account_public_info.c
index 6a04ef9..c9e08b8 100644
--- a/src/crypto/account_public_info.c
+++ b/src/crypto/account_public_info.c
@@ -884,9 +884,19 @@ int32_t AccountPublicSavePublicInfo(uint8_t accountIndex, const char *password,
// should setup ADA for bip39 wallet;
if (isBip39) {
char *mnemonic = NULL;
- bip39_mnemonic_from_bytes(NULL, entropy, entropyLen, &mnemonic);
+ ret = bip39_mnemonic_from_bytes(NULL, entropy, entropyLen, &mnemonic);
+ if (ret != SUCCESS_CODE) {
+ printf("get mnemonic error\r\n");
+ if (mnemonic != NULL) {
+ memset_s(mnemonic, MNEMONIC_MAX_LEN, 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
+ SRAM_FREE(mnemonic);
+ }
+ ret = ERR_GENERAL_FAIL;
+ break;
+ }
cip3_response = get_icarus_master_key(entropy, entropyLen, GetPassphrase(accountIndex));
ledger_bitbox02_response = get_ledger_bitbox02_master_key(mnemonic, GetPassphrase(accountIndex));
+ SRAM_FREE(mnemonic);
CHECK_AND_FREE_XPUB(cip3_response);
CHECK_AND_FREE_XPUB(ledger_bitbox02_response);
icarusMasterKey = cip3_response->data;
@@ -1080,9 +1090,18 @@ int32_t TempAccountPublicInfo(uint8_t accountIndex, const char *password, bool s
if (!isSlip39) {
do {
char *mnemonic = NULL;
- bip39_mnemonic_from_bytes(NULL, entropy, entropyLen, &mnemonic);
+ ret = bip39_mnemonic_from_bytes(NULL, entropy, entropyLen, &mnemonic);
+ if (ret != SUCCESS_CODE) {
+ printf("get mnemonic error\r\n");
+ if (mnemonic != NULL) {
+ memset_s(mnemonic, MNEMONIC_MAX_LEN, 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
+ SRAM_FREE(mnemonic);
+ }
+ break;
+ }
cip3_response = get_icarus_master_key(entropy, entropyLen, GetPassphrase(accountIndex));
ledger_bitbox02_response = get_ledger_bitbox02_master_key(mnemonic, GetPassphrase(accountIndex));
+ SRAM_FREE(mnemonic);
CHECK_AND_FREE_XPUB(cip3_response);
CHECK_AND_FREE_XPUB(ledger_bitbox02_response);
icarusMasterKey = cip3_response->data;
diff --git a/src/crypto/bips/bip39.c b/src/crypto/bips/bip39.c
index 6f36f75..130da1c 100644
--- a/src/crypto/bips/bip39.c
+++ b/src/crypto/bips/bip39.c
@@ -22,17 +22,6 @@ static const struct {
{ "en", &en_words},
};
-int bip39_get_languages(char **output)
-{
- if (!output)
- return -2;
-
- *output = SRAM_MALLOC(strlen("en") + 1);
- strcpy(*output, "en");
-//#endif
- return *output ? SUCCESS_CODE : -1;
-}
-
int bip39_get_wordlist(const char *lang, struct words **output)
{
size_t i;
diff --git a/src/crypto/secret_cache.c b/src/crypto/secret_cache.c
index 151ffa3..30e39cc 100644
--- a/src/crypto/secret_cache.c
+++ b/src/crypto/secret_cache.c
@@ -64,7 +64,7 @@ void SecretCacheSetPassword(char *password)
SRAM_FREE(g_passwordCache);
}
g_passwordCache = SRAM_MALLOC(strnlen_s(password, PASSWORD_MAX_LEN) + 1);
- strcpy(g_passwordCache, password);
+ strcpy_s(g_passwordCache, PASSWORD_MAX_LEN, password);
}
char *SecretCacheGetPassword(void)
@@ -78,7 +78,7 @@ void SecretCacheSetPassphrase(const char *passPhrase)
SRAM_FREE(g_passphraseCache);
}
g_passphraseCache = SRAM_MALLOC(strnlen_s(passPhrase, PASSPHRASE_MAX_LEN) + 1);
- strcpy(g_passphraseCache, passPhrase);
+ strcpy_s(g_passphraseCache, PASSPHRASE_MAX_LEN, passPhrase);
}
char *SecretCacheGetPassphrase(void)
@@ -92,7 +92,7 @@ void SecretCacheSetNewPassword(char *password)
SRAM_FREE(g_newPasswordCache);
}
g_newPasswordCache = SRAM_MALLOC(strnlen_s(password, PASSWORD_MAX_LEN) + 1);
- strcpy(g_newPasswordCache, password);
+ strcpy_s(g_newPasswordCache, PASSWORD_MAX_LEN, password);
}
char *SecretCacheGetNewPassword(void)
@@ -168,7 +168,7 @@ void SecretCacheSetMnemonic(char *mnemonic)
SRAM_FREE(g_mnemonicCache);
}
g_mnemonicCache = SRAM_MALLOC(strnlen_s(mnemonic, MNEMONIC_MAX_LEN) + 1);
- strcpy(g_mnemonicCache, mnemonic);
+ strcpy_s(g_mnemonicCache, MNEMONIC_MAX_LEN, mnemonic);
}
char *SecretCacheGetMnemonic(void)
diff --git a/src/crypto/slip39/slip39.c b/src/crypto/slip39/slip39.c
index 4707952..a4da2e2 100644
--- a/src/crypto/slip39/slip39.c
+++ b/src/crypto/slip39/slip39.c
@@ -279,8 +279,8 @@ static int _get_salt(uint16_t id, bool eb, uint8_t *salt)
return 0;
} else {
if (salt != NULL) {
- memset(salt, 0, SHAMIR_SALT_HEAD_LEN);
- memcpy(salt, SHAMIR_SALT_HEAD, strlen(SHAMIR_SALT_HEAD));
+ memset_s(salt, SHAMIR_SALT_HEAD_LEN, 0, SHAMIR_SALT_HEAD_LEN);
+ memcpy_s(salt, SHAMIR_SALT_HEAD_LEN, SHAMIR_SALT_HEAD, strnlen_s(SHAMIR_SALT_HEAD, SHAMIR_SALT_HEAD_LEN));
salt[6] = id >> 8;
salt[7] = id & 0xFF;
}
@@ -334,7 +334,7 @@ int interpolate(const uint8_t* xi, const uint8_t **yi, uint8_t n, uint8_t* resul
for (i = 0; i < threshold; i++) {
if (n == xi[i]) {
- memcpy(result, yi[i], len);
+ memcpy_s(result, len, yi[i], len);
return SLIP39_OK;
}
}
@@ -386,7 +386,7 @@ int SplitSecret(uint8_t count, uint8_t threshold, uint8_t *enMasterSecret, uint8
// If T is 1, then let yi = S for all i, 1 ≤ i ≤ N, and return.
if (count == 1) {
- memcpy(groupsBuff, enMasterSecret, enMasterSecretLen);
+ memcpy_s(groupsBuff, enMasterSecretLen, enMasterSecret, enMasterSecretLen);
return SLIP39_OK;
}
@@ -404,12 +404,12 @@ int SplitSecret(uint8_t count, uint8_t threshold, uint8_t *enMasterSecret, uint8
tempShare[threshold - 2] = (uint8_t *)(pool + ((threshold - 2) * enMasterSecretLen));
random_buffer(&tempShare[threshold - 2][4], enMasterSecretLen - 4);
hmac_sha256(&tempShare[threshold - 2][4], enMasterSecretLen - 4, enMasterSecret, enMasterSecretLen, sha256Hash);
- memcpy(tempShare[threshold - 2], sha256Hash, 4);
+ memcpy_s(tempShare[threshold - 2], 4, sha256Hash, 4);
// SECRET_INDEX
xi[threshold - 1] = SECRET_INDEX;
tempShare[threshold - 1] = (uint8_t *)(pool + ((threshold - 1) * enMasterSecretLen));
- memcpy(tempShare[threshold - 1], enMasterSecret, enMasterSecretLen);
+ memcpy_s(tempShare[threshold - 1], enMasterSecretLen, enMasterSecret, enMasterSecretLen);
for (int i = 0; i < count; i++) {
ret = interpolate(xi, (const uint8_t **)tempShare, i, groupsBuff + i * enMasterSecretLen, enMasterSecretLen, threshold);
if (ret != SLIP39_OK) {
@@ -453,34 +453,34 @@ int MasterSecretEncrypt(uint8_t *masterSecret, uint8_t masterSecretLen, uint8_t
uint32_t iterations;
// L = EMS[:len(EMS)/2]
- memcpy(left, masterSecret, halfLen);
+ memcpy_s(left, halfLen, masterSecret, halfLen);
// R = EMS[len(EMS)/2:]
- memcpy(right, masterSecret + halfLen, halfLen);
+ memcpy_s(right, halfLen, masterSecret + halfLen, halfLen);
// get salt
_get_salt(identifier, extendableBackupFlag, salt);
- memset(pass, 0, sizeof(pass));
+ memset_s(pass, passPhraseLen, 0, passPhraseLen);
if (passPhrase != NULL && passPhraseLen > 1) {
- memcpy(pass + 1, passPhrase, passPhraseLen - 1);
+ memcpy_s(pass + 1, passPhraseLen - 1, passPhrase, passPhraseLen - 1);
}
iterations = PBKDF2_BASE_ITERATION_COUNT << iterationExponent;
for (int i = 0; i < PBKDF2_ROUND_COUNT; i++) {
pass[0] = i;
- memcpy(salt + saltLen, right, halfLen);
+ memcpy_s(salt + saltLen, halfLen, right, halfLen);
pbkdf2_hmac_sha256_slip39(pass, sizeof(pass), salt, sizeof(salt), iterations, key, sizeof(key));
// (L, R) = (R, L xor F(i, R))
for (int j = 0; j < halfLen; j++) {
rightTemp[j] = left[j] ^ key[j];
}
- memcpy(left, right, sizeof(left));
- memcpy(right, rightTemp, sizeof(right));
+ memcpy_s(left, halfLen, right, halfLen);
+ memcpy_s(right, halfLen, rightTemp, halfLen);
}
- memcpy(enMasterSecret + halfLen, left, halfLen);
- memcpy(enMasterSecret, right, halfLen);
+ memcpy_s(enMasterSecret + halfLen, halfLen, left, halfLen);
+ memcpy_s(enMasterSecret, halfLen, right, halfLen);
return 0;
}
@@ -520,7 +520,7 @@ int GenerateMnemonics(uint8_t *masterSecret, uint8_t masterSecretLen, uint8_t *e
// identifier = identifier & 0x7FFF; // a 15-bit positive integer
MasterSecretEncrypt(masterSecret, masterSecretLen, iterationExponent, extendableBackupFlag, identifier, passPhrase, enMasterSecret);
- memcpy(ems, enMasterSecret, masterSecretLen);
+ memcpy_s(ems, masterSecretLen, enMasterSecret, masterSecretLen);
for (int i = 0; i < groupCount; i++) {
uint8_t groupsBuff[groups[i].count * masterSecretLen];
@@ -538,12 +538,12 @@ int GenerateMnemonics(uint8_t *masterSecret, uint8_t masterSecretLen, uint8_t *e
shards[j].memberIndex = j;
shards[j].memberThreshold = groups[i].threshold;
shards[j].valueLength = masterSecretLen;
- memset(shards[j].value, 0, 32);
- memcpy(shards[j].value, groupsBuff + j * masterSecretLen, masterSecretLen);
+ memset_s(shards[j].value, 32, 0, 32);
+ memcpy_s(shards[j].value, masterSecretLen, groupsBuff + j * masterSecretLen, masterSecretLen);
}
- memset(groupsBuff, 0, sizeof(groupsBuff));
+ memset_s(groupsBuff, sizeof(groupsBuff), 0, sizeof(groupsBuff));
}
- memset(enMasterSecret, 0, sizeof(enMasterSecret));
+ memset_s(enMasterSecret, sizeof(enMasterSecret), 0, sizeof(enMasterSecret));
uint16_t *mnemonic = sharesBuffer;
unsigned int word_count = 0;
@@ -608,7 +608,7 @@ static int _recover_secret(uint8_t t, int sl, uint8_t *gsi, const uint8_t **gs,
uint8_t hash[SHA256_DIGEST_LENGTH];
if (t == 1) {
- memcpy(result, gs[0], sl);
+ memcpy_s(result, sl, gs[0], sl);
return 0;
}
@@ -649,21 +649,21 @@ static int _decrypt(uint8_t *ems, int emsl, uint8_t *ms, int msl,
if (emsl & 1)
return -2;
- memcpy(l, ems, hl);
- memcpy(r, ems + hl, hl);
+ memcpy_s(l, hl, ems, hl);
+ memcpy_s(r, hl, ems + hl, hl);
// salt
_get_salt(id, eb, salt);
// pass
- memcpy(pass + 1, pp, ppl);
+ memcpy_s(pass + 1, ppl, pp, ppl);
// iterations
it = PBKDF2_BASE_ITERATION_COUNT << ie;
for (i = PBKDF2_ROUND_COUNT - 1; i >= 0; i--) {
// salt
- memcpy(salt + csl, r, hl);
+ memcpy_s(salt + csl, hl, r, hl);
// pass
pass[0] = i;
// PBKDF2
@@ -672,12 +672,12 @@ static int _decrypt(uint8_t *ems, int emsl, uint8_t *ms, int msl,
for (j = 0; j < hl; j++)
_r[j] = l[j] ^ f[j];
- memcpy(l, r, hl);
- memcpy(r, _r, hl);
+ memcpy_s(l, hl, r, hl);
+ memcpy_s(r, hl, _r, hl);
}
- memcpy(ms, r, hl);
- memcpy(ms + hl, l, hl);
+ memcpy_s(ms, hl, r, hl);
+ memcpy_s(ms + hl, hl, l, hl);
memzero(pass, sizeof(pass));
memzero(salt, sizeof(salt));
@@ -688,16 +688,15 @@ static int _decrypt(uint8_t *ems, int emsl, uint8_t *ms, int msl,
return 0;
}
-extern void TrngGet(void *buf, uint32_t len);
#define SHARE_BUFFER_SIZE 4096
-void GetSlip39MnemonicsWords(uint8_t *masterSecret, uint8_t *ems, uint8_t wordCnt, uint8_t memberCnt, uint8_t memberThreshold,
- char *wordsList[], uint16_t *id, bool *eb, uint8_t *ie)
+int GetSlip39MnemonicsWords(uint8_t *masterSecret, uint8_t *ems, uint8_t wordCnt, uint8_t memberCnt, uint8_t memberThreshold,
+ char *wordsList[], uint16_t *id, bool *eb, uint8_t *ie)
{
uint8_t *passPhrase = (uint8_t *)"";
uint8_t iterationExponent = 0;
bool extendableBackupFlag = true;
uint16_t identifier = 0;
- TrngGet(&identifier, 2);
+ random_buffer((uint8_t *)&identifier, sizeof(identifier));
identifier = identifier & 0x7FFF;
*ie = iterationExponent;
*eb = extendableBackupFlag;
@@ -714,13 +713,29 @@ void GetSlip39MnemonicsWords(uint8_t *masterSecret, uint8_t *ems, uint8_t wordCn
uint16_t shareBufferSize = SHARE_BUFFER_SIZE;
uint16_t sharesBuff[SHARE_BUFFER_SIZE];
- GenerateMnemonics(masterSecret, masterSecretLen, ems, iterationExponent, extendableBackupFlag, identifier, passPhrase,
- groupCnt, groupThereshold, groups, sharesBuff, shareBufferSize);
+ int ret = GenerateMnemonics(masterSecret, masterSecretLen, ems, iterationExponent, extendableBackupFlag, identifier, passPhrase,
+ groupCnt, groupThereshold, groups, sharesBuff, shareBufferSize);
+
+ if (ret != SLIP39_OK) {
+ return ret;
+ }
for (int i = 0; i < memberCnt; i++) {
uint16_t* words = sharesBuff + (i * wordCnt);
wordsList[i] = slip39_strings_for_words(words, wordCnt);
+ if (wordsList[i] == NULL) {
+ for (int j = 0; j < i; j++) {
+ if (wordsList[j] != NULL) {
+ memset_s(wordsList[j], strlen(wordsList[j]), 0, strlen(wordsList[j]));
+ SRAM_FREE(wordsList[j]);
+ wordsList[j] = NULL;
+ }
+ }
+ return SLIP39_INSUFFICIENT_SPACE;
+ }
}
+
+ return SLIP39_OK;
}
int Slip39GetSeed(uint8_t *ems, uint8_t *seed, uint8_t emsLen, const char *passphrase, uint8_t ie, bool eb, uint16_t id)
@@ -729,7 +744,7 @@ int Slip39GetSeed(uint8_t *ems, uint8_t *seed, uint8_t emsLen, const char *passp
}
int Slip39GetMasterSecret(uint8_t threshold, uint8_t wordsCount, uint8_t *ems, uint8_t *masterSecret,
- char *wordsList[], uint16_t *id, uint8_t *eb, uint8_t *ie)
+ char *wordsList[], uint16_t *id, bool *eb, uint8_t *ie)
{
uint16_t wordsIndexBuf[threshold][wordsCount];
Slip39Shared_t shards[threshold];
@@ -795,7 +810,7 @@ int Slip39GetMasterSecret(uint8_t threshold, uint8_t wordsCount, uint8_t *ems, u
*ie = iteration;
groupThreshold = shards[0].groupThreshold;
valueLength = shards[0].valueLength;
- memset(groupIndexMember, 0, sizeof(groupIndexMember));
+ memset_s(groupIndexMember, sizeof(groupIndexMember), 0, sizeof(groupIndexMember));
for (int i = 0; i < threshold; i++) {
groupIndexMember[shards[i].groupIndex]++;
@@ -822,8 +837,8 @@ int Slip39GetMasterSecret(uint8_t threshold, uint8_t wordsCount, uint8_t *ems, u
}
}
- memset(tempShare, 0, sizeof(tempShare));
- memset(xi, 0, sizeof(xi));
+ memset_s(tempShare, sizeof(tempShare), 0, sizeof(tempShare));
+ memset_s(xi, sizeof(xi), 0, sizeof(xi));
for (i = 0; i < 16; i++) {
if (groupIndexMember[i] != 0) {
@@ -846,7 +861,7 @@ int Slip39GetMasterSecret(uint8_t threshold, uint8_t wordsCount, uint8_t *ems, u
ret = _recover_secret(groupMemberThreshold, valueLength, m_share_index, (const uint8_t **)m_share, gsv);
if (ret == 0) {
tempShare[gmic] = (uint8_t *)SRAM_MALLOC(MAX_SAHRE_VALUE_LEN);
- memcpy(tempShare[gmic], gsv, valueLength);
+ memcpy_s(tempShare[gmic], valueLength, gsv, valueLength);
xi[gmic] = i;
gmic++;
@@ -862,34 +877,24 @@ int Slip39GetMasterSecret(uint8_t threshold, uint8_t wordsCount, uint8_t *ems, u
}
}
-#if 0
- if ((ms == NULL) || (*msl < sl)) {
- ret = -11;
- goto exit;
- }
-#endif
-
ret = _recover_secret(gmic, valueLength, xi, (const uint8_t **)tempShare, gsv);
if (ret == 0) {
- memcpy(ems, gsv, valueLength);
+ memcpy_s(ems, valueLength, gsv, valueLength);
_decrypt(gsv, valueLength, gsv, valueLength, pp, ppl, iteration, extendableBackupFlag, identifier);
- memcpy(masterSecret, gsv, valueLength);
-// *msl = sl;
+ memcpy_s(masterSecret, valueLength, gsv, valueLength);
} else {
ret = -12;
}
exit:
- printf("ret = %d\n", ret);
-
-#if 0
- if (gs != NULL)
- free(gs);
-
- for (i = 0; i < gmic; i++)
- if (g_share[i] != NULL)
- free(g_share[i]);
-#endif
+ for (i = 0; i < gmic; i++) {
+ if (tempShare[i] != NULL) {
+ memset_s(tempShare[i], MAX_SAHRE_VALUE_LEN, 0, MAX_SAHRE_VALUE_LEN);
+ SRAM_FREE(tempShare[i]);
+ }
+ }
+ memset_s(gsv, sizeof(gsv), 0, sizeof(gsv));
+ memset_s(m_share_index, sizeof(m_share_index), 0, sizeof(m_share_index));
return ret;
}
diff --git a/src/crypto/slip39/slip39.h b/src/crypto/slip39/slip39.h
index 052813d..427efc6 100644
--- a/src/crypto/slip39/slip39.h
+++ b/src/crypto/slip39/slip39.h
@@ -30,6 +30,9 @@
#define SLIP39_DEFAULT_MEMBER_COUNT (5)
#define SLIP39_DEFAULT_MEMBER_THRESHOLD (3)
#define SLIP39_MNEMONIC_WORDS_MAX (33)
+#define SLIP39_MNEMONIC_20_WORDS (20)
+#define SLIP39_MNEMONIC_33_WORDS (33)
+#define SLIP39_MAX_SLICE_COUNT (16)
#define SLIP39_INVALID_MNEMONIC_INDEX (~0)
#define PBKDF2_BASE_ITERATION_COUNT (2500)
@@ -45,10 +48,10 @@
int Slip39OneSliceCheck(char *wordsList, uint8_t wordCnt, uint16_t id, uint8_t eb, uint8_t ie, uint8_t *threshold);
int Slip39CheckFirstWordList(char *wordsList, uint8_t wordCnt, uint8_t *threshold);
-void GetSlip39MnemonicsWords(uint8_t *masterSecret, uint8_t *ems, uint8_t wordCnt, uint8_t memberCnt, uint8_t memberThreshold,
- char *wordsList[], uint16_t *id, bool *eb, uint8_t *ie);
+int GetSlip39MnemonicsWords(uint8_t *masterSecret, uint8_t *ems, uint8_t wordCnt, uint8_t memberCnt, uint8_t memberThreshold,
+ char *wordsList[], uint16_t *id, bool *eb, uint8_t *ie);
int Slip39GetMasterSecret(uint8_t threshold, uint8_t wordsCount, uint8_t *ems, uint8_t *masterSecret,
- char *wordsList[], uint16_t *id, uint8_t *eb, uint8_t *ie);
+ char *wordsList[], uint16_t *id, bool *eb, uint8_t *ie);
int Slip39GetSeed(uint8_t *ems, uint8_t *seed, uint8_t emsLen, const char *passphrase, uint8_t ie, bool eb, uint16_t id);
#endif /* _SLIP39_H */
diff --git a/src/crypto/slip39/trezor-crypto/pbkdf2.c b/src/crypto/slip39/trezor-crypto/pbkdf2.c
index c42171b..49946f4 100644
--- a/src/crypto/slip39/trezor-crypto/pbkdf2.c
+++ b/src/crypto/slip39/trezor-crypto/pbkdf2.c
@@ -26,6 +26,7 @@
#include "hmac.h"
#include "memzero.h"
#include "sha2.h"
+#include "user_memory.h"
void hmac_sha256_prepare_slip39(const uint8_t *key, const uint32_t keylen,
uint32_t *opad_digest, uint32_t *ipad_digest)
@@ -59,7 +60,7 @@ void hmac_sha256_prepare_slip39(const uint8_t *key, const uint32_t keylen,
key_pad[i] = key_pad[i] ^ 0x5c5c5c5c ^ 0x36363636;
}
sha256_Transform(sha256_initial_hash_value, key_pad, ipad_digest);
- memzero(key_pad, sizeof(key_pad));
+ memset_s(key_pad, sizeof(key_pad), 0, sizeof(key_pad));
}
void pbkdf2_hmac_sha256_Init(PBKDF2_HMAC_SHA256_CTX *pctx, const uint8_t *pass,
@@ -139,86 +140,4 @@ void pbkdf2_hmac_sha256_slip39(const uint8_t *pass, int passlen, const uint8_t *
memcpy(key + key_offset, digest, last_block_size);
}
}
-}
-
-#if 0
-void pbkdf2_hmac_sha512_Init(PBKDF2_HMAC_SHA512_CTX *pctx, const uint8_t *pass,
- int passlen, const uint8_t *salt, int saltlen,
- uint32_t blocknr)
-{
- SHA512_CTX ctx;
-#if BYTE_ORDER == LITTLE_ENDIAN
- REVERSE32(blocknr, blocknr);
-#endif
-
- hmac_sha512_prepare(pass, passlen, pctx->odig, pctx->idig);
- memzero(pctx->g, sizeof(pctx->g));
- pctx->g[8] = 0x8000000000000000;
- pctx->g[15] = (SHA512_BLOCK_LENGTH + SHA512_DIGEST_LENGTH) * 8;
-
- memcpy(ctx.state, pctx->idig, sizeof(pctx->idig));
- ctx.bitcount[0] = SHA512_BLOCK_LENGTH * 8;
- ctx.bitcount[1] = 0;
- sha512_Update(&ctx, salt, saltlen);
- sha512_Update(&ctx, (uint8_t *)&blocknr, sizeof(blocknr));
- sha512_Final(&ctx, (uint8_t *)pctx->g);
-#if BYTE_ORDER == LITTLE_ENDIAN
- for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
- REVERSE64(pctx->g[k], pctx->g[k]);
- }
-#endif
- sha512_Transform(pctx->odig, pctx->g, pctx->g);
- memcpy(pctx->f, pctx->g, SHA512_DIGEST_LENGTH);
- pctx->first = 1;
-}
-
-void pbkdf2_hmac_sha512_Update(PBKDF2_HMAC_SHA512_CTX *pctx,
- uint32_t iterations)
-{
- for (uint32_t i = pctx->first; i < iterations; i++) {
- sha512_Transform(pctx->idig, pctx->g, pctx->g);
- sha512_Transform(pctx->odig, pctx->g, pctx->g);
- for (uint32_t j = 0; j < SHA512_DIGEST_LENGTH / sizeof(uint64_t); j++) {
- pctx->f[j] ^= pctx->g[j];
- }
- }
- pctx->first = 0;
-}
-
-void pbkdf2_hmac_sha512_Final(PBKDF2_HMAC_SHA512_CTX *pctx, uint8_t *key)
-{
-#if BYTE_ORDER == LITTLE_ENDIAN
- for (uint32_t k = 0; k < SHA512_DIGEST_LENGTH / sizeof(uint64_t); k++) {
- REVERSE64(pctx->f[k], pctx->f[k]);
- }
-#endif
- memcpy(key, pctx->f, SHA512_DIGEST_LENGTH);
- memzero(pctx, sizeof(PBKDF2_HMAC_SHA512_CTX));
-}
-
-void pbkdf2_hmac_sha512(const uint8_t *pass, int passlen, const uint8_t *salt,
- int saltlen, uint32_t iterations, uint8_t *key,
- int keylen)
-{
- uint32_t last_block_size = keylen % SHA512_DIGEST_LENGTH;
- uint32_t blocks_count = keylen / SHA512_DIGEST_LENGTH;
- if (last_block_size) {
- blocks_count++;
- } else {
- last_block_size = SHA512_DIGEST_LENGTH;
- }
- for (uint32_t blocknr = 1; blocknr <= blocks_count; blocknr++) {
- PBKDF2_HMAC_SHA512_CTX pctx;
- pbkdf2_hmac_sha512_Init(&pctx, pass, passlen, salt, saltlen, blocknr);
- pbkdf2_hmac_sha512_Update(&pctx, iterations);
- uint8_t digest[SHA512_DIGEST_LENGTH];
- pbkdf2_hmac_sha512_Final(&pctx, digest);
- uint32_t key_offset = (blocknr - 1) * SHA512_DIGEST_LENGTH;
- if (blocknr < blocks_count) {
- memcpy(key + key_offset, digest, SHA512_DIGEST_LENGTH);
- } else {
- memcpy(key + key_offset, digest, last_block_size);
- }
- }
-}
-#endif
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/crypto/utils/hash_and_salt.c b/src/crypto/utils/hash_and_salt.c
index c883784..535c640 100644
--- a/src/crypto/utils/hash_and_salt.c
+++ b/src/crypto/utils/hash_and_salt.c
@@ -24,52 +24,52 @@ static const uint8_t g_saltData[] = {
#endif
-void HashWithSalt(uint8_t *outData, const uint8_t *inData, uint32_t inLen, const char *saltString)
+/**
+ * HashWithSaltImpl - Generate a salted hash using HMAC
+ *
+ * This function produces different hash results on different devices because it uses
+ * device-specific random salt data stored in OTP (One-Time Programmable) memory.
+ * Each device has its own unique salt, making the hash output device-specific.
+ */
+static void HashWithSaltImpl(uint8_t *outData, const uint8_t *inData, uint32_t inLen, const char *saltString, bool useSha512)
{
uint8_t saltData[SALT_DATA_LEN];
- uint8_t tempData[32];
+ uint8_t tempData256[32];
+ uint8_t tempData512[64];
#ifdef HASH_AND_SALT_TEST_MODE
- memcpy(saltData, g_saltData, sizeof(saltData));
+ memcpy_s(saltData, sizeof(saltData), g_saltData, sizeof(g_saltData));
#else
- //Get salt data from OTP, if salt data does not exist, then generate a ramdom salt data.
+ // Get salt data from OTP, if salt data does not exist, then generate a random salt data.
MpuSetOtpProtection(false);
OTP_PowerOn();
- memcpy(saltData, (uint8_t *)OTP_ADDR_SALT, SALT_DATA_LEN);
- //PrintArray("saltData", saltData, SALT_DATA_LEN);
+ memcpy_s(saltData, sizeof(saltData), (uint8_t *)OTP_ADDR_SALT, SALT_DATA_LEN);
if (CheckEntropy(saltData, SALT_DATA_LEN) == false) {
printf("need generate salt\r\n");
TrngGet(saltData, SALT_DATA_LEN);
- WriteOtpData(OTP_ADDR_SALT, saltData, SALT_DATA_LEN);
- //PrintArray("generate saltData", saltData, SALT_DATA_LEN);
+ ASSERT(SUCCESS_CODE == WriteOtpData(OTP_ADDR_SALT, saltData, SALT_DATA_LEN));
}
-#endif
MpuSetOtpProtection(true);
- hmac_sha256(saltData, SALT_DATA_LEN, (uint8_t *)inData, inLen, tempData);
- hmac_sha256((uint8_t *)saltString, strlen(saltString), tempData, 32, outData);
- memset(saltData, 0, sizeof(saltData));
+#endif
+
+ if (useSha512) {
+ hmac_sha512(saltData, SALT_DATA_LEN, (uint8_t *)inData, inLen, tempData512);
+ hmac_sha512((uint8_t *)saltString, strlen(saltString), tempData512, sizeof(tempData512), outData);
+ } else {
+ hmac_sha256(saltData, SALT_DATA_LEN, (uint8_t *)inData, inLen, tempData256);
+ hmac_sha256((uint8_t *)saltString, strlen(saltString), tempData256, sizeof(tempData256), outData);
+ }
+
+ memset_s(saltData, sizeof(saltData), 0, sizeof(saltData));
+ memset_s(tempData256, sizeof(tempData256), 0, sizeof(tempData256));
+ memset_s(tempData512, sizeof(tempData512), 0, sizeof(tempData512));
}
-void HashWithSalt512(uint8_t *outData, const uint8_t *inData, uint32_t inLen, const char *saltString)
+void HashWithSalt(uint8_t *outData, const uint8_t *inData, uint32_t inLen, const char *saltString)
{
- uint8_t saltData[SALT_DATA_LEN];
- uint8_t tempData[64];
-#ifdef HASH_AND_SALT_TEST_MODE
- memcpy(saltData, g_saltData, sizeof(saltData));
-#else
- //Get salt data from OTP, if salt data does not exist, then generate a ramdom salt data.
- MpuSetOtpProtection(false);
- OTP_PowerOn();
- memcpy(saltData, (uint8_t *)OTP_ADDR_SALT, SALT_DATA_LEN);
- //PrintArray("saltData", saltData, SALT_DATA_LEN);
- if (CheckEntropy(saltData, SALT_DATA_LEN) == false) {
- printf("need generate salt\r\n");
- TrngGet(saltData, SALT_DATA_LEN);
- WriteOtpData(OTP_ADDR_SALT, saltData, SALT_DATA_LEN);
- //PrintArray("generate saltData", saltData, SALT_DATA_LEN);
- }
-#endif
- MpuSetOtpProtection(true);
- hmac_sha512(saltData, SALT_DATA_LEN, (uint8_t *)inData, inLen, tempData);
- hmac_sha512((uint8_t *)saltString, strlen(saltString), tempData, 64, outData);
- memset(saltData, 0, sizeof(saltData));
+ return HashWithSaltImpl(outData, inData, inLen, saltString, false);
}
+
+void HashWithSalt512(uint8_t *outData, const uint8_t *inData, uint32_t inLen, const char *saltString)
+{
+ return HashWithSaltImpl(outData, inData, inLen, saltString, true);
+}
\ No newline at end of file
diff --git a/src/hardware_interface/se_interface.c b/src/hardware_interface/se_interface.c
index b77df96..6c9da3b 100644
--- a/src/hardware_interface/se_interface.c
+++ b/src/hardware_interface/se_interface.c
@@ -10,39 +10,39 @@
//START: Atecc608b
int32_t SE_EncryptWrite(uint8_t slot, uint8_t block, const uint8_t *data)
{
- //TODO: deal with error;
int32_t ret = Atecc608bEncryptWrite(slot, block, data);
- return ret;
+ ASSERT(ret == ATCA_SUCCESS);
+ return SUCCESS_CODE;
}
int32_t SE_Kdf(uint8_t slot, const uint8_t *authKey, const uint8_t *inData, uint32_t inLen, uint8_t *outData)
{
- //TODO: deal with error;
int32_t ret = Atecc608bKdf(slot, authKey, inData, inLen, outData);
- return ret;
+ ASSERT(ret == ATCA_SUCCESS);
+ return SUCCESS_CODE;
}
int32_t SE_DeriveKey(uint8_t slot, const uint8_t *authKey)
{
- //TODO: deal with error;
int32_t ret = Atecc608bDeriveKey(slot, authKey);
- return ret;
+ ASSERT(ret == ATCA_SUCCESS);
+ return SUCCESS_CODE;
}
//END
//START: DS28S60
int32_t SE_HmacEncryptRead(uint8_t *data, uint8_t page)
{
- int32_t ret = 0;
- ret = DS28S60_HmacEncryptRead(data, page);
- return ret;
+ int32_t ret = DS28S60_HmacEncryptRead(data, page);
+ ASSERT(ret == DS28S60_SUCCESS);
+ return SUCCESS_CODE;
}
int32_t SE_GetDS28S60Rng(uint8_t *rngArray, uint32_t num)
{
- int32_t ret = 0;
- ret = DS28S60_GetRng(rngArray, num);
- return ret;
+ int32_t ret = DS28S60_GetRng(rngArray, num) ;
+ ASSERT(ret == DS28S60_SUCCESS);
+ return SUCCESS_CODE;
}
void SE_GetTRng(void *buf, uint32_t len)
@@ -52,16 +52,16 @@ void SE_GetTRng(void *buf, uint32_t len)
int32_t SE_GetAtecc608bRng(uint8_t *rngArray, uint32_t num)
{
- int32_t ret = 0;
- ret = Atecc608bGetRng(rngArray, num);
- return ret;
+ int32_t ret = Atecc608bGetRng(rngArray, num);
+ ASSERT(ret == ATCA_SUCCESS);
+ return SUCCESS_CODE;
}
int32_t SE_HmacEncryptWrite(const uint8_t *data, uint8_t page)
{
- int32_t ret = 0;
- ret = DS28S60_HmacEncryptWrite(data, page);
- return ret;
+ int32_t ret = DS28S60_HmacEncryptWrite(data, page);
+ ASSERT(ret == DS28S60_SUCCESS);
+ return SUCCESS_CODE;
}
//END
diff --git a/src/managers/keystore.c b/src/managers/keystore.c
index 04bf506..2425679 100644
--- a/src/managers/keystore.c
+++ b/src/managers/keystore.c
@@ -57,6 +57,7 @@ int32_t GenerateEntropy(uint8_t *entropy, uint8_t entropyLen, const char *passwo
{
uint8_t randomBuffer[ENTROPY_MAX_LEN], inputBuffer[ENTROPY_MAX_LEN], outputBuffer[ENTROPY_MAX_LEN];
int32_t ret;
+ ASSERT(strnlen_s(password, PASSWORD_MAX_LEN) > MIN_PASSWORD_LEN);
do {
HashWithSalt(inputBuffer, (uint8_t *)password, strnlen_s(password, PASSWORD_MAX_LEN), "generate entropy");
@@ -87,6 +88,7 @@ int32_t GenerateEntropy(uint8_t *entropy, uint8_t entropyLen, const char *passwo
CLEAR_ARRAY(outputBuffer);
CLEAR_ARRAY(inputBuffer);
CLEAR_ARRAY(randomBuffer);
+ ASSERT(ret == SUCCESS_CODE);
return ret;
}
@@ -114,7 +116,9 @@ int32_t SaveNewBip39Entropy(uint8_t accountIndex, const uint8_t *entropy, uint8_
CHECK_ERRCODE_BREAK("bip39_mnemonic_from_bytes", ret);
ret = bip39_mnemonic_to_seed(mnemonic, NULL, accountSecret.seed, SEED_LEN, NULL);
CHECK_ERRCODE_BREAK("bip39_mnemonic_to_seed", ret);
+ memset_s(mnemonic, strnlen_s(mnemonic, MNEMONIC_MAX_LEN), 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
SRAM_FREE(mnemonic);
+ mnemonic = NULL;
ret = SaveAccountSecret(accountIndex, &accountSecret, password, true);
CHECK_ERRCODE_BREAK("SaveAccountSecret", ret);
@@ -124,8 +128,14 @@ int32_t SaveNewBip39Entropy(uint8_t accountIndex, const uint8_t *entropy, uint8_
} while (0);
+ if (mnemonic != NULL) {
+ memset_s(mnemonic, strnlen_s(mnemonic, MNEMONIC_MAX_LEN), 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
+ SRAM_FREE(mnemonic);
+ }
+
CLEAR_ARRAY(passwordHash);
CLEAR_OBJECT(accountSecret);
+ ASSERT(ret == SUCCESS_CODE);
return ret;
}
@@ -163,6 +173,7 @@ int32_t SaveNewSlip39Entropy(uint8_t accountIndex, const uint8_t *ems, const uin
CLEAR_ARRAY(passwordHash);
CLEAR_OBJECT(accountSecret);
+ ASSERT(ret == SUCCESS_CODE);
return ret;
}
@@ -417,7 +428,7 @@ bool PassphraseExist(uint8_t accountIndex)
return false;
}
- assert(g_passphraseInfo[accountIndex].passphraseExist == (strnlen_s(g_passphraseInfo[accountIndex].passphrase, PASSPHRASE_MAX_LEN) > 0));
+ ASSERT(g_passphraseInfo[accountIndex].passphraseExist == (strnlen_s(g_passphraseInfo[accountIndex].passphrase, PASSPHRASE_MAX_LEN) > 0));
return (strnlen_s(g_passphraseInfo[accountIndex].passphrase, PASSPHRASE_MAX_LEN) > 0);
}
@@ -663,8 +674,10 @@ static int32_t GetPassphraseSeed(uint8_t accountIndex, uint8_t *seed, const char
switch (mnemonicType) {
case MNEMONIC_TYPE_SLIP39: {
uint8_t slip39Ems[SLIP39_EMS_LEN];
- GetAccountSlip39Ems(accountIndex, slip39Ems, password);
+ ret = GetAccountSlip39Ems(accountIndex, slip39Ems, password);
+ CHECK_ERRCODE_BREAK("GetAccountSlip39Ems", ret);
ret = Slip39GetSeed(slip39Ems, seed, GetCurrentAccountEntropyLen(), passphrase, GetSlip39Ie(), GetSlip39Eb(), GetSlip39Id());
+ CLEAR_ARRAY(slip39Ems);
CHECK_ERRCODE_BREAK("slip39_mnemonic_to_seed", ret);
break;
}
@@ -675,11 +688,18 @@ static int32_t GetPassphraseSeed(uint8_t accountIndex, uint8_t *seed, const char
CHECK_ERRCODE_BREAK("bip39_mnemonic_from_bytes", ret);
ret = bip39_mnemonic_to_seed(mnemonic, passphrase, seed, SEED_LEN, NULL);
CHECK_ERRCODE_BREAK("bip39_mnemonic_to_seed", ret);
+ memset_s(mnemonic, strnlen_s(mnemonic, MNEMONIC_MAX_LEN), 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
SRAM_FREE(mnemonic);
+ mnemonic = NULL;
break;
}
} while (0);
+ if (mnemonic != NULL) {
+ memset_s(mnemonic, strnlen_s(mnemonic, MNEMONIC_MAX_LEN), 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
+ SRAM_FREE(mnemonic);
+ }
+ CLEAR_ARRAY(entropy);
return ret;
}
@@ -695,27 +715,26 @@ int32_t SaveNewTonMnemonic(uint8_t accountIndex, const char *mnemonic, const cha
int32_t ret;
AccountSecret_t accountSecret = {0};
uint8_t passwordHash[32];
- uint8_t entropy[64] = {0};
- uint8_t seed[64] = {0};
+ uint8_t entropy[TON_ENTROPY_LEN] = {0};
+ uint8_t seed[SEED_LEN] = {0};
ASSERT(accountIndex <= 2);
do {
ret = CheckPasswordExisted(password, 255);
CHECK_ERRCODE_BREAK("check repeat password", ret);
VecFFI_u8 *result = ton_mnemonic_to_entropy(mnemonic);
- memcpy_s(entropy, 64, result->data, 64);
+ CHECK_ERRCODE_BREAK("ton_mnemonic_to_entropy", TON_ENTROPY_LEN == result->size);
+ memcpy_s(entropy, sizeof(entropy), result->data, result->size);
free_VecFFI_u8(result);
memcpy_s(accountSecret.entropy, sizeof(accountSecret.entropy), entropy, 32);
memcpy_s(accountSecret.slip39EmsOrTonEntropyL32, sizeof(accountSecret.slip39EmsOrTonEntropyL32), entropy + 32, 32);
accountSecret.entropyLen = 32;
SimpleResponse_u8 *resultSeed = ton_entropy_to_seed(entropy, 64);
- if (resultSeed->error_code != 0) {
- break;
- }
- memcpy_s(seed, 64, resultSeed->data, 64);
+ CHECK_ERRCODE_BREAK("ton_entropy_to_seed", resultSeed->error_code);
+ memcpy_s(seed, sizeof(seed), resultSeed->data, SEED_LEN);
free_VecFFI_u8(resultSeed);
- memcpy_s(accountSecret.seed, sizeof(accountSecret.seed), seed, 64);
+ memcpy_s(accountSecret.seed, sizeof(accountSecret.seed), seed, SEED_LEN);
ret = SaveAccountSecret(accountIndex, &accountSecret, password, true);
CHECK_ERRCODE_BREAK("SaveAccountSecret", ret);
@@ -727,6 +746,9 @@ int32_t SaveNewTonMnemonic(uint8_t accountIndex, const char *mnemonic, const cha
CLEAR_ARRAY(passwordHash);
CLEAR_OBJECT(accountSecret);
+ CLEAR_ARRAY(entropy);
+ CLEAR_ARRAY(seed);
+ ASSERT(ret == SUCCESS_CODE);
return ret;
}
@@ -740,16 +762,16 @@ int32_t SaveNewTonMnemonic(uint8_t accountIndex, const char *mnemonic, const cha
int32_t GenerateTonMnemonic(char *mnemonic, const char *password)
{
uint8_t randomBuffer[TON_ENTROPY_LEN], inputBuffer[TON_ENTROPY_LEN], outputBuffer[TON_ENTROPY_LEN];
- int32_t ret;
+ int32_t ret = ERR_GENERAL_FAIL;
char temp_mnemonic[MNEMONIC_MAX_LEN] = {'\0'};
- int32_t count = 0;
- //generate the randomness by se;
+ if (mnemonic == NULL || password == NULL || strnlen_s(password, PASSWORD_MAX_LEN) < MIN_PASSWORD_LEN) {
+ return ERR_GENERAL_FAIL;
+ }
do {
HashWithSalt512(inputBuffer, (uint8_t *)password, strnlen_s(password, PASSWORD_MAX_LEN), "generate entropy");
SE_GetTRng(randomBuffer, TON_ENTROPY_LEN);
KEYSTORE_PRINT_ARRAY("trng", randomBuffer, TON_ENTROPY_LEN);
- // set the initial value
memcpy_s(outputBuffer, sizeof(outputBuffer), randomBuffer, TON_ENTROPY_LEN);
hkdf64(inputBuffer, randomBuffer, outputBuffer, ITERATION_TIME);
@@ -771,27 +793,52 @@ int32_t GenerateTonMnemonic(char *mnemonic, const char *password)
KEYSTORE_PRINT_ARRAY("finalEntropy", outputBuffer, TON_ENTROPY_LEN);
} while (0);
- //use randomness to generate the mnemonic
- //if the mnemonic is not valid, hash the randomness and try again
while (true) {
- printf("ton mnemonic generation, count: %d\r\n", count++);
- for (size_t i = 0; i < 24; i++) {
+ for (size_t i = 0; i < TON_MNEMONIC_WORDS_COUNT; i++) {
uint32_t index = ((uint32_t)outputBuffer[i * 2] << 8 | outputBuffer[i * 2 + 1]) & 0x07ff;
- char *word;
- bip39_get_word(NULL, index, &word);
+ char *word = NULL;
+ errno_t rc;
+ ret = bip39_get_word(NULL, index, &word);
+ CHECK_ERRCODE_BREAK("bip39_get_word", ret);
+ if (word == NULL) {
+ ret = ERR_KEYSTORE_MNEMONIC_INVALID;
+ break;
+ }
if (i != 0) {
- strcat(temp_mnemonic, " ");
+ rc = strcat_s(temp_mnemonic, MNEMONIC_MAX_LEN, " ");
+ if (rc != 0) {
+ SRAM_FREE(word);
+ memset_s(temp_mnemonic, sizeof(temp_mnemonic), 0, sizeof(temp_mnemonic));
+ ret = ERR_KEYSTORE_MNEMONIC_INVALID;
+ break;
+ }
}
- strcat(temp_mnemonic, word);
+ rc = strcat_s(temp_mnemonic, MNEMONIC_MAX_LEN, word);
SRAM_FREE(word);
+ if (rc != 0) {
+ memset_s(temp_mnemonic, sizeof(temp_mnemonic), 0, sizeof(temp_mnemonic));
+ ret = ERR_KEYSTORE_MNEMONIC_INVALID;
+ break;
+ }
}
- if (ton_verify_mnemonic(temp_mnemonic)) {
- break;
+
+ if (ret == SUCCESS_CODE || ret == ERR_GENERAL_FAIL) {
+ if (ton_verify_mnemonic(temp_mnemonic)) {
+ ret = SUCCESS_CODE;
+ break;
+ } else {
+ memset_s(temp_mnemonic, sizeof(temp_mnemonic), 0, sizeof(temp_mnemonic));
+ uint8_t hash[64];
+ memcpy_s(hash, 64, outputBuffer, 64);
+ sha512((struct sha512 *)outputBuffer, hash, sizeof(hash));
+ continue;
+ }
} else {
memset_s(temp_mnemonic, sizeof(temp_mnemonic), 0, sizeof(temp_mnemonic));
uint8_t hash[64];
memcpy_s(hash, 64, outputBuffer, 64);
sha512((struct sha512 *)outputBuffer, hash, sizeof(hash));
+ ret = ERR_GENERAL_FAIL;
}
}
@@ -799,7 +846,15 @@ int32_t GenerateTonMnemonic(char *mnemonic, const char *password)
CLEAR_ARRAY(inputBuffer);
CLEAR_ARRAY(randomBuffer);
- strcpy_s(mnemonic, MNEMONIC_MAX_LEN, temp_mnemonic);
+ if (ret == SUCCESS_CODE) {
+ errno_t rc = strcpy_s(mnemonic, MNEMONIC_MAX_LEN, temp_mnemonic);
+ if (rc != 0) {
+ memset_s(mnemonic, MNEMONIC_MAX_LEN, 0, MNEMONIC_MAX_LEN);
+ ret = ERR_KEYSTORE_MNEMONIC_INVALID;
+ }
+ memset_s(temp_mnemonic, sizeof(temp_mnemonic), 0, sizeof(temp_mnemonic));
+ }
+ ASSERT(ret == SUCCESS_CODE);
return ret;
}
#endif
@@ -810,18 +865,20 @@ void random_buffer(uint8_t *buf, size_t len)
uint8_t *tempBuf1 = SRAM_MALLOC(len);
uint8_t *tempBuf2 = SRAM_MALLOC(len);
- if (tempBuf1 && tempBuf2) {
- TrngGet(buf, len);
- assert(SE_GetDS28S60Rng(tempBuf1, len) == 0);
- assert(SE_GetAtecc608bRng(tempBuf2, len) == 0);
+ ASSERT(tempBuf1 != NULL && tempBuf2 != NULL);
- for (size_t i = 0; i < len; i++) {
- buf[i] ^= tempBuf1[i] ^ tempBuf2[i];
- }
+ TrngGet(buf, len);
+ ASSERT(SE_GetDS28S60Rng(tempBuf1, len) == 0);
+ ASSERT(SE_GetAtecc608bRng(tempBuf2, len) == 0);
- SRAM_FREE(tempBuf1);
- SRAM_FREE(tempBuf2);
+ for (size_t i = 0; i < len; i++) {
+ buf[i] ^= tempBuf1[i] ^ tempBuf2[i];
}
+
+ memzero(tempBuf1, len);
+ memzero(tempBuf2, len);
+ SRAM_FREE(tempBuf1);
+ SRAM_FREE(tempBuf2);
}
#endif
diff --git a/src/managers/keystore.h b/src/managers/keystore.h
index e7403c2..9e653df 100644
--- a/src/managers/keystore.h
+++ b/src/managers/keystore.h
@@ -26,6 +26,9 @@
#define ACCOUNT_TOTAL_LEN (AES_IV_LEN + ENTROPY_MAX_LEN + SEED_LEN + SLIP39_EMS_LEN + SE_DATA_RESERVED_LEN + HMAC_LEN)
#define PARAM_LEN 32
+#define MIN_PASSWORD_LEN 6
+#define TON_MNEMONIC_WORDS_COUNT 24
+
#define ITERATION_TIME 700
typedef struct {
diff --git a/src/ui/gui_components/gui_mnemonic_input.c b/src/ui/gui_components/gui_mnemonic_input.c
index 3e273d3..aa862a5 100644
--- a/src/ui/gui_components/gui_mnemonic_input.c
+++ b/src/ui/gui_components/gui_mnemonic_input.c
@@ -29,10 +29,13 @@
extern TrieSTPtr rootTree;
extern char g_wordBuf[GUI_KEYBOARD_CANDIDATE_WORDS_CNT][GUI_KEYBOARD_CANDIDATE_WORDS_LEN];
static char g_sliceHeadWords[GUI_KEYBOARD_CANDIDATE_WORDS_LEN]; // slip39 head three words
-static uint8_t g_sliceSha256[15][GUI_KEYBOARD_CANDIDATE_WORDS_LEN]; // slip39 words hash
+static uint8_t g_sliceSha256[SLIP39_MAX_SLICE_COUNT - 1][GUI_KEYBOARD_CANDIDATE_WORDS_LEN]; // slip39 words hash
static lv_obj_t *g_noticeHintBox = NULL;
static void HandleInputType(MnemonicKeyBoard_t *mkb);
+static void CompleteSlip39Import(MnemonicKeyBoard_t *mkb, KeyBoard_t *letterKb);
+static void ShowShareSuccessDialog(void);
+static void UpdateSliceLabels(MnemonicKeyBoard_t *mkb);
char *GuiMnemonicGetTrueWord(const char *word, char *trueWord)
{
@@ -48,33 +51,44 @@ char *GuiMnemonicGetTrueWord(const char *word, char *trueWord)
return trueWord;
}
-void ImportShareNextSlice(MnemonicKeyBoard_t *mkb, KeyBoard_t *letterKb)
+static void CollectMnemonicWords(MnemonicKeyBoard_t *mkb, char *mnemonic, size_t bufferSize)
{
- // todo slice==0 clear
- if (mkb->currentSlice == 0) {
- for (int i = 0; i < 15; i++) {
- memset_s(g_sliceSha256[i], 32, 0, 32);
- }
- memset_s(g_sliceHeadWords, sizeof(g_sliceHeadWords), 0, sizeof(g_sliceHeadWords));
- }
- mkb->currentId = 0;
- bool isSame = false;
- char *mnemonic = SRAM_MALLOC(10 * mkb->wordCnt + 1);
- memset_s(mnemonic, 10 * mkb->wordCnt + 1, 0, 10 * mkb->wordCnt + 1);
+ char *tempMnemonic = SRAM_MALLOC(bufferSize);
+ memset_s(tempMnemonic, bufferSize, 0, bufferSize);
for (int i = 0, j = 0; i < mkb->wordCnt; j++, i += 3) {
for (int k = i; k < i + 3; k++) {
char trueBuf[12] = {0};
GuiMnemonicGetTrueWord(lv_btnmatrix_get_btn_text(mkb->btnm, k), trueBuf);
- strcat(mnemonic, trueBuf);
- strcat(mnemonic, " ");
+ strcat_s(tempMnemonic, bufferSize, trueBuf);
+ strcat_s(tempMnemonic, bufferSize, " ");
}
}
- if (mkb->wordCnt == 20) {
- mnemonic[strlen(mnemonic) - 2] = '\0';
+
+ // Special handling for 20-word layout: 3x7 grid with last column empty
+ if (mkb->wordCnt == SLIP39_MNEMONIC_20_WORDS) {
+ tempMnemonic[strlen(tempMnemonic) - 2] = '\0';
} else {
- mnemonic[strlen(mnemonic) - 1] = '\0';
+ tempMnemonic[strlen(tempMnemonic) - 1] = '\0';
}
+ memcpy(mnemonic, tempMnemonic, bufferSize);
+ SRAM_FREE(tempMnemonic);
+}
+
+void ImportShareNextSlice(MnemonicKeyBoard_t *mkb, KeyBoard_t *letterKb)
+{
+ if (mkb->currentSlice == 0) {
+ for (int i = 0; i < 15; i++) {
+ memset_s(g_sliceSha256[i], 32, 0, 32);
+ }
+ memset_s(g_sliceHeadWords, sizeof(g_sliceHeadWords), 0, sizeof(g_sliceHeadWords));
+ }
+ mkb->currentId = 0;
+ bool isSame = false;
+ size_t bufferSize = 10 * mkb->wordCnt + 1;
+ char *mnemonic = SRAM_MALLOC(bufferSize);
+ memset_s(mnemonic, bufferSize, 0, bufferSize);
+ CollectMnemonicWords(mkb, mnemonic, bufferSize);
uint8_t threShold = 0;
do {
@@ -102,16 +116,17 @@ void ImportShareNextSlice(MnemonicKeyBoard_t *mkb, KeyBoard_t *letterKb)
mkb->threShold = threShold;
for (int i = 0; i < 3; i++) {
char trueBuf[12] = {0};
- strcat(g_sliceHeadWords, GuiMnemonicGetTrueWord(lv_btnmatrix_get_btn_text(mkb->btnm, i), trueBuf));
+ GuiMnemonicGetTrueWord(lv_btnmatrix_get_btn_text(mkb->btnm, i), trueBuf);
+ strcat_s(g_sliceHeadWords, sizeof(g_sliceHeadWords), trueBuf);
if (i == 2) {
break;
}
- strcat(g_sliceHeadWords, " ");
+ strcat_s(g_sliceHeadWords, sizeof(g_sliceHeadWords), " ");
}
} else {
uint8_t tempHash[32];
sha256((struct sha256 *)tempHash, mnemonic, strlen(mnemonic));
- for (int i = 0; i < mkb->currentSlice; i++) {
+ for (int i = 0; i < mkb->currentSlice && i < SLIP39_MAX_SLICE_COUNT - 1; i++) {
if (!memcmp(tempHash, g_sliceSha256[i], 32)) {
g_noticeHintBox = GuiCreateResultHintbox(386, &imgFailed, _("import_wallet_ssb_incorrect_title"),
_("import_wallet_ssb_repeat_desc"), NULL, DARK_GRAY_COLOR, _("OK"), DARK_GRAY_COLOR);
@@ -133,69 +148,37 @@ void ImportShareNextSlice(MnemonicKeyBoard_t *mkb, KeyBoard_t *letterKb)
mkb->currentSlice++;
lv_label_set_text_fmt(mkb->titleLabel, _("import_wallet_ssb_title_fmt"), mkb->currentSlice + 1);
lv_label_set_text_fmt(mkb->descLabel, _("import_wallet_ssb_desc_fmt"), mkb->wordCnt, mkb->currentSlice + 1);
- g_noticeHintBox = GuiCreateResultHintbox(386, &imgSuccess, _("shamir_phrase_verify_success_title"),
- _("import_wallet_share_success_desc"), _("Continue"), DARK_GRAY_COLOR, _("Done"), ORANGE_COLOR);
- lv_obj_t *rightBtn = GuiGetHintBoxRightBtn(g_noticeHintBox);
- lv_obj_add_event_cb(rightBtn, CloseToSubtopViewHandler, LV_EVENT_CLICKED, &g_noticeHintBox);
- lv_obj_t *leftBtn = GuiGetHintBoxLeftBtn(g_noticeHintBox);
- lv_obj_add_event_cb(leftBtn, CloseHintBoxHandler, LV_EVENT_CLICKED, &g_noticeHintBox);
+ ShowShareSuccessDialog();
ClearMnemonicKeyboard(mkb, &mkb->currentId);
} else {
lv_obj_clear_flag(mkb->stepLabel, LV_OBJ_FLAG_HIDDEN);
if (mkb->currentSlice + 1 == mkb->threShold) {
- if (mkb->intputType == MNEMONIC_INPUT_FORGET_VIEW) {
- GuiForgetAnimContDel(1);
- lv_obj_add_flag(letterKb->cont, LV_OBJ_FLAG_HIDDEN);
- Slip39Data_t slip39 = {
- .threShold = mkb->threShold,
- .wordCnt = mkb->wordCnt,
- };
- GuiModelSlip39ForgetPassword(slip39);
- } else {
- GuiEmitSignal(SIG_SETUP_VIEW_TILE_NEXT, NULL, 0);
- }
+ CompleteSlip39Import(mkb, letterKb);
} else {
mkb->currentSlice++;
- if (mkb->stepLabel != NULL) {
- if (lv_obj_has_flag(mkb->stepLabel, LV_OBJ_FLAG_HIDDEN)) {
- lv_obj_clear_flag(mkb->stepLabel, LV_OBJ_FLAG_HIDDEN);
- }
- lv_label_set_text_fmt(mkb->stepLabel, _("import_wallet_ssb_step_fmt"), mkb->currentSlice + 1, mkb->threShold);
- }
- if (mkb->titleLabel != NULL) {
- lv_label_set_text_fmt(mkb->titleLabel, _("import_wallet_ssb_title_fmt"), mkb->currentSlice + 1);
- }
- if (mkb->descLabel != NULL) {
- lv_label_set_text_fmt(mkb->descLabel, _("import_wallet_ssb_desc_fmt"),
- mkb->wordCnt, mkb->currentSlice + 1);
- }
+ UpdateSliceLabels(mkb);
}
}
}
}
} while (0);
GuiSetLetterBoardConfirm(letterKb, 0);
- memset_s(mnemonic, strlen(mnemonic), 0, strlen(mnemonic));
+ memset_s(mnemonic, bufferSize, 0, bufferSize);
SRAM_FREE(mnemonic);
}
-static void ProceedWithBip39(MnemonicKeyBoard_t *mkb)
-{
- GuiEmitSignal(SIG_SETUP_VIEW_TILE_NEXT, NULL, 0);
-}
-
static void HandleInputType(MnemonicKeyBoard_t *mkb)
{
switch (mkb->intputType) {
case MNEMONIC_INPUT_IMPORT_VIEW:
- ProceedWithBip39(mkb);
+ GuiEmitSignal(SIG_SETUP_VIEW_TILE_NEXT, NULL, 0);
break;
case MNEMONIC_INPUT_SETTING_VIEW:
GuiModelBip39RecoveryCheck(mkb->wordCnt);
GuiSettingRecoveryCheck();
break;
case MNEMONIC_INPUT_FORGET_VIEW:
- GuiForgetAnimContDel(1);
+ GuiForgetAnimContDel(false);
GuiModelBip39ForgetPassword(mkb->wordCnt);
break;
}
@@ -219,7 +202,7 @@ static void HandleTonCondition(bool isTon, MnemonicKeyBoard_t *mkb)
}
break;
case MNEMONIC_INPUT_FORGET_VIEW:
- GuiForgetAnimContDel(1);
+ GuiForgetAnimContDel(false);
GuiModelTonForgetPassword();
break;
}
@@ -231,31 +214,22 @@ static void HandleTonCondition(bool isTon, MnemonicKeyBoard_t *mkb)
void ImportSinglePhraseWords(MnemonicKeyBoard_t *mkb, KeyBoard_t *letterKb)
{
- char *mnemonic = SRAM_MALLOC(BIP39_MAX_WORD_LEN * mkb->wordCnt + 1);
- memset_s(mnemonic, BIP39_MAX_WORD_LEN * mkb->wordCnt + 1, 0, BIP39_MAX_WORD_LEN * mkb->wordCnt + 1);
-
- for (int i = 0, j = 0; i < mkb->wordCnt; j++, i += 3) {
- for (int k = i; k < i + 3; k++) {
- char trueBuf[12] = {0};
- GuiMnemonicGetTrueWord(lv_btnmatrix_get_btn_text(mkb->btnm, k), trueBuf);
- strcat(mnemonic, trueBuf);
- strcat(mnemonic, " ");
- }
- }
- mnemonic[strlen(mnemonic) - 1] = '\0';
+ size_t bufferSize = BIP39_MAX_WORD_LEN * mkb->wordCnt + mkb->wordCnt;
+ char *mnemonic = SRAM_MALLOC(bufferSize);
+ memset_s(mnemonic, bufferSize, 0, bufferSize);
+ CollectMnemonicWords(mkb, mnemonic, bufferSize);
SecretCacheSetMnemonic(mnemonic);
#ifdef WEB3_VERSION
- bool isTon = ton_verify_mnemonic(mnemonic);
- HandleTonCondition(isTon, mkb);
+ HandleTonCondition(ton_verify_mnemonic(mnemonic), mkb);
#else
HandleInputType(mkb);
#endif
lv_obj_add_flag(letterKb->cont, LV_OBJ_FLAG_HIDDEN);
lv_obj_set_height(mkb->cont, 400);
- memset_s(mnemonic, strlen(mnemonic), 0, strlen(mnemonic));
+ memset_s(mnemonic, bufferSize, 0, bufferSize);
SRAM_FREE(mnemonic);
}
@@ -275,7 +249,6 @@ bool GuiMnemonicInputCheck(MnemonicKeyBoard_t *mkb, KeyBoard_t *letterKb)
}
}
GuiSetLetterBoardConfirm(letterKb, 1);
- // lv_obj_add_flag(mkb->nextButton, LV_OBJ_FLAG_CLICKABLE);
return true;
}
@@ -391,7 +364,7 @@ void GuiMnemonicInputHandler(lv_event_t *e)
if (mkb->currentId == mkb->wordCnt) {
GuiSetLetterBoardConfirm(letterKb, 1);
- if (mkb->wordCnt == 33 || mkb->wordCnt == 20) {
+ if (mkb->wordCnt == SLIP39_MNEMONIC_33_WORDS || mkb->wordCnt == SLIP39_MNEMONIC_20_WORDS) {
ImportShareNextSlice(mkb, letterKb);
} else {
ImportSinglePhraseWords(mkb, letterKb);
@@ -431,7 +404,6 @@ void GuiMnemonicInputHandler(lv_event_t *e)
char *word = lv_event_get_param(e);
if ((strlen(word) == 0 && code == KEY_STONE_KEYBOARD_VALUE_CHANGE)) {
- // if (isClick || (strlen(word) == 0 && code == KEY_STONE_KEYBOARD_VALUE_CHANGE)) {
if (isClick > 0) {
isClick--;
}
@@ -505,4 +477,48 @@ lv_keyboard_user_mode_t GuiGetMnemonicKbType(int wordCnt)
}
return KEY_STONE_MNEMONIC_12;
+}
+
+static void UpdateSliceLabels(MnemonicKeyBoard_t *mkb)
+{
+ if (mkb->titleLabel != NULL) {
+ lv_label_set_text_fmt(mkb->titleLabel, _("import_wallet_ssb_title_fmt"), mkb->currentSlice + 1);
+ }
+ if (mkb->descLabel != NULL) {
+ lv_label_set_text_fmt(mkb->descLabel, _("import_wallet_ssb_desc_fmt"), mkb->wordCnt, mkb->currentSlice + 1);
+ }
+ if (mkb->stepLabel != NULL) {
+ if (lv_obj_has_flag(mkb->stepLabel, LV_OBJ_FLAG_HIDDEN)) {
+ lv_obj_clear_flag(mkb->stepLabel, LV_OBJ_FLAG_HIDDEN);
+ }
+ lv_label_set_text_fmt(mkb->stepLabel, _("import_wallet_ssb_step_fmt"), mkb->currentSlice + 1, mkb->threShold);
+ }
+}
+
+static void ShowShareSuccessDialog(void)
+{
+ g_noticeHintBox = GuiCreateResultHintbox(386, &imgSuccess,
+ _("shamir_phrase_verify_success_title"),
+ _("import_wallet_share_success_desc"),
+ _("Continue"), DARK_GRAY_COLOR,
+ _("Done"), ORANGE_COLOR);
+ lv_obj_t *rightBtn = GuiGetHintBoxRightBtn(g_noticeHintBox);
+ lv_obj_add_event_cb(rightBtn, CloseToSubtopViewHandler, LV_EVENT_CLICKED, &g_noticeHintBox);
+ lv_obj_t *leftBtn = GuiGetHintBoxLeftBtn(g_noticeHintBox);
+ lv_obj_add_event_cb(leftBtn, CloseHintBoxHandler, LV_EVENT_CLICKED, &g_noticeHintBox);
+}
+
+static void CompleteSlip39Import(MnemonicKeyBoard_t *mkb, KeyBoard_t *letterKb)
+{
+ if (mkb->intputType == MNEMONIC_INPUT_FORGET_VIEW) {
+ GuiForgetAnimContDel(false);
+ lv_obj_add_flag(letterKb->cont, LV_OBJ_FLAG_HIDDEN);
+ Slip39Data_t slip39 = {
+ .threShold = mkb->threShold,
+ .wordCnt = mkb->wordCnt,
+ };
+ GuiModelSlip39ForgetPassword(slip39);
+ } else {
+ GuiEmitSignal(SIG_SETUP_VIEW_TILE_NEXT, NULL, 0);
+ }
}
\ No newline at end of file
diff --git a/src/ui/gui_model/gui_model.c b/src/ui/gui_model/gui_model.c
index ee4f6cf..20ebd14 100644
--- a/src/ui/gui_model/gui_model.c
+++ b/src/ui/gui_model/gui_model.c
@@ -319,58 +319,109 @@ static int32_t ModelGenerateEntropy(const void *inData, uint32_t inDataLen)
{
bool enable = IsPreviousLockScreenEnable();
SetLockScreen(false);
- int32_t retData;
+ int32_t ret = ERR_GENERAL_FAIL;
char *mnemonic = NULL;
uint8_t entropy[32];
- uint32_t mnemonicNum, entropyLen;
- mnemonicNum = *((uint32_t *)inData);
- entropyLen = (mnemonicNum == 24) ? 32 : 16;
- GenerateEntropy(entropy, entropyLen, SecretCacheGetNewPassword());
- SecretCacheSetEntropy(entropy, entropyLen);
- bip39_mnemonic_from_bytes(NULL, entropy, entropyLen, &mnemonic);
- SecretCacheSetMnemonic(mnemonic);
- retData = SUCCESS_CODE;
- GuiApiEmitSignal(SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC, &retData, sizeof(retData));
- memset_s(mnemonic, strnlen_s(mnemonic, MNEMONIC_MAX_LEN), 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
- SRAM_FREE(mnemonic);
+ uint32_t mnemonicNum = 0, entropyLen = 0;
+
+ if (inData == NULL) {
+ goto cleanup;
+ }
+ mnemonicNum = *((const uint32_t *)inData);
+ if (mnemonicNum == 24) {
+ entropyLen = 32;
+ } else if (mnemonicNum == 12) {
+ entropyLen = 16;
+ } else {
+ ret = ERR_GENERAL_FAIL;
+ goto cleanup;
+ }
+ const char *pwd = SecretCacheGetNewPassword();
+ if (pwd == NULL || strnlen_s(pwd, PASSWORD_MAX_LEN) == 0) {
+ ret = ERR_GENERAL_FAIL;
+ goto cleanup;
+ }
+
+ do {
+ ret = GenerateEntropy(entropy, entropyLen, pwd);
+ CHECK_ERRCODE_BREAK("generate entropy", ret);
+
+ ret = bip39_mnemonic_from_bytes(NULL, entropy, entropyLen, &mnemonic);
+ CHECK_ERRCODE_BREAK("generate mnemonic", ret);
+
+ SecretCacheSetEntropy(entropy, entropyLen);
+ SecretCacheSetMnemonic(mnemonic);
+ } while (0);
+
+cleanup:
+ if (mnemonic != NULL) {
+ memset_s(mnemonic, strnlen_s(mnemonic, MNEMONIC_MAX_LEN), 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
+ SRAM_FREE(mnemonic);
+ }
+ if (ret != SUCCESS_CODE) {
+ // This error path should theoretically not be reached if entropy generation and mnemonic creation work correctly
+ GuiApiEmitSignal(SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC_FAIL, &ret, sizeof(ret));
+ } else {
+ GuiApiEmitSignal(SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC, &ret, sizeof(ret));
+ }
+ CLEAR_ARRAY(entropy);
SetLockScreen(enable);
- return SUCCESS_CODE;
+ return ret;
}
static int32_t ModelGenerateEntropyWithDiceRolls(const void *inData, uint32_t inDataLen)
{
bool enable = IsPreviousLockScreenEnable();
SetLockScreen(false);
- int32_t retData;
+ int32_t ret = SUCCESS_CODE;
char *mnemonic = NULL;
uint8_t entropy[32];
- uint8_t *hash;
+ uint8_t *hash = NULL;
uint32_t mnemonicNum, entropyLen;
mnemonicNum = *((uint32_t *)inData);
- entropyLen = (mnemonicNum == 24) ? 32 : 16;
- // GenerateEntropy(entropy, entropyLen, SecretCacheGetNewPassword());
- hash = SecretCacheGetDiceRollHash();
- memcpy_s(entropy, sizeof(entropy), hash, entropyLen);
- SecretCacheSetEntropy(entropy, entropyLen);
- bip39_mnemonic_from_bytes(NULL, entropy, entropyLen, &mnemonic);
- SecretCacheSetMnemonic(mnemonic);
- retData = SUCCESS_CODE;
- GuiEmitSignal(SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC, &retData, sizeof(retData));
- memset_s(mnemonic, strnlen_s(mnemonic, MNEMONIC_MAX_LEN), 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
- SRAM_FREE(mnemonic);
+
+ do {
+ if (mnemonicNum != 12 && mnemonicNum != 24) {
+ ret = ERR_GENERAL_FAIL;
+ break;
+ }
+ entropyLen = (mnemonicNum == 24) ? 32 : 16;
+ hash = SecretCacheGetDiceRollHash();
+ memcpy_s(entropy, sizeof(entropy), hash, entropyLen);
+ SecretCacheSetEntropy(entropy, entropyLen);
+
+ ret = bip39_mnemonic_from_bytes(NULL, entropy, entropyLen, &mnemonic);
+ CHECK_ERRCODE_BREAK("generate mnemonic", ret);
+
+ SecretCacheSetMnemonic(mnemonic);
+ } while (0);
+
+ if (mnemonic != NULL) {
+ size_t mlen = strnlen_s(mnemonic, MNEMONIC_MAX_LEN);
+ memset_s(mnemonic, mlen, 0, mlen);
+ SRAM_FREE(mnemonic);
+ }
+ if (ret == SUCCESS_CODE) {
+ GuiEmitSignal(SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC, &ret, sizeof(ret));
+ } else {
+ GuiEmitSignal(SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC_FAIL, &ret, sizeof(ret));
+ }
+ CLEAR_ARRAY(entropy);
SetLockScreen(enable);
- return SUCCESS_CODE;
+ return ret;
}
static int32_t ModelParseTransactionRawData(const void *inData, uint32_t inDataLen)
{
UserDelay(100);
GuiApiEmitSignal(SIG_SHOW_TRANSACTION_LOADING_DELAY, NULL, 0);
+ return SUCCESS_CODE;
}
static int32_t ModelTransactionParseRawDataDelay(const void *inData, uint32_t inDataLen)
{
GuiApiEmitSignal(SIG_HIDE_TRANSACTION_PARSE_LOADING_DELAY, NULL, 0);
+ return SUCCESS_CODE;
}
// Generate bip39 wallet writes
@@ -402,7 +453,8 @@ static int32_t ModelWriteEntropyAndSeed(const void *inData, uint32_t inDataLen)
ret = CreateNewAccount(newAccount, entropy, entropyLen, SecretCacheGetNewPassword());
ClearAccountPassphrase(newAccount);
if (strnlen_s(SecretCacheGetPassphrase(), PASSPHRASE_MAX_LEN) > 0) {
- SetPassphrase(GetCurrentAccountIndex(), SecretCacheGetPassphrase(), SecretCacheGetNewPassword());
+ ret = SetPassphrase(GetCurrentAccountIndex(), SecretCacheGetPassphrase(), SecretCacheGetNewPassword());
+ CHECK_ERRCODE_BREAK("set passphrase error", ret);
SetPassphraseQuickAccess(GuiPassphraseQuickAccess());
}
MODEL_WRITE_SE_END
@@ -415,17 +467,16 @@ static int32_t ModelBip39CalWriteEntropyAndSeed(const void *inData, uint32_t inD
{
bool enable = IsPreviousLockScreenEnable();
SetLockScreen(false);
- int32_t ret;
- uint8_t *entropy;
+ int32_t ret = SUCCESS_CODE;
+ uint8_t *entropy = NULL;
size_t entropyInLen;
size_t entropyOutLen;
Bip39Data_t *bip39Data = (Bip39Data_t *)inData;
- uint8_t newAccount;
- uint8_t accountCnt;
- AccountInfo_t accountInfo;
+ uint8_t newAccount = 0;
+ uint8_t accountCnt = 0;
+ AccountInfo_t accountInfo = {0};
entropyInLen = bip39Data->wordCnt * 16 / 12;
-
entropy = SRAM_MALLOC(entropyInLen);
MODEL_WRITE_SE_HEAD
@@ -439,13 +490,15 @@ static int32_t ModelBip39CalWriteEntropyAndSeed(const void *inData, uint32_t inD
CHECK_ERRCODE_BREAK("mnemonic repeat", ret);
}
if (bip39Data->forget) {
- GetAccountInfo(newAccount, &accountInfo);
+ ret = GetAccountInfo(newAccount, &accountInfo);
+ CHECK_ERRCODE_BREAK("get account info error", ret);
}
ret = CreateNewAccount(newAccount, entropy, (uint8_t)entropyOutLen, SecretCacheGetNewPassword());
CHECK_ERRCODE_BREAK("save entropy error", ret);
ClearAccountPassphrase(newAccount);
if (strnlen_s(SecretCacheGetPassphrase(), PASSPHRASE_MAX_LEN) > 0) {
- SetPassphrase(GetCurrentAccountIndex(), SecretCacheGetPassphrase(), SecretCacheGetNewPassword());
+ ret = SetPassphrase(GetCurrentAccountIndex(), SecretCacheGetPassphrase(), SecretCacheGetNewPassword());
+ CHECK_ERRCODE_BREAK("set passphrase error", ret);
SetPassphraseQuickAccess(GuiPassphraseQuickAccess());
}
ret = VerifyPasswordAndLogin(&newAccount, SecretCacheGetNewPassword());
@@ -458,7 +511,6 @@ static int32_t ModelBip39CalWriteEntropyAndSeed(const void *inData, uint32_t inD
CloseUsb();
}
GetExistAccountNum(&accountCnt);
- printf("after accountCnt = %d\n", accountCnt);
}
while (0);
if (ret == SUCCESS_CODE)
@@ -470,6 +522,7 @@ if (ret == SUCCESS_CODE)
GuiApiEmitSignal(SIG_CREAT_SINGLE_PHRASE_WRITE_SE_FAIL, &ret, sizeof(ret));
}
memset_s(entropy, entropyInLen, 0, entropyInLen);
+memset_s(&accountInfo, sizeof(accountInfo), 0, sizeof(accountInfo));
SRAM_FREE(entropy);
SetLockScreen(enable);
return 0;
@@ -601,7 +654,7 @@ static int32_t ModelComparePubkey(MnemonicType mnemonicType, uint8_t *ems, uint8
bool ton = false;
#endif
uint8_t seed[64] = {0};
- int ret = 0;
+ int ret = SUCCESS_CODE;
uint8_t existIndex = 0;
if (ton) {
#ifdef WEB3_VERSION
@@ -610,9 +663,14 @@ static int32_t ModelComparePubkey(MnemonicType mnemonicType, uint8_t *ems, uint8
CalculateTonChecksum(entropyResult->data, checksum);
free_VecFFI_u8(entropyResult);
char value[65] = {0};
- for (size_t i = 0; i < 32; i++) {
- snprintf_s(value, 65, "%s%02x", value, checksum[i]);
+ size_t offset = 0;
+ for (size_t i = 0; i < 32 && offset < 64; i++) {
+ int written = snprintf_s(value + offset, 65 - offset, "%02x", checksum[i]);
+ if (written > 0) {
+ offset += written;
+ }
}
+ value[64] = '\0';
existIndex = SpecifiedXPubExist(value, ton);
if (index != NULL) {
*index = existIndex;
@@ -628,10 +686,12 @@ static int32_t ModelComparePubkey(MnemonicType mnemonicType, uint8_t *ems, uint8
SimpleResponse_c_char *xPubResult;
if (bip39) {
ret = bip39_mnemonic_to_seed(SecretCacheGetMnemonic(), NULL, seed, 64, NULL);
+ CHECK_ERRCODE_BREAK("bip39_mnemonic_to_seed", ret);
xPubResult = get_extended_pubkey_by_seed(seed, 64, "M/49'/0'/0'");
}
if (slip39) {
ret = Slip39GetSeed(ems, seed, emsLen, "", ie, eb, id);
+ CHECK_ERRCODE_BREAK("Slip39GetSeed", ret);
xPubResult = get_extended_pubkey_by_seed(seed, emsLen, "M/49'/0'/0'");
}
@@ -657,20 +717,47 @@ static int32_t Slip39CreateGenerate(Slip39Data_t *slip39, bool isDiceRoll)
{
bool enable = IsPreviousLockScreenEnable();
SetLockScreen(false);
- uint8_t entropy[32], ems[32];
- uint32_t entropyLen;
- uint16_t id;
- uint8_t ie;
- bool eb;
- entropyLen = (slip39->wordCnt == 20) ? 16 : 32;
- char *wordsList[slip39->memberCnt];
+ int32_t ret = ERR_GENERAL_FAIL;
+ uint8_t entropy[32] = {0}, ems[32] = {0};
+ uint32_t entropyLen = 0;
+ uint16_t id = 0;
+ uint8_t ie = 0;
+ bool eb = false;
+ char *wordsList[SLIP39_MAX_MEMBER];
+
+ if (slip39 == NULL) {
+ goto cleanup;
+ }
+ if (!(slip39->wordCnt == SLIP39_MNEMONIC_20_WORDS || slip39->wordCnt == SLIP39_MNEMONIC_33_WORDS)) {
+ goto cleanup;
+ }
+ if (slip39->memberCnt == 0 || slip39->threShold == 0 || slip39->threShold > slip39->memberCnt || slip39->memberCnt > SLIP39_MAX_MEMBER) {
+ goto cleanup;
+ }
+
+ entropyLen = (slip39->wordCnt == SLIP39_MNEMONIC_20_WORDS) ? 16 : 32;
+
if (isDiceRoll) {
- memcpy_s(entropy, sizeof(entropy), SecretCacheGetDiceRollHash(), entropyLen);
+ const uint8_t *dice = SecretCacheGetDiceRollHash();
+ if (dice == NULL) goto cleanup;
+ memcpy_s(entropy, sizeof(entropy), dice, entropyLen);
} else {
- GenerateEntropy(entropy, entropyLen, SecretCacheGetNewPassword());
+ const char *pwd = SecretCacheGetNewPassword();
+ if (pwd == NULL || strnlen_s(pwd, PASSWORD_MAX_LEN) == 0) {
+ goto cleanup;
+ }
+ ret = GenerateEntropy(entropy, entropyLen, pwd);
+ if (ret != SUCCESS_CODE) {
+ goto cleanup;
+ }
+ }
+
+ ret = GetSlip39MnemonicsWords(entropy, ems, slip39->wordCnt, slip39->memberCnt, slip39->threShold, wordsList, &id, &eb, &ie);
+ if (ret != SUCCESS_CODE) {
+ goto cleanup_words;
}
+
SecretCacheSetEntropy(entropy, entropyLen);
- GetSlip39MnemonicsWords(entropy, ems, slip39->wordCnt, slip39->memberCnt, slip39->threShold, wordsList, &id, &eb, &ie);
SecretCacheSetEms(ems, entropyLen);
SecretCacheSetIdentifier(id);
SecretCacheSetIteration(ie);
@@ -678,14 +765,23 @@ static int32_t Slip39CreateGenerate(Slip39Data_t *slip39, bool isDiceRoll)
for (int i = 0; i < slip39->memberCnt; i++) {
SecretCacheSetSlip39Mnemonic(wordsList[i], i);
}
+ GuiApiEmitSignal(SIG_CREATE_SHARE_UPDATE_MNEMONIC, NULL, 0);
+cleanup_words:
for (int i = 0; i < slip39->memberCnt; i++) {
- memset_s(wordsList[i], strlen(wordsList[i]), 0, strlen(wordsList[i]));
- SRAM_FREE(wordsList[i]);
+ if (wordsList[i] != NULL) {
+ memset_s(wordsList[i], strlen(wordsList[i]), 0, strlen(wordsList[i]));
+ SRAM_FREE(wordsList[i]);
+ }
}
- GuiApiEmitSignal(SIG_CREATE_SHARE_UPDATE_MNEMONIC, NULL, 0);
+cleanup:
+ if (ret != SUCCESS_CODE) {
+ GuiApiEmitSignal(SIG_CREATE_SHARE_UPDATE_MNEMONIC_FAIL, NULL, 0);
+ }
+ CLEAR_ARRAY(ems);
+ CLEAR_ARRAY(entropy);
SetLockScreen(enable);
- return SUCCESS_CODE;
+ return ret;
}
// slip39 generate
@@ -705,16 +801,16 @@ static int32_t ModelSlip39WriteEntropy(const void *inData, uint32_t inDataLen)
{
bool enable = IsPreviousLockScreenEnable();
SetLockScreen(false);
- uint8_t *entropy;
- uint8_t *ems;
- uint32_t entropyLen;
- uint8_t newAccount;
- uint8_t accountCnt;
- uint16_t id;
- uint8_t ie;
- bool eb;
- uint8_t msCheck[32], emsCheck[32];
- uint8_t threShold;
+ uint8_t *entropy = NULL;
+ uint8_t *ems = NULL;
+ uint32_t entropyLen = 0;
+ uint8_t newAccount = 0;
+ uint8_t accountCnt = 0;
+ uint16_t id = 0;
+ uint8_t ie = 0;
+ bool eb = false;
+ uint8_t msCheck[32] = {0}, emsCheck[32] = {0};
+ uint8_t threShold = 0;
uint8_t wordCnt = *(uint8_t *)inData;
int ret;
@@ -725,6 +821,10 @@ static int32_t ModelSlip39WriteEntropy(const void *inData, uint32_t inDataLen)
ie = SecretCacheGetIteration();
MODEL_WRITE_SE_HEAD
+ if (wordCnt != SLIP39_MNEMONIC_20_WORDS || wordCnt != SLIP39_MNEMONIC_33_WORDS) {
+ ret = ERR_KEYSTORE_MNEMONIC_INVALID;
+ break;
+ }
ret = Slip39CheckFirstWordList(SecretCacheGetSlip39Mnemonic(0), wordCnt, &threShold);
char *words[threShold];
for (int i = 0; i < threShold; i++) {
@@ -743,7 +843,8 @@ static int32_t ModelSlip39WriteEntropy(const void *inData, uint32_t inDataLen)
CHECK_ERRCODE_BREAK("save slip39 entropy error", ret);
ClearAccountPassphrase(newAccount);
if (strnlen_s(SecretCacheGetPassphrase(), PASSPHRASE_MAX_LEN) > 0) {
- SetPassphrase(GetCurrentAccountIndex(), SecretCacheGetPassphrase(), SecretCacheGetNewPassword());
+ ret = SetPassphrase(GetCurrentAccountIndex(), SecretCacheGetPassphrase(), SecretCacheGetNewPassword());
+ CHECK_ERRCODE_BREAK("set passphrase error", ret);
SetPassphraseQuickAccess(GuiPassphraseQuickAccess());
}
MODEL_WRITE_SE_END
@@ -802,7 +903,8 @@ static int32_t ModelSlip39CalWriteEntropyAndSeed(const void *inData, uint32_t in
CHECK_ERRCODE_BREAK("save slip39 entropy error", ret);
ClearAccountPassphrase(newAccount);
if (strnlen_s(SecretCacheGetPassphrase(), PASSPHRASE_MAX_LEN) > 0) {
- SetPassphrase(GetCurrentAccountIndex(), SecretCacheGetPassphrase(), SecretCacheGetNewPassword());
+ ret = SetPassphrase(GetCurrentAccountIndex(), SecretCacheGetPassphrase(), SecretCacheGetNewPassword());
+ CHECK_ERRCODE_BREAK("set passphrase error", ret);
SetPassphraseQuickAccess(GuiPassphraseQuickAccess());
}
ret = VerifyPasswordAndLogin(&newAccount, SecretCacheGetNewPassword());
@@ -1503,7 +1605,7 @@ static int32_t ModelTonVerifyMnemonic(const void *inData, uint32_t inDataLen);
static int32_t ModelTonWriteEntropyAndSeed(const void *inData, uint32_t inDataLen);
static int32_t ModelGenerateTonMnemonic(const void *inData, uint32_t inDataLen);
static int32_t ModelTonForgetPass(const void *inData, uint32_t inDataLen);
-static int32_t ModelRsaGenerateKeyPair();
+static int32_t ModelRsaGenerateKeyPair(const void *inData, uint32_t inDataLen);
void GuiModelRsaGenerateKeyPair(void)
{
@@ -1536,8 +1638,10 @@ void GuiModelTonForgetPassword()
AsyncExecute(ModelTonForgetPass, NULL, 0);
}
-static int32_t ModelRsaGenerateKeyPair()
+static int32_t ModelRsaGenerateKeyPair(const void *inData, uint32_t inDataLen)
{
+ UNUSED(inData);
+ UNUSED(inDataLen);
return RsaGenerateKeyPair(true);
}
@@ -1546,20 +1650,29 @@ static int32_t ModelGenerateTonMnemonic(const void *inData, uint32_t inDataLen)
{
bool enable = IsPreviousLockScreenEnable();
SetLockScreen(false);
- int32_t retData;
+ UNUSED(inData);
+ UNUSED(inDataLen);
+ int32_t ret = ERR_GENERAL_FAIL;
+ const char *pwd = SecretCacheGetNewPassword();
+ if (pwd == NULL || strnlen_s(pwd, PASSWORD_MAX_LEN) == 0) {
+ goto cleanup;
+ }
char *mnemonic = SRAM_MALLOC(MNEMONIC_MAX_LEN);
memset_s(mnemonic, MNEMONIC_MAX_LEN, 0, MNEMONIC_MAX_LEN);
- GuiEmitSignal(SIG_CREAT_SINGLE_PHRASE_TON_GENERATION_START, NULL, 0);
- GenerateTonMnemonic(mnemonic, SecretCacheGetNewPassword());
- SecretCacheSetMnemonic(mnemonic);
- GuiEmitSignal(SIG_CREAT_SINGLE_PHRASE_TON_GENERATION_END, NULL, 0);
- retData = SUCCESS_CODE;
- GuiEmitSignal(SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC, &retData, sizeof(retData));
+ do {
+ GuiEmitSignal(SIG_CREAT_SINGLE_PHRASE_TON_GENERATION_START, NULL, 0);
+ ret = GenerateTonMnemonic(mnemonic, pwd);
+ CHECK_ERRCODE_BREAK("generate ton mnemonic", ret);
+ SecretCacheSetMnemonic(mnemonic);
+ GuiEmitSignal(SIG_CREAT_SINGLE_PHRASE_TON_GENERATION_END, NULL, 0);
+ } while (0);
+ GuiEmitSignal(SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC, &ret, sizeof(ret));
memset_s(mnemonic, strnlen_s(mnemonic, MNEMONIC_MAX_LEN), 0, strnlen_s(mnemonic, MNEMONIC_MAX_LEN));
SRAM_FREE(mnemonic);
+cleanup:
SetLockScreen(enable);
ClearLockScreenTime();
- return SUCCESS_CODE;
+ return ret;
}
// ton generate
@@ -1589,18 +1702,15 @@ static int32_t ModelTonCalWriteEntropyAndSeed(const void *inData, uint32_t inDat
{
bool enable = IsPreviousLockScreenEnable();
SetLockScreen(false);
- int32_t ret;
+ int32_t ret = SUCCESS_CODE;
TonData_t *tonData = (TonData_t *)inData;
- uint8_t newAccount;
- uint8_t accountCnt;
- AccountInfo_t accountInfo;
+ uint8_t newAccount = 0;
+ uint8_t accountCnt = 0;
+ AccountInfo_t accountInfo = {0};
MODEL_WRITE_SE_HEAD
bool isValid = ton_verify_mnemonic(SecretCacheGetMnemonic());
- if (!isValid) {
- printf("invalid ton mnemonic , line=%d\r\n", __LINE__);
- break;
- }
+ CHECK_ERRCODE_BREAK("invalid ton mnemonic", !isValid);
if (tonData->forget) {
ret = ModelComparePubkey(MNEMONIC_TYPE_TON, NULL, 0, 0, false, 0, &newAccount);
CHECK_ERRCODE_BREAK("mnemonic not match", !ret);
@@ -1609,7 +1719,8 @@ static int32_t ModelTonCalWriteEntropyAndSeed(const void *inData, uint32_t inDat
CHECK_ERRCODE_BREAK("mnemonic repeat", ret);
}
if (tonData->forget) {
- GetAccountInfo(newAccount, &accountInfo);
+ ret = GetAccountInfo(newAccount, &accountInfo);
+ CHECK_ERRCODE_BREAK("get account info error", ret);
}
ret = CreateNewTonAccount(newAccount, SecretCacheGetMnemonic(), SecretCacheGetNewPassword());
CHECK_ERRCODE_BREAK("save entropy error", ret);
@@ -1623,8 +1734,6 @@ static int32_t ModelTonCalWriteEntropyAndSeed(const void *inData, uint32_t inDat
CloseUsb();
}
UpdateFingerSignFlag(GetCurrentAccountIndex(), false);
- GetExistAccountNum(&accountCnt);
- printf("after accountCnt = %d\n", accountCnt);
}
while (0);
if (ret == SUCCESS_CODE)
@@ -1636,8 +1745,9 @@ if (ret == SUCCESS_CODE)
GuiApiEmitSignal(SIG_CREAT_SINGLE_PHRASE_WRITE_SE_FAIL, &ret, sizeof(ret));
}
SetLockScreen(enable);
+memset_s(&accountInfo, sizeof(accountInfo), 0, sizeof(accountInfo));
ClearLockScreenTime();
-return 0;
+return ret;
}
// Auxiliary word verification for ton
@@ -1715,29 +1825,50 @@ static int32_t ModelTonForgetPass(const void *inData, uint32_t inDataLen)
int32_t RsaGenerateKeyPair(bool needEmitSignal)
{
- printf("RsaGenerate RsaGenerate RsaGenerate");
bool lockState = IsPreviousLockScreenEnable();
SetLockScreen(false);
if (needEmitSignal) {
GuiApiEmitSignal(SIG_SETUP_RSA_PRIVATE_KEY_WITH_PASSWORD_START, NULL, 0);
}
- uint8_t seed[64];
- int len = GetMnemonicType() == MNEMONIC_TYPE_BIP39 ? sizeof(seed) : GetCurrentAccountEntropyLen();
- int32_t ret = GetAccountSeed(GetCurrentAccountIndex(), seed, SecretCacheGetPassword());
- ASSERT(ret == 0);
- SimpleResponse_u8 *secret = generate_arweave_secret(seed, len);
- ASSERT(secret != NULL && secret->error_code == 0);
- FlashWriteRsaPrimes(secret->data);
- free_simple_response_u8(secret);
- GuiApiEmitSignal(SIG_SETUP_RSA_PRIVATE_KEY_GENERATE_ADDRESS, NULL, 0);
- AccountPublicInfoSwitch(GetCurrentAccountIndex(), SecretCacheGetPassword(), true);
- RecalculateManageWalletState();
- ClearLockScreenTime();
- SetLockScreen(lockState);
+
+ int32_t ret = SUCCESS_CODE;
+ uint8_t seed[SEED_LEN] = {0};
+ SimpleResponse_u8* secret = NULL;
+
+ do {
+ int len = GetMnemonicType() == MNEMONIC_TYPE_BIP39 ? sizeof(seed) : GetCurrentAccountEntropyLen();
+
+ ret = GetAccountSeed(GetCurrentAccountIndex(), seed, SecretCacheGetPassword());
+ CHECK_ERRCODE_BREAK("get account seed", ret);
+
+ secret = generate_arweave_secret(seed, len);
+ CHECK_ERRCODE_BREAK("generate arweave secret", secret->error_code);
+
+ ret = FlashWriteRsaPrimes(secret->data);
+ CHECK_ERRCODE_BREAK("flash write rsa primes", ret);
+
+ GuiApiEmitSignal(SIG_SETUP_RSA_PRIVATE_KEY_GENERATE_ADDRESS, NULL, 0);
+
+ ret = AccountPublicInfoSwitch(GetCurrentAccountIndex(), SecretCacheGetPassword(), true);
+ CHECK_ERRCODE_BREAK("account public info switch", ret);
+
+ RecalculateManageWalletState();
+ } while (0);
+
if (needEmitSignal) {
- GuiApiEmitSignal(SIG_SETUP_RSA_PRIVATE_KEY_WITH_PASSWORD_PASS, NULL, 0);
+ if (ret == SUCCESS_CODE) {
+ GuiApiEmitSignal(SIG_SETUP_RSA_PRIVATE_KEY_WITH_PASSWORD_PASS, NULL, 0);
+ } else {
+ GuiApiEmitSignal(SIG_SETUP_RSA_PRIVATE_KEY_WRITE_FAIL, &ret, sizeof(ret));
+ }
GuiApiEmitSignal(SIG_SETUP_RSA_PRIVATE_KEY_HIDE_LOADING, NULL, 0);
}
- return SUCCESS_CODE;
+ memset_s(seed, sizeof(seed), 0, sizeof(seed));
+ if (secret != NULL) {
+ free_simple_response_u8(secret);
+ }
+ SetLockScreen(lockState);
+ ClearLockScreenTime();
+ return ret;
}
#endif
\ No newline at end of file
diff --git a/src/ui/gui_views/gui_views.h b/src/ui/gui_views/gui_views.h
index c55c612..4045c94 100644
--- a/src/ui/gui_views/gui_views.h
+++ b/src/ui/gui_views/gui_views.h
@@ -63,12 +63,14 @@ typedef enum {
SIG_CREATE_SHARE_VIEW_NEXT_SLICE = SIG_SETUP_VIEW_BUTT + 50,
SIG_CREATE_SHARE_UPDATE_MNEMONIC,
+ SIG_CREATE_SHARE_UPDATE_MNEMONIC_FAIL,
SIG_CREATE_SHARE_VIEW_BUTT,
SIG_IMPORT_SHARE_VIEW_NEXT_SLICE = SIG_CREATE_SHARE_VIEW_BUTT + 100,
SIG_IMPORT_SHARE_VIEW_BUTT,
SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC = SIG_IMPORT_SHARE_VIEW_BUTT + 100,
+ SIG_CREAT_SINGLE_PHRASE_UPDATE_MNEMONIC_FAIL,
SIG_CREAT_SINGLE_PHRASE_WRITE_SE_SUCCESS,
SIG_CREAT_SINGLE_PHRASE_WRITE_SE_FAIL,
SIG_CREAT_SINGLE_PHRASE_TON_GENERATION_START,
@@ -162,6 +164,7 @@ typedef enum {
SIG_SETUP_RSA_PRIVATE_KEY_RECEIVE_CONFIRM = SIG_TRANSACTION_BUTT + 50,
SIG_SETUP_RSA_PRIVATE_KEY_CONNECT_CONFIRM,
SIG_SETUP_RSA_PRIVATE_KEY_PARSER_CONFIRM,
+ SIG_SETUP_RSA_PRIVATE_KEY_WRITE_FAIL,
SIG_SETUP_RSA_PRIVATE_KEY_TX_CONFIRM,
SIG_SETUP_RSA_PRIVATE_KEY_WITH_PASSWORD,
SIG_SETUP_RSA_PRIVATE_KEY_RSA_VERIFY_PASSWORD_FAIL,
diff --git a/src/ui/gui_widgets/gui_create_wallet_widgets.h b/src/ui/gui_widgets/gui_create_wallet_widgets.h
index 2752773..ac87c58 100644
--- a/src/ui/gui_widgets/gui_create_wallet_widgets.h
+++ b/src/ui/gui_widgets/gui_create_wallet_widgets.h
@@ -20,7 +20,7 @@ bool GuiCreateWalletNeedPassphrase(void);
#define WALLET_TYPE_TON 0b00000010
#define ENTROPY_TYPE_STANDARD 0b00000000
-#define ENTORPY_TYPE_DICE_ROLLS 0b00000001
+#define ENTROPY_TYPE_DICE_ROLLS 0b00000001
#define WALLET_TYPE_MASK 0b00000010
#define ENTROPY_TYPE_MASK 0b00000001
diff --git a/src/ui/gui_widgets/gui_dice_rolls_widgets.c b/src/ui/gui_widgets/gui_dice_rolls_widgets.c
index 63b054f..f4c5796 100644
--- a/src/ui/gui_widgets/gui_dice_rolls_widgets.c
+++ b/src/ui/gui_widgets/gui_dice_rolls_widgets.c
@@ -6,6 +6,7 @@
#include "gui_create_wallet_widgets.h"
#include "sha256.h"
#include "log_print.h"
+#include "assert.h"
#define DICE_ROLLS_MAX_LEN 256
@@ -301,23 +302,28 @@ static void ConfirmHandler(lv_event_t *e)
// convert result
const char *txt = lv_textarea_get_text(ta);
- char *temp = SRAM_MALLOC(BUFFER_SIZE_512);
- size_t len = strnlen_s(txt, BUFFER_SIZE_512);
- strcpy_s(temp, BUFFER_SIZE_512, txt);
- for (size_t i = 0; i < len; i++) {
+ char *temp = SRAM_MALLOC(DICE_ROLLS_MAX_LEN + 1);
+ size_t rollsLen = strnlen_s(txt, DICE_ROLLS_MAX_LEN);
+ strcpy_s(temp, DICE_ROLLS_MAX_LEN + 1, txt);
+ for (size_t i = 0; i < rollsLen; i++) {
char c = temp[i];
+ if (c < '1' || c > '6') {
+ ASSERT(false);
+ }
if (c == '6') {
temp[i] = '0';
}
}
uint8_t hash[32] = {0};
- sha256((struct sha256 *)hash, temp, strnlen_s(temp, BUFFER_SIZE_512));
- uint8_t entropyMethod = 1;
+ sha256((struct sha256 *)hash, temp, rollsLen);
+ memset_s(temp, DICE_ROLLS_MAX_LEN + 1, 0, DICE_ROLLS_MAX_LEN + 1);
+ SRAM_FREE(temp);
+ uint8_t entropyMethod = ENTROPY_TYPE_DICE_ROLLS;
SecretCacheSetDiceRollHash(hash);
+ CLEAR_ARRAY(hash);
if (g_seedType == SEED_TYPE_BIP39) {
- GuiFrameOpenViewWithParam(&g_singlePhraseView, &entropyMethod, 1);
+ GuiFrameOpenViewWithParam(&g_singlePhraseView, &entropyMethod, sizeof(entropyMethod));
} else {
- GuiFrameOpenViewWithParam(&g_createShareView, &entropyMethod, 1);
+ GuiFrameOpenViewWithParam(&g_createShareView, &entropyMethod, sizeof(entropyMethod));
}
- SRAM_FREE(temp);
}
\ No newline at end of file
diff --git a/src/ui/gui_widgets/gui_forget_pass_widgets.c b/src/ui/gui_widgets/gui_forget_pass_widgets.c
index 03d83a6..27d9582 100644
--- a/src/ui/gui_widgets/gui_forget_pass_widgets.c
+++ b/src/ui/gui_widgets/gui_forget_pass_widgets.c
@@ -98,14 +98,14 @@ static void StopCreateViewHandler(lv_event_t *e)
lv_obj_add_event_cb(rightBtn, ContinueStopCreateHandler, LV_EVENT_CLICKED, NULL);
}
-void GuiForgetAnimContDel(int errCode)
+void GuiForgetAnimContDel(bool isReset)
{
if (g_waitAnimCont != NULL) {
lv_obj_del(g_waitAnimCont);
g_waitAnimCont = NULL;
}
- if (errCode == 0) {
+ if (isReset) {
g_waitAnimCont = GuiCreateAnimHintBox(480, 326, 82);
lv_obj_t *title = GuiCreateLittleTitleLabel(g_waitAnimCont, _("change_passcode_reset_title"));
lv_obj_align(title, LV_ALIGN_BOTTOM_MID, 0, -124);
@@ -190,7 +190,7 @@ void GuiForgetPassRepeatPinPass(const char* buf)
if (!strcmp(buf, g_pinBuf)) {
SecretCacheSetNewPassword((char *)buf);
memset_s(g_pinBuf, sizeof(g_pinBuf), 0, sizeof(g_pinBuf));
- GuiForgetAnimContDel(0);
+ GuiForgetAnimContDel(true);
if (g_forgetMkb->wordCnt == 33 || g_forgetMkb->wordCnt == 20) {
Slip39Data_t slip39 = {
.threShold = g_forgetMkb->threShold,
diff --git a/src/ui/gui_widgets/gui_forget_pass_widgets.h b/src/ui/gui_widgets/gui_forget_pass_widgets.h
index 7788dd2..f51a33c 100644
--- a/src/ui/gui_widgets/gui_forget_pass_widgets.h
+++ b/src/ui/gui_widgets/gui_forget_pass_widgets.h
@@ -1,7 +1,7 @@
#ifndef _GUI_FORGET_PASS_WIDGETS_H
#define _GUI_FORGET_PASS_WIDGETS_H
-void GuiForgetAnimContDel(int errCode);
+void GuiForgetAnimContDel(bool isReset);
void GuiForgetPassInit(void *param);
void GuiForgetPassRefresh(void);
int8_t GuiForgetPassNextTile(uint8_t tileIndex);
Why this scored 61/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.