#![cfg_attr(not(feature = "std"), no_std)]
#![forbid(unsafe_code)]
#[cfg(all(not(feature = "std"), feature = "alloc"))]
extern crate alloc;
use core::fmt::{Display, Formatter};
mod config;
pub use config::{
compiled_allow_legacy_algorithms, compiled_allow_sha1_signatures,
compiled_strict_constant_time, ConstantTimePolicy, LibraryConfig, SecurityPolicy,
};
#[cfg(all(
feature = "feature-tls",
not(any(
feature = "feature-tls10",
feature = "feature-tls11",
feature = "feature-tls12",
feature = "feature-tls13"
))
))]
compile_error!("feature-tls requires one of feature-tls10/11/12/13");
#[cfg(all(feature = "feature-cert-write", not(feature = "feature-cert")))]
compile_error!("feature-cert-write requires feature-cert");
#[cfg(all(feature = "feature-dtls", not(feature = "feature-tls")))]
compile_error!("feature-dtls requires feature-tls");
#[cfg(all(
feature = "policy-strict-constant-time",
feature = "policy-allow-legacy-algorithms"
))]
compile_error!("policy-strict-constant-time is incompatible with policy-allow-legacy-algorithms");
#[cfg(all(
feature = "policy-strict-constant-time",
feature = "policy-allow-sha1-signatures"
))]
compile_error!("policy-strict-constant-time is incompatible with policy-allow-sha1-signatures");
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Error {
InvalidLength(&'static str),
InvalidEncoding(&'static str),
ParseFailure(&'static str),
UnsupportedFeature(&'static str),
CryptoFailure(&'static str),
StateError(&'static str),
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Self::InvalidLength(msg)
| Self::InvalidEncoding(msg)
| Self::ParseFailure(msg)
| Self::UnsupportedFeature(msg)
| Self::CryptoFailure(msg)
| Self::StateError(msg) => f.write_str(msg),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {}
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Profile {
Default,
MinimalTlsClient,
TlsServerPki,
CryptoOnly,
FipsLike,
UtAllFeatures,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct FeatureSet {
pub tls: bool,
pub tls10: bool,
pub tls11: bool,
pub tls12: bool,
pub tls13: bool,
pub dtls: bool,
pub cert: bool,
pub cert_write: bool,
pub hash: bool,
pub encryption: bool,
pub drbg: bool,
pub pkc: bool,
}
impl Profile {
#[must_use]
pub fn features(self) -> FeatureSet {
match self {
Self::Default => FeatureSet {
tls: true,
tls10: false,
tls11: false,
tls12: true,
tls13: true,
dtls: true,
cert: true,
cert_write: false,
hash: true,
encryption: true,
drbg: true,
pkc: true,
},
Self::MinimalTlsClient => FeatureSet {
tls: true,
tls10: false,
tls11: false,
tls12: true,
tls13: true,
dtls: false,
cert: true,
cert_write: false,
hash: true,
encryption: true,
drbg: true,
pkc: true,
},
Self::TlsServerPki => FeatureSet {
tls: true,
tls10: false,
tls11: false,
tls12: true,
tls13: true,
dtls: true,
cert: true,
cert_write: true,
hash: true,
encryption: true,
drbg: true,
pkc: true,
},
Self::CryptoOnly => FeatureSet {
tls: false,
tls10: false,
tls11: false,
tls12: false,
tls13: false,
dtls: false,
cert: false,
cert_write: false,
hash: true,
encryption: true,
drbg: true,
pkc: true,
},
Self::FipsLike => FeatureSet {
tls: true,
tls10: false,
tls11: false,
tls12: true,
tls13: true,
dtls: false,
cert: true,
cert_write: false,
hash: true,
encryption: true,
drbg: true,
pkc: true,
},
Self::UtAllFeatures => FeatureSet {
tls: true,
tls10: true,
tls11: true,
tls12: true,
tls13: true,
dtls: true,
cert: true,
cert_write: true,
hash: true,
encryption: true,
drbg: true,
pkc: true,
},
}
}
}
pub fn read_u16_be(input: &[u8]) -> Result<u16> {
if input.len() < 2 {
return Err(Error::InvalidLength("not enough bytes for u16"));
}
Ok(u16::from_be_bytes([input[0], input[1]]))
}
pub fn read_u24_be(input: &[u8]) -> Result<u32> {
if input.len() < 3 {
return Err(Error::InvalidLength("not enough bytes for u24"));
}
Ok((u32::from(input[0]) << 16) | (u32::from(input[1]) << 8) | u32::from(input[2]))
}
pub fn secure_zero(data: &mut [u8]) {
data.fill(0);
}