diff options
author | Neal H. Walfield <neal@pep.foundation> | 2019-08-12 13:39:14 +0200 |
---|---|---|
committer | Neal H. Walfield <neal@pep.foundation> | 2019-08-23 19:15:13 +0200 |
commit | 05cf492f3417fd61f6b1e7dc4913a16fd5f201ea (patch) | |
tree | eca0c2e0481e10b54884a766e7e864020089fe84 /openpgp/src/parse | |
parent | 102dea398e920e91b34e5602033c2e7e53c50bb1 (diff) |
openpgp: Use marker types to denote a Key's type.
- In addition to providing some added protection, this allows us to
implement 'From<Key<_, _>> for Packet'.
Diffstat (limited to 'openpgp/src/parse')
-rw-r--r-- | openpgp/src/parse/parse.rs | 61 | ||||
-rw-r--r-- | openpgp/src/parse/stream.rs | 49 |
2 files changed, 73 insertions, 37 deletions
diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs index 6d313d71..75c8a599 100644 --- a/openpgp/src/parse/parse.rs +++ b/openpgp/src/parse/parse.rs @@ -1289,7 +1289,11 @@ fn one_pass_sig_test () { } } -impl Key { +// Key::parse doesn't actually use the Key type parameters. So, we +// can just set them to anything. This avoids the caller having to +// set them to something. +impl Key<key::UnspecifiedParts, key::UnspecifiedRole> +{ /// Parses the body of a public key, public subkey, secret key or /// secret subkey packet. fn parse<'a>(mut php: PacketHeaderParser<'a>) -> Result<PacketParser<'a>> { @@ -1315,7 +1319,11 @@ impl Key { } } -impl Key4 { +// Key4::parse doesn't actually use the Key4 type parameters. So, we +// can just set them to anything. This avoids the caller having to +// set them to something. +impl Key4<key::UnspecifiedParts, key::UnspecifiedRole> +{ /// Parses the body of a public key, public subkey, secret key or /// secret subkey packet. fn parse<'a>(mut php: PacketHeaderParser<'a>) -> Result<PacketParser<'a>> { @@ -1392,23 +1400,41 @@ impl Key4 { } } - let key = php_try!(Key4::new(time::Tm::from_pgp(creation_time), - pk_algo, mpis, secret)); + fn k<P, R>(creation_time: u32, + pk_algo: PublicKeyAlgorithm, + mpis: PublicKey, + secret: Option<SecretKeyMaterial>) + -> Result<Key4<P, R>> + where P: key::KeyParts, + R: key::KeyRole, + { + Key4::new(time::Tm::from_pgp(creation_time), + pk_algo, mpis, secret) + } let tag = php.header.ctb.tag; - php.ok(match tag { + + let p : Packet = match tag { // For the benefit of Key::from_bytes. Tag::Reserved => if have_secret { - Packet::SecretKey(key.into()) + Packet::SecretKey( + php_try!(k(creation_time, pk_algo, mpis, secret)).into()) } else { - Packet::PublicKey(key.into()) + Packet::PublicKey( + php_try!(k(creation_time, pk_algo, mpis, secret)).into()) }, - Tag::PublicKey => Packet::PublicKey(key.into()), - Tag::PublicSubkey => Packet::PublicSubkey(key.into()), - Tag::SecretKey => Packet::SecretKey(key.into()), - Tag::SecretSubkey => Packet::SecretSubkey(key.into()), + Tag::PublicKey => Packet::PublicKey( + php_try!(k(creation_time, pk_algo, mpis, secret)).into()), + Tag::PublicSubkey => Packet::PublicSubkey( + php_try!(k(creation_time, pk_algo, mpis, secret)).into()), + Tag::SecretKey => Packet::SecretKey( + php_try!(k(creation_time, pk_algo, mpis, secret)).into()), + Tag::SecretSubkey => Packet::SecretSubkey( + php_try!(k(creation_time, pk_algo, mpis, secret)).into()), _ => unreachable!(), - }) + }; + + php.ok(p) } /// Returns whether the data appears to be a key (no promises). @@ -1450,7 +1476,7 @@ impl Key4 { } } -impl<'a> Parse<'a, Key> for Key { +impl<'a> Parse<'a, key::UnspecifiedKey> for key::UnspecifiedKey { fn from_reader<R: 'a + Read>(reader: R) -> Result<Self> { let bio = buffered_reader::Generic::with_cookie( reader, None, Cookie::default()); @@ -1460,11 +1486,10 @@ impl<'a> Parse<'a, Key> for Key { pp.buffer_unread_content()?; match pp.next()? { - (Packet::PublicKey(o), PacketParserResult::EOF(_)) - | (Packet::PublicSubkey(o), PacketParserResult::EOF(_)) - | (Packet::SecretKey(o), PacketParserResult::EOF(_)) - | (Packet::SecretSubkey(o), PacketParserResult::EOF(_)) => - Ok(o), + (Packet::PublicKey(o), PacketParserResult::EOF(_)) => Ok(o.into()), + (Packet::PublicSubkey(o), PacketParserResult::EOF(_)) => Ok(o.into()), + (Packet::SecretKey(o), PacketParserResult::EOF(_)) => Ok(o.into()), + (Packet::SecretSubkey(o), PacketParserResult::EOF(_)) => Ok(o.into()), (p, PacketParserResult::EOF(_)) => Err(Error::InvalidOperation( format!("Not a Key packet: {:?}", p)).into()), diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index c2225f0d..6d7b7c64 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -27,6 +27,7 @@ use crate::{ packet::{ BodyLength, ctb::CTB, + key, Key, Literal, OnePassSig, @@ -146,7 +147,10 @@ pub enum VerificationResult<'a> { /// /// [web of trust]: https://en.wikipedia.org/wiki/Web_of_trust GoodChecksum(Signature, - &'a TPK, &'a Key, Option<&'a Signature>, RevocationStatus<'a>), + &'a TPK, + &'a key::UnspecifiedPublic, + Option<&'a Signature>, + RevocationStatus<'a>), /// Unable to verify the signature because the key is missing. MissingKey(Signature), /// The signature is bad. @@ -467,6 +471,20 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> { helper: H, t: time::Tm) -> Result<Verifier<'a, H>> { + fn can_sign<P, R>(key: &Key<P, R>, sig: Option<&Signature>, t: time::Tm) + -> bool + where P: key::KeyParts, R: key::KeyRole + { + if let Some(sig) = sig { + sig.key_flags().can_sign() + // Check expiry. + && sig.signature_alive_at(t) + && sig.key_alive_at(key, t) + } else { + false + } + } + let mut ppr = PacketParser::from_buffered_reader(bio)?; let mut v = Verifier { @@ -499,25 +517,14 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> { v.tpks = v.helper.get_public_keys(&issuers)?; for (i, tpk) in v.tpks.iter().enumerate() { - let can_sign = |key: &Key, sig: Option<&Signature>| -> bool { - if let Some(sig) = sig { - sig.key_flags().can_sign() - // Check expiry. - && sig.signature_alive_at(t) - && sig.key_alive_at(key, t) - } else { - false - } - }; - if can_sign(tpk.primary().key(), - tpk.primary_key_signature()) { + tpk.primary_key_signature(), t) { v.keys.insert(tpk.keyid(), (i, 0)); } for (j, skb) in tpk.subkeys().enumerate() { let key = skb.key(); - if can_sign(key, skb.binding_signature()) { + if can_sign(key, skb.binding_signature(), t) { v.keys.insert(key.keyid(), (i, j + 1)); } @@ -1284,7 +1291,9 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { v.tpks = v.helper.get_public_keys(&issuers)?; for (i, tpk) in v.tpks.iter().enumerate() { - let can_sign = |key: &Key, sig: Option<&Signature>| -> bool { + let can_sign = |key: &key::UnspecifiedKey, + sig: Option<&Signature>| -> bool + { if let Some(sig) = sig { sig.key_flags().can_sign() // Check expiry. @@ -1295,14 +1304,14 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { } }; - if can_sign(tpk.primary().key(), + if can_sign(tpk.primary().key().into(), tpk.primary_key_signature()) { v.keys.insert(tpk.keyid(), (i, 0)); } for (j, skb) in tpk.subkeys().enumerate() { let key = skb.key(); - if can_sign(key, skb.binding_signature()) { + if can_sign(key.into(), skb.binding_signature()) { v.keys.insert(key.keyid(), (i, j + 1)); } } @@ -1455,7 +1464,9 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { (sig) } else { VerificationResult::GoodChecksum - (sig, tpk, key, binding, + (sig, tpk, + key, + binding, revocation) } } else { @@ -1807,7 +1818,7 @@ mod test { let mut buf = vec![]; { let key = tpk.keys_all().signing_capable().nth(0).unwrap().2; - let mut keypair = key.clone().into_keypair().unwrap(); + let mut keypair = key.clone().mark_parts_secret().into_keypair().unwrap(); let m = Message::new(&mut buf); let signer = Signer::new(m, vec![&mut keypair], None).unwrap(); |