summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-07-04 17:34:28 +0200
committerJustus Winter <justus@sequoia-pgp.org>2019-07-04 17:34:28 +0200
commitb84543d448b00ac357a4b8f951659c49d12d2bfd (patch)
tree9e15511332171150ca215f533ec33471aaeac37b
parentd887f79b62c86cf7a29ecc206c5755ff56879713 (diff)
openpgp: Fix ECDH over the NIST curves.
- To derive the wrapping key, the X coordinate must be zero-padded to the size of the underlying field rounded to the next byte.
-rw-r--r--openpgp/src/crypto/ecdh.rs34
1 files changed, 27 insertions, 7 deletions
diff --git a/openpgp/src/crypto/ecdh.rs b/openpgp/src/crypto/ecdh.rs
index d8ba73f3..23ec9026 100644
--- a/openpgp/src/crypto/ecdh.rs
+++ b/openpgp/src/crypto/ecdh.rs
@@ -93,9 +93,19 @@ pub fn encrypt(recipient: &Key, session_key: &SessionKey) -> Result<Ciphertext>
// Compute the shared point S = vR;
let S = ecdh::point_mul(&v, &R)?;
- let Sx: Protected = S.as_bytes().0.into();
- encrypt_shared(recipient, session_key, VB, &Sx)
+ // Get the X coordinate, safely dispose of Y.
+ let (Sx, Sy) = S.as_bytes();
+ Protected::from(Sy); // Just a precaution.
+
+ // Zero-pad to the size of the underlying field,
+ // rounded to the next byte.
+ let mut Sx = Vec::from(Sx);
+ while Sx.len() < (field_sz + 7) / 8 {
+ Sx.insert(0, 0);
+ }
+
+ encrypt_shared(recipient, session_key, VB, &Sx.into())
}
// Not implemented in Nettle
@@ -208,14 +218,14 @@ pub fn decrypt(recipient: &Key, recipient_sec: &SecretKey,
// compute the shared point S = rV = rvG, where (r, R)
// is the recipient's key pair.
let (Vx, Vy) = e.decode_point(curve)?;
- let (V, r) = match curve {
+ let (V, r, field_sz) = match curve {
Curve::NistP256 => {
let V =
ecc::Point::new::<ecc::Secp256r1>(&Vx, &Vy)?;
let r =
ecc::Scalar::new::<ecc::Secp256r1>(scalar.value())?;
- (V, r)
+ (V, r, 256)
}
Curve::NistP384 => {
let V =
@@ -223,7 +233,7 @@ pub fn decrypt(recipient: &Key, recipient_sec: &SecretKey,
let r =
ecc::Scalar::new::<ecc::Secp384r1>(scalar.value())?;
- (V, r)
+ (V, r, 384)
}
Curve::NistP521 => {
let V =
@@ -231,12 +241,22 @@ pub fn decrypt(recipient: &Key, recipient_sec: &SecretKey,
let r =
ecc::Scalar::new::<ecc::Secp521r1>(scalar.value())?;
- (V, r)
+ (V, r, 521)
}
_ => unreachable!(),
};
let S = ecdh::point_mul(&r, &V)?;
- let (Sx, _) = S.as_bytes();
+
+ // Get the X coordinate, safely dispose of Y.
+ let (Sx, Sy) = S.as_bytes();
+ Protected::from(Sy); // Just a precaution.
+
+ // Zero-pad to the size of the underlying field,
+ // rounded to the next byte.
+ let mut Sx = Vec::from(Sx);
+ while Sx.len() < (field_sz + 7) / 8 {
+ Sx.insert(0, 0);
+ }
Sx.into()
}