From 50c4f851da95ac6cadb8e72038094328ab6cda38 Mon Sep 17 00:00:00 2001 From: Justin W Smith <103147162+justsmth@users.noreply.github.com> Date: Thu, 21 Dec 2023 18:14:17 -0500 Subject: [PATCH] Refactoring EC marshalling; support agreement::PrivateKey --- aws-lc-rs/src/agreement.rs | 589 ++++++++++-------- .../{ => agreement}/data/agreement_tests.txt | 0 aws-lc-rs/src/agreement/ephemeral.rs | 349 +++++++++++ aws-lc-rs/src/ec.rs | 36 +- aws-lc-rs/src/ec/key_pair.rs | 34 +- aws-lc-rs/src/ed25519.rs | 8 +- aws-lc-rs/src/encoding.rs | 7 +- aws-lc-rs/tests/ed25519_tests.rs | 4 +- 8 files changed, 727 insertions(+), 300 deletions(-) rename aws-lc-rs/src/{ => agreement}/data/agreement_tests.txt (100%) diff --git a/aws-lc-rs/src/agreement.rs b/aws-lc-rs/src/agreement.rs index 9d01b1c52c0..e2360f4e56c 100644 --- a/aws-lc-rs/src/agreement.rs +++ b/aws-lc-rs/src/agreement.rs @@ -56,17 +56,23 @@ pub use ephemeral::{agree_ephemeral, EphemeralPrivateKey}; use crate::ec::{ ec_group_from_nid, ec_point_from_bytes, evp_key_generate, evp_pkey_from_public_point, }; -use crate::error::Unspecified; +use crate::error::{KeyRejected, Unspecified}; use crate::fips::indicator_check; -use crate::ptr::LcPtr; +use crate::ptr::{ConstPointer, DetachableLcPtr, LcPtr, Pointer}; use crate::{ec, hex}; use aws_lc::{ EVP_PKEY_CTX_new, EVP_PKEY_CTX_new_id, EVP_PKEY_derive, EVP_PKEY_derive_init, - EVP_PKEY_derive_set_peer, EVP_PKEY_get_raw_public_key, EVP_PKEY_keygen, EVP_PKEY_keygen_init, - EVP_PKEY_new_raw_public_key, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, EVP_PKEY, - EVP_PKEY_X25519, NID_X25519, + EVP_PKEY_derive_set_peer, EVP_PKEY_get0_EC_KEY, EVP_PKEY_get_raw_private_key, + EVP_PKEY_get_raw_public_key, EVP_PKEY_keygen, EVP_PKEY_keygen_init, + EVP_PKEY_new_raw_private_key, EVP_PKEY_new_raw_public_key, NID_X9_62_prime256v1, NID_secp384r1, + NID_secp521r1, EVP_PKEY, EVP_PKEY_X25519, NID_X25519, }; +use crate::buffer::Buffer; +use crate::ed25519::ED25519_PRIVATE_KEY_SEED_LEN; +use crate::encoding::{ + AsBigEndian, AsDer, Curve25519SeedBin, EcPrivateKeyBin, EcPrivateKeyRfc5915Der, +}; use core::fmt; use std::fmt::{Debug, Formatter}; use std::ptr::null_mut; @@ -100,6 +106,16 @@ impl AlgorithmID { AlgorithmID::X25519 => 32, } } + + #[inline] + fn private_key_size(&self) -> usize { + match self { + AlgorithmID::ECDH_P256 => 32, + AlgorithmID::ECDH_P384 => 48, + AlgorithmID::ECDH_P521 => 66, + AlgorithmID::X25519 => ED25519_PRIVATE_KEY_SEED_LEN, + } + } } impl Debug for AlgorithmID { @@ -152,7 +168,6 @@ pub static ECDH_P521: Algorithm = Algorithm { pub static X25519: Algorithm = Algorithm { id: AlgorithmID::X25519, }; -#[cfg(test)] const X25519_PRIVATE_KEY_LEN: usize = aws_lc::X25519_PRIVATE_KEY_LEN as usize; #[cfg(test)] const ECDH_P256_PRIVATE_KEY_LEN: usize = 32; @@ -185,6 +200,15 @@ impl KeyInner { KeyInner::X25519(..) => &X25519, } } + + fn get_evp_pkey(&self) -> &LcPtr { + match self { + KeyInner::ECDH_P256(evp_pkey) + | KeyInner::ECDH_P384(evp_pkey) + | KeyInner::ECDH_P521(evp_pkey) + | KeyInner::X25519(evp_pkey) => evp_pkey, + } + } } unsafe impl Send for PrivateKey {} @@ -207,6 +231,23 @@ impl Debug for PrivateKey { } impl PrivateKey { + fn new(alg: &'static Algorithm, evp_pkey: LcPtr) -> Self { + match alg.id { + AlgorithmID::X25519 => Self { + inner_key: KeyInner::X25519(evp_pkey), + }, + AlgorithmID::ECDH_P256 => Self { + inner_key: KeyInner::ECDH_P256(evp_pkey), + }, + AlgorithmID::ECDH_P384 => Self { + inner_key: KeyInner::ECDH_P384(evp_pkey), + }, + AlgorithmID::ECDH_P521 => Self { + inner_key: KeyInner::ECDH_P521(evp_pkey), + }, + } + } + #[inline] /// Generate a new private key for the given algorithm. /// @@ -219,32 +260,67 @@ impl PrivateKey { /// # Errors /// `error::Unspecified` when operation fails due to internal error. pub fn generate(alg: &'static Algorithm) -> Result { - match alg.id { - AlgorithmID::X25519 => { - let priv_key = generate_x25519()?; - Ok(PrivateKey { - inner_key: KeyInner::X25519(priv_key), - }) - } - AlgorithmID::ECDH_P256 => { - let ec_key = evp_key_generate(ECDH_P256.id.nid())?; - Ok(PrivateKey { - inner_key: KeyInner::ECDH_P256(ec_key), - }) - } - AlgorithmID::ECDH_P384 => { - let ec_key = evp_key_generate(ECDH_P384.id.nid())?; - Ok(PrivateKey { - inner_key: KeyInner::ECDH_P384(ec_key), - }) - } - AlgorithmID::ECDH_P521 => { - let ec_key = evp_key_generate(ECDH_P521.id.nid())?; - Ok(PrivateKey { - inner_key: KeyInner::ECDH_P521(ec_key), - }) - } + let evp_pkey = match alg.id { + AlgorithmID::X25519 => generate_x25519()?, + _ => evp_key_generate(ECDH_P256.id.nid())?, + }; + Ok(Self::new(alg, evp_pkey)) + } + + /// Deserializes a DER-encoded private key structure to produce a `agreement::PrivateKey`. + /// + /// This function is typically used to deserialize RFC 5915 encoded private keys, but it will + /// attempt to automatically detect other key formats. This function supports unencrypted + /// PKCS#8 `PrivateKeyInfo` structures as well as key type specific formats. + /// + /// X25519 keys are not supported. See `PrivateKey::as_der`. + /// + /// # Errors + /// `error::KeyRejected` if parsing failed or key otherwise unacceptable. + /// + /// # Panics + pub fn from_private_key_der( + alg: &'static Algorithm, + key_bytes: &[u8], + ) -> Result { + if AlgorithmID::X25519 == alg.id { + return Err(KeyRejected::invalid_encoding()); } + let evp_pkey = unsafe { ec::unmarshal_der_to_private_key(key_bytes, alg.id.nid())? }; + Ok(Self::new(alg, evp_pkey)) + } + + /// Constructs an ECDH key from private key bytes + /// + /// The private key must encoded as a big-endian fixed-length integer. For + /// example, a P-256 private key must be 32 bytes prefixed with leading + /// zeros as needed. + /// + /// # Errors + /// `error::KeyRejected` if parsing failed or key otherwise unacceptable. + pub fn from_private_key( + alg: &'static Algorithm, + key_bytes: &[u8], + ) -> Result { + let evp_pkey = if AlgorithmID::X25519 == alg.id { + LcPtr::new(unsafe { + EVP_PKEY_new_raw_private_key( + EVP_PKEY_X25519, + null_mut(), + key_bytes.as_ptr(), + X25519_PRIVATE_KEY_LEN, + ) + })? + } else { + let ec_group = unsafe { ec_group_from_nid(alg.id.nid())? }; + let private_bn = DetachableLcPtr::try_from(key_bytes)?; + + unsafe { + ec::evp_pkey_from_private(&ec_group.as_const(), &private_bn.as_const()) + .map_err(|_| KeyRejected::invalid_encoding())? + } + }; + Ok(Self::new(alg, evp_pkey)) } #[cfg(test)] @@ -281,8 +357,6 @@ impl PrivateKey { fn from_x25519_private_key( priv_key: &[u8; X25519_PRIVATE_KEY_LEN], ) -> Result { - use aws_lc::EVP_PKEY_new_raw_private_key; - let pkey = LcPtr::new(unsafe { EVP_PKEY_new_raw_private_key( EVP_PKEY_X25519, @@ -368,10 +442,80 @@ impl PrivateKey { } } +impl AsDer for PrivateKey { + /// Serializes the key as a DER-encoded `ECPrivateKey` (RFC 5915) structure. + /// + /// X25519 is not supported. + /// + /// # Errors + /// `error::Unspecified` if serialization failed. + fn as_der(&self) -> Result { + if AlgorithmID::X25519 == self.inner_key.algorithm().id { + return Err(Unspecified); + } + + let mut outp = null_mut::(); + let ec_key = { + ConstPointer::new(unsafe { + EVP_PKEY_get0_EC_KEY(self.inner_key.get_evp_pkey().as_const_ptr()) + })? + }; + let length = usize::try_from(unsafe { aws_lc::i2d_ECPrivateKey(*ec_key, &mut outp) }) + .map_err(|_| Unspecified)?; + let outp = LcPtr::new(outp)?; + Ok(Buffer::take_from_slice(unsafe { + std::slice::from_raw_parts_mut(*outp, length) + })) + } +} + +impl AsBigEndian for PrivateKey { + /// Exposes the private key encoded as a big-endian fixed-length integer. + /// + /// X25519 is not supported. + /// + /// # Errors + /// `error::Unspecified` if serialization failed. + fn as_be_bytes(&self) -> Result { + if AlgorithmID::X25519 == self.inner_key.algorithm().id { + return Err(Unspecified); + } + let buffer = unsafe { + ec::marshal_private_key_to_buffer( + self.inner_key.algorithm().id.private_key_size(), + &self.inner_key.get_evp_pkey().as_const(), + )? + }; + Ok(EcPrivateKeyBin::new(buffer)) + } +} + +impl AsBigEndian for PrivateKey { + /// Exposes the seed encoded as a big-endian fixed-length integer. + /// + /// Only X25519 is supported. + /// + /// # Errors + /// `error::Unspecified` if serialization failed. + fn as_be_bytes(&self) -> Result { + if AlgorithmID::X25519 != self.inner_key.algorithm().id { + return Err(Unspecified); + } + let evp_pkey = self.inner_key.get_evp_pkey().as_const(); + let mut buffer = [0u8; ED25519_PRIVATE_KEY_SEED_LEN]; + let mut out_len = ED25519_PRIVATE_KEY_SEED_LEN; + if 1 != unsafe { + EVP_PKEY_get_raw_private_key(*evp_pkey, buffer.as_mut_ptr(), &mut out_len) + } { + return Err(Unspecified); + } + debug_assert_eq!(32, out_len); + Ok(Curve25519SeedBin::new(Vec::from(buffer))) + } +} + #[cfg(test)] fn from_ec_private_key(priv_key: &[u8], nid: i32) -> Result, Unspecified> { - use crate::ptr::DetachableLcPtr; - let ec_group = unsafe { ec_group_from_nid(nid)? }; let priv_key = DetachableLcPtr::try_from(priv_key)?; @@ -626,63 +770,13 @@ fn x25519_diffie_hellman<'a>( #[cfg(test)] mod tests { - use crate::error::Unspecified; - use crate::{agreement, rand, test, test_file}; - - #[cfg(feature = "fips")] - mod fips; - - #[test] - fn test_agreement_ecdh_x25519_rfc_iterated() { - fn expect_iterated_x25519( - expected_result: &str, - range: core::ops::Range, - k: &mut Vec, - u: &mut Vec, - ) { - for _ in range { - let new_k = x25519(k, u); - *u = k.clone(); - *k = new_k; - } - assert_eq!(&h(expected_result), k); - } - - let mut k = h("0900000000000000000000000000000000000000000000000000000000000000"); - let mut u = k.clone(); - - expect_iterated_x25519( - "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079", - 0..1, - &mut k, - &mut u, - ); - expect_iterated_x25519( - "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51", - 1..1_000, - &mut k, - &mut u, - ); - - // The spec gives a test vector for 1,000,000 iterations but it takes - // too long to do 1,000,000 iterations by default right now. This - // 10,000 iteration vector is self-computed. - expect_iterated_x25519( - "2c125a20f639d504a7703d2e223c79a79de48c4ee8c23379aa19a62ecd211815", - 1_000..10_000, - &mut k, - &mut u, - ); - - if cfg!(feature = "slow_tests") { - expect_iterated_x25519( - "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424", - 10_000..1_000_000, - &mut k, - &mut u, - ); - } - } + use crate::agreement::{ + PrivateKey, PublicKey, UnparsedPublicKey, ECDH_P256, ECDH_P384, ECDH_P521, X25519, + }; + use crate::encoding::{ + AsBigEndian, AsDer, Curve25519SeedBin, EcPrivateKeyBin, EcPrivateKeyRfc5915Der, + }; + use crate::{agreement, rand, test}; #[test] fn test_agreement_x25519() { @@ -700,7 +794,7 @@ mod tests { let my_private = { let rng = test::rand::FixedSliceRandom { bytes: &my_private }; - agreement::PrivateKey::generate_for_test(alg, &rng).unwrap() + PrivateKey::generate_for_test(alg, &rng).unwrap() }; let my_public = test::from_dirty_hex( @@ -712,22 +806,35 @@ mod tests { assert_eq!(my_private.algorithm(), alg); + let be_private_key_buffer: Curve25519SeedBin = my_private.as_be_bytes().unwrap(); + let be_private_key = + PrivateKey::from_private_key(&X25519, be_private_key_buffer.as_ref()).unwrap(); + { + let result = agreement::agree(&be_private_key, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + let computed_public = my_private.compute_public_key().unwrap(); assert_eq!(computed_public.as_ref(), &my_public[..]); assert_eq!(computed_public.algorithm(), alg); - - let result = agreement::agree(&my_private, &peer_public, (), |key_material| { - assert_eq!(key_material, &output[..]); - Ok(()) - }); - assert_eq!(result, Ok(())); - - let result2 = agreement::agree(&my_private, &peer_public, (), |key_material| { - assert_eq!(key_material, &output[..]); - Ok(()) - }); - assert_eq!(result2, Ok(())); + { + let result = agreement::agree(&my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + { + let result = agreement::agree(&my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } } #[test] @@ -748,7 +855,7 @@ mod tests { let my_private = { let rng = test::rand::FixedSliceRandom { bytes: &my_private }; - agreement::EphemeralPrivateKey::generate_for_test(alg, &rng).unwrap() + PrivateKey::generate_for_test(alg, &rng).unwrap() }; let my_public = test::from_dirty_hex( @@ -760,16 +867,48 @@ mod tests { assert_eq!(my_private.algorithm(), alg); + let be_private_key_buffer: EcPrivateKeyBin = my_private.as_be_bytes().unwrap(); + let be_private_key = + PrivateKey::from_private_key(&ECDH_P256, be_private_key_buffer.as_ref()).unwrap(); + { + let result = agreement::agree(&be_private_key, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + + let der_private_key_buffer: EcPrivateKeyRfc5915Der = my_private.as_der().unwrap(); + let der_private_key = + PrivateKey::from_private_key_der(&ECDH_P256, der_private_key_buffer.as_ref()).unwrap(); + { + let result = agreement::agree(&der_private_key, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + let computed_public = my_private.compute_public_key().unwrap(); assert_eq!(computed_public.as_ref(), &my_public[..]); assert_eq!(computed_public.algorithm(), alg); - let result = agreement::agree_ephemeral(my_private, &peer_public, (), |key_material| { - assert_eq!(key_material, &output[..]); - Ok(()) - }); - assert_eq!(result, Ok(())); + { + let result = agreement::agree(&my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + + { + let result = agreement::agree(&my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } } #[test] @@ -788,7 +927,7 @@ mod tests { let my_private = { let rng = test::rand::FixedSliceRandom { bytes: &my_private }; - agreement::EphemeralPrivateKey::generate_for_test(alg, &rng).unwrap() + PrivateKey::generate_for_test(alg, &rng).unwrap() }; let my_public = test::from_dirty_hex( @@ -800,16 +939,40 @@ mod tests { assert_eq!(my_private.algorithm(), alg); + let be_private_key_buffer: EcPrivateKeyBin = my_private.as_be_bytes().unwrap(); + let be_private_key = + PrivateKey::from_private_key(&ECDH_P384, be_private_key_buffer.as_ref()).unwrap(); + { + let result = agreement::agree(&be_private_key, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + + let der_private_key_buffer: EcPrivateKeyRfc5915Der = my_private.as_der().unwrap(); + let der_private_key = + PrivateKey::from_private_key_der(&ECDH_P384, der_private_key_buffer.as_ref()).unwrap(); + { + let result = agreement::agree(&der_private_key, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + let computed_public = my_private.compute_public_key().unwrap(); assert_eq!(computed_public.as_ref(), &my_public[..]); assert_eq!(computed_public.algorithm(), alg); - let result = agreement::agree_ephemeral(my_private, &peer_public, (), |key_material| { - assert_eq!(key_material, &output[..]); - Ok(()) - }); - assert_eq!(result, Ok(())); + { + let result = agreement::agree(&my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } } #[test] @@ -828,7 +991,7 @@ mod tests { let my_private = { let rng = test::rand::FixedSliceRandom { bytes: &my_private }; - agreement::EphemeralPrivateKey::generate_for_test(alg, &rng).unwrap() + agreement::PrivateKey::generate_for_test(alg, &rng).unwrap() }; let my_public = test::from_dirty_hex( @@ -840,16 +1003,46 @@ mod tests { assert_eq!(my_private.algorithm(), alg); + let be_private_key_buffer: EcPrivateKeyBin = my_private.as_be_bytes().unwrap(); + let be_private_key = + PrivateKey::from_private_key(&ECDH_P521, be_private_key_buffer.as_ref()).unwrap(); + { + let result = agreement::agree(&be_private_key, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + + let der_private_key_buffer: EcPrivateKeyRfc5915Der = my_private.as_der().unwrap(); + let der_private_key = + PrivateKey::from_private_key_der(&ECDH_P521, der_private_key_buffer.as_ref()).unwrap(); + { + let result = agreement::agree(&der_private_key, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + let computed_public = my_private.compute_public_key().unwrap(); assert_eq!(computed_public.as_ref(), &my_public[..]); assert_eq!(computed_public.algorithm(), alg); - - let result = agreement::agree_ephemeral(my_private, &peer_public, (), |key_material| { - assert_eq!(key_material, &output[..]); - Ok(()) - }); - assert_eq!(result, Ok(())); + { + let result = agreement::agree(&my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + { + let result = agreement::agree(&my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } } #[test] @@ -859,26 +1052,24 @@ mod tests { use regex::Regex; let rng = rand::SystemRandom::new(); - let private_key = - agreement::PrivateKey::generate_for_test(&agreement::ECDH_P256, &rng).unwrap(); + let private_key = PrivateKey::generate_for_test(&ECDH_P256, &rng).unwrap(); - test::compile_time_assert_send::(); - test::compile_time_assert_sync::(); + test::compile_time_assert_send::(); + test::compile_time_assert_sync::(); assert_eq!( format!("{:?}", &private_key), "PrivateKey { algorithm: Algorithm { curve: P256 } }" ); - let ephemeral_private_key = - agreement::EphemeralPrivateKey::generate_for_test(&agreement::ECDH_P256, &rng).unwrap(); + let ephemeral_private_key = PrivateKey::generate_for_test(&ECDH_P256, &rng).unwrap(); - test::compile_time_assert_send::(); - test::compile_time_assert_sync::(); + test::compile_time_assert_send::(); + test::compile_time_assert_sync::(); assert_eq!( format!("{:?}", &ephemeral_private_key), - "EphemeralPrivateKey { algorithm: Algorithm { curve: P256 } }" + "PrivateKey { algorithm: Algorithm { curve: P256 } }" ); let public_key = private_key.compute_public_key().unwrap(); @@ -898,25 +1089,25 @@ mod tests { assert_eq!(public_key.as_ref(), pubkey_clone.as_ref()); assert_eq!(pubkey_debug, format!("{:?}", &pubkey_clone)); - test::compile_time_assert_clone::(); - test::compile_time_assert_send::(); - //test::compile_time_assert_sync::(); + test::compile_time_assert_clone::(); + test::compile_time_assert_send::(); + test::compile_time_assert_sync::(); // Verify `PublicKey` implements `Debug`. // // TODO: Test the actual output. let _: &dyn core::fmt::Debug = &public_key; - test::compile_time_assert_clone::>(); - test::compile_time_assert_copy::>(); - test::compile_time_assert_sync::>(); + test::compile_time_assert_clone::>(); + test::compile_time_assert_copy::>(); + test::compile_time_assert_sync::>(); - test::compile_time_assert_clone::>>(); - test::compile_time_assert_sync::>>(); + test::compile_time_assert_clone::>>(); + test::compile_time_assert_sync::>>(); let bytes = [0x01, 0x02, 0x03]; - let unparsed_public_key = agreement::UnparsedPublicKey::new(&agreement::X25519, &bytes); + let unparsed_public_key = UnparsedPublicKey::new(&X25519, &bytes); let unparsed_pubkey_clone = unparsed_public_key; assert_eq!( format!("{unparsed_public_key:?}"), @@ -927,8 +1118,7 @@ mod tests { r#"UnparsedPublicKey { algorithm: Algorithm { curve: Curve25519 }, bytes: "010203" }"# ); - let unparsed_public_key = - agreement::UnparsedPublicKey::new(&agreement::X25519, Vec::from(bytes)); + let unparsed_public_key = UnparsedPublicKey::new(&X25519, Vec::from(bytes)); #[allow(clippy::redundant_clone)] let unparsed_pubkey_clone = unparsed_public_key.clone(); assert_eq!( @@ -940,115 +1130,4 @@ mod tests { r#"UnparsedPublicKey { algorithm: Algorithm { curve: Curve25519 }, bytes: "010203" }"# ); } - - #[test] - fn agreement_agree_ephemeral() { - let rng = rand::SystemRandom::new(); - - test::run( - test_file!("data/agreement_tests.txt"), - |section, test_case| { - assert_eq!(section, ""); - - let curve_name = test_case.consume_string("Curve"); - let alg = alg_from_curve_name(&curve_name); - let peer_public = - agreement::UnparsedPublicKey::new(alg, test_case.consume_bytes("PeerQ")); - - match test_case.consume_optional_string("Error") { - None => { - let my_private_bytes = test_case.consume_bytes("D"); - let my_private = { - let rng = test::rand::FixedSliceRandom { - bytes: &my_private_bytes, - }; - agreement::EphemeralPrivateKey::generate_for_test(alg, &rng)? - }; - let my_public = test_case.consume_bytes("MyQ"); - let output = test_case.consume_bytes("Output"); - - assert_eq!(my_private.algorithm(), alg); - - let computed_public = my_private.compute_public_key().unwrap(); - assert_eq!(computed_public.as_ref(), &my_public[..]); - - assert_eq!(my_private.algorithm(), alg); - - let result = agreement::agree_ephemeral( - my_private, - &peer_public, - (), - |key_material| { - assert_eq!(key_material, &output[..]); - Ok(()) - }, - ); - assert_eq!( - result, - Ok(()), - "Failed on private key: {:?}", - test::to_hex(my_private_bytes) - ); - } - - Some(_) => { - fn kdf_not_called(_: &[u8]) -> Result<(), ()> { - panic!( - "The KDF was called during ECDH when the peer's \ - public key is invalid." - ); - } - let dummy_private_key = - agreement::EphemeralPrivateKey::generate(alg, &rng)?; - assert!(agreement::agree_ephemeral( - dummy_private_key, - &peer_public, - (), - kdf_not_called - ) - .is_err()); - } - } - - Ok(()) - }, - ); - } - - fn h(s: &str) -> Vec { - match test::from_hex(s) { - Ok(v) => v, - Err(msg) => { - panic!("{msg} in {s}"); - } - } - } - - fn alg_from_curve_name(curve_name: &str) -> &'static agreement::Algorithm { - if curve_name == "P-256" { - &agreement::ECDH_P256 - } else if curve_name == "P-384" { - &agreement::ECDH_P384 - } else if curve_name == "P-521" { - &agreement::ECDH_P521 - } else if curve_name == "X25519" { - &agreement::X25519 - } else { - panic!("Unsupported curve: {curve_name}"); - } - } - - fn x25519(private_key: &[u8], public_key: &[u8]) -> Vec { - x25519_(private_key, public_key).unwrap() - } - - fn x25519_(private_key: &[u8], public_key: &[u8]) -> Result, Unspecified> { - let rng = test::rand::FixedSliceRandom { bytes: private_key }; - let private_key = - agreement::EphemeralPrivateKey::generate_for_test(&agreement::X25519, &rng)?; - let public_key = agreement::UnparsedPublicKey::new(&agreement::X25519, public_key); - agreement::agree_ephemeral(private_key, &public_key, Unspecified, |agreed_value| { - Ok(Vec::from(agreed_value)) - }) - } } diff --git a/aws-lc-rs/src/data/agreement_tests.txt b/aws-lc-rs/src/agreement/data/agreement_tests.txt similarity index 100% rename from aws-lc-rs/src/data/agreement_tests.txt rename to aws-lc-rs/src/agreement/data/agreement_tests.txt diff --git a/aws-lc-rs/src/agreement/ephemeral.rs b/aws-lc-rs/src/agreement/ephemeral.rs index 0ae81ab3078..c3ad65b8351 100644 --- a/aws-lc-rs/src/agreement/ephemeral.rs +++ b/aws-lc-rs/src/agreement/ephemeral.rs @@ -111,3 +111,352 @@ where { agree(&my_private_key.0, peer_public_key, error_value, kdf) } + +#[cfg(test)] +mod tests { + use crate::error::Unspecified; + use crate::{agreement, rand, test, test_file}; + + #[test] + fn test_agreement_ecdh_x25519_rfc_iterated() { + fn expect_iterated_x25519( + expected_result: &str, + range: core::ops::Range, + k: &mut Vec, + u: &mut Vec, + ) { + for _ in range { + let new_k = x25519(k, u); + *u = k.clone(); + *k = new_k; + } + assert_eq!(&h(expected_result), k); + } + + let mut k = h("0900000000000000000000000000000000000000000000000000000000000000"); + let mut u = k.clone(); + + expect_iterated_x25519( + "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079", + 0..1, + &mut k, + &mut u, + ); + expect_iterated_x25519( + "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51", + 1..1_000, + &mut k, + &mut u, + ); + + // The spec gives a test vector for 1,000,000 iterations but it takes + // too long to do 1,000,000 iterations by default right now. This + // 10,000 iteration vector is self-computed. + expect_iterated_x25519( + "2c125a20f639d504a7703d2e223c79a79de48c4ee8c23379aa19a62ecd211815", + 1_000..10_000, + &mut k, + &mut u, + ); + + if cfg!(feature = "slow_tests") { + expect_iterated_x25519( + "7c3911e0ab2586fd864497297e575e6f3bc601c0883c30df5f4dd2d24f665424", + 10_000..1_000_000, + &mut k, + &mut u, + ); + } + } + + #[test] + fn test_agreement_x25519() { + let alg = &agreement::X25519; + let peer_public = agreement::UnparsedPublicKey::new( + alg, + test::from_dirty_hex( + "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c", + ), + ); + + let my_private = test::from_dirty_hex( + "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4", + ); + + let my_private = { + let rng = test::rand::FixedSliceRandom { bytes: &my_private }; + agreement::EphemeralPrivateKey::generate_for_test(alg, &rng).unwrap() + }; + + let my_public = test::from_dirty_hex( + "1c9fd88f45606d932a80c71824ae151d15d73e77de38e8e000852e614fae7019", + ); + let output = test::from_dirty_hex( + "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552", + ); + + assert_eq!(my_private.algorithm(), alg); + + let computed_public = my_private.compute_public_key().unwrap(); + assert_eq!(computed_public.as_ref(), &my_public[..]); + + assert_eq!(computed_public.algorithm(), alg); + + let result = agreement::agree_ephemeral(my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + + #[test] + fn test_agreement_ecdh_p256() { + let alg = &agreement::ECDH_P256; + let peer_public = agreement::UnparsedPublicKey::new( + alg, + test::from_dirty_hex( + "04D12DFB5289C8D4F81208B70270398C342296970A0BCCB74C736FC7554494BF6356FBF3CA366CC23E8157854C13C58D6AAC23F046ADA30F8353E74F33039872AB", + ), + ); + assert_eq!(peer_public.algorithm(), alg); + assert_eq!(peer_public.bytes(), &peer_public.bytes); + + let my_private = test::from_dirty_hex( + "C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433", + ); + + let my_private = { + let rng = test::rand::FixedSliceRandom { bytes: &my_private }; + agreement::EphemeralPrivateKey::generate_for_test(alg, &rng).unwrap() + }; + + let my_public = test::from_dirty_hex( + "04DAD0B65394221CF9B051E1FECA5787D098DFE637FC90B9EF945D0C37725811805271A0461CDB8252D61F1C456FA3E59AB1F45B33ACCF5F58389E0577B8990BB3", + ); + let output = test::from_dirty_hex( + "D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE", + ); + + assert_eq!(my_private.algorithm(), alg); + + let computed_public = my_private.compute_public_key().unwrap(); + assert_eq!(computed_public.as_ref(), &my_public[..]); + + assert_eq!(computed_public.algorithm(), alg); + + let result = agreement::agree_ephemeral(my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + + #[test] + fn test_agreement_ecdh_p384() { + let alg = &agreement::ECDH_P384; + let peer_public = agreement::UnparsedPublicKey::new( + alg, + test::from_dirty_hex( + "04E558DBEF53EECDE3D3FCCFC1AEA08A89A987475D12FD950D83CFA41732BC509D0D1AC43A0336DEF96FDA41D0774A3571DCFBEC7AACF3196472169E838430367F66EEBE3C6E70C416DD5F0C68759DD1FFF83FA40142209DFF5EAAD96DB9E6386C", + ), + ); + + let my_private = test::from_dirty_hex( + "099F3C7034D4A2C699884D73A375A67F7624EF7C6B3C0F160647B67414DCE655E35B538041E649EE3FAEF896783AB194", + ); + + let my_private = { + let rng = test::rand::FixedSliceRandom { bytes: &my_private }; + agreement::EphemeralPrivateKey::generate_for_test(alg, &rng).unwrap() + }; + + let my_public = test::from_dirty_hex( + "04667842D7D180AC2CDE6F74F37551F55755C7645C20EF73E31634FE72B4C55EE6DE3AC808ACB4BDB4C88732AEE95F41AA9482ED1FC0EEB9CAFC4984625CCFC23F65032149E0E144ADA024181535A0F38EEB9FCFF3C2C947DAE69B4C634573A81C", + ); + let output = test::from_dirty_hex( + "11187331C279962D93D604243FD592CB9D0A926F422E47187521287E7156C5C4D603135569B9E9D09CF5D4A270F59746", + ); + + assert_eq!(my_private.algorithm(), alg); + + let computed_public = my_private.compute_public_key().unwrap(); + assert_eq!(computed_public.as_ref(), &my_public[..]); + + assert_eq!(computed_public.algorithm(), alg); + + let result = agreement::agree_ephemeral(my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + + #[test] + fn test_agreement_ecdh_p521() { + let alg = &agreement::ECDH_P521; + let peer_public = agreement::UnparsedPublicKey::new( + alg, + test::from_dirty_hex( + "0401a32099b02c0bd85371f60b0dd20890e6c7af048c8179890fda308b359dbbc2b7a832bb8c6526c4af99a7ea3f0b3cb96ae1eb7684132795c478ad6f962e4a6f446d017627357b39e9d7632a1370b3e93c1afb5c851b910eb4ead0c9d387df67cde85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d1a46", + ), + ); + + let my_private = test::from_dirty_hex( + "00df14b1f1432a7b0fb053965fd8643afee26b2451ecb6a8a53a655d5fbe16e4c64ce8647225eb11e7fdcb23627471dffc5c2523bd2ae89957cba3a57a23933e5a78", + ); + + let my_private = { + let rng = test::rand::FixedSliceRandom { bytes: &my_private }; + agreement::EphemeralPrivateKey::generate_for_test(alg, &rng).unwrap() + }; + + let my_public = test::from_dirty_hex( + "04004e8583bbbb2ecd93f0714c332dff5ab3bc6396e62f3c560229664329baa5138c3bb1c36428abd4e23d17fcb7a2cfcc224b2e734c8941f6f121722d7b6b9415457601cf0874f204b0363f020864672fadbf87c8811eb147758b254b74b14fae742159f0f671a018212bbf25b8519e126d4cad778cfff50d288fd39ceb0cac635b175ec0", + ); + let output = test::from_dirty_hex( + "01aaf24e5d47e4080c18c55ea35581cd8da30f1a079565045d2008d51b12d0abb4411cda7a0785b15d149ed301a3697062f42da237aa7f07e0af3fd00eb1800d9c41", + ); + + assert_eq!(my_private.algorithm(), alg); + + let computed_public = my_private.compute_public_key().unwrap(); + assert_eq!(computed_public.as_ref(), &my_public[..]); + + assert_eq!(computed_public.algorithm(), alg); + + let result = agreement::agree_ephemeral(my_private, &peer_public, (), |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }); + assert_eq!(result, Ok(())); + } + + #[test] + fn agreement_traits() { + use crate::test; + + let rng = rand::SystemRandom::new(); + + let ephemeral_private_key = + agreement::EphemeralPrivateKey::generate_for_test(&agreement::ECDH_P256, &rng).unwrap(); + + test::compile_time_assert_send::(); + test::compile_time_assert_sync::(); + + assert_eq!( + format!("{:?}", &ephemeral_private_key), + "EphemeralPrivateKey { algorithm: Algorithm { curve: P256 } }" + ); + } + + #[test] + fn agreement_agree_ephemeral() { + let rng = rand::SystemRandom::new(); + + test::run( + test_file!("data/agreement_tests.txt"), + |section, test_case| { + assert_eq!(section, ""); + + let curve_name = test_case.consume_string("Curve"); + let alg = alg_from_curve_name(&curve_name); + let peer_public = + agreement::UnparsedPublicKey::new(alg, test_case.consume_bytes("PeerQ")); + + match test_case.consume_optional_string("Error") { + None => { + let my_private_bytes = test_case.consume_bytes("D"); + let my_private = { + let rng = test::rand::FixedSliceRandom { + bytes: &my_private_bytes, + }; + agreement::EphemeralPrivateKey::generate_for_test(alg, &rng)? + }; + let my_public = test_case.consume_bytes("MyQ"); + let output = test_case.consume_bytes("Output"); + + assert_eq!(my_private.algorithm(), alg); + + let computed_public = my_private.compute_public_key().unwrap(); + assert_eq!(computed_public.as_ref(), &my_public[..]); + + assert_eq!(my_private.algorithm(), alg); + + let result = agreement::agree_ephemeral( + my_private, + &peer_public, + (), + |key_material| { + assert_eq!(key_material, &output[..]); + Ok(()) + }, + ); + assert_eq!( + result, + Ok(()), + "Failed on private key: {:?}", + test::to_hex(my_private_bytes) + ); + } + + Some(_) => { + fn kdf_not_called(_: &[u8]) -> Result<(), ()> { + panic!( + "The KDF was called during ECDH when the peer's \ + public key is invalid." + ); + } + let dummy_private_key = + agreement::EphemeralPrivateKey::generate(alg, &rng)?; + assert!(agreement::agree_ephemeral( + dummy_private_key, + &peer_public, + (), + kdf_not_called + ) + .is_err()); + } + } + + Ok(()) + }, + ); + } + + fn h(s: &str) -> Vec { + match test::from_hex(s) { + Ok(v) => v, + Err(msg) => { + panic!("{msg} in {s}"); + } + } + } + + fn alg_from_curve_name(curve_name: &str) -> &'static agreement::Algorithm { + if curve_name == "P-256" { + &agreement::ECDH_P256 + } else if curve_name == "P-384" { + &agreement::ECDH_P384 + } else if curve_name == "P-521" { + &agreement::ECDH_P521 + } else if curve_name == "X25519" { + &agreement::X25519 + } else { + panic!("Unsupported curve: {curve_name}"); + } + } + + fn x25519(private_key: &[u8], public_key: &[u8]) -> Vec { + x25519_(private_key, public_key).unwrap() + } + + fn x25519_(private_key: &[u8], public_key: &[u8]) -> Result, Unspecified> { + let rng = test::rand::FixedSliceRandom { bytes: private_key }; + let private_key = + agreement::EphemeralPrivateKey::generate_for_test(&agreement::X25519, &rng)?; + let public_key = agreement::UnparsedPublicKey::new(&agreement::X25519, public_key); + agreement::agree_ephemeral(private_key, &public_key, Unspecified, |agreed_value| { + Ok(Vec::from(agreed_value)) + }) + } +} diff --git a/aws-lc-rs/src/ec.rs b/aws-lc-rs/src/ec.rs index 9ffaf9d389b..5d6ac84fb91 100644 --- a/aws-lc-rs/src/ec.rs +++ b/aws-lc-rs/src/ec.rs @@ -8,7 +8,6 @@ use std::fmt::{Debug, Formatter}; use std::mem::MaybeUninit; use std::ops::Deref; use std::os::raw::{c_int, c_uint}; -#[cfg(test)] use std::ptr::null; use std::ptr::null_mut; @@ -19,14 +18,12 @@ use untrusted::Input; use aws_lc::EC_KEY_check_fips; #[cfg(not(feature = "fips"))] use aws_lc::EC_KEY_check_key; -#[cfg(test)] -use aws_lc::EC_POINT_mul; use aws_lc::{ point_conversion_form_t, BN_bn2bin_padded, BN_num_bytes, ECDSA_SIG_from_bytes, ECDSA_SIG_get0_r, ECDSA_SIG_get0_s, ECDSA_SIG_new, ECDSA_SIG_set0, ECDSA_SIG_to_bytes, EC_GROUP_get_curve_name, EC_GROUP_new_by_curve_name, EC_KEY_get0_group, EC_KEY_get0_private_key, EC_KEY_get0_public_key, EC_KEY_new, EC_KEY_set_group, - EC_KEY_set_private_key, EC_KEY_set_public_key, EC_POINT_new, EC_POINT_oct2point, + EC_KEY_set_private_key, EC_KEY_set_public_key, EC_POINT_mul, EC_POINT_new, EC_POINT_oct2point, EC_POINT_point2oct, EVP_DigestVerify, EVP_DigestVerifyInit, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_assign_EC_KEY, EVP_PKEY_get0_EC_KEY, EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY_new, NID_X9_62_prime256v1, NID_secp256k1, @@ -321,6 +318,26 @@ pub(crate) unsafe fn marshal_private_key_to_buffer( Ok(buffer) } + +pub(crate) unsafe fn unmarshal_der_to_private_key( + key_bytes: &[u8], + nid: i32, +) -> Result, KeyRejected> { + let mut out = null_mut(); + let evp_pkey = LcPtr::new(aws_lc::d2i_PrivateKey( + EVP_PKEY_EC, + &mut out, + &mut key_bytes.as_ptr(), + key_bytes + .len() + .try_into() + .map_err(|_| KeyRejected::too_large())?, + ))?; + validate_evp_key(&evp_pkey.as_const(), nid)?; + + Ok(evp_pkey) +} + pub(crate) unsafe fn marshal_public_key_to_buffer( buffer: &mut [u8; PUBLIC_KEY_MAX_LEN], evp_pkey: &ConstPointer, @@ -383,7 +400,6 @@ pub(crate) unsafe fn evp_pkey_from_public_point( Ok(pkey) } -#[cfg(test)] pub(crate) unsafe fn evp_pkey_from_private( ec_group: &ConstPointer, private_big_num: &ConstPointer, @@ -448,17 +464,19 @@ pub(crate) fn evp_key_generate(nid: c_int) -> Result, Unspecifie } #[inline] -unsafe fn evp_key_from_public_private( +pub(crate) unsafe fn evp_key_from_public_private( ec_group: &LcPtr, - public_ec_point: &LcPtr, + public_ec_point: Option<&LcPtr>, private_bignum: &DetachableLcPtr, ) -> Result, KeyRejected> { let ec_key = DetachableLcPtr::new(EC_KEY_new())?; if 1 != EC_KEY_set_group(*ec_key, **ec_group) { return Err(KeyRejected::unexpected_error()); } - if 1 != EC_KEY_set_public_key(*ec_key, **public_ec_point) { - return Err(KeyRejected::unexpected_error()); + if let Some(ec_point) = public_ec_point { + if 1 != EC_KEY_set_public_key(*ec_key, **ec_point) { + return Err(KeyRejected::unexpected_error()); + } } if 1 != EC_KEY_set_private_key(*ec_key, **private_bignum) { return Err(KeyRejected::unexpected_error()); diff --git a/aws-lc-rs/src/ec/key_pair.rs b/aws-lc-rs/src/ec/key_pair.rs index 1642f5edc32..a11f7a31384 100644 --- a/aws-lc-rs/src/ec/key_pair.rs +++ b/aws-lc-rs/src/ec/key_pair.rs @@ -8,7 +8,7 @@ use std::fmt::{Debug, Formatter}; use std::mem::MaybeUninit; use std::ptr::{null, null_mut}; -use aws_lc::{EVP_DigestSign, EVP_DigestSignInit, EVP_PKEY_get0_EC_KEY, EVP_PKEY, EVP_PKEY_EC}; +use aws_lc::{EVP_DigestSign, EVP_DigestSignInit, EVP_PKEY_get0_EC_KEY, EVP_PKEY}; use crate::buffer::Buffer; use crate::digest::digest_ctx::DigestContext; @@ -54,7 +54,7 @@ impl KeyPair for EcdsaKeyPair { impl EcdsaKeyPair { #[allow(clippy::needless_pass_by_value)] - unsafe fn new( + fn new( algorithm: &'static EcdsaSigningAlgorithm, evp_pkey: LcPtr, ) -> Result { @@ -73,11 +73,9 @@ impl EcdsaKeyPair { /// `error::Unspecified` on internal error. /// pub fn generate(alg: &'static EcdsaSigningAlgorithm) -> Result { - unsafe { - let evp_pkey = evp_key_generate(alg.0.id.nid())?; + let evp_pkey = evp_key_generate(alg.0.id.nid())?; - Ok(Self::new(alg, evp_pkey)?) - } + Ok(Self::new(alg, evp_pkey)?) } /// Constructs an ECDSA key pair by parsing an unencrypted PKCS#8 v1 @@ -157,7 +155,7 @@ impl EcdsaKeyPair { .map_err(|_| KeyRejected::invalid_encoding())?; let private_bn = DetachableLcPtr::try_from(private_key)?; let evp_pkey = - ec::evp_key_from_public_private(&ec_group, &public_ec_point, &private_bn)?; + ec::evp_key_from_public_private(&ec_group, Some(&public_ec_point), &private_bn)?; let key_pair = Self::new(alg, evp_pkey)?; Ok(key_pair) @@ -180,27 +178,9 @@ impl EcdsaKeyPair { alg: &'static EcdsaSigningAlgorithm, private_key: &[u8], ) -> Result { - unsafe { - let mut out = std::ptr::null_mut(); - if aws_lc::d2i_PrivateKey( - EVP_PKEY_EC, - &mut out, - &mut private_key.as_ptr(), - private_key - .len() - .try_into() - .map_err(|_| KeyRejected::too_large())?, - ) - .is_null() - { - // FIXME: unclear which error or if we can get more detail - return Err(KeyRejected::unexpected_error()); - } - let evp_pkey = LcPtr::new(out)?; - validate_evp_key(&evp_pkey.as_const(), alg.id.nid())?; + let evp_pkey = unsafe { ec::unmarshal_der_to_private_key(private_key, alg.id.nid())? }; - Ok(Self::new(alg, evp_pkey)?) - } + Ok(Self::new(alg, evp_pkey)?) } /// Access functions related to the private key. diff --git a/aws-lc-rs/src/ed25519.rs b/aws-lc-rs/src/ed25519.rs index 27c39956613..707ea3c1cda 100644 --- a/aws-lc-rs/src/ed25519.rs +++ b/aws-lc-rs/src/ed25519.rs @@ -18,7 +18,7 @@ use aws_lc::{ EVP_PKEY_keygen_init, EVP_PKEY_new_raw_private_key, EVP_PKEY, EVP_PKEY_ED25519, }; -use crate::encoding::{AsBigEndian, Ed25519SeedBin}; +use crate::encoding::{AsBigEndian, Curve25519SeedBin}; use crate::error::{KeyRejected, Unspecified}; use crate::fips::indicator_check; use crate::pkcs8::{Document, Version}; @@ -105,16 +105,16 @@ impl Drop for Ed25519KeyPair { /// The seed value for the `EdDSA` signature scheme using Curve25519 pub struct Seed<'a>(&'a Ed25519KeyPair); -impl AsBigEndian for Seed<'_> { +impl AsBigEndian for Seed<'_> { /// Exposes the seed encoded as a big-endian fixed-length integer. /// /// For most use-cases, `EcdsaKeyPair::to_pkcs8()` should be preferred. /// /// # Errors /// `error::Unspecified` if serialization failed. - fn as_be_bytes(&self) -> Result { + fn as_be_bytes(&self) -> Result { let buffer = Vec::from(&self.0.private_key[..ED25519_PRIVATE_KEY_SEED_LEN]); - Ok(Ed25519SeedBin::new(buffer)) + Ok(Curve25519SeedBin::new(buffer)) } } diff --git a/aws-lc-rs/src/encoding.rs b/aws-lc-rs/src/encoding.rs index 4216a17967b..a640910b25e 100644 --- a/aws-lc-rs/src/encoding.rs +++ b/aws-lc-rs/src/encoding.rs @@ -5,7 +5,8 @@ use crate::buffer::Buffer; use crate::encoding::types::{ - EcPrivateKeyBinType, EcPrivateKeyRfc5915DerType, EcPublicKeyX509DerType, Ed25519SeedBufferType, + Curve25519SeedBufferType, EcPrivateKeyBinType, EcPrivateKeyRfc5915DerType, + EcPublicKeyX509DerType, }; mod types { @@ -21,7 +22,7 @@ mod types { _priv: (), } - pub struct Ed25519SeedBufferType { + pub struct Curve25519SeedBufferType { _priv: (), } } @@ -54,4 +55,4 @@ pub type EcPrivateKeyRfc5915Der = Buffer<'static, EcPrivateKeyRfc5915DerType>; pub type EcPublicKeyX509Der = Buffer<'static, EcPublicKeyX509DerType>; /// Elliptic curve private key data encoded as a big-endian fixed-length integer. -pub type Ed25519SeedBin = Buffer<'static, Ed25519SeedBufferType>; +pub type Curve25519SeedBin = Buffer<'static, Curve25519SeedBufferType>; diff --git a/aws-lc-rs/tests/ed25519_tests.rs b/aws-lc-rs/tests/ed25519_tests.rs index 5f349f4a459..0dcda20ac42 100644 --- a/aws-lc-rs/tests/ed25519_tests.rs +++ b/aws-lc-rs/tests/ed25519_tests.rs @@ -3,7 +3,7 @@ // Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC -use aws_lc_rs::encoding::{AsBigEndian, Ed25519SeedBin}; +use aws_lc_rs::encoding::{AsBigEndian, Curve25519SeedBin}; use aws_lc_rs::rand::SystemRandom; use aws_lc_rs::{ error, @@ -223,7 +223,7 @@ fn test_seed() { let key_pair = Ed25519KeyPair::from_pkcs8(key_pair_doc.as_ref()).unwrap(); let seed = key_pair.seed().unwrap(); - let seed_buffer: Ed25519SeedBin = seed.as_be_bytes().unwrap(); + let seed_buffer: Curve25519SeedBin = seed.as_be_bytes().unwrap(); let pub_key = key_pair.public_key();