summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock3
-rw-r--r--ipc/Cargo.toml3
-rw-r--r--ipc/build.rs36
-rw-r--r--ipc/src/gnupg.rs2
-rw-r--r--ipc/src/lib.rs26
-rw-r--r--ipc/src/sexp.rs (renamed from openpgp/src/crypto/sexp.rs)52
-rw-r--r--ipc/src/sexp/parse/grammar.lalrpop (renamed from openpgp/src/parse/sexp/grammar.lalrpop)4
-rw-r--r--ipc/src/sexp/parse/lexer.rs (renamed from openpgp/src/parse/sexp/lexer.rs)0
-rw-r--r--ipc/src/sexp/parse/mod.rs (renamed from openpgp/src/parse/sexp/mod.rs)13
-rw-r--r--ipc/src/sexp/serialize.rs (renamed from openpgp/src/serialize/sexp.rs)54
-rw-r--r--ipc/src/tests.rs41
-rw-r--r--ipc/tests/data/sexp/dsa-signature.sexp (renamed from openpgp/tests/data/sexp/dsa-signature.sexp)0
-rw-r--r--ipc/tests/data/sexp/ecdsa-signature.sexp (renamed from openpgp/tests/data/sexp/ecdsa-signature.sexp)0
-rw-r--r--ipc/tests/data/sexp/eddsa-signature.sexp (renamed from openpgp/tests/data/sexp/eddsa-signature.sexp)0
-rw-r--r--ipc/tests/data/sexp/rsa-signature.sexp (renamed from openpgp/tests/data/sexp/rsa-signature.sexp)0
-rw-r--r--openpgp/src/crypto/mod.rs1
-rw-r--r--openpgp/src/parse.rs1
-rw-r--r--openpgp/src/serialize.rs1
18 files changed, 193 insertions, 44 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5d32e7dc..32e345cb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1778,6 +1778,7 @@ name = "sequoia-ipc"
version = "0.18.0"
dependencies = [
"anyhow 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)",
+ "buffered-reader 0.18.0",
"capnp-rpc 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ctor 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1785,9 +1786,11 @@ dependencies = [
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
"lalrpop 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
"lalrpop-util 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.74 (registry+https://github.com/rust-lang/crates.io-index)",
"memsec 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-tokio-ipc 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "quickcheck 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"sequoia-core 0.18.0",
"sequoia-openpgp 0.18.0",
diff --git a/ipc/Cargo.toml b/ipc/Cargo.toml
index b21fcfd1..ef5ed0ea 100644
--- a/ipc/Cargo.toml
+++ b/ipc/Cargo.toml
@@ -24,10 +24,12 @@ sequoia-openpgp = { path = "../openpgp", version = "0.18" }
sequoia-core = { path = "../core", version = "0.18" }
anyhow = "1"
+buffered-reader = { path = "../buffered-reader", version = "0.18", default-features = false }
capnp-rpc = "0.10"
fs2 = "0.4.2"
futures = "0.1"
lalrpop-util = "0.17"
+lazy_static = "1.3"
libc = "0.2.33"
memsec = "0.5.6"
rand = { version = "0.7", default-features = false }
@@ -52,3 +54,4 @@ lalrpop = "0.17"
[dev-dependencies]
clap = "2.32.0"
+quickcheck = { version = "0.9", default-features = false }
diff --git a/ipc/build.rs b/ipc/build.rs
index 23c7d3f8..5c8a9ffb 100644
--- a/ipc/build.rs
+++ b/ipc/build.rs
@@ -1,5 +1,41 @@
+use std::env;
+use std::fs;
+use std::io::{self, Write};
+use std::path::PathBuf;
extern crate lalrpop;
fn main() {
lalrpop::process_root().unwrap();
+ include_test_data().unwrap();
+}
+
+/// Builds the index of the test data for use with the `::tests`
+/// module.
+fn include_test_data() -> io::Result<()> {
+ let cwd = env::current_dir()?;
+ let mut sink = fs::File::create(
+ PathBuf::from(env::var_os("OUT_DIR").unwrap())
+ .join("tests.index.rs.inc")).unwrap();
+
+ writeln!(&mut sink, "{{")?;
+ let mut dirs = vec![PathBuf::from("tests/data")];
+ while let Some(dir) = dirs.pop() {
+ println!("rerun-if-changed={}", dir.to_str().unwrap());
+ for entry in fs::read_dir(dir).unwrap() {
+ let entry = entry?;
+ let path = entry.path();
+ if path.is_file() {
+ writeln!(
+ &mut sink, " add!({:?}, {:?});",
+ path.components().skip(2)
+ .map(|c| c.as_os_str().to_str().expect("valid UTF-8"))
+ .collect::<Vec<_>>().join("/"),
+ cwd.join(path))?;
+ } else if path.is_dir() {
+ dirs.push(path.clone());
+ }
+ }
+ }
+ writeln!(&mut sink, "}}")?;
+ Ok(())
}
diff --git a/ipc/src/gnupg.rs b/ipc/src/gnupg.rs
index 4b565553..b81e0927 100644
--- a/ipc/src/gnupg.rs
+++ b/ipc/src/gnupg.rs
@@ -14,13 +14,13 @@ use sequoia_openpgp as openpgp;
use openpgp::types::HashAlgorithm;
use openpgp::fmt::hex;
use openpgp::crypto;
-use openpgp::crypto::sexp::Sexp;
use openpgp::packet::prelude::*;
use openpgp::parse::Parse;
use openpgp::serialize::Serialize;
use crate::Result;
use crate::assuan;
+use crate::sexp::Sexp;
/// A GnuPG context.
#[derive(Debug)]
diff --git a/ipc/src/lib.rs b/ipc/src/lib.rs
index 7e6a62ab..f0d2c2b6 100644
--- a/ipc/src/lib.rs
+++ b/ipc/src/lib.rs
@@ -65,9 +65,35 @@ use std::thread;
use sequoia_openpgp as openpgp;
use sequoia_core as core;
+// Turns an `if let` into an expression so that it is possible to do
+// things like:
+//
+// ```rust,nocompile
+// if destructures_to(Foo::Bar(_) = value)
+// || destructures_to(Foo::Bam(_) = value) { ... }
+// ```
+// TODO: Replace with `std::matches!` once MSRV is bumped to 1.42.
+#[cfg(test)]
+macro_rules! destructures_to {
+ ( $error: pat = $expr:expr ) => {
+ {
+ let x = $expr;
+ if let $error = x {
+ true
+ } else {
+ false
+ }
+ }
+ };
+}
+
#[macro_use] mod trace;
pub mod assuan;
pub mod gnupg;
+pub mod sexp;
+
+#[cfg(test)]
+mod tests;
macro_rules! platform {
{ unix => { $($unix:tt)* }, windows => { $($windows:tt)* } } => {
diff --git a/openpgp/src/crypto/sexp.rs b/ipc/src/sexp.rs
index 96709651..38429557 100644
--- a/openpgp/src/crypto/sexp.rs
+++ b/ipc/src/sexp.rs
@@ -10,14 +10,18 @@ use std::convert::TryFrom;
use std::fmt;
use std::ops::Deref;
-#[cfg(any(test, feature = "quickcheck"))]
+#[cfg(test)]
use quickcheck::{Arbitrary, Gen};
-use crate::crypto::{self, mpi, SessionKey};
-use crate::crypto::mem::Protected;
+use sequoia_openpgp as openpgp;
+use openpgp::crypto::{mpi, SessionKey};
+use openpgp::crypto::mem::Protected;
+
+use openpgp::Error;
+use openpgp::Result;
-use crate::Error;
-use crate::Result;
+mod parse;
+mod serialize;
/// An *S-Expression*.
///
@@ -47,14 +51,14 @@ impl Sexp {
/// command. `padding` must be set according to the status
/// messages sent.
pub fn finish_decryption<R>(&self,
- recipient: &crate::packet::Key<
- crate::packet::key::PublicParts, R>,
+ recipient: &openpgp::packet::Key<
+ openpgp::packet::key::PublicParts, R>,
ciphertext: &mpi::Ciphertext,
padding: bool)
-> Result<SessionKey>
- where R: crate::packet::key::KeyRole
+ where R: openpgp::packet::key::KeyRole
{
- use crate::crypto::mpi::PublicKey;
+ use openpgp::crypto::mpi::PublicKey;
let not_a_session_key = || -> anyhow::Error {
Error::MalformedMPI(
format!("Not a session key: {:?}", self)).into()
@@ -114,7 +118,7 @@ impl Sexp {
// The session key is not padded. Currently, this
// happens if the session key is decrypted using
// scdaemon.
- assert!(! padding);
+ assert!(! padding); // XXX: Don't assert that.
Ok(s.to_vec().into())
},
@@ -127,7 +131,7 @@ impl Sexp {
// XXX: Erase shared point from s.
// Now finish the decryption.
- crypto::ecdh::decrypt_shared(recipient, &S, ciphertext)
+ openpgp::crypto::ecdh::decrypt_shared(recipient, &S, ciphertext)
},
_ =>
@@ -250,7 +254,7 @@ impl TryFrom<&mpi::Ciphertext> for Sexp {
/// 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::*;
+ use openpgp::crypto::mpi::Ciphertext::*;
match ciphertext {
RSA { ref c } =>
Ok(Sexp::List(vec![
@@ -400,10 +404,10 @@ impl Arbitrary for String_ {
#[cfg(test)]
mod tests {
use super::*;
- use crate::parse::Parse;
- use crate::serialize::Serialize;
+ use openpgp::parse::Parse;
+ use openpgp::serialize::Serialize;
- quickcheck! {
+ quickcheck::quickcheck! {
fn roundtrip(s: Sexp) -> bool {
let mut buf = Vec::new();
s.serialize(&mut buf).unwrap();
@@ -415,18 +419,18 @@ mod tests {
#[test]
fn to_signature() {
- use crate::crypto::mpi::Signature::*;
- assert_match!(DSA { .. } = Sexp::from_bytes(
+ use openpgp::crypto::mpi::Signature::*;
+ assert!(destructures_to!(DSA { .. } = Sexp::from_bytes(
crate::tests::file("sexp/dsa-signature.sexp")).unwrap()
- .to_signature().unwrap());
- assert_match!(ECDSA { .. } = Sexp::from_bytes(
+ .to_signature().unwrap()));
+ assert!(destructures_to!(ECDSA { .. } = Sexp::from_bytes(
crate::tests::file("sexp/ecdsa-signature.sexp")).unwrap()
- .to_signature().unwrap());
- assert_match!(EdDSA { .. } = Sexp::from_bytes(
+ .to_signature().unwrap()));
+ assert!(destructures_to!(EdDSA { .. } = Sexp::from_bytes(
crate::tests::file("sexp/eddsa-signature.sexp")).unwrap()
- .to_signature().unwrap());
- assert_match!(RSA { .. } = Sexp::from_bytes(
+ .to_signature().unwrap()));
+ assert!(destructures_to!(RSA { .. } = Sexp::from_bytes(
crate::tests::file("sexp/rsa-signature.sexp")).unwrap()
- .to_signature().unwrap());
+ .to_signature().unwrap()));
}
}
diff --git a/openpgp/src/parse/sexp/grammar.lalrpop b/ipc/src/sexp/parse/grammar.lalrpop
index 8712e7d2..9a880361 100644
--- a/openpgp/src/parse/sexp/grammar.lalrpop
+++ b/ipc/src/sexp/parse/grammar.lalrpop
@@ -5,8 +5,8 @@
//
// [S-Expressions]: https://people.csail.mit.edu/rivest/Sexp.txt
-use crate::parse::sexp::lexer::{self, LexicalError};
-use crate::crypto::sexp::{Sexp, String_};
+use crate::sexp::parse::lexer::{self, LexicalError};
+use crate::sexp::{Sexp, String_};
grammar<'input>;
diff --git a/openpgp/src/parse/sexp/lexer.rs b/ipc/src/sexp/parse/lexer.rs
index 0a570475..0a570475 100644
--- a/openpgp/src/parse/sexp/lexer.rs
+++ b/ipc/src/sexp/parse/lexer.rs
diff --git a/openpgp/src/parse/sexp/mod.rs b/ipc/src/sexp/parse/mod.rs
index 92bfd591..560f3764 100644
--- a/openpgp/src/parse/sexp/mod.rs
+++ b/ipc/src/sexp/parse/mod.rs
@@ -11,17 +11,18 @@ use std::path::Path;
use buffered_reader::{self, BufferedReader};
use lalrpop_util::{lalrpop_mod, ParseError};
+use sequoia_openpgp as openpgp;
+use openpgp::parse::Parse;
-use crate::Error;
+use openpgp::Error;
use crate::Result;
-use crate::crypto::sexp::Sexp;
-use crate::parse::Parse;
+use crate::sexp::Sexp;
mod lexer;
use self::lexer::Lexer;
// Load the generated code.
-lalrpop_mod!(#[allow(missing_docs, unused_parens)] grammar, "/parse/sexp/grammar.rs");
+lalrpop_mod!(#[allow(missing_docs, unused_parens)] grammar, "/sexp/parse/grammar.rs");
impl<'a> Parse<'a, Sexp> for Sexp {
fn from_reader<R: 'a + Read>(reader: R) -> Result<Sexp> {
@@ -79,8 +80,8 @@ impl Sexp {
#[cfg(test)]
mod tests {
- use crate::crypto::sexp::{Sexp, String_};
- use crate::parse::Parse;
+ use crate::sexp::{Sexp, String_};
+ use sequoia_openpgp::parse::Parse;
#[test]
fn basics() {
diff --git a/openpgp/src/serialize/sexp.rs b/ipc/src/sexp/serialize.rs
index 8c072ee0..a360c01e 100644
--- a/openpgp/src/serialize/sexp.rs
+++ b/ipc/src/sexp/serialize.rs
@@ -1,13 +1,18 @@
-use crate::Result;
-use crate::serialize::{
- Marshal,
- MarshalInto,
- generic_serialize_into,
+use std::io;
+
+use sequoia_openpgp as openpgp;
+use openpgp::{
+ Result,
+ Error,
+ serialize::{
+ Marshal,
+ MarshalInto,
+ },
};
-use crate::crypto::sexp::{Sexp, String_};
+use crate::sexp::{Sexp, String_};
-impl crate::serialize::Serialize for Sexp {}
+impl openpgp::serialize::Serialize for Sexp {}
impl Marshal for Sexp {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
@@ -25,7 +30,7 @@ impl Marshal for Sexp {
}
}
-impl crate::serialize::SerializeInto for Sexp {}
+impl openpgp::serialize::SerializeInto for Sexp {}
impl MarshalInto for Sexp {
fn serialized_len(&self) -> usize {
@@ -79,6 +84,39 @@ impl MarshalInto for String_ {
}
}
+/// Provides a generic implementation for SerializeInto::serialize_into.
+///
+/// For now, we express SerializeInto using Serialize. In the future,
+/// we may provide implementations not relying on Serialize for a
+/// no_std configuration of this crate.
+fn generic_serialize_into(o: &dyn Marshal, serialized_len: usize,
+ buf: &mut [u8])
+ -> Result<usize> {
+ let buf_len = buf.len();
+ let mut cursor = ::std::io::Cursor::new(buf);
+ match o.serialize(&mut cursor) {
+ Ok(_) => (),
+ Err(e) => {
+ let short_write =
+ if let Some(ioe) = e.downcast_ref::<io::Error>() {
+ ioe.kind() == io::ErrorKind::WriteZero
+ } else {
+ false
+ };
+ return if short_write {
+ assert!(buf_len < serialized_len,
+ "o.serialized_len() underestimated the required space");
+ Err(Error::InvalidArgument(
+ format!("Invalid buffer size, expected {}, got {}",
+ serialized_len, buf_len)).into())
+ } else {
+ Err(e)
+ }
+ }
+ };
+ Ok(cursor.position() as usize)
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/ipc/src/tests.rs b/ipc/src/tests.rs
new file mode 100644
index 00000000..3a827f92
--- /dev/null
+++ b/ipc/src/tests.rs
@@ -0,0 +1,41 @@
+//! Test data for Sequoia.
+//!
+//! This module includes the test data from `ipc/tests/data` in a
+//! structured way.
+
+use std::collections::BTreeMap;
+
+/// Returns the content of the given file below `ipc/tests/data`.
+pub fn file(name: &str) -> &'static [u8] {
+ lazy_static::lazy_static! {
+ static ref FILES: BTreeMap<&'static str, &'static [u8]> = {
+ let mut m: BTreeMap<&'static str, &'static [u8]> =
+ Default::default();
+
+ macro_rules! add {
+ ( $key: expr, $path: expr ) => {
+ m.insert($key, include_bytes!($path))
+ }
+ }
+ include!(concat!(env!("OUT_DIR"), "/tests.index.rs.inc"));
+
+ // Sanity checks.
+ assert!(m.contains_key("sexp/rsa-signature.sexp"));
+ m
+ };
+ }
+
+ FILES.get(name).unwrap_or_else(|| panic!("No such file {:?}", name))
+}
+
+/// Returns the content of the given file below `ipc/tests/data/keys`.
+#[allow(dead_code)]
+pub fn key(name: &str) -> &'static [u8] {
+ file(&format!("keys/{}", name))
+}
+
+/// Returns the content of the given file below `ipc/tests/data/messages`.
+#[allow(dead_code)]
+pub fn message(name: &str) -> &'static [u8] {
+ file(&format!("messages/{}", name))
+}
diff --git a/openpgp/tests/data/sexp/dsa-signature.sexp b/ipc/tests/data/sexp/dsa-signature.sexp
index 8585774f..8585774f 100644
--- a/openpgp/tests/data/sexp/dsa-signature.sexp
+++ b/ipc/tests/data/sexp/dsa-signature.sexp
diff --git a/openpgp/tests/data/sexp/ecdsa-signature.sexp b/ipc/tests/data/sexp/ecdsa-signature.sexp
index 03f0743d..03f0743d 100644
--- a/openpgp/tests/data/sexp/ecdsa-signature.sexp
+++ b/ipc/tests/data/sexp/ecdsa-signature.sexp
diff --git a/openpgp/tests/data/sexp/eddsa-signature.sexp b/ipc/tests/data/sexp/eddsa-signature.sexp
index 7a67e2a0..7a67e2a0 100644
--- a/openpgp/tests/data/sexp/eddsa-signature.sexp
+++ b/ipc/tests/data/sexp/eddsa-signature.sexp
diff --git a/openpgp/tests/data/sexp/rsa-signature.sexp b/ipc/tests/data/sexp/rsa-signature.sexp
index dc7438c0..dc7438c0 100644
--- a/openpgp/tests/data/sexp/rsa-signature.sexp
+++ b/ipc/tests/data/sexp/rsa-signature.sexp
diff --git a/openpgp/src/crypto/mod.rs b/openpgp/src/crypto/mod.rs
index 710dc5df..75e8fe9b 100644
--- a/openpgp/src/crypto/mod.rs
+++ b/openpgp/src/crypto/mod.rs
@@ -35,7 +35,6 @@ pub mod mem;
pub mod mpi;
mod s2k;
pub use s2k::S2K;
-pub mod sexp;
pub(crate) mod symmetric;
/// Holds a session key.
diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs
index 8524dbc5..e9fbcc91 100644
--- a/openpgp/src/parse.rs
+++ b/openpgp/src/parse.rs
@@ -258,7 +258,6 @@ pub use self::packet_parser_builder::{Dearmor, PacketParserBuilder};
pub mod map;
mod mpis;
-mod sexp;
pub mod stream;
// Whether to trace execution by default (on stderr).
diff --git a/openpgp/src/serialize.rs b/openpgp/src/serialize.rs
index fb80a85d..87c12cd6 100644
--- a/openpgp/src/serialize.rs
+++ b/openpgp/src/serialize.rs
@@ -140,7 +140,6 @@ use std::convert::{TryFrom, TryInto};
use super::*;
-mod sexp;
mod cert;
pub use self::cert::TSK;
mod cert_armored;