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 | |
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')
30 files changed, 1269 insertions, 421 deletions
diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs index 6562b3db..ad8920c0 100644 --- a/openpgp/examples/decrypt-with.rs +++ b/openpgp/examples/decrypt-with.rs @@ -10,6 +10,7 @@ extern crate sequoia_openpgp as openpgp; use crate::openpgp::crypto::{KeyPair, SessionKey}; use crate::openpgp::constants::SymmetricAlgorithm; +use crate::openpgp::packet::key; use crate::openpgp::parse::{ Parse, stream::{ @@ -49,7 +50,7 @@ pub fn main() { /// keys for the signature verification and implements the /// verification policy. struct Helper { - keys: HashMap<openpgp::KeyID, KeyPair>, + keys: HashMap<openpgp::KeyID, KeyPair<key::UnspecifiedRole>>, } impl Helper { @@ -64,7 +65,9 @@ impl Helper { .unwrap_or(false) { // This only works for unencrypted secret keys. - if let Ok(keypair) = key.clone().into_keypair() { + if let Ok(keypair) + = key.clone().mark_parts_secret().into_keypair() + { keys.insert(key.keyid(), keypair); } } diff --git a/openpgp/examples/generate-encrypt-decrypt.rs b/openpgp/examples/generate-encrypt-decrypt.rs index c0360f33..301a4340 100644 --- a/openpgp/examples/generate-encrypt-decrypt.rs +++ b/openpgp/examples/generate-encrypt-decrypt.rs @@ -114,7 +114,7 @@ impl<'a> DecryptionHelper for Helper<'a> { .unwrap(); // The secret key is not encrypted. - let mut pair = key.into_keypair().unwrap(); + let mut pair = key.mark_parts_secret().into_keypair().unwrap(); pkesks[0].decrypt(&mut pair) .and_then(|(algo, session_key)| decrypt(algo, &session_key)) diff --git a/openpgp/examples/generate-sign-verify.rs b/openpgp/examples/generate-sign-verify.rs index cc350a63..36582e6b 100644 --- a/openpgp/examples/generate-sign-verify.rs +++ b/openpgp/examples/generate-sign-verify.rs @@ -41,7 +41,7 @@ fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::TPK) -> openpgp::Result<()> { // Get the keypair to do the signing from the TPK. let mut keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2 - .clone().into_keypair()?; + .clone().mark_parts_secret().into_keypair()?; // Start streaming an OpenPGP message. let message = Message::new(sink); diff --git a/openpgp/examples/notarize.rs b/openpgp/examples/notarize.rs index 54c7fa79..271e9b42 100644 --- a/openpgp/examples/notarize.rs +++ b/openpgp/examples/notarize.rs @@ -43,7 +43,7 @@ fn main() { .expect("decryption failed"); } n += 1; - key.into_keypair().unwrap() + key.mark_parts_secret().into_keypair().unwrap() }); } @@ -64,7 +64,9 @@ fn main() { // Now, create a signer that emits a detached signature. let mut signer = Signer::new( message, - keys.iter_mut().map(|s| -> &mut dyn crypto::Signer { s }).collect(), + keys.iter_mut() + .map(|s| -> &mut dyn crypto::Signer<_> { s }) + .collect(), None) .expect("Failed to create signer"); diff --git a/openpgp/examples/sign-detached.rs b/openpgp/examples/sign-detached.rs index 30620eb3..d4d8d40d 100644 --- a/openpgp/examples/sign-detached.rs +++ b/openpgp/examples/sign-detached.rs @@ -38,7 +38,7 @@ fn main() { .expect("decryption failed"); } n += 1; - key.into_keypair().unwrap() + key.mark_parts_secret().into_keypair().unwrap() }); } @@ -59,7 +59,7 @@ fn main() { // Now, create a signer that emits a detached signature. let mut signer = Signer::detached( message, - keys.iter_mut().map(|s| -> &mut dyn crypto::Signer { s }).collect(), + keys.iter_mut().map(|s| -> &mut dyn crypto::Signer<_> { s }).collect(), None) .expect("Failed to create signer"); diff --git a/openpgp/examples/sign.rs b/openpgp/examples/sign.rs index cfd9c136..bdb29c4c 100644 --- a/openpgp/examples/sign.rs +++ b/openpgp/examples/sign.rs @@ -38,7 +38,7 @@ fn main() { .expect("decryption failed"); } n += 1; - key.into_keypair().unwrap() + key.mark_parts_secret().into_keypair().unwrap() }); } @@ -59,7 +59,9 @@ fn main() { // Now, create a signer that emits a signature. let signer = Signer::new( message, - keys.iter_mut().map(|s| -> &mut dyn crypto::Signer { s }).collect(), + keys.iter_mut() + .map(|s| -> &mut dyn crypto::Signer<_> { s }) + .collect(), None) .expect("Failed to create signer"); diff --git a/openpgp/src/autocrypt.rs b/openpgp/src/autocrypt.rs index b15fddbf..39d374d8 100644 --- a/openpgp/src/autocrypt.rs +++ b/openpgp/src/autocrypt.rs @@ -101,13 +101,13 @@ impl AutocryptHeader { -> Result<Self> where P: Into<Option<&'a str>> { - use crate::packet::Tag; + use crate::packet::key; // Minimize TPK. let mut acc = Vec::new(); // The primary key and the most recent selfsig. - acc.push(tpk.primary().key().clone().into_packet(Tag::PublicKey)?); + acc.push(tpk.primary().key().clone().into()); tpk.selfsigs().iter().take(1) .for_each(|s| acc.push(s.clone().into())); @@ -120,7 +120,8 @@ impl AutocryptHeader { continue; } - acc.push(skb.key().clone().into_packet(Tag::PublicSubkey)?); + let k : key::PublicSubkey = skb.key().clone(); + acc.push(k.into()); skb.selfsigs().iter().take(1) .for_each(|s| acc.push(s.clone().into())); } diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs index af8ea7f0..9232bd14 100644 --- a/openpgp/src/crypto/asymmetric.rs +++ b/openpgp/src/crypto/asymmetric.rs @@ -2,7 +2,7 @@ use nettle::{dsa, ecc, ecdsa, ed25519, rsa, Yarrow}; -use crate::packet::{self, Key}; +use crate::packet::{self, key, Key}; use crate::crypto::SessionKey; use crate::crypto::mpis::{self, MPI}; use crate::constants::{Curve, HashAlgorithm}; @@ -16,9 +16,11 @@ use crate::Result; /// signature. Using this trait allows Sequoia to perform all /// operations involving signing to use a variety of secret key /// storage mechanisms (e.g. smart cards). -pub trait Signer { +pub trait Signer<R> + where R: key::KeyRole +{ /// Returns a reference to the public key. - fn public(&self) -> &Key; + fn public(&self) -> &Key<key::PublicParts, R>; /// Creates a signature over the `digest` produced by `hash_algo`. fn sign(&mut self, hash_algo: HashAlgorithm, digest: &[u8]) @@ -31,9 +33,11 @@ pub trait Signer { /// ciphertext. Using this trait allows Sequoia to perform all /// operations involving decryption to use a variety of secret key /// storage mechanisms (e.g. smart cards). -pub trait Decryptor { +pub trait Decryptor<R> + where R: key::KeyRole +{ /// Returns a reference to the public key. - fn public(&self) -> &Key; + fn public(&self) -> &Key<key::PublicParts, R>; /// Decrypts `ciphertext`, returning the plain session key. fn decrypt(&mut self, ciphertext: &mpis::Ciphertext) @@ -49,14 +53,21 @@ pub trait Decryptor { /// [`Signer`]: trait.Signer.html /// [`Decryptor`]: trait.Decryptor.html #[derive(Clone)] -pub struct KeyPair { - public: Key, +pub struct KeyPair<R> + where R: key::KeyRole +{ + public: Key<key::PublicParts, R>, secret: packet::key::Unencrypted, } -impl KeyPair { +impl<R> KeyPair<R> + where R: key::KeyRole +{ /// Creates a new key pair. - pub fn new(public: Key, secret: packet::key::Unencrypted) -> Result<Self> { + pub fn new(public: Key<key::PublicParts, R>, + secret: packet::key::Unencrypted) + -> Result<Self> + { Ok(Self { public: public, secret: secret, @@ -64,7 +75,7 @@ impl KeyPair { } /// Returns a reference to the public key. - pub fn public(&self) -> &Key { + pub fn public(&self) -> &Key<key::PublicParts, R> { &self.public } @@ -74,8 +85,10 @@ impl KeyPair { } } -impl Signer for KeyPair { - fn public(&self) -> &Key { +impl<R> Signer<R> for KeyPair<R> + where R: key::KeyRole +{ + fn public(&self) -> &Key<key::PublicParts, R> { &self.public } @@ -202,8 +215,10 @@ impl Signer for KeyPair { } } -impl Decryptor for KeyPair { - fn public(&self) -> &Key { +impl<R> Decryptor<R> for KeyPair<R> + where R: key::KeyRole +{ + fn public(&self) -> &Key<key::PublicParts, R> { &self.public } @@ -248,11 +263,12 @@ impl Decryptor for KeyPair { } } -impl From<KeyPair> for packet::Key { - fn from(p: KeyPair) -> Self { +impl<R> From<KeyPair<R>> for Key<key::SecretParts, R> + where R: key::KeyRole +{ + fn from(p: KeyPair<R>) -> Self { let (mut key, secret) = (p.public, p.secret); key.set_secret(Some(secret.into())); - key + key.mark_parts_secret() } - } diff --git a/openpgp/src/crypto/ecdh.rs b/openpgp/src/crypto/ecdh.rs index a51362b6..9b8ad9e0 100644 --- a/openpgp/src/crypto/ecdh.rs +++ b/openpgp/src/crypto/ecdh.rs @@ -1,7 +1,10 @@ //! Elliptic Curve Diffie-Hellman. use crate::Error; -use crate::packet::Key; +use crate::packet::{ + Key, + key, +}; use crate::Result; use crate::constants::{ Curve, @@ -20,7 +23,10 @@ use nettle::{cipher, curve25519, mode, Mode, ecc, ecdh, Yarrow}; /// Wraps a session key using Elliptic Curve Diffie-Hellman. #[allow(non_snake_case)] -pub fn encrypt(recipient: &Key, session_key: &SessionKey) -> Result<Ciphertext> +pub fn encrypt<R>(recipient: &Key<key::PublicParts, R>, + session_key: &SessionKey) + -> Result<Ciphertext> + where R: key::KeyRole { let mut rng = Yarrow::default(); @@ -130,9 +136,11 @@ pub fn encrypt(recipient: &Key, session_key: &SessionKey) -> Result<Ciphertext> /// `VB` is the ephemeral public key (with 0x40 prefix), `S` is the /// shared Diffie-Hellman secret. #[allow(non_snake_case)] -pub fn encrypt_shared(recipient: &Key, session_key: &SessionKey, VB: MPI, - S: &Protected) - -> Result<Ciphertext> +pub fn encrypt_shared<R>(recipient: &Key<key::PublicParts, R>, + session_key: &SessionKey, VB: MPI, + S: &Protected) + -> Result<Ciphertext> + where R: key::KeyRole { match recipient.mpis() { &PublicKey::ECDH{ ref curve, ref hash, ref sym,.. } => { @@ -169,9 +177,12 @@ pub fn encrypt_shared(recipient: &Key, session_key: &SessionKey, VB: MPI, /// Unwraps a session key using Elliptic Curve Diffie-Hellman. #[allow(non_snake_case)] -pub fn decrypt(recipient: &Key, recipient_sec: &SecretKeyMaterial, - ciphertext: &Ciphertext) - -> Result<SessionKey> { +pub fn decrypt<R>(recipient: &Key<key::PublicParts, R>, + recipient_sec: &SecretKeyMaterial, + ciphertext: &Ciphertext) + -> Result<SessionKey> + where R: key::KeyRole +{ match (recipient.mpis(), recipient_sec, ciphertext) { (PublicKey::ECDH { ref curve, ..}, SecretKeyMaterial::ECDH { ref scalar, }, @@ -280,8 +291,11 @@ pub fn decrypt(recipient: &Key, recipient_sec: &SecretKeyMaterial, /// `recipient` is the message receiver's public key, `S` is the /// shared Diffie-Hellman secret used to encrypt `ciphertext`. #[allow(non_snake_case)] -pub fn decrypt_shared(recipient: &Key, S: &Protected, ciphertext: &Ciphertext) - -> Result<SessionKey> +pub fn decrypt_shared<R>(recipient: &Key<key::PublicParts, R>, + S: &Protected, + ciphertext: &Ciphertext) + -> Result<SessionKey> + where R: key::KeyRole { match (recipient.mpis(), ciphertext) { (PublicKey::ECDH { ref curve, ref hash, ref sym, ..}, @@ -308,8 +322,13 @@ pub fn decrypt_shared(recipient: &Key, S: &Protected, ciphertext: &Ciphertext) } } -fn make_param(recipient: &Key, curve: &Curve, hash: &HashAlgorithm, - sym: &SymmetricAlgorithm) -> Vec<u8> { +fn make_param<P, R>(recipient: &Key<P, R>, + curve: &Curve, hash: &HashAlgorithm, + sym: &SymmetricAlgorithm) + -> Vec<u8> + where P: key::KeyParts, + R: key::KeyRole +{ // Param = curve_OID_len || curve_OID || // public_key_alg_ID || 03 || 01 || KDF_hash_ID || // KEK_alg_ID for AESKeyWrap || "Anonymous Sender " || diff --git a/openpgp/src/crypto/hash.rs b/openpgp/src/crypto/hash.rs index 9ace7d38..3ffded0c 100644 --- a/openpgp/src/crypto/hash.rs +++ b/openpgp/src/crypto/hash.rs @@ -3,7 +3,7 @@ use crate::HashAlgorithm; use crate::packet::UserID; use crate::packet::UserAttribute; -use crate::packet::Key; +use crate::packet::key; use crate::packet::key::Key4; use crate::packet::Signature; use crate::packet::signature::{self, Signature4}; @@ -221,7 +221,10 @@ impl Hash for UserAttribute { } } -impl Hash for Key4 { +impl<P, R> Hash for Key4<P, R> + where P: key::KeyParts, + R: key::KeyRole, +{ /// Update the Hash with a hash of the key. fn hash(&self, hash: &mut Context) { // We hash 8 bytes plus the MPIs. But, the len doesn't @@ -335,9 +338,10 @@ impl Hash for signature::Builder { impl Signature { /// Returns the message digest of the primary key binding over the /// specified primary key. - pub fn primary_key_binding_hash<'a, S>(sig: S, key: &Key) + pub fn primary_key_binding_hash<'a, S>(sig: S, key: &key::PublicKey) -> Result<Vec<u8>> - where S: Into<&'a signature::Builder> { + where S: Into<&'a signature::Builder> + { let sig = sig.into(); let mut h = sig.hash_algo().context()?; @@ -352,9 +356,12 @@ impl Signature { /// Returns the message digest of the subkey binding over the /// specified primary key and subkey. - pub fn subkey_binding_hash<'a, S>(sig: S, key: &Key, subkey: &Key) + pub fn subkey_binding_hash<'a, S>(sig: S, + key: &key::PublicKey, + subkey: &key::PublicSubkey) -> Result<Vec<u8>> - where S: Into<&'a signature::Builder> { + where S: Into<&'a signature::Builder> + { let sig = sig.into(); let mut h = sig.hash_algo().context()?; @@ -370,10 +377,12 @@ impl Signature { /// Returns the message digest of the user ID binding over the /// specified primary key, user ID, and signature. - pub fn userid_binding_hash<'a, S>(sig: S, key: &Key, userid: &UserID) + pub fn userid_binding_hash<'a, S>(sig: S, + key: &key::PublicKey, + userid: &UserID) -> Result<Vec<u8>> - where S: Into<&'a signature::Builder> { - + where S: Into<&'a signature::Builder> + { let sig = sig.into(); let mut h = sig.hash_algo().context()?; @@ -388,10 +397,12 @@ impl Signature { /// Returns the message digest of the user attribute binding over /// the specified primary key, user attribute, and signature. - pub fn user_attribute_binding_hash<'a, S>(sig: S, key: &Key, + pub fn user_attribute_binding_hash<'a, S>(sig: S, + key: &key::PublicKey, ua: &UserAttribute) -> Result<Vec<u8>> - where S: Into<&'a signature::Builder> { + where S: Into<&'a signature::Builder> + { let sig = sig.into(); let mut h = sig.hash_algo().context()?; diff --git a/openpgp/src/crypto/sexp.rs b/openpgp/src/crypto/sexp.rs index 454ed5e7..acd970aa 100644 --- a/openpgp/src/crypto/sexp.rs +++ b/openpgp/src/crypto/sexp.rs @@ -90,11 +90,14 @@ impl Sexp { /// Such an expression is returned from gpg-agent's `PKDECRYPT` /// command. `padding` must be set according to the status /// messages sent. - pub fn finish_decryption(&self, - recipient: &crate::packet::Key, - ciphertext: &mpis::Ciphertext, - padding: bool) - -> Result<SessionKey> { + pub fn finish_decryption<R>(&self, + recipient: &crate::packet::Key< + crate::packet::key::PublicParts, R>, + ciphertext: &mpis::Ciphertext, + padding: bool) + -> Result<SessionKey> + where R: crate::packet::key::KeyRole + { use crate::crypto::mpis::PublicKey; let not_a_session_key = || -> failure::Error { Error::MalformedMPI( diff --git a/openpgp/src/lib.rs b/openpgp/src/lib.rs index 1c44137d..54b124c5 100644 --- a/openpgp/src/lib.rs +++ b/openpgp/src/lib.rs @@ -109,7 +109,7 @@ pub mod conversions; pub mod crypto; pub mod packet; -use crate::packet::{BodyLength, Header, Container}; +use crate::packet::{BodyLength, Header, Container, key}; use crate::packet::ctb::{CTB, CTBOld, CTBNew}; pub mod parse; @@ -265,13 +265,13 @@ pub enum Packet { /// One pass signature packet. OnePassSig(packet::OnePassSig), /// Public key packet. - PublicKey(packet::Key), + PublicKey(packet::key::PublicKey), /// Public subkey packet. - PublicSubkey(packet::Key), + PublicSubkey(packet::key::PublicSubkey), /// Public/Secret key pair. - SecretKey(packet::Key), + SecretKey(packet::key::SecretKey), /// Public/Secret subkey pair. - SecretSubkey(packet::Key), + SecretSubkey(packet::key::SecretSubkey), /// Marker packet. Marker(packet::Marker), /// Trust packet. diff --git a/openpgp/src/message/mod.rs b/openpgp/src/message/mod.rs index 877f503b..d36ddb3c 100644 --- a/openpgp/src/message/mod.rs +++ b/openpgp/src/message/mod.rs @@ -798,7 +798,7 @@ mod tests { lit.set_body(b"data".to_vec()); let hash = crate::constants::HashAlgorithm::SHA512; - let key: Key = + let key: key::SecretKey = crate::packet::key::Key4::generate_ecc(true, crate::constants::Curve::Ed25519) .unwrap().into(); let mut pair = key.clone().into_keypair().unwrap(); @@ -910,7 +910,7 @@ mod tests { lit.set_body(b"data".to_vec()); let hash = crate::constants::HashAlgo |