diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-04-29 14:36:24 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-04-29 14:55:52 +0200 |
commit | b3b18a2a9e370b226cdc3015616e072d22937ddf (patch) | |
tree | addde6ca6e51fb788dd0c7bbdb5d6beeddd3d66d /openpgp-ffi | |
parent | 36ed0f847c4f033c67fca9f2a332598b5effc107 (diff) |
openpgp-ffi: Introduce a new Packet type.
- See #156.
Diffstat (limited to 'openpgp-ffi')
-rw-r--r-- | openpgp-ffi/examples/immutable-reference-demo.c | 55 | ||||
-rw-r--r-- | openpgp-ffi/include/sequoia/openpgp.h | 6 | ||||
-rw-r--r-- | openpgp-ffi/include/sequoia/openpgp/packet.h | 33 | ||||
-rw-r--r-- | openpgp-ffi/include/sequoia/openpgp/types.h | 15 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/mod.rs | 68 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/skesk.rs | 6 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/user_attribute.rs | 7 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/userid.rs | 7 | ||||
-rw-r--r-- | openpgp-ffi/src/parse/mod.rs | 10 |
9 files changed, 129 insertions, 78 deletions
diff --git a/openpgp-ffi/examples/immutable-reference-demo.c b/openpgp-ffi/examples/immutable-reference-demo.c index 47efbdd6..90a76d43 100644 --- a/openpgp-ffi/examples/immutable-reference-demo.c +++ b/openpgp-ffi/examples/immutable-reference-demo.c @@ -9,36 +9,51 @@ fflush (stderr); \ if (s) { exit (s); } \ } while (0) -#include <fcntl.h> +#include <assert.h> #include <stdio.h> -#include <stdlib.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> +#include <string.h> #include <sequoia/openpgp.h> +const char *SIGNATURE = + "-----BEGIN PGP SIGNATURE-----\n" + "\n" + "woQEHxYKADYCHgMCmwEFglzG4sgFiQWfpgAWIQRQOSL5kHbC6ABk1wR4FqN0BApT\n" + "FwkQeBajdAQKUxcCFQoAAApUAP9IqLtwGgfxwzwGYqBSQszNwsg9OHAdputlUvVZ\n" + "WZ+vqgEA5lRTlWwcS3ofH758FQWJFyHwHBQ6weler8510ZEahg4=\n" + "=Ebj8\n" + "-----END PGP SIGNATURE-----\n"; + int main (int argc, char **argv) { - /* Create a new TSK. */ - pgp_tsk_t tsk; - pgp_signature_t revocation; - pgp_tsk_new (NULL, "", &tsk, &revocation); - pgp_signature_free (revocation); + /* Let's parse a signature. */ + pgp_packet_parser_result_t ppr; + pgp_packet_parser_t pp; + ppr = pgp_packet_parser_from_bytes (NULL, + (uint8_t *) SIGNATURE, + strlen (SIGNATURE)); + while ((pp = pgp_packet_parser_result_packet_parser (ppr))) + { + /* Let's borrow a immutable reference from the parser. */ + pgp_packet_t p = pgp_packet_parser_packet (pp); + + /* We happen to know that it is a signature. */ + pgp_signature_t sig = pgp_packet_ref_signature (p); + assert(sig); - /* Let's borrow a immutable reference from it. */ - pgp_tpk_t tpk = pgp_tsk_tpk (tsk); + /* Let's violate The Rules and forge a mutable reference from + * the immutable one! */ + pgp_signature_t sig_mut = (pgp_signature_t) sig; - /* Let's violate The Rules and forge a mutable reference from - * the immutable one! */ - pgp_tpk_t tpk_mut = (pgp_tpk_t) tpk; + /* And try to convert the Signature to a Packet, moving the ownership! */ + pgp_signature_into_packet (sig_mut); - /* And try to convert the TPK to a TSK, moving the ownership! */ - pgp_tpk_into_tsk (tpk_mut); + /* Always clean up though. */ + pgp_signature_free (sig); + pgp_packet_free (p); + } - /* Always clean up though. */ - pgp_tsk_free (tsk); + pgp_packet_parser_result_free (ppr); return 0; } diff --git a/openpgp-ffi/include/sequoia/openpgp.h b/openpgp-ffi/include/sequoia/openpgp.h index ae005999..0d2494bd 100644 --- a/openpgp-ffi/include/sequoia/openpgp.h +++ b/openpgp-ffi/include/sequoia/openpgp.h @@ -1001,7 +1001,7 @@ pgp_key_pair_t pgp_key_into_key_pair (pgp_error_t *errp, pgp_key_t key); /// The returned pointer is valid until `uid` is deallocated. If /// `value_len` is not `NULL`, the size of value is stored there. /*/ -const uint8_t *pgp_user_id_value (pgp_user_id_t uid, +const uint8_t *pgp_user_id_value (pgp_packet_t uid, size_t *value_len); /*/ @@ -1010,7 +1010,7 @@ const uint8_t *pgp_user_id_value (pgp_user_id_t uid, /// The returned pointer is valid until `ua` is deallocated. If /// `value_len` is not `NULL`, the size of value is stored there. /*/ -const uint8_t *pgp_user_attribute_value (pgp_user_attribute_t ua, +const uint8_t *pgp_user_attribute_value (pgp_packet_t ua, size_t *value_len); /*/ @@ -1021,7 +1021,7 @@ const uint8_t *pgp_user_attribute_value (pgp_user_attribute_t ua, /// is not written to it. Either way, `key_len` is set to the size of /// the session key. /*/ -pgp_status_t pgp_skesk_decrypt (pgp_error_t *errp, pgp_skesk_t skesk, +pgp_status_t pgp_skesk_decrypt (pgp_error_t *errp, pgp_packet_t skesk, const uint8_t *password, size_t password_len, uint8_t *algo, /* XXX */ uint8_t *key, size_t *key_len); diff --git a/openpgp-ffi/include/sequoia/openpgp/packet.h b/openpgp-ffi/include/sequoia/openpgp/packet.h index 7d9f3f07..778deabe 100644 --- a/openpgp-ffi/include/sequoia/openpgp/packet.h +++ b/openpgp-ffi/include/sequoia/openpgp/packet.h @@ -2,14 +2,14 @@ #define SEQUOIA_OPENPGP_PACKET_H /*/ -/// Returns a human-readable tag name. +/// Frees the Packet. /*/ -const char *pgp_tag_to_string (pgp_tag_t tag); +void pgp_packet_free (pgp_packet_t p); /*/ -/// Frees the Packet. +/// Clones this object. /*/ -void pgp_packet_free (pgp_packet_t p); +pgp_packet_t pgp_packet_clone (pgp_packet_t keyid); /*/ /// Returns a human readable description of this object suitable for @@ -18,6 +18,16 @@ void pgp_packet_free (pgp_packet_t p); 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); + +/*/ +/// Hashes this object. +/*/ +uint64_t pgp_packet_hash (pgp_packet_t keyid); + +/*/ /// Returns the `Packet's` corresponding OpenPGP tag. /// /// Tags are explained in [Section 4.3 of RFC 4880]. @@ -37,4 +47,19 @@ pgp_tag_t pgp_packet_tag (pgp_packet_t p); /*/ pgp_tag_t pgp_packet_kind (pgp_packet_t p); +/*/ +/// Returns a human-readable tag name. +/*/ +const char *pgp_tag_to_string (pgp_tag_t tag); + +/*/ +/// Given a packet references the contained signature, if any. +/// +/// If the Packet is not of the `Packet::Signature` variant, this +/// function returns `NULL`. Objects returned from this function must +/// be deallocated using `pgp_signature_free` even though they only +/// reference the given packet. +/*/ +pgp_signature_t pgp_packet_ref_signature (pgp_packet_t p); + #endif diff --git a/openpgp-ffi/include/sequoia/openpgp/types.h b/openpgp-ffi/include/sequoia/openpgp/types.h index 140554f5..742c782ce 100644 --- a/openpgp-ffi/include/sequoia/openpgp/types.h +++ b/openpgp-ffi/include/sequoia/openpgp/types.h @@ -321,20 +321,7 @@ typedef struct pgp_mdc *pgp_mdc_t; /// /// [Section 5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5 /*/ -typedef union pgp_packet { - pgp_unknown_t unknown; - pgp_signature_t signature; - pgp_one_pass_sig_t one_pass_sig; - pgp_key_t key; - pgp_user_id_t user_id; - pgp_user_attribute_t user_attribute; - pgp_literal_t literal; - pgp_compressed_data_t compressed_data; - pgp_pkesk_t pkesk; - pgp_skesk_t skesk; - pgp_seip_t seip; - pgp_mdc_t mdc; -} pgp_packet_t; +typedef struct pgp_packet *pgp_packet_t; /*/ /// A low-level OpenPGP message parser. diff --git a/openpgp-ffi/src/packet/mod.rs b/openpgp-ffi/src/packet/mod.rs index 52ffaee5..3576210d 100644 --- a/openpgp-ffi/src/packet/mod.rs +++ b/openpgp-ffi/src/packet/mod.rs @@ -10,7 +10,6 @@ extern crate sequoia_openpgp as openpgp; extern crate time; use self::openpgp::{ - Packet, packet::Tag, }; @@ -22,23 +21,41 @@ pub mod skesk; pub mod user_attribute; pub mod userid; -/// Frees the Packet. -#[::sequoia_ffi_macros::extern_fn] #[no_mangle] -pub extern "system" fn pgp_packet_free(p: Option<&mut Packet>) { - ffi_free!(p) -} +use Maybe; +use MoveIntoRaw; +use RefRaw; + +/// The OpenPGP packets that Sequoia understands. +/// +/// The different OpenPGP packets are detailed in [Section 5 of RFC 4880]. +/// +/// The `Unknown` packet allows Sequoia to deal with packets that it +/// doesn't understand. The `Unknown` packet is basically a binary +/// blob that includes the packet's tag. +/// +/// The unknown packet is also used for packets that are understood, +/// but use unsupported options. For instance, when the packet parser +/// encounters a compressed data packet with an unknown compression +/// algorithm, it returns the packet in an `Unknown` packet rather +/// than a `CompressedData` packet. +/// +/// [Section 5 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5 +/// +/// Wraps [`sequoia-openpgp::Packet`]. +/// +/// [`sequoia-openpgp::Packet`]: ../../sequoia_openpgp/enum.Packet.html +#[::ffi_wrapper_type(prefix = "pgp_", + derive = "Clone, Debug, Hash, PartialEq")] +pub struct Packet(openpgp::Packet); /// Returns the `Packet's` corresponding OpenPGP tag. /// /// Tags are explained in [Section 4.3 of RFC 4880]. /// /// [Section 4.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-4.3 -#[::sequoia_ffi_macros::extern_fn] #[no_mangle] -pub extern "system" fn pgp_packet_tag(p: *const Packet) - -> uint8_t { - let p = ffi_param_ref!(p); - let tag: u8 = p.tag().into(); - tag as uint8_t +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "system" +fn pgp_packet_tag(p: *const Packet) -> uint8_t { + u8::from(p.ref_raw().tag()) as uint8_t } /// Returns the parsed `Packet's` corresponding OpenPGP tag. @@ -48,11 +65,9 @@ pub extern "system" fn pgp_packet_tag(p: *const Packet) /// Signature Packet uses some unsupported methods, it is parsed /// into an `Packet::Unknown`. `tag()` returns `PGP_TAG_SIGNATURE`, /// whereas `kind()` returns `0`. -#[::sequoia_ffi_macros::extern_fn] #[no_mangle] -pub extern "system" fn pgp_packet_kind(p: *const Packet) - -> uint8_t { - let p = ffi_param_ref!(p); - if let Some(kind) = p.kind() { +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "system" +fn pgp_packet_kind(p: *const Packet) -> uint8_t { + if let Some(kind) = p.ref_raw().kind() { kind.into() } else { 0 @@ -92,10 +107,17 @@ pub extern "system" fn pgp_tag_to_string(tag: uint8_t) -> *const c_char { }.as_bytes().as_ptr() as *const c_char } -/// Pretty prints a packet -#[::sequoia_ffi_macros::extern_fn] #[no_mangle] -pub extern "system" fn pgp_packet_debug(p: *const Packet) -> *const c_char { - let p = ffi_param_ref!(p); - format!("{:?}", p).as_ptr() as *const c_char +/// Given a packet references the contained signature, if any. +/// +/// If the Packet is not of the `Packet::Signature` variant, this +/// function returns `NULL`. Objects returned from this function must +/// be deallocated using `pgp_signature_free` even though they only +/// reference the given packet. +#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "system" +fn pgp_packet_ref_signature(p: *const Packet) -> Maybe<signature::Signature> { + if let openpgp::Packet::Signature(ref p) = p.ref_raw() { + ::std::ptr::NonNull::new(p.move_into_raw()) + } else { + None + } } - diff --git a/openpgp-ffi/src/packet/skesk.rs b/openpgp-ffi/src/packet/skesk.rs index f8e466ec..5e5b6f5b 100644 --- a/openpgp-ffi/src/packet/skesk.rs +++ b/openpgp-ffi/src/packet/skesk.rs @@ -5,9 +5,10 @@ use libc::{uint8_t, size_t}; use failure; extern crate sequoia_openpgp as openpgp; -use self::openpgp::Packet; +use super::Packet; use error::Status; +use RefRaw; /// Returns the session key. /// @@ -25,7 +26,6 @@ pub extern "system" fn pgp_skesk_decrypt(errp: Option<&mut *mut ::error::Error>, key_len: *mut size_t) -> Status { ffi_make_fry_from_errp!(errp); - let skesk = ffi_param_ref!(skesk); assert!(!password.is_null()); let password = unsafe { slice::from_raw_parts(password, password_len as usize) @@ -33,7 +33,7 @@ pub extern "system" fn pgp_skesk_decrypt(errp: Option<&mut *mut ::error::Error>, let algo = ffi_param_ref_mut!(algo); let key_len = ffi_param_ref_mut!(key_len); - if let &Packet::SKESK(ref skesk) = skesk { + if let &openpgp::Packet::SKESK(ref skesk) = skesk.ref_raw() { match skesk.decrypt(&password.to_owned().into()) { Ok((a, k)) => { *algo = a.into(); diff --git a/openpgp-ffi/src/packet/user_attribute.rs b/openpgp-ffi/src/packet/user_attribute.rs index 925884c9..131c15de 100644 --- a/openpgp-ffi/src/packet/user_attribute.rs +++ b/openpgp-ffi/src/packet/user_attribute.rs @@ -6,7 +6,9 @@ use libc::{uint8_t, size_t}; extern crate sequoia_openpgp as openpgp; -use self::openpgp::Packet; +use super::Packet; + +use RefRaw; /// Returns the value of the User Attribute Packet. /// @@ -16,8 +18,7 @@ use self::openpgp::Packet; pub extern "system" fn pgp_user_attribute_value(ua: *const Packet, value_len: Option<&mut size_t>) -> *const uint8_t { - let ua = ffi_param_ref!(ua); - if let &Packet::UserAttribute(ref ua) = ua { + if let &openpgp::Packet::UserAttribute(ref ua) = ua.ref_raw() { if let Some(p) = value_len { *p = ua.value().len(); } diff --git a/openpgp-ffi/src/packet/userid.rs b/openpgp-ffi/src/packet/userid.rs index cdcdeca6..15f0d0a2 100644 --- a/openpgp-ffi/src/packet/userid.rs +++ b/openpgp-ffi/src/packet/userid.rs @@ -6,7 +6,9 @@ use libc::{uint8_t, size_t}; extern crate sequoia_openpgp as openpgp; -use self::openpgp::Packet; +use super::Packet; + +use RefRaw; /// Returns the value of the User ID Packet. /// @@ -16,8 +18,7 @@ use self::openpgp::Packet; pub extern "system" fn pgp_user_id_value(uid: *const Packet, value_len: Option<&mut size_t>) -> *const uint8_t { - let uid = ffi_param_ref!(uid); - if let &Packet::UserID(ref uid) = uid { + if let &openpgp::Packet::UserID(ref uid) = uid.ref_raw() { if let Some(p) = value_len { *p = uid.value().len(); } diff --git a/openpgp-ffi/src/parse/mod.rs b/openpgp-ffi/src/parse/mod.rs index 23ed2ffc..427e53f1 100644 --- a/openpgp-ffi/src/parse/mod.rs +++ b/openpgp-ffi/src/parse/mod.rs @@ -14,7 +14,7 @@ use libc::{uint8_t, c_char, c_int, size_t}; extern crate sequoia_openpgp as openpgp; extern crate time; -use self::openpgp::{ +use super::packet::{ Packet, }; use self::openpgp::parse::{ @@ -113,7 +113,7 @@ pub extern "system" fn pgp_packet_parser_packet (pp: *const PacketParser) -> *const Packet { let pp = ffi_param_ref!(pp); - &pp.packet + (&pp.packet).move_into_raw() } /// Returns the current packet's recursion depth. @@ -208,7 +208,7 @@ pub extern "system" fn pgp_packet_parser_next<'a> match pp.next() { Ok((old_p, new_ppr)) => { if let Some(p) = old_packet { - *p = box_raw!(old_p); + *p = old_p.move_into_raw(); } if let Some(p) = ppr { *p = box_raw!(new_ppr); @@ -252,7 +252,7 @@ pub extern "system" fn pgp_packet_parser_recurse<'a> match pp.recurse() { Ok((old_p, new_ppr)) => { if let Some(p) = old_packet { - *p = box_raw!(old_p); + *p = old_p.move_into_raw(); } if let Some(p) = ppr { *p = box_raw!(new_ppr); @@ -298,7 +298,7 @@ pub extern "system" fn pgp_packet_parser_finish<'a> match pp.finish() { Ok(p) => { if let Some(out_p) = packet { - *out_p = p; + *out_p = p.move_into_raw(); } Status::Success }, |