summaryrefslogtreecommitdiffstats
path: root/openpgp/src/packet/key.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/packet/key.rs')
-rw-r--r--openpgp/src/packet/key.rs2006
1 files changed, 2006 insertions, 0 deletions
diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs
new file mode 100644
index 00000000..722bead4
--- /dev/null
+++ b/openpgp/src/packet/key.rs
@@ -0,0 +1,2006 @@
+//! Public key, public subkey, private key and private subkey packets.
+//! Key variants.
+//!
+//! There are four variants of OpenPGP keys: public keys, public
+//! subkeys, secret keys, and secret subkeys. These are based on
+//! the cross product of two attributes: whether the key contains
+//! any secret key material, and the key's role.
+//!
+//! The underlying representation of these four variants is
+//! identical (even a public key and a secret key are the same:
+//! the public key variant just contains 0 bits of secret key
+//! material), and many (but not all) operations can be done on
+//! all four variants.
+//!
+//! We separate these variants into two types: parts (public or
+//! secret) and roles (primary or secondary). We also add
+//! unspecified variants, because sometimes we want a slice of
+//! keys, and we don't care about the key's role. For instance,
+//! when iterating over all of the keys in a Cert, we want the
+//! primary and the subkeys. These can't be put in the same slice
+//! without first wrapping them, which is awkward.
+//!
+//! For the most part, the user doesn't need to worry about the
+//! markers. Occasionally, it is necessary to change a key's markers.
+//! For these cases, it is possible to just use the `From` trait to
+//! get the require markers. But, it is also possible to explicitly
+//! set markers. Compare:
+//!
+//! ```rust
+//! # extern crate sequoia_openpgp as openpgp;
+//! # use openpgp::Result;
+//! # use openpgp::parse::{Parse, PacketParserResult, PacketParser};
+//! # use openpgp::cert::prelude::*;
+//! use openpgp::packet::{Key, key};
+//!
+//! # fn main() { f().unwrap(); }
+//! # fn f() -> Result<()>
+//! # {
+//! # let (cert, _) = CertBuilder::new()
+//! # .set_cipher_suite(CipherSuite::Cv25519)
+//! # .generate()?;
+//! // Get a handle to the Cert's primary key that allows using the
+//! // secret key material.
+//! use std::convert::TryInto;
+//! let sk: &Key<key::SecretParts, key::PrimaryRole> = cert.primary_key().key().try_into()?;
+//!
+//! // Make the conversion explicit.
+//! let sk = cert.primary_key().key().mark_parts_secret_ref()?;
+//! # Ok(())
+//! # }
+//! ```
+
+use std::fmt;
+use std::cmp::Ordering;
+use std::convert::{TryFrom, TryInto};
+use std::time;
+
+use crate::Error;
+use crate::cert::prelude::*;
+use crate::crypto::{self, mem::{self, Protected}, mpis, hash::Hash};
+use crate::packet;
+use crate::packet::prelude::*;
+use crate::PublicKeyAlgorithm;
+use crate::SymmetricAlgorithm;
+use crate::HashAlgorithm;
+use crate::types::{Curve, Timestamp};
+use crate::crypto::S2K;
+use crate::Result;
+use crate::crypto::Password;
+use crate::KeyID;
+use crate::Fingerprint;
+use crate::KeyHandle;
+
+/// A marker trait that indicates whether a `Key` only contains
+/// public key material or *may* also contains secret key
+/// material.
+pub trait KeyParts: fmt::Debug {
+ /// Converts a key with unspecified parts into this kind of key.
+ fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
+ -> Result<Key<Self, R>>
+ where Self: Sized;
+
+ /// Converts a reference to a key with unspecified parts into this
+ /// kind of key reference.
+ fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
+ -> Result<&Key<Self, R>>
+ where Self: Sized;
+
+ /// Converts a key bundle with unspecified parts into this kind of
+ /// key bundle.
+ fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
+ -> Result<KeyBundle<Self, R>>
+ where Self: Sized;
+
+ /// Converts a reference to a key bundle with unspecified parts
+ /// into this kind of key bundle reference.
+ fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
+ -> Result<&KeyBundle<Self, R>>
+ where Self: Sized;
+
+ /// Converts a key amalgamation with unspecified parts into this
+ /// kind of key amalgamation.
+ fn convert_key_amalgamation<'a, R: KeyRole>(
+ ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
+ -> Result<ComponentAmalgamation<'a, Key<Self, R>>>
+ where Self: Sized;
+
+ /// Converts a reference to a key amalgamation with unspecified
+ /// parts into this kind of key amalgamation reference.
+ fn convert_key_amalgamation_ref<'a, R: KeyRole>(
+ ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
+ -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>>
+ where Self: Sized;
+}
+
+/// A marker trait that indicates whether a `Key` is a primary key or
+/// subordinate key (i.e., a subkey).
+pub trait KeyRole: fmt::Debug {
+ /// Converts a key with unspecified role into this kind of key.
+ fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
+ -> Key<P, Self>
+ where Self: Sized;
+
+ /// Converts a reference to a key with unspecified role into this
+ /// kind of key reference.
+ fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
+ -> &Key<P, Self>
+ where Self: Sized;
+
+ /// Converts a key bundle with unspecified role into this kind of
+ /// key bundle.
+ fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
+ -> KeyBundle<P, Self>
+ where Self: Sized;
+
+ /// Converts a reference to a key bundle with unspecified role
+ /// into this kind of key bundle reference.
+ fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
+ -> &KeyBundle<P, Self>
+ where Self: Sized;
+}
+
+/// Indicates that a `Key` should be treated like a public key.
+///
+/// Note: this doesn't indicate whether the data structure contains
+/// secret key material; it indicates whether any secret key material
+/// should be ignored. For instance, when exporting a key with the
+/// `PublicParts` marker, secret key material will *not* be exported.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct PublicParts;
+impl KeyParts for PublicParts {
+ fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
+ -> Result<Key<Self, R>> {
+ Ok(key.into())
+ }
+
+ fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
+ -> Result<&Key<Self, R>> {
+ Ok(key.into())
+ }
+
+ fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
+ -> Result<KeyBundle<Self, R>> {
+ Ok(bundle.into())
+ }
+
+ fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
+ -> Result<&KeyBundle<Self, R>> {
+ Ok(bundle.into())
+ }
+
+ fn convert_key_amalgamation<'a, R: KeyRole>(
+ ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
+ -> Result<ComponentAmalgamation<'a, Key<Self, R>>> {
+ Ok(ka.into())
+ }
+
+ /// Converts a reference to a key amalgamation with unspecified
+ /// parts into this kind of key amalgamation reference.
+ fn convert_key_amalgamation_ref<'a, R: KeyRole>(
+ ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
+ -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> {
+ Ok(ka.into())
+ }
+}
+
+/// Indicates that a `Key` should be treated like a secret key.
+///
+/// Note: this doesn't indicate whether the data structure contains
+/// secret key material; it indicates whether any secret key material
+/// should be used. For instance, when exporting a key with the
+/// `SecretParts` marker, secret key material will be exported.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct SecretParts;
+impl KeyParts for SecretParts {
+ fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
+ -> Result<Key<Self, R>>{
+ key.try_into()
+ }
+
+ fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
+ -> Result<&Key<Self, R>> {
+ key.try_into()
+ }
+
+ fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
+ -> Result<KeyBundle<Self, R>> {
+ bundle.try_into()
+ }
+
+ fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
+ -> Result<&KeyBundle<Self, R>> {
+ bundle.try_into()
+ }
+
+ fn convert_key_amalgamation<'a, R: KeyRole>(
+ ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
+ -> Result<ComponentAmalgamation<'a, Key<Self, R>>> {
+ ka.try_into()
+ }
+
+ /// Converts a reference to a key amalgamation with unspecified
+ /// parts into this kind of key amalgamation reference.
+ fn convert_key_amalgamation_ref<'a, R: KeyRole>(
+ ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
+ -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> {
+ ka.try_into()
+ }
+}
+
+/// Indicates that a `Key`'s parts are unspecified.
+///
+/// Neither public key-specific nor secret key-specific operations are
+/// allowed on such keys.
+///
+/// For instance, it is not possible to export a key with the
+/// `UnspecifiedParts` marker, because it is unclear how to treat any
+/// secret key material. To export such a key, you need to use a
+/// different `KeyParts` marker.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct UnspecifiedParts;
+impl KeyParts for UnspecifiedParts {
+ fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
+ -> Result<Key<Self, R>> {
+ Ok(key)
+ }
+
+ fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
+ -> Result<&Key<Self, R>> {
+ Ok(key)
+ }
+
+ fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
+ -> Result<KeyBundle<Self, R>> {
+ Ok(bundle)
+ }
+
+ fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
+ -> Result<&KeyBundle<Self, R>> {
+ Ok(bundle)
+ }
+
+ fn convert_key_amalgamation<'a, R: KeyRole>(
+ ka: ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
+ -> Result<ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>> {
+ Ok(ka.into())
+ }
+
+ /// Converts a reference to a key amalgamation with unspecified
+ /// parts into this kind of key amalgamation reference.
+ fn convert_key_amalgamation_ref<'a, R: KeyRole>(
+ ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
+ -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> {
+ Ok(ka.into())
+ }
+}
+
+/// Indicates that a `Key` should treated like a primary key.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct PrimaryRole;
+impl KeyRole for PrimaryRole {
+ fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
+ -> Key<P, Self> {
+ key.into()
+ }
+
+ fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
+ -> &Key<P, Self> {
+ key.into()
+ }
+
+ fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
+ -> KeyBundle<P, Self> {
+ bundle.into()
+ }
+
+ fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
+ -> &KeyBundle<P, Self> {
+ bundle.into()
+ }
+}
+
+/// Indicates that a `Key` should treated like a subkey key.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct SubordinateRole;
+impl KeyRole for SubordinateRole {
+ fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
+ -> Key<P, Self> {
+ key.into()
+ }
+
+ fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
+ -> &Key<P, Self> {
+ key.into()
+ }
+
+ fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
+ -> KeyBundle<P, Self> {
+ bundle.into()
+ }
+
+ fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
+ -> &KeyBundle<P, Self> {
+ bundle.into()
+ }
+}
+
+/// Indicates that a `Key`'s role is unknown.
+///
+/// Neither primary key-specific nor subkey-specific operations
+/// are allowed.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
+pub struct UnspecifiedRole;
+impl KeyRole for UnspecifiedRole {
+ fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
+ -> Key<P, Self> {
+ key
+ }
+
+ fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
+ -> &Key<P, Self> {
+ key
+ }
+
+ fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
+ -> KeyBundle<P, Self> {
+ bundle
+ }
+
+ fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
+ -> &KeyBundle<P, Self> {
+ bundle
+ }
+}
+
+/// A Public Key.
+pub(crate) type PublicKey = Key<PublicParts, PrimaryRole>;
+/// A Public Subkey.
+pub(crate) type PublicSubkey = Key<PublicParts, SubordinateRole>;
+/// A Secret Key.
+pub(crate) type SecretKey = Key<SecretParts, PrimaryRole>;
+/// A Secret Subkey.
+pub(crate) type SecretSubkey = Key<SecretParts, SubordinateRole>;
+
+/// A key with public parts, and an unspecified role
+/// (`UnspecifiedRole`).
+#[allow(dead_code)]
+pub(crate) type UnspecifiedPublic = Key<PublicParts, UnspecifiedRole>;
+/// A key with secret parts, and an unspecified role
+/// (`UnspecifiedRole`).
+pub(crate) type UnspecifiedSecret = Key<SecretParts, UnspecifiedRole>;
+
+/// A primary key with unspecified parts (`UnspecifiedParts`).
+#[allow(dead_code)]
+pub(crate) type UnspecifiedPrimary = Key<UnspecifiedParts, PrimaryRole>;
+/// A subkey key with unspecified parts (`UnspecifiedParts`).
+#[allow(dead_code)]
+pub(crate) type UnspecifiedSecondary = Key<UnspecifiedParts, SubordinateRole>;
+
+/// A key whose parts and role are unspecified
+/// (`UnspecifiedParts`, `UnspecifiedRole`).
+#[allow(dead_code)]
+pub(crate) type UnspecifiedKey = Key<UnspecifiedParts, UnspecifiedRole>;
+
+macro_rules! convert {
+ ( $x:ident ) => {
+ // XXX: This is ugly, but how can we do better?
+ unsafe { std::mem::transmute($x) }
+ }
+}
+
+macro_rules! convert_ref {
+ ( $x:ident ) => {
+ // XXX: This is ugly, but how can we do better?
+ unsafe { std::mem::transmute($x) }
+ }
+}
+
+// Make it possible to go from an arbitrary Key<P, R> to an
+// arbitrary Key<P', R'> (or &Key<P, R> to &Key<P', R'>) in a
+// single .into().
+//
+// To allow the programmer to make the intent clearer, also
+// provide explicit conversion function.
+
+// In principle, this is as easy as the following:
+//
+// impl<P, P2, R, R2> From<Key<P, R>> for Key<P2, R2>
+// where P: KeyParts, P2: KeyParts, R: KeyRole, R2: KeyRole
+// {
+// fn from(p: Key<P, R>) -> Self {
+// unimplemented!()
+// }
+// }
+//
+// But that results in:
+//
+// error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<_, _>>` for type `packet::Key<_, _>`:
+// = note: conflicting implementation in crate `core`:
+// - impl<T> std::convert::From<T> for T;
+//
+// Unfortunately, it's not enough to make one type variable
+// concrete, as the following errors demonstrate:
+//
+// error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<packet::key::PublicParts, _>>` for type `packet::Key<packet::key::PublicParts, _>`:
+// ...
+// = note: conflicting implementation in crate `core`:
+// - impl<T> std::convert::From<T> for T;
+//
+// impl<P, R, R2> From<Key<P, R>> for Key<PublicParts, R2>
+// where P: KeyParts, R: KeyRole, R2: KeyRole
+// {
+// fn from(p: Key<P, R>) -> Self {
+// unimplemented!()
+// }
+// }
+//
+// error[E0119]: conflicting implementations of trait `std::convert::From<packet::Key<packet::key::PublicParts, _>>` for type `packet::Key<packet::key::PublicParts, _>`:
+// --> openpgp/src/packet/key.rs:186:5
+// ...
+// = note: conflicting implementation in crate `core`:
+// - impl<T> std::convert::From<T> for T;
+// impl<P2, R, R2> From<Key<PublicParts, R>> for Key<P2, R2>
+// where P2: KeyParts, R: KeyRole, R2: KeyRole
+// {
+// fn from(p: Key<PublicParts, R>) -> Self {
+// unimplemented!()
+// }
+// }
+//
+// To solve this, we need at least one generic variable to be
+// concrete on both sides of the `From`.
+
+macro_rules! create_part_conversions {
+ ( $Key:ident<$( $l:lifetime ),*; $( $g:ident ),*>) => {
+ create_part_conversions!($Key<$($l),*; $($g),*> where );
+ };
+ ( $Key:ident<$( $l:lifetime ),*; $( $g:ident ),*> where $( $w:ident: $c:path ),* ) => {
+ // Convert between two KeyParts for a constant KeyRole.
+ // Unfortunately, we can't let the KeyRole vary as otherwise we
+ // get conflicting types when we do the same to convert between
+ // two KeyRoles for a constant KeyParts. :(
+ macro_rules! p {
+ ( <$from_parts:ty> -> <$to_parts:ty> ) => {
+ impl<$($l, )* $($g, )* > From<$Key<$($l, )* $from_parts, $($g, )* >> for $Key<$($l, )* $to_parts, $($g, )* >
+ where $($w: $c ),*
+ {
+ fn from(p: $Key<$($l, )* $from_parts, $($g, )* >) -> Self {
+ convert!(p)
+ }
+ }
+
+ impl<$($l, )* $($g, )* > From<&$($l)* $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* $Key<$($l, )* $to_parts, $($g, )* >
+ where $($w: $c ),*
+ {
+ fn from(p: &$($l)* $Key<$($l, )* $from_parts, $($g, )* >) -> Self {
+ convert_ref!(p)
+ }
+ }
+ }
+ }
+
+ // Likewise, but using TryFrom.
+ macro_rules! p_try {
+ ( <$from_parts:ty> -> <$to_parts:ty>) => {
+ impl<$($l, )* $($g, )* > TryFrom<$Key<$($l, )* $from_parts, $($g, )* >> for $Key<$($l, )* $to_parts, $($g, )* >
+ where $($w: $c ),*
+ {
+ type Error = anyhow::Error;
+ fn try_from(p: $Key<$($l, )* $from_parts, $($g, )* >) -> Result<Self> {
+ p.mark_parts_secret()
+ }
+ }
+
+ impl<$($l, )* $($g, )* > TryFrom<&$($l)* $Key<$($l, )* $from_parts, $($g, )* >> for &$($l)* $Key<$($l, )* $to_parts, $($g, )* >
+ where $($w: $c ),*
+ {
+ type Error = anyhow::Error;
+ fn try_from(p: &$($l)* $Key<$($l, )* $from_parts, $($g, )* >) -> Result<Self> {
+ if p.has_secret() {
+ Ok(convert_ref!(p))
+ } else {
+ Err(Error::InvalidArgument("No secret key".into())
+ .into())
+ }
+ }
+ }
+ }
+ }
+
+
+ p_try!(<PublicParts> -> <SecretParts>);
+ p!(<PublicParts> -> <UnspecifiedParts>);
+
+ p!(<SecretParts> -> <PublicParts>);
+ p!(<SecretParts> -> <UnspecifiedParts>);
+
+ p!(<UnspecifiedParts> -> <PublicParts>);
+ p_try!(<UnspecifiedParts> -> <SecretParts>);
+
+
+ impl<$($l, )* P, $($g, )*> $Key<$($l, )* P, $($g, )*> where P: KeyParts, $($w: $c ),*
+ {
+ /// Changes the key's parts tag to `PublicParts`.
+ pub fn mark_parts_public(self) -> $Key<$($l, )* PublicParts, $($g, )*> {
+ // Ideally, we'd use self.into() to do the actually
+ // conversion. But, because P is not concrete, we get the
+ // following error:
+ //
+ // error[E0277]: the trait bound `packet::Key<packet::key::PublicParts, R>: std::convert::From<packet::Key<P, R>>` is not satisfied
+ // --> openpgp/src/packet/key.rs:401:18
+ // |
+ // 401 | self.into()
+ // | ^^^^ the trait `std::convert::From<packet::Key<P, R>>` is not implemented for `packet::Key<packet::key::PublicParts, R>`
+ // |
+ // = help: consider adding a `where packet::Key<packet::key::PublicParts, R>: std::convert::From<packet::Key<P, R>>` bound
+ // = note: required because of the requirements on the impl of `std::convert::Into<packet::Key<packet::key::PublicParts, R>>` for `packet::Key<P, R>`
+ //
+ // But we can't implement implement `From<Key<P, R>>` for
+ // `Key<PublicParts, R>`, because that conflicts with a
+ // standard conversion! (See the comment for the `p`
+ // macro above.)
+ //
+ // Adding the trait bound is annoying, because then we'd
+ // have to add it everywhere that we use into.
+ convert!(self)
+ }
+
+ /// Changes the key's parts tag to `PublicParts`.
+ pub fn mark_parts_public_ref(&$($l)* self) -> &$($l)* $Key<$($l, )* PublicParts, $($g, )*> {
+ convert_ref!(self)
+ }
+
+ /// Changes the key's parts tag to `SecretParts`.
+ pub fn mark_parts_secret(self) -> Result<$Key<$($l, )* SecretParts, $($g, )*>> {
+ if self.has_secret() {
+ Ok(convert!(self))
+ } else {
+ Err(Error::InvalidArgument("No secret key".into()).into())
+ }
+ }
+
+ /// Changes the key's parts tag to `SecretParts`.
+ pub fn mark_parts_secret_ref(&$($l)* self) -> Result<&$($l)* $Key<$($l, )* SecretParts, $($g, )*>>
+ {
+ if self.has_secret() {
+ Ok(convert_ref!(self))
+ } else {
+ Err(Error::InvalidArgument("No secret key".into()).into())
+ }
+ }
+
+ /// Changes the key's parts tag to `UnspecifiedParts`.
+ pub fn mark_parts_unspecified(self) -> $Key<$($l, )* UnspecifiedParts, $($g, )*> {
+ convert!(self)
+ }
+
+ /// Changes the key's parts tag to `UnspecifiedParts`.
+ pub fn mark_parts_unspecified_ref(&$($l)* self) -> &$Key<$($l, )* UnspecifiedParts, $($g, )*> {
+ convert_ref!(self)
+ }
+ }
+ }
+}
+
+macro_rules! create_role_conversions {
+ ( $Key:ident<$( $l:lifetime ),*> ) => {
+ // Convert between two KeyRoles for a constant KeyParts. See
+ // the comment for the p macro above.
+ macro_rules! r {
+ ( <$from_role:ty> -> <$to_role:ty>) => {
+ impl<$($l, )* P> From<$Key<$($l, )* P, $from_role>> for $Key<$($l, )* P, $to_role>
+ where P: KeyParts
+ {
+ fn from(p: $Key<$($l, )* P, $from_role>) -> Self {
+ convert!(p)
+ }
+ }
+
+ impl<$($l, )* P> From<&$($l)* $Key<$($l, )* P, $from_role>> for &$($l)* $Key<$($l, )* P, $to_role>
+ where P: KeyParts
+ {
+ fn from(p: &$($l)* $Key<$($l, )* P, $from_role>) -> Self {
+ convert_ref!(p)
+ }
+ }
+ }
+ }
+
+ r!(<PrimaryRole> -> <SubordinateRole>);
+ r!(<PrimaryRole> -> <UnspecifiedRole>);
+
+ r!(<SubordinateRole> -> <PrimaryRole>);
+ r!(<SubordinateRole> -> <UnspecifiedRole>);
+
+ r!(<UnspecifiedRole> -> <PrimaryRole>);
+ r!(<UnspecifiedRole> -> <SubordinateRole>);
+ }
+}
+
+macro_rules! create_conversions {
+ ( $Key:ident<$( $l:lifetime ),*> ) => {
+ create_part_conversions!($Key<$($l ),* ; R> where R: KeyRole);
+ create_role_conversions!($Key<$($l ),* >);
+
+ // We now handle converting both the part and the role at the same
+ // time.
+
+ macro_rules! f {
+ ( <$from_parts:ty, $from_role:ty> -> <$to_parts:ty, $to_role:ty> ) => {
+ impl<$($l ),*> From<$Key<$($l, )* $from_parts, $from_role>> for $Key<$($l, )* $to_parts, $to_role>
+ {
+ fn from(p: $Key<$($l, )* $from_parts, $from_role>) -> Self {
+ convert!(p)
+ }
+ }
+
+ impl<$($l ),*> From<&$($l)* $Key<$($l, )* $from_parts, $from_role>> for &$($l)* $Key<$($l, )* $to_parts, $to_role>
+ {
+ fn from(p: &$($l)* $Key<$from_parts, $from_role>) -> Self {
+ convert_ref!(p)
+ }
+ }
+ }
+ }
+
+ // The calls that are comment out are the calls for the
+ // combinations where either the KeyParts or the KeyRole does not
+ // change.
+
+ //f!(<PublicParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
+ //f!(<PublicParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
+ //f!(<PublicParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
+ //f!(<PublicParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
+ f!(<PublicParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
+ f!(<PublicParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
+ //f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
+ f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
+ f!(<PublicParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
+
+ //f!(<PublicParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
+ //f!(<PublicParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
+ //f!(<PublicParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
+ f!(<PublicParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
+ //f!(<PublicParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
+ f!(<PublicParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
+ f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
+ //f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);
+ f!(<PublicParts, SubordinateRole> -> <UnspecifiedParts, UnspecifiedRole>);
+
+ //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, PrimaryRole>);
+ //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, SubordinateRole>);
+ //f!(<PublicParts, UnspecifiedRole> -> <PublicParts, UnspecifiedRole>);
+ f!(<PublicParts, UnspecifiedRole> -> <SecretParts, PrimaryRole>);
+ f!(<PublicParts, UnspecifiedRole> -> <SecretParts, SubordinateRole>);
+ //f!(<PublicParts, UnspecifiedRole> -> <SecretParts, UnspecifiedRole>);
+ f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, PrimaryRole>);
+ f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, SubordinateRole>);
+ //f!(<PublicParts, UnspecifiedRole> -> <UnspecifiedParts, UnspecifiedRole>);
+
+ //f!(<SecretParts, PrimaryRole> -> <PublicParts, PrimaryRole>);
+ f!(<SecretParts, PrimaryRole> -> <PublicParts, SubordinateRole>);
+ f!(<SecretParts, PrimaryRole> -> <PublicParts, UnspecifiedRole>);
+ //f!(<SecretParts, PrimaryRole> -> <SecretParts, PrimaryRole>);
+ //f!(<SecretParts, PrimaryRole> -> <SecretParts, SubordinateRole>);
+ //f!(<SecretParts, PrimaryRole> -> <SecretParts, UnspecifiedRole>);
+ //f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, PrimaryRole>);
+ f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, SubordinateRole>);
+ f!(<SecretParts, PrimaryRole> -> <UnspecifiedParts, UnspecifiedRole>);
+
+ f!(<SecretParts, SubordinateRole> -> <PublicParts, PrimaryRole>);
+ //f!(<SecretParts, SubordinateRole> -> <PublicParts, SubordinateRole>);
+ f!(<SecretParts, SubordinateRole> -> <PublicParts, UnspecifiedRole>);
+ //f!(<SecretParts, SubordinateRole> -> <SecretParts, PrimaryRole>);
+ //f!(<SecretParts, SubordinateRole> -> <SecretParts, SubordinateRole>);
+ //f!(<SecretParts, SubordinateRole> -> <SecretParts, UnspecifiedRole>);
+ f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, PrimaryRole>);
+ //f!(<SecretParts, SubordinateRole> -> <UnspecifiedParts, SubordinateRole>);