summaryrefslogtreecommitdiffstats
path: root/openpgp
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
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')
-rw-r--r--openpgp/examples/decrypt-with.rs7
-rw-r--r--openpgp/examples/generate-encrypt-decrypt.rs2
-rw-r--r--openpgp/examples/generate-sign-verify.rs2
-rw-r--r--openpgp/examples/notarize.rs6
-rw-r--r--openpgp/examples/sign-detached.rs4
-rw-r--r--openpgp/examples/sign.rs6
-rw-r--r--openpgp/src/autocrypt.rs7
-rw-r--r--openpgp/src/crypto/asymmetric.rs52
-rw-r--r--openpgp/src/crypto/ecdh.rs43
-rw-r--r--openpgp/src/crypto/hash.rs33
-rw-r--r--openpgp/src/crypto/sexp.rs13
-rw-r--r--openpgp/src/lib.rs10
-rw-r--r--openpgp/src/message/mod.rs4
-rw-r--r--openpgp/src/packet/key/mod.rs (renamed from openpgp/src/packet/key.rs)614
-rw-r--r--openpgp/src/packet/mod.rs53
-rw-r--r--openpgp/src/packet/pkesk.rs36
-rw-r--r--openpgp/src/packet/prelude.rs1
-rw-r--r--openpgp/src/packet/signature/mod.rs162
-rw-r--r--openpgp/src/packet/signature/subpacket.rs27
-rw-r--r--openpgp/src/parse/parse.rs61
-rw-r--r--openpgp/src/parse/stream.rs49
-rw-r--r--openpgp/src/serialize/mod.rs34
-rw-r--r--openpgp/src/serialize/stream.rs80
-rw-r--r--openpgp/src/serialize/tpk.rs63
-rw-r--r--openpgp/src/tpk/bindings.rs105
-rw-r--r--openpgp/src/tpk/builder.rs25
-rw-r--r--openpgp/src/tpk/keyiter.rs60
-rw-r--r--openpgp/src/tpk/mod.rs96
-rw-r--r--openpgp/src/tpk/parser/grammar.lalrpop29
-rw-r--r--openpgp/src/tpk/parser/lexer.rs6
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/sr