diff options
Diffstat (limited to 'openpgp/src/crypto/sexp.rs')
-rw-r--r-- | openpgp/src/crypto/sexp.rs | 141 |
1 files changed, 75 insertions, 66 deletions
diff --git a/openpgp/src/crypto/sexp.rs b/openpgp/src/crypto/sexp.rs index a7da7f0c..17805234 100644 --- a/openpgp/src/crypto/sexp.rs +++ b/openpgp/src/crypto/sexp.rs @@ -6,11 +6,14 @@ //! //! [S-Expressions]: https://people.csail.mit.edu/rivest/Sexp.txt +use std::convert::TryFrom; use std::fmt; use std::ops::Deref; + +#[cfg(any(test, feature = "quickcheck"))] use quickcheck::{Arbitrary, Gen}; -use crate::crypto::{self, mpis, SessionKey}; +use crate::crypto::{self, mpi, SessionKey}; use crate::crypto::mem::Protected; use crate::Error; @@ -37,55 +40,6 @@ impl fmt::Debug for Sexp { } impl Sexp { - /// Constructs an S-Expression representing `ciphertext`. - /// - /// The resulting expression is suitable for gpg-agent's `INQUIRE - /// CIPHERTEXT` inquiry. - pub fn from_ciphertext(ciphertext: &mpis::Ciphertext) -> Result<Self> { - use crate::crypto::mpis::Ciphertext::*; - match ciphertext { - RSA { ref c } => - Ok(Sexp::List(vec![ - Sexp::String("enc-val".into()), - Sexp::List(vec![ - Sexp::String("rsa".into()), - Sexp::List(vec![ - Sexp::String("a".into()), - Sexp::String(c.value().into())])])])), - - &ElGamal { ref e, ref c } => - Ok(Sexp::List(vec![ - Sexp::String("enc-val".into()), - Sexp::List(vec![ - Sexp::String("elg".into()), - Sexp::List(vec![ - Sexp::String("a".into()), - Sexp::String(e.value().into())]), - Sexp::List(vec![ - Sexp::String("b".into()), - Sexp::String(c.value().into())])])])), - - &ECDH { ref e, ref key } => - Ok(Sexp::List(vec![ - Sexp::String("enc-val".into()), - Sexp::List(vec![ - Sexp::String("ecdh".into()), - Sexp::List(vec![ - Sexp::String("s".into()), - Sexp::String(key.as_ref().into())]), - Sexp::List(vec![ - Sexp::String("e".into()), - Sexp::String(e.value().into())])])])), - - &Unknown { .. } => - Err(Error::InvalidArgument( - format!("Don't know how to convert {:?}", ciphertext)) - .into()), - - __Nonexhaustive => unreachable!(), - } - } - /// Completes the decryption of this S-Expression representing a /// wrapped session key. /// @@ -95,12 +49,12 @@ impl Sexp { pub fn finish_decryption<R>(&self, recipient: &crate::packet::Key< crate::packet::key::PublicParts, R>, - ciphertext: &mpis::Ciphertext, + ciphertext: &mpi::Ciphertext, padding: bool) -> Result<SessionKey> where R: crate::packet::key::KeyRole { - use crate::crypto::mpis::PublicKey; + use crate::crypto::mpi::PublicKey; let not_a_session_key = || -> anyhow::Error { Error::MalformedMPI( format!("Not a session key: {:?}", self)).into() @@ -167,7 +121,7 @@ impl Sexp { PublicKey::ECDH { curve, .. } => { // The shared point has been computed by the // remote agent. The shared point is not padded. - let mut s = mpis::MPI::new(s); + let mut s = mpi::MPI::new(s); #[allow(non_snake_case)] let S: Protected = s.decode_point(curve)?.0.into(); s.secure_memzero(); @@ -189,7 +143,7 @@ impl Sexp { /// /// Such an expression is returned from gpg-agent's `PKSIGN` /// command. - pub fn to_signature(&self) -> Result<mpis::Signature> { + pub fn to_signature(&self) -> Result<mpi::Signature> { let not_a_signature = || -> anyhow::Error { Error::MalformedMPI( format!("Not a signature: {:?}", self)).into() @@ -207,9 +161,9 @@ impl Sexp { p.get(b"s").ok().unwrap_or_default() .and_then(|l| l.get(0).and_then(Sexp::string).cloned()) }).ok_or_else(not_a_signature)?; - Ok(mpis::Signature::EdDSA { - r: mpis::MPI::new(&r), - s: mpis::MPI::new(&s), + Ok(mpi::Signature::EdDSA { + r: mpi::MPI::new(&r), + s: mpi::MPI::new(&s), }) } else if let Some(param) = sig.get(b"ecdsa")? { let r = param.iter().find_map(|p| { @@ -220,17 +174,17 @@ impl Sexp { p.get(b"s").ok().unwrap_or_default() .and_then(|l| l.get(0).and_then(Sexp::string).cloned()) }).ok_or_else(not_a_signature)?; - Ok(mpis::Signature::ECDSA { - r: mpis::MPI::new(&r), - s: mpis::MPI::new(&s), + Ok(mpi::Signature::ECDSA { + r: mpi::MPI::new(&r), + s: mpi::MPI::new(&s), }) } else if let Some(param) = sig.get(b"rsa")? { let s = param.iter().find_map(|p| { p.get(b"s").ok().unwrap_or_default() .and_then(|l| l.get(0).and_then(Sexp::string).cloned()) }).ok_or_else(not_a_signature)?; - Ok(mpis::Signature::RSA { - s: mpis::MPI::new(&s), + Ok(mpi::Signature::RSA { + s: mpi::MPI::new(&s), }) } else if let Some(param) = sig.get(b"dsa")? { let r = param.iter().find_map(|p| { @@ -241,9 +195,9 @@ impl Sexp { p.get(b"s").ok().unwrap_or_default() .and_then(|l| l.get(0).and_then(Sexp::string).cloned()) }).ok_or_else(not_a_signature)?; - Ok(mpis::Signature::DSA { - r: mpis::MPI::new(&r), - s: mpis::MPI::new(&s), + Ok(mpi::Signature::DSA { + r: mpi::MPI::new(&r), + s: mpi::MPI::new(&s), }) } else { Err(Error::MalformedMPI( @@ -288,6 +242,60 @@ impl Sexp { } } +impl TryFrom<&mpi::Ciphertext> for Sexp { + type Error = anyhow::Error; + + /// Constructs an S-Expression representing `ciphertext`. + /// + /// The resulting expression is suitable for gpg-agent's `INQUIRE + /// CIPHERTEXT` inquiry. + fn try_from(ciphertext: &mpi::Ciphertext) -> Result<Self> { + use crate::crypto::mpi::Ciphertext::*; + match ciphertext { + RSA { ref c } => + Ok(Sexp::List(vec![ + Sexp::String("enc-val".into()), + Sexp::List(vec![ + Sexp::String("rsa".into()), + Sexp::List(vec![ + Sexp::String("a".into()), + Sexp::String(c.value().into())])])])), + + &ElGamal { ref e, ref c } => + Ok(Sexp::List(vec![ + Sexp::String("enc-val".into()), + Sexp::List(vec![ + Sexp::String("elg".into()), + Sexp::List(vec![ + Sexp::String("a".into()), + Sexp::String(e.value().into())]), + Sexp::List(vec![ + Sexp::String("b".into()), + Sexp::String(c.value().into())])])])), + + &ECDH { ref e, ref key } => + Ok(Sexp::List(vec![ + Sexp::String("enc-val".into()), + Sexp::List(vec![ + Sexp::String("ecdh".into()), + Sexp::List(vec![ + Sexp::String("s".into()), + Sexp::String(key.as_ref().into())]), + Sexp::List(vec![ + Sexp::String("e".into()), + Sexp::String(e.value().into())])])])), + + &Unknown { .. } => + Err(Error::InvalidArgument( + format!("Don't know how to convert {:?}", ciphertext)) + .into()), + + __Nonexhaustive => unreachable!(), + } + } +} + +#[cfg(any(test, feature = "quickcheck"))] impl Arbitrary for Sexp { fn arbitrary<G: Gen>(g: &mut G) -> Self { if f32::arbitrary(g) < 0.7 { @@ -377,6 +385,7 @@ impl Deref for String_ { } } +#[cfg(any(test, feature = "quickcheck"))] impl Arbitrary for String_ { fn arbitrary<G: Gen>(g: &mut G) -> Self { if bool::arbitrary(g) { @@ -406,7 +415,7 @@ mod tests { #[test] fn to_signature() { - use crate::crypto::mpis::Signature::*; + use crate::crypto::mpi::Signature::*; assert_match!(DSA { .. } = Sexp::from_bytes( crate::tests::file("sexp/dsa-signature.sexp")).unwrap() .to_signature().unwrap()); |