Skip to content

Commit d5560b0

Browse files
authored
Merge pull request #10556 from holtrop-wolfssl/rust-crate-updates-3
Rust wrapper: add scrypt KDF and RSA-OAEP support
2 parents 97095d2 + 226f96d commit d5560b0

18 files changed

Lines changed: 1391 additions & 14 deletions

wrapper/rust/include.am

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,44 +13,66 @@ EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/build.rs
1313
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/headers.h
1414
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/aes.rs
1515
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/blake2.rs
16+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/blake2_digest.rs
17+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/blake2_mac.rs
1618
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/chacha20_poly1305.rs
1719
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/cmac.rs
20+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/cmac_mac.rs
1821
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/curve25519.rs
1922
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/dh.rs
2023
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/dilithium.rs
2124
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/ecc.rs
25+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/ecdsa.rs
2226
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/ed25519.rs
2327
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/ed448.rs
2428
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/fips.rs
2529
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/hkdf.rs
2630
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/hmac.rs
31+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/hmac_mac.rs
2732
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/kdf.rs
2833
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/lib.rs
2934
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/lms.rs
3035
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/mlkem.rs
36+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/mlkem_kem.rs
37+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/pbkdf2_password_hash.rs
3138
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/prf.rs
3239
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/random.rs
3340
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/rsa.rs
41+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/rsa_oaep.rs
42+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/rsa_pkcs1v15.rs
43+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/scrypt_password_hash.rs
3444
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/sha.rs
45+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/sha_digest.rs
3546
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/src/sys.rs
3647
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/common/mod.rs
3748
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_aes.rs
3849
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2.rs
50+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2_digest.rs
51+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_blake2_mac.rs
3952
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_chacha20_poly1305.rs
4053
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_cmac.rs
54+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_cmac_mac.rs
4155
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_curve25519.rs
4256
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_dh.rs
4357
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_dilithium.rs
4458
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_ecc.rs
59+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_ecdsa.rs
4560
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_ed25519.rs
4661
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_ed448.rs
4762
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_hkdf.rs
4863
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_hmac.rs
64+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_hmac_mac.rs
4965
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_kdf.rs
5066
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_lms.rs
5167
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_mlkem.rs
68+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_mlkem_kem.rs
69+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_pbkdf2_password_hash.rs
5270
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_prf.rs
5371
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_random.rs
5472
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa.rs
73+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa_oaep.rs
74+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_rsa_pkcs1v15.rs
75+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_scrypt_password_hash.rs
5576
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_sha.rs
77+
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_sha_digest.rs
5678
EXTRA_DIST += wrapper/rust/wolfssl-wolfcrypt/tests/test_wolfcrypt.rs

wrapper/rust/wolfssl-wolfcrypt/build.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,7 @@ fn scan_cfg() -> Result<()> {
425425
/* kdf */
426426
check_cfg(&binding, "wc_PBKDF2", "kdf_pbkdf2");
427427
check_cfg(&binding, "wc_PKCS12_PBKDF_ex", "kdf_pkcs12");
428+
check_cfg(&binding, "wc_scrypt", "kdf_scrypt");
428429
check_cfg(&binding, "wc_SRTP_KDF", "kdf_srtp");
429430
check_cfg(&binding, "wc_SSH_KDF", "kdf_ssh");
430431
check_cfg(&binding, "wc_Tls13_HKDF_Extract_ex", "kdf_tls13");
@@ -457,6 +458,7 @@ fn scan_cfg() -> Result<()> {
457458
check_cfg(&binding, "wc_RsaDirect", "rsa_direct");
458459
check_cfg(&binding, "wc_MakeRsaKey", "rsa_keygen");
459460
check_cfg(&binding, "wc_RsaPSS_Sign", "rsa_pss");
461+
check_cfg(&binding, "wc_RsaPublicEncrypt_ex", "rsa_oaep");
460462
check_cfg(&binding, "wc_RsaSetRNG", "rsa_setrng");
461463
check_cfg(&binding, "WC_MGF1SHA512_224", "rsa_mgf1sha512_224");
462464
check_cfg(&binding, "WC_MGF1SHA512_256", "rsa_mgf1sha512_256");

wrapper/rust/wolfssl-wolfcrypt/src/aes.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -806,19 +806,23 @@ impl CFB {
806806
/// * `din`: Data to encrypt.
807807
/// * `dout`: Buffer in which to store the encrypted data. The size of
808808
/// the buffer must match that of the `din` buffer.
809+
/// * `size`: Number of bits to encrypt. The `din` and `dout` buffers must
810+
/// each be large enough to hold this number of bits.
809811
///
810812
/// # Returns
811813
///
812814
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
813815
/// library return code on failure.
814-
pub fn encrypt1(&mut self, din: &[u8], dout: &mut [u8]) -> Result<(), i32> {
815-
let in_size = crate::buffer_len_to_u32(din.len())?;
816-
let out_size = crate::buffer_len_to_u32(dout.len())?;
817-
if in_size != out_size {
816+
pub fn encrypt1(&mut self, din: &[u8], dout: &mut [u8], size: usize) -> Result<(), i32> {
817+
if din.len() != dout.len() {
818818
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
819819
}
820+
if din.len() < size.div_ceil(8) {
821+
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
822+
}
823+
let bit_size = crate::buffer_len_to_u32(size)?;
820824
let rc = unsafe {
821-
sys::wc_AesCfb1Encrypt(&mut self.ws_aes, dout.as_mut_ptr(), din.as_ptr(), in_size)
825+
sys::wc_AesCfb1Encrypt(&mut self.ws_aes, dout.as_mut_ptr(), din.as_ptr(), bit_size)
822826
};
823827
if rc != 0 {
824828
return Err(rc);
@@ -894,20 +898,24 @@ impl CFB {
894898
/// * `din`: Data to decrypt.
895899
/// * `dout`: Buffer in which to store the decrypted data. The size of
896900
/// the buffer must match that of the `din` buffer.
901+
/// * `size`: Number of bits to decrypt. The `din` and `dout` buffers must
902+
/// each be large enough to hold this number of bits.
897903
///
898904
/// # Returns
899905
///
900906
/// A Result which is Ok(()) on success or an Err containing the wolfSSL
901907
/// library return code on failure.
902908
#[cfg(aes_decrypt)]
903-
pub fn decrypt1(&mut self, din: &[u8], dout: &mut [u8]) -> Result<(), i32> {
904-
let in_size = crate::buffer_len_to_u32(din.len())?;
905-
let out_size = crate::buffer_len_to_u32(dout.len())?;
906-
if in_size != out_size {
909+
pub fn decrypt1(&mut self, din: &[u8], dout: &mut [u8], size: usize) -> Result<(), i32> {
910+
if din.len() != dout.len() {
911+
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
912+
}
913+
if din.len() < size.div_ceil(8) {
907914
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
908915
}
916+
let bit_size = crate::buffer_len_to_u32(size)?;
909917
let rc = unsafe {
910-
sys::wc_AesCfb1Decrypt(&mut self.ws_aes, dout.as_mut_ptr(), din.as_ptr(), in_size)
918+
sys::wc_AesCfb1Decrypt(&mut self.ws_aes, dout.as_mut_ptr(), din.as_ptr(), bit_size)
911919
};
912920
if rc != 0 {
913921
return Err(rc);
@@ -2993,7 +3001,10 @@ impl XTSStream {
29933001
#[cfg(aes_xts_stream)]
29943002
impl XTSStream {
29953003
fn zeroize(&mut self) {
2996-
unsafe { crate::zeroize_raw(&mut self.ws_xtsaes); }
3004+
unsafe {
3005+
crate::zeroize_raw(&mut self.ws_xtsaes);
3006+
crate::zeroize_raw(&mut self.ws_xtsaesstreamdata);
3007+
}
29973008
}
29983009
}
29993010
#[cfg(aes_xts_stream)]

wrapper/rust/wolfssl-wolfcrypt/src/cmac.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ impl CMAC {
201201
data.as_ptr(), data_size,
202202
key.as_ptr(), key_size)
203203
};
204+
if rc == sys::wolfCrypt_ErrorCodes_MAC_CMP_FAILED_E {
205+
return Ok(false);
206+
}
204207
if rc < 0 {
205208
return Err(rc);
206209
}
@@ -402,6 +405,9 @@ impl CMAC {
402405
data.as_ptr(), data_size,
403406
key.as_ptr(), key_size, heap, dev_id)
404407
};
408+
if rc == sys::wolfCrypt_ErrorCodes_MAC_CMP_FAILED_E {
409+
return Ok(false);
410+
}
405411
if rc < 0 {
406412
return Err(rc);
407413
}

wrapper/rust/wolfssl-wolfcrypt/src/kdf.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,114 @@ pub fn pkcs12_pbkdf_ex(password: &[u8], salt: &[u8], iterations: i32, typ: i32,
269269
Ok(())
270270
}
271271

272+
/// Implement the scrypt password-based key derivation function as defined
273+
/// in RFC 7914.
274+
///
275+
/// # Parameters
276+
///
277+
/// * `password`: Password to use for key derivation.
278+
/// * `salt`: Salt value to use for key derivation.
279+
/// * `cost`: log base 2 of the iteration count (`N = 1 << cost`). Must
280+
/// satisfy `1 <= cost < 128 * block_size / 8`.
281+
/// * `block_size`: Number of 128-byte octets in a working block (the `r`
282+
/// parameter from RFC 7914). Must be in `1..=8`.
283+
/// * `parallel`: Number of parallel mix operations to perform (the `p`
284+
/// parameter from RFC 7914). This implementation does not use threads.
285+
/// * `out`: Output buffer in which to store the derived key.
286+
///
287+
/// # Returns
288+
///
289+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
290+
/// library error code value.
291+
///
292+
/// # Example
293+
///
294+
/// ```rust
295+
/// #[cfg(kdf_scrypt)]
296+
/// {
297+
/// use wolfssl_wolfcrypt::kdf::scrypt;
298+
/// let password = b"password";
299+
/// let salt = b"NaCl";
300+
/// let expected_key = [
301+
/// 0xfdu8, 0xba, 0xbe, 0x1c, 0x9d, 0x34, 0x72, 0x00,
302+
/// 0x78, 0x56, 0xe7, 0x19, 0x0d, 0x01, 0xe9, 0xfe,
303+
/// 0x7c, 0x6a, 0xd7, 0xcb, 0xc8, 0x23, 0x78, 0x30,
304+
/// 0xe7, 0x73, 0x76, 0x63, 0x4b, 0x37, 0x31, 0x62,
305+
/// 0x2e, 0xaf, 0x30, 0xd9, 0x2e, 0x22, 0xa3, 0x88,
306+
/// 0x6f, 0xf1, 0x09, 0x27, 0x9d, 0x98, 0x30, 0xda,
307+
/// 0xc7, 0x27, 0xaf, 0xb9, 0x4a, 0x83, 0xee, 0x6d,
308+
/// 0x83, 0x60, 0xcb, 0xdf, 0xa2, 0xcc, 0x06, 0x40
309+
/// ];
310+
/// let mut keyout = [0u8; 64];
311+
/// scrypt(password, salt, 10, 8, 16, &mut keyout).expect("Error with scrypt()");
312+
/// assert_eq!(keyout, expected_key);
313+
/// }
314+
/// ```
315+
#[cfg(kdf_scrypt)]
316+
pub fn scrypt(password: &[u8], salt: &[u8], cost: i32, block_size: i32,
317+
parallel: i32, out: &mut [u8]) -> Result<(), i32> {
318+
let password_size = crate::buffer_len_to_i32(password.len())?;
319+
let salt_size = crate::buffer_len_to_i32(salt.len())?;
320+
let out_size = crate::buffer_len_to_i32(out.len())?;
321+
let rc = unsafe {
322+
sys::wc_scrypt(out.as_mut_ptr(), password.as_ptr(), password_size,
323+
salt.as_ptr(), salt_size, cost, block_size, parallel, out_size)
324+
};
325+
if rc != 0 {
326+
return Err(rc);
327+
}
328+
Ok(())
329+
}
330+
331+
/// Implement the scrypt password-based key derivation function as defined
332+
/// in RFC 7914. This variant takes the iteration count `N` directly
333+
/// instead of `log2(N)`.
334+
///
335+
/// # Parameters
336+
///
337+
/// * `password`: Password to use for key derivation.
338+
/// * `salt`: Salt value to use for key derivation.
339+
/// * `iterations`: Iteration count (`N`). Must be a power of two greater
340+
/// than 1.
341+
/// * `block_size`: Number of 128-byte octets in a working block (the `r`
342+
/// parameter from RFC 7914). Must be in `1..=8`.
343+
/// * `parallel`: Number of parallel mix operations to perform (the `p`
344+
/// parameter from RFC 7914). This implementation does not use threads.
345+
/// * `out`: Output buffer in which to store the derived key.
346+
///
347+
/// # Returns
348+
///
349+
/// Returns either Ok(()) on success or Err(e) containing the wolfSSL
350+
/// library error code value.
351+
///
352+
/// # Example
353+
///
354+
/// ```rust
355+
/// #[cfg(kdf_scrypt)]
356+
/// {
357+
/// use wolfssl_wolfcrypt::kdf::scrypt_ex;
358+
/// let password = b"password";
359+
/// let salt = b"NaCl";
360+
/// let mut keyout = [0u8; 64];
361+
/// scrypt_ex(password, salt, 1024, 8, 16, &mut keyout).expect("Error with scrypt_ex()");
362+
/// }
363+
/// ```
364+
#[cfg(kdf_scrypt)]
365+
pub fn scrypt_ex(password: &[u8], salt: &[u8], iterations: u32,
366+
block_size: i32, parallel: i32, out: &mut [u8]) -> Result<(), i32> {
367+
let password_size = crate::buffer_len_to_i32(password.len())?;
368+
let salt_size = crate::buffer_len_to_i32(salt.len())?;
369+
let out_size = crate::buffer_len_to_i32(out.len())?;
370+
let rc = unsafe {
371+
sys::wc_scrypt_ex(out.as_mut_ptr(), password.as_ptr(), password_size,
372+
salt.as_ptr(), salt_size, iterations, block_size, parallel, out_size)
373+
};
374+
if rc != 0 {
375+
return Err(rc);
376+
}
377+
Ok(())
378+
}
379+
272380
/// Perform RFC 5869 HKDF-Extract operation for TLS v1.3 key derivation.
273381
///
274382
/// # Parameters

wrapper/rust/wolfssl-wolfcrypt/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,15 @@ pub mod mlkem_kem;
7474
pub mod prf;
7575
pub mod random;
7676
pub mod rsa;
77+
#[cfg(rsa_oaep)]
78+
pub mod rsa_oaep;
7779
#[cfg(feature = "signature")]
7880
pub mod rsa_pkcs1v15;
7981
pub mod sha;
8082
#[cfg(all(feature = "password-hash", hmac, kdf_pbkdf2))]
8183
pub mod pbkdf2_password_hash;
84+
#[cfg(all(feature = "password-hash", kdf_scrypt))]
85+
pub mod scrypt_password_hash;
8286
#[cfg(feature = "digest")]
8387
pub mod sha_digest;
8488

wrapper/rust/wolfssl-wolfcrypt/src/lms.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,9 @@ impl Lms {
774774
if rc != 0 {
775775
return Err(rc);
776776
}
777+
if kid_ptr.is_null() {
778+
return Err(sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG);
779+
}
777780
let src = unsafe { core::slice::from_raw_parts(kid_ptr, kid_sz as usize) };
778781
if kid.len() < src.len() {
779782
return Err(sys::wolfCrypt_ErrorCodes_BUFFER_E);

wrapper/rust/wolfssl-wolfcrypt/src/mlkem_kem.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ macro_rules! impl_mlkem_kem {
135135
let mut ss = [0u8; crate::mlkem::MlKem::SHARED_SECRET_SIZE];
136136
wc_key.encapsulate_with_random(&mut ct, &mut ss, &rand)
137137
.expect("encapsulate_with_random failed");
138+
zeroize::Zeroize::zeroize(&mut rand[..]);
138139

139140
(ct.into(), ss.into())
140141
}
@@ -184,6 +185,7 @@ macro_rules! impl_mlkem_kem {
184185
let wc_key = crate::mlkem::MlKem::generate_with_random(
185186
$key_type, &rand,
186187
).expect("generate_with_random failed");
188+
zeroize::Zeroize::zeroize(&mut rand[..]);
187189

188190
let mut pk = [0u8; $pk_len];
189191
let mut sk = [0u8; $sk_len];

wrapper/rust/wolfssl-wolfcrypt/src/pbkdf2_password_hash.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,14 @@ impl password_hash::CustomizedPasswordHasher<PasswordHash> for Pbkdf2 {
217217
None => self.algorithm,
218218
};
219219

220-
if params.rounds < MIN_ROUNDS || params.output_len > Output::MAX_LENGTH {
220+
if params.rounds < MIN_ROUNDS {
221221
return Err(Error::ParamInvalid { name: "i" });
222222
}
223223

224+
if params.output_len > Output::MAX_LENGTH {
225+
return Err(Error::ParamInvalid { name: "l" });
226+
}
227+
224228
let iterations = i32::try_from(params.rounds)
225229
.map_err(|_| Error::ParamInvalid { name: "i" })?;
226230

0 commit comments

Comments
 (0)