From 3f58832474a4b270e136544016a401ef773ac065 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Thu, 17 Jan 2019 11:11:27 +0100 Subject: openpgp-ffi: New crate. - This creates a new crate, 'sequoia-openpgp-ffi', and moves a handful of functions from 'sequoia-ffi' to it. - The 'sequoia-ffi' crate is a superset of the 'sequoia-openpgp-ffi' crate. This is accomplished by some include! magic. - My first attempt involved having 'sequoia-ffi' depend on 'sequoia-openpgp-ffi', so that the former just re-exports the symbols. However, that turned out to be unreliable, and might be not what we want, because it could also duplicate parts of Rust's standard library. - Fixes #144. --- Cargo.toml | 1 + Makefile | 4 +- ffi/Cargo.toml | 1 + ffi/examples/.gitignore | 5 - ffi/examples/Makefile | 4 +- ffi/examples/armor.c | 60 - ffi/examples/encrypt-for.c | 96 -- ffi/examples/example.c | 45 - ffi/examples/parser.c | 93 -- ffi/examples/reader.c | 48 - ffi/include/sequoia.h | 2 +- ffi/include/sequoia/core.h | 80 -- ffi/include/sequoia/error.h | 147 -- ffi/include/sequoia/openpgp.h | 1658 ----------------------- ffi/include/sequoia/openpgp/crypto.h | 50 - ffi/lang/python/Makefile | 2 +- ffi/lang/python/sequoia/sequoia_build.py | 16 +- ffi/src/core.rs | 175 +-- ffi/src/error.rs | 118 +- ffi/src/lib.rs | 242 +--- ffi/src/openpgp/armor.rs | 347 ----- ffi/src/openpgp/crypto.rs | 54 - ffi/src/openpgp/fingerprint.rs | 110 -- ffi/src/openpgp/keyid.rs | 99 -- ffi/src/openpgp/mod.rs | 1637 ---------------------- ffi/src/openpgp/packet_pile.rs | 93 -- ffi/src/openpgp/tpk.rs | 698 ---------- ffi/src/openpgp/tsk.rs | 76 -- ffi/tests/c-tests.rs | 1 + openpgp-ffi/Cargo.toml | 35 + openpgp-ffi/Makefile | 66 + openpgp-ffi/examples/.gitignore | 5 + openpgp-ffi/examples/Makefile | 17 + openpgp-ffi/examples/armor.c | 60 + openpgp-ffi/examples/encrypt-for.c | 96 ++ openpgp-ffi/examples/example.c | 45 + openpgp-ffi/examples/parser.c | 93 ++ openpgp-ffi/examples/reader.c | 48 + openpgp-ffi/include/sequoia/io.h | 83 ++ openpgp-ffi/include/sequoia/openpgp.h | 1663 +++++++++++++++++++++++ openpgp-ffi/include/sequoia/openpgp/crypto.h | 50 + openpgp-ffi/include/sequoia/openpgp/error.h | 147 ++ openpgp-ffi/rustdoc.head.html | 4 + openpgp-ffi/sequoia-openpgp.pc.in | 11 + openpgp-ffi/src/armor.rs | 347 +++++ openpgp-ffi/src/common.rs | 1873 ++++++++++++++++++++++++++ openpgp-ffi/src/crypto.rs | 54 + openpgp-ffi/src/error.rs | 173 +++ openpgp-ffi/src/fingerprint.rs | 110 ++ openpgp-ffi/src/io.rs | 175 +++ openpgp-ffi/src/keyid.rs | 99 ++ openpgp-ffi/src/lib.rs | 118 ++ openpgp-ffi/src/mod.rs | 0 openpgp-ffi/src/packet_pile.rs | 93 ++ openpgp-ffi/src/tpk.rs | 698 ++++++++++ openpgp-ffi/src/tsk.rs | 76 ++ openpgp-ffi/tests/c-tests.rs | 303 +++++ 57 files changed, 6577 insertions(+), 5927 deletions(-) delete mode 100644 ffi/examples/armor.c delete mode 100644 ffi/examples/encrypt-for.c delete mode 100644 ffi/examples/example.c delete mode 100644 ffi/examples/parser.c delete mode 100644 ffi/examples/reader.c delete mode 100644 ffi/include/sequoia/error.h delete mode 100644 ffi/include/sequoia/openpgp.h delete mode 100644 ffi/include/sequoia/openpgp/crypto.h delete mode 100644 ffi/src/openpgp/armor.rs delete mode 100644 ffi/src/openpgp/crypto.rs delete mode 100644 ffi/src/openpgp/fingerprint.rs delete mode 100644 ffi/src/openpgp/keyid.rs delete mode 100644 ffi/src/openpgp/mod.rs delete mode 100644 ffi/src/openpgp/packet_pile.rs delete mode 100644 ffi/src/openpgp/tpk.rs delete mode 100644 ffi/src/openpgp/tsk.rs create mode 100644 openpgp-ffi/Cargo.toml create mode 100644 openpgp-ffi/Makefile create mode 100644 openpgp-ffi/examples/.gitignore create mode 100644 openpgp-ffi/examples/Makefile create mode 100644 openpgp-ffi/examples/armor.c create mode 100644 openpgp-ffi/examples/encrypt-for.c create mode 100644 openpgp-ffi/examples/example.c create mode 100644 openpgp-ffi/examples/parser.c create mode 100644 openpgp-ffi/examples/reader.c create mode 100644 openpgp-ffi/include/sequoia/io.h create mode 100644 openpgp-ffi/include/sequoia/openpgp.h create mode 100644 openpgp-ffi/include/sequoia/openpgp/crypto.h create mode 100644 openpgp-ffi/include/sequoia/openpgp/error.h create mode 100644 openpgp-ffi/rustdoc.head.html create mode 100644 openpgp-ffi/sequoia-openpgp.pc.in create mode 100644 openpgp-ffi/src/armor.rs create mode 100644 openpgp-ffi/src/common.rs create mode 100644 openpgp-ffi/src/crypto.rs create mode 100644 openpgp-ffi/src/error.rs create mode 100644 openpgp-ffi/src/fingerprint.rs create mode 100644 openpgp-ffi/src/io.rs create mode 100644 openpgp-ffi/src/keyid.rs create mode 100644 openpgp-ffi/src/lib.rs create mode 100644 openpgp-ffi/src/mod.rs create mode 100644 openpgp-ffi/src/packet_pile.rs create mode 100644 openpgp-ffi/src/tpk.rs create mode 100644 openpgp-ffi/src/tsk.rs create mode 100644 openpgp-ffi/tests/c-tests.rs diff --git a/Cargo.toml b/Cargo.toml index 24442b0b..a330a5f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ maintenance = { status = "actively-developed" } [dependencies] buffered-reader = { path = "buffered-reader", version = "0.3.0" } sequoia-openpgp = { path = "openpgp", version = "0.3.0" } +sequoia-openpgp-ffi = { path = "openpgp-ffi", version = "0.3.0" } sequoia-core = { path = "core", version = "0.3.0" } sequoia-ffi = { path = "ffi", version = "0.3.0" } sequoia-ffi-macros = { path = "ffi-macros", version = "0.3.0" } diff --git a/Makefile b/Makefile index 134ded7b..6d83e0e5 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,9 @@ doc: $(CARGO) doc $(CARGO_FLAGS) --no-deps --all env RUSTDOCFLAGS="$(FFI_RUSTDOCFLAGS)" \ CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) \ - $(CARGO) doc $(CARGO_FLAGS) --no-deps --package sequoia-ffi + $(CARGO) doc $(CARGO_FLAGS) --no-deps \ + --package sequoia-ffi \ + --package sequoia-openpgp-ffi .PHONY: deploy-doc deploy-doc: doc diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml index 80059a09..3e158d0c 100644 --- a/ffi/Cargo.toml +++ b/ffi/Cargo.toml @@ -23,6 +23,7 @@ maintenance = { status = "actively-developed" } [dependencies] sequoia-ffi-macros = { path = "../ffi-macros" } sequoia-openpgp = { path = "../openpgp" } +sequoia-openpgp-ffi = { path = "../openpgp-ffi" } sequoia-core = { path = "../core" } sequoia-store = { path = "../store" } sequoia-net = { path = "../net" } diff --git a/ffi/examples/.gitignore b/ffi/examples/.gitignore index 17a9b656..e72a3164 100644 --- a/ffi/examples/.gitignore +++ b/ffi/examples/.gitignore @@ -1,7 +1,2 @@ configure -example keyserver -reader -parser -encrypt-for -armor diff --git a/ffi/examples/Makefile b/ffi/examples/Makefile index 4ca01078..a8d2baa1 100644 --- a/ffi/examples/Makefile +++ b/ffi/examples/Makefile @@ -5,8 +5,8 @@ CARGO_TARGET_DIR ?= $(shell pwd)/../../target # We currently only support absolute paths. CARGO_TARGET_DIR := $(abspath $(CARGO_TARGET_DIR)) -TARGETS = example keyserver configure reader parser encrypt-for armor -CFLAGS = -I../include -O0 -g -Wall -Werror +TARGETS = keyserver configure +CFLAGS = -I../include -I../../openpgp-ffi/include -O0 -g -Wall -Werror LDFLAGS = -L$(CARGO_TARGET_DIR)/debug -lsequoia_ffi all: $(TARGETS) diff --git a/ffi/examples/armor.c b/ffi/examples/armor.c deleted file mode 100644 index 5a1b9339..00000000 --- a/ffi/examples/armor.c +++ /dev/null @@ -1,60 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include - -#include - -const char *armored = - "-----BEGIN PGP ARMORED FILE-----\n" - "Key0: Value0\n" - "Key1: Value1\n" - "\n" - "SGVsbG8gd29ybGQh\n" - "=s4Gu\n" - "-----END PGP ARMORED FILE-----\n"; - -int -main (int argc, char **argv) -{ - sq_error_t err; - sq_reader_t bytes; - sq_reader_t armor; - sq_armor_kind_t kind; - char message[12]; - sq_armor_header_t *header; - size_t header_len; - - bytes = sq_reader_from_bytes ((uint8_t *) armored, strlen (armored)); - armor = sq_armor_reader_new (bytes, SQ_ARMOR_KIND_ANY); - - header = sq_armor_reader_headers (&err, armor, &header_len); - if (header == NULL) - error (1, 0, "Getting headers failed: %s", sq_error_string (err)); - - assert (header_len == 2); - assert (strcmp (header[0].key, "Key0") == 0 - && strcmp (header[0].value, "Value0") == 0); - assert (strcmp (header[1].key, "Key1") == 0 - && strcmp (header[1].value, "Value1") == 0); - for (size_t i = 0; i < header_len; i++) - { - free (header[i].key); - free (header[i].value); - } - free (header); - - kind = sq_armor_reader_kind (armor); - assert (kind == SQ_ARMOR_KIND_FILE); - - if (sq_reader_read (&err, armor, (uint8_t *) message, 12) < 0) - error (1, 0, "Reading failed: %s", sq_error_string (err)); - - assert (memcmp (message, "Hello world!", 12) == 0); - - sq_reader_free (armor); - sq_reader_free (bytes); - return 0; -} diff --git a/ffi/examples/encrypt-for.c b/ffi/examples/encrypt-for.c deleted file mode 100644 index f0c34449..00000000 --- a/ffi/examples/encrypt-for.c +++ /dev/null @@ -1,96 +0,0 @@ -/* This example demonstrates how to use the low-level interface to - encrypt a file. */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -int -main (int argc, char **argv) -{ - struct stat st; - int fd; - uint8_t *b; - sq_status_t rc; - sq_error_t err; - int use_armor = 1; - sq_tpk_t tpk; - sq_writer_t sink; - sq_writer_stack_t writer = NULL; - void *cipher = NULL; - size_t cipher_bytes = 0; - - if (argc != 2) - error (1, 0, "Usage: %s cipher", argv[0]); - - 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); - close (fd); - if (b == MAP_FAILED) - error (1, errno, "mmap"); - - tpk = sq_tpk_from_bytes (&err, b, st.st_size); - if (tpk == NULL) - error (1, 0, "sq_packet_parser_from_bytes: %s", sq_error_string (err)); - - sink = sq_writer_alloc (&cipher, &cipher_bytes); - - if (use_armor) - sink = sq_armor_writer_new (&err, sink, SQ_ARMOR_KIND_MESSAGE, - NULL, 0); - - writer = sq_writer_stack_message (sink); - writer = sq_encryptor_new (&err, - writer, - NULL, 0, /* no passwords */ - &tpk, 1, - SQ_ENCRYPTION_MODE_FOR_TRANSPORT); - if (writer == NULL) - error (1, 0, "sq_encryptor_new: %s", sq_error_string (err)); - - writer = sq_literal_writer_new (&err, writer); - if (writer == NULL) - error (1, 0, "sq_literal_writer_new: %s", sq_error_string (err)); - - size_t nread; - uint8_t buf[4096]; - while ((nread = fread (buf, 1, sizeof buf, stdin))) - { - uint8_t *b = buf; - while (nread) - { - ssize_t written; - written = sq_writer_stack_write (&err, writer, b, nread); - if (written < 0) - error (1, 0, "sq_writer_stack_write: %s", sq_error_string (err)); - - b += written; - nread -= written; - } - } - - rc = sq_writer_stack_finalize (&err, writer); - writer = NULL; - if (rc) - error (1, 0, "sq_writer_stack_write: %s", sq_error_string (err)); - - fwrite (cipher, 1, cipher_bytes, stdout); - - munmap (b, st.st_size); - return 0; -} diff --git a/ffi/examples/example.c b/ffi/examples/example.c deleted file mode 100644 index 8636d011..00000000 --- a/ffi/examples/example.c +++ /dev/null @@ -1,45 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -int -main (int argc, char **argv) -{ - struct stat st; - int fd; - uint8_t *b; - sq_error_t err; - sq_tpk_t tpk; - - if (argc != 2) - error (1, 0, "Usage: %s ", argv[0]); - - 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"); - - tpk = sq_tpk_from_bytes (&err, b, st.st_size); - if (tpk == NULL) - error (1, 0, "sq_tpk_from_bytes: %s", sq_error_string (err)); - - sq_tpk_dump (tpk); - sq_tpk_free (tpk); - munmap (b, st.st_size); - close (fd); - return 0; -} diff --git a/ffi/examples/parser.c b/ffi/examples/parser.c deleted file mode 100644 index 8d953422..00000000 --- a/ffi/examples/parser.c +++ /dev/null @@ -1,93 +0,0 @@ -/* This example demonstrates how to use the packet parser from C. It - * also serves as a simple benchmark. */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -int -main (int argc, char **argv) -{ - struct stat st; - int fd; - uint8_t *b; - sq_status_t rc; - sq_error_t err; - sq_packet_parser_result_t ppr; - sq_packet_parser_t pp; - - if (argc != 2) - error (1, 0, "Usage: %s ", argv[0]); - - 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); - close (fd); - if (b == MAP_FAILED) - error (1, errno, "mmap"); - - size_t n = 0; - time_t start = time (NULL); - time_t elapsed; - size_t tens_of_s = 0; - - ppr = sq_packet_parser_from_bytes (&err, b, st.st_size); - while (ppr && (pp = sq_packet_parser_result_packet_parser (ppr))) - { - // Get a reference to the packet that is currently being parsed. - sq_packet_t p = sq_packet_parser_packet (pp); - - if (sq_packet_tag(p) == SQ_TAG_LITERAL) - { - // Stream the packet here. - } - - // Finish parsing the current packet (returned in p), and read - // the header of the next packet (returned in ppr). - rc = sq_packet_parser_next (&err, pp, &p, &ppr); - if (rc) - error (1, 0, "sq_packet_parser_from_bytes: %s", - sq_error_string (err)); - - // We now own p. If we want, we can save it in some structure. - // This would be useful when collecting PKESK packets. Either - // way, we need to free it when we are done. - - n += 1; - - sq_packet_free (p); - - elapsed = time (NULL) - start; - if (elapsed % 10 == 0 && tens_of_s != elapsed / 10) - { - fprintf (stderr, - "Parsed %ld packets in %ld seconds, %.2f packets/s.\n", - n, elapsed, (double) n / (double) elapsed); - fflush (stderr); - tens_of_s = elapsed / 10; - } - } - if (ppr == NULL) - error (1, 0, "sq_packet_parser_from_bytes: %s", sq_error_string (err)); - - fprintf (stderr, "Parsed %ld packets in %ld seconds, %.2f packets/s.\n", - n, elapsed, (double) n / (double) elapsed); - - sq_packet_parser_result_free (ppr); - munmap (b, st.st_size); - return 0; -} diff --git a/ffi/examples/reader.c b/ffi/examples/reader.c deleted file mode 100644 index 8e458620..00000000 --- a/ffi/examples/reader.c +++ /dev/null @@ -1,48 +0,0 @@ -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -int -main (int argc, char **argv) -{ - struct stat st; - int fd; - uint8_t *b; - sq_error_t err; - sq_reader_t reader; - sq_tpk_t tpk; - - if (argc != 2) - error (1, 0, "Usage: %s ", argv[0]); - - 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); - tpk = sq_tpk_from_reader (&err, reader); - if (tpk == NULL) - error (1, 0, "sq_tpk_from_reader: %s", sq_error_string (err)); - - sq_tpk_dump (tpk); - sq_tpk_free (tpk); - sq_reader_free (reader); - munmap (b, st.st_size); - close (fd); - return 0; -} diff --git a/ffi/include/sequoia.h b/ffi/include/sequoia.h index 485b8cc3..8c62ba8f 100644 --- a/ffi/include/sequoia.h +++ b/ffi/include/sequoia.h @@ -1,7 +1,7 @@ #ifndef SEQUOIA_H #define SEQUOIA_H -#include +#include #include #include #include diff --git a/ffi/include/sequoia/core.h b/ffi/include/sequoia/core.h index 9d7d261b..0d2ea3cd 100644 --- a/ffi/include/sequoia/core.h +++ b/ffi/include/sequoia/core.h @@ -218,84 +218,4 @@ void sq_config_ipc_policy(sq_config_t cfg, sq_ipc_policy_t policy); /*/ void sq_config_ephemeral(sq_config_t cfg); - -/* Reader and writer. */ - -/*/ -/// A generic reader. -/*/ -typedef struct sq_reader *sq_reader_t; - -/*/ -/// Opens a file returning a reader. -/*/ -sq_reader_t sq_reader_from_file (sq_error_t *errp, const char *filename); - -/*/ -/// Opens a file descriptor returning a reader. -/*/ -sq_reader_t sq_reader_from_fd (int fd); - -/*/ -/// Creates a reader from a buffer. -/*/ -sq_reader_t sq_reader_from_bytes (const uint8_t *buf, size_t len); - -/*/ -/// Frees a reader. -/*/ -void sq_reader_free (sq_reader_t reader); - -/*/ -/// Reads up to `len` bytes into `buf`. -/*/ -ssize_t sq_reader_read (sq_error_t *errp, sq_reader_t reader, - uint8_t *buf, size_t len); - -/*/ -/// A generic writer. -/*/ -typedef struct sq_writer *sq_writer_t; - -/*/ -/// Opens a file returning a writer. -/// -/// The file will be created if it does not exist, or be truncated -/// otherwise. If you need more control, use `sq_writer_from_fd`. -/*/ -sq_writer_t sq_writer_from_file (sq_error_t *errp, const char *filename); - -/*/ -/// Opens a file descriptor returning a writer. -/*/ -sq_writer_t sq_writer_from_fd (int fd); - -/*/ -/// Creates a writer from a buffer. -/*/ -sq_writer_t sq_writer_from_bytes (uint8_t *buf, size_t len); - -/*/ -/// Creates an allocating writer. -/// -/// This writer allocates memory using `malloc`, and stores the -/// pointer to the memory and the number of bytes written to the given -/// locations `buf`, and `len`. Both must either be set to zero, or -/// reference a chunk of memory allocated using libc's heap allocator. -/// The caller is responsible to `free` it once the writer has been -/// destroyed. -/*/ -sq_writer_t sq_writer_alloc (void **buf, size_t *len); - -/*/ -/// Frees a writer. -/*/ -void sq_writer_free (sq_writer_t writer); - -/*/ -/// Writes up to `len` bytes of `buf` into `writer`. -/*/ -ssize_t sq_writer_write (sq_error_t *errp, sq_writer_t writer, - const uint8_t *buf, size_t len); - #endif diff --git a/ffi/include/sequoia/error.h b/ffi/include/sequoia/error.h deleted file mode 100644 index dd42753c..00000000 --- a/ffi/include/sequoia/error.h +++ /dev/null @@ -1,147 +0,0 @@ -#ifndef SEQUOIA_ERRORS_H -#define SEQUOIA_ERRORS_H - -#include -#include -#include - -/* XXX: Reorder and name-space before release. */ -typedef enum sq_status { - /*/ - /// The operation was successful. - /*/ - SQ_STATUS_SUCCESS = 0, - - /*/ - /// An unknown error occurred. - /*/ - SQ_STATUS_UNKNOWN_ERROR = -1, - - /*/ - /// The network policy was violated by the given action. - /*/ - SQ_STATUS_NETWORK_POLICY_VIOLATION = -2, - - /*/ - /// An IO error occurred. - /*/ - SQ_STATUS_IO_ERROR = -3, - - /*/ - /// A given argument is invalid. - /*/ - SQ_STATUS_INVALID_ARGUMENT = -15, - - /*/ - /// The requested operation is invalid. - /*/ - SQ_STATUS_INVALID_OPERATION = -4, - - /*/ - /// The packet is malformed. - /*/ - SQ_STATUS_MALFORMED_PACKET = -5, - - /*/ - /// Unsupported hash algorithm. - /*/ - SQ_STATUS_UNSUPPORTED_HASH_ALGORITHM = -9, - - /*/ - /// Unsupported public key algorithm. - /*/ - SQ_STATUS_UNSUPPORTED_PUBLICKEY_ALGORITHM = -18, - - /*/ - /// Unsupported elliptic curve. - /*/ - SQ_STATUS_UNSUPPORTED_ELLIPTIC_CURVE = -21, - - /*/ - /// Unsupported symmetric algorithm. - /*/ - SQ_STATUS_UNSUPPORTED_SYMMETRIC_ALGORITHM = -10, - - /*/ - /// Unsupported AEAD algorithm. - /*/ - SQ_STATUS_UNSUPPORTED_AEAD_ALGORITHM = -26, - - /*/ - /// Unsupport signature type. - /*/ - SQ_STATUS_UNSUPPORTED_SIGNATURE_TYPE = -20, - - /*/ - /// Invalid password. - /*/ - SQ_STATUS_INVALID_PASSWORD = -11, - - /*/ - /// Invalid session key. - /*/ - SQ_STATUS_INVALID_SESSION_KEY = -12, - - /*/ - /// Missing session key. - /*/ - SQ_STATUS_MISSING_SESSION_KEY = -27, - - /*/ - /// Malformed TPK. - /*/ - SQ_STATUS_MALFORMED_TPK = -13, - - /*/ - /// Bad signature. - /*/ - SQ_STATUS_BAD_SIGNATURE = -19, - - /*/ - /// Message has been manipulated. - /*/ - SQ_STATUS_MANIPULATED_MESSAGE = -25, - - /*/ - /// Malformed message. - /*/ - SQ_STATUS_MALFORMED_MESSAGE = -22, - - /*/ - /// Index out of range. - /*/ - SQ_STATUS_INDEX_OUT_OF_RANGE = -23, - - /*/ - /// TPK not supported. - /*/ - SQ_STATUS_UNSUPPORTED_TPK = -24, - - /* Dummy value to make sure the enumeration has a defined size. Do - not use this value. */ - SQ_STATUS_FORCE_WIDTH = INT_MAX, -} sq_status_t; - -/*/ -/// Complex errors returned from Sequoia. -/*/ -typedef struct sq_error *sq_error_t; - -/*/ -/// Frees an error. -/*/ -void sq_error_free (sq_error_t error); - -/*/ -/// Returns the error message. -/// -/// The returned value must be freed with `free(3)`. -/*/ -char *sq_error_string (const sq_error_t err); - -/*/ -/// Returns the error status code. -/*/ -sq_status_t sq_error_status (const sq_error_t err); - -#endif diff --git a/ffi/include/sequoia/openpgp.h b/ffi/include/sequoia/openpgp.h deleted file mode 100644 index 2632a58a..00000000 --- a/ffi/include/sequoia/openpgp.h +++ /dev/null @@ -1,1658 +0,0 @@ -#ifndef SEQUOIA_OPENPGP_H -#define SEQUOIA_OPENPGP_H - -#include -#include - -#include - -/*/ -/// A low-level OpenPGP message parser. -/// -/// A `PacketParser` provides a low-level, iterator-like interface to -/// parse OpenPGP messages. -/// -/// For each iteration, the user is presented with a [`Packet`] -/// corresponding to the last packet, a `PacketParser` for the next -/// packet, and their positions within the message. -/// -/// Using the `PacketParser`, the user is able to configure how the -/// new packet will be parsed. For instance, it is possible to stream -/// the packet's contents (a `PacketParser` implements the -/// `std::io::Read` and the `BufferedReader` traits), buffer them -/// within the [`Packet`], or drop them. The user can also decide to -/// recurse into the packet, if it is a container, instead of getting -/// the following packet. -/*/ -typedef struct sq_packet_parser *sq_packet_parser_t; - -/*/ -/// Like an `Option`, but the `None` variant -/// (`PacketParserEOF`) contains some summary information. -/*/ -typedef struct sq_packet_parser_result *sq_packet_parser_result_t; - -/*/ -/// The `None` variant of a `PacketParserResult`. -/*/ -typedef struct sq_packet_parser_eof *sq_packet_parser_eof_t; - -/* sequoia::openpgp::KeyID. */ - -/*/ -/// Holds a KeyID. -/*/ -typedef struct sq_keyid *sq_keyid_t; - -/*/ -/// Reads a binary key ID. -/*/ -sq_keyid_t sq_keyid_from_bytes (const uint8_t *id); - -/*/ -/// Reads a hex-encoded Key ID. -/*/ -sq_keyid_t sq_keyid_from_hex (const char *id); - -/*/ -/// Frees a sq_keyid_t. -/*/ -void sq_keyid_free (sq_keyid_t keyid); - -/*/ -/// Clones the KeyID. -/*/ -sq_keyid_t sq_keyid_clone (sq_keyid_t keyid); - -/*/ -/// Hashes the KeyID. -/*/ -uint64_t sq_keyid_hash (sq_keyid_t keyid); - -/*/ -/// Converts the KeyID to its standard representation. -/*/ -char *sq_keyid_to_string (const sq_keyid_t fp); - -/*/ -/// Converts the KeyID to a hexadecimal number. -/*/ -char *sq_keyid_to_hex (const sq_keyid_t keyid); - -/*/ -/// Compares KeyIDs. -/*/ -int sq_keyid_equal (const sq_keyid_t a, const sq_keyid_t b); - - -/* sequoia::openpgp::Fingerprint. */ - -/*/ -/// Holds a fingerprint. -/*/ -typedef struct sq_fingerprint *sq_fingerprint_t; - -/*/ -/// Reads a binary fingerprint. -/*/ -sq_fingerprint_t sq_fingerprint_from_bytes (const uint8_t *buf, size_t len); - -/*/ -/// Reads a hexadecimal fingerprint. -/*/ -sq_fingerprint_t sq_fingerprint_from_hex (const char *hex); - -/*/ -/// Frees a sq_fingerprint_t. -/*/ -void sq_fingerprint_free (sq_fingerprint_t fp); - -/*/ -/// Clones the Fingerprint. -/*/ -sq_fingerprint_t sq_fingerprint_clone (sq_fingerprint_t fingerprint); - -/*/ -/// Hashes the Fingerprint. -/*/ -uint64_t sq_fingerprint_hash (sq_fingerprint_t fingerprint); - -/*/ -/// Returns a reference to the raw Fingerprint. -/// -/// This returns a reference to the internal buffer that is valid as -/// long as the fingerprint is. -/*/ -uint8_t *sq_fingerprint_as_bytes (const sq_fingerprint_t fp, size_t *fp_len); - -/*/ -/// Converts the fingerprint to its standard representation. -/*/ -char *sq_fingerprint_to_string (const sq_fingerprint_t fp); - -/*/ -/// Converts the fingerprint to a hexadecimal number. -/*/ -char *sq_fingerprint_to_hex (const sq_fingerprint_t fp); - -/*/ -/// Converts the fingerprint to a key ID. -/*/ -sq_keyid_t sq_fingerprint_to_keyid (const sq_fingerprint_t fp); - -/*/ -/// Compares Fingerprints. -/*/ -int sq_fingerprint_equal (const sq_fingerprint_t a, const sq_fingerprint_t b); - -/* sequoia::openpgp::RevocationStatus. */ - -/*/ -/// Holds a revocation status. -/*/ -typedef struct sq_revocation_status *sq_revocation_status_t; - -typedef enum sq_revocation_status_variant { - /*/ - /// The key is definitely revoked. - /// - /// All self-revocations are returned, the most recent revocation - /// first. - /*/ - SQ_REVOCATION_STATUS_REVOKED, - - /*/ - /// We have a third-party revocation certificate that is allegedly - /// from a designated revoker, but we don't have the designated - /// revoker's key to check its validity. - /// - /// All such certificates are returned. The caller must check - /// them manually. - /*/ - SQ_REVOCATION_STATUS_COULD_BE, - - /*/ - /// The key does not appear to be revoked, but perhaps an attacker - /// has performed a DoS, which prevents us from seeing the - /// revocation certificate. - /*/ - SQ_REVOCATION_STATUS_NOT_AS_FAR_AS_WE_KNOW, - - /* Dummy value to make sure the enumeration has a defined size. Do - not use this value. */ - SQ_REVOCATION_STATUS_FORCE_WIDTH = INT_MAX, -} sq_revocation_status_variant_t; - -/*/ -/// Returns the revocation status's variant. -/*/ -sq_revocation_status_variant_t sq_revocation_status_variant ( - sq_revocation_status_t rs); - -/*/ -/// Frees the revocation status. -/*/ -void sq_revocation_status_free (sq_revocation_status_t rs); - - -/* 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 { - /*/ - /// When reading an Armored file, accept any type. - /*/ - SQ_ARMOR_KIND_ANY, - - /*/ - /// A generic OpenPGP message. - /*/ - SQ_ARMOR_KIND_MESSAGE, - - /*/ - /// A transferable public key. - /*/ - SQ_ARMOR_KIND_PUBLICKEY, - - /*/ - /// A transferable secret key. - /*/ - SQ_ARMOR_KIND_SECRETKEY, - - /*/ - /// A detached signature. - /*/ - SQ_ARMOR_KIND_SIGNATURE, - - /*/ - /// A generic file. This is a GnuPG extension. - /*/ - SQ_ARMOR_KIND_FILE, - - /* 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; - -/*/ -/// Represents a (key, value) pair in an armor header. -/*/ -typedef struct sq_armor_header { - char *key; - char *value; -} sq_armor_header_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); - -/*/ -/// Creates a `Reader` from a file. -/*/ -sq_reader_t sq_armor_reader_from_file (sq_error_t *errp, - const char *filename, - sq_armor_kind_t kind); - -/*/ -/// Creates a `Reader` from a buffer. -/*/ -sq_reader_t sq_armor_reader_from_bytes (const uint8_t *b, size_t len, - sq_armor_kind_t kind); - - -/*/ -/// Returns the kind of data this reader is for. -/// -/// Useful if the kind of data is not known in advance. If the header -/// has not been encountered yet (try reading some data first!), this -/// function returns SQ_ARMOR_KIND_ANY. -/*/ -sq_armor_kind_t sq_armor_reader_kind (sq_reader_t reader); - -/*/ -/// Returns the armored headers. -/// -/// The tuples contain a key and a value. -/// -/// Note: if a key occurs multiple times, then there are multiple -/// entries in the vector with the same key; values with the same -/// key are *not* combined. -/// -/// The returned array and the strings in the headers have been -/// allocated with `malloc`, and the caller is responsible for freeing -/// both the array and the strings. -/*/ -sq_armor_header_t *sq_armor_reader_headers (sq_error_t *errp, - sq_reader_t reader, - size_t *len); - - -/*/ -/// 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_error_t *errp, sq_writer_t inner, - sq_armor_kind_t kind, - sq_armor_header_t *header, size_t header_len); - - - -/*/ -/// The OpenPGP packet tags as defined in [Section 4.3 of RFC 4880]. -/// -/// [Section 4.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-4.3 -/// -/// The values correspond to the serialized format. The packet types -/// named `UnassignedXX` are not in use as of RFC 4880. -/// -/// Use [`Tag::from_numeric`] to translate a numeric value to a symbolic -/// one. -/// -/// [`Tag::from_numeric`]: enum.Tag.html#method.from_numeric -/*/ -typedef enum sq_tag { - SQ_TAG_RESERVED0 = 0, - /* Public-Key Encrypted Session Key Packet. */ - SQ_TAG_PKESK = 1, - SQ_TAG_SIGNATURE = 2, - /* Symmetric-Key Encrypted Session Key Packet. */ - SQ_TAG_SKESK = 3, - /* One-Pass Signature Packet. */ - SQ_TAG_ONE_PASS_SIG = 4, - SQ_TAG_SECRET_KEY = 5, - SQ_TAG_PUBLIC_KEY = 6, - SQ_TAG_SECRET_SUBKEY = 7, - SQ_TAG_COMPRESSED_DATA = 8, - /* Symmetrically Encrypted Data Packet. */ - SQ_TAG_SED = 9, - SQ_TAG_MARKER = 10, - SQ_TAG_LITERAL = 11, - SQ_TAG_TRUST = 12, - SQ_TAG_USER_ID = 13, - SQ_TAG_PUBLIC_SUBKEY = 14, - - SQ_TAG_UNASSIGNED15 = 15, - SQ_TAG_UNASSIGNED16 = 16, - - SQ_TAG_USER_ATTRIBUTE = 17, - /* Sym. Encrypted and Integrity Protected Data Packet. */ - SQ_TAG_SEIP = 18, - /* Modification Detection Code Packet. */ - SQ_TAG_MDC = 19, - - /* Unassigned packets (as of RFC4880). */ - SQ_TAG_UNASSIGNED20 = 20, - SQ_TAG_UNASSIGNED21 = 21, - SQ_TAG_UNASSIGNED22 = 22, - SQ_TAG_UNASSIGNED23 = 23, - SQ_TAG_UNASSIGNED24 = 24, - SQ_TAG_UNASSIGNED25 = 25, - SQ_TAG_UNASSIGNED26 = 26, - SQ_TAG_UNASSIGNED27 = 27, - SQ_TAG_UNASSIGNED28 = 28, - SQ_TAG_UNASSIGNED29 = 29, - - SQ_TAG_UNASSIGNED30 = 30, - SQ_TAG_UNASSIGNED31 = 31, - SQ_TAG_UNASSIGNED32 = 32, - SQ_TAG_UNASSIGNED33 = 33, - SQ_TAG_UNASSIGNED34 = 34, - SQ_TAG_UNASSIGNED35 = 35, - SQ_TAG_UNASSIGNED36 = 36, - SQ_TAG_UNASSIGNED37 = 37, - SQ_TAG_UNASSIGNED38 = 38, - SQ_TAG_UNASSIGNED39 = 39, - - SQ_TAG_UNASSIGNED40 = 40, - SQ_TAG_UNASSIGNED41 = 41, - SQ_TAG_UNASSIGNED42 = 42, - SQ_TAG_UNASSIGNED43 = 43, - SQ_TAG_UNASSIGNED44 = 44, - SQ_TAG_UNASSIGNED45 = 45, - SQ_TAG_UNASSIGNED46 = 46, - SQ_TAG_UNASSIGNED47 = 47, - SQ_TAG_UNASSIGNED48 = 48, - SQ_TAG_UNASSIGNED49 = 49, - - SQ_TAG_UNASSIGNED50 = 50, - SQ_TAG_UNASSIGNED51 = 51, - SQ_TAG_UNASSIGNED52 = 52, - SQ_TAG_UNASSIGNED53 = 53, - SQ_TAG_UNASSIGNED54 = 54, - SQ_TAG_UNASSIGNED55 = 55, - SQ_TAG_UNASSIGNED56 = 56, - SQ_TAG_UNASSIGNED57 = 57, - SQ_TAG_UNASSIGNED58 = 58, - SQ_TAG_UNASSIGNED59 = 59, - - /* Experimental packets. */ - SQ_TAG_PRIVATE0 = 60, - SQ_TAG_PRIVATE1 = 61, - SQ_TAG_PRIVATE2 = 62, - SQ_TAG_PRIVATE3 = 63, -} sq_tag_t; - -/*/ -/// Returns a human-readable tag name. -/*/ -const char *sq_tag_to_string (sq_tag_t tag); - -/*/ -/// Opaque types for all the Packets that Sequoia understands. -/*/ -typedef struct sq_unknown *sq_unknown_t; -typedef struct sq_signature *sq_signature_t; -typedef struct sq_one_pass_sig *sq_one_pass_sig_t; -typedef struct sq_p_key *sq_p_key_t; -typedef struct sq_user_id *sq_user_id_t; -typedef struct sq_user_attribute *sq_user_attribute_t; -typedef struct sq_literal *sq_literal_t; -typedef struct sq_compressed_data *sq_compressed_data_t; -typedef struct sq_pkesk *sq_pkesk_t; -typedef struct sq_skesk *sq_skesk_t; -typedef struct sq_seip *sq_seip_t; -typedef struct sq_mdc *sq_mdc_t; - -/*/ -/// 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 -/*/ -typedef union sq_packet { - sq_unknown_t unknown; - sq_signature_t signature; - sq_one_pass_sig_t one_pass_sig; - sq_p_key_t key; - sq_user_id_t user_id; - sq_user_attribute_t user_attribute; - sq_literal_t literal; - sq_compressed_data_t compressed_data; - sq_pkesk_t pkesk; - sq_skesk_t skesk; - sq_seip_t seip; - sq_mdc_t mdc; -} sq_packet_t; - -/*/ -/// Frees the Packet. -/*/ -void sq_packet_free (sq_packet_t p); - -/*/ -/// 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 -/*/ -sq_tag_t sq_packet_tag (sq_packet_t p); - -/*/ -/// Returns the parsed `Packet's` corresponding OpenPGP tag. -/// -/// Returns the packets tag, but only if it was successfully -/// parsed into the corresponding packet type. If e.g. a -/// Signature Packet uses some unsupported methods, it is parsed -/// into an `Packet::Unknown`. `tag()` returns `SQ_TAG_SIGNATURE`, -/// whereas `kind()` returns `0`. -/*/ -sq_tag_t sq_packet_kind (sq_packet_t p); - -/* openpgp::PacketPile. */ - -/*/ -/// A `PacketPile` holds a deserialized OpenPGP message. -/*/ -typedef struct sq_packet_pile *sq_packet_pile_t; - -/*/ -/// Deserializes the OpenPGP message stored in a `std::io::Read` -/// object. -/// -/// Although this method is easier to use to parse an OpenPGP -/// packet pile than a `PacketParser` or a `PacketPileParser`, this -/// interface buffers the whole packet pile in memory. Thus, the -/// caller must be certain that the *deserialized* packet pile is not -/// too large. -/// -/// Note: this interface *does* buffer the contents of packets. -/*/ -sq_packet_pile_t sq_packet_pile_from_reader (sq_error_t *errp, - sq_reader_t reader); - -/*/ -/// Deserializes the OpenPGP packet pile stored in the file named by -/// `filename`. -/// -/// See `sq_packet_pile_from_reader` for more details and caveats. -/*/ -sq_packet_pile_t sq_packet_pile_from_file (sq_error_t *errp, - const char *filename); - -/*/ -/// Deserializes the OpenPGP packet pile stored in the provided buffer. -/// -/// See `sq_packet_pile_from_reader` for more details and caveats. -/*/ -sq_packet_pile_t sq_packet_pile_from_bytes (sq_error_t *errp, - const uint8_t *b, size_t len); - -/*/ -/// Frees the packet pile. -/*/ -void sq_packet_pile_free (sq_packet_pile_t message); - -/*/ -/// Clones the packet pile. -/*/ -sq_packet_pile_t sq_packet_pile_clone (sq_packet_pile_t message); - -/*/ -/// Serializes the packet pile. -/*/ -sq_status_t sq_packet_pile_serialize (sq_error_t *errp, - const sq_packet_pile_t message, - sq_writer_t writer); - -/*/ -/// Frees the signature. -/*/ -void sq_signature_free (sq_signature_t signature); - -/*/ -/// Converts the signature to a packet. -/*/ -sq_packet_t sq_signature_to_packet (sq_signature_t signature); - -/*/ -/// Returns the value of the `Signature` packet's Issuer subpacket. -/// -/// If there is no Issuer subpacket, this returns NULL. Note: if -/// there is no Issuer subpacket, but there is an IssuerFingerprint -/// subpacket, this still returns NULL. -/*/ -sq_keyid_t sq_signature_issuer(sq_signature_t sig); - -/*/ -/// Returns the value of the `Signature` packet's IssuerFingerprint subpacket. -/// -/// If there is no IssuerFingerprint subpacket, this returns NULL. -/// Note: if there is no IssuerFingerprint subpacket, but there is an -/// Issuer subpacket, this still returns NULL. -/*/ -sq_fingerprint_t sq_signature_issuer_fingerprint(sq_signature_t sig); - -/*/ -/// Returns whether the KeyFlags indicates that the key can be used to -/// make certifications. -/*/ -int sq_signature_can_certify(sq_signature_t signature); - -/*/ -/// Returns whether the KeyFlags indicates that the key can be used to -/// make signatures. -/*/ -int sq_signature_can_sign(sq_signature_t signature); - -/*/ -/// Returns whether the KeyFlags indicates that the key can be used to -/// encrypt data for transport. -/*/ -int sq_signature_can_encrypt_for_transport(sq_signature_t signature); - -/*/ -/// Returns whether the KeyFlags indicates that the key can be used to -/// encrypt data at rest. -/*/ -int sq_signature_can_encrypt_at_rest(sq_signature_t signature); - -/*/ -/// Returns whether the KeyFlags indicates that the key can be used -/// for authentication. -/*/ -int sq_signature_can_authenticate(sq_signature_t signature); - -/*/ -/// Returns whether the KeyFlags indicates that the key is a split -/// key. -/*/ -int sq_signature_is_split_key(sq_signature_t signature); - -/*/ -/// Returns whether the KeyFlags indicates that the key is a group -/// key. -/*/ -int sq_signature_is_group_key(sq_signature_t signature); - -/*/ -/// Returns whether the signature is alive. -/// -/// A signature is alive if the creation date is in the past, and the -/// signature has not expired. -/*/ -int sq_signature_alive(sq_signature_t signature); - -/*/ -/// Returns whether the signature is alive at the specified time. -/// -/// A signature is alive if the creation date is in the past, and the -/// signature has not expired at the specified time. -/*/ -int sq_signature_alive_at(sq_signature_t signature, time_t when); - -/*/ -/// Returns whether the signature is expired. -/*/ -int sq_signature_expired(sq_signature_t signature); - -/*/ -/// Returns whether the signature is expired at the specified time. -/*/ -int sq_signature_expired_at(sq_signature_t signature, time_t when); - -/*/ -/// Returns the PKESK's recipient. -/// -/// The return value is a reference ot a `KeyID`. The caller must not -/// modify or free it. -/*/ -sq_keyid_t sq_pkesk_recipient(sq_pkesk_t pkesk); - -/*/ -/// Returns the session key. -/// -/// `key` of size `key_len` must be a buffer large enough to hold the -/// session key. If `key` is NULL, or not large enough, then the key -/// is not written to it. Either way, `key_len` is set to the size of -/// the session key. -/*/ -sq_status_t sq_pkesk_decrypt (sq_error_t *errp, sq_pkesk_t pkesk, - sq_p_key_t secret_key, - uint8_t *algo, /* XXX */ - uint8_t *key, size_t *key_len); - -typedef enum sq_reason_for_revocation { - /*/ - /// No reason specified (key revocations or cert revocations) - /*/ - SQ_REASON_FOR_REVOCATION_UNSPECIFIED, - - /*/ - /// Key is superseded (key revocations) - /*/ - SQ_REASON_FOR_REVOCATION_KEY_SUPERSEDED, - - /*/ - /// Key material has been compromised (key revocations) - /*/ - SQ_REASON_FOR_REVOCATION_KEY_COMPROMISED, - - /*/ - /// Key is retired and no longer used (key revocations) - /*/ - SQ_REASON_FOR_REVOCATION_KEY_RETIRED, - - /*/ - /// User ID information is no longer valid (cert revocations) - /*/ - SQ_REASON_FOR_REVOCATION_UID_RETIRED, - - /* Dummy value to make sure the enumeration has a defined size. Do - not use this value. */ - SQ_REASON_FOR_REVOCATION_FORCE_WIDTH = INT_MAX, -} sq_reason_for_revocation_t; - -/* openpgp::tpk::UserIDBinding. */ - -/*/ -/// A `UserIDBinding`. -/*/ -typedef struct sq_user_id_binding *sq_user_id_binding_t; - -/*/ -/// Returns the user id. -/// -/// This function may fail and return NULL if the user id contains an -/// interior NUL byte. We do this rather than complicate the API, as -/// there is no valid use for such user ids; they must be malicious. -/// -/// The caller must free the returned value. -/*/ -char *sq_user_id_binding_user_id (sq_user_id_binding_t binding); - -/*/ -/// Returns a reference to the self-signature, if any. -/*/ -sq_signature_t sq_user_id_binding_selfsig(sq_user_id_binding_t binding); - -/* openpgp::tpk::UserIDBindingIter. */ - -/*/ -/// An iterator over `UserIDBinding`s. -/*/ -typedef struct sq_user_id_binding_iter *sq_user_id_binding_iter_t; - -/*/ -/// Returns the next element in the iterator. -/*/ -sq_user_id_binding_t sq_user_id_binding_iter_next (sq_user_id_binding_iter_t iter); - -/// Frees an sq_user_id_binding_iter_t. -void sq_user_id_binding_iter_free (sq_user_id_binding_iter_t iter); - -/* openpgp::tpk::KeyIter. */ - -/*/ -/// An iterator over keys in a TPK. -/*/ -typedef struct sq_tpk_key_iter *sq_tpk_key_iter_t; - -/*/ -/// Returns the next key. Returns NULL if there are no more elements. -/// -/// If sigo is not NULL, stores the current self-signature (if any) in -/// *sigo. (Note: subkeys always have signatures, but a primary key -/// may not have a direct signature, and there might not be any user -/// ids.) -/// -/// If rso is not NULL, this stores the key's revocation status in -/// *rso. -/*/ -sq_p_key_t sq_tpk_key_iter_next (sq_tpk_key_iter_t iter, - sq_signature_t *signature, - sq_revocation_status_t *rev); - -/// Frees an sq_tpk_key_iter_t. -void sq_tpk_key_iter_free (sq_tpk_key_iter_t iter); - -/* openpgp::tpk. */ - -/*/ -/// A transferable public key (TPK). -/// -/// A TPK (see [RFC 4880, section 11.1]) can be used to verify -/// signatures and encrypt data. It can be stored in a keystore and -/// uploaded to keyservers. -/// -/// [RFC 4880, section 11.1]: https://tools.ietf.org/html/rfc4880#section-11.1 -/*/ -typedef struct sq_tpk *sq_tpk_t; - - -/*/ -/// A transferable secret key (TSK). -/// -/// A TSK (see [RFC 4880, section 11.2]) can be used to create -/// signatures and decrypt data. -/// -/// [RFC 4880, section 11.2]: https://tools.ietf.org/html/rfc4880#section-11.2 -/*/ -typedef struct sq_tsk *sq_tsk_t; - - -/*/ -/// Returns the first TPK encountered in the reader. -/*/ -sq_tpk_t sq_tpk_from_reader (sq_error_t *errp, - sq_reader_t reader); - -/*/ -/// Returns the first TPK encountered in the file. -/*/ -sq_tpk_t sq_tpk_from_file (sq_error_t *errp, - const char *filename); - -/*/ -/// Returns the first TPK found in `m`. -/// -/// Consumes `m`. -/*/ -sq_tpk_t sq_tpk_from_packet_pile (sq_error_t *errp, - sq_packet_pile_t m); - -/*/ -/// Returns the first TPK found in `buf`. -/// -/// `buf` must be an OpenPGP-encoded TPK. -/*/ -sq_tpk_t sq_tpk_from_bytes (sq_error_t *errp, - const uint8_t *b, size_t len); - -/*/ -/// Returns the first TPK found in the packet parser. -/// -/// Consumes the packet parser result. -/*/ -sq_tpk_t sq_tpk_from_packet_parser (sq_error_t *errp, - sq_packet_parser_result_t ppr); - -/*/ -/// Frees the TPK. -/*/ -void sq_tpk_free (sq_tpk_t tpk); - -/*/ -/// Clones the TPK. -/*/ -sq_tpk_t sq_tpk_clone (sq_tpk_t tpk); - -/*/ -/// Compares TPKs. -/*/ -int sq_tpk_equal (const sq_tpk_t a, const sq_tpk_t b); - -/*/ -/// Serializes the TPK. -/*/ -sq_status_t sq_tpk_serialize (sq_error_t *errp, - const sq_tpk_t tpk, - sq_writer_t writer); - -/*/ -/// Merges `other` into `tpk`. -/// -/// If `other` is a different key, then nothing is merged into -/// `tpk`, but `tpk` is still canonicalized. -/// -/// Consumes `tpk` and `other`. -/*/ -sq_tpk_t sq_tpk_merge (sq_error_t *errp, - sq_tpk_t tpk, - sq_tpk_t other); - -/*/ -/// Adds packets to the TPK. -/// -/// This recanonicalizes the TPK. If the packets are invalid, they -/// are dropped. -/// -/// Consumes `tpk` and the packets in `packets`. The buffer, however, -/// must be freed by the caller. -/*/ -sq_tpk_t sq_tpk_merge_packets (sq_error_t *errp, - sq_tpk_t tpk, - sq_packet_t *packets, - size_t packets_len); -/*/ -/// Dumps the TPK. -/*/ -void sq_tpk_dump (const sq_tpk_t tpk); - -/*/ -/// Returns the fingerprint. -/*/ -sq_fingerprint_t sq_tpk_fingerprint (const sq_tpk_t tpk); - - -/*/ -/// Cast the public key into a secret key that allows using the secret -/// parts of the containing keys. -/*/ -sq_tsk_t sq_tpk_into_tsk (sq_tpk_t tpk); - -/*/ -/// Returns a reference to the TPK's primary key. -/// -/// The tpk still owns the key. The caller should neither modify nor -/// free the key. -/*/ -sq_p_key_t sq_tpk_primary (sq_tpk_t tpk); - -/*/ -/// Returns the TPK's revocation status. -/// -/// Note: this only returns whether the TPK has been revoked, and does -/// not reflect whether an individual user id, user attribute or -/// subkey has been revoked. -/*/ -sq_revocation_status_t sq_tpk_revocation_status (sq_tpk_t tpk); - -/*/ -/// Writes a revocation certificate to the writer. -/// -/// This function consumes the writer. It does *not* consume tpk. -/*/ -sq_signature_t sq_tpk_revoke (sq_error_t *errp, - sq_tpk_t tpk, - sq_signer_t primary_signer, - sq_reason_for_revocation_t code, - const char *reason); - -/*/ -/// Adds a revocation certificate to the tpk. -/// -/// This function consumes the tpk. -/*/ -sq_tpk_t sq_tpk_revoke_in_place (sq_error_t *errp, - sq_tpk_t tpk, - sq_signer_t primary_signer, - sq_reason_for_revocation_t code, - const char *reason); - -/*/ -/// Returns whether the TPK has expired. -/*/ -int sq_tpk_expired(sq_tpk_t tpk); - -/*/ -/// Returns whether the TPK has expired at the specified time. -/*/ -int sq_tpk_expired_at(sq_tpk_t tpk, time_t at); - -/*/ -/// Returns whether the TPK is alive. -/*/ -int sq_tpk_alive(sq_tpk_t tpk); - -/*/ -/// Returns whether the TPK is alive at the specified time. -/*/ -int sq_tpk_alive_at(sq_tpk_t tpk, time_t at); - -/*/ -/// Changes the TPK's expiration. -/// -/// Expiry is when the key should expire in seconds relative to the -/// key's creation (not the current time). -/// -/// This function consumes `tpk` and returns a new `TPK`. -/*/ -sq_tpk_t sq_tpk_set_expiry(sq_error_t *errp, - sq_tpk_t tpk, - uint32_t expiry); - -/*/ -/// Returns whether the TPK includes any secret key material. -/*/ -int sq_tpk_is_tsk(sq_tpk_t tpk); - -/*/ -/// Returns an iterator over the `UserIDBinding`s. -/*/ -sq_user_id_binding_iter_t sq_tpk_user_id_binding_iter (sq_tpk_t tpk); - -/*/ -/// Returns an iterator over all `Key`s (both the primary key and any -/// subkeys) in a TPK. -/*/ -sq_tpk_key_iter_t sq_tpk_key_iter (sq_tpk_t tpk); - -/*/ -/// Returns the TPK's primary user id (if any). -/*/ -char *sq_tpk_primary_user_id(sq_tpk_t tpk); - -/* TPKBuilder */ - -typedef struct sq_tpk_builder *sq_tpk_builder_t; - -typedef enum sq_tpk_cipher_suite { - /*/ - /// EdDSA and ECDH over Curve25519 with SHA512 and AES256. - /*/ - SQ_TPK_CIPHER_SUITE_CV25519, - - /*/ - /// 3072 bit RSA with SHA512 and AES256. - /*/ - SQ_TPK_CIPHER_SUITE_RSA3K, - - /* Dummy value to make sure the enumeration has a defined size. Do - not use this value. */ - SQ_TPK_CIPHER_SUITE_FORCE_WIDTH = INT_MAX, -} sq_tpk_cipher_suite_t; - -/*/ -/// Creates a default `sq_tpk_builder_t`. -/*/ -sq_tpk_builder_t sq_tpk_builder_default(void); - -/*/ -/// Generates a key compliant to [Autocrypt Level 1]. -/// -/// [Autocrypt Level 1]: https://autocrypt.org/level1.html -/*/ -sq_tpk_builder_t sq_tpk_builder_autocrypt(void); - -/*/ -/// Frees an `sq_tpk_builder_t`. -/*/ -void sq_tpk_builder_free(sq_tpk_builder_t tpkb); - -/*/ -/// Sets the encryption and signature algorithms for primary and all -/// subkeys. -/*/ -void sq_tpk_builder_set_cipher_suite(sq_tpk_builder_t *tpkb, - sq_tpk_cipher_suite_t cs); - -/*/ -/// Adds a new user ID. The first user ID added replaces the default -/// ID that is just the empty string. -/*/ -void sq_tpk_builder_add_userid(sq_tpk_builder_t *tpkb, const char *uid); - -/*/ -/// Adds a signing capable subkey. -/*/ -void sq_tpk_builder_add_signing_subkey(sq_tpk_builder_t *tpkb); - -/*/ -/// Adds an encryption capable subkey. -/*/ -void sq_tpk_builder_add_encryption_subkey(sq_tpk_builder_t *tpkb); - -/*/ -/// Adds an certification capable subkey. -/*/ -void sq_tpk_builder_add_certification_subkey(sq_tpk_builder_t *tpkb); - -/*/ -/// Generates the actual TPK. -/// -/// Consumes `tpkb`. -/*/ -sq_tpk_t sq_tpk_builder_generate(sq_error_t *errp, sq_tpk_builder_t tpkb, - sq_tpk_t *tpk, sq_signature_t *revocation); - - -/* TSK */ - -/*/ -/// Generates a new RSA 3072 bit key with UID `primary_uid`. -/*/ -sq_status_t sq_tsk_new (sq_error_t *errp, char *primary_uid, - sq_tsk_t *tpk, sq_signature_t *revocation); - -/*/ -/// Frees the TSK. -/*/ -void sq_tsk_free (sq_tsk_t tsk); - -/*/ -/// Returns a reference to the corresponding TPK. -/*/ -sq_tpk_t sq_tsk_tpk (sq_tsk_t tsk); - -/*/ -/// Converts the TSK into a TPK. -/*/ -sq_tpk_t sq_tsk_into_tpk (sq_tsk_t tsk); - -/*/ -/// Serializes the TSK. -/*/ -sq_status_t sq_tsk_serialize (sq_error_t *errp, - const sq_tsk_t tsk, - sq_writer_t writer); - -/*/ -/// Clones the key. -/*/ -sq_p_key_t sq_p_key_clone (sq_p_key_t key); - -/*/ -/// Computes and returns the key's fingerprint as per Section 12.2 -/// of RFC 4880. -/*/ -sq_fingerprint_t sq_p_key_fingerprint (sq_p_key_t p); - -/*/ -/// Computes and returns the key's key ID as per Section 12.2 of RFC -/// 4880. -/*/ -sq_keyid_t sq_p_key_keyid (sq_p_key_t p); - -/*/ -/// Returns whether the key is expired according to the provided -/// self-signature. -/// -/// Note: this is with respect to the provided signature, which is not -/// checked for validity. That is, we do not check whether the -/// signature is a valid self-signature for the given key. -/*/ -int sq_p_key_expired(sq_p_key_t key, sq_signature_t self_signature); - -/*/ -/// Like sq_p_key_expired, but at a specific time. -/*/ -int sq_p_key_expired_at(sq_p_key_t key, sq_signature_t self_signature, - time_t when); - -/*/ -/// Returns whether the key is alive according to the provided -/// self-signature. -/// -/// A key is alive if the creation date is in the past, and the key -/// has not expired. -/// -/// Note: this is with respect to the provided signature, which is not -/// checked for validity. That is, we do not check whether the -/// signature is a valid self-signature for the given key. -/*/ -int sq_p_key_alive(sq_p_key_t key, sq_signature_t self_signature); - -/*/ -/// Like sq_p_key_alive, but at a specific time. -/*/ -int sq_p_key_alive_at(sq_p_key_t key, sq_signature_t self_signature, - time_t when); - -typedef enum sq_public_key_algorithm { - /*/ - /// RSA (Encrypt or Sign) - /*/ - SQ_PUBLIC_KEY_ALGO_RSA_ENCRYPT_SIGN, - - /*/ - /// RSA Encrypt-Only - /*/ - SQ_PUBLIC_KEY_ALGO_RSA_ENCRYPT, - - /*/ - /// RSA Sign-Only - /*/ - SQ_PUBLIC_KEY_ALGO_RSA_SIGN, - - /*/ - /// Elgamal (Encrypt-Only) - /*/ - SQ_PUBLIC_KEY_ALGO_ELGAMAL_ENCRYPT, - - /*/ - /// DSA (Digital Signature Algorithm) - /*/ - SQ_PUBLIC_KEY_ALGO_DSA, - - /*/ - /// Elliptic curve DH - /*/ - SQ_PUBLIC_KEY_ALGO_ECDH, - - /*/ - /// Elliptic curve DSA - /*/ - SQ_PUBLIC_KEY_ALGO_ECDSA, - - /*/ - /// Elgamal (Encrypt or Sign) - /*/ - SQ_PUBLIC_KEY_ALGO_ELGAMAL_ENCRYPT_SIGN, - - /*/ - /// "Twisted" Edwards curve DSA - /*/ - SQ_PUBLIC_KEY_ALGO_EDDSA, - - /* Dummy value to make sure the enumeration has a defined size. Do - not use this value. */ - SQ_PUBLIC_KEY_ALGO_FORCE_WIDTH = INT_MAX, -} sq_public_key_algo_t; - -/*/ -/// Returns the key's public key algorithm. -/*/ -sq_public_key_algo_t sq_p_key_public_key_algo(sq_p_key_t key); - -/*/ -/// Returns the public key's size in bits. -/*/ -int sq_p_key_public_key_bits(sq_p_key_t key); - -/*/ -/// Creates a new key pair from a Key packet with an unencrypted -/// secret key. -/// -/// # Errors -/// -/// Fails if the secret key is missing, or encrypted. -/*/ -sq_key_pair_t sq_p_key_into_key_pair (sq_error_t *errp, sq_p_key_t key); - -/*/ -/// Returns the value of the User ID Packet. -/// -/// 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 *sq_user_id_value (sq_user_id_t uid, - size_t *value_len); - -/*/ -/// Returns the value of the User Attribute Packet. -/// -/// 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 *sq_user_attribute_value (sq_user_attribute_t ua, - size_t *value_len); - -/*/ -/// Returns the session key. -/// -/// `key` of size `key_len` must be a buffer large enough to hold the -/// session key. If `key` is NULL, or not large enough, then the key -/// is not written to it. Either way, `key_len` is set to the size of -/// the session key. -/*/ -sq_status_t sq_skesk_decrypt (sq_error_t *errp, sq_skesk_t skesk, - const uint8_t *password, size_t password_len, - uint8_t *algo, /* XXX */ - uint8_t *key, size_t *key_len); - -/*/ -/// Returns the key's creation time. -/*/ -uint32_t sq_p_key_creation_time (sq_p_key_t p); - -/* openpgp::parse. */ - -/*/ -/// Starts parsing an OpenPGP message stored in a `sq_reader_t` object. -/*/ -sq_packet_parser_result_t sq_packet_parser_from_reader (sq_error_t *errp, - sq_reader_t reader); - -/*/ -/// Starts parsing an OpenPGP message stored in a file named `path`. -/*/ -sq_packet_parser_result_t sq_packet_parser_from_file (sq_error_t *errp, - const char *filename); - -/*/ -/// Starts parsing an OpenPGP message stored in a buffer. -/*/ -sq_packet_parser_result_t sq_packet_parser_from_bytes (sq_error_t *errp, - const uint8_t *b, - size_t len); - -/// Returns the current packet's tag. -/// -/// This is a convenience function to inspect the containing packet, -/// without turning the `PacketParserResult` into a `PacketParser`. -/// -/// This function does not consume the ppr. -/// -/// Returns 0 if the PacketParserResult does not contain a packet. -sq_tag_t sq_packet_parser_result_tag(sq_packet_parser_result_t ppr); - -/*/ -/// If the `PacketParserResult` contains a `PacketParser`, returns it, -/// otherwise, returns NULL. -/// -/// If the `PacketParser` reached EOF, then the `PacketParserResult` -/// contains a `PacketParserEOF` and you should use -/// `sq_packet_parser_result_eof` to get it. -/// -/// If this function returns a `PacketParser`, then it consumes the -/// `PacketParserResult` and ownership of the `PacketParser` is -/// returned to the caller, i.e., the caller is responsible for -/// ensuring that the `PacketParser` is freed. -/*/ -sq_packet_parser_t sq_packet_parser_result_packet_parser ( - sq_packet_parser_result_t ppr); - -/*/ -/// If the `PacketParserResult` contains a `PacketParserEOF`, returns -/// it, otherwise, returns NULL. -/// -/// If the `PacketParser` did not yet reach EOF, then the -/// `PacketParserResult` contains a `PacketParser` and you should use -/// `sq_packet_parser_result_packet_parser` to get it. -/// -/// If this function returns a `PacketParserEOF`, then it consumes the -/// `PacketParserResult` and ownership of the `PacketParserEOF` is -/// returned to the caller, i.e., the caller is responsible for -/// ensuring that the `PacketParserEOF` is freed. -/*/ -sq_packet_parser_eof_t sq_packet_parser_result_eof ( - sq_packet_parser_result_t ppr); - -/*/ -/// Frees the packet parser result. -/*/ -void sq_packet_parser_result_free (sq_packet_parser_result_t ppr); - -/*/ -/// Frees the packet parser. -/*/ -void sq_packet_parser_free (sq_packet_parser_t pp); - -/*/ -/// Returns whether the message is a well-formed OpenPGP message. -/*/ -int sq_packet_parser_eof_is_message(sq_packet_parser_eof_t eof); - -/*/ -/// Frees the packet parser EOF object. -/*/ -void sq_packet_parser_eof_free (sq_packet_parser_eof_t eof); - -/*/ -/// Returns a reference to the packet that is being parsed. -/*/ -sq_packet_t sq_packet_parser_packet (sq_packet_parser_t pp); - -/*/ -/// Returns the current packet's recursion depth. -/// -/// A top-level packet has a recursion depth of 0. Packets in a -/// top-level container have a recursion depth of 1, etc. -/*/ -uint8_t sq_packet_parser_recursion_depth (sq_packet_parser_t pp); - -/*/ -/// Finishes parsing the current packet and starts parsing the -/// next one. -/// -/// This function finishes parsing the current packet. By -/// default, any unread content is dropped. (See -/// [`PacketParsererBuilder`] for how to configure this.) It then -/// creates a new packet parser for the next packet. If the -/// current packet is a container, this function does *not* -/// recurse into the container, but skips any packets it contains. -/// To recurse into the container, use the [`recurse()`] method. -/// -/// [`PacketParsererBuilder`]: parse/struct.PacketParserBuilder.html -/// [`recurse()`]: #method.recurse -/// -/// The return value is a tuple containing: -/// -/// - A `Packet` holding the fully processed old packet; -/// -/// - A `PacketParser` holding the new packet; -/// -/// To determine the two packet's position within the parse tree, -/// you can use `last_path()` and `path()`, respectively. To -/// determine their depth, you can use `last_recursion_depth()` -/// and `recursion_depth()`, respectively. -/// -/// Note: A recursion depth of 0 means that the packet is a -/// top-level packet, a recursion depth of 1 means that the packet -/// is an immediate child of a top-level-packet, etc. -/// -/// Since the packets are serialized in depth-first order and all -/// interior nodes are visited, we know that if the recursion -/// depth is the same, then the packets are siblings (they have a -/// common parent) and not, e.g., cousins (they have a common -/// grandparent). This is because, if we move up the tree, the -/// only way to move back down is to first visit a new container -/// (e.g., an aunt). -/// -/// Using the two positions, we can compute the change in depth as -/// new_depth - old_depth. Thus, if the change in depth is 0, the -/// two packets are siblings. If the value is 1, the old packet -/// is a container, and the new packet is its first child. And, -/// if the value is -1, the new packet is contained in the old -/// packet's grandparent. The idea is illustrated below: -/// -/// ```text -/// ancestor -/// | \ -/// ... -n -/// | -/// grandparent -/// | \ -/// parent -1 -/// | \ -/// packet 0 -/// | -/// 1 -/// ``` -/// -/// Note: since this function does not automatically recurse into -/// a container, the change in depth will always be non-positive. -/// If the current container is empty, this function DOES pop that -/// container off the container stack, and returns the following -/// packet in the parent container. -/// -/// The items of the tuple are returned in out-parameters. If you do -/// not wish to receive the value, pass `NULL` as the parameter. -/// -/// Consumes the given packet parser. -/*/ -sq_status_t sq_packet_parser_next (sq_error_t *errp, - sq_packet_parser_t pp, - sq_packet_t *old_packet, - sq_packet_parser_result_t *ppr); - -/*/ -/// Finishes parsing the current packet and starts parsing the -/// next one, recursing if possible. -/// -/// This method is similar to the [`next()`] method (see that -/// method for more details), but if the current packet is a -/// container (and we haven't reached the maximum recursion depth, -/// and the user hasn't started reading the packet's contents), we -/// recurse into the container, and return a `PacketParser` for -/// its first child. Otherwise, we return the next packet in the -/// packet stream. If this function recurses, then the new -/// packet's position will be old_position + 1; because we always -/// visit interior nodes, we can't recurse more than one level at -/// a time. -/// -/// [`next()`]: #method.next -/// -/// The items of the tuple are returned in out-parameters. If you do -/// not wish to receive the value, pass `NULL` as the parameter. -/// -/// Consumes the given packet parser. -/*/ -sq_status_t sq_packet_parser_recurse (sq_error_t *errp, - sq_packet_parser_t pp, - sq_packet_t *old_packet, - sq_packet_parser_result_t *ppr); - -/*/ -/// Causes the PacketParser to buffer the packet's contents. -/// -/// The packet's contents are stored in `packet.content`. In -/// general, you should avoid buffering a packet's content and -/// prefer streaming its content unless you are certain that the -/// content is small. -/*/ -uint8_t *sq_packet_parser_buffer_unread_content (sq_error_t *errp, - sq_packet_parser_t pp, - size_t *len); - -/*/ -/// Finishes parsing the current packet. -/// -/// By default, this drops any unread content. Use, for instance, -/// `PacketParserBuild` to customize the default behavior. -/*/ -sq_status_t sq_packet_parser_finish (sq_error_t *errp, - sq_packet_parser_t pp, - sq_packet_t **packet); - -/*/ -/// Tries to decrypt the current packet. -/// -/// On success, this function pushes one or more readers onto the -/// `Pack