From a4afbce8ed0f8b710a34b32ab9211c861be08bb6 Mon Sep 17 00:00:00 2001 From: Satoshi Otomakan Date: Mon, 16 Oct 2023 16:50:15 +0200 Subject: [PATCH 1/2] [Crypto]: Replace scrypt.c with Rust's `crypto_scrypt` --- rust/Cargo.lock | 51 +++ rust/Cargo.toml | 1 + rust/tw_keystore/Cargo.toml | 12 + rust/tw_keystore/fuzz/.gitignore | 5 + rust/tw_keystore/fuzz/Cargo.toml | 27 ++ .../fuzz/fuzz_targets/crypto_scrypt.rs | 36 ++ rust/tw_keystore/src/crypto_scrypt/mod.rs | 42 +++ rust/tw_keystore/src/crypto_scrypt/params.rs | 94 +++++ rust/tw_keystore/src/crypto_scrypt/romix.rs | 82 +++++ rust/tw_keystore/src/ffi/crypto_scrypt.rs | 70 ++++ rust/tw_keystore/src/ffi/mod.rs | 7 + rust/tw_keystore/src/lib.rs | 8 + rust/tw_keystore/tests/crypto_scrypt.rs | 44 +++ rust/tw_keystore/tests/crypto_scrypt_ffi.rs | 36 ++ rust/tw_memory/src/ffi/c_byte_array_ref.rs | 2 +- rust/wallet_core_rs/Cargo.toml | 1 + rust/wallet_core_rs/cbindgen.toml | 2 + rust/wallet_core_rs/src/lib.rs | 1 + src/Keystore/EncryptionParameters.cpp | 29 +- src/rust/Wrapper.h | 4 + trezor-crypto/CMakeLists.txt | 1 - trezor-crypto/crypto/scrypt.c | 343 ------------------ trezor-crypto/include/TrezorCrypto/scrypt.h | 68 ---- 23 files changed, 544 insertions(+), 422 deletions(-) create mode 100644 rust/tw_keystore/Cargo.toml create mode 100644 rust/tw_keystore/fuzz/.gitignore create mode 100644 rust/tw_keystore/fuzz/Cargo.toml create mode 100644 rust/tw_keystore/fuzz/fuzz_targets/crypto_scrypt.rs create mode 100644 rust/tw_keystore/src/crypto_scrypt/mod.rs create mode 100644 rust/tw_keystore/src/crypto_scrypt/params.rs create mode 100644 rust/tw_keystore/src/crypto_scrypt/romix.rs create mode 100644 rust/tw_keystore/src/ffi/crypto_scrypt.rs create mode 100644 rust/tw_keystore/src/ffi/mod.rs create mode 100644 rust/tw_keystore/src/lib.rs create mode 100644 rust/tw_keystore/tests/crypto_scrypt.rs create mode 100644 rust/tw_keystore/tests/crypto_scrypt_ffi.rs delete mode 100644 trezor-crypto/crypto/scrypt.c delete mode 100644 trezor-crypto/include/TrezorCrypto/scrypt.h diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 7ae598db1fd..82ef3615b49 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -296,6 +296,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" version = "2.34.0" @@ -662,6 +672,15 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + [[package]] name = "itertools" version = "0.10.5" @@ -865,6 +884,16 @@ dependencies = [ "nom", ] +[[package]] +name = "pbkdf2" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31" +dependencies = [ + "digest 0.10.6", + "hmac", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -1091,6 +1120,15 @@ version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "sec1" version = "0.7.1" @@ -1561,6 +1599,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "tw_keystore" +version = "0.1.0" +dependencies = [ + "pbkdf2", + "salsa20", + "sha2 0.10.6", + "tw_encoding", + "tw_memory", + "tw_misc", +] + [[package]] name = "tw_memory" version = "0.1.0" @@ -1700,6 +1750,7 @@ dependencies = [ "tw_ethereum", "tw_hash", "tw_keypair", + "tw_keystore", "tw_memory", "tw_misc", "tw_move_parser", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index b8fdf347fca..e048d20fb37 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -9,6 +9,7 @@ members = [ "tw_evm", "tw_hash", "tw_keypair", + "tw_keystore", "tw_memory", "tw_misc", "tw_move_parser", diff --git a/rust/tw_keystore/Cargo.toml b/rust/tw_keystore/Cargo.toml new file mode 100644 index 00000000000..62dcab9e7a0 --- /dev/null +++ b/rust/tw_keystore/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "tw_keystore" +version = "0.1.0" +edition = "2021" + +[dependencies] +pbkdf2 = "0.12.1" +salsa20 = "0.10.2" +sha2 = "0.10.6" +tw_encoding = { path = "../tw_encoding" } +tw_memory = { path = "../tw_memory" } +tw_misc = { path = "../tw_misc" } diff --git a/rust/tw_keystore/fuzz/.gitignore b/rust/tw_keystore/fuzz/.gitignore new file mode 100644 index 00000000000..5c404b9583f --- /dev/null +++ b/rust/tw_keystore/fuzz/.gitignore @@ -0,0 +1,5 @@ +target +corpus +artifacts +coverage +Cargo.lock diff --git a/rust/tw_keystore/fuzz/Cargo.toml b/rust/tw_keystore/fuzz/Cargo.toml new file mode 100644 index 00000000000..7d95b6ea080 --- /dev/null +++ b/rust/tw_keystore/fuzz/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "tw_keystore-fuzz" +version = "0.0.0" +publish = false +edition = "2021" + +[package.metadata] +cargo-fuzz = true + +[dependencies] +libfuzzer-sys = { version = "0.4", features = ["arbitrary-derive"] } + +[dependencies.tw_keystore] +path = ".." + +# Prevent this from interfering with workspaces +[workspace] +members = ["."] + +[profile.release] +debug = 1 + +[[bin]] +name = "crypto_scrypt" +path = "fuzz_targets/crypto_scrypt.rs" +test = false +doc = false diff --git a/rust/tw_keystore/fuzz/fuzz_targets/crypto_scrypt.rs b/rust/tw_keystore/fuzz/fuzz_targets/crypto_scrypt.rs new file mode 100644 index 00000000000..47016594cc4 --- /dev/null +++ b/rust/tw_keystore/fuzz/fuzz_targets/crypto_scrypt.rs @@ -0,0 +1,36 @@ +// Copyright © 2017-2023 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#![no_main] + +use libfuzzer_sys::{arbitrary, fuzz_target}; +use tw_keystore::crypto_scrypt::{params::Params, scrypt}; + +#[derive(arbitrary::Arbitrary, Debug)] +struct ScryptInput<'a> { + password: &'a [u8], + salt: &'a [u8], + log_n: u8, + r: u32, + p: u32, + desired_len: usize, +} + +fuzz_target!(|input: ScryptInput<'_>| { + // Greater r, p parameters make `scrypt` incredibly slow. + if input.r > 16 || input.p > 16 { + return; + } + + let params = Params { + log_n: input.log_n, + r: input.r, + p: input.p, + desired_len: input.desired_len, + }; + + let _ = scrypt(input.password, input.salt, ¶ms); +}); diff --git a/rust/tw_keystore/src/crypto_scrypt/mod.rs b/rust/tw_keystore/src/crypto_scrypt/mod.rs new file mode 100644 index 00000000000..8e0b475d853 --- /dev/null +++ b/rust/tw_keystore/src/crypto_scrypt/mod.rs @@ -0,0 +1,42 @@ +// Copyright © 2017-2023 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +use crate::crypto_scrypt::params::{InvalidParams, Params}; +use pbkdf2::pbkdf2_hmac; +use sha2::Sha256; + +pub mod params; +mod romix; + +/// The scrypt key derivation function. +/// Original: https://github.com/RustCrypto/password-hashes/blob/a737bef1f992368f165face097d621bb1e76eba4/scrypt/src/lib.rs#L89 +/// +/// The only reason we should have rewritten the function is that it does unnecessary `log_n >= r * 16` check: +/// https://github.com/RustCrypto/password-hashes/blob/a737bef1f992368f165face097d621bb1e76eba4/scrypt/src/params.rs#L67-L72 +pub fn scrypt(password: &[u8], salt: &[u8], params: &Params) -> Result, InvalidParams> { + params.check_params()?; + + // The checks in the `Params::check_params` guarantee + // that the following is safe: + let n = params.n as usize; + let r128 = (params.r as usize) * 128; + let pr128 = (params.p as usize) * r128; + let nr128 = n * r128; + + let mut b = vec![0u8; pr128]; + pbkdf2_hmac::(password, salt, 1, &mut b); + + let mut v = vec![0u8; nr128]; + let mut t = vec![0u8; r128]; + + for chunk in &mut b.chunks_mut(r128) { + romix::scrypt_ro_mix(chunk, &mut v, &mut t, n); + } + + let mut output = vec![0u8; params.desired_len]; + pbkdf2_hmac::(password, &b, 1, &mut output); + Ok(output) +} diff --git a/rust/tw_keystore/src/crypto_scrypt/params.rs b/rust/tw_keystore/src/crypto_scrypt/params.rs new file mode 100644 index 00000000000..e4a76d43e3f --- /dev/null +++ b/rust/tw_keystore/src/crypto_scrypt/params.rs @@ -0,0 +1,94 @@ +// Copyright © 2017-2023 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +use std::mem::size_of; + +#[derive(Clone, Copy, Debug)] +pub struct InvalidParams; + +pub struct Params { + /// Scrypt parameter `N`: CPU/memory cost. + /// Must be a power of 2. + pub n: u32, + /// Scrypt parameter `r`: block size. + pub r: u32, + /// Scrypt parameter `p`: parallelism. + pub p: u32, + /// Scrypt parameter `Key length`. + pub desired_len: usize, +} + +impl Params { + /// Create a new instance of [`Params`]. + /// + /// # Conditions + /// - `log_n` must be less than `64` + /// - `r` must be greater than `0` and less than or equal to `4294967295` + /// - `p` must be greater than `0` and less than `4294967295` + /// - `desired_len` must be greater than `9` and less than or equal to `64` + /// + /// Original: https://github.com/RustCrypto/password-hashes/blob/a737bef1f992368f165face097d621bb1e76eba4/scrypt/src/params.rs#L44 + /// + /// The only reason we should have rewritten the function is that it does unnecessary `log_n >= r * 16` check: + /// https://github.com/RustCrypto/password-hashes/blob/a737bef1f992368f165face097d621bb1e76eba4/scrypt/src/params.rs#L67-L72 + pub fn check_params(&self) -> Result<(), InvalidParams> { + let log_n = self.try_log_n()?; + + let cond1 = (log_n as usize) < usize::BITS as usize; + let cond2 = size_of::() >= size_of::(); + let cond3 = self.r <= usize::MAX as u32 && self.p < usize::MAX as u32; + let cond4 = (10..=64).contains(&self.desired_len); + if !(self.r > 0 && self.p > 0 && cond1 && (cond2 || cond3) && cond4) { + return Err(InvalidParams); + } + + let r = self.r as usize; + let p = self.p as usize; + let n = self.n as usize; + + // check that r * 128 doesn't overflow + let r128 = r.checked_mul(128).ok_or(InvalidParams)?; + + // check that n * r * 128 doesn't overflow + r128.checked_mul(n).ok_or(InvalidParams)?; + + // check that p * r * 128 doesn't overflow + r128.checked_mul(p).ok_or(InvalidParams)?; + + // This check required by Scrypt: + // check: p <= ((2^32-1) * 32) / (128 * r) + // It takes a bit of re-arranging to get the check above into this form, + // but it is indeed the same. + if r * p >= 0x4000_0000 { + return Err(InvalidParams); + } + + // The following checks are copied from C++: + // https://github.com/trustwallet/wallet-core/blob/b530432921d7a9709428b0162673e0ab72de1c3d/src/Keystore/ScryptParameters.cpp#L27-L42 + + if (n & (n - 1)) != 0 || n < 2 { + // Invalid cost factor. + return Err(InvalidParams); + } + + let max_r = u32::MAX as usize / 128_usize / p; + let max_n = u32::MAX as usize / 128 / r; + if r > max_r || n > max_n { + return Err(InvalidParams); + } + + Ok(()) + } + + fn try_log_n(&self) -> Result { + let log_n = self.n.checked_ilog2().ok_or(InvalidParams)?; + // `Params::n` must be equal to 2^log_n. + if 1 << log_n != self.n { + return Err(InvalidParams); + } + log_n.try_into().map_err(|_| InvalidParams) + } +} diff --git a/rust/tw_keystore/src/crypto_scrypt/romix.rs b/rust/tw_keystore/src/crypto_scrypt/romix.rs new file mode 100644 index 00000000000..7da01f0d0f7 --- /dev/null +++ b/rust/tw_keystore/src/crypto_scrypt/romix.rs @@ -0,0 +1,82 @@ +// Copyright © 2017-2023 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +//! Original: https://github.com/RustCrypto/password-hashes/blob/master/scrypt/src/romix.rs + +/// Execute the ROMix operation in-place. +/// b - the data to operate on +/// v - a temporary variable to store the vector V +/// t - a temporary variable to store the result of the xor +/// n - the scrypt parameter N +#[allow(clippy::many_single_char_names)] +pub(crate) fn scrypt_ro_mix(b: &mut [u8], v: &mut [u8], t: &mut [u8], n: usize) { + fn integerify(x: &[u8], n: usize) -> usize { + // n is a power of 2, so n - 1 gives us a bitmask that we can use to perform a calculation + // mod n using a simple bitwise and. + let mask = n - 1; + // This cast is safe since we're going to get the value mod n (which is a power of 2), so we + // don't have to care about truncating any of the high bits off + //let result = (LittleEndian::read_u32(&x[x.len() - 64..x.len() - 60]) as usize) & mask; + let t = u32::from_le_bytes(x[x.len() - 64..x.len() - 60].try_into().unwrap()); + (t as usize) & mask + } + + let len = b.len(); + + for chunk in v.chunks_mut(len) { + chunk.copy_from_slice(b); + scrypt_block_mix(chunk, b); + } + + for _ in 0..n { + let j = integerify(b, n); + xor(b, &v[j * len..(j + 1) * len], t); + scrypt_block_mix(t, b); + } +} + +/// Execute the BlockMix operation +/// input - the input vector. The length must be a multiple of 128. +/// output - the output vector. Must be the same length as input. +fn scrypt_block_mix(input: &[u8], output: &mut [u8]) { + use salsa20::{ + cipher::{typenum::U4, StreamCipherCore}, + SalsaCore, + }; + + type Salsa20_8 = SalsaCore; + + let mut x = [0u8; 64]; + x.copy_from_slice(&input[input.len() - 64..]); + + let mut t = [0u8; 64]; + + for (i, chunk) in input.chunks(64).enumerate() { + xor(&x, chunk, &mut t); + + let mut t2 = [0u32; 16]; + + for (c, b) in t.chunks_exact(4).zip(t2.iter_mut()) { + *b = u32::from_le_bytes(c.try_into().unwrap()); + } + + Salsa20_8::from_raw_state(t2).write_keystream_block((&mut x).into()); + + let pos = if i % 2 == 0 { + (i / 2) * 64 + } else { + (i / 2) * 64 + input.len() / 2 + }; + + output[pos..pos + 64].copy_from_slice(&x); + } +} + +fn xor(x: &[u8], y: &[u8], output: &mut [u8]) { + for ((out, &x_i), &y_i) in output.iter_mut().zip(x.iter()).zip(y.iter()) { + *out = x_i ^ y_i; + } +} diff --git a/rust/tw_keystore/src/ffi/crypto_scrypt.rs b/rust/tw_keystore/src/ffi/crypto_scrypt.rs new file mode 100644 index 00000000000..44968c16f4e --- /dev/null +++ b/rust/tw_keystore/src/ffi/crypto_scrypt.rs @@ -0,0 +1,70 @@ +// Copyright © 2017-2023 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +#![allow(clippy::missing_safety_doc)] + +use crate::crypto_scrypt::params::Params; +use crate::crypto_scrypt::scrypt; +use tw_memory::ffi::c_byte_array::{CByteArray, CByteArrayResult}; +use tw_memory::ffi::c_byte_array_ref::CByteArrayRef; +use tw_memory::ffi::c_result::ErrorCode; +use tw_misc::try_or_else; + +#[repr(C)] +pub enum ScryptError { + Ok = 0, + InvalidParams = 1, +} + +impl From for ErrorCode { + fn from(error: ScryptError) -> Self { + error as ErrorCode + } +} + +/// The scrypt key derivation function. +/// +/// \param password *nullable* byte array. +/// \param password_len the length of the `password` array. +/// \param salt *nullable* byte array. +/// \param salt_len the length of the `salt` array. +/// \param n scrypt parameter `N`: CPU/memory cost. +/// \param r scrypt parameter `r`: block size. +/// \param p scrypt parameter `p`: parallelism. +/// \param desired_len scrypt parameter `Key length`. +/// \return C-compatible byte array. +#[no_mangle] +pub unsafe extern "C" fn crypto_scrypt( + password: *const u8, + password_len: usize, + salt: *const u8, + salt_len: usize, + n: u32, + r: u32, + p: u32, + desired_len: usize, +) -> CByteArrayResult { + let password_ref = CByteArrayRef::new(password, password_len); + let password = try_or_else!(password_ref.as_slice(), || CByteArrayResult::error( + ScryptError::InvalidParams + )); + + let salt_ref = CByteArrayRef::new(salt, salt_len); + let salt = try_or_else!(salt_ref.as_slice(), || CByteArrayResult::error( + ScryptError::InvalidParams + )); + + let params = Params { + n, + r, + p, + desired_len, + }; + scrypt(password, salt, ¶ms) + .map(CByteArray::from) + .map_err(|_| ScryptError::InvalidParams) + .into() +} diff --git a/rust/tw_keystore/src/ffi/mod.rs b/rust/tw_keystore/src/ffi/mod.rs new file mode 100644 index 00000000000..f74c45f578b --- /dev/null +++ b/rust/tw_keystore/src/ffi/mod.rs @@ -0,0 +1,7 @@ +// Copyright © 2017-2023 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +pub mod crypto_scrypt; diff --git a/rust/tw_keystore/src/lib.rs b/rust/tw_keystore/src/lib.rs new file mode 100644 index 00000000000..281790c771c --- /dev/null +++ b/rust/tw_keystore/src/lib.rs @@ -0,0 +1,8 @@ +// Copyright © 2017-2023 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +pub mod crypto_scrypt; +pub mod ffi; diff --git a/rust/tw_keystore/tests/crypto_scrypt.rs b/rust/tw_keystore/tests/crypto_scrypt.rs new file mode 100644 index 00000000000..9957951b5d3 --- /dev/null +++ b/rust/tw_keystore/tests/crypto_scrypt.rs @@ -0,0 +1,44 @@ +// Copyright © 2017-2023 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +use tw_encoding::hex; +use tw_keystore::crypto_scrypt::params::Params; +use tw_keystore::crypto_scrypt::scrypt; + +#[test] +fn test_scrypt() { + let password = hex::decode("70617373776f7264").unwrap(); + let salt = + hex::decode("80132842c6cde8f9d04582932ef92c3cad3ba6b41e1296ef681692372886db86").unwrap(); + + let params = Params { + n: 1 << 12, + r: 8, + p: 6, + desired_len: 32, + }; + let res = scrypt(&password, &salt, ¶ms).unwrap(); + assert_eq!( + hex::encode(&res, false), + "1217705511f43b7d2faea767a156a9946c579b3436ba27252a73278a7162cedc" + ); +} + +#[test] +fn test_scrypt_invalid_n() { + let password = hex::decode("70617373776f7264").unwrap(); + let salt = + hex::decode("80132842c6cde8f9d04582932ef92c3cad3ba6b41e1296ef681692372886db86").unwrap(); + + let params = Params { + // Must be a power of 2. + n: (1 << 12) + 1, + r: 8, + p: 6, + desired_len: 32, + }; + scrypt(&password, &salt, ¶ms).unwrap_err(); +} diff --git a/rust/tw_keystore/tests/crypto_scrypt_ffi.rs b/rust/tw_keystore/tests/crypto_scrypt_ffi.rs new file mode 100644 index 00000000000..d539db9c746 --- /dev/null +++ b/rust/tw_keystore/tests/crypto_scrypt_ffi.rs @@ -0,0 +1,36 @@ +// Copyright © 2017-2023 Trust Wallet. +// +// This file is part of Trust. The full Trust copyright notice, including +// terms governing use, modification, and redistribution, is contained in the +// file LICENSE at the root of the source code distribution tree. + +use tw_encoding::hex; +use tw_keystore::ffi::crypto_scrypt::crypto_scrypt; +use tw_memory::ffi::c_byte_array::CByteArray; + +#[test] +fn test_crypto_scrypt_ffi_null_salt() { + let password = hex::decode("70617373776f7264").unwrap(); + let password = CByteArray::from(password); + + let salt = CByteArray::null(); + + let res = unsafe { + crypto_scrypt( + password.data(), + password.size(), + salt.data(), + salt.size(), + 16384, + 8, + 4, + 32, + ) + } + .unwrap(); + let data = unsafe { res.into_vec() }; + assert_eq!( + hex::encode(&data, false), + "004f57df809101216a343d6215879a9a7f1d7e2c04ef2845b4494cf5f10181a1" + ); +} diff --git a/rust/tw_memory/src/ffi/c_byte_array_ref.rs b/rust/tw_memory/src/ffi/c_byte_array_ref.rs index 160b14d3f0d..36ccf6b1bcf 100644 --- a/rust/tw_memory/src/ffi/c_byte_array_ref.rs +++ b/rust/tw_memory/src/ffi/c_byte_array_ref.rs @@ -36,7 +36,7 @@ impl CByteArrayRef { /// The inner data must be valid. pub unsafe fn as_slice(&self) -> Option<&'static [u8]> { if self.data.is_null() { - return None; + return if self.size == 0 { Some(&[]) } else { None }; } Some(std::slice::from_raw_parts(self.data, self.size)) } diff --git a/rust/wallet_core_rs/Cargo.toml b/rust/wallet_core_rs/Cargo.toml index 90586221f9a..496550ab7a7 100644 --- a/rust/wallet_core_rs/Cargo.toml +++ b/rust/wallet_core_rs/Cargo.toml @@ -22,6 +22,7 @@ tw_encoding = { path = "../tw_encoding" } tw_ethereum = { path = "../tw_ethereum" } tw_hash = { path = "../tw_hash" } tw_keypair = { path = "../tw_keypair" } +tw_keystore = { path = "../tw_keystore" } tw_memory = { path = "../tw_memory" } tw_move_parser = { path = "../tw_move_parser" } tw_misc = { path = "../tw_misc" } diff --git a/rust/wallet_core_rs/cbindgen.toml b/rust/wallet_core_rs/cbindgen.toml index fcab0505411..0e3e7646ec9 100644 --- a/rust/wallet_core_rs/cbindgen.toml +++ b/rust/wallet_core_rs/cbindgen.toml @@ -14,6 +14,7 @@ extra_bindings = [ "tw_ethereum", "tw_hash", "tw_keypair", + "tw_keystore", "tw_memory", "tw_move_parser", "tw_proto" @@ -26,6 +27,7 @@ include = [ "tw_ethereum", "tw_hash", "tw_keypair", + "tw_keystore", "tw_memory", "tw_move_parser", "tw_proto" diff --git a/rust/wallet_core_rs/src/lib.rs b/rust/wallet_core_rs/src/lib.rs index 6335fa4a0f4..52ebe6c20f5 100644 --- a/rust/wallet_core_rs/src/lib.rs +++ b/rust/wallet_core_rs/src/lib.rs @@ -11,6 +11,7 @@ pub extern crate tw_encoding; pub extern crate tw_ethereum; pub extern crate tw_hash; pub extern crate tw_keypair; +pub extern crate tw_keystore; pub extern crate tw_memory; pub extern crate tw_move_parser; pub extern crate tw_proto; diff --git a/src/Keystore/EncryptionParameters.cpp b/src/Keystore/EncryptionParameters.cpp index 57a60d56346..ccef8a98584 100644 --- a/src/Keystore/EncryptionParameters.cpp +++ b/src/Keystore/EncryptionParameters.cpp @@ -10,8 +10,8 @@ #include #include -#include #include +#include using namespace TW; @@ -39,6 +39,23 @@ static const auto kdfParams = "kdfparams"; static const auto mac = "mac"; } // namespace CodingKeys +static Data rustScrypt(const Data& password, const ScryptParameters& params) { + Rust::CByteArrayResultWrapper res = Rust::crypto_scrypt( + password.data(), + password.size(), + params.salt.data(), + params.salt.size(), + params.n, + params.r, + params.p, + params.desiredKeyLength + ); + if (!res.isOk()) { + throw std::runtime_error("Invalid scrypt parameters"); + } + return res.unwrap().data; +} + EncryptionParameters::EncryptionParameters(const nlohmann::json& json) { auto cipher = json[CodingKeys::cipher].get(); cipherParams = AESParameters::AESParametersFromJson(json[CodingKeys::cipherParams], cipher); @@ -70,10 +87,7 @@ nlohmann::json EncryptionParameters::json() const { EncryptedPayload::EncryptedPayload(const Data& password, const Data& data, const EncryptionParameters& params) : params(std::move(params)), _mac() { auto scryptParams = std::get(this->params.kdfParams); - auto derivedKey = Data(scryptParams.desiredKeyLength); - scrypt(reinterpret_cast(password.data()), password.size(), scryptParams.salt.data(), - scryptParams.salt.size(), scryptParams.n, scryptParams.r, scryptParams.p, derivedKey.data(), - scryptParams.desiredKeyLength); + auto derivedKey = rustScrypt(password, scryptParams); aes_encrypt_ctx ctx; auto result = 0; @@ -108,10 +122,7 @@ Data EncryptedPayload::decrypt(const Data& password) const { auto mac = Data(); if (auto* scryptParams = std::get_if(¶ms.kdfParams); scryptParams) { - derivedKey.resize(scryptParams->defaultDesiredKeyLength); - scrypt(password.data(), password.size(), scryptParams->salt.data(), - scryptParams->salt.size(), scryptParams->n, scryptParams->r, scryptParams->p, derivedKey.data(), - scryptParams->defaultDesiredKeyLength); + derivedKey = rustScrypt(password, *scryptParams); mac = computeMAC(derivedKey.end() - params.getKeyBytesSize(), derivedKey.end(), encrypted); } else if (auto* pbkdf2Params = std::get_if(¶ms.kdfParams); pbkdf2Params) { derivedKey.resize(pbkdf2Params->defaultDesiredKeyLength); diff --git a/src/rust/Wrapper.h b/src/rust/Wrapper.h index 3b4f9436f39..20c391ee853 100644 --- a/src/rust/Wrapper.h +++ b/src/rust/Wrapper.h @@ -196,6 +196,10 @@ class CResult { return !isOk(); } + ErrorCode err() const { + return code; + } + private: ErrorCode code; std::optional inner; diff --git a/trezor-crypto/CMakeLists.txt b/trezor-crypto/CMakeLists.txt index 2e38617da2f..828e742bdd4 100644 --- a/trezor-crypto/CMakeLists.txt +++ b/trezor-crypto/CMakeLists.txt @@ -51,7 +51,6 @@ add_library(TrezorCrypto crypto/nem.c crypto/cash_addr.c crypto/memzero.c - crypto/scrypt.c crypto/nist256p1.c crypto/groestl.c crypto/hmac_drbg.c diff --git a/trezor-crypto/crypto/scrypt.c b/trezor-crypto/crypto/scrypt.c deleted file mode 100644 index c1856dcbda5..00000000000 --- a/trezor-crypto/crypto/scrypt.c +++ /dev/null @@ -1,343 +0,0 @@ -/*- - * Copyright 2009 Colin Percival - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#include - -#include -#include -#include - -#include -#ifndef _WIN32 -#include -#endif -#include -#include -#include -#include - -static void blkcpy(void *, void *, size_t); -static void blkxor(void *, void *, size_t); -static void salsa20_8(uint32_t[16]); -static void blockmix_salsa8(uint32_t *, uint32_t *, uint32_t *, size_t); -static uint64_t integerify(void *, size_t); -static void smix(uint8_t *, size_t, uint64_t, uint32_t *, uint32_t *); - -static void -blkcpy(void * dest, void * src, size_t len) -{ - size_t * D = dest; - size_t * S = src; - size_t L = len / sizeof(size_t); - size_t i; - - for (i = 0; i < L; i++) - D[i] = S[i]; -} - -static void -blkxor(void * dest, void * src, size_t len) -{ - size_t * D = dest; - size_t * S = src; - size_t L = len / sizeof(size_t); - size_t i; - - for (i = 0; i < L; i++) - D[i] ^= S[i]; -} - -/** - * salsa20_8(B): - * Apply the salsa20/8 core to the provided block. - */ -static void -salsa20_8(uint32_t B[16]) -{ - uint32_t x[16]; - size_t i; - - blkcpy(x, B, 64); - for (i = 0; i < 8; i += 2) { -#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) - /* Operate on columns. */ - x[ 4] ^= R(x[ 0]+x[12], 7); x[ 8] ^= R(x[ 4]+x[ 0], 9); - x[12] ^= R(x[ 8]+x[ 4],13); x[ 0] ^= R(x[12]+x[ 8],18); - - x[ 9] ^= R(x[ 5]+x[ 1], 7); x[13] ^= R(x[ 9]+x[ 5], 9); - x[ 1] ^= R(x[13]+x[ 9],13); x[ 5] ^= R(x[ 1]+x[13],18); - - x[14] ^= R(x[10]+x[ 6], 7); x[ 2] ^= R(x[14]+x[10], 9); - x[ 6] ^= R(x[ 2]+x[14],13); x[10] ^= R(x[ 6]+x[ 2],18); - - x[ 3] ^= R(x[15]+x[11], 7); x[ 7] ^= R(x[ 3]+x[15], 9); - x[11] ^= R(x[ 7]+x[ 3],13); x[15] ^= R(x[11]+x[ 7],18); - - /* Operate on rows. */ - x[ 1] ^= R(x[ 0]+x[ 3], 7); x[ 2] ^= R(x[ 1]+x[ 0], 9); - x[ 3] ^= R(x[ 2]+x[ 1],13); x[ 0] ^= R(x[ 3]+x[ 2],18); - - x[ 6] ^= R(x[ 5]+x[ 4], 7); x[ 7] ^= R(x[ 6]+x[ 5], 9); - x[ 4] ^= R(x[ 7]+x[ 6],13); x[ 5] ^= R(x[ 4]+x[ 7],18); - - x[11] ^= R(x[10]+x[ 9], 7); x[ 8] ^= R(x[11]+x[10], 9); - x[ 9] ^= R(x[ 8]+x[11],13); x[10] ^= R(x[ 9]+x[ 8],18); - - x[12] ^= R(x[15]+x[14], 7); x[13] ^= R(x[12]+x[15], 9); - x[14] ^= R(x[13]+x[12],13); x[15] ^= R(x[14]+x[13],18); -#undef R - } - for (i = 0; i < 16; i++) - B[i] += x[i]; -} - -/** - * blockmix_salsa8(Bin, Bout, X, r): - * Compute Bout = BlockMix_{salsa20/8, r}(Bin). The input Bin must be 128r - * bytes in length; the output Bout must also be the same size. The - * temporary space X must be 64 bytes. - */ -static void -blockmix_salsa8(uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r) -{ - size_t i; - - /* 1: X <-- B_{2r - 1} */ - blkcpy(X, &Bin[(2 * r - 1) * 16], 64); - - /* 2: for i = 0 to 2r - 1 do */ - for (i = 0; i < 2 * r; i += 2) { - /* 3: X <-- H(X \xor B_i) */ - blkxor(X, &Bin[i * 16], 64); - salsa20_8(X); - - /* 4: Y_i <-- X */ - /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ - blkcpy(&Bout[i * 8], X, 64); - - /* 3: X <-- H(X \xor B_i) */ - blkxor(X, &Bin[i * 16 + 16], 64); - salsa20_8(X); - - /* 4: Y_i <-- X */ - /* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */ - blkcpy(&Bout[i * 8 + r * 16], X, 64); - } -} - -/** - * integerify(B, r): - * Return the result of parsing B_{2r-1} as a little-endian integer. - */ -static uint64_t -integerify(void * B, size_t r) -{ - uint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64); - - return (((uint64_t)(X[1]) << 32) + X[0]); -} - -/** - * smix(B, r, N, V, XY): - * Compute B = SMix_r(B, N). The input B must be 128r bytes in length; - * the temporary storage V must be 128rN bytes in length; the temporary - * storage XY must be 256r + 64 bytes in length. The value N must be a - * power of 2 greater than 1. The arrays B, V, and XY must be aligned to a - * multiple of 64 bytes. - */ -static void -smix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY) -{ - uint32_t * X = XY; - uint32_t * Y = &XY[32 * r]; - uint32_t * Z = &XY[64 * r]; - uint64_t i; - uint64_t j; - size_t k; - - /* 1: X <-- B */ - for (k = 0; k < 32 * r; k++) - X[k] = le32dec(&B[4 * k]); - - /* 2: for i = 0 to N - 1 do */ - for (i = 0; i < N; i += 2) { - /* 3: V_i <-- X */ - blkcpy(&V[i * (32 * r)], X, 128 * r); - - /* 4: X <-- H(X) */ - blockmix_salsa8(X, Y, Z, r); - - /* 3: V_i <-- X */ - blkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r); - - /* 4: X <-- H(X) */ - blockmix_salsa8(Y, X, Z, r); - } - - /* 6: for i = 0 to N - 1 do */ - for (i = 0; i < N; i += 2) { - /* 7: j <-- Integerify(X) mod N */ - j = integerify(X, r) & (N - 1); - - /* 8: X <-- H(X \xor V_j) */ - blkxor(X, &V[j * (32 * r)], 128 * r); - blockmix_salsa8(X, Y, Z, r); - - /* 7: j <-- Integerify(X) mod N */ - j = integerify(Y, r) & (N - 1); - - /* 8: X <-- H(X \xor V_j) */ - blkxor(Y, &V[j * (32 * r)], 128 * r); - blockmix_salsa8(Y, X, Z, r); - } - - /* 10: B' <-- X */ - for (k = 0; k < 32 * r; k++) - le32enc(&B[4 * k], X[k]); -} - -/** - * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): - * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, - * p, buflen) and write the result into buf. The parameters r, p, and buflen - * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N - * must be a power of 2 greater than 1. - * - * Return 0 on success; or -1 on error - */ -int -scrypt(const uint8_t * passwd, size_t passwdlen, - const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t r, uint32_t p, - uint8_t * buf, size_t buflen) -{ - void * B0, * V0, * XY0; - uint8_t * B; - uint32_t * V; - uint32_t * XY; - uint32_t i; - - /* Sanity-check parameters. */ -#if SIZE_MAX > UINT32_MAX - if (buflen > (((uint64_t)(1) << 32) - 1) * 32) { - errno = EFBIG; - goto err0; - } -#endif - if ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) { - errno = EFBIG; - goto err0; - } - if (r == 0 || p == 0) { - errno = EINVAL; - goto err0; - } - if (((N & (N - 1)) != 0) || (N < 2)) { - errno = EINVAL; - goto err0; - } - if ((r > SIZE_MAX / 128 / p) || -#if SIZE_MAX / 256 <= UINT32_MAX - (r > SIZE_MAX / 256) || -#endif - (N > SIZE_MAX / 128 / r)) { - errno = ENOMEM; - goto err0; - } - - /* Allocate memory. */ -#ifdef HAVE_POSIX_MEMALIGN - if ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0) - goto err0; - B = (uint8_t *)(B0); - if ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0) - goto err1; - XY = (uint32_t *)(XY0); -#ifndef MAP_ANON - if ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0) - goto err2; - V = (uint32_t *)(V0); -#endif -#else - if ((B0 = malloc(128 * r * p + 63)) == NULL) - goto err0; - B = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63)); - if ((XY0 = malloc(256 * r + 64 + 63)) == NULL) - goto err1; - XY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63)); -#ifndef MAP_ANON - if ((V0 = malloc(128 * r * N + 63)) == NULL) - goto err2; - V = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63)); -#endif -#endif -#ifdef MAP_ANON - if ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE, -#ifdef MAP_NOCORE - MAP_ANON | MAP_PRIVATE | MAP_NOCORE, -#else - MAP_ANON | MAP_PRIVATE, -#endif - -1, 0)) == MAP_FAILED) - goto err2; - V = (uint32_t *)(V0); -#endif - - /* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */ - pbkdf2_hmac_sha256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r); - - /* 2: for i = 0 to p - 1 do */ - for (i = 0; i < p; i++) { - /* 3: B_i <-- MF(B_i, N) */ - smix(&B[i * 128 * r], r, N, V, XY); - } - - /* 5: DK <-- PBKDF2(P, B, 1, dkLen) */ - pbkdf2_hmac_sha256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen); - - /* Free memory. */ -#ifdef MAP_ANON - if (munmap(V0, 128 * r * N)) - goto err2; -#else - free(V0); -#endif - free(XY0); - free(B0); - - /* Success! */ - return (0); - -err2: - free(XY0); -err1: - free(B0); -err0: - /* Failure! */ - return (-1); -} diff --git a/trezor-crypto/include/TrezorCrypto/scrypt.h b/trezor-crypto/include/TrezorCrypto/scrypt.h deleted file mode 100644 index 7140bc2e255..00000000000 --- a/trezor-crypto/include/TrezorCrypto/scrypt.h +++ /dev/null @@ -1,68 +0,0 @@ -/*- - * Copyright 2009 Colin Percival - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file was originally written by Colin Percival as part of the Tarsnap - * online backup system. - */ - -#ifndef _SCRYPT_H_ -#define _SCRYPT_H_ - - -#include -#include -#ifdef __cplusplus -extern "C"{ -#endif - -/** - * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): - * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r, - * p, buflen) and write the result into buf. The parameters r, p, and buflen - * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32. The parameter N - * must be a power of 2 greater than 1. - * - * scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen): - * password; duh - * N: CPU AND RAM cost (first modifier) - * r: RAM Cost - * p: CPU cost (parallelisation) - * In short, N is your main performance modifier. Values of r = 8, p = 1 are - * standard unless you want to modify the CPU/RAM ratio. - * Return 0 on success; or -1 on error. - */ -int scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t, - uint32_t, uint32_t, /*@out@*/ uint8_t *, size_t); - -#ifdef __cplusplus -} -#endif - -/* Sane default values */ -#define SCRYPT_N 16384 -#define SCRYPT_r 8 -#define SCRYPT_p 16 - -#endif /* !_SCRYPT_H_ */ From 721779b5d5f90e9bbe0e5721ad77c1735f47fbb5 Mon Sep 17 00:00:00 2001 From: Satoshi Otomakan Date: Tue, 17 Oct 2023 12:09:05 +0200 Subject: [PATCH 2/2] [Crypto]: Fix iOS, Kotlin, Rust CI --- rust/Cargo.toml | 7 +++++-- swift/common-xcframework.yml | 1 - swift/project.yml | 1 - tools/rust-test | 5 ++++- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/rust/Cargo.toml b/rust/Cargo.toml index e048d20fb37..05377fd2345 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -22,11 +22,14 @@ members = [ [profile.wasm-test] inherits = "release" -# Fixes an incredibly slow compilation of `curve25519-dalek` package. -opt-level = 1 +opt-level = 3 debug = true debug-assertions = true overflow-checks = true +# Fixes an incredibly slow compilation of `curve25519-dalek` package. +[profile.wasm-test.package.curve25519-dalek] +opt-level = 1 + [profile.release.package.curve25519-dalek] opt-level = 2 diff --git a/swift/common-xcframework.yml b/swift/common-xcframework.yml index dae0d4b55c7..edd9290e083 100644 --- a/swift/common-xcframework.yml +++ b/swift/common-xcframework.yml @@ -106,7 +106,6 @@ targets: - trezor-crypto/crypto/nem.c - trezor-crypto/crypto/cash_addr.c - trezor-crypto/crypto/memzero.c - - trezor-crypto/crypto/scrypt.c - trezor-crypto/crypto/nist256p1.c - trezor-crypto/crypto/groestl.c - trezor-crypto/crypto/hmac_drbg.c diff --git a/swift/project.yml b/swift/project.yml index df46f6a29e5..b9e41ccf9f8 100644 --- a/swift/project.yml +++ b/swift/project.yml @@ -124,7 +124,6 @@ targets: - trezor-crypto/crypto/nem.c - trezor-crypto/crypto/cash_addr.c - trezor-crypto/crypto/memzero.c - - trezor-crypto/crypto/scrypt.c - trezor-crypto/crypto/nist256p1.c - trezor-crypto/crypto/groestl.c - trezor-crypto/crypto/hmac_drbg.c diff --git a/tools/rust-test b/tools/rust-test index 1b20938f589..ac07ded5d88 100755 --- a/tools/rust-test +++ b/tools/rust-test @@ -18,7 +18,10 @@ if [[ "$1" == "wasm" ]]; then source ../emsdk/emsdk_env.sh export CARGO_TARGET_WASM32_UNKNOWN_EMSCRIPTEN_RUNNER=node - cargo test --target wasm32-unknown-emscripten --profile wasm-test + # Increase the `TOTAL_MEMORY` value if required. + CONFIG='build.rustflags=["-C","link-arg=-s","-C","link-arg=TOTAL_MEMORY=33554432"]' + + cargo --config "$CONFIG" test --target wasm32-unknown-emscripten --profile wasm-test else cargo test --all fi