summaryrefslogtreecommitdiffstats
path: root/openpgp/src
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2024-06-18 17:04:54 +0200
committerJustus Winter <justus@sequoia-pgp.org>2024-06-18 17:04:54 +0200
commit454dfe881879f7f78c9bf46d8bb6e8d853271618 (patch)
tree74f39153d12360c9bbb115eb1427fb23cb759ac7 /openpgp/src
parent2ca2c8811f74dd40bd4857a2abb7e81099b949dd (diff)
openpgp: Consolidate ECDH over Cv25519 encryption.
Diffstat (limited to 'openpgp/src')
-rw-r--r--openpgp/src/crypto/backend/botan/ecdh.rs17
-rw-r--r--openpgp/src/crypto/backend/cng/ecdh.rs29
-rw-r--r--openpgp/src/crypto/backend/nettle/ecdh.rs23
-rw-r--r--openpgp/src/crypto/backend/openssl/ecdh.rs14
-rw-r--r--openpgp/src/crypto/backend/rust/ecdh.rs29
-rw-r--r--openpgp/src/packet/key.rs25
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 |