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.rs93
1 files changed, 90 insertions, 3 deletions
diff --git a/openpgp/src/crypto/backend/rust/asymmetric.rs b/openpgp/src/crypto/backend/rust/asymmetric.rs
index d8adf44f..a5a434f8 100644
--- a/openpgp/src/crypto/backend/rust/asymmetric.rs
+++ b/openpgp/src/crypto/backend/rust/asymmetric.rs
@@ -67,10 +67,8 @@ impl Asymmetric for super::Backend {
fn supports_curve(curve: &Curve) -> bool {
use self::Curve::*;
match curve {
- NistP256 | NistP384
+ NistP256 | NistP384 | NistP521
=> true,
- NistP521
- => false,
Ed25519 | Cv25519
=> true,
BrainpoolP256 | BrainpoolP512 | Unknown(_)
@@ -323,6 +321,31 @@ impl KeyPair {
})
},
+ Curve::NistP521 => {
+ use p521::Scalar;
+ const LEN: usize = 66;
+
+ 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()),
},
@@ -504,6 +527,30 @@ impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
key.verify_prehashed(&dig, &sig).map_err(bad)
},
+ Curve::NistP521 => {
+ use p521::{AffinePoint, ecdsa::Signature};
+ const LEN: usize = 66;
+
+ let key = AffinePoint::from_encoded_point(
+ &EncodedPoint::<p521::NistP521>::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!(
@@ -688,6 +735,46 @@ impl<R> Key4<SecretParts, R>
Ok((PublicKeyAlgorithm::ECDH, public_mpis, private_mpis))
},
+ (Curve::NistP521, true) => {
+ use p521::{EncodedPoint, SecretKey};
+
+ let secret = SecretKey::random(
+ &mut p521::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::NistP521, false) => {
+ use p521::{EncodedPoint, SecretKey};
+
+ let secret = SecretKey::random(
+ &mut p521::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()),
}
}