summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <neal@pep.foundation>2020-04-02 14:48:03 +0200
committerNeal H. Walfield <neal@pep.foundation>2020-04-02 16:42:54 +0200
commit789ae8615fda8e6dcbc1a39625e322255da90cef (patch)
tree97b8fec96ef1bfcd1d7c09a264d138803a6b85c0
parent6dd60b0b306e5d69b8770a5fa1f0bbfcead2270c (diff)
openpgp-ffi: Use UserIDAmalgamations, not UserIDBundles.
- Add the `UserID`, `UserIDAmalgamation` and `ValidUserIDAmalgamation` types, and some associated methods. - Replace the use of `UserIDBundle` with `UserIDAmalgamation` and `ValidUserIDAmalgamation`.
-rw-r--r--openpgp-ffi/include/sequoia/openpgp.h137
-rw-r--r--openpgp-ffi/include/sequoia/openpgp/types.h18
-rw-r--r--openpgp-ffi/src/amalgamation.rs112
-rw-r--r--openpgp-ffi/src/cert.rs129
-rw-r--r--openpgp-ffi/src/common.rs1
-rw-r--r--openpgp-ffi/src/packet/userid.rs13
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.