diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-01-18 13:50:47 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-01-18 13:50:47 +0100 |
commit | bc449472af7519be591a9e8279a8e7d8b0d19aab (patch) | |
tree | 2702247af5288164ecac3a255883bc68f85108f4 /openpgp-ffi/src/packet/pkesk.rs | |
parent | 96adda80309492c11cd13c32c85e48a2fb15d46e (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.rs | 63 |
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"); + } +} |