spacedls 0.4.0

no_std CCSDS 355.0-B-2 (SDLS) Space Data Link Security implementation
Documentation
use super::ReplayInfo;
use core::fmt;

#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Errors from software encryption providers.
pub enum GenericEncryptError {
    OutputTooSmall,
}

impl fmt::Display for GenericEncryptError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::OutputTooSmall => write!(f, "output buffer too small"),
        }
    }
}

impl core::error::Error for GenericEncryptError {}

#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Errors from software decryption providers.
pub enum GenericDecryptError {
    InputTooShort,
    InputNotBlockAligned,
    InvalidCiphertext,
}

impl fmt::Display for GenericDecryptError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::InputTooShort => write!(f, "input too short"),
            Self::InputNotBlockAligned => write!(f, "input not block-aligned"),
            Self::InvalidCiphertext => write!(f, "invalid ciphertext"),
        }
    }
}

impl core::error::Error for GenericDecryptError {}

#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
/// Errors from [`SecurityAssociation`](crate::protocol::SecurityAssociation) operations.
///
/// The `E` parameter carries the underlying service provider's error type.
pub enum SaOperationError<E> {
    KeyNotAvailable,
    ReplayDetected(ReplayInfo),
    InvalidSpi { input_spi: u16, expected_spi: u16 },
    InvalidFrameFormat {},
    AbmTooShort { abm_len: usize, required: usize },
    Service(E),
}

impl<E: fmt::Display> fmt::Display for SaOperationError<E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::KeyNotAvailable => write!(f, "key not available"),
            Self::ReplayDetected(info) => write!(f, "replay detected: {info}"),
            Self::InvalidSpi { input_spi, expected_spi } => {
                write!(f, "invalid SPI: got {input_spi:#06x}, expected {expected_spi:#06x}")
            }
            Self::InvalidFrameFormat {} => write!(f, "invalid frame format"),
            Self::AbmTooShort { abm_len, required } => {
                write!(f, "ABM too short: length {abm_len}, need {required}")
            }
            Self::Service(e) => write!(f, "service error: {e}"),
        }
    }
}

impl<E: fmt::Debug + fmt::Display> core::error::Error for SaOperationError<E> {}

impl<E> SaOperationError<E> {
    #[inline]
    pub fn is_valid_spi(input_spi: u16, expected_spi: u16) -> Result<(), SaOperationError<E>> {
        if input_spi == expected_spi {
            Ok(())
        } else {
            Err(SaOperationError::InvalidSpi { input_spi, expected_spi })
        }
    }
}