diff options
Diffstat (limited to 'openpgp/src/packet/key.rs')
-rw-r--r-- | openpgp/src/packet/key.rs | 2006 |
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>); |