summaryrefslogtreecommitdiffstats
path: root/openpgp/src/crypto/backend/rust/asymmetric.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/crypto/backend/rust/asymmetric.rs')
-rw-r--r--openpgp/src/crypto/backend/rust/asymmetric.rs95
1 files changed, 93 insertions, 2 deletions
diff --git a/openpgp/src/crypto/backend/rust/asymmetric.rs b/openpgp/src/crypto/backend/rust/asymmetric.rs
index a07a760c..d8adf44f 100644
--- a/openpgp/src/crypto/backend/rust/asymmetric.rs
+++ b/openpgp/src/crypto/backend/rust/asymmetric.rs
@@ -67,9 +67,9 @@ impl Asymmetric for super::Backend {
fn supports_curve(curve: &Curve) -> bool {
use self::Curve::*;
match curve {
- NistP256
+ NistP256 | NistP384
=> true,
- NistP384 | NistP521
+ NistP521
=> false,
Ed25519 | Cv25519
=> true,
@@ -297,6 +297,32 @@ impl KeyPair {
s: MPI::new(&sig.s().to_bytes()),
})
},
+
+ Curve::NistP384 => {
+ use p384::Scalar;
+ const LEN: usize = 48;
+
+ let key = scalar.value_padded(LEN);
+ let key = Scalar::reduce_bytes(GA::try_from_slice(&key)?);
+ let dig = pad_truncating(digest, LEN);
+ let dig = GA::try_from_slice(&dig)?;
+
+ let sig = loop {
+ let mut k: Protected = vec![0; LEN].into();
+ crate::crypto::random(&mut k);
+ let k = Scalar::reduce_bytes(
+ GA::try_from_slice(&k)?);
+ if let Ok(s) = key.try_sign_prehashed(k, &dig) {
+ break s.0;
+ }
+ };
+
+ Ok(mpi::Signature::ECDSA {
+ r: MPI::new(&sig.r().to_bytes()),
+ s: MPI::new(&sig.s().to_bytes()),
+ })
+ },
+
_ => Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
},
@@ -453,6 +479,31 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
let dig = GA::try_from_slice(&dig)?;
key.verify_prehashed(&dig, &sig).map_err(bad)
},
+
+ Curve::NistP384 => {
+ use p384::{AffinePoint, ecdsa::Signature};
+ const LEN: usize = 48;
+
+ let key = AffinePoint::from_encoded_point(
+ &EncodedPoint::<p384::NistP384>::from_bytes(q.value())?);
+ let key = if key.is_some().into() {
+ key.unwrap()
+ } else {
+ return Err(Error::InvalidKey(
+ "Point is not on the curve".into()).into());
+ };
+
+ let sig = Signature::from_scalars(
+ GA::try_clone_from_slice(
+ &r.value_padded(LEN).map_err(bad)?)?,
+ GA::try_clone_from_slice(
+ &s.value_padded(LEN).map_err(bad)?)?)
+ .map_err(bad)?;
+ let dig = pad_truncating(digest, LEN);
+ let dig = GA::try_from_slice(&dig)?;
+ key.verify_prehashed(&dig, &sig).map_err(bad)
+ },
+
_ => Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
},
_ => Err(Error::MalformedPacket(format!(
@@ -597,6 +648,46 @@ impl<R> Key4<SecretParts, R>
Ok((PublicKeyAlgorithm::ECDH, public_mpis, private_mpis))
},
+ (Curve::NistP384, true) => {
+ use p384::{EncodedPoint, SecretKey};
+
+ let secret = SecretKey::random(
+ &mut p384::elliptic_curve::rand_core::OsRng);
+ let public = EncodedPoint::from(secret.public_key());
+
+ let public_mpis = mpi::PublicKey::ECDSA {
+ curve,
+ q: MPI::new(public.as_bytes()),
+ };
+ let private_mpis = mpi::SecretKeyMaterial::ECDSA {
+ scalar: Vec::from(secret.to_bytes().as_slice()).into(),
+ };
+
+ Ok((PublicKeyAlgorithm::ECDSA, public_mpis, private_mpis))
+ },
+
+ (Curve::NistP384, false) => {
+ use p384::{EncodedPoint, SecretKey};
+
+ let secret = SecretKey::random(
+ &mut p384::elliptic_curve::rand_core::OsRng);
+ let public = EncodedPoint::from(secret.public_key());
+
+ let public_mpis = mpi::PublicKey::ECDH {
+ q: MPI::new(public.as_bytes()),
+ hash:
+ crate::crypto::ecdh::default_ecdh_kdf_hash(&curve),
+ sym:
+ crate::crypto::ecdh::default_ecdh_kek_cipher(&curve),
+ curve,
+ };
+ let private_mpis = mpi::SecretKeyMaterial::ECDH {
+ scalar: Vec::from(secret.to_bytes().as_slice()).into(),
+ };
+
+ Ok((PublicKeyAlgorithm::ECDH, public_mpis, private_mpis))
+ },
+
_ => Err(Error::UnsupportedEllipticCurve(curve).into()),
}
}