diff options
Diffstat (limited to 'ext/node/ops/crypto/keys.rs')
-rw-r--r-- | ext/node/ops/crypto/keys.rs | 156 |
1 files changed, 123 insertions, 33 deletions
diff --git a/ext/node/ops/crypto/keys.rs b/ext/node/ops/crypto/keys.rs index 86280c11a..5f634b35f 100644 --- a/ext/node/ops/crypto/keys.rs +++ b/ext/node/ops/crypto/keys.rs @@ -30,6 +30,7 @@ use rsa::pkcs1::EncodeRsaPublicKey; use rsa::traits::PublicKeyParts; use rsa::RsaPrivateKey; use rsa::RsaPublicKey; +use sec1::der::Tag; use sec1::der::Writer as _; use sec1::pem::PemLabel as _; use sec1::DecodeEcPrivateKey as _; @@ -46,7 +47,10 @@ use spki::EncodePublicKey as _; use spki::SubjectPublicKeyInfoRef; use super::dh; +use super::dh::DiffieHellmanGroup; use super::digest::match_fixed_digest_with_oid; +use super::pkcs3; +use super::pkcs3::DhParameter; use super::primes::Prime; #[derive(Clone)] @@ -66,8 +70,7 @@ pub enum AsymmetricPrivateKey { Ec(EcPrivateKey), X25519(x25519_dalek::StaticSecret), Ed25519(ed25519_dalek::SigningKey), - #[allow(unused)] - Dh(dh::PrivateKey), + Dh(DhPrivateKey), } #[derive(Clone)] @@ -126,16 +129,20 @@ pub enum EcPrivateKey { } #[derive(Clone)] +pub struct DhPrivateKey { + pub key: dh::PrivateKey, + pub params: DhParameter, +} + +#[derive(Clone)] pub enum AsymmetricPublicKey { Rsa(rsa::RsaPublicKey), RsaPss(RsaPssPublicKey), Dsa(dsa::VerifyingKey), Ec(EcPublicKey), - #[allow(unused)] X25519(x25519_dalek::PublicKey), Ed25519(ed25519_dalek::VerifyingKey), - #[allow(unused)] - Dh(dh::PublicKey), + Dh(DhPublicKey), } #[derive(Clone)] @@ -151,6 +158,12 @@ pub enum EcPublicKey { P384(p384::PublicKey), } +#[derive(Clone)] +pub struct DhPublicKey { + pub key: dh::PublicKey, + pub params: DhParameter, +} + impl KeyObjectHandle { /// Returns the private key if the handle is an asymmetric private key. pub fn as_private_key(&self) -> Option<&AsymmetricPrivateKey> { @@ -492,9 +505,18 @@ impl KeyObjectHandle { bytes.copy_from_slice(string_ref.as_bytes()); AsymmetricPrivateKey::Ed25519(ed25519_dalek::SigningKey::from(bytes)) } - DH_KEY_AGREEMENT_OID => AsymmetricPrivateKey::Dh( - dh::PrivateKey::from_bytes(pk_info.private_key), - ), + DH_KEY_AGREEMENT_OID => { + let params = pk_info + .algorithm + .parameters + .ok_or_else(|| type_error("missing dh parameters"))?; + let params = pkcs3::DhParameter::from_der(¶ms.to_der().unwrap()) + .map_err(|_| type_error("malformed dh parameters"))?; + AsymmetricPrivateKey::Dh(DhPrivateKey { + key: dh::PrivateKey::from_bytes(pk_info.private_key), + params, + }) + } _ => return Err(type_error("unsupported private key oid")), }; @@ -634,11 +656,20 @@ impl KeyObjectHandle { AsymmetricPublicKey::Ed25519(verifying_key) } DH_KEY_AGREEMENT_OID => { + let params = spki + .algorithm + .parameters + .ok_or_else(|| type_error("missing dh parameters"))?; + let params = pkcs3::DhParameter::from_der(¶ms.to_der().unwrap()) + .map_err(|_| type_error("malformed dh parameters"))?; let Some(subject_public_key) = spki.subject_public_key.as_bytes() else { return Err(type_error("malformed or missing public key in dh spki")); }; - AsymmetricPublicKey::Dh(dh::PublicKey::from_bytes(subject_public_key)) + AsymmetricPublicKey::Dh(DhPublicKey { + key: dh::PublicKey::from_bytes(subject_public_key), + params, + }) } _ => return Err(type_error("unsupported public key oid")), }; @@ -788,16 +819,18 @@ impl AsymmetricPublicKey { .into_boxed_slice() } AsymmetricPublicKey::Dh(key) => { - let public_key_bytes = key.clone().into_vec(); - let spki = - SubjectPublicKeyInfoRef { - algorithm: rsa::pkcs8::AlgorithmIdentifierRef { - oid: DH_KEY_AGREEMENT_OID, - parameters: None, - }, - subject_public_key: BitStringRef::from_bytes(&public_key_bytes) - .map_err(|_| type_error("invalid DH public key"))?, - }; + let public_key_bytes = key.key.clone().into_vec(); + let params = key.params.to_der().unwrap(); + let spki = SubjectPublicKeyInfoRef { + algorithm: rsa::pkcs8::AlgorithmIdentifierRef { + oid: DH_KEY_AGREEMENT_OID, + parameters: Some(AnyRef::new(Tag::Sequence, ¶ms).unwrap()), + }, + subject_public_key: BitStringRef::from_bytes(&public_key_bytes) + .map_err(|_| { + type_error("invalid DH public key") + })?, + }; spki .to_der() .map_err(|_| type_error("invalid DH public key"))? @@ -917,11 +950,12 @@ impl AsymmetricPrivateKey { .into_boxed_slice() } AsymmetricPrivateKey::Dh(key) => { - let private_key = key.clone().into_vec(); + let private_key = key.key.clone().into_vec(); + let params = key.params.to_der().unwrap(); let private_key = PrivateKeyInfo { algorithm: rsa::pkcs8::AlgorithmIdentifierRef { oid: DH_KEY_AGREEMENT_OID, - parameters: None, + parameters: Some(AnyRef::new(Tag::Sequence, ¶ms).unwrap()), }, private_key: &private_key, public_key: None, @@ -1514,21 +1548,66 @@ pub async fn op_node_generate_ed25519_key_async() -> KeyObjectHandlePair { spawn_blocking(ed25519_generate).await.unwrap() } +fn u32_slice_to_u8_slice(slice: &[u32]) -> &[u8] { + // SAFETY: just reinterpreting the slice as u8 + unsafe { + std::slice::from_raw_parts( + slice.as_ptr() as *const u8, + std::mem::size_of_val(slice), + ) + } +} + fn dh_group_generate( group_name: &str, ) -> Result<KeyObjectHandlePair, AnyError> { - let dh = match group_name { - "modp5" => dh::DiffieHellman::group::<dh::Modp1536>(), - "modp14" => dh::DiffieHellman::group::<dh::Modp2048>(), - "modp15" => dh::DiffieHellman::group::<dh::Modp3072>(), - "modp16" => dh::DiffieHellman::group::<dh::Modp4096>(), - "modp17" => dh::DiffieHellman::group::<dh::Modp6144>(), - "modp18" => dh::DiffieHellman::group::<dh::Modp8192>(), + let (dh, prime, generator) = match group_name { + "modp5" => ( + dh::DiffieHellman::group::<dh::Modp1536>(), + dh::Modp1536::MODULUS, + dh::Modp1536::GENERATOR, + ), + "modp14" => ( + dh::DiffieHellman::group::<dh::Modp2048>(), + dh::Modp2048::MODULUS, + dh::Modp2048::GENERATOR, + ), + "modp15" => ( + dh::DiffieHellman::group::<dh::Modp3072>(), + dh::Modp3072::MODULUS, + dh::Modp3072::GENERATOR, + ), + "modp16" => ( + dh::DiffieHellman::group::<dh::Modp4096>(), + dh::Modp4096::MODULUS, + dh::Modp4096::GENERATOR, + ), + "modp17" => ( + dh::DiffieHellman::group::<dh::Modp6144>(), + dh::Modp6144::MODULUS, + dh::Modp6144::GENERATOR, + ), + "modp18" => ( + dh::DiffieHellman::group::<dh::Modp8192>(), + dh::Modp8192::MODULUS, + dh::Modp8192::GENERATOR, + ), _ => return Err(type_error("Unsupported group name")), }; + let params = DhParameter { + prime: asn1::Int::new(u32_slice_to_u8_slice(prime)).unwrap(), + base: asn1::Int::new(generator.to_be_bytes().as_slice()).unwrap(), + private_value_length: None, + }; Ok(KeyObjectHandlePair::new( - AsymmetricPrivateKey::Dh(dh.private_key), - AsymmetricPublicKey::Dh(dh.public_key), + AsymmetricPrivateKey::Dh(DhPrivateKey { + key: dh.private_key, + params: params.clone(), + }), + AsymmetricPublicKey::Dh(DhPublicKey { + key: dh.public_key, + params, + }), )) } @@ -1558,10 +1637,21 @@ fn dh_generate( let prime = prime .map(|p| p.into()) .unwrap_or_else(|| Prime::generate(prime_len)); - let dh = dh::DiffieHellman::new(prime, generator); + let dh = dh::DiffieHellman::new(prime.clone(), generator); + let params = DhParameter { + prime: asn1::Int::new(&prime.0.to_bytes_be()).unwrap(), + base: asn1::Int::new(generator.to_be_bytes().as_slice()).unwrap(), + private_value_length: None, + }; Ok(KeyObjectHandlePair::new( - AsymmetricPrivateKey::Dh(dh.private_key), - AsymmetricPublicKey::Dh(dh.public_key), + AsymmetricPrivateKey::Dh(DhPrivateKey { + key: dh.private_key, + params: params.clone(), + }), + AsymmetricPublicKey::Dh(DhPublicKey { + key: dh.public_key, + params, + }), )) } |