diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2018-12-27 16:25:42 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-01-10 14:44:39 +0100 |
commit | d678ea32802a4896b95fc9b01c86ba7114fb2b9f (patch) | |
tree | 377de42676043931b7ea1ef65d7088119ec86f39 | |
parent | 6e53bb4f673786acee95a416fbf7859659d626b7 (diff) |
openpgp: Use Signer when revoking TPKs.
-rw-r--r-- | ffi/include/sequoia/openpgp.h | 5 | ||||
-rw-r--r-- | ffi/src/openpgp/tpk.rs | 34 | ||||
-rw-r--r-- | openpgp/src/tpk/builder.rs | 10 | ||||
-rw-r--r-- | openpgp/src/tpk/mod.rs | 37 |
4 files changed, 65 insertions, 21 deletions
diff --git a/ffi/include/sequoia/openpgp.h b/ffi/include/sequoia/openpgp.h index 7b1aa3b6..6fe71f6b 100644 --- a/ffi/include/sequoia/openpgp.h +++ b/ffi/include/sequoia/openpgp.h @@ -894,7 +894,9 @@ sq_revocation_status_t sq_tpk_revocation_status (sq_tpk_t tpk); /// This function consumes the writer. It does *not* consume tpk. /*/ sq_signature_t sq_tpk_revoke (sq_context_t ctx, - sq_tpk_t tpk, sq_reason_for_revocation_t code, + sq_tpk_t tpk, + sq_signer_t primary_signer, + sq_reason_for_revocation_t code, const char *reason); /*/ @@ -904,6 +906,7 @@ sq_signature_t sq_tpk_revoke (sq_context_t ctx, /*/ sq_tpk_t sq_tpk_revoke_in_place (sq_context_t ctx, sq_tpk_t tpk, + sq_signer_t primary_signer, sq_reason_for_revocation_t code, const char *reason); diff --git a/ffi/src/openpgp/tpk.rs b/ffi/src/openpgp/tpk.rs index 32166a5f..6acb45de 100644 --- a/ffi/src/openpgp/tpk.rs +++ b/ffi/src/openpgp/tpk.rs @@ -20,6 +20,7 @@ use self::sequoia_openpgp::{ TPK, TSK, autocrypt::Autocrypt, + crypto, constants::ReasonForRevocation, packet::{self, Signature}, parse::PacketParserResult, @@ -254,6 +255,9 @@ fn int_to_reason_for_revocation(code: c_int) -> ReasonForRevocation { /// sq_tpk_builder_t builder; /// sq_tpk_t tpk; /// sq_signature_t revocation; +/// sq_p_key_t primary_key; +/// sq_key_pair_t primary_keypair; +/// sq_signer_t primary_signer; /// /// ctx = sq_context_new ("org.sequoia-pgp.tests", NULL); /// @@ -264,10 +268,17 @@ fn int_to_reason_for_revocation(code: c_int) -> ReasonForRevocation { /// assert (revocation); /// sq_signature_free (revocation); /* Free the generated one. */ /// -/// revocation = sq_tpk_revoke (ctx, tpk, +/// primary_key = sq_p_key_clone (sq_tpk_primary (tpk)); +/// assert (primary_key); +/// primary_keypair = sq_p_key_into_key_pair (ctx, primary_key); +/// assert (primary_keypair); +/// primary_signer = sq_key_pair_as_signer (primary_keypair); +/// revocation = sq_tpk_revoke (ctx, tpk, primary_signer, /// SQ_REASON_FOR_REVOCATION_KEY_COMPROMISED, /// "It was the maid :/"); /// assert (revocation); +/// sq_signer_free (primary_signer); +/// sq_key_pair_free (primary_keypair); /// /// sq_packet_t packet = sq_signature_to_packet (revocation); /// tpk = sq_tpk_merge_packets (ctx, tpk, &packet, 1); @@ -283,12 +294,14 @@ fn int_to_reason_for_revocation(code: c_int) -> ReasonForRevocation { #[no_mangle] pub extern "system" fn sq_tpk_revoke(ctx: *mut Context, tpk: *mut TPK, + primary_signer: *mut Box<crypto::Signer>, code: c_int, reason: Option<&c_char>) -> *mut packet::Signature { let ctx = ffi_param_ref_mut!(ctx); let tpk = ffi_param_ref!(tpk); + let signer = ffi_param_ref_mut!(primary_signer); let code = int_to_reason_for_revocation(code); let reason = if let Some(reason) = reason { unsafe { @@ -298,7 +311,7 @@ pub extern "system" fn sq_tpk_revoke(ctx: *mut Context, b"" }; - fry_box!(ctx, tpk.revoke(code, reason)) + fry_box!(ctx, tpk.revoke(signer.as_mut(), code, reason)) } /// Adds a revocation certificate to the tpk. @@ -315,6 +328,9 @@ pub extern "system" fn sq_tpk_revoke(ctx: *mut Context, /// sq_tpk_builder_t builder; /// sq_tpk_t tpk; /// sq_signature_t revocation; +/// sq_p_key_t primary_key; +/// sq_key_pair_t primary_keypair; +/// sq_signer_t primary_signer; /// /// ctx = sq_context_new ("org.sequoia-pgp.tests", NULL); /// @@ -325,9 +341,17 @@ pub extern "system" fn sq_tpk_revoke(ctx: *mut Context, /// assert (revocation); /// sq_signature_free (revocation); /* Free the generated one. */ /// -/// tpk = sq_tpk_revoke_in_place (ctx, tpk, +/// primary_key = sq_p_key_clone (sq_tpk_primary (tpk)); +/// assert (primary_key); +/// primary_keypair = sq_p_key_into_key_pair (ctx, primary_key); +/// assert (primary_keypair); +/// primary_signer = sq_key_pair_as_signer (primary_keypair); +/// tpk = sq_tpk_revoke_in_place (ctx, tpk, primary_signer, /// SQ_REASON_FOR_REVOCATION_KEY_COMPROMISED, /// "It was the maid :/"); +/// assert (tpk); +/// sq_signer_free (primary_signer); +/// sq_key_pair_free (primary_keypair); /// /// sq_revocation_status_t rs = sq_tpk_revocation_status (tpk); /// assert (sq_revocation_status_variant (rs) == SQ_REVOCATION_STATUS_REVOKED); @@ -339,12 +363,14 @@ pub extern "system" fn sq_tpk_revoke(ctx: *mut Context, #[no_mangle] pub extern "system" fn sq_tpk_revoke_in_place(ctx: *mut Context, tpk: *mut TPK, + primary_signer: *mut Box<crypto::Signer>, code: c_int, reason: Option<&c_char>) -> *mut TPK { let ctx = ffi_param_ref_mut!(ctx); let tpk = ffi_param_move!(tpk); + let signer = ffi_param_ref_mut!(primary_signer); let code = int_to_reason_for_revocation(code); let reason = if let Some(reason) = reason { unsafe { @@ -354,7 +380,7 @@ pub extern "system" fn sq_tpk_revoke_in_place(ctx: *mut Context, b"" }; - fry_box!(ctx, tpk.revoke_in_place(code, reason)) + fry_box!(ctx, tpk.revoke_in_place(signer.as_mut(), code, reason)) } /// Returns whether the TPK has expired. diff --git a/openpgp/src/tpk/builder.rs b/openpgp/src/tpk/builder.rs index fa145720..4723157f 100644 --- a/openpgp/src/tpk/builder.rs +++ b/openpgp/src/tpk/builder.rs @@ -7,6 +7,7 @@ use crypto::KeyPair; use SymmetricAlgorithm; use HashAlgorithm; use packet::signature::{self, Signature}; +use packet::key::SecretKey; use TPK; use PublicKeyAlgorithm; use Error; @@ -207,7 +208,14 @@ impl TPKBuilder { let tpk = TPK::from_packet_pile(PacketPile::from_packets(packets))?; - let revocation = tpk.revoke(ReasonForRevocation::Unspecified, + let sec = + if let Some(SecretKey::Unencrypted { ref mpis }) = primary.secret() { + mpis.clone() + } else { + unreachable!() + }; + let revocation = tpk.revoke(&mut KeyPair::new(primary, sec)?, + ReasonForRevocation::Unspecified, b"Unspecified")?; // keys generated by the builder are never invalid diff --git a/openpgp/src/tpk/mod.rs b/openpgp/src/tpk/mod.rs index 6c092f80..2515b537 100644 --- a/openpgp/src/tpk/mod.rs +++ b/openpgp/src/tpk/mod.rs @@ -11,7 +11,7 @@ use time; use failure; use { - crypto::KeyPair, + crypto::{Signer, KeyPair}, Error, Result, RevocationStatus, @@ -1305,6 +1305,7 @@ impl TPK { /// use openpgp::RevocationStatus; /// use openpgp::constants::{ReasonForRevocation, SignatureType}; /// use openpgp::tpk::{CipherSuite, TPKBuilder}; + /// use openpgp::crypto::KeyPair; /// use openpgp::parse::Parse; /// # fn main() { f().unwrap(); } /// # fn f() -> Result<()> @@ -1314,7 +1315,8 @@ impl TPK { /// .generate()?; /// assert_eq!(RevocationStatus::NotAsFarAsWeKnow, tpk.revoked()); /// - /// let sig = tpk.revoke(ReasonForRevocation::KeyCompromised, + /// let mut keypair = tpk.primary().clone().into_keypair()?; + /// let sig = tpk.revoke(&mut keypair, ReasonForRevocation::KeyCompromised, /// b"It was the maid :/")?; /// assert_eq!(sig.sigtype(), SignatureType::KeyRevocation); /// @@ -1322,9 +1324,15 @@ impl TPK { /// assert_eq!(RevocationStatus::Revoked(&[sig]), tpk.revoked()); /// # Ok(()) /// # } - pub fn revoke(&self, code: ReasonForRevocation, reason: &[u8]) + pub fn revoke(&self, primary_signer: &mut Signer, + code: ReasonForRevocation, reason: &[u8]) -> Result<Signature> { + if primary_signer.public().fingerprint() != self.fingerprint() { + return Err(Error::InvalidArgument( + "signer is not the primary key".into()).into()); + } + let mut sig = signature::Builder::new(SignatureType::KeyRevocation); sig.set_signature_creation_time(time::now_utc())?; sig.set_issuer_fingerprint(self.primary().fingerprint())?; @@ -1338,14 +1346,7 @@ impl TPK { let mut hash = hash_algo.context()?; pair.hash(&mut hash); - if let Some(SecretKey::Unencrypted{ mpis: ref sec }) = pair.secret() { - // Generate the signature. - sig.sign_hash(&mut KeyPair::new(pair.clone(), sec.clone())?, - hash_algo, hash) - } else { - return Err(Error::InvalidOperation( - "Secret key is encrypted".into()).into()); - } + sig.sign_hash(primary_signer, hash_algo, hash) } /// Revokes the TPK. @@ -1358,6 +1359,7 @@ impl TPK { /// use openpgp::RevocationStatus; /// use openpgp::constants::{ReasonForRevocation, SignatureType}; /// use openpgp::tpk::{CipherSuite, TPKBuilder}; + /// use openpgp::crypto::KeyPair; /// use openpgp::parse::Parse; /// # fn main() { f().unwrap(); } /// # fn f() -> Result<()> @@ -1367,7 +1369,9 @@ impl TPK { /// .generate()?; /// assert_eq!(RevocationStatus::NotAsFarAsWeKnow, tpk.revoked()); /// - /// let tpk = tpk.revoke_in_place(ReasonForRevocation::KeyCompromised, + /// let mut keypair = tpk.primary().clone().into_keypair()?; + /// let tpk = tpk.revoke_in_place(&mut keypair, + /// ReasonForRevocation::KeyCompromised, /// b"It was the maid :/")?; /// if let RevocationStatus::Revoked(sigs) = tpk.revoked() { /// assert_eq!(sigs.len(), 1); @@ -1381,10 +1385,11 @@ impl TPK { /// # Ok(()) /// # } /// ``` - pub fn revoke_in_place(self, code: ReasonForRevocation, reason: &[u8]) + pub fn revoke_in_place(self, primary_signer: &mut Signer, + code: ReasonForRevocation, reason: &[u8]) -> Result<TPK> { - let sig = self.revoke(code, reason)?; + let sig = self.revoke(primary_signer, code, reason)?; self.merge_packets(vec![sig.to_packet()]) } @@ -3324,7 +3329,9 @@ mod test { let tpk = tsk.into_tpk(); assert_eq!(RevocationStatus::NotAsFarAsWeKnow, tpk.revoked()); - let sig = tpk.revoke(ReasonForRevocation::KeyCompromised, + let mut keypair = tpk.primary().clone().into_keypair().unwrap(); + let sig = tpk.revoke(&mut keypair, + ReasonForRevocation::KeyCompromised, b"It was the maid :/").unwrap(); assert_eq!(sig.sigtype(), SignatureType::KeyRevocation); |