summaryrefslogtreecommitdiffstats
path: root/openpgp/src/policy.rs
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2020-02-14 12:38:24 +0100
committerNeal H. Walfield <neal@pep.foundation>2020-02-14 12:40:50 +0100
commit3c51bbaccd6cad5449c40f18b123d652199bf558 (patch)
tree380cf3f95f5756ec01151ea17b62d211e524b6f7 /openpgp/src/policy.rs
parent03bbb8d0e066e101ca1c4378cc0473deb925acdd (diff)
openpgp: Add a test.
- Add a test to make sure `Policy::key` works when verifying signatures.
Diffstat (limited to 'openpgp/src/policy.rs')
-rw-r--r--openpgp/src/policy.rs225
1 files changed, 206 insertions, 19 deletions
diff --git a/openpgp/src/policy.rs b/openpgp/src/policy.rs
index 49b33064..87a8d04e 100644
--- a/openpgp/src/policy.rs
+++ b/openpgp/src/policy.rs
@@ -360,9 +360,23 @@ mod test {
use super::*;
use crate::Fingerprint;
- use crate::cert::{Cert, CertBuilder};
+ use crate::cert::{Cert, CertBuilder, CipherSuite};
+ use crate::crypto::SessionKey;
+ use crate::packet::key::Key4;
+ use crate::packet::signature;
+ use crate::packet::{PKESK, SKESK};
use crate::parse::Parse;
+ use crate::parse::stream::DecryptionHelper;
+ use crate::parse::stream::Decryptor;
+ use crate::parse::stream::DetachedVerifier;
+ use crate::parse::stream::MessageLayer;
+ use crate::parse::stream::MessageStructure;
+ use crate::parse::stream::VerificationHelper;
+ use crate::parse::stream::Verifier;
use crate::policy::StandardPolicy as P;
+ use crate::types::Curve;
+ use crate::types::KeyFlags;
+ use crate::types::SymmetricAlgorithm;
#[test]
fn binding_signature() {
@@ -526,16 +540,6 @@ mod test {
#[test]
fn binary_signature() {
- use crate::crypto::SessionKey;
- use crate::types::SymmetricAlgorithm;
- use crate::packet::{PKESK, SKESK};
- use crate::parse::stream::MessageLayer;
- use crate::parse::stream::MessageStructure;
- use crate::parse::stream::Verifier;
- use crate::parse::stream::Decryptor;
- use crate::parse::stream::VerificationHelper;
- use crate::parse::stream::DecryptionHelper;
-
#[derive(PartialEq, Debug)]
struct VHelper {
good: usize,
@@ -879,10 +883,7 @@ mod test {
}
#[test]
- fn key() -> Result<()> {
- use crate::cert::CipherSuite;
- use crate::types::Curve;
-
+ fn key_verify_self_signature() -> Result<()> {
let p = &P::new();
#[derive(Debug)]
@@ -915,10 +916,6 @@ mod test {
assert!(cert.primary_key().with_policy(p, None).is_ok());
assert!(cert.primary_key().with_policy(norsa, None).is_err());
- use crate::packet::key::Key4;
- use crate::packet::signature;
- use crate::types::KeyFlags;
-
// Generate a certificate with an ECC primary, an ECC subkey,
// and an RSA subkey.
let (cert,_) = CertBuilder::new()
@@ -981,4 +978,194 @@ mod test {
Ok(())
}
+
+ #[test]
+ fn key_verify_binary_signature() -> Result<()> {
+ use crate::packet::signature;
+ use crate::serialize::Serialize;
+ use crate::Packet;
+ use crate::types::KeyFlags;
+
+ let p = &P::new();
+
+ #[derive(Debug)]
+ struct NoRsa;
+ impl Policy for NoRsa {
+ fn key(&self, ka: &ValidKeyAmalgamation<key::PublicParts>)
+ -> Result<()>
+ {
+ use crate::types::PublicKeyAlgorithm::*;
+
+ eprintln!("algo: {} is {}",
+ ka.fingerprint(), ka.key().pk_algo());
+ if ka.key().pk_algo() == RSAEncryptSign {
+ Err(format_err!("RSA!"))
+ } else {
+ Ok(())
+ }
+ }
+ }
+ let norsa = &NoRsa {};
+
+ #[derive(PartialEq, Debug)]
+ struct VHelper {
+ good: usize,
+ errors: usize,
+ keys: Vec<Cert>,
+ }
+
+ impl VHelper {
+ fn new(keys: Vec<Cert>) -> Self {
+ VHelper {
+ good: 0,
+ errors: 0,
+ keys: keys,
+ }
+ }
+ }
+
+ impl VerificationHelper for VHelper {
+ fn get_public_keys(&mut self, _ids: &[crate::KeyHandle])
+ -> Result<Vec<Cert>>
+ {
+ Ok(self.keys.clone())
+ }
+
+ fn check(&mut self, structure: MessageStructure) -> Result<()>
+ {
+ use crate::parse::stream::VerificationResult::*;
+ for layer in structure.iter() {
+ match layer {
+ MessageLayer::SignatureGroup { ref results } =>
+ for result in results {
+ match result {
+ GoodChecksum { .. } => self.good += 1,
+ Error { .. } => self.errors += 1,
+ _ => (),
+ }
+ }
+ MessageLayer::Compression { .. } => (),
+ _ => unreachable!(),
+ }
+ }
+
+ Ok(())
+ }
+ }
+
+ impl DecryptionHelper for VHelper {
+ fn decrypt<D>(&mut self, _: &[PKESK], _: &[SKESK],
+ _: Option<SymmetricAlgorithm>,_: D)
+ -> Result<Option<Fingerprint>>
+ where D: FnMut(SymmetricAlgorithm, &SessionKey) -> Result<()>
+ {
+ unreachable!();
+ }
+ }
+
+ // Sign msg using cert's first subkey, return the signature.
+ fn sign_and_verify(p: &dyn Policy, cert: &Cert, good: bool) {
+ eprintln!("Expect verification to be {}",
+ if good { "good" } else { "bad" });
+ for (i, k) in cert.keys().enumerate() {
+ eprintln!(" {}. {}", i, k.fingerprint());
+ }
+
+ let msg = b"Hello, World";
+
+ // We always use the first subkey.
+ let key = cert.keys().nth(1).unwrap().key();
+ let mut keypair = key.clone()
+ .mark_parts_secret().unwrap()
+ .into_keypair().unwrap();
+
+ // Create a signature.
+ let sig = signature::Builder::new(SignatureType::Binary)
+ .set_signature_creation_time(
+ std::time::SystemTime::now()).unwrap()
+ .set_issuer_fingerprint(key.fingerprint()).unwrap()
+ .set_issuer(key.keyid()).unwrap()
+ .sign_message(&mut keypair, msg).unwrap();
+
+ // Make sure the signature is ok.
+ sig.verify_message(key, msg).unwrap();
+
+ // Turn it into a detached signature.
+ let sig = {
+ let mut v = Vec::new();
+ let sig : Packet = sig.into();
+ sig.serialize(&mut v).unwrap();
+ v
+ };
+
+ let h = VHelper::new(vec![ cert.clone() ]);
+ let mut v =
+ match DetachedVerifier::from_bytes(p, &sig, msg, h, None) {
+ Ok(v) => v,
+ Err(e) => panic!("{}", e),
+ };
+ assert!(v.message_processed());
+ assert_eq!(v.helper_ref().good, if good { 1 } else { 0 });
+ assert_eq!(v.helper_ref().errors, if good { 0 } else { 1 });
+
+ let mut content = Vec::new();
+ v.read_to_end(&mut content).unwrap();
+ assert_eq!(msg.len(), content.len());
+ assert_eq!(msg, &content[..]);
+ }
+
+
+ // A certificate with an ECC primary and an ECC signing
+ // subkey.
+ eprintln!("Trying ECC primary, ECC sub:");
+ let (cert,_) = CertBuilder::new()
+ .set_cipher_suite(CipherSuite::Cv25519)
+ .add_subkey(KeyFlags::default().set_signing(true), None,
+ None)
+ .generate()?;
+
+ assert_eq!(cert.keys().with_policy(p, None).count(), 2);
+ assert_eq!(cert.keys().with_policy(norsa, None).count(), 2);
+ assert!(cert.primary_key().with_policy(p, None).is_ok());
+ assert!(cert.primary_key().with_policy(norsa, None).is_ok());
+
+ sign_and_verify(p, &cert, true);
+ sign_and_verify(norsa, &cert, true);
+
+ // A certificate with an RSA primary and an RCC signing
+ // subkey.
+ eprintln!("Trying RSA primary, ECC sub:");
+ let (cert,_) = CertBuilder::new()
+ .set_cipher_suite(CipherSuite::RSA4k)
+ .add_subkey(KeyFlags::default().set_signing(true), None,
+ CipherSuite::Cv25519)
+ .generate()?;
+
+ assert_eq!(cert.keys().with_policy(p, None).count(), 2);
+ assert_eq!(cert.keys().with_policy(norsa, None).count(), 0);
+ assert!(cert.primary_key().with_policy(p, None).is_ok());
+ assert!(cert.primary_key().with_policy(norsa, None).is_err());
+
+ sign_and_verify(p, &cert, true);
+ sign_and_verify(norsa, &cert, false);
+
+ // A certificate with an ECC primary and an RSA signing
+ // subkey.
+ eprintln!("Trying ECC primary, RSA sub:");
+ let (cert,_) = CertBuilder::new()
+ .set_cipher_suite(CipherSuite::Cv25519)
+ .add_subkey(KeyFlags::default().set_signing(true), None,
+ CipherSuite::RSA4k)
+ .generate()?;
+
+ assert_eq!(cert.keys().with_policy(p, None).count(), 2);
+ assert_eq!(cert.keys().with_policy(norsa, None).count(), 1);
+ assert!(cert.primary_key().with_policy(p, None).is_ok());
+ assert!(cert.primary_key().with_policy(norsa, None).is_ok());
+
+ sign_and_verify(p, &cert, true);
+ sign_and_verify(norsa, &cert, false);
+
+ Ok(())
+ }
}