summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-04-29 14:36:24 +0200
committerJustus Winter <justus@sequoia-pgp.org>2019-04-29 14:55:52 +0200
commitb3b18a2a9e370b226cdc3015616e072d22937ddf (patch)
treeaddde6ca6e51fb788dd0c7bbdb5d6beeddd3d66d
parent36ed0f847c4f033c67fca9f2a332598b5effc107 (diff)
openpgp-ffi: Introduce a new Packet type.
- See #156.
-rw-r--r--ffi/lang/python/sequoia/openpgp.py21
-rw-r--r--ffi/lang/python/sequoia/sequoia_build.py1
-rw-r--r--openpgp-ffi/examples/immutable-reference-demo.c55
-rw-r--r--openpgp-ffi/include/sequoia/openpgp.h6
-rw-r--r--openpgp-ffi/include/sequoia/openpgp/packet.h33
-rw-r--r--openpgp-ffi/include/sequoia/openpgp/types.h15
-rw-r--r--openpgp-ffi/src/packet/mod.rs68
-rw-r--r--openpgp-ffi/src/packet/skesk.rs6
-rw-r--r--openpgp-ffi/src/packet/user_attribute.rs7
-rw-r--r--openpgp-ffi/src/packet/userid.rs7
-rw-r--r--openpgp-ffi/src/parse/mod.rs10
11 files changed, 142 insertions, 87 deletions
diff --git a/ffi/lang/python/sequoia/openpgp.py b/ffi/lang/python/sequoia/openpgp.py
index de567c09..ddd76dbe 100644
--- a/ffi/lang/python/sequoia/openpgp.py
+++ b/ffi/lang/python/sequoia/openpgp.py
@@ -235,22 +235,25 @@ class SEIP(SQObject):
class Packet(SQObject):
_map = {
- Tag.PublicKey: lambda x, **kwargs: PublicKey(x.key, **kwargs),
- Tag.PublicSubkey: lambda x, **kwargs: PublicSubkey(x.key, **kwargs),
- Tag.SecretKey: lambda x, **kwargs: SecretKey(x.key, **kwargs),
- Tag.SecretSubkey: lambda x, **kwargs: SecretSubkey(x.key, **kwargs),
- Tag.UserID: lambda x, **kwargs: UserID(x.user_id, **kwargs),
- Tag.UserAttribute: lambda x, **kwargs: UserAttribute(x.user_attribute, **kwargs),
- Tag.SKESK: lambda x, **kwargs: SKESK(x.skesk, **kwargs),
- Tag.SEIP: lambda x, **kwargs: SEIP(x.seip, **kwargs),
+ Tag.PublicKey: lambda x, **kwargs: PublicKey(x, **kwargs),
+ Tag.PublicSubkey: lambda x, **kwargs: PublicSubkey(x, **kwargs),
+ Tag.SecretKey: lambda x, **kwargs: SecretKey(x, **kwargs),
+ Tag.SecretSubkey: lambda x, **kwargs: SecretSubkey(x, **kwargs),
+ Tag.UserID: lambda x, **kwargs: UserID(x, **kwargs),
+ Tag.UserAttribute: lambda x, **kwargs: UserAttribute(x, **kwargs),
+ Tag.SKESK: lambda x, **kwargs: SKESK(x, **kwargs),
+ Tag.SEIP: lambda x, **kwargs: SEIP(x, **kwargs),
}
@property
def tag(self):
return Tag(lib.pgp_packet_tag(self.ref()))
+ @property
+ def kind(self):
+ return Tag(lib.pgp_packet_kind(self.ref()))
def __str__(self):
return "<Packet tag={}>".format(self.tag)
def match(self):
- return self._map[self.tag](self.ref(), context=self.context(), owner=self)
+ return self._map[self.kind](self.ref(), context=self.context(), owner=self)
class PacketParserResult(SQObject):
_del = lib.pgp_packet_parser_result_free
diff --git a/ffi/lang/python/sequoia/sequoia_build.py b/ffi/lang/python/sequoia/sequoia_build.py
index 9fe6343a..5243e489 100644
--- a/ffi/lang/python/sequoia/sequoia_build.py
+++ b/ffi/lang/python/sequoia/sequoia_build.py
@@ -10,6 +10,7 @@ defs = "".join(l
open(join(pgp_inc, "io.h")).readlines(),
open(join(pgp_inc, "openpgp/types.h")).readlines(),
open(join(pgp_inc, "openpgp/crypto.h")).readlines(),
+ open(join(pgp_inc, "openpgp/packet.h")).readlines(),
open(join(pgp_inc, "openpgp.h")).readlines(),
open(join(sq_inc, "core.h")).readlines(),
open(join(sq_inc, "net.h")).readlines(),
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
},