summaryrefslogtreecommitdiffstats
path: root/openpgp/src/crypto/sexp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/crypto/sexp.rs')
-rw-r--r--openpgp/src/crypto/sexp.rs141
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());