Skip to main content

crypto/
crypto.rs

1#[cfg(feature = "alloc")]
2extern crate alloc;
3
4#[cfg(feature = "alloc")]
5use alloc::vec::Vec;
6
7pub mod aes;
8#[cfg(feature = "alloc")]
9pub mod argon2;
10pub mod blake2;
11pub mod chacha;
12pub mod curve25519;
13pub mod hkdf;
14pub mod hmac;
15pub mod mldsa;
16pub mod mlkem;
17pub mod poly1305;
18pub mod sha2;
19pub mod sha3;
20pub mod xwing;
21
22mod bytes;
23
24#[cfg(feature = "alloc")]
25pub mod encoding;
26pub mod p256;
27pub use aes::Aes256Gcm;
28pub use bytes::Bytes;
29
30pub use crate::hkdf::HkdfError;
31
32const MAX_HASH_BLOCK_SIZE: usize = 128;
33
34pub type Hash = Bytes<64>;
35pub type Tag = Bytes<32>;
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum Error {
39    Hkdf(HkdfError),
40    Aead(AeadError),
41    EllipticCurve(EllipticCurveError),
42}
43
44impl core::fmt::Display for Error {
45    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
46        match self {
47            Error::Hkdf(err) => write!(f, "{err}"),
48            Error::Aead(err) => write!(f, "{err}"),
49            Error::EllipticCurve(err) => write!(f, "{err}"),
50        }
51    }
52}
53
54#[cfg(feature = "std")]
55impl std::error::Error for Error {}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
58pub enum AeadError {
59    InvalidKey,
60    InvalidNonce,
61    InvalidCiphertext,
62}
63
64impl core::fmt::Display for AeadError {
65    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
66        match self {
67            AeadError::InvalidKey => write!(f, "key is not valid"),
68            AeadError::InvalidNonce => write!(f, "nonce is not valid"),
69            AeadError::InvalidCiphertext => write!(f, "ciphertext is not valid"),
70        }
71    }
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75pub enum EllipticCurveError {
76    InvalidKey,
77    Unspecified,
78    InvalidSignature,
79}
80
81impl core::fmt::Display for EllipticCurveError {
82    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83        match self {
84            EllipticCurveError::InvalidKey => write!(f, "key is not valid"),
85            EllipticCurveError::Unspecified => write!(f, "unknown error"),
86            EllipticCurveError::InvalidSignature => write!(f, "signature is not valid"),
87        }
88    }
89}
90
91#[cfg(feature = "std")]
92impl std::error::Error for EllipticCurveError {}
93
94pub trait StreamCipher: Sized {
95    fn xor_keystream(&mut self, in_out: &mut [u8]);
96}
97
98pub trait Aead: Sized {
99    const TAG_SIZE: usize;
100    const NONCE_SIZE: usize;
101
102    fn encrypt_in_place(&self, in_out: &mut [u8], nonce: &[u8], aad: &[u8]) -> Tag;
103
104    fn decrypt_in_place(&self, in_out: &mut [u8], nonce: &[u8], aad: &[u8], tag: &[u8]) -> Result<(), AeadError>;
105
106    #[cfg(feature = "alloc")]
107    fn encrypt(&self, plaintext: &[u8], nonce: &[u8], aad: &[u8]) -> Vec<u8> {
108        let mut ciphertext = Vec::with_capacity(plaintext.len() + Self::TAG_SIZE);
109        ciphertext.extend_from_slice(plaintext);
110
111        let tag = self.encrypt_in_place(&mut ciphertext, nonce, aad);
112        ciphertext.extend_from_slice(tag.as_ref());
113
114        return ciphertext;
115    }
116
117    #[cfg(feature = "alloc")]
118    fn decrypt(&self, ciphertext: &[u8], nonce: &[u8], aad: &[u8]) -> Result<Vec<u8>, AeadError> {
119        if ciphertext.len() < Self::TAG_SIZE {
120            return Err(AeadError::InvalidCiphertext);
121        }
122
123        let plaintext_length = ciphertext.len() - Self::TAG_SIZE;
124        let mut plaintext = Vec::with_capacity(plaintext_length);
125        plaintext.extend_from_slice(&ciphertext[..plaintext_length]);
126
127        self.decrypt_in_place(&mut plaintext, &nonce, aad, &ciphertext[plaintext_length..])?;
128
129        return Ok(plaintext);
130    }
131}
132
133#[cfg(feature = "zeroize")]
134pub trait Zeroize: zeroize::Zeroize {}
135#[cfg(feature = "zeroize")]
136impl<T: zeroize::Zeroize> Zeroize for T {}
137
138#[cfg(not(feature = "zeroize"))]
139pub trait Zeroize {}
140#[cfg(not(feature = "zeroize"))]
141impl<T> Zeroize for T {}
142
143pub trait Hasher: Sized + Clone + Zeroize {
144    /// The internal block size of the hash function
145    const BLOCK_SIZE: usize;
146    /// The output size of the hash function
147    const OUTPUT_SIZE: usize;
148
149    fn new() -> Self;
150    fn update(&mut self, data: &[u8]);
151    fn sum(self) -> Hash;
152
153    #[inline]
154    fn hash(data: &[u8]) -> Hash {
155        let mut hasher = Self::new();
156        hasher.update(data);
157        return hasher.sum();
158    }
159}
160
161pub trait Xof: Sized + Send + Sync {
162    fn absorb(&mut self, data: &[u8]);
163    fn squeeze(&mut self, out: &mut [u8]);
164}