diff options
24 files changed, 152 insertions, 61 deletions
diff --git a/guide/src/chapter_01.md b/guide/src/chapter_01.md index 5c9d177f..b2b143bb 100644 --- a/guide/src/chapter_01.md +++ b/guide/src/chapter_01.md @@ -10,6 +10,7 @@ fragments yields the [`openpgp/examples/generate-sign-verify.rs`]. ```rust use std::io::{self, Write}; +use std::convert::TryInto; extern crate failure; extern crate sequoia_openpgp as openpgp; @@ -51,7 +52,7 @@ fn main() { # -> openpgp::Result<()> { # // Get the keypair to do the signing from the TPK. # let key : key::UnspecifiedSecret -# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into(); +# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().try_into()?; # let keypair = key.into_keypair()?; # # // Start streaming an OpenPGP message. @@ -155,6 +156,7 @@ create it: ```rust # use std::io::{self, Write}; +# use std::convert::TryInto; # # extern crate failure; # extern crate sequoia_openpgp as openpgp; @@ -196,7 +198,7 @@ fn generate() -> openpgp::Result<openpgp::TPK> { # -> openpgp::Result<()> { # // Get the keypair to do the signing from the TPK. # let key : key::UnspecifiedSecret -# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into(); +# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().try_into()?; # let keypair = key.into_keypair()?; # # // Start streaming an OpenPGP message. @@ -300,6 +302,7 @@ implements [`io::Write`], and we simply write the plaintext to it. ```rust # use std::io::{self, Write}; +# use std::convert::TryInto; # # extern crate failure; # extern crate sequoia_openpgp as openpgp; @@ -341,7 +344,7 @@ fn sign(sink: &mut Write, plaintext: &str, tsk: &openpgp::TPK) -> openpgp::Result<()> { // Get the keypair to do the signing from the TPK. let key : key::UnspecifiedSecret - = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into(); + = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().try_into()?; let keypair = key.into_keypair()?; // Start streaming an OpenPGP message. @@ -456,7 +459,8 @@ Verified data can be read from this using [`io::Read`]. ```rust # use std::io::{self, Write}; -# +# use std::convert::TryInto; +# # extern crate failure; # extern crate sequoia_openpgp as openpgp; # use openpgp::serialize::stream::*; @@ -497,7 +501,7 @@ Verified data can be read from this using [`io::Read`]. # -> openpgp::Result<()> { # // Get the keypair to do the signing from the TPK. # let key : key::UnspecifiedSecret -# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().into(); +# = tsk.keys_valid().signing_capable().nth(0).unwrap().2.clone().try_into()?; # let keypair = key.into_keypair()?; # # // Start streaming an OpenPGP message. diff --git a/guide/src/chapter_02.md b/guide/src/chapter_02.md index acc2cb2e..d2d11964 100644 --- a/guide/src/chapter_02.md +++ b/guide/src/chapter_02.md @@ -132,7 +132,7 @@ fn main() { # .unwrap(); # # // The secret key is not encrypted. -# let mut pair = key.mark_parts_secret().into_keypair().unwrap(); +# let mut pair = key.mark_parts_secret().unwrap().into_keypair().unwrap(); # # pkesks[0].decrypt(&mut pair) # .and_then(|(algo, session_key)| decrypt(algo, &session_key)) @@ -275,7 +275,7 @@ fn generate() -> openpgp::Result<openpgp::TPK> { # .unwrap(); # # // The secret key is not encrypted. -# let mut pair = key.mark_parts_secret().into_keypair().unwrap(); +# let mut pair = key.mark_parts_secret().unwrap().into_keypair().unwrap(); # # pkesks[0].decrypt(&mut pair) # .and_then(|(algo, session_key)| decrypt(algo, &session_key)) @@ -418,7 +418,7 @@ fn encrypt(sink: &mut Write, plaintext: &str, recipient: &openpgp::TPK) # .unwrap(); # # // The secret key is not encrypted. -# let mut pair = key.mark_parts_secret().into_keypair().unwrap(); +# let mut pair = key.mark_parts_secret().unwrap().into_keypair().unwrap(); # # pkesks[0].decrypt(&mut pair) # .and_then(|(algo, session_key)| decrypt(algo, &session_key)) @@ -575,7 +575,7 @@ impl<'a> DecryptionHelper for Helper<'a> { .unwrap(); // The secret key is not encrypted. - let mut pair = key.mark_parts_secret().into_keypair().unwrap(); + let mut pair = key.mark_parts_secret().unwrap().into_keypair().unwrap(); pkesks[0].decrypt(&mut pair) .and_then(|(algo, session_key)| decrypt(algo, &session_key)) diff --git a/openpgp-ffi/src/common.rs b/openpgp-ffi/src/common.rs index 078c035e..7c615bab 100644 --- a/openpgp-ffi/src/common.rs +++ b/openpgp-ffi/src/common.rs @@ -164,6 +164,30 @@ macro_rules! ffi_make_fry_from_errp { /// Like try! for ffi glue. /// + /// Evaluates the given expression. `Ok(v)` evaluates to `v`. + /// On failure, stashes the error in the context and returns + /// the appropriate Status code. + #[allow(unused_macros)] + macro_rules! ffi_try_or_status { + ($expr:expr) => { + match $expr { + Ok(v) => v, + Err(e) => { + use crate::MoveIntoRaw; + use failure::Error; + let status = crate::error::Status::from(&e); + if let Some(errp) = $errp { + let e : Error = e.into(); + *errp = e.move_into_raw(); + } + return status; + }, + } + }; + } + + /// Like try! for ffi glue. + /// /// Unwraps the given expression. On failure, stashes the /// error in the context and returns $or. #[allow(unused_macros)] diff --git a/openpgp-ffi/src/packet/key.rs b/openpgp-ffi/src/packet/key.rs index e0eead22..7f08d040 100644 --- a/openpgp-ffi/src/packet/key.rs +++ b/openpgp-ffi/src/packet/key.rs @@ -4,6 +4,8 @@ //! //! [Section 5.5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.5 +use std::convert::TryInto; + use libc::{c_int, time_t}; extern crate sequoia_openpgp as openpgp; @@ -79,6 +81,6 @@ fn pgp_key_into_key_pair(errp: Option<&mut *mut crate::error::Error>, { ffi_make_fry_from_errp!(errp); let key : self::openpgp::packet::key::UnspecifiedSecret - = key.move_from_raw().into(); + = ffi_try!(key.move_from_raw().try_into()); ffi_try_box!(key.into_keypair()) } diff --git a/openpgp-ffi/src/packet/pkesk.rs b/openpgp-ffi/src/packet/pkesk.rs index 8f844d6c..82227065 100644 --- a/openpgp-ffi/src/packet/pkesk.rs +++ b/openpgp-ffi/src/packet/pkesk.rs @@ -44,7 +44,9 @@ pub extern "C" fn pgp_pkesk_decrypt(errp: Option<&mut *mut crate::error::Error>, let algo = ffi_param_ref_mut!(algo); let key_len = ffi_param_ref_mut!(key_len); - match secret_key.clone().mark_parts_secret().into_keypair() { + match ffi_try_or_status!(secret_key.clone().mark_parts_secret()) + .into_keypair() + { Ok(mut keypair) => { match pkesk.decrypt(&mut keypair) { Ok((a, k)) => { diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs index 4b5d231a..99ec1fd7 100644 --- a/openpgp/examples/decrypt-with.rs +++ b/openpgp/examples/decrypt-with.rs @@ -65,8 +65,8 @@ impl Helper { .unwrap_or(false) { // This only works for unencrypted secret keys. - if let Ok(keypair) - = key.clone().mark_parts_secret().into_keypair() + if let Ok(keypair) = + key.clone().mark_parts_secret().unwrap().into_keypair() { keys.insert(key.keyid(), keypair); } diff --git a/openpgp/examples/generate-encrypt-decrypt.rs b/openpgp/examples/generate-encrypt-decrypt.rs index d20219ab..a2577906 100644 --- a/openpgp/examples/generate-encrypt-decrypt.rs +++ b/openpgp/examples/generate-encrypt-decrypt.rs @@ -123,7 +123,7 @@ impl<'a> DecryptionHelper for Helper<'a> { .unwrap(); // The secret key is not encrypted. - let mut pair = key.mark_parts_secret().into_keypair().unwrap(); + let mut pair = key.mark_parts_secret().unwrap().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 98e94f21..0ab1c7a5 100644 --- a/openpgp/examples/generate-sign-verify.rs +++ b/openpgp/examples/generate-sign-verify.rs @@ -41,7 +41,7 @@ fn sign(sink: &mut dyn Write, plaintext: &str, tsk: &openpgp::TPK) -> openpgp::Result<()> { // Get the keypair to do the signing from the TPK. let keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2 - .clone().mark_parts_secret().into_keypair()?; + .clone().mark_parts_secret().unwrap().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 d17aec44..fc161373 100644 --- a/openpgp/examples/notarize.rs +++ b/openpgp/examples/notarize.rs @@ -41,7 +41,7 @@ fn main() { .expect("decryption failed"); } n += 1; - key.mark_parts_secret().into_keypair().unwrap() + key.mark_parts_secret().unwrap().into_keypair().unwrap() }); } diff --git a/openpgp/examples/sign-detached.rs b/openpgp/examples/sign-detached.rs index 98202bd2..54c9ceef 100644 --- a/openpgp/examples/sign-detached.rs +++ b/openpgp/examples/sign-detached.rs @@ -37,7 +37,7 @@ fn main() { .expect("decryption failed"); } n += 1; - key.mark_parts_secret().into_keypair().unwrap() + key.mark_parts_secret().unwrap().into_keypair().unwrap() }); } diff --git a/openpgp/examples/sign.rs b/openpgp/examples/sign.rs index 523c9e26..ec80e87f 100644 --- a/openpgp/examples/sign.rs +++ b/openpgp/examples/sign.rs @@ -36,7 +36,7 @@ fn main() { .expect("decryption failed"); } n += 1; - key.mark_parts_secret().into_keypair().unwrap() + key.mark_parts_secret().unwrap().into_keypair().unwrap() }); } diff --git a/openpgp/src/crypto/asymmetric.rs b/openpgp/src/crypto/asymmetric.rs index 144bcc4c..41d61014 100644 --- a/openpgp/src/crypto/asymmetric.rs +++ b/openpgp/src/crypto/asymmetric.rs @@ -280,6 +280,6 @@ impl<R> From<KeyPair<R>> for Key<key::SecretParts, R> fn from(p: KeyPair<R>) -> Self { let (mut key, secret) = (p.public, p.secret); key.set_secret(Some(secret.into())); - key.mark_parts_secret() + key.mark_parts_secret().expect("XXX") } } diff --git a/openpgp/src/packet/key/mod.rs b/openpgp/src/packet/key/mod.rs index b6337ce0..389d16f5 100644 --- a/openpgp/src/packet/key/mod.rs +++ b/openpgp/src/packet/key/mod.rs @@ -42,16 +42,18 @@ //! # .generate()?; //! // Get a handle to the TPK's primary key that allows using the //! // secret key material. -//! let sk : &key::SecretKey = tpk.primary().into(); +//! use std::convert::TryInto; +//! let sk : &key::SecretKey = tpk.primary().try_into()?; //! //! // Make the conversion explicit. -//! let sk : &key::SecretKey = tpk.primary().mark_parts_secret_ref(); +//! let sk : &key::SecretKey = tpk.primary().mark_parts_secret_ref()?; //! # Ok(()) //! # } //! ``` use std::fmt; use std::cmp::Ordering; +use std::convert::TryFrom; use std::time; use crate::Error; @@ -249,14 +251,43 @@ macro_rules! create_conversions { } } - p!(<PublicParts> -> <SecretParts>); + // Likewise, but using TryFrom. + macro_rules! p_try { + ( <$from_parts:ty> -> <$to_parts:ty>) => { + impl<R> TryFrom<$Key<$from_parts, R>> for $Key<$to_parts, R> + where R: KeyRole + { + type Error = failure::Error; + fn try_from(p: $Key<$from_parts, R>) -> Result<Self> { + p.mark_parts_secret() + } + } + + impl<R> TryFrom<&$Key<$from_parts, R>> for &$Key<$to_parts, R> + where R: KeyRole + { + type Error = failure::Error; + fn try_from(p: &$Key<$from_parts, R>) -> Result<Self> { + if p.secret().is_some() { + 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!(<UnspecifiedParts> -> <SecretParts>); + p_try!(<UnspecifiedParts> -> <SecretParts>); // Convert between two KeyRoles for a constant KeyParts. See // the comment for the p macro above. @@ -438,13 +469,22 @@ macro_rules! create_conversions { } /// Changes the key's parts tag to `SecretParts`. - pub fn mark_parts_secret(self) -> $Key<SecretParts, R> { - convert!(self) + pub fn mark_parts_secret(self) -> Result<$Key<SecretParts, R>> { + if self.secret().is_some() { + 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(&self) -> &$Key<SecretParts, R> { - convert_ref!(self) + pub fn mark_parts_secret_ref(&self) -> Result<&$Key<SecretParts, R>> + { + if self.secret().is_some() { + Ok(convert_ref!(self)) + } else { + Err(Error::InvalidArgument("No secret key".into()).into()) + } } /// Changes the key's parts tag to `UnspecifiedParts`. @@ -1370,7 +1410,8 @@ mod tests { for key in keys.into_iter() { let key : key::PublicKey = key.into(); let mut keypair - = key.clone().mark_parts_secret().into_keypair().unwrap(); + = key.clone().mark_parts_secret().unwrap() + .into_keypair().unwrap(); let cipher = SymmetricAlgorithm::AES256; let sk = SessionKey::new(cipher.key_size().unwrap()); diff --git a/openpgp/src/packet/pkesk.rs b/openpgp/src/packet/pkesk.rs index b2e9a0f4..29fd715f 100644 --- a/openpgp/src/packet/pkesk.rs +++ b/openpgp/src/packet/pkesk.rs @@ -229,7 +229,7 @@ mod tests { crate::tests::message("encrypted-to-testy.gpg")).unwrap(); let mut keypair = tpk.subkeys().next().unwrap() - .key().clone().mark_parts_secret().into_keypair().unwrap(); + .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap(); let pkg = pile.descendants().skip(0).next().clone(); @@ -250,7 +250,7 @@ mod tests { crate::tests::message("encrypted-to-testy-new.pgp")).unwrap(); let mut keypair = tpk.subkeys().next().unwrap() - .key().clone().mark_parts_secret().into_keypair().unwrap(); + .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap(); let pkg = pile.descendants().skip(0).next().clone(); @@ -271,7 +271,7 @@ mod tests { crate::tests::message("encrypted-to-testy-nistp256.pgp")).unwrap(); let mut keypair = tpk.subkeys().next().unwrap() - .key().clone().mark_parts_secret().into_keypair().unwrap(); + .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap(); let pkg = pile.descendants().skip(0).next().clone(); @@ -292,7 +292,7 @@ mod tests { crate::tests::message("encrypted-to-testy-nistp384.pgp")).unwrap(); let mut keypair = tpk.subkeys().next().unwrap() - .key().clone().mark_parts_secret().into_keypair().unwrap(); + .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap(); let pkg = pile.descendants().skip(0).next().clone(); @@ -313,7 +313,7 @@ mod tests { crate::tests::message("encrypted-to-testy-nistp521.pgp")).unwrap(); let mut keypair = tpk.subkeys().next().unwrap() - .key().clone().mark_parts_secret().into_keypair().unwrap(); + .key().clone().mark_parts_secret().unwrap().into_keypair().unwrap(); let pkg = pile.descendants().skip(0).next().clone(); @@ -370,7 +370,8 @@ mod tests { let sess_key = SessionKey::new(32); let pkesk = PKESK3::for_recipient(SymmetricAlgorithm::AES256, &sess_key, &key).unwrap(); - let mut keypair = key.mark_parts_secret().into_keypair().unwrap(); + let mut keypair = + key.mark_parts_secret().unwrap().into_keypair().unwrap(); pkesk.decrypt(&mut keypair).unwrap(); } } diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs index ab7762b9..211a4447 100644 --- a/openpgp/src/packet/signature/mod.rs +++ b/openpgp/src/packet/signature/mod.rs @@ -1260,7 +1260,7 @@ mod test { ] { let tpk = TPK::from_bytes(crate::tests::key(key)).unwrap(); let mut pair = tpk.primary().clone() - .mark_parts_secret() + .mark_parts_secret().unwrap() .into_keypair() .expect("secret key is encrypted/missing"); diff --git a/openpgp/src/packet/signature/subpacket.rs b/openpgp/src/packet/signature/subpacket.rs index b801eb6c..2a83920b 100644 --- a/openpgp/src/packet/signature/subpacket.rs +++ b/openpgp/src/packet/signature/subpacket.rs @@ -2735,7 +2735,8 @@ fn accessors() { let mut sig = signature::Builder::new(crate::constants::SignatureType::Binary); let mut key: crate::packet::key::PublicKey = crate::packet::key::Key4::generate_ecc(true, Curve::Ed25519).unwrap().into(); - let mut keypair = key.clone().mark_parts_secret().into_keypair().unwrap(); + let mut keypair = key.clone().mark_parts_secret().unwrap() + .into_keypair().unwrap(); // Cook up a timestamp without ns resolution. let now = time::SystemTime::now().canonicalize(); diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index bab21e4c..48c1fd2a 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -1911,7 +1911,8 @@ mod test { { let key = tpk.keys_all().signing_capable().nth(0).unwrap().2; let keypair = - key.clone().mark_parts_secret().into_keypair().unwrap(); + key.clone().mark_parts_secret().unwrap() + .into_keypair().unwrap(); let m = Message::new(&mut buf); let signer = Signer::new(m, keypair).build().unwrap(); diff --git a/openpgp/src/serialize/mod.rs b/openpgp/src/serialize/mod.rs index d37c0c7e..325b181f 100644 --- a/openpgp/src/serialize/mod.rs +++ b/openpgp/src/serialize/mod.rs @@ -2938,7 +2938,7 @@ mod test { let (tpk, _) = TPKBuilder::new().generate().unwrap(); let mut keypair = tpk.primary().clone().mark_parts_secret() - .into_keypair().unwrap(); + .unwrap().into_keypair().unwrap(); let uid = UserID::from("foo"); // Make a signature w/o an exportable certification subpacket. diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index 4b1e0d88..5af424d3 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -230,7 +230,7 @@ impl<'a> Signer<'a> { /// # "../../tests/data/keys/testy-new-private.pgp")[..]) /// # .unwrap(); /// # let keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2 - /// # .clone().mark_parts_secret().into_keypair().unwrap(); + /// # .clone().mark_parts_secret().unwrap().into_keypair().unwrap(); /// # f(tsk, keypair).unwrap(); /// # fn f(tpk: TPK, mut signing_keypair: KeyPair<key::UnspecifiedRole>) /// # -> Result<()> { @@ -333,7 +333,7 @@ impl<'a> Signer<'a> { /// # "../../tests/data/keys/testy-new-private.pgp")[..]) /// # .unwrap(); /// # let keypair = tsk.keys_valid().signing_capable().nth(0).unwrap().2 - /// # .clone().mark_parts_secret().into_keypair().unwrap(); + /// # .clone().mark_parts_secret().unwrap().into_keypair().unwrap(); /// # f(tsk, keypair).unwrap(); /// # fn f(tpk: TPK, mut signing_keypair: KeyPair<key::UnspecifiedRole>) /// # -> Result<()> { @@ -1478,7 +1478,7 @@ mod test { let mut o = vec![]; { let mut signers = keys.iter().map(|(_, key)| { - key.clone().mark_parts_secret().into_keypair() + key.clone().mark_parts_secret().unwrap().into_keypair() .expect("expected unencrypted secret key") }).collect::<Vec<KeyPair<_>>>(); |