1 //! For storing OpenPGP certificates.
2 //!
3 //! The key store stores OpenPGP Certificates ("Certs") using an
4 //! arbitrary label. Stored keys are automatically updated from
5 //! remote sources. This ensures that updates like new subkeys and
6 //! revocations are discovered in a timely manner.
7 //!
8 //! # Security considerations
9 //!
10 //! Storing public keys potentially leaks communication partners.
11 //! Protecting against adversaries inspecting the local storage is out
12 //! of scope for Sequoia. Please take the necessary precautions.
13 //!
14 //! Sequoia updates keys in compliance with the [network policy] used
15 //! to create the store.
16 //!
17 //! [network policy]: ../../sequoia_core/enum.NetworkPolicy.html
18 //!
19 //! # Example
20 //!
21 //! ```c, ignore
22 //! XXX
23 //! ```
24
25
26 use libc::c_char;
27 use std::ptr;
28
29 extern crate sequoia_openpgp as openpgp;
30
31 use sequoia_store::{
32 self, Mapping, MappingIter, Binding, BundleIter, Key, KeyIter, LogIter, Store,
33 };
34
35 use super::error::Status;
36 use super::core::Context;
37
38 use crate::openpgp::fingerprint::Fingerprint;
39 use crate::openpgp::keyid::KeyID;
40 use crate::openpgp::cert::Cert;
41 use crate::RefRaw;
42 use crate::MoveIntoRaw;
43 use crate::MoveResultIntoRaw;
44 use crate::Maybe;
45 use crate::to_time_t;
46
47 /// Lists all mappings with the given prefix.
48 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_store_list_mappings(ctx: *mut Context, realm_prefix: *const c_char) -> *mut MappingIter49 fn sq_store_list_mappings(ctx: *mut Context,
50 realm_prefix: *const c_char)
51 -> *mut MappingIter {
52 let ctx = ffi_param_ref_mut!(ctx);
53 ffi_make_fry_from_ctx!(ctx);
54 let realm_prefix = ffi_param_cstr!(realm_prefix).to_string_lossy();
55
56 ffi_try_box!(Mapping::list(&ctx.c, &realm_prefix))
57 }
58
59 /// Returns the next mapping.
60 ///
61 /// Returns `NULL` on exhaustion. If `realmp` is not `NULL`, the
62 /// mapping's realm is stored there. If `namep` is not `NULL`, the
63 /// mapping's name is stored there. If `policyp` is not `NULL`, the
64 /// mapping's network policy is stored there.
65 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_iter_next(iter: *mut MappingIter, realmp: Option<&mut *mut c_char>, namep: Option<&mut *mut c_char>, policyp: Option<&mut u8>) -> *mut Mapping66 fn sq_mapping_iter_next(iter: *mut MappingIter,
67 realmp: Option<&mut *mut c_char>,
68 namep: Option<&mut *mut c_char>,
69 policyp: Option<&mut u8>)
70 -> *mut Mapping {
71 let iter = ffi_param_ref_mut!(iter);
72 match iter.next() {
73 Some((realm, name, policy, mapping)) => {
74 if realmp.is_some() {
75 *realmp.unwrap() = ffi_return_maybe_string!(realm);
76 }
77
78 if namep.is_some() {
79 *namep.unwrap() = ffi_return_maybe_string!(name);
80 }
81
82 if policyp.is_some() {
83 *policyp.unwrap() = (&policy).into();
84 }
85
86 box_raw!(mapping)
87 },
88 None => ptr::null_mut(),
89 }
90 }
91
92 /// Frees a sq_mapping_iter_t.
93 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_iter_free(iter: Option<&mut MappingIter>)94 fn sq_mapping_iter_free(iter: Option<&mut MappingIter>) {
95 ffi_free!(iter)
96 }
97
98 /// Lists all keys in the common key pool.
99 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_store_list_keys(ctx: *mut Context) -> *mut KeyIter100 fn sq_store_list_keys(ctx: *mut Context) -> *mut KeyIter {
101 let ctx = ffi_param_ref_mut!(ctx);
102 ffi_make_fry_from_ctx!(ctx);
103
104 ffi_try_box!(Store::list_keys(&ctx.c))
105 }
106
107 /// Lists all log entries.
108 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_store_server_log(ctx: *mut Context) -> *mut LogIter109 fn sq_store_server_log(ctx: *mut Context) -> *mut LogIter {
110 let ctx = ffi_param_ref_mut!(ctx);
111 ffi_make_fry_from_ctx!(ctx);
112
113 ffi_try_box!(Store::server_log(&ctx.c))
114 }
115
116 /// Returns the next key.
117 ///
118 /// Returns `NULL` on exhaustion. If `fpp` is not `NULL`, the key's
119 /// fingerprint is stored there.
120 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_key_iter_next(iter: *mut KeyIter, fpp: Option<&mut Maybe<Fingerprint>>) -> *mut Key121 fn sq_key_iter_next(iter: *mut KeyIter,
122 fpp: Option<&mut Maybe<Fingerprint>>)
123 -> *mut Key {
124 let iter = ffi_param_ref_mut!(iter);
125 match iter.next() {
126 Some((fingerprint, key)) => {
127 if fpp.is_some() {
128 *fpp.unwrap() = Some(fingerprint).move_into_raw();
129 }
130
131 box_raw!(key)
132 },
133 None => {
134 if fpp.is_some() {
135 *fpp.unwrap() = None;
136 }
137 ptr::null_mut()
138 },
139 }
140 }
141
142 /// Frees a sq_key_iter_t.
143 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_key_iter_free(iter: Option<&mut KeyIter>)144 fn sq_key_iter_free(iter: Option<&mut KeyIter>) {
145 ffi_free!(iter)
146 }
147
148
149 /// Returns the next log entry.
150 ///
151 /// Returns `NULL` on exhaustion.
152 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_log_iter_next(iter: *mut LogIter) -> *mut Log153 fn sq_log_iter_next(iter: *mut LogIter) -> *mut Log {
154 let iter = ffi_param_ref_mut!(iter);
155 match iter.next() {
156 Some(e) => {
157 let (status, error) = match e.status {
158 Ok(s) => (ffi_return_string!(&s), ptr::null_mut()),
159 Err((s, e)) => (ffi_return_string!(&s), ffi_return_string!(&e)),
160 };
161
162 box_raw!(Log{
163 timestamp: to_time_t(e.timestamp),
164 mapping: maybe_box_raw!(e.mapping),
165 binding: maybe_box_raw!(e.binding),
166 key: maybe_box_raw!(e.key),
167 slug: ffi_return_string!(&e.slug),
168 status,
169 error,
170 })
171 },
172 None => ptr::null_mut(),
173 }
174 }
175
176 /// Frees a sq_log_iter_t.
177 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_log_iter_free(iter: Option<&mut LogIter>)178 fn sq_log_iter_free(iter: Option<&mut LogIter>) {
179 ffi_free!(iter)
180 }
181
182 /// Opens a mapping.
183 ///
184 /// Opens a mapping with the given name. If the mapping does not
185 /// exist, it is created. Mappings are handles for objects
186 /// maintained by a background service. The background service
187 /// associates state with this name.
188 ///
189 /// The mapping updates Certs in compliance with the network policy
190 /// of the context that created the mapping in the first place.
191 /// Opening the mapping with a different network policy is
192 /// forbidden.
193 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_open(ctx: *mut Context, realm: *const c_char, name: *const c_char) -> *mut Mapping194 fn sq_mapping_open(ctx: *mut Context,
195 realm: *const c_char,
196 name: *const c_char)
197 -> *mut Mapping {
198 let ctx = ffi_param_ref_mut!(ctx);
199 ffi_make_fry_from_ctx!(ctx);
200 let realm = ffi_param_cstr!(realm).to_string_lossy();
201 let name = ffi_param_cstr!(name).to_string_lossy();
202
203 ffi_try_box!(Mapping::open(&ctx.c, &realm, &name))
204 }
205
206 /// Frees a sq_mapping_t.
207 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_free(mapping: Option<&mut Mapping>)208 fn sq_mapping_free(mapping: Option<&mut Mapping>) {
209 ffi_free!(mapping)
210 }
211
212 /// Adds a key identified by fingerprint to the mapping.
213 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_add(ctx: *mut Context, mapping: *const Mapping, label: *const c_char, fingerprint: *const Fingerprint) -> *mut Binding214 fn sq_mapping_add(ctx: *mut Context,
215 mapping: *const Mapping,
216 label: *const c_char,
217 fingerprint: *const Fingerprint)
218 -> *mut Binding {
219 let ctx = ffi_param_ref_mut!(ctx);
220 ffi_make_fry_from_ctx!(ctx);
221 let mapping = ffi_param_ref!(mapping);
222 let label = ffi_param_cstr!(label).to_string_lossy();
223 let fingerprint = fingerprint.ref_raw();
224
225 ffi_try_box!(mapping.add(&label, fingerprint))
226 }
227
228 /// Imports a key into the mapping.
229 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_import(ctx: *mut Context, mapping: *const Mapping, label: *const c_char, cert: *const Cert) -> Maybe<Cert>230 fn sq_mapping_import(ctx: *mut Context,
231 mapping: *const Mapping,
232 label: *const c_char,
233 cert: *const Cert)
234 -> Maybe<Cert> {
235 let ctx = ffi_param_ref_mut!(ctx);
236 ffi_make_fry_from_ctx!(ctx);
237 let mapping = ffi_param_ref!(mapping);
238 let label = ffi_param_cstr!(label).to_string_lossy();
239 let cert = cert.ref_raw();
240
241 mapping.import(&label, cert).move_into_raw(Some(ctx.errp()))
242 }
243
244 /// Returns the binding for the given label.
245 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_lookup(ctx: *mut Context, mapping: *const Mapping, label: *const c_char) -> *mut Binding246 fn sq_mapping_lookup(ctx: *mut Context,
247 mapping: *const Mapping,
248 label: *const c_char)
249 -> *mut Binding {
250 let ctx = ffi_param_ref_mut!(ctx);
251 ffi_make_fry_from_ctx!(ctx);
252 let mapping = ffi_param_ref!(mapping);
253 let label = ffi_param_cstr!(label).to_string_lossy();
254
255 ffi_try_box!(mapping.lookup(&label))
256 }
257
258 /// Looks up a key in the common key pool by KeyID.
259 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_store_lookup_by_keyid(ctx: *mut Context, keyid: *const KeyID) -> *mut Key260 fn sq_store_lookup_by_keyid(ctx: *mut Context, keyid: *const KeyID)
261 -> *mut Key
262 {
263 let ctx = ffi_param_ref_mut!(ctx);
264 ffi_make_fry_from_ctx!(ctx);
265 let keyid = keyid.ref_raw();
266
267 ffi_try_box!(Store::lookup_by_keyid(&ctx.c, keyid))
268 }
269
270 /// Looks up a key in the common key pool by (Sub)KeyID.
271 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_store_lookup_by_subkeyid(ctx: *mut Context, keyid: *const KeyID) -> *mut Key272 fn sq_store_lookup_by_subkeyid(ctx: *mut Context, keyid: *const KeyID)
273 -> *mut Key
274 {
275 let ctx = ffi_param_ref_mut!(ctx);
276 ffi_make_fry_from_ctx!(ctx);
277 let keyid = keyid.ref_raw();
278
279 ffi_try_box!(Store::lookup_by_subkeyid(&ctx.c, keyid))
280 }
281
282 /// Deletes this mapping.
283 ///
284 /// Consumes `mapping`. Returns != 0 on error.
285 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_delete(ctx: *mut Context, mapping: *mut Mapping) -> Status286 fn sq_mapping_delete(ctx: *mut Context, mapping: *mut Mapping)
287 -> Status {
288 let ctx = ffi_param_ref_mut!(ctx);
289 ffi_make_fry_from_ctx!(ctx);
290 let mapping = ffi_param_move!(mapping);
291
292 ffi_try_status!(mapping.delete())
293 }
294
295 /// Lists all bindings.
296 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_iter(ctx: *mut Context, mapping: *const Mapping) -> *mut BundleIter297 fn sq_mapping_iter(ctx: *mut Context, mapping: *const Mapping)
298 -> *mut BundleIter {
299 let ctx = ffi_param_ref_mut!(ctx);
300 ffi_make_fry_from_ctx!(ctx);
301 let mapping = ffi_param_ref!(mapping);
302
303 ffi_try_box!(mapping.iter())
304 }
305
306 /// Returns the next binding.
307 ///
308 /// Returns `NULL` on exhaustion. If `labelp` is not `NULL`, the
309 /// bindings label is mappingd there. If `fpp` is not `NULL`, the
310 /// bindings fingerprint is mappingd there.
311 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_iter_next(iter: *mut BundleIter, labelp: Option<&mut *mut c_char>, fpp: Option<&mut Maybe<Fingerprint>>) -> *mut Binding312 fn sq_binding_iter_next(iter: *mut BundleIter,
313 labelp: Option<&mut *mut c_char>,
314 fpp: Option<&mut Maybe<Fingerprint>>)
315 -> *mut Binding {
316 let iter = ffi_param_ref_mut!(iter);
317 match iter.next() {
318 Some((label, fp, binding)) => {
319 if labelp.is_some() {
320 *labelp.unwrap() = ffi_return_maybe_string!(label);
321 }
322
323 if fpp.is_some() {
324 *fpp.unwrap() = Some(fp).move_into_raw();
325 }
326
327 box_raw!(binding)
328 },
329 None => {
330 if fpp.is_some() {
331 *fpp.unwrap() = None;
332 }
333 ptr::null_mut()
334 },
335 }
336 }
337
338 /// Frees a sq_binding_iter_t.
339 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_iter_free(iter: Option<&mut BundleIter>)340 fn sq_binding_iter_free(iter: Option<&mut BundleIter>) {
341 ffi_free!(iter)
342 }
343
344 /// Lists all log entries related to this mapping.
345 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_mapping_log(ctx: *mut Context, mapping: *const Mapping) -> *mut LogIter346 fn sq_mapping_log(ctx: *mut Context, mapping: *const Mapping)
347 -> *mut LogIter {
348 let ctx = ffi_param_ref_mut!(ctx);
349 ffi_make_fry_from_ctx!(ctx);
350 let mapping = ffi_param_ref!(mapping);
351
352 ffi_try_box!(mapping.log())
353 }
354
355 /// Frees a sq_binding_t.
356 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_free(binding: Option<&mut Binding>)357 fn sq_binding_free(binding: Option<&mut Binding>) {
358 ffi_free!(binding)
359 }
360
361 /// Frees a sq_key_t.
362 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_key_free(key: Option<&mut Key>)363 fn sq_key_free(key: Option<&mut Key>) {
364 ffi_free!(key)
365 }
366
367 /// Frees a sq_log_t.
368 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_log_free(log: Option<&mut Log>)369 fn sq_log_free(log: Option<&mut Log>) {
370 if let Some(log) = log {
371 let log = unsafe { Box::from_raw(log) };
372 if ! log.mapping.is_null() {
373 ffi_param_move!(log.mapping);
374 }
375 if ! log.binding.is_null() {
376 ffi_param_move!(log.binding);
377 }
378 if ! log.key.is_null() {
379 ffi_param_move!(log.key);
380 }
381 unsafe {
382 libc::free(log.slug as *mut libc::c_void);
383 libc::free(log.status as *mut libc::c_void);
384 libc::free(log.error as *mut libc::c_void);
385 }
386 drop(log)
387 }
388 }
389
390 /// Returns the `sq_stats_t` of this binding.
391 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_stats(ctx: *mut Context, binding: *const Binding) -> *mut Stats392 fn sq_binding_stats(ctx: *mut Context, binding: *const Binding)
393 -> *mut Stats {
394 let ctx = ffi_param_ref_mut!(ctx);
395 ffi_make_fry_from_ctx!(ctx);
396 let binding = ffi_param_ref!(binding);
397
398 box_raw!(Stats::new(ffi_try!(binding.stats())))
399 }
400
401 /// Returns the `sq_key_t` of this binding.
402 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_key(ctx: *mut Context, binding: *const Binding) -> *mut Key403 fn sq_binding_key(ctx: *mut Context, binding: *const Binding)
404 -> *mut Key {
405 let ctx = ffi_param_ref_mut!(ctx);
406 ffi_make_fry_from_ctx!(ctx);
407 let binding = ffi_param_ref!(binding);
408
409 ffi_try_box!(binding.key())
410 }
411
412 /// Returns the `pgp_cert_t` of this binding.
413 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_cert(ctx: *mut Context, binding: *const Binding) -> Maybe<Cert>414 fn sq_binding_cert(ctx: *mut Context, binding: *const Binding)
415 -> Maybe<Cert> {
416 let ctx = ffi_param_ref_mut!(ctx);
417 ffi_make_fry_from_ctx!(ctx);
418 let binding = ffi_param_ref!(binding);
419
420 binding.cert().move_into_raw(Some(ctx.errp()))
421 }
422
423 /// Updates this binding with the given Cert.
424 ///
425 /// If the new key `cert` matches the current key, i.e. they have
426 /// the same fingerprint, both keys are merged and normalized.
427 /// The returned key contains all packets known to Sequoia, and
428 /// should be used instead of `cert`.
429 ///
430 /// If the new key does not match the current key, but carries a
431 /// valid signature from the current key, it replaces the current
432 /// key. This provides a natural way for key rotations.
433 ///
434 /// If the new key does not match the current key, and it does not
435 /// carry a valid signature from the current key, an
436 /// `Error::Conflict` is returned, and you have to resolve the
437 /// conflict, either by ignoring the new key, or by using
438 /// `sq_binding_rotate` to force a rotation.
439 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_import(ctx: *mut Context, binding: *const Binding, cert: *const Cert) -> Maybe<Cert>440 fn sq_binding_import(ctx: *mut Context,
441 binding: *const Binding,
442 cert: *const Cert)
443 -> Maybe<Cert> {
444 let ctx = ffi_param_ref_mut!(ctx);
445 ffi_make_fry_from_ctx!(ctx);
446 let binding = ffi_param_ref!(binding);
447 let cert = cert.ref_raw();
448
449 binding.import(&cert).move_into_raw(Some(ctx.errp()))
450 }
451
452
453 /// Forces a keyrotation to the given Cert.
454 ///
455 /// The current key is replaced with the new key `cert`, even if
456 /// they do not have the same fingerprint. If a key with the same
457 /// fingerprint as `cert` is already in the mapping, is merged with
458 /// `cert` and normalized. The returned key contains all packets
459 /// known to Sequoia, and should be used instead of `cert`.
460 ///
461 /// Use this function to resolve conflicts returned from
462 /// `sq_binding_import`. Make sure that you have authenticated
463 /// `cert` properly. How to do that depends on your thread model.
464 /// You could simply ask Alice to call her communication partner
465 /// Bob and confirm that he rotated his keys.
466 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_rotate(ctx: *mut Context, binding: *const Binding, cert: *const Cert) -> Maybe<Cert>467 fn sq_binding_rotate(ctx: *mut Context,
468 binding: *const Binding,
469 cert: *const Cert)
470 -> Maybe<Cert> {
471 let ctx = ffi_param_ref_mut!(ctx);
472 ffi_make_fry_from_ctx!(ctx);
473 let binding = ffi_param_ref!(binding);
474 let cert = cert.ref_raw();
475
476 binding.rotate(&cert).move_into_raw(Some(ctx.errp()))
477 }
478
479 /// Deletes this binding.
480 ///
481 /// Consumes `binding`. Returns != 0 on error.
482 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_delete(ctx: *mut Context, binding: *mut Binding) -> Status483 fn sq_binding_delete(ctx: *mut Context,
484 binding: *mut Binding)
485 -> Status {
486 let ctx = ffi_param_ref_mut!(ctx);
487 ffi_make_fry_from_ctx!(ctx);
488 let binding = ffi_param_move!(binding);
489
490 ffi_try_status!(binding.delete())
491 }
492
493 /// Lists all log entries related to this binding.
494 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_binding_log(ctx: *mut Context, binding: *const Binding) -> *mut LogIter495 fn sq_binding_log(ctx: *mut Context,
496 binding: *const Binding)
497 -> *mut LogIter {
498 let ctx = ffi_param_ref_mut!(ctx);
499 ffi_make_fry_from_ctx!(ctx);
500 let binding = ffi_param_ref!(binding);
501
502 ffi_try_box!(binding.log())
503 }
504
505 /// Returns the `sq_stats_t` of this key.
506 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_key_stats(ctx: *mut Context, key: *const Key) -> *mut Stats507 fn sq_key_stats(ctx: *mut Context,
508 key: *const Key)
509 -> *mut Stats {
510 let ctx = ffi_param_ref_mut!(ctx);
511 ffi_make_fry_from_ctx!(ctx);
512 let key = ffi_param_ref!(key);
513
514 box_raw!(Stats::new(ffi_try!(key.stats())))
515 }
516
517 /// Returns the `pgp_cert_t`.
518 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_key_cert(ctx: *mut Context, key: *const Key) -> Maybe<Cert>519 fn sq_key_cert(ctx: *mut Context,
520 key: *const Key)
521 -> Maybe<Cert> {
522 let ctx = ffi_param_ref_mut!(ctx);
523 ffi_make_fry_from_ctx!(ctx);
524 let key = ffi_param_ref!(key);
525
526 key.cert().move_into_raw(Some(ctx.errp()))
527 }
528
529 /// Updates this stored key with the given Cert.
530 ///
531 /// If the new key `cert` matches the current key, i.e. they have
532 /// the same fingerprint, both keys are merged and normalized.
533 /// The returned key contains all packets known to Sequoia, and
534 /// should be used instead of `cert`.
535 ///
536 /// If the new key does not match the current key,
537 /// `Error::Conflict` is returned.
538 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_key_import(ctx: *mut Context, key: *const Key, cert: *const Cert) -> Maybe<Cert>539 fn sq_key_import(ctx: *mut Context,
540 key: *const Key,
541 cert: *const Cert)
542 -> Maybe<Cert> {
543 let ctx = ffi_param_ref_mut!(ctx);
544 ffi_make_fry_from_ctx!(ctx);
545 let key = ffi_param_ref!(key);
546 let cert = cert.ref_raw();
547
548 key.import(&cert).move_into_raw(Some(ctx.errp()))
549 }
550
551 /// Lists all log entries related to this key.
552 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_key_log(ctx: *mut Context, key: *const Key) -> *mut LogIter553 fn sq_key_log(ctx: *mut Context,
554 key: *const Key)
555 -> *mut LogIter {
556 let ctx = ffi_param_ref_mut!(ctx);
557 ffi_make_fry_from_ctx!(ctx);
558 let key = ffi_param_ref!(key);
559
560 ffi_try_box!(key.log())
561 }
562
563 /// Frees a sq_stats_t.
564 #[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
sq_stats_free(stats: Option<&mut Stats>)565 fn sq_stats_free(stats: Option<&mut Stats>) {
566 ffi_free!(stats)
567 }
568
569 /// Counter and timestamps.
570 #[repr(C)]
571 pub struct Stamps {
572 /// Counts how many times this has been used.
573 pub count: u64,
574
575 /// Records the time when this has been used first.
576 pub first: libc::time_t,
577
578 /// Records the time when this has been used last.
579 pub last: libc::time_t,
580 }
581
582 impl Stamps {
new(s: &sequoia_store::Stamps) -> Stamps583 fn new(s: &sequoia_store::Stamps) -> Stamps {
584 Stamps{
585 count: s.count as u64,
586 first: to_time_t(s.first),
587 last: to_time_t(s.last),
588 }
589 }
590 }
591
592 /// Statistics about bindings and stored keys.
593 ///
594 /// We collect some data about binginds and stored keys. This
595 /// information can be used to make informed decisions about key
596 /// transitions.
597 #[repr(C)]
598 pub struct Stats {
599 /// Records the time this item was created.
600 pub created: libc::time_t,
601
602 /// Records the time this item was last updated.
603 pub updated: libc::time_t,
604
605 /// Records counters and timestamps of encryptions.
606 pub encryption: Stamps,
607
608 /// Records counters and timestamps of verifications.
609 pub verification: Stamps,
610 }
611
612 impl Stats {
new(s: sequoia_store::Stats) -> Stats613 fn new(s: sequoia_store::Stats) -> Stats {
614 Stats {
615 created: to_time_t(s.created),
616 updated: to_time_t(s.updated),
617 encryption: Stamps::new(&s.encryption),
618 verification: Stamps::new(&s.verification),
619 }
620 }
621 }
622
623 /// Represents a log entry.
624 #[repr(C)]
625 pub struct Log {
626 /// Records the time of the entry.
627 pub timestamp: libc::time_t,
628
629 /// Relates the entry to a mapping.
630 ///
631 /// May be `NULL`.
632 pub mapping: *mut Mapping,
633
634 /// Relates the entry to a binding.
635 ///
636 /// May be `NULL`.
637 pub binding: *mut Binding,
638
639 /// Relates the entry to a key.
640 ///
641 /// May be `NULL`.
642 pub key: *mut Key,
643
644 /// Relates the entry to some object.
645 ///
646 /// This is a human-readable description of what this log entry is
647 /// mainly concerned with.
648 pub slug: *mut c_char,
649
650 /// Holds the log message.
651 pub status: *mut c_char,
652
653 /// Holds the error message, if any.
654 ///
655 /// May be `NULL`.
656 pub error: *mut c_char,
657 }
658