summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp-ffi')
-rw-r--r--openpgp-ffi/Cargo.toml8
-rw-r--r--openpgp-ffi/Makefile4
-rw-r--r--openpgp-ffi/examples/decrypt-with.c8
-rw-r--r--openpgp-ffi/include/sequoia/openpgp.h223
-rw-r--r--openpgp-ffi/include/sequoia/openpgp/crypto.h4
-rw-r--r--openpgp-ffi/include/sequoia/openpgp/packet.h2
-rw-r--r--openpgp-ffi/include/sequoia/openpgp/types.h29
-rw-r--r--openpgp-ffi/src/amalgamation.rs112
-rw-r--r--openpgp-ffi/src/armor.rs2
-rw-r--r--openpgp-ffi/src/cert.rs309
-rw-r--r--openpgp-ffi/src/common.rs1
-rw-r--r--openpgp-ffi/src/fingerprint.rs6
-rw-r--r--openpgp-ffi/src/io.rs6
-rw-r--r--openpgp-ffi/src/key_amalgamation.rs54
-rw-r--r--openpgp-ffi/src/keyid.rs2
-rw-r--r--openpgp-ffi/src/packet/key.rs2
-rw-r--r--openpgp-ffi/src/packet/pkesk.rs8
-rw-r--r--openpgp-ffi/src/packet/userid.rs13
-rw-r--r--openpgp-ffi/src/parse/stream.rs204
-rw-r--r--openpgp-ffi/src/serialize.rs63
20 files changed, 699 insertions, 361 deletions
diff --git a/openpgp-ffi/Cargo.toml b/openpgp-ffi/Cargo.toml
index 7afedee4..ba7f7d0c 100644
--- a/openpgp-ffi/Cargo.toml
+++ b/openpgp-ffi/Cargo.toml
@@ -1,13 +1,13 @@
[package]
name = "sequoia-openpgp-ffi"
description = "C API for Sequoia's low-level OpenPGP crate"
-version = "0.15.0"
+version = "0.17.0"
authors = [
"Justus Winter <justus@sequoia-pgp.org>",
"Kai Michaelis <kai@sequoia-pgp.org>",
"Neal H. Walfield <neal@sequoia-pgp.org>",
]
-documentation = "https://docs.sequoia-pgp.org/0.15.0/sequoia_openpgp_ffi"
+documentation = "https://docs.sequoia-pgp.org/0.17.0/sequoia_openpgp_ffi"
homepage = "https://sequoia-pgp.org/"
repository = "https://gitlab.com/sequoia-pgp/sequoia"
readme = "../README.md"
@@ -22,8 +22,8 @@ gitlab = { repository = "sequoia-pgp/sequoia" }
maintenance = { status = "actively-developed" }
[dependencies]
-sequoia-ffi-macros = { path = "../ffi-macros", version = "0.15" }
-sequoia-openpgp = { path = "../openpgp", version = "0.15" }
+sequoia-ffi-macros = { path = "../ffi-macros", version = "0.17" }
+sequoia-openpgp = { path = "../openpgp", version = "0.17" }
anyhow = "1"
lazy_static = "1.0.0"
libc = "0.2.33"
diff --git a/openpgp-ffi/Makefile b/openpgp-ffi/Makefile
index 8d01c41e..49511468 100644
--- a/openpgp-ffi/Makefile
+++ b/openpgp-ffi/Makefile
@@ -31,10 +31,10 @@ export PREFIX
export DESTDIR
# $(1) = install dir
-# $(2) = whether to set libdir to $(1) (empty string = false)
+# $(2) = whether to set libdir and prefix to $(1) (empty string = false)
sequoia_openpgp_pc = \
sed -e 's|VERSION|$(VERSION)|g' \
- -e 's|PREFIX|$(shell pwd)|g' \
+ $(if $(2),-e 's|PREFIX|$(shell pwd)|g',-e's|PREFIX|$(PREFIX)|g') \
$(if $(2),-e 's|libdir=.*|libdir=$(1)|g') \
sequoia-openpgp.pc.in \
> $(1)/sequoia-openpgp.pc
diff --git a/openpgp-ffi/examples/decrypt-with.c b/openpgp-ffi/examples/decrypt-with.c
index b6fff7b1..4519a2f1 100644
--- a/openpgp-ffi/examples/decrypt-with.c
+++ b/openpgp-ffi/examples/decrypt-with.c
@@ -26,7 +26,7 @@ struct decrypt_cookie {
};
static pgp_status_t
-get_public_keys_cb (void *cookie_raw,
+get_certs_cb (void *cookie_raw,
pgp_keyid_t *keyids, size_t keyids_len,
pgp_cert_t **certs, size_t *cert_len,
void (**our_free)(void *))
@@ -41,7 +41,8 @@ get_public_keys_cb (void *cookie_raw,
static pgp_status_t
check_cb (void *cookie_opaque, pgp_message_structure_t structure)
{
- pgp_message_structure_iter_t iter = pgp_message_structure_iter (structure);
+ pgp_message_structure_iter_t iter =
+ pgp_message_structure_into_iter (structure);
for (pgp_message_layer_t layer = pgp_message_structure_iter_next (iter);
layer;
@@ -142,7 +143,6 @@ check_cb (void *cookie_opaque, pgp_message_structure_t structure)
}
pgp_message_structure_iter_free (iter);
- pgp_message_structure_free (structure);
/* Implement your verification policy here. */
return PGP_STATUS_SUCCESS;
@@ -236,7 +236,7 @@ main (int argc, char **argv)
.decrypt_called = 0,
};
plaintext = pgp_decryptor_new (&err, policy, source,
- get_public_keys_cb, decrypt_cb,
+ get_certs_cb, decrypt_cb,
check_cb, NULL, &cookie, 0);
if (! plaintext)
error (1, 0, "pgp_decryptor_new: %s", pgp_error_to_string (err));
diff --git a/openpgp-ffi/include/sequoia/openpgp.h b/openpgp-ffi/include/sequoia/openpgp.h
index 6b3e90c0..9b6dadd1 100644
--- a/openpgp-ffi/include/sequoia/openpgp.h
+++ b/openpgp-ffi/include/sequoia/openpgp.h
@@ -60,7 +60,7 @@ char *pgp_keyid_to_hex (const pgp_keyid_t keyid);
/*/
/// Compares KeyIDs.
/*/
-int pgp_keyid_equal (const pgp_keyid_t a, const pgp_keyid_t b);
+bool pgp_keyid_equal (const pgp_keyid_t a, const pgp_keyid_t b);
/* sequoia::openpgp::Fingerprint. */
@@ -122,7 +122,7 @@ pgp_keyid_t pgp_fingerprint_to_keyid (const pgp_fingerprint_t fp);
/*/
/// Compares Fingerprints.
/*/
-int pgp_fingerprint_equal (const pgp_fingerprint_t a, const pgp_fingerprint_t b);
+bool pgp_fingerprint_equal (const pgp_fingerprint_t a, const pgp_fingerprint_t b);
/* sequoia::openpgp::RevocationStatus. */
@@ -570,38 +570,110 @@ 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.
+/// Returns a copy of 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_packet_t pgp_user_id_amalgamation_user_id (pgp_user_id_amalgamation_t ua);
+
+/*/
+/// Frees the User ID Amalgamation.
+/*/
+void pgp_user_id_amalgamation_free (pgp_user_id_amalgamation_t ua);
+
+/*/
+/// 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 a copy of the user id.
///
/// The caller must free the returned value.
/*/
-char *pgp_user_id_bundle_user_id (pgp_user_id_bundle_t binding);
+pgp_packet_t pgp_valid_user_id_amalgamation_user_id
+ (pgp_valid_user_id_amalgamation_t ua);
/*/
-/// Returns a reference to the self-signature, if any.
+/// Returns the Valid UserID Amalgamation's revocation status.
/*/
-pgp_signature_t pgp_user_id_bundle_selfsig(pgp_user_id_bundle_t binding,
- pgp_policy_t policy);
+pgp_revocation_status_t pgp_valid_user_id_amalgamation_revocation_status
+ (pgp_valid_user_id_amalgamation_t ua);
-/* openpgp::cert::UserIDBundleIter. */
+/*/
+/// 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. */
+/* openpgp::cert::KeyAmalgamationIter. */
/*/
/// Changes the iterator to only return keys that have secret keys.
@@ -619,10 +691,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);
@@ -794,7 +866,7 @@ pgp_cert_t pgp_cert_clone (pgp_cert_t cert);
/*/
/// Compares Certs.
/*/
-int pgp_cert_equal (const pgp_cert_t a, const pgp_cert_t b);
+bool pgp_cert_equal (const pgp_cert_t a, const pgp_cert_t b);
/*/
/// Returns a human readable description of this object intended for
@@ -874,30 +946,30 @@ pgp_key_t pgp_cert_primary_key (pgp_cert_t cert);
/// If `when` is 0, then returns the Cert's revocation status as of the
/// time of the call.
/*/
-pgp_revocation_status_t pgp_cert_revoked (pgp_cert_t cert,
- pgp_policy_t policy, time_t when);
+pgp_revocation_status_t pgp_cert_revocation_status (pgp_cert_t cert,
+ pgp_policy_t policy, time_t when);
/*/
-/// Writes a revocation certificate to the writer.
+/// Returns a new revocation certificate for the Cert.
///
-/// This function consumes the writer. It does *not* consume cert.
+/// This function does *not* consume `cert`.
/*/
pgp_signature_t pgp_cert_revoke (pgp_error_t *errp,
- pgp_cert_t cert,
- pgp_signer_t primary_signer,
- pgp_reason_for_revocation_t code,
- const char *reason);
+ pgp_cert_t cert,
+ pgp_signer_t primary_signer,
+ pgp_reason_for_revocation_t code,
+ const char *reason);
/*/
-/// Adds a revocation certificate to the cert.
+/// Returns a new revocation certificate for the Cert.
///
-/// This function consumes the cert.
+/// This function consumes `cert` and returns a new `Cert`.
/*/
pgp_cert_t pgp_cert_revoke_in_place (pgp_error_t *errp,
- pgp_cert_t cert,
- pgp_signer_t primary_signer,
- pgp_reason_for_revocation_t code,
- const char *reason);
+ pgp_cert_t cert,
+ pgp_signer_t primary_signer,
+ pgp_reason_for_revocation_t code,
+ const char *reason);
/*/
/// Returns whether the Cert is alive at the specified time.
@@ -924,9 +996,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.
@@ -980,7 +1059,7 @@ pgp_cert_parser_t pgp_cert_parser_from_packet_parser(pgp_packet_parser_result_t
pgp_cert_t pgp_cert_parser_next(pgp_error_t *errp, pgp_cert_parser_t parser);
/*/
-/// Frees an pgp_cert_key_iter_t.
+/// Frees an pgp_cert_parser_t.
/*/
void pgp_cert_parser_free (pgp_cert_parser_t parser);
@@ -1106,8 +1185,19 @@ pgp_status_t pgp_valid_key_amalgamation_set_expiration_time
pgp_valid_key_amalgamation_t ka,
pgp_signer_t signer,
time_t time,
- pgp_packet_t **packets,
- size_t *packet_count);
+ pgp_signature_t **sigs,
+ size_t *sig_count);
+
+/*/
+/// Changes the policy applied to the `ValidKeyAmalgamation`.
+///
+/// This consumes the key amalgamation.
+/*/
+pgp_valid_key_amalgamation_t pgp_valid_key_amalgamation_with_policy
+ (pgp_error_t *errp,
+ pgp_valid_key_amalgamation_t ka,
+ pgp_policy_t policy,
+ time_t time);
/*/
/// Frees the Valid Key Amalgamation.
@@ -1349,6 +1439,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
@@ -1715,7 +1826,7 @@ void pgp_message_structure_free (pgp_message_structure_t);
char *pgp_message_structure_debug (const pgp_message_structure_t);
pgp_message_structure_iter_t
-pgp_message_structure_iter (pgp_message_structure_t);
+pgp_message_structure_into_iter (pgp_message_structure_t);
/*/
/// Frees this object.
@@ -1825,7 +1936,7 @@ bool pgp_verification_result_bad_signature (pgp_verification_result_t,
pgp_reader_t pgp_decryptor_new (pgp_error_t *errp,
pgp_policy_t policy,
pgp_reader_t input,
- pgp_decryptor_get_public_keys_cb_t get_public_keys,
+ pgp_decryptor_get_certs_cb_t get_certs,
pgp_decryptor_decrypt_cb_t decrypt,
pgp_decryptor_check_cb_t check,
pgp_decryptor_inspect_cb_t inspect,
@@ -1840,27 +1951,35 @@ pgp_reader_t pgp_decryptor_new (pgp_error_t *errp,
pgp_reader_t pgp_verifier_new (pgp_error_t *errp,
pgp_policy_t policy,
pgp_reader_t input,
- pgp_decryptor_get_public_keys_cb_t get_public_keys,
+ pgp_decryptor_get_certs_cb_t get_certs,
pgp_decryptor_check_cb_t check,
+ pgp_decryptor_inspect_cb_t inspect,
void *cookie, time_t time);
/*/
-/// Verifies a detached OpenPGP signature.///
-/// A Certificate (see [RFC 4880, section 11.1]) can be used to verify
-/// signatures and encrypt data. It can be stored in a keystore and
-/// uploaded to keyservers.
-///
-/// [RFC 4880, section 11.1]: https://tools.ietf.org/html/rfc4880#section-11.1
-
+/// Verifies a detached OpenPGP signature.
/*/
-pgp_reader_t pgp_detached_verifier_new (pgp_error_t *errp,
+pgp_detached_verifier_t pgp_detached_verifier_new (pgp_error_t *errp,
pgp_policy_t policy,
- pgp_reader_t signature_input, pgp_reader_t input,
- pgp_decryptor_get_public_keys_cb_t get_public_keys,
+ pgp_reader_t signature_input,
+ pgp_decryptor_get_certs_cb_t get_certs,
pgp_decryptor_check_cb_t check,
+ pgp_decryptor_inspect_cb_t inspect,
void *cookie, time_t time);
/*/
+/// Frees this object.
+/*/
+void pgp_detached_verifier_free (pgp_detached_verifier_t);
+
+/*/
+/// Verifies `data` using `verifier`.
+/*/
+pgp_status_t pgp_detached_verifier_verify (pgp_error_t *errp,
+ pgp_detached_verifier_t verifier,
+ pgp_reader_t data);
+
+/*/
/// Returns a new standard policy.
/*/
pgp_policy_t pgp_standard_policy ();
diff --git a/openpgp-ffi/include/sequoia/openpgp/crypto.h b/openpgp-ffi/include/sequoia/openpgp/crypto.h
index 9a3c3964..d0330da4 100644
--- a/openpgp-ffi/include/sequoia/openpgp/crypto.h
+++ b/openpgp-ffi/include/sequoia/openpgp/crypto.h
@@ -32,7 +32,7 @@ pgp_session_key_t pgp_session_key_clone (pgp_session_key_t session_key);
/*/
/// Compares session keys.
/*/
-int pgp_session_key_equal (const pgp_session_key_t a,
+bool pgp_session_key_equal (const pgp_session_key_t a,
const pgp_session_key_t b);
/*/
@@ -59,7 +59,7 @@ pgp_password_t pgp_password_clone (pgp_password_t password);
/*/
/// Compares passwords.
/*/
-int pgp_password_equal (const pgp_password_t a, const pgp_password_t b);
+bool pgp_password_equal (const pgp_password_t a, const pgp_password_t b);
typedef struct pgp_key_unencrypted *pgp_key_unencrypted_t;
diff --git a/openpgp-ffi/include/sequoia/openpgp/packet.h b/openpgp-ffi/include/sequoia/openpgp/packet.h
index 8035b0c3..702ad355 100644
--- a/openpgp-ffi/include/sequoia/openpgp/packet.h
+++ b/openpgp-ffi/include/sequoia/openpgp/packet.h
@@ -20,7 +20,7 @@ char *pgp_packet_debug (const pgp_packet_t fp);
/*/
/// Compares objects of this kind.
/*/
-int pgp_packet_equal (const pgp_packet_t a, const pgp_packet_t b);
+bool pgp_packet_equal (const pgp_packet_t a, const pgp_packet_t b);
/*/
/// Hashes this object.
diff --git a/openpgp-ffi/include/sequoia/openpgp/types.h b/openpgp-ffi/include/sequoia/openpgp/types.h
index ec883df6..216c69cb 100644
--- a/openpgp-ffi/include/sequoia/openpgp/types.h
+++ b/openpgp-ffi/include/sequoia/openpgp/types.h
@@ -1,6 +1,8 @@
#ifndef SEQUOIA_OPENPGP_TYPES_H
#define SEQUOIA_OPENPGP_TYPES_H
+#include <stdbool.h>
+
/*/
/// Holds a session key.
///
@@ -364,14 +366,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_cert_user_id_iter *pgp_cert_user_id_iter_t;
+
+/*/
+/// An iterator over valid User IDs in a Cert.
+/*/
+typedef struct pgp_cert_valid_user_id_iter *pgp_cert_valid_user_id_iter_t;
+
+/*/
+/// A `UserIDAmalgmation`.
/*/
-typedef struct pgp_user_id_bundle *pgp_user_id_bundle_t;
+typedef struct pgp_user_id_amalgamation *pgp_user_id_amalgamation_t;
/*/
-/// An iterator over `UserIDBinding`s.
+/// A `UserIDAmalgmation`.
/*/
-typedef struct pgp_user_id_bundle_iter *pgp_user_id_bundle_iter_t;
+typedef struct pgp_valid_user_id_amalgamation *pgp_valid_user_id_amalgamation_t;
/*/
/// An iterator over keys in a Cert.
@@ -509,12 +521,12 @@ typedef enum pgp_verification_result_variant {
PGP_VERIFICATION_RESULT_CODE_FORCE_WIDTH = INT_MAX,
} pgp_verification_result_variant_t;
-typedef pgp_status_t (*pgp_decryptor_get_public_keys_cb_t) (void *,
+typedef pgp_status_t (*pgp_decryptor_get_certs_cb_t) (void *,
pgp_keyid_t *, size_t,
pgp_cert_t **, size_t *,
void (**free)(void *));
-typedef pgp_status_t (pgp_decryptor_do_decrypt_cb_t) (
+typedef bool (pgp_decryptor_do_decrypt_cb_t) (
void *,
uint8_t,
pgp_session_key_t);
@@ -534,6 +546,11 @@ typedef pgp_status_t (*pgp_decryptor_inspect_cb_t) (void *,
pgp_packet_parser_t);
/*/
+/// Verifies a detached signature.
+/*/
+typedef struct pgp_detached_verifier *pgp_detached_verifier_t;
+
+/*/
/// An OpenPGP policy.
/*/
typedef struct pgp_policy *pgp_policy_t;
diff --git a/openpgp-ffi/src/amalgamation.rs b/openpgp-ffi/src/amalgamation.rs
new file mode 100644
index 00000000..18cf83e8
--- /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::Packet;
+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::UserIDAmalgamation<'a>;
+
+/// 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 copy of the `UserID`.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
+pub extern "C" fn pgp_user_id_amalgamation_user_id<'a>(ua: *const UserIDAmalgamation<'a>)
+ -> *mut Packet
+{
+ let ua = ua.ref_raw();
+
+ openpgp::Packet::from(ua.userid().clone()).move_into_raw()
+}
+
+/// A local alias to appease the proc macro transformation.
+type ValidUserIDAmalgamationType<'a>
+ = openpgp::cert::amalgamation::ValidUserIDAmalgamation<'a>;
+
+/// 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 Packet
+{
+ let ua = ua.ref_raw();
+
+ openpgp::Packet::from(ua.userid().clone()).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()
+ .revocation_status()
+ .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/armor.rs b/openpgp-ffi/src/armor.rs
index dd79c9e3..094d4dc7 100644
--- a/openpgp-ffi/src/armor.rs
+++ b/openpgp-ffi/src/armor.rs
@@ -389,7 +389,7 @@ pub extern "C" fn pgp_armor_writer_new
let header: Vec<(&str, &str)> =
header_.iter().map(|h| (h.0.as_ref(), h.1.as_ref())).collect();
- armor::Writer::new(inner, kind, &header)
+ armor::Writer::with_headers(inner, kind, header)
.map(|w| WriterKind::Armored(w))
.map_err(|e| ::anyhow::Error::from(e))
.move_into_raw(errp)
diff --git a/openpgp-ffi/src/cert.rs b/openpgp-ffi/src/cert.rs
index 5f04ac8c..b2e8a576 100644
--- a/openpgp-ffi/src/cert.r