diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-02-11 14:56:49 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-02-11 15:04:47 +0100 |
commit | b43dffe86bb7e93bf548b91ff92d0565fe8981fe (patch) | |
tree | b5525f99a04b94f07e955c18f34d615e3e6a157f | |
parent | 30590aae7f98337e84df90a25cca1479b502d322 (diff) |
openpgp: Provide all possible conversions between KeyAmalgamations.
-rw-r--r-- | openpgp/src/cert/key_amalgamation.rs | 190 |
1 files changed, 72 insertions, 118 deletions
diff --git a/openpgp/src/cert/key_amalgamation.rs b/openpgp/src/cert/key_amalgamation.rs index aa12476c..76486456 100644 --- a/openpgp/src/cert/key_amalgamation.rs +++ b/openpgp/src/cert/key_amalgamation.rs @@ -1,6 +1,5 @@ use std::time; use std::time::SystemTime; -use std::convert::TryInto; use std::convert::TryFrom; use std::ops::Deref; @@ -46,90 +45,88 @@ impl<'a, P: key::KeyParts> Deref for KeyAmalgamation<'a, P> { } } -// We can't make the key parts generic, because then the impl would -// conflict with 'impl<T> std::convert::From<T> for T'. -impl<'a> From<KeyAmalgamation<'a, key::PublicParts>> - for KeyAmalgamation<'a, key::UnspecifiedParts> -{ - fn from(ka: KeyAmalgamation<'a, key::PublicParts>) -> Self { - match ka { - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Primary(), - } => - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Primary(), - }, - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Subordinate(bundle), - } => - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Subordinate(bundle.into()), - }, +macro_rules! create_p_conversions { + ( $Key:ident ) => { + macro_rules! convert { + ( $x:ident ) => { + // XXX: This is ugly, but how can we do better? + unsafe { std::mem::transmute($x) } + } } - } -} -impl<'a> From<KeyAmalgamation<'a, key::SecretParts>> - for KeyAmalgamation<'a, key::PublicParts> -{ - fn from(ka: KeyAmalgamation<'a, key::SecretParts>) -> Self { - match ka { - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Primary(), - } => - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Primary(), - }, - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Subordinate(bundle), - } => - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Subordinate(bundle.into()), - }, + macro_rules! convert_ref { + ( $x:ident ) => { + // XXX: This is ugly, but how can we do better? + unsafe { std::mem::transmute($x) } + } } - } -} -impl<'a> TryFrom<KeyAmalgamation<'a, key::PublicParts>> - for KeyAmalgamation<'a, key::SecretParts> -{ - type Error = failure::Error; + // 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<'a> From<$Key<'a, $from_parts>> for $Key<'a, $to_parts> { + fn from(p: $Key<'a, $from_parts>) -> Self { + convert!(p) + } + } - fn try_from(ka: KeyAmalgamation<'a, key::PublicParts>) -> Result<Self> { - Ok(match ka { - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Primary(), - } => { - // Error out if the primary key does not have secret - // key material. - let _ : &KeyBundle<key::SecretParts, key::PrimaryRole> - = (&cert.primary).try_into()?; - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Primary(), + impl<'a> From<&$Key<'a, $from_parts>> for &$Key<'a, $to_parts> { + fn from(p: &$Key<'a, $from_parts>) -> Self { + convert_ref!(p) + } } } - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Subordinate(bundle), - } => - KeyAmalgamation { - cert, - bundle: KeyAmalgamationBundle::Subordinate(bundle.try_into()?), - }, - }) + } + + // Likewise, but using TryFrom. + macro_rules! p_try { + ( <$from_parts:ty> -> <$to_parts:ty>) => { + impl<'a> TryFrom<$Key<'a, $from_parts>> for $Key<'a, $to_parts> { + type Error = failure::Error; + fn try_from(p: $Key<'a, $from_parts>) -> Result<Self> { + if p.secret().is_some() { + Ok(convert!(p)) + } else { + Err(Error::InvalidArgument("No secret key".into()) + .into()) + } + } + } + + impl<'a> TryFrom<&$Key<'a, $from_parts>> for &$Key<'a, $to_parts> { + type Error = failure::Error; + fn try_from(p: &$Key<'a, $from_parts>) -> Result<Self> { + if p.secret().is_some() { + Ok(convert_ref!(p)) + } else { + Err(Error::InvalidArgument("No secret key".into()) + .into()) + } + } + } + } + } + + + p_try!(<key::PublicParts> -> <key::SecretParts>); + p!(<key::PublicParts> -> <key::UnspecifiedParts>); + + p!(<key::SecretParts> -> <key::PublicParts>); + p!(<key::SecretParts> -> <key::UnspecifiedParts>); + + p!(<key::UnspecifiedParts> -> <key::PublicParts>); + p_try!(<key::UnspecifiedParts> -> <key::SecretParts>); } } +create_p_conversions!(KeyAmalgamation); +create_p_conversions!(PrimaryKeyAmalgamation); +create_p_conversions!(ValidKeyAmalgamation); +create_p_conversions!(ValidPrimaryKeyAmalgamation); + impl<'a, P: 'a + key::KeyParts> KeyAmalgamation<'a, P> { pub(crate) fn new_primary(cert: &'a Cert) -> Self { KeyAmalgamation { @@ -355,49 +352,6 @@ impl<'a, P: key::KeyParts> From<ValidKeyAmalgamation<'a, P>> } } -// We can't make the key parts generic, because then the impl would -// conflict with 'impl<T> std::convert::From<T> for T'. -impl<'a> From<ValidKeyAmalgamation<'a, key::PublicParts>> - for ValidKeyAmalgamation<'a, key::UnspecifiedParts> -{ - fn from(ka: ValidKeyAmalgamation<'a, key::PublicParts>) -> Self { - ValidKeyAmalgamation { - a: ka.a.into(), - policy: ka.policy, - time: ka.time, - binding_signature: ka.binding_signature, - } - } -} - -impl<'a> From<ValidKeyAmalgamation<'a, key::SecretParts>> - for ValidKeyAmalgamation<'a, key::PublicParts> -{ - fn from(ka: ValidKeyAmalgamation<'a, key::SecretParts>) -> Self { - ValidKeyAmalgamation { - a: ka.a.into(), - policy: ka.policy, - time: ka.time, - binding_signature: ka.binding_signature, - } - } -} - -impl<'a> TryFrom<ValidKeyAmalgamation<'a, key::PublicParts>> - for ValidKeyAmalgamation<'a, key::SecretParts> -{ - type Error = failure::Error; - - fn try_from(ka: ValidKeyAmalgamation<'a, key::PublicParts>) -> Result<Self> { - Ok(ValidKeyAmalgamation { - a: ka.a.try_into()?, - policy: ka.policy, - time: ka.time, - binding_signature: ka.binding_signature, - }) - } -} - impl<'a, P: 'a + key::KeyParts> Amalgamation<'a> for ValidKeyAmalgamation<'a, P> { // NOTE: No docstring, because KeyAmalgamation has the same method. |