From 05cf492f3417fd61f6b1e7dc4913a16fd5f201ea Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Mon, 12 Aug 2019 13:39:14 +0200 Subject: openpgp: Use marker types to denote a Key's type. - In addition to providing some added protection, this allows us to implement 'From> for Packet'. --- tool/src/commands/decrypt.rs | 19 ++-- tool/src/commands/dump.rs | 266 ++++++++++++++++++++++--------------------- tool/src/commands/inspect.rs | 19 ++-- tool/src/commands/mod.rs | 9 +- tool/src/commands/sign.rs | 6 +- 5 files changed, 171 insertions(+), 148 deletions(-) (limited to 'tool') diff --git a/tool/src/commands/decrypt.rs b/tool/src/commands/decrypt.rs index 9ffa6303..3c4b3658 100644 --- a/tool/src/commands/decrypt.rs +++ b/tool/src/commands/decrypt.rs @@ -10,7 +10,7 @@ use crate::openpgp::constants::SymmetricAlgorithm; use crate::openpgp::conversions::hex; use crate::openpgp::crypto::SessionKey; use crate::openpgp::{Fingerprint, TPK, KeyID, Result}; -use crate::openpgp::packet::{Key, key::SecretKeyMaterial, Signature, PKESK, SKESK}; +use crate::openpgp::packet::prelude::*; use crate::openpgp::parse::PacketParser; use crate::openpgp::parse::stream::{ VerificationHelper, DecryptionHelper, Decryptor, MessageStructure, @@ -21,7 +21,8 @@ use super::{dump::PacketDumper, VHelper}; struct Helper<'a> { vhelper: VHelper<'a>, - secret_keys: HashMap, + secret_keys: + HashMap, key_identities: HashMap, key_hints: HashMap, dump_session_key: bool, @@ -34,18 +35,22 @@ impl<'a> Helper<'a> { signatures: usize, tpks: Vec, secrets: Vec, dump_session_key: bool, dump: bool, hex: bool) -> Self { - let mut keys: HashMap = HashMap::new(); + let mut keys: HashMap + = HashMap::new(); let mut identities: HashMap = HashMap::new(); let mut hints: HashMap = HashMap::new(); for tsk in secrets { - let can_encrypt = |_: &Key, sig: Option<&Signature>| -> bool { + fn can_encrypt(_: &Key, sig: Option<&Signature>) -> bool + where P: key::KeyParts, + R: key::KeyRole, + { if let Some(sig) = sig { sig.key_flags().can_encrypt_at_rest() || sig.key_flags().can_encrypt_for_transport() } else { false } - }; + } let hint = match tsk.userids().nth(0) { Some(uid) => format!("{} ({})", uid.userid(), @@ -55,7 +60,7 @@ impl<'a> Helper<'a> { if can_encrypt(tsk.primary().key(), tsk.primary_key_signature()) { let id = tsk.fingerprint().to_keyid(); - keys.insert(id.clone(), tsk.primary().key().clone()); + keys.insert(id.clone(), tsk.primary().key().clone().into()); identities.insert(id.clone(), tsk.fingerprint()); hints.insert(id, hint.clone()); } @@ -64,7 +69,7 @@ impl<'a> Helper<'a> { let key = skb.key(); if can_encrypt(key, skb.binding_signature()) { let id = key.fingerprint().to_keyid(); - keys.insert(id.clone(), key.clone()); + keys.insert(id.clone(), key.clone().into()); identities.insert(id.clone(), tsk.fingerprint()); hints.insert(id, hint.clone()); } diff --git a/tool/src/commands/dump.rs b/tool/src/commands/dump.rs index 8fb98ffe..579b9ad7 100644 --- a/tool/src/commands/dump.rs +++ b/tool/src/commands/dump.rs @@ -6,6 +6,7 @@ use self::openpgp::constants::SymmetricAlgorithm; use self::openpgp::conversions::hex; use self::openpgp::crypto::mpis; use self::openpgp::{Packet, Result}; +use self::openpgp::packet::prelude::*; use self::openpgp::packet::ctb::CTB; use self::openpgp::packet::{Header, BodyLength, Signature}; use self::openpgp::packet::signature::subpacket::{Subpacket, SubpacketValue}; @@ -250,6 +251,139 @@ impl PacketDumper { })?; } + fn dump_key(pd: &PacketDumper, + output: &mut dyn io::Write, i: &str, p: &Packet, + k: &Key) + -> Result<()> + where P: key::KeyParts, + R: key::KeyRole, + { + writeln!(output, "{}", p.tag())?; + writeln!(output, "{} Version: {}", i, k.version())?; + writeln!(output, "{} Creation time: {}", i, + time::strftime(TIMEFMT, k.creation_time()).unwrap())?; + writeln!(output, "{} Pk algo: {}", i, k.pk_algo())?; + if let Some(bits) = k.mpis().bits() { + writeln!(output, "{} Pk size: {} bits", i, bits)?; + } + if pd.mpis { + writeln!(output, "{}", i)?; + writeln!(output, "{} Public Key:", i)?; + + let ii = format!("{} ", i); + match k.mpis() { + mpis::PublicKey::RSA { e, n } => + pd.dump_mpis(output, &ii, + &[e.value(), n.value()], + &["e", "n"])?, + mpis::PublicKey::DSA { p, q, g, y } => + pd.dump_mpis(output, &ii, + &[p.value(), q.value(), g.value(), + y.value()], + &["p", "q", "g", "y"])?, + mpis::PublicKey::Elgamal { p, g, y } => + pd.dump_mpis(output, &ii, + &[p.value(), g.value(), y.value()], + &["p", "g", "y"])?, + mpis::PublicKey::EdDSA { curve, q } => { + writeln!(output, "{} Curve: {}", ii, curve)?; + pd.dump_mpis(output, &ii, &[q.value()], &["q"])?; + }, + mpis::PublicKey::ECDSA { curve, q } => { + writeln!(output, "{} Curve: {}", ii, curve)?; + pd.dump_mpis(output, &ii, &[q.value()], &["q"])?; + }, + mpis::PublicKey::ECDH { curve, q, hash, sym } => { + writeln!(output, "{} Curve: {}", ii, curve)?; + writeln!(output, "{} Hash algo: {}", ii, hash)?; + writeln!(output, "{} Symmetric algo: {}", ii, + sym)?; + pd.dump_mpis(output, &ii, &[q.value()], &["q"])?; + }, + mpis::PublicKey::Unknown { mpis, rest } => { + let keys: Vec = + (0..mpis.len()).map( + |i| format!("mpi{}", i)).collect(); + pd.dump_mpis( + output, &ii, + &mpis.iter().map(|m| { + m.value().iter().as_slice() + }).collect::>()[..], + &keys.iter().map(|k| k.as_str()) + .collect::>()[..], + )?; + + pd.dump_mpis(output, &ii, &[&rest[..]], &["rest"])?; + }, + } + + if let Some(secrets) = k.secret() { + use self::openpgp::packet::key::SecretKeyMaterial; + writeln!(output, "{}", i)?; + writeln!(output, "{} Secret Key:", i)?; + + let ii = format!("{} ", i); + match secrets { + SecretKeyMaterial::Unencrypted(ref u) => u.map( + |mpis| -> Result<()> { + match mpis + { + mpis::SecretKeyMaterial::RSA { d, p, q, u } => + pd.dump_mpis(output, &ii, + &[d.value(), p.value(), + q.value(), u.value()], + &["d", "p", "q", "u"])?, + mpis::SecretKeyMaterial::DSA { x } => + pd.dump_mpis(output, &ii, &[x.value()], + &["x"])?, + mpis::SecretKeyMaterial::Elgamal { x } => + pd.dump_mpis(output, &ii, &[x.value()], + &["x"])?, + mpis::SecretKeyMaterial::EdDSA { scalar } => + pd.dump_mpis(output, &ii, + &[scalar.value()], + &["scalar"])?, + mpis::SecretKeyMaterial::ECDSA { scalar } => + pd.dump_mpis(output, &ii, + &[scalar.value()], + &["scalar"])?, + mpis::SecretKeyMaterial::ECDH { scalar } => + pd.dump_mpis(output, &ii, + &[scalar.value()], + &["scalar"])?, + mpis::SecretKeyMaterial::Unknown { mpis, rest } => { + let keys: Vec = + (0..mpis.len()).map( + |i| format!("mpi{}", i)).collect(); + pd.dump_mpis( + output, &ii, + &mpis.iter().map(|m| { + m.value().iter().as_slice() + }).collect::>()[..], + &keys.iter().map(|k| k.as_str()) + .collect::>()[..], + )?; + + pd.dump_mpis(output, &ii, &[rest], + &["rest"])?; + }, + } Ok(()) })?, + SecretKeyMaterial::Encrypted(ref e) => { + writeln!(output, "{}", i)?; + write!(output, "{} S2K: ", ii)?; + pd.dump_s2k(output, &ii, e.s2k())?; + writeln!(output, "{} Sym. algo: {}", ii, + e.algo())?; + pd.dump_mpis(output, &ii, &[e.ciphertext()], + &["ciphertext"])?; + }, + } + } + } + + Ok(()) + } + match p { Unknown(ref u) => { writeln!(output, "Unknown Packet")?; @@ -257,6 +391,11 @@ impl PacketDumper { writeln!(output, "{} Error: {}", i, u.error())?; }, + PublicKey(ref k) => dump_key(self, output, i, p, k)?, + PublicSubkey(ref k) => dump_key(self, output, i, p, k)?, + SecretKey(ref k) => dump_key(self, output, i, p, k)?, + SecretSubkey(ref k) => dump_key(self, output, i, p, k)?, + Signature(ref s) => { writeln!(output, "Signature Packet")?; writeln!(output, "{} Version: {}", i, s.version())?; @@ -340,133 +479,6 @@ impl PacketDumper { writeln!(output, "{} Last: {}", i, o.last())?; }, - PublicKey(ref k) | PublicSubkey(ref k) - | SecretKey(ref k) | SecretSubkey(ref k) => - { - writeln!(output, "{}", p.tag())?; - writeln!(output, "{} Version: {}", i, k.version())?; - writeln!(output, "{} Creation time: {}", i, - time::strftime(TIMEFMT, k.creation_time()).unwrap())?; - writeln!(output, "{} Pk algo: {}", i, k.pk_algo())?; - if let Some(bits) = k.mpis().bits() { - writeln!(output, "{} Pk size: {} bits", i, bits)?; - } - if self.mpis { - writeln!(output, "{}", i)?; - writeln!(output, "{} Public Key:", i)?; - - let ii = format!("{} ", i); - match k.mpis() { - mpis::PublicKey::RSA { e, n } => - self.dump_mpis(output, &ii, - &[e.value(), n.value()], - &["e", "n"])?, - mpis::PublicKey::DSA { p, q, g, y } => - self.dump_mpis(output, &ii, - &[p.value(), q.value(), g.value(), - y.value()], - &["p", "q", "g", "y"])?, - mpis::PublicKey::Elgamal { p, g, y } => - self.dump_mpis(output, &ii, - &[p.value(), g.value(), y.value()], - &["p", "g", "y"])?, - mpis::PublicKey::EdDSA { curve, q } => { - writeln!(output, "{} Curve: {}", ii, curve)?; - self.dump_mpis(output, &ii, &[q.value()], &["q"])?; - }, - mpis::PublicKey::ECDSA { curve, q } => { - writeln!(output, "{} Curve: {}", ii, curve)?; - self.dump_mpis(output, &ii, &[q.value()], &["q"])?; - }, - mpis::PublicKey::ECDH { curve, q, hash, sym } => { - writeln!(output, "{} Curve: {}", ii, curve)?; - writeln!(output, "{} Hash algo: {}", ii, hash)?; - writeln!(output, "{} Symmetric algo: {}", ii, - sym)?; - self.dump_mpis(output, &ii, &[q.value()], &["q"])?; - }, - mpis::PublicKey::Unknown { mpis, rest } => { - let keys: Vec = - (0..mpis.len()).map( - |i| format!("mpi{}", i)).collect(); - self.dump_mpis( - output, &ii, - &mpis.iter().map(|m| { - m.value().iter().as_slice() - }).collect::>()[..], - &keys.iter().map(|k| k.as_str()) - .collect::>()[..], - )?; - - self.dump_mpis(output, &ii, &[&rest[..]], &["rest"])?; - }, - } - - if let Some(secrets) = k.secret() { - use self::openpgp::packet::key::SecretKeyMaterial; - writeln!(output, "{}", i)?; - writeln!(output, "{} Secret Key:", i)?; - - let ii = format!("{} ", i); - match secrets { - SecretKeyMaterial::Unencrypted(ref u) => u.map( - |mpis| -> Result<()> { - match mpis - { - mpis::SecretKeyMaterial::RSA { d, p, q, u } => - self.dump_mpis(output, &ii, - &[d.value(), p.value(), - q.value(), u.value()], - &["d", "p", "q", "u"])?, - mpis::SecretKeyMaterial::DSA { x } => - self.dump_mpis(output, &ii, &[x.value()], - &["x"])?, - mpis::SecretKeyMaterial::Elgamal { x } => - self.dump_mpis(output, &ii, &[x.value()], - &["x"])?, - mpis::SecretKeyMaterial::EdDSA { scalar } => - self.dump_mpis(output, &ii, - &[scalar.value()], - &["scalar"])?, - mpis::SecretKeyMaterial::ECDSA { scalar } => - self.dump_mpis(output, &ii, - &[scalar.value()], - &["scalar"])?, - mpis::SecretKeyMaterial::ECDH { scalar } => - self.dump_mpis(output, &ii, - &[scalar.value()], - &["scalar"])?, - mpis::SecretKeyMaterial::Unknown { mpis, rest } => { - let keys: Vec = - (0..mpis.len()).map( - |i| format!("mpi{}", i)).collect(); - self.dump_mpis( - output, &ii, - &mpis.iter().map(|m| { - m.value().iter().as_slice() - }).collect::>()[..], - &keys.iter().map(|k| k.as_str()) - .collect::>()[..], - )?; - - self.dump_mpis(output, &ii, &[rest], - &["rest"])?; - }, - } Ok(()) })?, - SecretKeyMaterial::Encrypted(ref e) => { - writeln!(output, "{}", i)?; - write!(output, "{} S2K: ", ii)?; - self.dump_s2k(output, &ii, e.s2k())?; - writeln!(output, "{} Sym. algo: {}", ii, - e.algo())?; - self.dump_mpis(output, &ii, &[e.ciphertext()], - &["ciphertext"])?; - }, - } - } - } - }, - Trust(ref p) => { writeln!(output, "Trust Packet")?; writeln!(output, "{} Value: {}", i, hex::encode(p.value()))?; diff --git a/tool/src/commands/inspect.rs b/tool/src/commands/inspect.rs index e9d42083..e1a73bc5 100644 --- a/tool/src/commands/inspect.rs +++ b/tool/src/commands/inspect.rs @@ -164,14 +164,17 @@ fn inspect_tpk(output: &mut io::Write, tpk: &openpgp::TPK, Ok(()) } -fn inspect_key(output: &mut io::Write, - indent: &str, - key: &openpgp::packet::Key, - binding_signature: Option<&openpgp::packet::Signature>, - certs: &[openpgp::packet::Signature], - print_keygrips: bool, - print_certifications: bool) - -> Result<()> { +fn inspect_key(output: &mut io::Write, + indent: &str, + key: &openpgp::packet::Key, + binding_signature: Option<&openpgp::packet::Signature>, + certs: &[openpgp::packet::Signature], + print_keygrips: bool, + print_certifications: bool) + -> Result<()> + where P: openpgp::packet::key::KeyParts, + R: openpgp::packet::key::KeyRole +{ if let Some(sig) = binding_signature { if sig.key_expired(key) { writeln!(output, "{} Expired", indent)?; diff --git a/tool/src/commands/mod.rs b/tool/src/commands/mod.rs index c4175cd9..4593d95d 100644 --- a/tool/src/commands/mod.rs +++ b/tool/src/commands/mod.rs @@ -11,7 +11,7 @@ use sequoia_core::Context; use crate::openpgp::constants::DataFormat; use crate::openpgp::crypto; use crate::openpgp::{TPK, KeyID, Result}; -use crate::openpgp::packet::key::SecretKeyMaterial; +use crate::openpgp::packet::prelude::*; use crate::openpgp::parse::{ Parse, PacketParserResult, @@ -42,7 +42,10 @@ fn tm2str(t: &time::Tm) -> String { } /// Returns suitable signing keys from a given list of TPKs. -fn get_signing_keys(tpks: &[openpgp::TPK]) -> Result> { +fn get_signing_keys(tpks: &[openpgp::TPK]) + -> Result>> +{ let mut keys = Vec::new(); 'next_tpk: for tsk in tpks { for key in tsk.keys_valid() @@ -115,7 +118,7 @@ pub fn encrypt(store: &mut store::Store, if ! signers.is_empty() { sink = Signer::with_intended_recipients( sink, - signers.iter_mut().map(|s| -> &mut dyn crypto::Signer { s }) + signers.iter_mut().map(|s| -> &mut dyn crypto::Signer<_> { s }) .collect(), &recipients, None)?; diff --git a/tool/src/commands/sign.rs b/tool/src/commands/sign.rs index 749781dc..164b5710 100644 --- a/tool/src/commands/sign.rs +++ b/tool/src/commands/sign.rs @@ -84,7 +84,7 @@ fn sign_data(input: &mut io::Read, output_path: Option<&str>, let mut keypairs = super::get_signing_keys(&secrets)?; let signers = keypairs.iter_mut() - .map(|s| -> &mut dyn crypto::Signer { s }) + .map(|s| -> &mut dyn crypto::Signer<_> { s }) .collect(); // When extending a detached signature, prepend any existing @@ -146,8 +146,8 @@ fn sign_message(input: &mut io::Read, output_path: Option<&str>, // the loop, because the borrow checker does not understand that // it happens only once. let mut signers = Some(keypairs.iter_mut() - .map(|s| -> &mut dyn crypto::Signer { s }) - .collect::>()); + .map(|s| -> &mut dyn crypto::Signer<_> { s }) + .collect::>>()); let mut sink = Message::new(output); -- cgit v1.2.3