summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi/src/serialize.rs
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-09-06 13:47:50 +0200
committerJustus Winter <justus@sequoia-pgp.org>2019-09-06 16:42:12 +0200
commit38a4d2b4ff4fc4512b31a4ff4e4ddd8a6b3c7503 (patch)
tree469d667b6bab8333df02c7a2402b9edabbe08419 /openpgp-ffi/src/serialize.rs
parent4d642187f1df0c9a4c60dc2355c797ebac6fcd4f (diff)
openpgp: Rework streaming encryptor.
- Instead of giving a set of TPKs to the encryptor, hand in a set of recipients, which are (keyid, key)-tuples, conveniently created from key queries over TPKs. This simplifies the encryptor, and makes the key selection explicit. - Drop the EncryptionMode type. - As a nice side effect, we can now generate encrypted messages with wildcard recipient addresses.
Diffstat (limited to 'openpgp-ffi/src/serialize.rs')
-rw-r--r--openpgp-ffi/src/serialize.rs104
1 files changed, 84 insertions, 20 deletions
diff --git a/openpgp-ffi/src/serialize.rs b/openpgp-ffi/src/serialize.rs
index 33fa9181..4322241b 100644
--- a/openpgp-ffi/src/serialize.rs
+++ b/openpgp-ffi/src/serialize.rs
@@ -25,7 +25,9 @@ use self::openpgp::constants::{
use crate::error::Status;
use crate::MoveFromRaw;
+use crate::MoveIntoRaw;
use crate::RefRaw;
+use crate::RefMutRaw;
use self::openpgp::serialize::{
writer,
@@ -35,12 +37,13 @@ use self::openpgp::serialize::{
ArbitraryWriter,
Signer,
LiteralWriter,
- EncryptionMode,
Encryptor,
},
};
-use super::tpk::TPK;
+use super::keyid::KeyID;
+use super::packet::key::Key;
+use super::tpk::KeyIterWrapper;
/// Streams an OpenPGP message.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
@@ -228,6 +231,74 @@ pub extern "C" fn pgp_literal_writer_new
None))
}
+/// A recipient of an encrypted message.
+///
+/// Wraps [`sequoia-openpgp::serialize::stream::Recipient`].
+///
+/// [`sequoia-openpgp::serialize::stream::Recipient`]: ../../sequoia_openpgp/serialize/stream/struct.Recipient.html
+#[crate::ffi_wrapper_type(prefix = "pgp_", derive = "Debug")]
+pub struct Recipient<'a>(openpgp::serialize::stream::Recipient<'a>);
+
+/// Creates a new recipient with an explicit recipient keyid.
+///
+/// Consumes `keyid`, references `key`.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
+fn pgp_recipient_new<'a>(keyid: *mut KeyID,
+ key: *const Key)
+ -> *mut Recipient<'a>
+{
+ openpgp::serialize::stream::Recipient::new(
+ keyid.move_from_raw(),
+ key.ref_raw().mark_parts_public_ref(),
+ ).move_into_raw()
+}
+
+/// Gets the KeyID.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
+fn pgp_recipient_keyid(recipient: *const Recipient) -> *mut KeyID {
+ recipient.ref_raw().keyid().clone().move_into_raw()
+}
+
+/// Sets the KeyID.
+///
+/// Consumes `keyid`.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
+fn pgp_recipient_set_keyid(recipient: *mut Recipient, keyid: *mut KeyID) {
+ recipient.ref_mut_raw().set_keyid(keyid.move_from_raw());
+}
+
+/// Collects recipients from a `pgp_tpk_key_iter_t`.
+///
+/// Consumes the iterator. The returned buffer must be freed using
+/// libc's allocator.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
+fn pgp_recipients_from_key_iter<'a>(
+ iter_wrapper: *mut KeyIterWrapper<'a>,
+ result_len: *mut size_t)
+ -> *mut *mut Recipient<'a>
+{
+ let iter_wrapper = ffi_param_move!(iter_wrapper);
+ let result_len = ffi_param_ref_mut!(result_len);
+ let recipients =
+ iter_wrapper.iter
+ .map(|(_, _, key)| key.into())
+ .collect::<Vec<openpgp::serialize::stream::Recipient>>();
+
+ let result = unsafe {
+ libc::calloc(recipients.len(), std::mem::size_of::<* mut Recipient>())
+ as *mut *mut Recipient
+ };
+ let r = unsafe {
+ slice::from_raw_parts_mut(result,
+ recipients.len())
+ };
+ *result_len = recipients.len();
+ r.iter_mut().zip(recipients.into_iter())
+ .for_each(|(r, recipient)| *r = recipient.move_into_raw());
+ result
+}
+
+
/// Creates a new encryptor.
///
/// The stream will be encrypted using a generated session key,
@@ -237,15 +308,14 @@ pub extern "C" fn pgp_literal_writer_new
/// The stream is encrypted using `cipher_algo`. Pass 0 for the
/// default (which is what you usually want).
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
-pub extern "C" fn pgp_encryptor_new
+pub extern "C" fn pgp_encryptor_new<'a>
(errp: Option<&mut *mut crate::error::Error>,
- inner: *mut writer::Stack<'static, Cookie>,
+ inner: *mut writer::Stack<'a, Cookie>,
passwords: Option<&*const c_char>, passwords_len: size_t,
- recipients: Option<&*const TPK>, recipients_len: size_t,
- encryption_mode: u8,
+ recipients: Option<&*const Recipient<'a>>, recipients_len: size_t,
cipher_algo: u8,
aead_algo: u8)
- -> *mut writer::Stack<'static, Cookie>
+ -> *mut writer::Stack<'a, Cookie>
{
ffi_make_fry_from_errp!(errp);
let inner = ffi_param_move!(inner);
@@ -260,20 +330,15 @@ pub extern "C" fn pgp_encryptor_new
.to_bytes().to_owned().into());
}
}
- let recipients = if recipients_len > 0 {
+ let mut recipients_ = Vec::new();
+ if recipients_len > 0 {
let recipients = recipients.expect("Recipients is NULL");
- unsafe {
+ let recipients = unsafe {
slice::from_raw_parts(recipients, recipients_len)
+ };
+ for recipient in recipients {
+ recipients_.push(recipient.ref_raw());
}
- } else {
- &[]
- };
- let recipients : Vec<&::sequoia_openpgp::TPK>
- = recipients.into_iter().map(|&tpk| tpk.ref_raw()).collect();
- let encryption_mode = match encryption_mode {
- 0 => EncryptionMode::AtRest,
- 1 => EncryptionMode::ForTransport,
- _ => panic!("Bad encryption mode: {}", encryption_mode),
};
let cipher_algo : Option<SymmetricAlgorithm> = if cipher_algo == 0 {
None
@@ -287,8 +352,7 @@ pub extern "C" fn pgp_encryptor_new
};
ffi_try_box!(Encryptor::new(*inner,
&passwords_.iter().collect::<Vec<&Password>>(),
- &recipients[..],
- encryption_mode,
+ recipients_,
cipher_algo,
aead_algo))
}