From dec0efdff67e41338e5fc76e4656e743f26b6fa9 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Mon, 30 Oct 2023 03:53:08 -0400 Subject: [PATCH 1/3] Impld secp256k1 DHKEX --- .github/workflows/ci.yml | 6 ++++++ Cargo.toml | 2 ++ src/dhkex.rs | 2 +- src/dhkex/ecdh_nistp.rs | 11 +++++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f7529c..c1e87f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,12 @@ jobs: toolchain: ${{ matrix.toolchain }} override: true + - name: Run cargo test with just K256 and serde enabled + env: + CARGO_INCREMENTAL: 0 + RUSTFLAGS: -D warnings -A dead_code -A unused_imports + run: cargo test --no-default-features --features="k256,serde_impls" + - name: Run cargo test with just X25519 enabled env: CARGO_INCREMENTAL: 0 diff --git a/Cargo.toml b/Cargo.toml index 65b3bdf..b5b6553 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ default = ["alloc", "p256", "x25519"] x25519 = ["dep:x25519-dalek"] p384 = ["dep:p384"] p256 = ["dep:p256"] +k256 = ["dep:k256"] # Include allocating methods like open() and seal() alloc = [] # Includes an implementation of `std::error::Error` for `HpkeError`. Also does what `alloc` does. @@ -34,6 +35,7 @@ digest = "0.10" hkdf = "0.12" hmac = "0.12" rand_core = { version = "0.6", default-features = false } +k256 = { version = "0.13", default-features = false, features = ["arithmetic", "ecdh"], optional = true} p256 = { version = "0.13", default-features = false, features = ["arithmetic", "ecdh"], optional = true} p384 = { version = "0.13", default-features = false, features = ["arithmetic", "ecdh"], optional = true} sha2 = { version = "0.10", default-features = false } diff --git a/src/dhkex.rs b/src/dhkex.rs index 2a3e29c..eabcfeb 100644 --- a/src/dhkex.rs +++ b/src/dhkex.rs @@ -44,7 +44,7 @@ pub trait DhKeyExchange { ) -> (Self::PrivateKey, Self::PublicKey); } -#[cfg(any(feature = "p256", feature = "p384"))] +#[cfg(any(feature = "p256", feature = "p384", feature = "k256"))] pub(crate) mod ecdh_nistp; #[cfg(feature = "x25519")] diff --git a/src/dhkex/ecdh_nistp.rs b/src/dhkex/ecdh_nistp.rs index 00d3fb8..b1b11b1 100644 --- a/src/dhkex/ecdh_nistp.rs +++ b/src/dhkex/ecdh_nistp.rs @@ -259,6 +259,17 @@ nistp_dhkex!( 0xFF // RFC 9180 ยง7.1.3: The `bitmask` in DeriveKeyPair to be 0xFF for P-384 ); +#[cfg(feature = "k256")] +nistp_dhkex!( + "K-256", + DhK256, + k256, + typenum::U65, + typenum::U32, + typenum::U32, + 0xFF +); + #[cfg(test)] mod tests { use crate::{dhkex::DhKeyExchange, test_util::dhkex_gen_keypair, Deserializable, Serializable}; From 469dd349f444c6eba84761be8aa9fd1f94aa51fc Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Thu, 16 Nov 2023 01:45:20 -0500 Subject: [PATCH 2/3] Filled in k256 KEM and most automated tests --- src/aead.rs | 29 +++++++++++++++++++++++ src/dhkex.rs | 2 +- src/dhkex/{ecdh_nistp.rs => ecdh_nist.rs} | 29 ++++++++++++++++++++--- src/kem.rs | 8 +++++++ src/kem/dhkem.rs | 15 ++++++++++-- src/setup.rs | 18 ++++++++++++++ src/single_shot.rs | 8 +++++++ 7 files changed, 103 insertions(+), 6 deletions(-) rename src/dhkex/{ecdh_nistp.rs => ecdh_nist.rs} (96%) diff --git a/src/aead.rs b/src/aead.rs index a927db4..63244da 100644 --- a/src/aead.rs +++ b/src/aead.rs @@ -765,6 +765,35 @@ mod test { ); } + #[cfg(all(feature = "p256", any(feature = "alloc", feature = "std")))] + mod k256_tests { + use super::*; + + test_export_idempotence!(test_export_idempotence_k256, crate::kem::DhP256HkdfSha256); + test_exportonly_panics!( + test_exportonly_panics_k256_seal, + test_exportonly_panics_k256_open, + crate::kem::DhK256HkdfSha256 + ); + test_overflow!(test_overflow_k256, crate::kem::DhK256HkdfSha256); + + test_ctx_correctness!( + test_ctx_correctness_aes128_k256, + AesGcm128, + crate::kem::DhK256HkdfSha256 + ); + test_ctx_correctness!( + test_ctx_correctness_aes256_k256, + AesGcm256, + crate::kem::DhK256HkdfSha256 + ); + test_ctx_correctness!( + test_ctx_correctness_chacha_k256, + ChaCha20Poly1305, + crate::kem::DhK256HkdfSha256 + ); + } + /// Tests that Serialize::write_exact() panics when given a buffer of incorrect length #[should_panic] #[test] diff --git a/src/dhkex.rs b/src/dhkex.rs index eabcfeb..6e79646 100644 --- a/src/dhkex.rs +++ b/src/dhkex.rs @@ -45,7 +45,7 @@ pub trait DhKeyExchange { } #[cfg(any(feature = "p256", feature = "p384", feature = "k256"))] -pub(crate) mod ecdh_nistp; +pub(crate) mod ecdh_nist; #[cfg(feature = "x25519")] pub(crate) mod x25519; diff --git a/src/dhkex/ecdh_nistp.rs b/src/dhkex/ecdh_nist.rs similarity index 96% rename from src/dhkex/ecdh_nistp.rs rename to src/dhkex/ecdh_nist.rs index b1b11b1..c2702e0 100644 --- a/src/dhkex/ecdh_nistp.rs +++ b/src/dhkex/ecdh_nist.rs @@ -274,6 +274,8 @@ nistp_dhkex!( mod tests { use crate::{dhkex::DhKeyExchange, test_util::dhkex_gen_keypair, Deserializable, Serializable}; + #[cfg(feature = "k256")] + use super::k256::DhK256; #[cfg(feature = "p256")] use super::p256::DhP256; #[cfg(feature = "p384")] @@ -437,6 +439,12 @@ mod tests { fn test_vector_ecdh_p384() { test_vector_ecdh::(&P384_PRIVKEYS[0], &P384_PUBKEYS[1], &P384_DH_RES_XCOORD); } + #[cfg(feature = "k256")] + #[test] + fn test_vector_ecdh_k256() { + // TODO: Get some test vectors + test_vector_ecdh::(todo!(), todo!(), todo!()); + } #[cfg(feature = "p256")] #[test] @@ -448,6 +456,12 @@ mod tests { fn test_vector_corresponding_pubkey_p384() { test_vector_corresponding_pubkey::(P384_PRIVKEYS, P384_PUBKEYS); } + #[cfg(feature = "k256")] + #[test] + fn test_vector_corresponding_pubkey_k256() { + // TODO: Get some test vectors + test_vector_corresponding_pubkey::(todo!(), todo!()); + } #[cfg(feature = "p256")] #[test] @@ -459,16 +473,25 @@ mod tests { fn test_pubkey_serialize_correctness_p384() { test_pubkey_serialize_correctness::(); } + #[cfg(feature = "k256")] + #[test] + fn test_pubkey_serialize_correctness_k256() { + test_pubkey_serialize_correctness::(); + } - #[cfg(feature = "256")] + #[cfg(feature = "p256")] #[test] fn test_dh_serialize_correctness_p256() { test_dh_serialize_correctness::(); } - - #[cfg(feature = "384")] + #[cfg(feature = "p384")] #[test] fn test_dh_serialize_correctness_p384() { test_dh_serialize_correctness::(); } + #[cfg(feature = "k256")] + #[test] + fn test_dh_serialize_correctness_k256() { + test_dh_serialize_correctness::(); + } } diff --git a/src/kem.rs b/src/kem.rs index 532714c..f36cd11 100644 --- a/src/kem.rs +++ b/src/kem.rs @@ -215,4 +215,12 @@ mod tests { test_encap_correctness!(test_encap_correctness_p384, crate::kem::DhP384HkdfSha384); test_encapped_serialize!(test_encapped_serialize_p384, crate::kem::DhP384HkdfSha384); } + + #[cfg(feature = "k256")] + mod k256_tests { + use super::*; + + test_encap_correctness!(test_encap_correctness_k256, crate::kem::DhK256HkdfSha256); + test_encapped_serialize!(test_encapped_serialize_k256, crate::kem::DhK256HkdfSha256); + } } diff --git a/src/kem/dhkem.rs b/src/kem/dhkem.rs index e5bb6a9..14049a9 100644 --- a/src/kem/dhkem.rs +++ b/src/kem/dhkem.rs @@ -364,7 +364,7 @@ impl_dhkem!( impl_dhkem!( dhp256_hkdfsha256, DhP256HkdfSha256, - crate::dhkex::ecdh_nistp::p256::DhP256, + crate::dhkex::ecdh_nist::p256::DhP256, crate::kdf::HkdfSha256, 0x0010, "Represents DHKEM(P-256, HKDF-SHA256)" @@ -375,8 +375,19 @@ impl_dhkem!( impl_dhkem!( dhp384_hkdfsha384, DhP384HkdfSha384, - crate::dhkex::ecdh_nistp::p384::DhP384, + crate::dhkex::ecdh_nist::p384::DhP384, crate::kdf::HkdfSha384, 0x0011, "Represents DHKEM(P-384, HKDF-SHA384)" ); + +// Implement DHKEM(K-256, HKDF-SHA256) +#[cfg(feature = "k256")] +impl_dhkem!( + dhk256_hkdfsha256, + DhK256HkdfSha256, + crate::dhkex::ecdh_nist::k256::DhK256, + crate::kdf::HkdfSha256, + 0x0016, + "Represents DHKEM(K-256, HKDF-SHA256)" +); diff --git a/src/setup.rs b/src/setup.rs index 59b0a08..dbe34d4 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -391,4 +391,22 @@ mod test { crate::kem::dhp384_hkdfsha384::DhP384HkdfSha384 ); } + + #[cfg(feature = "k256")] + mod k256_tests { + use super::*; + + test_setup_correctness!( + test_setup_correctness_k256, + ChaCha20Poly1305, + HkdfSha256, + crate::kem::dhk256_hkdfsha256::DhK256HkdfSha256 + ); + test_setup_soundness!( + test_setup_soundness_k256, + ChaCha20Poly1305, + HkdfSha256, + crate::kem::dhk256_hkdfsha256::DhK256HkdfSha256 + ); + } } diff --git a/src/single_shot.rs b/src/single_shot.rs index 9059d6a..ecb4dec 100644 --- a/src/single_shot.rs +++ b/src/single_shot.rs @@ -247,4 +247,12 @@ mod test { crate::kdf::HkdfSha384, crate::kem::dhp384_hkdfsha384::DhP384HkdfSha384 ); + + #[cfg(feature = "k256")] + test_single_shot_correctness!( + test_single_shot_correctness_k256, + ChaCha20Poly1305, + crate::kdf::HkdfSha256, + crate::kem::dhk256_hkdfsha256::DhK256HkdfSha256 + ); } From 60271a8f3aec460df92fb855ba062dd2f63f7148 Mon Sep 17 00:00:00 2001 From: Michael Rosenberg Date: Thu, 16 Nov 2023 01:46:36 -0500 Subject: [PATCH 3/3] Removed serde from CI --- .github/workflows/ci.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1e87f5..8f7529c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,12 +31,6 @@ jobs: toolchain: ${{ matrix.toolchain }} override: true - - name: Run cargo test with just K256 and serde enabled - env: - CARGO_INCREMENTAL: 0 - RUSTFLAGS: -D warnings -A dead_code -A unused_imports - run: cargo test --no-default-features --features="k256,serde_impls" - - name: Run cargo test with just X25519 enabled env: CARGO_INCREMENTAL: 0