1mod aes256;
5mod callback;
6mod chacha20_poly1305;
7mod context;
8mod debug;
9mod error;
10mod rng;
11mod ssl;
12
13pub use aes256::*;
14pub use callback::*;
15pub use chacha20_poly1305::*;
16pub use context::*;
17pub use rng::*;
18pub use ssl::*;
19
20pub use error::{Error, ErrorKind, Poll, Result};
21
22#[cfg(feature = "debug")]
23pub use debug::*;
24use wolfssl_sys::{
25 WOLFSSL_VERIFY_FAIL_EXCEPT_PSK_c_int as WOLFSSL_VERIFY_FAIL_EXCEPT_PSK,
26 WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT_c_int as WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
27 WOLFSSL_VERIFY_NONE_c_int as WOLFSSL_VERIFY_NONE,
28 WOLFSSL_VERIFY_PEER_c_int as WOLFSSL_VERIFY_PEER,
29};
30
31use std::{os::raw::c_int, ptr::NonNull};
32
33pub use wolfssl_sys::get_wolfssl_version_string;
34
35const TLS_MAX_RECORD_SIZE: usize = 2usize.pow(14) + 1;
46
47fn wolf_init() -> Result<()> {
53 static ONCE: std::sync::OnceLock<Result<()>> = std::sync::OnceLock::new();
54
55 ONCE.get_or_init(|| {
56 match unsafe { wolfssl_sys::wolfSSL_Init() } {
64 wolfssl_sys::WOLFSSL_SUCCESS_c_int => Ok(()),
65 e => Err(Error::fatal(e)),
66 }
67 })
68 .clone()
69}
70
71#[cfg(feature = "debug")]
76pub fn enable_debugging(on: bool) {
77 wolf_init().expect("Unable to initialize wolfSSL");
78
79 if on {
80 match unsafe { wolfssl_sys::wolfSSL_Debugging_ON() } {
86 0 => {}
87 wolfssl_sys::wolfCrypt_ErrorCodes_NOT_COMPILED_IN => {
89 panic!("Inconsistent build, debug not enabled in wolfssl_sys")
90 }
91 e => unreachable!("wolfSSL_Debugging_ON: {e:?}"),
92 }
93 } else {
94 unsafe { wolfssl_sys::wolfSSL_Debugging_OFF() }
99 }
100}
101
102#[cfg(feature = "debug")]
103pub use wolfssl_sys::wolfSSL_Logging_cb as WolfsslLoggingCallback;
104
105#[cfg(feature = "debug")]
109pub fn set_logging_callback(cb: WolfsslLoggingCallback) {
110 wolf_init().expect("Unable to initialize wolfSSL");
111
112 match unsafe { wolfssl_sys::wolfSSL_SetLoggingCb(cb) } {
117 0 => {}
118 wolfssl_sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG => {
119 panic!("Function pointer is not provided")
120 }
121 e => unreachable!("wolfSSL_SetLoggingCb: {e:?}"),
122 }
123}
124
125#[derive(Debug, Copy, Clone, PartialEq)]
127pub enum ProtocolVersion {
128 SslV2,
130 SslV3,
132 TlsV1_0,
134 TlsV1_1,
136 TlsV1_2,
138 TlsV1_3,
140 DtlsV1_0,
142 DtlsV1_2,
144 DtlsV1_3,
146 Unknown,
148}
149
150impl ProtocolVersion {
151 pub fn as_str(&self) -> &'static str {
153 match self {
154 ProtocolVersion::SslV2 => "ssl_2",
155 ProtocolVersion::SslV3 => "ssl_3",
156 ProtocolVersion::TlsV1_0 => "tls_1_0",
157 ProtocolVersion::TlsV1_1 => "tls_1_1",
158 ProtocolVersion::TlsV1_2 => "tls_1_2",
159 ProtocolVersion::TlsV1_3 => "tls_1_3",
160 ProtocolVersion::DtlsV1_0 => "dtls_1_0",
161 ProtocolVersion::DtlsV1_2 => "dtls_1_2",
162 ProtocolVersion::DtlsV1_3 => "dtls_1_3",
163 ProtocolVersion::Unknown => "unknown",
164 }
165 }
166
167 fn is_tls_13(&self) -> bool {
169 matches!(self, Self::TlsV1_3)
170 }
171
172 fn is_dtls_13(&self) -> bool {
174 matches!(self, Self::DtlsV1_3)
175 }
176}
177
178#[derive(Debug, Copy, Clone)]
180pub enum Method {
181 DtlsClient,
183 DtlsClientV1_2,
185 DtlsClientV1_3,
187 DtlsServer,
189 DtlsServerV1_2,
191 DtlsServerV1_3,
193 TlsClient,
195 TlsClientV1_2,
197 TlsClientV1_3,
199 TlsServer,
201 TlsServerV1_2,
203 TlsServerV1_3,
205}
206
207impl Method {
208 fn into_method_ptr(self) -> Option<NonNull<wolfssl_sys::WOLFSSL_METHOD>> {
211 let ptr = match self {
212 Self::DtlsClient => unsafe { wolfssl_sys::wolfDTLS_client_method() },
220 Self::DtlsClientV1_2 => unsafe { wolfssl_sys::wolfDTLSv1_2_client_method() },
222 Self::DtlsClientV1_3 => unsafe { wolfssl_sys::wolfDTLSv1_3_client_method() },
224 Self::DtlsServer => unsafe { wolfssl_sys::wolfDTLS_server_method() },
226 Self::DtlsServerV1_2 => unsafe { wolfssl_sys::wolfDTLSv1_2_server_method() },
228 Self::DtlsServerV1_3 => unsafe { wolfssl_sys::wolfDTLSv1_3_server_method() },
230 Self::TlsClient => unsafe { wolfssl_sys::wolfTLS_client_method() },
232 Self::TlsClientV1_2 => unsafe { wolfssl_sys::wolfTLSv1_2_client_method() },
234 Self::TlsClientV1_3 => unsafe { wolfssl_sys::wolfTLSv1_3_client_method() },
236 Self::TlsServer => unsafe { wolfssl_sys::wolfTLS_server_method() },
238 Self::TlsServerV1_2 => unsafe { wolfssl_sys::wolfTLSv1_2_server_method() },
240 Self::TlsServerV1_3 => unsafe { wolfssl_sys::wolfTLSv1_3_server_method() },
242 };
243
244 NonNull::new(ptr)
245 }
246}
247
248#[derive(Debug, Copy, Clone)]
250pub enum CurveGroup {
251 EccSecp256R1,
253
254 EccX25519,
256
257 #[cfg(feature = "postquantum")]
259 P256KyberLevel1,
260 #[cfg(feature = "postquantum")]
262 P384KyberLevel3,
263 #[cfg(feature = "postquantum")]
265 P521KyberLevel5,
266
267 #[cfg(feature = "postquantum")]
269 P256MLKEM512,
270 #[cfg(feature = "postquantum")]
272 P384MLKEM768,
273 #[cfg(feature = "postquantum")]
275 P521MLKEM1024,
276
277 #[cfg(feature = "postquantum")]
279 X25519MLKEM768,
280}
281
282#[cfg(unix)]
283type CurveGroupType = std::os::raw::c_uint;
284#[cfg(windows)]
285type CurveGroupType = std::os::raw::c_int;
286
287impl CurveGroup {
288 fn as_ffi(&self) -> CurveGroupType {
289 use CurveGroup::*;
290 match self {
291 EccSecp256R1 => wolfssl_sys::WOLFSSL_ECC_SECP256R1,
292 EccX25519 => wolfssl_sys::WOLFSSL_ECC_X25519,
293 #[cfg(feature = "postquantum")]
294 P256KyberLevel1 => wolfssl_sys::WOLFSSL_P256_KYBER_LEVEL1,
295 #[cfg(feature = "postquantum")]
296 P384KyberLevel3 => wolfssl_sys::WOLFSSL_P384_KYBER_LEVEL3,
297 #[cfg(feature = "postquantum")]
298 P521KyberLevel5 => wolfssl_sys::WOLFSSL_P521_KYBER_LEVEL5,
299 #[cfg(feature = "postquantum")]
300 P256MLKEM512 => wolfssl_sys::WOLFSSL_SECP256R1MLKEM512,
301 #[cfg(feature = "postquantum")]
302 P384MLKEM768 => wolfssl_sys::WOLFSSL_SECP384R1MLKEM768,
303 #[cfg(feature = "postquantum")]
304 P521MLKEM1024 => wolfssl_sys::WOLFSSL_SECP521R1MLKEM1024,
305 #[cfg(feature = "postquantum")]
306 X25519MLKEM768 => wolfssl_sys::WOLFSSL_X25519MLKEM768,
307 }
308 }
309}
310
311#[derive(Debug, Copy, Clone)]
313pub enum RootCertificate<'a> {
314 PemBuffer(&'a [u8]),
316 Asn1Buffer(&'a [u8]),
318 PemFileOrDirectory(&'a std::path::Path),
320}
321
322#[derive(Debug, Copy, Clone)]
324pub enum Secret<'a> {
325 Asn1Buffer(&'a [u8]),
327 Asn1File(&'a std::path::Path),
329 PemBuffer(&'a [u8]),
331 PemFile(&'a std::path::Path),
333}
334
335#[derive(Debug, Default, Copy, Clone)]
338pub enum SslVerifyMode {
339 SslVerifyNone,
341 #[default]
343 SslVerifyPeer,
344 SslVerifyFailIfNoPeerCert,
346 SslVerifyFailExceptPsk,
348}
349
350impl From<SslVerifyMode> for c_int {
351 fn from(value: SslVerifyMode) -> Self {
352 match value {
353 SslVerifyMode::SslVerifyNone => WOLFSSL_VERIFY_NONE,
354 SslVerifyMode::SslVerifyPeer => WOLFSSL_VERIFY_PEER,
355 SslVerifyMode::SslVerifyFailIfNoPeerCert => WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
356 SslVerifyMode::SslVerifyFailExceptPsk => WOLFSSL_VERIFY_FAIL_EXCEPT_PSK,
357 }
358 }
359}
360
361#[cfg(test)]
362mod tests {
363 use super::*;
364 use test_case::test_case;
365
366 #[test]
367 fn wolf_init_test() {
368 wolf_init().unwrap();
369 }
370
371 #[test_case(ProtocolVersion::SslV2 => "ssl_2")]
372 #[test_case(ProtocolVersion::SslV3 => "ssl_3")]
373 #[test_case(ProtocolVersion::TlsV1_0 => "tls_1_0")]
374 #[test_case(ProtocolVersion::TlsV1_1 => "tls_1_1")]
375 #[test_case(ProtocolVersion::TlsV1_2 => "tls_1_2")]
376 #[test_case(ProtocolVersion::TlsV1_3 => "tls_1_3")]
377 #[test_case(ProtocolVersion::DtlsV1_0 => "dtls_1_0")]
378 #[test_case(ProtocolVersion::DtlsV1_2 => "dtls_1_2")]
379 #[test_case(ProtocolVersion::DtlsV1_3 => "dtls_1_3")]
380 #[test_case(ProtocolVersion::Unknown => "unknown")]
381 fn protocol_version_as_str(p: ProtocolVersion) -> &'static str {
382 p.as_str()
383 }
384
385 #[test_case(SslVerifyMode::SslVerifyNone => WOLFSSL_VERIFY_NONE)]
386 #[test_case(SslVerifyMode::SslVerifyPeer => WOLFSSL_VERIFY_PEER)]
387 #[test_case(SslVerifyMode::SslVerifyFailIfNoPeerCert => WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT)]
388 #[test_case(SslVerifyMode::SslVerifyFailExceptPsk => WOLFSSL_VERIFY_FAIL_EXCEPT_PSK)]
389 fn ssl_verify_mode(s: SslVerifyMode) -> c_int {
390 s.into()
391 }
392}