From 551a2814dea26d8d36db89fda1296a835bcab245 Mon Sep 17 00:00:00 2001 From: Geovane Fedrecheski Date: Wed, 13 Mar 2024 11:34:39 +0100 Subject: [PATCH 1/2] fix(crypto/psa): off-by-1 bugs in hkdf_expand --- crypto/Cargo.toml | 3 ++ crypto/lakers-crypto-psa/src/lib.rs | 4 +-- crypto/src/lib.rs | 55 +++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index 4a4aaa61..bc278f5d 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -27,6 +27,9 @@ lakers-crypto-cryptocell310 = { workspace = true, optional = true } lakers-crypto-rustcrypto = { workspace = true, optional = true } rand_core = { version = "0.6.4", optional = true, default-features = false } +[dev-dependencies] +hexlit = "0.5.3" + [features] default = [ ] # hacspec = [ "lakers-crypto-hacspec" ] diff --git a/crypto/lakers-crypto-psa/src/lib.rs b/crypto/lakers-crypto-psa/src/lib.rs index fe5091d0..16961f88 100644 --- a/crypto/lakers-crypto-psa/src/lib.rs +++ b/crypto/lakers-crypto-psa/src/lib.rs @@ -60,13 +60,13 @@ impl CryptoTrait for Crypto { let mut t_i = self.hmac_sha256(&message[..info_len + 1], prk); output[..SHA256_DIGEST_LEN].copy_from_slice(&t_i); - for i in 2..n { + for i in 2..=n { message[..SHA256_DIGEST_LEN].copy_from_slice(&t_i); message[SHA256_DIGEST_LEN..SHA256_DIGEST_LEN + info_len] .copy_from_slice(&info[..info_len]); message[SHA256_DIGEST_LEN + info_len] = i as u8; t_i = self.hmac_sha256(&message[..SHA256_DIGEST_LEN + info_len + 1], prk); - output[i * SHA256_DIGEST_LEN..(i + 1) * SHA256_DIGEST_LEN].copy_from_slice(&t_i); + output[(i - 1) * SHA256_DIGEST_LEN..i * SHA256_DIGEST_LEN].copy_from_slice(&t_i); } output[length..].fill(0x00); diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index b31de25c..caaa23ab 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -55,3 +55,58 @@ fn test_helper() {} fn test_implements_crypto() { test_helper::() } + +#[cfg(test)] +mod tests { + use hexlit::hex; + use lakers_shared::*; + + use super::*; + + // Test vectors from RFC 5869 (TV1 = test vector for Test Case 1) + pub const PRK_TV1: &[u8] = + &hex!("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"); + pub const INFO_TV1: &[u8] = &hex!("f0f1f2f3f4f5f6f7f8f9"); + pub const L_TV1: usize = 42; + pub const OKM_TV1: &[u8] = &hex!( + "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865" + ); + + #[test] + fn test_hkdf_expand_basic() { + let mut crypto = default_crypto(); + + let mut prk = [0; SHA256_DIGEST_LEN]; + prk[..PRK_TV1.len()].copy_from_slice(PRK_TV1); + let mut info = [0; MAX_INFO_LEN]; + info[..INFO_TV1.len()].copy_from_slice(INFO_TV1); + + let mut okm_tv: BytesMaxBuffer = [0; MAX_BUFFER_LEN]; + okm_tv[..OKM_TV1.len()].copy_from_slice(OKM_TV1); + + let okm = crypto.hkdf_expand(&prk, &info, INFO_TV1.len(), L_TV1); + assert_eq!(okm, okm_tv); + } + + pub const PRK_TV2: &[u8] = + &hex!("06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244"); + pub const INFO_TV2: &[u8] = &hex!("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); + pub const L_TV2: usize = 82; + pub const OKM_TV2: &[u8] = &hex!("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"); + + #[test] + fn test_hkdf_expand_long() { + let mut crypto = default_crypto(); + + let mut prk = [0; SHA256_DIGEST_LEN]; + prk[..PRK_TV2.len()].copy_from_slice(PRK_TV2); + let mut info = [0; MAX_INFO_LEN]; + info[..INFO_TV2.len()].copy_from_slice(INFO_TV2); + + let mut okm_tv: BytesMaxBuffer = [0; MAX_BUFFER_LEN]; + okm_tv[..OKM_TV2.len()].copy_from_slice(OKM_TV2); + + let okm = crypto.hkdf_expand(&prk, &info, INFO_TV2.len(), L_TV2); + assert_eq!(okm, okm_tv); + } +} From 7b0d6cc29908fe928adf5f41b2ea2be5b32aaaac Mon Sep 17 00:00:00 2001 From: Geovane Fedrecheski Date: Wed, 13 Mar 2024 11:47:38 +0100 Subject: [PATCH 2/2] feat(crypto): parameterize tests with rstest --- crypto/Cargo.toml | 1 + crypto/src/lib.rs | 67 ++++++++++++++++++----------------------------- 2 files changed, 27 insertions(+), 41 deletions(-) diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index bc278f5d..05fbd914 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -29,6 +29,7 @@ rand_core = { version = "0.6.4", optional = true, default-features = false } [dev-dependencies] hexlit = "0.5.3" +rstest = "0.11.0" [features] default = [ ] diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index caaa23ab..d8550b6a 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -4,7 +4,7 @@ //! avoids the need for all lakers types to be generic over a back-end, which would then be //! provided by the user at initialization time. On the long run, its type may turn into a //! default associated type. -#![no_std] +#![cfg_attr(not(test), no_std)] /// Convenience re-export pub use lakers_shared::Crypto as CryptoTrait; @@ -60,53 +60,38 @@ fn test_implements_crypto() { mod tests { use hexlit::hex; use lakers_shared::*; + use rstest::rstest; use super::*; - // Test vectors from RFC 5869 (TV1 = test vector for Test Case 1) - pub const PRK_TV1: &[u8] = - &hex!("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"); - pub const INFO_TV1: &[u8] = &hex!("f0f1f2f3f4f5f6f7f8f9"); - pub const L_TV1: usize = 42; - pub const OKM_TV1: &[u8] = &hex!( - "3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865" - ); - - #[test] - fn test_hkdf_expand_basic() { + // Test vectors from RFC 5869, covering Test Cases 1 and 2 + #[rstest] + #[case( + &hex!("077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"), + &hex!("f0f1f2f3f4f5f6f7f8f9"), + 42, + &hex!("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865") + )] + #[case( + &hex!("06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244"), + &hex!("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"), + 82, + &hex!("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87") + )] + fn test_hkdf_expand( + #[case] prk_slice: &[u8], + #[case] info_slice: &[u8], + #[case] output_length: usize, + #[case] expected_okm_slice: &[u8], + ) { let mut crypto = default_crypto(); let mut prk = [0; SHA256_DIGEST_LEN]; - prk[..PRK_TV1.len()].copy_from_slice(PRK_TV1); + prk[..prk_slice.len()].copy_from_slice(prk_slice); let mut info = [0; MAX_INFO_LEN]; - info[..INFO_TV1.len()].copy_from_slice(INFO_TV1); + info[..info_slice.len()].copy_from_slice(info_slice); - let mut okm_tv: BytesMaxBuffer = [0; MAX_BUFFER_LEN]; - okm_tv[..OKM_TV1.len()].copy_from_slice(OKM_TV1); - - let okm = crypto.hkdf_expand(&prk, &info, INFO_TV1.len(), L_TV1); - assert_eq!(okm, okm_tv); - } - - pub const PRK_TV2: &[u8] = - &hex!("06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244"); - pub const INFO_TV2: &[u8] = &hex!("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"); - pub const L_TV2: usize = 82; - pub const OKM_TV2: &[u8] = &hex!("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"); - - #[test] - fn test_hkdf_expand_long() { - let mut crypto = default_crypto(); - - let mut prk = [0; SHA256_DIGEST_LEN]; - prk[..PRK_TV2.len()].copy_from_slice(PRK_TV2); - let mut info = [0; MAX_INFO_LEN]; - info[..INFO_TV2.len()].copy_from_slice(INFO_TV2); - - let mut okm_tv: BytesMaxBuffer = [0; MAX_BUFFER_LEN]; - okm_tv[..OKM_TV2.len()].copy_from_slice(OKM_TV2); - - let okm = crypto.hkdf_expand(&prk, &info, INFO_TV2.len(), L_TV2); - assert_eq!(okm, okm_tv); + let okm = crypto.hkdf_expand(&prk, &info, info_slice.len(), output_length); + assert_eq!(okm[..output_length], expected_okm_slice[..]); } }