summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi/src/packet/pkesk.rs
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-01-18 13:50:47 +0100
committerJustus Winter <justus@sequoia-pgp.org>2019-01-18 13:50:47 +0100
commitbc449472af7519be591a9e8279a8e7d8b0d19aab (patch)
tree2702247af5288164ecac3a255883bc68f85108f4 /openpgp-ffi/src/packet/pkesk.rs
parent96adda80309492c11cd13c32c85e48a2fb15d46e (diff)
openpgp-ffi: Move the packet-related functions.
Diffstat (limited to 'openpgp-ffi/src/packet/pkesk.rs')
-rw-r--r--openpgp-ffi/src/packet/pkesk.rs63
1 files changed, 63 insertions, 0 deletions
diff --git a/openpgp-ffi/src/packet/pkesk.rs b/openpgp-ffi/src/packet/pkesk.rs
new file mode 100644
index 00000000..17e7ab5b
--- /dev/null
+++ b/openpgp-ffi/src/packet/pkesk.rs
@@ -0,0 +1,63 @@
+//! Asymmetrically encrypted session keys.
+
+use failure;
+use libc::{uint8_t, size_t};
+
+extern crate sequoia_openpgp as openpgp;
+use self::openpgp::KeyID;
+use self::openpgp::packet::{Key, PKESK, key::SecretKey};
+
+use error::Status;
+
+/// Returns the PKESK's recipient.
+///
+/// The return value is a reference ot a `KeyID`. The caller must not
+/// modify or free it.
+#[::ffi_catch_abort] #[no_mangle]
+pub extern "system" fn pgp_pkesk_recipient(pkesk: *const PKESK)
+ -> *const KeyID {
+ let pkesk = ffi_param_ref!(pkesk);
+ pkesk.recipient()
+}
+
+/// Returns the session key.
+///
+/// `key` of size `key_len` must be a buffer large enough to hold the
+/// session key. If `key` is NULL, or not large enough, then the key
+/// is not written to it. Either way, `key_len` is set to the size of
+/// the session key.
+#[::ffi_catch_abort] #[no_mangle]
+pub extern "system" fn pgp_pkesk_decrypt(errp: Option<&mut *mut failure::Error>,
+ pkesk: *const PKESK,
+ secret_key: *const Key,
+ algo: *mut uint8_t, // XXX
+ key: *mut uint8_t,
+ key_len: *mut size_t)
+ -> Status {
+ ffi_make_fry_from_errp!(errp);
+ let pkesk = ffi_param_ref!(pkesk);
+ let secret_key = ffi_param_ref!(secret_key);
+ let algo = ffi_param_ref_mut!(algo);
+ let key_len = ffi_param_ref_mut!(key_len);
+
+ if let Some(SecretKey::Unencrypted{ mpis: ref secret_part }) = secret_key.secret() {
+ match pkesk.decrypt(secret_key, secret_part) {
+ Ok((a, k)) => {
+ *algo = a.into();
+ if !key.is_null() && *key_len >= k.len() {
+ unsafe {
+ ::std::ptr::copy(k.as_ptr(),
+ key,
+ k.len());
+ }
+ }
+ *key_len = k.len();
+ Status::Success
+ },
+ Err(e) => ffi_try_status!(Err::<(), failure::Error>(e)),
+ }
+ } else {
+ // XXX: Better message.
+ panic!("No secret parts");
+ }
+}