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
//! Fingerprints.
//!
//! A fingerprint uniquely identifies a public key.  For more details
//! about how a fingerprint is generated, see [Section 12.2 of RFC
//! 4880].
//!
//!   [Section 12.2 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-12.2
//!
//! Wraps [`sequoia-openpgp::Fingerprint`].
//!
//! [`sequoia-openpgp::Fingerprint`]: sequoia_openpgp::Fingerprint

use std::slice;
use libc::{c_char, size_t};

use sequoia_openpgp as openpgp;
use super::keyid::KeyID;
use crate::Maybe;
use crate::MoveIntoRaw;
use crate::RefRaw;

/// Holds a fingerprint.
///
/// A fingerprint uniquely identifies a public key.  For more details
/// about how a fingerprint is generated, see [Section 12.2 of RFC
/// 4880].
///
///   [Section 12.2 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-12.2
///
/// Wraps [`sequoia-openpgp::Fingerprint`].
///
/// [`sequoia-openpgp::Fingerprint`]: sequoia_openpgp::Fingerprint
#[crate::ffi_wrapper_type(prefix = "pgp_",
                     derive = "Clone, Debug, Display, Hash, PartialEq")]
pub struct Fingerprint(openpgp::Fingerprint);

/// Reads a binary fingerprint.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_fingerprint_from_bytes(buf: *const u8,
                              len: size_t)
                              -> *mut Fingerprint {
    assert!(!buf.is_null());
    let buf = unsafe {
        slice::from_raw_parts(buf, len as usize)
    };
    openpgp::Fingerprint::from_bytes(buf).move_into_raw()
}

/// Reads a hexadecimal fingerprint.
///
/// # Examples
///
/// ```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,
///                 "D2F2C5D45BE9FDE6A4EE0AAF31855247603831FD") == 0);
///
/// free (pretty);
/// pgp_fingerprint_free (fp);
/// ```
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_fingerprint_from_hex(hex: *const c_char)
                            -> Maybe<Fingerprint> {
    let hex = ffi_param_cstr!(hex).to_string_lossy();
    hex.parse::<openpgp::Fingerprint>().ok().move_into_raw()
}

/// Returns a reference to the raw Fingerprint.
///
/// This returns a reference to the internal buffer that is valid as
/// long as the fingerprint is.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_fingerprint_as_bytes(fp: *const Fingerprint,
                            fp_len: Option<&mut size_t>)
                            -> *const u8 {
    let fp = fp.ref_raw();
    if let Some(p) = fp_len {
        *p = fp.as_bytes().len();
    }
    fp.as_bytes().as_ptr()
}

/// Converts the fingerprint to a hexadecimal number.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_fingerprint_to_hex(fp: *const Fingerprint)
                          -> *mut c_char {
    ffi_return_string!(format!("{:X}", fp.ref_raw()))
}

/// Converts the fingerprint to a key ID.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_fingerprint_to_keyid(fp: *const Fingerprint)
                            -> *mut KeyID {
    openpgp::KeyID::from(fp.ref_raw()).move_into_raw()
}