summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-05-09 15:19:24 +0200
committerJustus Winter <justus@sequoia-pgp.org>2019-05-09 15:19:24 +0200
commit75d4e6dda12e8b7ae8573227e61e718ede3f2cfc (patch)
treec6b9e3f177d8c65d134acfd889c236203b2ac13f /openpgp-ffi
parent8e0f817f312f469871a5fbed6bb961f6117ba742 (diff)
openpgp: Communicate message structure from the decryptor.
- Fixes #100.
Diffstat (limited to 'openpgp-ffi')
-rw-r--r--openpgp-ffi/examples/decrypt-with.c87
-rw-r--r--openpgp-ffi/include/sequoia/openpgp.h96
-rw-r--r--openpgp-ffi/include/sequoia/openpgp/types.h37
-rw-r--r--openpgp-ffi/src/parse/stream.rs379
4 files changed, 453 insertions, 146 deletions
diff --git a/openpgp-ffi/examples/decrypt-with.c b/openpgp-ffi/examples/decrypt-with.c
index 969b7e28..68ef0606 100644
--- a/openpgp-ffi/examples/decrypt-with.c
+++ b/openpgp-ffi/examples/decrypt-with.c
@@ -38,9 +38,90 @@ get_public_keys_cb (void *cookie_raw,
}
static pgp_status_t
-check_signatures_cb(void *cookie_opaque,
- pgp_verification_results_t results, size_t levels)
+check_cb (void *cookie_opaque, pgp_message_structure_t structure)
{
+ pgp_message_structure_iter_t iter = pgp_message_structure_iter (structure);
+
+ for (pgp_message_layer_t layer = pgp_message_structure_iter_next (iter);
+ layer;
+ layer = pgp_message_structure_iter_next (iter)) {
+ uint8_t algo;
+ uint8_t aead_algo;
+ pgp_verification_result_iter_t results;
+
+ switch (pgp_message_layer_variant (layer)) {
+ case PGP_MESSAGE_LAYER_COMPRESSION:
+ pgp_message_layer_compression (layer, &algo);
+ fprintf (stderr, "Compressed using %d\n", algo);
+ break;
+
+ case PGP_MESSAGE_LAYER_ENCRYPTION:
+ pgp_message_layer_encryption (layer, &algo, &aead_algo);
+ if (aead_algo) {
+ fprintf (stderr, "Encrypted and protected using %d/%d\n",
+ algo, aead_algo);
+ } else {
+ fprintf (stderr, "Encrypted using %d\n", algo);
+ }
+ break;
+
+ case PGP_MESSAGE_LAYER_SIGNATURE_GROUP:
+ pgp_message_layer_signature_group (layer, &results);
+ for (pgp_verification_result_t result =
+ pgp_verification_result_iter_next (results);
+ result;
+ result = pgp_verification_result_iter_next (results)) {
+ pgp_signature_t sig;
+ pgp_keyid_t keyid;
+ char *keyid_str = NULL;
+
+ switch (pgp_verification_result_variant (result)) {
+ case PGP_VERIFICATION_RESULT_GOOD_CHECKSUM:
+ pgp_verification_result_good_checksum (result, &sig, NULL,
+ NULL, NULL, NULL);
+ keyid = pgp_signature_issuer (sig);
+ keyid_str = pgp_keyid_to_string (keyid);
+ fprintf (stderr, "Good signature from %s\n", keyid_str);
+ break;
+
+ case PGP_VERIFICATION_RESULT_MISSING_KEY:
+ pgp_verification_result_missing_key (result, &sig);
+ keyid = pgp_signature_issuer (sig);
+ keyid_str = pgp_keyid_to_string (keyid);
+ fprintf (stderr, "No key to check signature from %s\n", keyid_str);
+ break;
+
+ case PGP_VERIFICATION_RESULT_BAD_CHECKSUM:
+ pgp_verification_result_bad_checksum (result, &sig);
+ keyid = pgp_signature_issuer (sig);
+ if (keyid) {
+ keyid_str = pgp_keyid_to_string (keyid);
+ fprintf (stderr, "Bad signature from %s\n", keyid_str);
+ } else {
+ fprintf (stderr, "Bad signature without issuer information\n");
+ }
+ break;
+
+ default:
+ assert (! "reachable");
+ }
+ free (keyid_str);
+ pgp_signature_free (sig);
+ pgp_verification_result_free (result);
+ }
+ pgp_verification_result_iter_free (results);
+ break;
+
+ default:
+ assert (! "reachable");
+ }
+
+ pgp_message_layer_free (layer);
+ }
+
+ pgp_message_structure_iter_free (iter);
+ pgp_message_structure_free (structure);
+
/* Implement your verification policy here. */
return PGP_STATUS_SUCCESS;
}
@@ -128,7 +209,7 @@ main (int argc, char **argv)
};
plaintext = pgp_decryptor_new (&err, source,
get_public_keys_cb, decrypt_cb,
- check_signatures_cb, &cookie, 0);
+ check_cb, &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 db3c82aa..3b001a15 100644
--- a/openpgp-ffi/include/sequoia/openpgp.h
+++ b/openpgp-ffi/include/sequoia/openpgp.h
@@ -1447,33 +1447,91 @@ pgp_writer_stack_t pgp_encryptor_new (pgp_error_t *errp,
pgp_encryption_mode_t mode,
uint8_t cipher_algo);
-void pgp_verification_results_at_level(pgp_verification_results_t results,
- size_t level,
- pgp_verification_result_t **r,
- size_t *r_count);
+/*/
+/// Frees this object.
+/*/
+void pgp_message_structure_free (pgp_message_structure_t);
+
+/*/
+/// Returns a human readable description of this object suitable for
+/// debugging.
+/*/
+char *pgp_message_structure_debug (const pgp_message_structure_t);
+pgp_message_structure_iter_t
+pgp_message_structure_iter (pgp_message_structure_t);
/*/
-/// Returns the verification result code.
+/// Frees this object.
/*/
-pgp_verification_result_code_t pgp_verification_result_code(
- pgp_verification_result_t r);
+void pgp_message_structure_iter_free (pgp_message_structure_iter_t);
+
+pgp_message_layer_t
+pgp_message_structure_iter_next (pgp_message_structure_iter_t);
/*/
-/// Returns a reference to the signature.
-///
-/// Do not modify the signature nor free it.
+/// Frees this object.
/*/
-pgp_signature_t pgp_verification_result_signature(
+void pgp_message_layer_free (pgp_message_layer_t);
+
+/*/
+/// Returns a human readable description of this object suitable for
+/// debugging.
+/*/
+char *pgp_message_layer_debug (const pgp_message_layer_t);
+
+/*/
+/// Returns the message layer variant.
+/*/
+pgp_message_layer_variant_t
+pgp_message_layer_variant (pgp_message_layer_t);
+
+/*/
+/// Return the fields of the variants.
+/*/
+bool pgp_message_layer_compression (pgp_message_layer_t, uint8_t *);
+bool pgp_message_layer_encryption (pgp_message_layer_t, uint8_t *, uint8_t *);
+bool pgp_message_layer_signature_group (pgp_message_layer_t,
+ pgp_verification_result_iter_t *);
+
+/*/
+/// Frees this object.
+/*/
+void pgp_verification_result_iter_free (pgp_verification_result_iter_t);
+
+pgp_verification_result_t
+pgp_verification_result_iter_next (pgp_verification_result_iter_t);
+
+/*/
+/// Frees this object.
+/*/
+void pgp_verification_result_free (pgp_verification_result_t);
+
+/*/
+/// Returns a human readable description of this object suitable for
+/// debugging.
+/*/
+char *pgp_verification_result_debug (const pgp_verification_result_t);
+
+/*/
+/// Returns the verification result variant.
+/*/
+pgp_verification_result_variant_t pgp_verification_result_variant (
pgp_verification_result_t r);
/*/
-/// Returns the signature's level.
-///
-/// A level of zero means that the data was signed, a level of one
-/// means that one or more signatures were notarized, etc.
+/// Return the fields of the variants.
/*/
-int pgp_verification_result_level(pgp_verification_result_t r);
+bool pgp_verification_result_good_checksum (pgp_verification_result_t,
+ pgp_signature_t *,
+ pgp_tpk_t *,
+ pgp_key_t *,
+ pgp_signature_t *,
+ pgp_revocation_status_t *);
+bool pgp_verification_result_missing_key (pgp_verification_result_t,
+ pgp_signature_t *);
+bool pgp_verification_result_bad_checksum (pgp_verification_result_t,
+ pgp_signature_t *);
/*/
/// Decrypts an OpenPGP message.
@@ -1492,7 +1550,7 @@ int pgp_verification_result_level(pgp_verification_result_t r);
pgp_reader_t pgp_decryptor_new (pgp_error_t *errp, pgp_reader_t input,
pgp_decryptor_get_public_keys_cb_t get_public_keys,
pgp_decryptor_decrypt_cb_t decrypt,
- pgp_decryptor_check_signatures_cb_t check_signatures,
+ pgp_decryptor_check_cb_t check,
void *cookie, time_t time);
/*/
@@ -1503,7 +1561,7 @@ pgp_reader_t pgp_decryptor_new (pgp_error_t *errp, pgp_reader_t input,
/*/
pgp_reader_t pgp_verifier_new (pgp_error_t *errp, pgp_reader_t input,
pgp_decryptor_get_public_keys_cb_t get_public_keys,
- pgp_decryptor_check_signatures_cb_t check_signatures,
+ pgp_decryptor_check_cb_t check,
void *cookie, time_t time);
/*/
@@ -1512,7 +1570,7 @@ pgp_reader_t pgp_verifier_new (pgp_error_t *errp, pgp_reader_t input,
pgp_reader_t pgp_detached_verifier_new (pgp_error_t *errp,
pgp_reader_t signature_input, pgp_reader_t input,
pgp_decryptor_get_public_keys_cb_t get_public_keys,
- pgp_decryptor_check_signatures_cb_t check_signatures,
+ pgp_decryptor_check_cb_t check,
void *cookie, time_t time);
#endif
diff --git a/openpgp-ffi/include/sequoia/openpgp/types.h b/openpgp-ffi/include/sequoia/openpgp/types.h
index c6572346..40c926d0 100644
--- a/openpgp-ffi/include/sequoia/openpgp/types.h
+++ b/openpgp-ffi/include/sequoia/openpgp/types.h
@@ -464,18 +464,38 @@ typedef enum pgp_encryption_mode {
PGP_ENCRYPTION_MODE_FOR_TRANSPORT = 1,
} pgp_encryption_mode_t;
-typedef struct pgp_verification_results *pgp_verification_results_t;
+/// Communicates the message structure to the VerificationHelper.
+typedef struct pgp_message_structure *pgp_message_structure_t;
+
+/// Iterates over the message structure.
+typedef struct pgp_message_structure_iter *pgp_message_structure_iter_t;
+
+/// Represents a layer of the message structure.
+typedef struct pgp_message_layer *pgp_message_layer_t;
+
+typedef enum pgp_message_layer_variant {
+ PGP_MESSAGE_LAYER_COMPRESSION = 1,
+ PGP_MESSAGE_LAYER_ENCRYPTION = 2,
+ PGP_MESSAGE_LAYER_SIGNATURE_GROUP = 3,
+
+ /* Dummy value to make sure the enumeration has a defined size. Do
+ not use this value. */
+ PGP_MESSAGE_LAYER_CODE_FORCE_WIDTH = INT_MAX,
+} pgp_message_layer_variant_t;
+
typedef struct pgp_verification_result *pgp_verification_result_t;
-typedef enum pgp_verification_result_code {
- PGP_VERIFICATION_RESULT_CODE_GOOD_CHECKSUM = 1,
- PGP_VERIFICATION_RESULT_CODE_MISSING_KEY = 2,
- PGP_VERIFICATION_RESULT_CODE_BAD_CHECKSUM = 3,
+typedef struct pgp_verification_result_iter *pgp_verification_result_iter_t;
+
+typedef enum pgp_verification_result_variant {
+ PGP_VERIFICATION_RESULT_GOOD_CHECKSUM = 1,
+ PGP_VERIFICATION_RESULT_MISSING_KEY = 2,
+ PGP_VERIFICATION_RESULT_BAD_CHECKSUM = 3,
/* Dummy value to make sure the enumeration has a defined size. Do
not use this value. */
PGP_VERIFICATION_RESULT_CODE_FORCE_WIDTH = INT_MAX,
-} pgp_verification_result_code_t;
+} pgp_verification_result_variant_t;
typedef pgp_status_t (*pgp_decryptor_get_public_keys_cb_t) (void *,
pgp_keyid_t *, size_t,
@@ -494,8 +514,7 @@ typedef pgp_status_t (*pgp_decryptor_decrypt_cb_t) (void *,
void *,
pgp_fingerprint_t *);
-typedef pgp_status_t (*pgp_decryptor_check_signatures_cb_t) (void *,
- pgp_verification_results_t,
- size_t);
+typedef pgp_status_t (*pgp_decryptor_check_cb_t) (void *,
+ pgp_message_structure_t);
#endif
diff --git a/openpgp-ffi/src/parse/stream.rs b/openpgp-ffi/src/parse/stream.rs
index ebd4bc50..8dcaf101 100644
--- a/openpgp-ffi/src/parse/stream.rs
+++ b/openpgp-ffi/src/parse/stream.rs
@@ -11,7 +11,7 @@
//! [`sequoia-openpgp::parse::stream`]: ../../../sequoia_openpgp/parse/stream/index.html
use std::ptr;
-use libc::{c_int, size_t, c_void, uint8_t, time_t};
+use libc::{c_int, c_void, uint8_t, time_t};
extern crate sequoia_openpgp as openpgp;
extern crate time;
@@ -25,10 +25,10 @@ use self::openpgp::{
},
};
use self::openpgp::parse::stream::{
+ self,
DecryptionHelper,
Decryptor,
VerificationHelper,
- VerificationResult,
Verifier,
DetachedVerifier,
};
@@ -45,93 +45,221 @@ use super::super::{
crypto,
io,
keyid,
- packet,
tpk::TPK,
+ packet::signature::Signature,
+ packet::key::Key,
+ revocation_status::RevocationStatus,
};
-// Decryptor.
+/// Communicates the message structure to the VerificationHelper.
+#[::ffi_wrapper_type(prefix = "pgp_", derive = "Debug")]
+pub struct MessageStructure<'a>(stream::MessageStructure<'a>);
-/// A message's verification results.
-///
-/// Conceptually, the verification results are an array of an array of
-/// VerificationResult. The outer array is for the verification level
-/// and is indexed by the verification level. A verification level of
-/// zero corresponds to direct signatures; A verification level of 1
-/// corresponds to notarizations (i.e., signatures of signatures);
-/// etc.
+/// Iterates over the message structure.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "system"
+fn pgp_message_structure_iter(structure: *const MessageStructure)
+ -> *mut MessageStructureIter {
+ structure.ref_raw().iter().move_into_raw()
+}
+
+/// Iterates over the message structure.
+#[::ffi_wrapper_type(prefix = "pgp_", derive = "Iterator(MessageLayer)")]
+pub struct MessageStructureIter<'a>(stream::MessageStructureIter<'a>);
+
+/// Represents a layer of the message structure.
+#[::ffi_wrapper_type(prefix = "pgp_", derive = "Debug")]
+pub struct MessageLayer<'a>(stream::MessageLayer<'a>);
+
+/// Returns the message layer variant.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
+fn pgp_message_layer_variant(result: *const MessageLayer)
+ -> c_int
+{
+ use self::stream::MessageLayer::*;
+ match result.ref_raw() {
+ Compression { .. } => 1,
+ Encryption { .. } => 2,
+ SignatureGroup { .. } => 3,
+ }
+}
+
+/// Decomposes a `MessageLayer::Compression`.
///
-/// Within each level, there can be one or more signatures.
-pub struct VerificationResults<'a> {
- results: Vec<Vec<&'a VerificationResult<'a>>>,
+/// Returns `true` iff the given value is a
+/// `MessageLayer::Compression`, and returns each of the variants
+/// members if the corresponding parameter is not `NULL`.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
+fn pgp_message_layer_compression(v: *const MessageLayer,
+ algo_r: Maybe<uint8_t>)
+ -> bool
+{
+ use self::stream::MessageLayer::*;
+ if let Compression { algo } = v.ref_raw() {
+ if let Some(mut p) = algo_r {
+ *unsafe { p.as_mut() } = (*algo).into();
+ }
+ true
+ } else {
+ false
+ }
}
-/// Returns the `VerificationResult`s at level `level.
+/// Decomposes a `MessageLayer::Encryption`.
///
-/// Conceptually, the verification results are an array of an array of
-/// VerificationResult. The outer array is for the verification level
-/// and is indexed by the verification level. A verification level of
-/// zero corresponds to direct signatures; A verification level of 1
-/// corresponds to notarizations (i.e., signatures of signatures);
-/// etc.
+/// Returns `true` iff the given value is a
+/// `MessageLayer::Encryption`, and returns each of the variants
+/// members if the corresponding parameter is not `NULL`.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
+fn pgp_message_layer_encryption(v: *const MessageLayer,
+ sym_algo_r: Maybe<uint8_t>,
+ aead_algo_r: Maybe<uint8_t>)
+ -> bool
+{
+ use self::stream::MessageLayer::*;
+ if let Encryption { sym_algo, aead_algo } = v.ref_raw() {
+ if let Some(mut p) = sym_algo_r {
+ *unsafe { p.as_mut() } = (*sym_algo).into();
+ }
+ if let Some(mut p) = aead_algo_r {
+ *unsafe { p.as_mut() } =
+ aead_algo.map(|a| a.into()).unwrap_or(0);
+ }
+ true
+ } else {
+ false
+ }
+}
+
+/// Decomposes a `MessageLayer::SignatureGroup`.
///
-/// This function returns the verification results for a particular
-/// level. The result is an array of references to
-/// `VerificationResult`.
+/// Returns `true` iff the given value is a
+/// `MessageLayer::SignatureGroup`, and returns each of the variants
+/// members if the corresponding parameter is not `NULL`.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
-fn pgp_verification_results_at_level<'a>(results: *const VerificationResults<'a>,
- level: size_t,
- r: *mut *const &'a VerificationResult<'a>,
- r_count: *mut size_t) {
- let results = ffi_param_ref!(results);
- let r = ffi_param_ref_mut!(r);
- let r_count = ffi_param_ref_mut!(r_count);
-
- assert!(level < results.results.len());
-
- // The size of VerificationResult is not known in C. Convert from
- // an array of VerificationResult to an array of
- // VerificationResult refs.
- *r = results.results[results.results.len() - level - 1].as_ptr();
- *r_count = results.results[results.results.len() - level - 1].len();
+fn pgp_message_layer_signature_group<'a>(
+ v: *const MessageLayer<'a>,
+ results_r: Maybe<* mut VerificationResultIter<'a>>)
+ -> bool
+{
+ use self::stream::MessageLayer::*;
+ if let SignatureGroup { results } = v.ref_raw() {
+ if let Some(mut p) = results_r {
+ *unsafe { p.as_mut() } = results.iter().move_into_raw();
+ }
+ true
+ } else {
+ false
+ }
}
-/// Returns the verification result code.
+/// A message's verification results.
+#[::ffi_wrapper_type(prefix = "pgp_", derive = "Iterator(VerificationResult)")]
+pub struct VerificationResultIter<'a>(
+ ::std::slice::Iter<'a, stream::VerificationResult<'a>>);
+
+/// A message's verification results.
+#[::ffi_wrapper_type(prefix = "pgp_", derive = "Debug")]
+pub struct VerificationResult<'a>(stream::VerificationResult<'a>);
+
+/// Returns the verification result variant.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
-fn pgp_verification_result_code(result: *const VerificationResult)
+fn pgp_verification_result_variant(result: *const VerificationResult)
-> c_int
{
- let result = ffi_param_ref!(result);
- match result {
- VerificationResult::GoodChecksum(..) => 1,
- VerificationResult::MissingKey(_) => 2,
- VerificationResult::BadChecksum(_) => 3,
+ use self::stream::VerificationResult::*;
+ match result.ref_raw() {
+ GoodChecksum(..) => 1,
+ MissingKey(_) => 2,
+ BadChecksum(_) => 3,
}
}
-/// Returns the verification result code.
+/// Decomposes a `VerificationResult::GoodChecksum`.
+///
+/// Returns `true` iff the given value is a
+/// `VerificationResult::GoodChecksum`, and returns the variants members
+/// in `sig_r` and the like iff `sig_r != NULL`.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
-fn pgp_verification_result_signature(result: *const VerificationResult)
- -> *mut packet::signature::Signature
+fn pgp_verification_result_good_checksum<'a>(
+ result: *const VerificationResult<'a>,
+ sig_r: Maybe<*mut Signature>,
+ tpk_r: Maybe<*mut TPK>,
+ key_r: Maybe<*mut Key>,
+ binding_r: Maybe<Maybe<Signature>>,
+ revocation_status_r:
+ Maybe<*mut RevocationStatus<'a>>)
+ -> bool
{
- let result = ffi_param_ref!(result);
- let sig = match result {
- VerificationResult::GoodChecksum(ref sig, ..) => sig,
- VerificationResult::MissingKey(ref sig) => sig,
- VerificationResult::BadChecksum(ref sig) => sig,
- };
-
- sig.move_into_raw()
+ use self::stream::VerificationResult::*;
+ if let GoodChecksum(ref sig, ref tpk, ref key, ref binding, ref revocation)
+ = result.ref_raw()
+ {
+ if let Some(mut p) = sig_r {
+ *unsafe { p.as_mut() } = sig.move_into_raw();
+ }
+ if let Some(mut p) = tpk_r {
+ *unsafe { p.as_mut() } = tpk.move_into_raw();
+ }
+ if let Some(mut p) = key_r {
+ *unsafe { p.as_mut() } = key.move_into_raw();
+ }
+ if let Some(mut p) = binding_r {
+ *unsafe { p.as_mut() } = binding.move_into_raw();
+ }
+ if let Some(mut p) = revocation_status_r {
+ *unsafe { p.as_mut() } = revocation.move_into_raw();
+ }
+ true
+ } else {
+ false
+ }
}
-/// Returns the verification result code.
+/// Decomposes a `VerificationResult::MissingKey`.
+///
+/// Returns `true` iff the given value is a
+/// `VerificationResult::MissingKey`, and returns the variants members
+/// in `sig_r` and the like iff `sig_r != NULL`.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
-fn pgp_verification_result_level(result: *const VerificationResult)
- -> c_int
+fn pgp_verification_result_missing_key<'a>(
+ result: *const VerificationResult<'a>,
+ sig_r: Maybe<*mut Signature>)
+ -> bool
{
- let result = ffi_param_ref!(result);
- result.level() as c_int
+ use self::stream::VerificationResult::*;
+ if let MissingKey(ref sig) = result.ref_raw()
+ {
+ if let Some(mut p) = sig_r {
+ *unsafe { p.as_mut() } = sig.move_into_raw();
+ }
+ true
+ } else {
+ false
+ }
}
+/// Decomposes a ``VerificationResult::BadChecksum`.
+///
+/// Returns `true` iff the given value is a
+/// `VerificationResult::BadChecksum`, and returns the variants
+/// members in `sig_r` and the like iff `sig_r != NULL`.
+#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
+fn pgp_verification_result_bad_checksum<'a>(
+ result: *const VerificationResult<'a>,
+ sig_r: Maybe<*mut Signature>)
+ -> bool
+{
+ use self::stream::VerificationResult::*;
+ if let BadChecksum(ref sig) = result.ref_raw()
+ {
+ if let Some(mut p) = sig_r {
+ *unsafe { p.as_mut() } = sig.move_into_raw();
+ }
+ true
+ } else {
+ false
+ }
+}
/// Passed as the first argument to the callbacks used by pgp_verify
/// and pgp_decrypt.
@@ -174,20 +302,20 @@ type DecryptCallback = fn(*mut HelperCookie,
///
/// If the result is not Status::Success, then this aborts the
/// Verification.
-type CheckSignaturesCallback = fn(*mut HelperCookie,
- *const VerificationResults,
- usize) -> Status;
+type CheckCallback = fn(*mut HelperCookie,
+ *const MessageStructure)
+ -> Status;
// This fetches keys and computes the validity of the verification.
struct VHelper {
get_public_keys_cb: GetPublicKeysCallback,
- check_signatures_cb: CheckSignaturesCallback,
+ check_signatures_cb: CheckCallback,
cookie: *mut HelperCookie,
}
impl VHelper {
fn new(get_public_keys: GetPublicKeysCallback,
- check_signatures: CheckSignaturesCallback,
+ check_signatures: CheckCallback,
cookie: *mut HelperCookie)
-> Self
{
@@ -244,20 +372,11 @@ impl VerificationHelper for VHelper {
Ok(tpks)
}
- fn check(&mut self, sigs: Vec<Vec<VerificationResult>>)
+ fn check(&mut self, structure: &stream::MessageStructure)
-> Result<(), failure::Error>
{
- // The size of VerificationResult is not known in C. Convert
- // from an array of VerificationResults to an array of
- // VerificationResult refs.
- let results = VerificationResults {
- results: sigs.iter().map(
- |r| r.iter().collect::<Vec<&VerificationResult>>()).collect()
- };
-
let result = (self.check_signatures_cb)(self.cookie,
- &results,
- results.results.len());
+ structure.move_into_raw());
if result != Status::Success {
// XXX: We need to convert the status to an error. A
// status contains less information, but we should do the
@@ -310,17 +429,31 @@ impl VerificationHelper for VHelper {
/// }
///
/// static pgp_status_t
-/// check_signatures_cb(void *cookie_opaque,
-/// pgp_verification_results_t results, size_t levels)
+/// check_cb (void *cookie_opaque, pgp_message_structure_t structure)
/// {
-/// /* Implement your verification policy here. */
-/// assert (levels == 1);
-/// pgp_verification_result_t *vrs;
-/// size_t vr_count;
-/// pgp_verification_results_at_level (results, 0, &vrs, &vr_count);
-/// assert (vr_count == 1);
-/// pgp_verification_result_code_t code = pgp_verification_result_code(vrs[0]);
-/// assert (code == PGP_VERIFICATION_RESULT_CODE_GOOD_CHECKSUM);
+/// pgp_message_structure_iter_t iter =
+/// pgp_message_structure_iter (structure);
+/// pgp_message_layer_t layer = pgp_message_structure_iter_next (iter);
+/// assert (layer);
+/// assert (pgp_message_layer_compression (layer, NULL));
+/// pgp_message_layer_free (layer);
+/// layer = pgp_message_structure_iter_next (iter);
+/// assert (layer);
+/// pgp_verification_result_iter_t results;
+/// if (pgp_message_layer_signature_group (layer, &results)) {
+/// pgp_verification_result_t result =
+/// pgp_verification_result_iter_next (results);
+/// assert (result);
+/// assert (pgp_verification_result_good_checksum (result, NULL, NULL,
+/// NULL, NULL, NULL));
+/// pgp_verification_result_free (result);
+/// } else {
+/// assert (! "reachable");
+/// }
+/// pgp_verification_result_iter_free (results);
+/// pgp_message_layer_free (layer);
+/// pgp_message_structure_iter_free (iter);
+/// pgp_message_structure_free (structure);
/// return PGP_STATUS_SUCCESS;
/// }
///
@@ -344,7 +477,7 @@ impl VerificationHelper for VHelper {
/// .key = tpk, /* Move. */
/// };
/// plaintext = pgp_verifier_new (NULL, source,
-/// get_public_keys_cb, check_signatures_cb,
+/// get_public_keys_cb, check_cb,
/// &cookie, 1554542219);
/// assert (source);
///
@@ -362,12 +495,12 @@ impl VerificationHelper for VHelper {
fn pgp_verifier_new<'a>(errp: Option<&mut *mut ::error::Error>,
input: *mut io::Reader,
get_public_keys: GetPublicKeysCallback,
- check_signatures: CheckSignaturesCallback,
+ check: CheckCallback,
cookie: *mut HelperCookie,
time: time_t)
-> Maybe<io::Reader>
{
- let helper = VHelper::new(get_public_keys, check_signatures, cookie);
+ let helper = VHelper::new(get_public_keys, check, cookie);
Verifier::from_reader(input.ref_mut_raw(), helper, maybe_time(time))
.map(|r| io::ReaderKind::Generic(Box::new(r)))
@@ -418,17 +551,27 @@ fn maybe_time(t: time_t) -> Option<time::Tm> {
/// }
///
/// static pgp_status_t
-/// check_signatures_cb(void *cookie_opaque,
-/// pgp_verification_results_t results, size_t levels)
+/// check_cb (void *cookie_opaque, pgp_message_structure_t structure)
/// {
-/// /* Implement your verification policy here. */
-/// assert (levels == 1);
-/// pgp_verification_result_t *vrs;
-/// size_t vr_count;
-/// pgp_verification_results_at_level (results, 0, &vrs, &vr_count);
-/// assert (vr_count == 1);
-/// pgp_verification_result_code_t code = pgp_verification_result_code(vrs[0]);
-/// assert (code == PGP_VERIFICATION_RESULT_CODE_GOOD_CHECKSUM);
+/// pgp_message_structure_iter_t iter =
+/// pgp_message_structure_iter (structure);
+/// pgp_message_layer_t layer = pgp_message_structure_iter_next (iter);
+/// assert (layer);
+/// pgp_verification_result_iter_t results;
+/// if (pgp_message_layer_signature_group (layer, &results)) {
+/// pgp_verification_result_t result =
+/// pgp_verification_result_iter_next (results);