mod aes256;
mod callback;
mod chacha20_poly1305;
mod context;
mod debug;
mod error;
mod rng;
mod ssl;
pub use aes256::*;
pub use callback::*;
pub use chacha20_poly1305::*;
pub use context::*;
pub use rng::*;
pub use ssl::*;
pub use error::{Error, ErrorKind, Poll, Result};
#[cfg(feature = "debug")]
pub use debug::*;
use wolfssl_sys::{
WOLFSSL_VERIFY_FAIL_EXCEPT_PSK_c_int as WOLFSSL_VERIFY_FAIL_EXCEPT_PSK,
WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT_c_int as WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
WOLFSSL_VERIFY_NONE_c_int as WOLFSSL_VERIFY_NONE,
WOLFSSL_VERIFY_PEER_c_int as WOLFSSL_VERIFY_PEER,
};
use std::{os::raw::c_int, ptr::NonNull};
pub use wolfssl_sys::get_wolfssl_version_string;
const TLS_MAX_RECORD_SIZE: usize = 2usize.pow(14) + 1;
fn wolf_init() -> Result<()> {
static ONCE: std::sync::OnceLock<Result<()>> = std::sync::OnceLock::new();
ONCE.get_or_init(|| {
match unsafe { wolfssl_sys::wolfSSL_Init() } {
wolfssl_sys::WOLFSSL_SUCCESS_c_int => Ok(()),
e => Err(Error::fatal(e)),
}
})
.clone()
}
#[cfg(feature = "debug")]
pub fn enable_debugging(on: bool) {
wolf_init().expect("Unable to initialize wolfSSL");
if on {
match unsafe { wolfssl_sys::wolfSSL_Debugging_ON() } {
0 => {}
wolfssl_sys::wolfCrypt_ErrorCodes_NOT_COMPILED_IN => {
panic!("Inconsistent build, debug not enabled in wolfssl_sys")
}
e => unreachable!("wolfSSL_Debugging_ON: {e:?}"),
}
} else {
unsafe { wolfssl_sys::wolfSSL_Debugging_OFF() }
}
}
#[cfg(feature = "debug")]
pub use wolfssl_sys::wolfSSL_Logging_cb as LoggingCallback;
#[cfg(feature = "debug")]
pub fn set_logging_callback(cb: LoggingCallback) {
wolf_init().expect("Unable to initialize wolfSSL");
match unsafe { wolfssl_sys::wolfSSL_SetLoggingCb(cb) } {
0 => {}
wolfssl_sys::wolfCrypt_ErrorCodes_BAD_FUNC_ARG => {
panic!("Function pointer is not provided")
}
e => unreachable!("wolfSSL_SetLoggingCb: {e:?}"),
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ProtocolVersion {
SslV2,
SslV3,
TlsV1_0,
TlsV1_1,
TlsV1_2,
TlsV1_3,
DtlsV1_0,
DtlsV1_2,
DtlsV1_3,
Unknown,
}
impl ProtocolVersion {
pub fn as_str(&self) -> &'static str {
match self {
ProtocolVersion::SslV2 => "ssl_2",
ProtocolVersion::SslV3 => "ssl_3",
ProtocolVersion::TlsV1_0 => "tls_1_0",
ProtocolVersion::TlsV1_1 => "tls_1_1",
ProtocolVersion::TlsV1_2 => "tls_1_2",
ProtocolVersion::TlsV1_3 => "tls_1_3",
ProtocolVersion::DtlsV1_0 => "dtls_1_0",
ProtocolVersion::DtlsV1_2 => "dtls_1_2",
ProtocolVersion::DtlsV1_3 => "dtls_1_3",
ProtocolVersion::Unknown => "unknown",
}
}
fn is_tls_13(&self) -> bool {
matches!(self, Self::TlsV1_3)
}
fn is_dtls_13(&self) -> bool {
matches!(self, Self::DtlsV1_3)
}
}
#[derive(Debug, Copy, Clone)]
pub enum Method {
DtlsClient,
DtlsClientV1_2,
DtlsClientV1_3,
DtlsServer,
DtlsServerV1_2,
DtlsServerV1_3,
TlsClient,
TlsClientV1_2,
TlsClientV1_3,
TlsServer,
TlsServerV1_2,
TlsServerV1_3,
}
impl Method {
fn into_method_ptr(self) -> Option<NonNull<wolfssl_sys::WOLFSSL_METHOD>> {
let ptr = match self {
Self::DtlsClient => unsafe { wolfssl_sys::wolfDTLS_client_method() },
Self::DtlsClientV1_2 => unsafe { wolfssl_sys::wolfDTLSv1_2_client_method() },
Self::DtlsClientV1_3 => unsafe { wolfssl_sys::wolfDTLSv1_3_client_method() },
Self::DtlsServer => unsafe { wolfssl_sys::wolfDTLS_server_method() },
Self::DtlsServerV1_2 => unsafe { wolfssl_sys::wolfDTLSv1_2_server_method() },
Self::DtlsServerV1_3 => unsafe { wolfssl_sys::wolfDTLSv1_3_server_method() },
Self::TlsClient => unsafe { wolfssl_sys::wolfTLS_client_method() },
Self::TlsClientV1_2 => unsafe { wolfssl_sys::wolfTLSv1_2_client_method() },
Self::TlsClientV1_3 => unsafe { wolfssl_sys::wolfTLSv1_3_client_method() },
Self::TlsServer => unsafe { wolfssl_sys::wolfTLS_server_method() },
Self::TlsServerV1_2 => unsafe { wolfssl_sys::wolfTLSv1_2_server_method() },
Self::TlsServerV1_3 => unsafe { wolfssl_sys::wolfTLSv1_3_server_method() },
};
NonNull::new(ptr)
}
}
#[derive(Debug, Copy, Clone)]
pub enum CurveGroup {
EccSecp256R1,
EccX25519,
#[cfg(feature = "postquantum")]
P256KyberLevel1,
#[cfg(feature = "postquantum")]
P384KyberLevel3,
#[cfg(feature = "postquantum")]
P521KyberLevel5,
#[cfg(feature = "postquantum")]
P256MLKEM512,
#[cfg(feature = "postquantum")]
P384MLKEM768,
#[cfg(feature = "postquantum")]
P521MLKEM1024,
#[cfg(feature = "postquantum")]
X25519MLKEM768,
}
#[cfg(unix)]
type CurveGroupType = std::os::raw::c_uint;
#[cfg(windows)]
type CurveGroupType = std::os::raw::c_int;
impl CurveGroup {
fn as_ffi(&self) -> CurveGroupType {
use CurveGroup::*;
match self {
EccSecp256R1 => wolfssl_sys::WOLFSSL_ECC_SECP256R1,
EccX25519 => wolfssl_sys::WOLFSSL_ECC_X25519,
#[cfg(feature = "postquantum")]
P256KyberLevel1 => wolfssl_sys::WOLFSSL_P256_KYBER_LEVEL1,
#[cfg(feature = "postquantum")]
P384KyberLevel3 => wolfssl_sys::WOLFSSL_P384_KYBER_LEVEL3,
#[cfg(feature = "postquantum")]
P521KyberLevel5 => wolfssl_sys::WOLFSSL_P521_KYBER_LEVEL5,
#[cfg(feature = "postquantum")]
P256MLKEM512 => wolfssl_sys::WOLFSSL_SECP256R1MLKEM512,
#[cfg(feature = "postquantum")]
P384MLKEM768 => wolfssl_sys::WOLFSSL_SECP384R1MLKEM768,
#[cfg(feature = "postquantum")]
P521MLKEM1024 => wolfssl_sys::WOLFSSL_SECP521R1MLKEM1024,
#[cfg(feature = "postquantum")]
X25519MLKEM768 => wolfssl_sys::WOLFSSL_X25519MLKEM768,
}
}
}
#[derive(Debug, Copy, Clone)]
pub enum RootCertificate<'a> {
PemBuffer(&'a [u8]),
Asn1Buffer(&'a [u8]),
PemFileOrDirectory(&'a std::path::Path),
}
#[derive(Debug, Copy, Clone)]
pub enum Secret<'a> {
Asn1Buffer(&'a [u8]),
Asn1File(&'a std::path::Path),
PemBuffer(&'a [u8]),
PemFile(&'a std::path::Path),
}
#[derive(Debug, Default, Copy, Clone)]
pub enum SslVerifyMode {
SslVerifyNone,
#[default]
SslVerifyPeer,
SslVerifyFailIfNoPeerCert,
SslVerifyFailExceptPsk,
}
impl From<SslVerifyMode> for c_int {
fn from(value: SslVerifyMode) -> Self {
match value {
SslVerifyMode::SslVerifyNone => WOLFSSL_VERIFY_NONE,
SslVerifyMode::SslVerifyPeer => WOLFSSL_VERIFY_PEER,
SslVerifyMode::SslVerifyFailIfNoPeerCert => WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
SslVerifyMode::SslVerifyFailExceptPsk => WOLFSSL_VERIFY_FAIL_EXCEPT_PSK,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use test_case::test_case;
#[test]
fn wolf_init_test() {
wolf_init().unwrap();
}
#[test_case(ProtocolVersion::SslV2 => "ssl_2")]
#[test_case(ProtocolVersion::SslV3 => "ssl_3")]
#[test_case(ProtocolVersion::TlsV1_0 => "tls_1_0")]
#[test_case(ProtocolVersion::TlsV1_1 => "tls_1_1")]
#[test_case(ProtocolVersion::TlsV1_2 => "tls_1_2")]
#[test_case(ProtocolVersion::TlsV1_3 => "tls_1_3")]
#[test_case(ProtocolVersion::DtlsV1_0 => "dtls_1_0")]
#[test_case(ProtocolVersion::DtlsV1_2 => "dtls_1_2")]
#[test_case(ProtocolVersion::DtlsV1_3 => "dtls_1_3")]
#[test_case(ProtocolVersion::Unknown => "unknown")]
fn protocol_version_as_str(p: ProtocolVersion) -> &'static str {
p.as_str()
}
#[test_case(SslVerifyMode::SslVerifyNone => WOLFSSL_VERIFY_NONE)]
#[test_case(SslVerifyMode::SslVerifyPeer => WOLFSSL_VERIFY_PEER)]
#[test_case(SslVerifyMode::SslVerifyFailIfNoPeerCert => WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT)]
#[test_case(SslVerifyMode::SslVerifyFailExceptPsk => WOLFSSL_VERIFY_FAIL_EXCEPT_PSK)]
fn ssl_verify_mode(s: SslVerifyMode) -> c_int {
s.into()
}
}