summaryrefslogtreecommitdiffstats
path: root/openpgp-ffi/src/packet/mod.rs
blob: d3392c9970bdfbef56c6b1594352dd64188a5533 (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
//! Packet-related types.
//!
//! See [Section 4 of RFC 4880] for more details.
//!
//!   [Section 4 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-4

use libc::c_char;

extern crate sequoia_openpgp as openpgp;

use self::openpgp::{
    packet::Tag,
};


pub mod key;
pub mod pkesk;
pub mod signature;
pub mod skesk;
pub mod user_attribute;
pub mod userid;
pub mod literal;

use crate::Maybe;
use crate::MoveIntoRaw;
use crate::RefRaw;

/// 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
///
/// Wraps [`sequoia-openpgp::Packet`].
///
/// [`sequoia-openpgp::Packet`]: ../../../sequoia_openpgp/enum.Packet.html
#[crate::ffi_wrapper_type(prefix = "pgp_",
                     derive = "Clone, Debug, Hash, PartialEq")]
pub struct Packet(openpgp::Packet);

/// 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
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_packet_tag(p: *const Packet) -> u32 {
    u8::from(p.ref_raw().tag()) as u32
}

/// 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 `PGP_TAG_SIGNATURE`,
/// whereas `kind()` returns `0`.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_packet_kind(p: *const Packet) -> u32 {
    if let Some(kind) = p.ref_raw().kind() {
        u8::from(kind) as u32
    } else {
        0
    }
}

/// Returns a human-readable tag name.
///
/// ```c
/// #include <assert.h>
/// #include <string.h>
/// #include <sequoia/openpgp.h>
///
/// assert (strcmp (pgp_tag_to_string (2), "SIGNATURE") == 0);
/// ```
#[::sequoia_ffi_macros::extern_fn] #[no_mangle]
pub extern "C" fn pgp_tag_to_string(tag: u8) -> *const c_char {
    match Tag::from(tag) {
        Tag::PKESK => "PKESK\x00",
        Tag::Signature => "SIGNATURE\x00",
        Tag::SKESK => "SKESK\x00",
        Tag::OnePassSig => "ONE PASS SIG\x00",
        Tag::SecretKey => "SECRET KEY\x00",
        Tag::PublicKey => "PUBLIC KEY\x00",
        Tag::SecretSubkey => "SECRET SUBKEY\x00",
        Tag::CompressedData => "COMPRESSED DATA\x00",
        Tag::SED => "SED\x00",
        Tag::Marker => "MARKER\x00",
        Tag::Literal => "LITERAL\x00",
        Tag::Trust => "TRUST\x00",
        Tag::UserID => "USER ID\x00",
        Tag::PublicSubkey => "PUBLIC SUBKEY\x00",
        Tag::UserAttribute => "USER ATTRIBUTE\x00",
        Tag::SEIP => "SEIP\x00",
        Tag::MDC => "MDC\x00",
        _ => "OTHER\x00",
    }.as_bytes().as_ptr() as *const c_char
}

/// Given a packet references the contained signature, if any.
///
/// If the Packet is not of the `Packet::Signature` variant, this
/// function returns `NULL`.  Objects returned from this function must
/// be deallocated using `pgp_signature_free` even though they only
/// reference the given packet.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_packet_ref_signature(p: *const Packet) -> Maybe<signature::Signature> {
    if let openpgp::Packet::Signature(ref p) = p.ref_raw() {
        ::std::ptr::NonNull::new(p.move_into_raw())
    } else {
        None
    }
}

/// Given a packet references the contained literal data packet, if
/// any.
///
/// If the Packet is not of the `Packet::Literal` variant, this
/// function returns `NULL`.  Objects returned from this function must
/// be deallocated using `pgp_literal_data_free` even though they only
/// reference the given packet.
#[::sequoia_ffi_macros::extern_fn] #[no_mangle] pub extern "C"
fn pgp_packet_ref_literal(p: *const Packet) -> Maybe<literal::Literal> {
    if let openpgp::Packet::Literal(ref p) = p.ref_raw() {
        ::std::ptr::NonNull::new(p.move_into_raw())
    } else {
        None
    }
}