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/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 2a3e29c..6e79646 100644 --- a/src/dhkex.rs +++ b/src/dhkex.rs @@ -44,8 +44,8 @@ pub trait DhKeyExchange { ) -> (Self::PrivateKey, Self::PublicKey); } -#[cfg(any(feature = "p256", feature = "p384"))] -pub(crate) mod ecdh_nistp; +#[cfg(any(feature = "p256", feature = "p384", feature = "k256"))] +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 95% rename from src/dhkex/ecdh_nistp.rs rename to src/dhkex/ecdh_nist.rs index 00d3fb8..c2702e0 100644 --- a/src/dhkex/ecdh_nistp.rs +++ b/src/dhkex/ecdh_nist.rs @@ -259,10 +259,23 @@ 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}; + #[cfg(feature = "k256")] + use super::k256::DhK256; #[cfg(feature = "p256")] use super::p256::DhP256; #[cfg(feature = "p384")] @@ -426,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] @@ -437,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] @@ -448,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 + ); }