use core::fmt;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum LengthRequirement {
Exactly(usize),
AtLeast(usize),
AtMost(usize),
Between { minimum: usize, maximum: usize },
}
impl fmt::Display for LengthRequirement {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Exactly(length) => write!(f, "exactly {length}"),
Self::AtLeast(length) => write!(f, "at least {length}"),
Self::AtMost(length) => write!(f, "at most {length}"),
Self::Between { minimum, maximum } => {
write!(f, "between {minimum} and {maximum}")
}
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum Error {
InvalidKeyLength { actual: usize },
InvalidParameters,
InvalidPlaintextLength {
actual: usize,
required: LengthRequirement,
},
InvalidHeaderLength { actual: usize },
InvalidHeaderParameters,
InvalidHeaderTag,
InvalidCiphertextLength {
actual: usize,
required: LengthRequirement,
},
InvalidSegmentPrefix,
AuthenticationFailed,
Closed,
Truncated,
SegmentLimit,
OutputTooSmall { actual: usize, required: usize },
InvalidBufferState,
ProviderSelectionRequired,
LengthOverflow,
RngFailure,
CryptoFailure,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidKeyLength { actual } => {
write!(f, "FLOE keys must be 32 bytes, got {actual}")
}
Self::InvalidParameters => f.write_str("FLOE parameter sets do not match"),
Self::InvalidPlaintextLength { actual, required } => write!(
f,
"invalid plaintext segment length {actual}; required {required}"
),
Self::InvalidHeaderLength { actual } => write!(
f,
"FLOE headers must be {} bytes, got {actual}",
crate::HEADER_LENGTH
),
Self::InvalidHeaderParameters => {
f.write_str("header parameters do not match the selected FLOE parameters")
}
Self::InvalidHeaderTag => f.write_str("invalid FLOE header tag"),
Self::InvalidCiphertextLength { actual, required } => write!(
f,
"invalid ciphertext segment length {actual}; required {required}"
),
Self::InvalidSegmentPrefix => {
f.write_str("non-final FLOE segment has an invalid prefix")
}
Self::AuthenticationFailed => f.write_str("FLOE segment authentication failed"),
Self::Closed => f.write_str("FLOE online state is already closed"),
Self::Truncated => f.write_str("FLOE input has no authenticated final segment"),
Self::SegmentLimit => f.write_str("FLOE segment limit exceeded"),
Self::OutputTooSmall { actual, required } => {
write!(
f,
"output buffer is {actual} bytes; {required} bytes are required"
)
}
Self::InvalidBufferState => {
f.write_str("segment buffer is not prepared for this operation")
}
Self::ProviderSelectionRequired => {
f.write_str("multiple FLOE providers are compiled (")?;
for (index, provider) in crate::Provider::COMPILED.iter().enumerate() {
if index != 0 {
f.write_str(", ")?;
}
f.write_str(provider.name())?;
}
f.write_str(
") and none was named; construct keys with \
Key::from_bytes_with_provider or Key::generate_with_provider",
)
}
Self::LengthOverflow => f.write_str("FLOE length calculation overflowed"),
Self::RngFailure => f.write_str("random backend generation failed"),
Self::CryptoFailure => f.write_str("cryptographic backend operation failed"),
}
}
}
impl std::error::Error for Error {}