diff options
-rw-r--r-- | openpgp-ffi/include/sequoia/openpgp.h | 137 | ||||
-rw-r--r-- | openpgp-ffi/include/sequoia/openpgp/types.h | 18 | ||||
-rw-r--r-- | openpgp-ffi/src/amalgamation.rs | 112 | ||||
-rw-r--r-- | openpgp-ffi/src/cert.rs | 129 | ||||
-rw-r--r-- | openpgp-ffi/src/common.rs | 1 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/userid.rs | 13 |
6 files changed, 357 insertions, 53 deletions
diff --git a/openpgp-ffi/include/sequoia/openpgp.h b/openpgp-ffi/include/sequoia/openpgp.h index e9158f15..09b2f49e 100644 --- a/openpgp-ffi/include/sequoia/openpgp.h +++ b/openpgp-ffi/include/sequoia/openpgp.h @@ -570,7 +570,7 @@ pgp_packet_t pgp_literal_into_packet (pgp_literal_t literal); /*/ void pgp_literal_free (pgp_literal_t literal); -/* openpgp::cert::UserIDBundle. */ +/* openpgp::amalgamation::UserIDAmalgamation. */ /*/ /// Returns the user id. @@ -581,26 +581,105 @@ void pgp_literal_free (pgp_literal_t literal); /// /// The caller must free the returned value. /*/ -char *pgp_user_id_bundle_user_id (pgp_user_id_bundle_t binding); +char *pgp_user_id_amalgamation_user_id (pgp_user_id_amalgamation_t ua); /*/ -/// Returns a reference to the self-signature, if any. +/// Frees the User ID Amalgamation. /*/ -pgp_signature_t pgp_user_id_bundle_selfsig(pgp_error_t *errp, - pgp_user_id_bundle_t binding, - pgp_policy_t policy); +void pgp_user_id_amalgamation_free (pgp_user_id_amalgamation_t ua); -/* openpgp::cert::UserIDBundleIter. */ +/*/ +/// Clones the UserID Amalgamation. +/*/ +pgp_user_id_amalgamation_t pgp_user_id_amalgamation_clone (pgp_user_id_amalgamation_t ua); + +/*/ +/// Returns a human readable description of this object suitable for +/// debugging. +/*/ +char *pgp_user_id_amalgamation_debug (const pgp_user_id_amalgamation_t ua); + +/*/ +/// Returns the user id. +/// +/// This function may fail and return NULL if the user id contains an +/// interior NUL byte. We do this rather than complicate the API, as +/// there is no valid use for such user ids; they must be malicious. +/// +/// The caller must free the returned value. +/*/ +pgp_user_id_t pgp_valid_user_id_amalgamation_user_id + (pgp_valid_user_id_amalgamation_t ua); + +/*/ +/// Returns the Valid UserID Amalgamation's revocation status. +/*/ +pgp_revocation_status_t pgp_valid_user_id_amalgamation_revocation_status + (pgp_valid_user_id_amalgamation_t ua); + +/*/ +/// Returns a reference to the self-signature. +/*/ +pgp_signature_t pgp_valid_user_id_amalgamation_binding_signature + (pgp_valid_user_id_amalgamation_t ua); + +/*/ +/// Changes the policy applied to the `ValidUserIDAmalgamation`. +/// +/// This consumes the UserID amalgamation. +/*/ +pgp_valid_user_id_amalgamation_t pgp_valid_user_id_amalgamation_with_policy + (pgp_error_t *errp, + pgp_valid_user_id_amalgamation_t ua, + pgp_policy_t policy, + time_t time); + +/*/ +/// Frees the User ID Amalgamation. +/*/ +void pgp_valid_user_id_amalgamation_free (pgp_valid_user_id_amalgamation_t ua); + +/*/ +/// Clones the UserID Amalgamation. +/*/ +pgp_valid_user_id_amalgamation_t pgp_valid_user_id_amalgamation_clone (pgp_valid_user_id_amalgamation_t ua); + +/*/ +/// Returns a human readable description of this object suitable for +/// debugging. +/*/ +char *pgp_valid_user_id_amalgamation_debug (const pgp_valid_user_id_amalgamation_t ua); + +/* openpgp::cert::UserIDIter. */ + +/*/ +/// Returns the next element in the iterator. +/*/ +pgp_user_id_amalgamation_t pgp_cert_user_id_iter_next (pgp_cert_user_id_iter_t iter); + +/*/ +/// Sets a policy. +/// +/// Only User IDs that are valid according to the policy at the +/// specified time are returned. +/*/ +pgp_cert_valid_user_id_iter_t pgp_cert_user_id_iter_policy + (pgp_cert_user_id_iter_t iter, pgp_policy_t policy, time_t when); + +/*/ +/// Frees a pgp_cert_user_id_iter_t. +/*/ +void pgp_cert_user_id_iter_free (pgp_cert_user_id_iter_t iter); /*/ /// Returns the next element in the iterator. /*/ -pgp_user_id_bundle_t pgp_user_id_bundle_iter_next (pgp_user_id_bundle_iter_t iter); +pgp_valid_user_id_amalgamation_t pgp_cert_valid_user_id_iter_next (pgp_cert_valid_user_id_iter_t iter); /*/ -/// Frees an pgp_user_id_bundle_iter_t. +/// Frees a pgp_cert_valid_user_id_iter_t. /*/ -void pgp_user_id_bundle_iter_free (pgp_user_id_bundle_iter_t iter); +void pgp_cert_valid_user_id_iter_free (pgp_cert_valid_user_id_iter_t iter); /* openpgp::cert::KeyIter. */ @@ -620,10 +699,10 @@ void pgp_cert_key_iter_secret (pgp_cert_key_iter_t iter); void pgp_cert_key_iter_unencrypted_secret (pgp_cert_key_iter_t iter); /*/ -/// Changes the iterator to only return keys that have unencrypted -/// secret keys. +/// Sets a policy. /// -/// Note: you may not call this function after starting to iterate. +/// Only keys that are valid according to the policy at the specified +/// time are returned. /*/ pgp_cert_valid_key_iter_t pgp_cert_key_iter_policy (pgp_cert_key_iter_t iter, pgp_policy_t policy, time_t when); @@ -925,9 +1004,16 @@ pgp_cert_t pgp_cert_set_expiration_time(pgp_error_t *errp, int pgp_cert_is_tsk(pgp_cert_t cert); /*/ -/// Returns an iterator over the `UserIDBundle`s. +/// Returns an iterator over the `UserID`s. /*/ -pgp_user_id_bundle_iter_t pgp_cert_user_id_bundle_iter (pgp_cert_t cert); +pgp_cert_user_id_iter_t pgp_cert_user_id_iter (pgp_cert_t cert); + +/*/ +/// Returns an iterator over the valid `UserID`s. +/*/ +pgp_cert_valid_user_id_iter_t pgp_cert_valid_user_id_iter (pgp_cert_t cert, + pgp_policy_t policy, + time_t when); /*/ /// Returns an iterator over all `Key`s in a Cert. @@ -1361,6 +1447,27 @@ const uint8_t *pgp_user_attribute_value (pgp_packet_t ua, size_t *value_len); /*/ +/// Frees a pgp_user_id_t. +/*/ +void pgp_user_id_free (pgp_user_id_t userid); + +/*/ +/// Clones the UserID. +/*/ +pgp_user_id_t pgp_user_id_clone (pgp_user_id_t userid); + +/*/ +/// Returns a human readable description of this object suitable for +/// debugging. +/*/ +char *pgp_user_id_debug (const pgp_user_id_t userid); + +/*/ +/// Compares passwords. +/*/ +bool pgp_user_id_equal (const pgp_user_id_t a, const pgp_user_id_t b); + +/*/ /// Returns the session key. /// /// `key` of size `key_len` must be a buffer large enough to hold the diff --git a/openpgp-ffi/include/sequoia/openpgp/types.h b/openpgp-ffi/include/sequoia/openpgp/types.h index 14c4ef08..74b4f1d6 100644 --- a/openpgp-ffi/include/sequoia/openpgp/types.h +++ b/openpgp-ffi/include/sequoia/openpgp/types.h @@ -364,14 +364,24 @@ typedef struct pgp_packet_parser_eof *pgp_packet_parser_eof_t; typedef struct pgp_packet_pile *pgp_packet_pile_t; /*/ -/// A `UserIDBinding`. +/// An iterator over User IDs in a Cert. /*/ -typedef struct pgp_user_id_bundle *pgp_user_id_bundle_t; +typedef struct pgp_cert_user_id_iter *pgp_cert_user_id_iter_t; /*/ -/// An iterator over `UserIDBinding`s. +/// An iterator over valid User IDs in a Cert. /*/ -typedef struct pgp_user_id_bundle_iter *pgp_user_id_bundle_iter_t; +typedef struct pgp_cert_valid_user_id_iter *pgp_cert_valid_user_id_iter_t; + +/*/ +/// A `UserIDAmalgmation`. +/*/ +typedef struct pgp_user_id_amalgamation *pgp_user_id_amalgamation_t; + +/*/ +/// A `UserIDAmalgmation`. +/*/ +typedef struct pgp_valid_user_id_amalgamation *pgp_valid_user_id_amalgamation_t; /*/ /// An iterator over keys in a Cert. diff --git a/openpgp-ffi/src/amalgamation.rs b/openpgp-ffi/src/amalgamation.rs new file mode 100644 index 00000000..248fe24f --- /dev/null +++ b/openpgp-ffi/src/amalgamation.rs @@ -0,0 +1,112 @@ +//! `KeyAmalgamation`s. +//! +//! +//! Wraps [`sequoia-openpgp::cert::key_amalgamation::KeyAmalgamation`]. +//! +//! [`sequoia-openpgp::cert::key_amalgamation::KeyAmalgamation`]: ../../../sequoia_openpgp/cert/key_amalgamation/struct.KeyAmalgamation.html + +use libc::time_t; + +extern crate sequoia_openpgp as openpgp; + +use self::openpgp::cert::amalgamation::ValidAmalgamation as _; +use self::openpgp::cert::amalgamation::ValidateAmalgamation as _; + +use super::packet::userid::UserID; +use super::packet::signature::Signature; +use super::policy::Policy; +use super::revocation_status::RevocationStatus; + +use crate::Maybe; +use crate::MoveIntoRaw; +use crate::MoveResultIntoRaw; +use crate::RefRaw; +use crate::MoveFromRaw; +use crate::maybe_time; + +/// A local alias to appease the proc macro transformation. +type UserIDAmalgamationType<'a> + = openpgp::cert::amalgamation::ComponentAmalgamation<'a, openpgp::packet::UserID>; + +/// A `UserIDAmalgamation` holds a `UserID` and associated data. +/// +/// Wraps [`sequoia-openpgp::cert::amalgamation::ComponentAmalgamation`]. +/// +/// [`sequoia-openpgp::cert::amalgamation::ComponentAmalgamation`]: ../../../sequoia_openpgp/cert/amalgamation/struct.ComponentAmalgamation.html +#[crate::ffi_wrapper_type(prefix = "pgp_", + derive = "Clone, Debug")] +pub struct UserIDAmalgamation<'a>(UserIDAmalgamationType<'a>); + +/// Returns a reference to the `UserID`. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "C" fn pgp_user_id_amalgamation_user_id<'a>(ua: *const UserIDAmalgamation<'a>) + -> *const UserID +{ + let ua = ua.ref_raw(); + + ua.userid().move_into_raw() +} + +/// A local alias to appease the proc macro transformation. +type ValidUserIDAmalgamationType<'a> + = openpgp::cert::amalgamation::ValidComponentAmalgamation<'a, openpgp::packet::UserID>; + +/// A `ValidUserIDAmalgamation` holds a `UserID` and associated data +/// including a policy and a reference time. +/// +/// Wraps [`sequoia-openpgp::cert::amalgamation::ValidComponentAmalgamation`]. +/// +/// [`sequoia-openpgp::cert::amalgamation::ValidComponentAmalgamation`]: ../../../sequoia_openpgp/cert/amalgamation/struct.ValidComponentAmalgamation.html +#[crate::ffi_wrapper_type(prefix = "pgp_", + derive = "Clone, Debug")] +pub struct ValidUserIDAmalgamation<'a>(ValidUserIDAmalgamationType<'a>); + +/// Returns a reference to the `UserID`. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "C" fn pgp_valid_user_id_amalgamation_user_id<'a>(ua: *const ValidUserIDAmalgamation<'a>) + -> *const UserID +{ + let ua = ua.ref_raw(); + + ua.userid().move_into_raw() +} + +/// Returns the UserID's revocation status. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "C" fn pgp_valid_user_id_amalgamation_revocation_status<'a>(ua: *const ValidUserIDAmalgamation<'a>) + -> *mut RevocationStatus<'a> +{ + ua.ref_raw() + .revoked() + .move_into_raw() +} + +/// Returns the User ID's binding signature. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "C" fn pgp_valid_user_id_amalgamation_binding_signature<'a>(ua: *const ValidUserIDAmalgamation<'a>) + -> *const Signature +{ + ua.ref_raw() + .binding_signature() + .move_into_raw() +} + +/// Changes the policy applied to the `ValidUserIDAmalgamation`. +/// +/// This consumes the User ID amalgamation. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "C" +fn pgp_valid_user_id_amalgamation_with_policy<'a>(errp: Option<&mut *mut crate::error::Error>, + ua: *mut ValidUserIDAmalgamation<'a>, + policy: *const Policy, + time: time_t) + -> Maybe<ValidUserIDAmalgamation<'a>> +{ + ffi_make_fry_from_errp!(errp); + + let ua = ua.move_from_raw(); + let policy = policy.ref_raw(); + let time = maybe_time(time); + + ua.with_policy(&**policy, time).move_into_raw(errp) +} diff --git a/openpgp-ffi/src/cert.rs b/openpgp-ffi/src/cert.rs index 9c3f43ad..eb32d5a0 100644 --- a/openpgp-ffi/src/cert.rs +++ b/openpgp-ffi/src/cert.rs @@ -29,6 +29,7 @@ use super::packet_pile::PacketPile; use super::tsk::TSK; use super::revocation_status::RevocationStatus; use super::policy::Policy; +use super::amalgamation::{UserIDAmalgamation, ValidUserIDAmalgamation}; use super::key_amalgamation::{KeyAmalgamation, ValidKeyAmalgamation}; use crate::Maybe; @@ -371,68 +372,128 @@ fn pgp_cert_primary_user_id(cert: *const Cert, policy: *const Policy, } } -/* UserIDBundle */ +/* UserIDIter */ -/// Returns the user id. -/// -/// This function may fail and return NULL if the user id contains an -/// interior NUL byte. We do this rather than complicate the API, as -/// there is no valid use for such user ids; they must be malicious. +/// Wraps a UserIDIter for export via the FFI. +pub struct UserIDIterWrapper<'a> { + pub(crate) // For serialize.rs. + iter: Option<ComponentIter<'a, openpgp::packet::UserID>>, + // Whether next has been called. + next_called: bool, +} + +/// Returns an iterator over the Cert's user ids. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "C" fn pgp_cert_user_id_iter(cert: *const Cert) + -> *mut UserIDIterWrapper<'static> +{ + let cert = cert.ref_raw(); + box_raw!(UserIDIterWrapper { + iter: Some(cert.userids()), + next_called: false, + }) +} + +/// Changes the iterator to only return keys that are valid at time +/// `t`. /// -/// The caller must free the returned value. +/// Note: you may not call this function after starting to iterate. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] -pub extern "C" fn pgp_user_id_bundle_user_id( - binding: *const UserIDBundle) - -> *mut c_char +pub extern "C" fn pgp_cert_user_id_iter_policy<'a>( + iter_wrapper: *mut UserIDIterWrapper<'a>, + policy: *const Policy, + when: time_t) + -> *mut ValidUserIDIterWrapper<'static> { - let binding = ffi_param_ref!(binding); + let policy = policy.ref_raw(); + let iter_wrapper = ffi_param_ref_mut!(iter_wrapper); + if iter_wrapper.next_called { + panic!("Can't change UserIDIter filter after iterating."); + } - ffi_return_maybe_string!(binding.userid().value()) + use std::mem::transmute; + box_raw!(ValidUserIDIterWrapper { + iter: Some(unsafe { + transmute(iter_wrapper.iter.take().unwrap() + .with_policy(&**policy, maybe_time(when))) + }), + next_called: false, + }) } -/// Returns a reference to the self-signature, if any. + +/// Frees a pgp_user_id_iter_t. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] -pub extern "C" fn pgp_user_id_bundle_selfsig( - errp: Option<&mut *mut crate::error::Error>, - binding: *const UserIDBundle, - policy: *const Policy) - -> Maybe<Signature> +pub extern "C" fn pgp_cert_user_id_iter_free( + iter: Option<&mut UserIDIterWrapper>) { - let binding = ffi_param_ref!(binding); - let policy = &**policy.ref_raw(); - binding.binding_signature(policy, None).move_into_raw(errp) + ffi_free!(iter) } +/// Returns the next `UserIDAmalgamation`. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] +pub extern "C" fn pgp_cert_user_id_iter_next<'a>( + iter_wrapper: *mut UserIDIterWrapper<'a>) + -> Maybe<UserIDAmalgamation<'a>> +{ + let iter_wrapper = ffi_param_ref_mut!(iter_wrapper); + iter_wrapper.next_called = true; + + if let Some(ua) = iter_wrapper.iter.as_mut().unwrap().next() { + Some(ua).move_into_raw() + } else { + None + } +} -/* UserIDBundleIter */ +/// Wraps a ValidKeyIter for export via the FFI. +pub struct ValidUserIDIterWrapper<'a> { + pub(crate) // For serialize.rs. + iter: Option<ValidComponentIter<'a, openpgp::packet::UserID>>, + // Whether next has been called. + next_called: bool, +} /// Returns an iterator over the Cert's user id bundles. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] -pub extern "C" fn pgp_cert_user_id_bundle_iter(cert: *const Cert) - -> *mut UserIDBundleIter<'static> +pub extern "C" fn pgp_cert_valid_user_id_iter(cert: *const Cert, + policy: *const Policy, when: time_t) + -> *mut ValidUserIDIterWrapper<'static> { let cert = cert.ref_raw(); - box_raw!(cert.userids().bundles()) + let iter = box_raw!(UserIDIterWrapper { + iter: Some(cert.userids()), + next_called: false, + }); + + pgp_cert_user_id_iter_policy(iter, policy, when) } -/// Frees a pgp_user_id_bundle_iter_t. +/// Frees a pgp_user_id_iter_t. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] -pub extern "C" fn pgp_user_id_bundle_iter_free( - iter: Option<&mut UserIDBundleIter>) +pub extern "C" fn pgp_cert_valid_user_id_iter_free( + iter: Option<&mut ValidUserIDIterWrapper>) { ffi_free!(iter) } -/// Returns the next `UserIDBundle`. +/// Returns the next `UserIDAmalgamation`. #[::sequoia_ffi_macros::extern_fn] #[no_mangle] -pub extern "C" fn pgp_user_id_bundle_iter_next<'a>( - iter: *mut UserIDBundleIter<'a>) - -> Option<&'a UserIDBundle> +pub extern "C" fn pgp_cert_valid_user_id_iter_next<'a>( + iter_wrapper: *mut ValidUserIDIterWrapper<'a>) + -> Maybe<ValidUserIDAmalgamation<'a>> { - let iter = ffi_param_ref_mut!(iter); - iter.next() + let iter_wrapper = ffi_param_ref_mut!(iter_wrapper); + iter_wrapper.next_called = true; + + if let Some(ua) = iter_wrapper.iter.as_mut().unwrap().next() { + Some(ua).move_into_raw() + } else { + None + } } + /* cert::KeyIter. */ /// Wraps a KeyIter for export via the FFI. diff --git a/openpgp-ffi/src/common.rs b/openpgp-ffi/src/common.rs index cc2deb5e..529a33e5 100644 --- a/openpgp-ffi/src/common.rs +++ b/openpgp-ffi/src/common.rs @@ -344,3 +344,4 @@ pub mod tsk; pub mod revocation_status; pub mod policy; pub mod key_amalgamation; +pub mod amalgamation; diff --git a/openpgp-ffi/src/packet/userid.rs b/openpgp-ffi/src/packet/userid.rs index 69e49b42..339f1486 100644 --- a/openpgp-ffi/src/packet/userid.rs +++ b/openpgp-ffi/src/packet/userid.rs @@ -12,6 +12,19 @@ use super::Packet; use crate::RefRaw; use crate::MoveIntoRaw; +/// Holds a UserID packet. +/// +/// See [Section 5.11 of RFC 4880] for details. +/// +/// [Section 5.11 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.11 +/// +/// Wraps [`sequoia-openpgp::packet::UserID`]. +/// +/// [`sequoia-openpgp::packet::UserID`]: ../../../sequoia_openpgp/packet/struct.UserID.html +#[crate::ffi_wrapper_type(prefix = "pgp_", + derive = "Clone, Debug, PartialEq")] +pub struct UserID(openpgp::packet::UserID); + /// Create a new User ID with the value `value`. /// /// `value` need not be valid UTF-8, but it must be NUL terminated. |