Skip to main content

sealed_channel/
error.rs

1//! Error type for the sealed channel.
2//!
3//! The variants are intentionally *detailed* so that internal logic and tests
4//! can distinguish failure modes precisely. However, the **consumer** of this
5//! crate (not this crate itself) is responsible for collapsing any error into a
6//! single, generic reason before it is exposed on a wire or to a remote peer.
7//! Leaking the precise failure reason (e.g. distinguishing an out-of-order
8//! frame from an authentication failure) to an attacker can create oracles, so
9//! callers should map every [`Error`] to one opaque "channel error" externally.
10
11use core::fmt;
12
13/// Errors produced by the sealed channel.
14///
15/// This crate never panics on attacker-controlled input; every fallible
16/// operation returns one of these variants instead.
17///
18/// Note: this type intentionally does **not** implement `std::error::Error`
19/// because the crate is `#![no_std]`.
20#[non_exhaustive]
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub enum Error {
23    /// The supplied Diffie-Hellman shared secret is all-zero.
24    ///
25    /// X25519 produces an all-zero output for low-order points (RFC 7748),
26    /// which would make the resulting keys predictable; such a secret is
27    /// rejected with a constant-time check.
28    WeakSharedSecret,
29    /// The HKDF key-derivation step failed (e.g. an `expand` length error).
30    KeyDerivation,
31    /// AEAD decryption (authentication) failed: the frame was tampered with,
32    /// the keys do not match, or the nonce/AAD did not correspond.
33    Decrypt,
34    /// A frame arrived with a sequence number other than the next expected
35    /// one (replay or reordering).
36    OutOfOrder,
37    /// The 64-bit sequence counter is exhausted. The channel fails closed
38    /// rather than wrapping or reusing a nonce.
39    SequenceExhausted,
40    /// A frame was too short, or did not begin with the expected magic byte.
41    MalformedFrame,
42}
43
44impl fmt::Display for Error {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        let msg = match self {
47            Error::WeakSharedSecret => "weak (all-zero) Diffie-Hellman shared secret",
48            Error::KeyDerivation => "key derivation failed",
49            Error::Decrypt => "AEAD authentication/decryption failed",
50            Error::OutOfOrder => "frame sequence number out of order",
51            Error::SequenceExhausted => "sequence counter exhausted",
52            Error::MalformedFrame => "malformed frame",
53        };
54        f.write_str(msg)
55    }
56}