summaryrefslogtreecommitdiffstats
path: root/ffi
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2018-02-28 16:05:52 +0100
committerJustus Winter <justus@sequoia-pgp.org>2018-02-28 18:27:14 +0100
commit70918970bb7ef7436cc1386a88e9e41a07cc1b44 (patch)
tree221a6edd68ddbaa6044e3d3402fbc3a27ce7553d /ffi
parent7df799b20555785c6591e824c967898f4683a644 (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/Makefile2
-rw-r--r--ffi/examples/reader.c56
-rw-r--r--ffi/include/sequoia/openpgp.h69
-rw-r--r--ffi/src/openpgp.rs57
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.