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 const BLOCK_SIZE: usize;
146 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}