summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ffi/include/sequoia/openpgp.h5
-rw-r--r--ffi/src/openpgp/tpk.rs34
-rw-r--r--openpgp/src/tpk/builder.rs10
-rw-r--r--openpgp/src/tpk/mod.rs37
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);