summaryrefslogtreecommitdiffstats
path: root/openpgp/src/parse
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2019-08-12 13:39:14 +0200
committerNeal H. Walfield <neal@pep.foundation>2019-08-23 19:15:13 +0200
commit05cf492f3417fd61f6b1e7dc4913a16fd5f201ea (patch)
treeeca0c2e0481e10b54884a766e7e864020089fe84 /openpgp/src/parse
parent102dea398e920e91b34e5602033c2e7e53c50bb1 (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.rs61
-rw-r--r--openpgp/src/parse/stream.rs49
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();