diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2018-02-28 16:05:52 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2018-02-28 18:27:14 +0100 |
commit | 70918970bb7ef7436cc1386a88e9e41a07cc1b44 (patch) | |
tree | 221a6edd68ddbaa6044e3d3402fbc3a27ce7553d /ffi | |
parent | 7df799b20555785c6591e824c967898f4683a644 (diff) |
ffi: Bind {reader,writer}-related functions in the openpgp module.
- Bind the armor filters, as well as the reader-based constructor of
TPK.
Diffstat (limited to 'ffi')
-rw-r--r-- | ffi/examples/Makefile | 2 | ||||
-rw-r--r-- | ffi/examples/reader.c | 56 | ||||
-rw-r--r-- | ffi/include/sequoia/openpgp.h | 69 | ||||
-rw-r--r-- | ffi/src/openpgp.rs | 57 |
4 files changed, 181 insertions, 3 deletions
diff --git a/ffi/examples/Makefile b/ffi/examples/Makefile index aa1da727..d3fff15e 100644 --- a/ffi/examples/Makefile +++ b/ffi/examples/Makefile @@ -1,6 +1,6 @@ # Makefile for examples written in C. -TARGETS = example keyserver configure +TARGETS = example keyserver configure reader CFLAGS = -I../include -O0 -g -Wall LDFLAGS = -L../../target/debug -lsequoia_ffi diff --git a/ffi/examples/reader.c b/ffi/examples/reader.c new file mode 100644 index 00000000..dde98016 --- /dev/null +++ b/ffi/examples/reader.c @@ -0,0 +1,56 @@ +#define _GNU_SOURCE +#include <error.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include <sequoia.h> + +int +main (int argc, char **argv) +{ + struct stat st; + int fd; + uint8_t *b; + sq_context_t ctx; + sq_reader_t reader; + sq_tpk_t tpk; + + if (argc != 2) + error (1, 0, "Usage: %s <file>", argv[0]); + + ctx = sq_context_new("org.sequoia-pgp.example"); + if (ctx == NULL) + error (1, 0, "Initializing sequoia failed."); + + if (stat (argv[1], &st)) + error (1, errno, "%s", argv[1]); + + fd = open (argv[1], O_RDONLY); + if (fd == -1) + error (1, errno, "%s", argv[1]); + + b = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (b == MAP_FAILED) + error (1, errno, "mmap"); + + reader = sq_reader_from_bytes (b, st.st_size); + if (reader == NULL) + error (1, 0, "sq_reader_from_bytes: %s", sq_last_strerror (ctx)); + + tpk = sq_tpk_from_reader (ctx, reader); + if (tpk == NULL) + error (1, 0, "sq_tpk_from_reader: %s", sq_last_strerror (ctx)); + + sq_tpk_dump (tpk); + sq_tpk_free (tpk); + sq_reader_free (reader); + sq_context_free (ctx); + munmap (b, st.st_size); + close (fd); + return 0; +} diff --git a/ffi/include/sequoia/openpgp.h b/ffi/include/sequoia/openpgp.h index 2dd3c599..cde50be2 100644 --- a/ffi/include/sequoia/openpgp.h +++ b/ffi/include/sequoia/openpgp.h @@ -84,6 +84,69 @@ sq_keyid_t sq_fingerprint_to_keyid (const sq_fingerprint_t fp); int sq_fingerprint_equal (const sq_fingerprint_t a, const sq_fingerprint_t b); +/* openpgp::armor. */ + +/*/ +/// Specifies the type of data (see [RFC 4880, section 6.2]). +/// +/// [RFC 4880, section 6.2]: https://tools.ietf.org/html/rfc4880#section-6.2 +/*/ +typedef enum sq_armor_kind { + /*/ + /// A generic OpenPGP message. + /*/ + SQ_ARMOR_KIND_MESSAGE, + + /*/ + /// A transferable public key. + /*/ + SQ_ARMOR_KIND_PUBLICKEY, + + /*/ + /// A transferable secret key. + /*/ + SQ_ARMOR_KIND_PRIVATEKEY, + + /*/ + /// Alias for PrivateKey. + /*/ + SQ_ARMOR_KIND_SECRETKEY, + + /*/ + /// A detached signature. + /*/ + SQ_ARMOR_KIND_SIGNATURE, + + /*/ + /// A generic file. This is a GnuPG extension. + /*/ + SQ_ARMOR_KIND_FILE, + + /*/ + /// When reading an Armored file, accept any type. + /*/ + SQ_ARMOR_KIND_ANY, + + /* Dummy value to make sure the enumeration has a defined size. Do + not use this value. */ + SQ_ARMOR_KIND_FORCE_WIDTH = INT_MAX, +} sq_armor_kind_t; + +/*/ +/// Constructs a new filter for the given type of data. +/// +/// A filter that strips ASCII Armor from a stream of data. +/*/ +sq_reader_t sq_armor_reader_new (sq_reader_t inner, sq_armor_kind_t kind); + +/*/ +/// Constructs a new filter for the given type of data. +/// +/// A filter that applies ASCII Armor to the data written to it. +/*/ +sq_writer_t sq_armor_writer_new (sq_writer_t inner, sq_armor_kind_t kind); + + /* sequoia::keys. */ /*/ @@ -98,6 +161,12 @@ int sq_fingerprint_equal (const sq_fingerprint_t a, const sq_fingerprint_t b); typedef struct sq_tpk *sq_tpk_t; /*/ +/// Returns the first TPK encountered in the reader. +/*/ +sq_tpk_t sq_tpk_from_reader (sq_context_t ctx, + sq_reader_t reader); + +/*/ /// Returns the first TPK found in `buf`. /// /// `buf` must be an OpenPGP encoded message. diff --git a/ffi/src/openpgp.rs b/ffi/src/openpgp.rs index ba6c56b3..ed8c8f53 100644 --- a/ffi/src/openpgp.rs +++ b/ffi/src/openpgp.rs @@ -3,12 +3,13 @@ use std::ffi::{CString, CStr}; use std::ptr; use std::slice; -use libc::{uint8_t, c_char, size_t}; +use std::io::{Read, Write}; +use libc::{uint8_t, c_char, c_int, size_t}; extern crate openpgp; use self::openpgp::tpk::TPK; -use self::openpgp::{Fingerprint, KeyID}; +use self::openpgp::{armor, Fingerprint, KeyID}; use super::core::Context; @@ -145,8 +146,60 @@ pub extern "system" fn sq_fingerprint_equal(a: Option<&Fingerprint>, } +/* openpgp::armor. */ + +fn int_to_kind(kind: c_int) -> armor::Kind { + match kind { + 0 => armor::Kind::Message, + 1 => armor::Kind::PublicKey, + 2 => armor::Kind::PrivateKey, + 3 => armor::Kind::SecretKey, + 4 => armor::Kind::Signature, + 5 => armor::Kind::File, + 6 => armor::Kind::Any, + _ => panic!("Bad kind: {}", kind), + } +} + +/// Constructs a new filter for the given type of data. +/// +/// A filter that strips ASCII Armor from a stream of data. +#[no_mangle] +pub extern "system" fn sq_armor_reader_new(inner: Option<&'static mut Box<Read>>, + kind: c_int) + -> *mut Box<Read> { + let inner = inner.expect("Inner is NULL"); + let kind = int_to_kind(kind); + + box_raw!(Box::new(armor::Reader::new(inner, kind))) +} + +/// Constructs a new filter for the given type of data. +/// +/// A filter that applies ASCII Armor to the data written to it. +#[no_mangle] +pub extern "system" fn sq_armor_writer_new(inner: Option<&'static mut Box<Write>>, + kind: c_int) + -> *mut Box<Write> { + let inner = inner.expect("Inner is NULL"); + let kind = int_to_kind(kind); + + box_raw!(Box::new(armor::Writer::new(inner, kind))) +} + + /* sequoia::keys. */ +/// Returns the first TPK encountered in the reader. +#[no_mangle] +pub extern "system" fn sq_tpk_from_reader(ctx: Option<&mut Context>, + reader: Option<&mut Box<Read>>) + -> *mut TPK { + let ctx = ctx.expect("Context is NULL"); + let reader = reader.expect("Reader is NULL"); + fry_box!(ctx, TPK::from_reader(reader)) +} + /// Returns the first TPK found in `buf`. /// /// `buf` must be an OpenPGP encoded message. |