diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2024-06-18 17:04:54 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2024-06-18 17:04:54 +0200 |
commit | 454dfe881879f7f78c9bf46d8bb6e8d853271618 (patch) | |
tree | 74f39153d12360c9bbb115eb1427fb23cb759ac7 /openpgp/src | |
parent | 2ca2c8811f74dd40bd4857a2abb7e81099b949dd (diff) |
openpgp: Consolidate ECDH over Cv25519 encryption.
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/crypto/backend/botan/ecdh.rs | 17 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/cng/ecdh.rs | 29 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/nettle/ecdh.rs | 23 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/openssl/ecdh.rs | 14 | ||||
-rw-r--r-- | openpgp/src/crypto/backend/rust/ecdh.rs | 29 | ||||
-rw-r--r-- | openpgp/src/packet/key.rs | 25 |
6 files changed, 34 insertions, 103 deletions
diff --git a/openpgp/src/crypto/backend/botan/ecdh.rs b/openpgp/src/crypto/backend/botan/ecdh.rs index 41591421..423f3718 100644 --- a/openpgp/src/crypto/backend/botan/ecdh.rs +++ b/openpgp/src/crypto/backend/botan/ecdh.rs @@ -31,21 +31,8 @@ pub fn encrypt<R>(recipient: &Key<key::PublicParts, R>, ref curve, ref q,.. } = recipient.mpis() { match curve { - Curve::Cv25519 => { - // Obtain the recipient public key R - let R = &q.decode_point(curve)?.0; - - // Generate an ephemeral key pair {v, V=vG} - let v = Privkey::create("Curve25519", "", &mut rng)?; - let V = v.pubkey()?.get_x25519_key()?; - - // Compute the shared point S = vR; - let S: Protected = v.agree(&R, 32, b"", "Raw")?.into(); - - encrypt_wrap(recipient, session_key, - MPI::new_compressed_point(&V), - &S) - }, + Curve::Cv25519 => + Err(Error::InvalidArgument("implemented elsewhere".into()).into()), // N/A Curve::Unknown(_) if ! curve.is_brainpoolp384() => diff --git a/openpgp/src/crypto/backend/cng/ecdh.rs b/openpgp/src/crypto/backend/cng/ecdh.rs index afa688d1..ab234d19 100644 --- a/openpgp/src/crypto/backend/cng/ecdh.rs +++ b/openpgp/src/crypto/backend/cng/ecdh.rs @@ -32,34 +32,9 @@ where }; match curve { - Curve::Cv25519 => { - // Obtain the authenticated recipient public key R - let R = q.decode_point(curve)?.0; - let provider = AsymmetricAlgorithm::open(AsymmetricAlgorithmId::Ecdh(NamedCurve::Curve25519))?; - let recipient_key = AsymmetricKey::<Ecdh<Curve25519>, Public>::import_from_parts( - &provider, - R, - )?; - - // Generate an ephemeral key pair {v, V=vG} - let ephemeral = AsymmetricKey::builder(Ecdh(Curve25519)).build().unwrap(); + Curve::Cv25519 => return + Err(Error::InvalidArgument("implemented elsewhere".into()).into()), - // Compute the public key. We need to add an encoding - // octet in front of the key. - let blob = ephemeral.export().unwrap(); - let mut VB = [0; 33]; - VB[0] = 0x40; - VB[1..].copy_from_slice(blob.x()); - let VB = MPI::new(&VB); - - // Compute the shared point S = vR; - let secret = cng::asymmetric::agreement::secret_agreement(&ephemeral, &recipient_key)?; - let mut S = Protected::from(secret.derive_raw()?); - // Returned secret is little-endian, flip it to big-endian - S.reverse(); - - encrypt_wrap(recipient, session_key, VB, &S) - } Curve::NistP256 | Curve::NistP384 | Curve::NistP521 => { let (Rx, Ry) = q.decode_point(curve)?; diff --git a/openpgp/src/crypto/backend/nettle/ecdh.rs b/openpgp/src/crypto/backend/nettle/ecdh.rs index 69cf4752..607e304b 100644 --- a/openpgp/src/crypto/backend/nettle/ecdh.rs +++ b/openpgp/src/crypto/backend/nettle/ecdh.rs @@ -23,28 +23,9 @@ pub fn encrypt<R>(recipient: &Key<key::PublicParts, R>, ref curve, ref q,.. } = recipient.mpis() { match curve { - Curve::Cv25519 => { - // Obtain the authenticated recipient public key R - let R = q.decode_point(curve)?.0; + Curve::Cv25519 => + Err(Error::InvalidArgument("implemented elsewhere".into()).into()), - // Generate an ephemeral key pair {v, V=vG} - let v: Protected = - curve25519::private_key(&mut rng).into(); - - // Compute the public key. - let mut VB = [0; curve25519::CURVE25519_SIZE]; - curve25519::mul_g(&mut VB, &v) - .expect("buffers are of the wrong size"); - let VB = MPI::new_compressed_point(&VB); - - // Compute the shared point S = vR; - let mut S: Protected = - vec![0; curve25519::CURVE25519_SIZE].into(); - curve25519::mul(&mut S, &v, R) - .expect("buffers are of the wrong size"); - - encrypt_wrap(recipient, session_key, VB, &S) - } Curve::NistP256 | Curve::NistP384 | Curve::NistP521 => { // Obtain the authenticated recipient public key R and // generate an ephemeral private key v. diff --git a/openpgp/src/crypto/backend/openssl/ecdh.rs b/openpgp/src/crypto/backend/openssl/ecdh.rs index 04a87c23..f8c8ba98 100644 --- a/openpgp/src/crypto/backend/openssl/ecdh.rs +++ b/openpgp/src/crypto/backend/openssl/ecdh.rs @@ -27,19 +27,7 @@ where _ => return Err(Error::InvalidArgument("Expected an ECDHPublicKey".into()).into()), }; if curve == &Curve::Cv25519 { - let public = q.decode_point(curve)?.0; - - let public_key = PKey::public_key_from_raw_bytes(public, openssl::pkey::Id::X25519)?; - - let key = PKey::generate_x25519()?; - let mut deriver = Deriver::new(&key)?; - deriver.set_peer(&public_key)?; - - let secret = deriver.derive_to_vec()?.into(); - - let q = mpi::MPI::new_compressed_point(&key.raw_public_key()?); - - return encrypt_wrap(recipient, session_key, q, &secret); + return Err(Error::InvalidArgument("implemented elsewhere".into()).into()); } let nid = curve.try_into()?; diff --git a/openpgp/src/crypto/backend/rust/ecdh.rs b/openpgp/src/crypto/backend/rust/ecdh.rs index 77fd7d23..047b4e5b 100644 --- a/openpgp/src/crypto/backend/rust/ecdh.rs +++ b/openpgp/src/crypto/backend/rust/ecdh.rs @@ -32,34 +32,9 @@ pub fn encrypt<R>(recipient: &Key<key::PublicParts, R>, }; let (VB, shared) = match curve { - Curve::Cv25519 => { - // x25519_dalek v1.1 doesn't reexport OsRng. It - // depends on rand 0.8. - use rand::rngs::OsRng; - use x25519_dalek::{EphemeralSecret, PublicKey}; - - // Decode the recipient's public key. - let R: [u8; CURVE25519_SIZE] = q.decode_point(curve)?.0.try_into()?; - let recipient_key = PublicKey::from(R); - - // Generate a keypair and perform Diffie-Hellman. - let secret = EphemeralSecret::random_from_rng(OsRng); - let public = PublicKey::from(&secret); - let shared = secret.diffie_hellman(&recipient_key); + Curve::Cv25519 => return + Err(Error::InvalidArgument("implemented elsewhere".into()).into()), - // Encode our public key. We need to add an encoding - // octet in front of the key. - let mut VB = [0; 1 + CURVE25519_SIZE]; - VB[0] = 0x40; - VB[1..].copy_from_slice(public.as_bytes()); - let VB = MPI::new(&VB); - - // Encode the shared secret. - let shared: &[u8] = shared.as_bytes(); - let shared = Protected::from(shared); - - (VB, shared) - }, Curve::NistP256 => { use p256::{EncodedPoint, PublicKey, ecdh::EphemeralSecret}; diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs index a6d7c660..765580f7 100644 --- a/openpgp/src/packet/key.rs +++ b/openpgp/src/packet/key.rs @@ -742,6 +742,8 @@ impl<P, R> Key<P, R> { /// Encrypts the given data with this key. pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> { + use crate::crypto::backend::{Backend, interface::Asymmetric}; + use crate::crypto::mpi::PublicKey; use PublicKeyAlgorithm::*; #[allow(deprecated, non_snake_case)] @@ -751,6 +753,29 @@ impl<P, R> Key<P, R> format!("{} is not an encryption algorithm", self.pk_algo()) ).into()), + ECDH if matches!(self.mpis(), + PublicKey::ECDH { curve: Curve::Cv25519, ..}) => + { + let q = match self.mpis() { + PublicKey::ECDH { q, .. } => q, + _ => unreachable!(), + }; + + // Obtain the authenticated recipient public key R + let R = q.decode_point(&Curve::Cv25519)?.0; + + // Generate an ephemeral key pair {v, V=vG} + // Compute the public key. + let (v, VB) = Backend::x25519_generate_key()?; + let VB = mpi::MPI::new_compressed_point(&VB); + + // Compute the shared point S = vR; + let S = Backend::x25519_shared_point(&v, R.try_into()?)?; + + crate::crypto::ecdh::encrypt_wrap( + self.parts_as_public(), data, VB, &S) + }, + RSAEncryptSign | RSAEncrypt | ElGamalEncrypt | ElGamalEncryptSign | ECDH | |