summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi/src/lib.rs
blob: d36582a3abeb96daf901d83529c705b8d3ad7359 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
//! OpenPGP data types and associated machinery for C.
//!
//! This crate aims to provide a complete implementation of OpenPGP as
//! defined by [RFC 4880] as well as several extensions (e.g., [RFC
//! 6637], which describes ECC cryptography for OpenPGP, and [RFC
//! 4880bis], the draft of the next OpenPGP standard).  This includes
//! support for unbuffered message processing.
//!
//! A few features that the OpenPGP community considers to be
//! deprecated (e.g., version 3 compatibility) have been left out as
//! well as support for functionality that we consider to be not only
//! completely useless, but also dangerous (e.g., support for
//! [unhashed signature subpackets]).  We have also updated some
//! OpenPGP defaults to avoid foot guns (e.g., this crate does not
//! fallback to IDEA, but instead assumes all OpenPGP implementations
//! understand AES).  If some functionality is missing, please file a
//! bug report.
//!
//! A non-goal of this crate is support for any sort of high-level,
//! bolted-on functionality.  For instance, [RFC 4880] does not define
//! trust models, such as the web of trust, direct trust, or TOFU.
//! Neither does this crate.  [RFC 4880] does provide some mechanisms
//! for creating trust models (specifically, UserID certifications),
//! and this crate does expose those mechanisms.
//!
//! We also try hard to avoid dictating how OpenPGP should be used.
//! This doesn't mean that we don't have opinions about how OpenPGP
//! should be used in a number of common scenarios (for instance,
//! message validation).  But, in this crate, we refrain from
//! expressing those opinions; we expose an opinionated, high-level
//! interface in the [sequoia-core] and related crates.  In our
//! opinion, you should generally use those crates instead of this
//! one.
//!
//! [RFC 4880]: https://tools.ietf.org/html/rfc4880
//! [RFC 6637]: https://tools.ietf.org/html/rfc6637
//! [RFC 4880bis]: https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-05
//! [unhashed signature subpackets]: https://tools.ietf.org/html/rfc4880#section-5.2.3.2
//! [sequoia-core]: ../sequoia_core
//!
//!
//! # Dear User,
//!
//! This library is written in Rust.  Its expressive type system helps
//! prevent many classes of bugs, but it is also very demanding.
//! For example, the infamous borrow checker, feared by those who dare
//! to approach Rust, allows us to safely use shared resources.  If
//! you want to use this library, we need you to follow a set of
//! rules, and you don't have the borrow checker to double check.
//!
//! We provide a set of functions that use C types and the C calling
//! convention.  These interfaces allow you to use Sequoia safely from
//! any other language provided that you follow [The Rules].
//!
//! If you don't follow [The Rules], we will terminate the process.
//! That is not meant as a threat, of course.  But, as in C, passing a
//! bad pointer to a function is undefined behavior in Rust.
//! Therefore, passing a bad pointer to a function in this crate is
//! undefined behavior as well.  We try to mitigate this problem by
//! trying to detect undefined behavior resulting from not following
//! [The Rules] by printing assertion failures on stderr, and
//! terminating the process.
//!
//! In return for following [The Rules], you can enjoy the reliability
//! that Rust's type system brings this library.  For example, the
//! robust tracking of ownership ensures that we will not leak memory.
//!
//! The C API is documented here.  We invite you to visit the
//! documentation for the [corresponding Rust crate], the structure
//! closely resembles this crate.
//!
//! [The Rules]: #the-rules
//! [corresponding Rust crate]: ../sequoia_openpgp/index.html
//!
//!
//! # Examples
//!
//! This documentation contains examples in the style of Rust
//! examples.  For short examples, we will omit the main function.
//! For example:
//!
//! ```c
//! #include <sequoia/openpgp.h>
//! #include <error.h>
//!
//! pgp_error_t err;
//! pgp_cert_t cert = pgp_cert_from_file (&err, "../openpgp/tests/data/keys/testy.pgp");
//! if (cert == NULL)
//!   error (1, 0, "pgp_cert_from_file: %s", pgp_error_to_string (err));
//!
//!  /* XXX: Do something interesting.  */
//!
//! pgp_cert_free (cert);
//! ```
//!
//! The examples are compiled and executed as part of the test suite,
//! and they will free all objects that are created.
//!
//!
//! # The Rules
//!
//! These rules must be followed.  Failure to follow these rules
//! results in problems like memory leaks, undefined behavior, or
//! process termination.  This is also a guide on how to read the
//! documentation for this library.
//!
//! ## Undefined Behavior
//!
//! Undefined behavior means that the state of the library is
//! inconsistent, and the resulting behavior is unpredictable.  It
//! often leads to security problems, like information exfiltration,
//! or code execution.
//!
//! Undefined behavior may be the result of a bug in this library, or
//! due to failure to comply to [The Rules].  Furthermore, memory
//! exhaustion may lead to undefined behavior.
//!
//! This library tries to detect cases of undefined behavior, and
//! *abort(3)* the process.  This fail-fast policy helps to protect
//! against exfiltration and code execution attacks, and should
//! clearly highlight either a bug in this library (please get in
//! contact!), or a bug in your code.
//!
//! ## Error Handling
//!
//! Errors happen and must be handled by the caller.  There are
//! functions that cannot fail, functions that may fail, and functions
//! that may fail and communicate a complex error value to the caller.
//!
//! Functions that cannot fail are a nice consequence of the
//! 'fail-fast on undefined behavior'-rule.  An example of such
//! function is [`pgp_fingerprint_to_string`].  This function cannot
//! fail, unless either the given fingerprint reference is invalid,
//! or the allocation for the string failed, which is considered
//! undefined behavior.
//!
//! [`pgp_fingerprint_to_string`]: fingerprint/struct.Fingerprint.html#method.pgp_fingerprint_to_string
//!
//! Failing functions signal failure either in-band (e.g. `NULL`, or
//! -1), using `pgp_status_t`, and may store complex error information
//! in a caller-provided location.  For example, constructors often
//! return `NULL` to signal errors.  An example of a constructor that
//! may fail and return `NULL`, but does not communicate complex error
//! is [`pgp_fingerprint_from_hex`]. [`pgp_packet_parser_from_bytes`],
//! on the other hand, will return `NULL` and store a complex error at
//! the location given using the `errp` parameter.
//!
//! [`pgp_fingerprint_from_hex`]: fingerprint/struct.Fingerprint.html#method.pgp_fingerprint_from_hex
//! [`pgp_packet_parser_from_bytes`]: parse/fn.pgp_packet_parser_from_bytes.html
//!
//! Errors may be inspected using [`pgp_error_status`], and formatted
//! as an error message using [`pgp_error_to_string`].  Errors must be freed
//! using [`pgp_error_free`].
//!
//! [`pgp_error_status`]: error/fn.pgp_error_status.html
//! [`pgp_error_to_string`]: error/fn.pgp_error_to_string.html
//! [`pgp_error_free`]: error/fn.pgp_error_free.html
//!
//! ## Types
//!
//! When we interact across the FFI boundary between C and Rust, we
//! need to talk about the types used to interchange data.  The types
//! follow different rules.
//!
//! ### Objects
//!
//! Sequoia objects are opaque objects.  They are created in
//! constructors, and must be freed when no longer needed.  Failure to
//! free an object results in a memory leak.
//!
//! A typical example of creating an object, using it, and
//! deallocating it is the following in which we [parse a fingerprint]
//! from a hexadecimal number, and then [pretty-print] it for user
//! consumption:
//!
//! [parse a fingerprint]: fingerprint/fn.pgp_fingerprint_from_hex.html
//! [pretty-print]: fingerprint/fn.pgp_fingerprint_to_string.html
//!
//! ```c
//! #include <assert.h>
//! #include <stdlib.h>
//! #include <string.h>
//! #include <sequoia/openpgp.h>
//!
//! pgp_fingerprint_t fp =
//!     pgp_fingerprint_from_hex ("D2F2C5D45BE9FDE6A4EE0AAF31855247603831FD");
//!
//! char *pretty = pgp_fingerprint_to_string (fp);
//! assert (strcmp (pretty,
//!                 "D2F2 C5D4 5BE9 FDE6 A4EE  0AAF 3185 5247 6038 31FD") == 0);
//!
//! free (pretty);
//! pgp_fingerprint_free (fp);
//! ```
//!
//! After use, the fingerprint object must be deallocated.  Although
//! not the case here, an object may reference an existing objects.
//! As such, it is good practice to deallocate the objects in the
//! reverse order to which they were created to avoid having the
//! destructor trigger a use-after-free bug.
//!
//! #### Ownership
//!
//! In Rust, every value has an owner.  A value may reside on the
//! stack, on the heap, or be embedded in a struct or enum.  If you
//! take ownership of an object, e.g., by using some constructor, it
//! is your responsibility to manage its lifetime.  The most common
//! way to transfer ownership back to Rust is to deallocate the
//! object.  Failure to deallocate an object leads to a memory leak.
//!
//! Looking at the Rust functions in this library, when ownership of
//! an object of type `T` is transferred across the FFI boundary, the
//! function signature uses the type `*mut T`.
//!
//! In this crate, we use a series of macros to transfer ownership from
//! Rust to C.  `ffi_try_box` matches on `Result<T>`, handling errors
//! by terminating the current function and returning the error.
//! `maybe_box_raw` matches on `Option<T>`, turning `None` into
//! `NULL`.  Finally, `box_raw` is merely a shortcut for
//! `Box::into_raw(Box::new(..))`.
//!
//! ### References
//!
//! All references transferred across the FFI boundary must be valid,
//! and point to live objects constructed using constructors of this
//! library.  Using references constructed in any other way results in
//! undefined behavior.
//!
//! In some places, references handed to, or returned from this
//! library may be `NULL`.  This is the exception rather than the
//! rule.  If you look at a function's Rust signature, an `Option<&T>`
//! or `Option<&mut T>` is used for arguments or results that may be
//! NULL.  On the other hand, function arguments that are not optional
//! use `*const T`, or `*mut T`.
//!
//! Application code must adhere to Rust's reference rules:
//!
//!  - Either one mutable reference or any number of immutable ones.
//!  - All references are non-`NULL`.
//!  - All references are valid.
//!
//! In this crate we enforce the second rule by asserting that all
//! pointers handed in are non-`NULL`.  An exception is if a parameter
//! of an FFI function uses `Option<&T>` or `Option<&mut T>`.  In that
//! case it may be called with `NULL`.  Notable exceptions are the
//! destructors (`pgp_*_free`).
//!
//! ### Lifetimes
//!
//! If you derive a complex object from another complex object, you
//! must assume that the original object is borrowed (i.e.,
//! referenced) by the resulting object unless explicitly stated
//! otherwise.  For example, objects created using a context must not
//! outlive that context.  Similarly, iterators must not outlive the
//! object they are created from.  It is a good practice to
//! deallocate the objects in the reverse order they were created in.
//!
//! Failing to adhere to lifetime restrictions results in undefined
//! behavior.
//!
//! ### Strings
//!
//! Strings given to this library must be UTF-8 encoded and
//! zero-terminated.  Malformed characters will be substituted.
//!
//! Strings produced by this library will be UTF-8 encoded and
//! zero-terminated.  Malformed characters will be substituted.  They
//! will be allocated using *malloc(3)* und must be *free(3)* d.  A
//! few functions in this library may return a `const char *`, which
//! must not be freed.
//!
//! ### Enumerations
//!
//! Values must be constructed using functionality provided by
//! this library.  Using values constructed in any other way is
//! undefined behavior.
//!
//! In the following example, we will decode an armored blob in
//! memory.  Note how we use `PGP_ARMOR_KIND_ANY` in the [constructor]
//! of the armor reader to indicate that we will consume any kind of
//! data, and later use `PGP_ARMOR_KIND_FILE` to check what we got in
//! the end.
//!
//! [constructor]: armor/fn.pgp_armor_reader_from_bytes.html
//!
//! ```c
//! #include <assert.h>
//! #include <error.h>
//! #include <stdlib.h>
//! #include <stdio.h>
//! #include <string.h>
//! #include <sequoia/openpgp.h>
//!
//! const char *armored =
//!   "-----BEGIN PGP ARMORED FILE-----\n"
//!   "\n"
//!   "SGVsbG8gd29ybGQh\n"
//!   "=s4Gu\n"
//!   "-----END PGP ARMORED FILE-----\n";
//!
//! pgp_reader_t armor =
//!     pgp_armor_reader_from_bytes ((uint8_t *) armored, strlen (armored),
//!                                  PGP_ARMOR_KIND_ANY);
//!
//! pgp_error_t err;
//! char message[12];
//! if (pgp_reader_read (&err, armor, (uint8_t *) message, 12) != 12)
//!     error (1, 0, "Reading failed: %s", pgp_error_to_string (err));
//!
//! assert (pgp_armor_reader_kind (armor) == PGP_ARMOR_KIND_FILE);
//! assert (memcmp (message, "Hello world!", 12) == 0);
//!
//! pgp_reader_free (armor);
//! ```

#![warn(missing_docs)]

use libc;

use sequoia_ffi_macros;
use sequoia_ffi_macros::{
    ffi_wrapper_type,
};

include!("common.rs");