diff options
Diffstat (limited to 'openpgp/src/crypto/backend/rust/asymmetric.rs')
-rw-r--r-- | openpgp/src/crypto/backend/rust/asymmetric.rs | 93 |
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()), } } |