rustls_ffi/
enums.rs

1use rustls::{HandshakeKind, ProtocolVersion, SupportedProtocolVersion};
2
3use crate::panic::ffi_panic_boundary;
4use crate::rslice::rustls_str;
5
6#[derive(Debug, Default)]
7#[repr(C)]
8/// Definitions of known TLS protocol versions.
9pub enum rustls_tls_version {
10    #[default]
11    Unknown = 0x0000,
12    Sslv2 = 0x0200,
13    Sslv3 = 0x0300,
14    Tlsv1_0 = 0x0301,
15    Tlsv1_1 = 0x0302,
16    Tlsv1_2 = 0x0303,
17    Tlsv1_3 = 0x0304,
18}
19
20impl From<&SupportedProtocolVersion> for rustls_tls_version {
21    fn from(version: &SupportedProtocolVersion) -> Self {
22        match version.version {
23            ProtocolVersion::SSLv2 => rustls_tls_version::Sslv2,
24            ProtocolVersion::SSLv3 => rustls_tls_version::Sslv3,
25            ProtocolVersion::TLSv1_0 => rustls_tls_version::Tlsv1_0,
26            ProtocolVersion::TLSv1_1 => rustls_tls_version::Tlsv1_1,
27            ProtocolVersion::TLSv1_2 => rustls_tls_version::Tlsv1_2,
28            ProtocolVersion::TLSv1_3 => rustls_tls_version::Tlsv1_3,
29            _ => rustls_tls_version::Unknown,
30        }
31    }
32}
33
34/// Rustls' list of supported protocol versions. The length of the array is
35/// given by `RUSTLS_ALL_VERSIONS_LEN`.
36#[no_mangle]
37pub static RUSTLS_ALL_VERSIONS: [u16; 2] = [
38    rustls_tls_version::Tlsv1_3 as u16,
39    rustls_tls_version::Tlsv1_2 as u16,
40];
41
42/// The length of the array `RUSTLS_ALL_VERSIONS`.
43#[no_mangle]
44pub static RUSTLS_ALL_VERSIONS_LEN: usize = RUSTLS_ALL_VERSIONS.len();
45
46/// Rustls' default list of protocol versions. The length of the array is
47/// given by `RUSTLS_DEFAULT_VERSIONS_LEN`.
48#[no_mangle]
49pub static RUSTLS_DEFAULT_VERSIONS: [u16; 2] = [
50    rustls_tls_version::Tlsv1_3 as u16,
51    rustls_tls_version::Tlsv1_2 as u16,
52];
53
54/// The length of the array `RUSTLS_DEFAULT_VERSIONS`.
55#[no_mangle]
56pub static RUSTLS_DEFAULT_VERSIONS_LEN: usize = RUSTLS_DEFAULT_VERSIONS.len();
57
58#[derive(Debug, Default)]
59#[repr(C)]
60/// Describes which sort of handshake happened.
61pub enum rustls_handshake_kind {
62    /// The type of handshake could not be determined.
63    ///
64    /// This variant should not be used.
65    #[default]
66    Unknown = 0x0,
67
68    /// A full TLS handshake.
69    ///
70    /// This is the typical TLS connection initiation process when resumption is
71    /// not yet unavailable, and the initial client hello was accepted by the server.
72    Full = 0x1,
73
74    /// A full TLS handshake, with an extra round-trip for a hello retry request.
75    ///
76    /// The server can respond with a hello retry request (HRR) if the initial client
77    /// hello is unacceptable for several reasons, the most likely if no supported key
78    /// shares were offered by the client.
79    FullWithHelloRetryRequest = 0x2,
80
81    /// A resumed TLS handshake.
82    ///
83    /// Resumed handshakes involve fewer round trips and less cryptography than
84    /// full ones, but can only happen when the peers have previously done a full
85    /// handshake together, and then remember data about it.
86    Resumed = 0x3,
87}
88
89/// Convert a `rustls_handshake_kind` to a string with a friendly description of the kind
90/// of handshake.
91///
92/// The returned `rustls_str` has a static lifetime equal to that of the program and does
93/// not need to be manually freed.
94#[no_mangle]
95pub extern "C" fn rustls_handshake_kind_str(kind: rustls_handshake_kind) -> rustls_str<'static> {
96    ffi_panic_boundary! {
97        rustls_str::from_str_unchecked(match kind {
98            rustls_handshake_kind::Unknown => "unknown",
99            rustls_handshake_kind::Full => "full",
100            rustls_handshake_kind::FullWithHelloRetryRequest => "full with hello retry request",
101            rustls_handshake_kind::Resumed => "resumed",
102        })
103    }
104}
105
106impl From<HandshakeKind> for rustls_handshake_kind {
107    fn from(kind: HandshakeKind) -> Self {
108        match kind {
109            HandshakeKind::Full => Self::Full,
110            HandshakeKind::FullWithHelloRetryRequest => Self::FullWithHelloRetryRequest,
111            HandshakeKind::Resumed => Self::Resumed,
112        }
113    }
114}
115
116#[cfg(test)]
117mod tests {
118    use rustls::{ALL_VERSIONS, DEFAULT_VERSIONS};
119
120    use super::*;
121
122    #[test]
123    fn all_versions_arrays() {
124        assert_eq!(RUSTLS_ALL_VERSIONS_LEN, ALL_VERSIONS.len());
125        for (original, ffi) in ALL_VERSIONS.iter().zip(RUSTLS_ALL_VERSIONS.iter()) {
126            assert_eq!(u16::from(original.version), *ffi);
127        }
128    }
129
130    #[test]
131    fn default_versions_arrays() {
132        assert_eq!(RUSTLS_DEFAULT_VERSIONS_LEN, DEFAULT_VERSIONS.len());
133        for (original, ffi) in DEFAULT_VERSIONS.iter().zip(RUSTLS_DEFAULT_VERSIONS.iter()) {
134            assert_eq!(u16::from(original.version), *ffi);
135        }
136    }
137}