summaryrefslogtreecommitdiffstats
path: root/ffi
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2018-11-22 10:32:14 +0100
committerNeal H. Walfield <neal@pep.foundation>2018-11-22 10:36:05 +0100
commitfce58a063f8c2aeeaef783f45ec089cfcc753102 (patch)
tree9733d1552daf4fdc2985353cac7393886c830226 /ffi
parentf9725cdcd471a5dbf1d61aef4f40cf229e0c04c1 (diff)
ffi: Wrap TPK.
- In particular, add sq_tpk_primary, sq_tpk_revocation_status, sq_tpk_revoke, sq_tpk_revoke_in_place, sq_tpk_expired, sq_tpk_set_expiry, and sq_tpk_is_tsk.
Diffstat (limited to 'ffi')
-rw-r--r--ffi/include/sequoia/openpgp.h89
-rw-r--r--ffi/src/openpgp.rs127
2 files changed, 216 insertions, 0 deletions
diff --git a/ffi/include/sequoia/openpgp.h b/ffi/include/sequoia/openpgp.h
index 64e6a1db..f898c2a3 100644
--- a/ffi/include/sequoia/openpgp.h
+++ b/ffi/include/sequoia/openpgp.h
@@ -514,6 +514,37 @@ sq_keyid_t sq_signature_issuer(sq_signature_t sig);
/*/
sq_fingerprint_t sq_signature_issuer_fingerprint(sq_signature_t sig);
+typedef enum sq_reason_for_revocation {
+ /*/
+ /// No reason specified (key revocations or cert revocations)
+ /*/
+ SQ_REASON_FOR_REVOCATION_UNSPECIFIED,
+
+ /*/
+ /// Key is superseded (key revocations)
+ /*/
+ SQ_REASON_FOR_REVOCATION_KEY_SUPERSEDED,
+
+ /*/
+ /// Key material has been compromised (key revocations)
+ /*/
+ SQ_REASON_FOR_REVOCATION_KEY_COMPROMISED,
+
+ /*/
+ /// Key is retired and no longer used (key revocations)
+ /*/
+ SQ_REASON_FOR_REVOCATION_KEY_RETIRED,
+
+ /*/
+ /// User ID information is no longer valid (cert revocations)
+ /*/
+ SQ_REASON_FOR_REVOCATION_UID_RETIRED,
+
+ /* Dummy value to make sure the enumeration has a defined size. Do
+ not use this value. */
+ SQ_REASON_FOR_REVOCATION_FORCE_WIDTH = INT_MAX,
+} sq_reason_for_revocation_t;
+
/* openpgp::tpk. */
@@ -619,6 +650,64 @@ sq_fingerprint_t sq_tpk_fingerprint (const sq_tpk_t tpk);
/*/
sq_tsk_t sq_tpk_into_tsk (sq_tpk_t tpk);
+/*/
+/// Returns a reference to the TPK's primary key.
+///
+/// The tpk still owns the key. The caller should neither modify nor
+/// free the key.
+/*/
+sq_p_key_t sq_tpk_primary (sq_tpk_t tpk);
+
+/*/
+/// Returns the TPK's revocation status.
+///
+/// Note: this only returns whether the TPK has been revoked, and does
+/// not reflect whether an individual user id, user attribute or
+/// subkey has been revoked.
+/*/
+sq_revocation_status_t sq_tpk_revocation_status (sq_tpk_t tpk);
+
+/*/
+/// Writes a revocation certificate to the writer.
+///
+/// This function consumes the writer. It does *not* consume tpk.
+/*/
+sq_status_t sq_tpk_revoke (sq_context_t ctx,
+ sq_tpk_t tpk, sq_reason_for_revocation_t code,
+ const char *reason, sq_writer_t writer);
+
+/*/
+/// Adds a revocation certificate to the tpk.
+///
+/// This function consumes the tpk.
+/*/
+sq_tpk_t sq_tpk_revoke_in_place (sq_context_t ctx,
+ sq_tpk_t tpk,
+ sq_reason_for_revocation_t code,
+ const char *reason);
+
+/*/
+/// Returns whether the TPK has expired.
+/*/
+int sq_tpk_expired(sq_tpk_t tpk);
+
+/*/
+/// Changes the TPK's expiration.
+///
+/// Expiry is when the key should expire in seconds relative to the
+/// key's creation (not the current time).
+///
+/// This function consumes `tpk` and returns a new `TPK`.
+/*/
+sq_tpk_t sq_tpk_set_expiry(sq_context_t ctx,
+ sq_tpk_t tpk,
+ uint32_t expiry);
+
+/*/
+/// Returns whether the TPK includes any secret key material.
+/*/
+int sq_tpk_is_tsk(sq_tpk_t tpk);
+
/* TPKBuilder */
typedef struct sq_tpk_builder *sq_tpk_builder_t;
diff --git a/ffi/src/openpgp.rs b/ffi/src/openpgp.rs
index 1d23ad61..b740e571 100644
--- a/ffi/src/openpgp.rs
+++ b/ffi/src/openpgp.rs
@@ -31,6 +31,7 @@ use self::openpgp::parse::{PacketParserResult, PacketParser, PacketParserEOF};
use self::openpgp::serialize::Serialize;
use self::openpgp::constants::{
DataFormat,
+ ReasonForRevocation,
};
use super::build_hasher;
@@ -821,6 +822,132 @@ pub extern "system" fn sq_tpk_into_tsk(tpk: *mut TPK)
box_raw!(tpk.into_tsk())
}
+/// Returns a reference to the TPK's primary key.
+///
+/// The tpk still owns the key. The caller should neither modify nor
+/// free the key.
+#[no_mangle]
+pub extern "system" fn sq_tpk_primary(tpk: Option<&TPK>)
+ -> Option<&packet::Key> {
+ let tpk = tpk.expect("TPK is NULL");
+ Some(tpk.primary())
+}
+
+/// Returns the TPK's revocation status.
+///
+/// Note: this only returns whether the TPK has been revoked, and does
+/// not reflect whether an individual user id, user attribute or
+/// subkey has been revoked.
+#[no_mangle]
+pub extern "system" fn sq_tpk_revocation_status(tpk: Option<&TPK>)
+ -> *mut RevocationStatus {
+ let tpk = tpk.expect("TPK is NULL");
+ box_raw!(tpk.revoked())
+}
+
+fn int_to_reason_for_revocation(code: c_int) -> ReasonForRevocation {
+ match code {
+ 0 => ReasonForRevocation::KeyCompromised,
+ 1 => ReasonForRevocation::Unspecified,
+ 2 => ReasonForRevocation::KeySuperseded,
+ 3 => ReasonForRevocation::KeyCompromised,
+ 4 => ReasonForRevocation::KeyRetired,
+ 5 => ReasonForRevocation::UIDRetired,
+ _ => panic!("Bad reason for revocation: {}", code),
+ }
+}
+
+
+/// Returns a new revocation certificate for the TPK.
+///
+/// This function does *not* consume tpk.
+#[no_mangle]
+pub extern "system" fn sq_tpk_revoke (ctx: Option<&mut Context>,
+ tpk: *mut TPK,
+ code: c_int,
+ reason: Option<*const c_char>)
+ -> *mut packet::Signature
+{
+ let ctx = ctx.expect("Context is NULL");
+ assert!(!tpk.is_null());
+ let tpk = unsafe {
+ Box::from_raw(tpk)
+ };
+ let code = int_to_reason_for_revocation(code);
+ let reason = if let Some(reason) = reason {
+ unsafe {
+ CStr::from_ptr(reason).to_bytes()
+ }
+ } else {
+ b""
+ };
+
+ fry_box!(ctx, tpk.revoke(code, reason))
+}
+
+/// Adds a revocation certificate to the tpk.
+///
+/// This function consumes the tpk.
+#[no_mangle]
+pub extern "system" fn sq_tpk_revoke_in_place (ctx: Option<&mut Context>,
+ tpk: *mut TPK,
+ code: c_int,
+ reason: Option<*const c_char>)
+ -> *mut TPK
+{
+ let ctx = ctx.expect("Context is NULL");
+ assert!(!tpk.is_null());
+ let tpk = unsafe {
+ Box::from_raw(tpk)
+ };
+ let code = int_to_reason_for_revocation(code);
+ let reason = if let Some(reason) = reason {
+ unsafe {
+ CStr::from_ptr(reason).to_bytes()
+ }
+ } else {
+ b""
+ };
+
+ fry_box!(ctx, tpk.revoke_in_place(code, reason))
+}
+
+/// Returns whether the TPK has expired.
+#[no_mangle]
+pub extern "system" fn sq_tpk_expired(tpk: Option<&TPK>)
+ -> c_int {
+ let tpk = tpk.expect("TPK is NULL");
+
+ tpk.expired() as c_int
+}
+
+/// Changes the TPK's expiration.
+///
+/// Expiry is when the key should expire in seconds relative to the
+/// key's creation (not the current time).
+///
+/// This function consumes `tpk` and returns a new `TPK`.
+#[no_mangle]
+pub extern "system" fn sq_tpk_set_expiry(ctx: Option<&mut Context>,
+ tpk: *mut TPK, expiry: u32)
+ -> *mut TPK {
+ let ctx = ctx.expect("CTX is NULL");
+ assert!(!tpk.is_null());
+ let tpk = unsafe {
+ Box::from_raw(tpk)
+ };
+
+ fry_box!(ctx, tpk.set_expiry_in_seconds(expiry))
+}
+
+/// Returns whether the TPK includes any secret key material.
+#[no_mangle]
+pub extern "system" fn sq_tpk_is_tsk(tpk: Option<&TPK>)
+ -> c_int {
+ let tpk = tpk.expect("TPK is NULL");
+ tpk.is_tsk() as c_int
+}
+
fn revocation_status_to_int(rs: &RevocationStatus) -> c_int {
match rs {
RevocationStatus::Revoked(_) => 0,