pamoja-session 0.1.10

Encrypted, authenticated sessions for pamoja: X25519 key agreement (RFC 7748) and HKDF-SHA256 (RFC 5869) derive a session key, then ChaCha20-Poly1305 (RFC 8439) protects each message with counter nonces and an anti-replay window, so two devices that know each other's keys share a confidential, tamper-evident link, no_std and allocation-free. The secured-channel half ahead of the rustls/DTLS driver.
Documentation
//! The error type for secured sessions.

/// What can go wrong opening a sealed message on a session.
///
/// Sealing never fails, so this only describes the receive side. The two cases are
/// kept distinct on purpose: a forged or corrupted message is an attack or a wire
/// fault, while a replayed message is a captured-and-resent valid message, and an
/// operator may want to react to them differently.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum SessionError {
    /// The message did not authenticate: its tag does not match, so it was altered
    /// in flight, was sealed under a different key, or is an outright forgery. The
    /// plaintext is never revealed in this case.
    Inauthentic,
    /// The message's counter has already been seen, or is older than the replay
    /// window still tracks, so it is a replay of a message already accepted (or one
    /// too old to prove is not). It is rejected without revealing the plaintext.
    Replayed,
}

impl core::fmt::Display for SessionError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        match self {
            SessionError::Inauthentic => f.write_str("session message failed authentication"),
            SessionError::Replayed => f.write_str("session message is a replay"),
        }
    }
}