libcrux_traits/kem/
slice.rs

1//! This module contains the trait and related errors for a KEM that takes slices as
2//! arguments and writes the results to mutable slices..
3
4use libcrux_secrets::U8;
5
6use super::arrayref;
7
8/// A Key Encapsulation Mechanismd (KEM). This trait takes slices as arguments.
9pub trait Kem {
10    /// Generate a pair of encapsulation and decapsulation keys.
11    /// It is the responsibility of the caller to ensure  that the `rand` argument is actually
12    /// random.
13    fn keygen(ek: &mut [u8], dk: &mut [U8], rand: &[U8]) -> Result<(), KeyGenError>;
14
15    /// Encapsulate a shared secret towards a given encapsulation key.
16    /// It is the responsibility of the caller to ensure  that the `rand` argument is actually
17    /// random.
18    fn encaps(ct: &mut [u8], ss: &mut [U8], ek: &[u8], rand: &[U8]) -> Result<(), EncapsError>;
19
20    /// Decapsulate a shared secret.
21    fn decaps(ss: &mut [U8], ct: &[u8], dk: &[U8]) -> Result<(), DecapsError>;
22}
23
24/// Error generating key with provided randomness
25#[derive(Debug)]
26pub enum KeyGenError {
27    /// Error generating key with provided randomness
28    InvalidRandomness,
29    /// The provided randomness has the wrong length
30    InvalidRandomnessLength,
31    /// The provided encapsulation key has the wrong length
32    InvalidEncapsKeyLength,
33    /// The provided decapulation key has the wrong length
34    InvalidDecapsKeyLength,
35    /// An unknown error occurred
36    Unknown,
37}
38
39/// Error indicating that encapsulating failed
40#[derive(Debug)]
41pub enum EncapsError {
42    /// Encapsulation key is invalid
43    InvalidEncapsKey,
44    /// Error encapsulating key with provided randomness
45    InvalidRandomness,
46    /// The provided randomness has the wrong length
47    InvalidRandomnessLength,
48    /// The provided encapsulation key has the wrong length
49    InvalidEncapsKeyLength,
50    /// The provided ciphertext has the wrong length
51    InvalidCiphertextLength,
52    /// The provided shared secret has the wrong length
53    InvalidSharedSecretLength,
54    /// An unknown error occurred
55    Unknown,
56}
57
58/// Error indicating that decapsulating failed
59#[derive(Debug)]
60pub enum DecapsError {
61    /// Ciphertext key is invalid
62    InvalidCiphertext,
63    /// Decapsulation key is invalid
64    InvalidDecapsKey,
65    /// The provided decapulation key has the wrong length
66    InvalidDecapsKeyLength,
67    /// The provided ciphertext has the wrong length
68    InvalidCiphertextLength,
69    /// The provided shared secret has the wrong length
70    InvalidSharedSecretLength,
71    /// An unknown error occurred
72    Unknown,
73}
74
75impl From<arrayref::KeyGenError> for KeyGenError {
76    fn from(value: arrayref::KeyGenError) -> Self {
77        match value {
78            arrayref::KeyGenError::InvalidRandomness => KeyGenError::InvalidRandomness,
79            arrayref::KeyGenError::Unknown => KeyGenError::Unknown,
80        }
81    }
82}
83
84impl From<arrayref::EncapsError> for EncapsError {
85    fn from(value: arrayref::EncapsError) -> Self {
86        match value {
87            arrayref::EncapsError::InvalidEncapsKey => EncapsError::InvalidEncapsKey,
88            arrayref::EncapsError::InvalidRandomness => EncapsError::InvalidRandomness,
89            arrayref::EncapsError::Unknown => EncapsError::Unknown,
90        }
91    }
92}
93
94impl From<arrayref::DecapsError> for DecapsError {
95    fn from(value: arrayref::DecapsError) -> Self {
96        match value {
97            arrayref::DecapsError::InvalidCiphertext => DecapsError::InvalidCiphertext,
98            arrayref::DecapsError::InvalidDecapsKey => DecapsError::InvalidDecapsKey,
99            arrayref::DecapsError::Unknown => DecapsError::Unknown,
100        }
101    }
102}
103
104#[macro_export]
105/// Implements [`Kem`] for any [`arrayref::Kem`]
106macro_rules! impl_trait {
107    ($type:ty => $ek:expr, $dk:expr, $ct:expr, $ss:expr, $rand_kg:expr, $rand_encaps:expr) => {
108        impl $crate::kem::slice::Kem for $type {
109            fn keygen(ek: &mut [u8], dk: &mut [$crate::libcrux_secrets::U8], rand: &[$crate::libcrux_secrets::U8]) -> Result<(), $crate::kem::slice::KeyGenError> {
110                let ek : &mut [u8; $ek] = ek
111                    .try_into()
112                    .map_err(|_| $crate::kem::slice::KeyGenError::InvalidEncapsKeyLength)?;
113                let dk : &mut [$crate::libcrux_secrets::U8; $dk] = dk
114                    .try_into()
115                    .map_err(|_| $crate::kem::slice::KeyGenError::InvalidDecapsKeyLength)?;
116                let rand : &[$crate::libcrux_secrets::U8; $rand_kg] = rand
117                    .try_into()
118                    .map_err(|_| $crate::kem::slice::KeyGenError::InvalidRandomnessLength)?;
119
120                <$type as $crate::kem::arrayref::Kem<$ek, $dk, $ct, $ss, $rand_kg, $rand_encaps>>::keygen(ek, dk, rand).map_err($crate::kem::slice::KeyGenError::from)
121            }
122
123            fn encaps(ct: &mut [u8], ss: &mut [$crate::libcrux_secrets::U8], ek: &[u8], rand: &[$crate::libcrux_secrets::U8]) -> Result<(), $crate::kem::slice::EncapsError>{
124                let ct : &mut [u8; $ct] = ct
125                    .try_into()
126                    .map_err(|_| $crate::kem::slice::EncapsError::InvalidCiphertextLength)?;
127                let ss : &mut [$crate::libcrux_secrets::U8; $ss] = ss
128                    .try_into()
129                    .map_err(|_| $crate::kem::slice::EncapsError::InvalidSharedSecretLength)?;
130                let ek : & [u8; $ek] = ek
131                    .try_into()
132                    .map_err(|_| $crate::kem::slice::EncapsError::InvalidEncapsKeyLength)?;
133                let rand : &[$crate::libcrux_secrets::U8; $rand_encaps] = rand
134                    .try_into()
135                    .map_err(|_| $crate::kem::slice::EncapsError::InvalidRandomnessLength)?;
136
137
138                <$type as $crate::kem::arrayref::Kem<$ek, $dk, $ct, $ss, $rand_kg, $rand_encaps>>::encaps(ct, ss, ek,rand).map_err($crate::kem::slice::EncapsError::from)
139            }
140
141            fn decaps(ss: &mut [$crate::libcrux_secrets::U8], ct: &[u8], dk: &[$crate::libcrux_secrets::U8]) -> Result<(), $crate::kem::slice::DecapsError> {
142                let ss : &mut [$crate::libcrux_secrets::U8; $ss] = ss
143                    .try_into()
144                    .map_err(|_| $crate::kem::slice::DecapsError::InvalidSharedSecretLength)?;
145                let ct : &[u8; $ct] = ct
146                    .try_into()
147                    .map_err(|_| $crate::kem::slice::DecapsError::InvalidCiphertextLength)?;
148                let dk : &[$crate::libcrux_secrets::U8; $dk] = dk
149                    .try_into()
150                    .map_err(|_| $crate::kem::slice::DecapsError::InvalidDecapsKeyLength)?;
151
152                <$type as $crate::kem::arrayref::Kem<$ek, $dk, $ct, $ss, $rand_kg, $rand_encaps>>::decaps(ss, ct, dk).map_err($crate::kem::slice::DecapsError::from)
153            }
154
155        }
156
157        #[cfg(test)]
158        #[test]
159        fn simple_kem_test(){
160            $crate::kem::tests::simple::<$ek, $dk, $ct, $ss, $rand_kg, $rand_encaps, $type>();
161        }
162    };
163
164}
165
166pub use impl_trait;
167
168impl core::fmt::Display for KeyGenError {
169    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
170        let text = match self {
171            KeyGenError::InvalidRandomness => "error generating key with provided randomness",
172            KeyGenError::Unknown => "an unknown error occurred",
173            KeyGenError::InvalidRandomnessLength => "the provided randomness has the wrong length",
174            KeyGenError::InvalidEncapsKeyLength => {
175                "the provided encapsulation key has the wrong length"
176            }
177            KeyGenError::InvalidDecapsKeyLength => {
178                "the provided decapsulation key has the wrong length"
179            }
180        };
181
182        f.write_str(text)
183    }
184}
185
186impl core::fmt::Display for EncapsError {
187    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
188        let text = match self {
189            EncapsError::InvalidEncapsKey => "encapsulation key is invalid",
190            EncapsError::InvalidRandomness => "error generating key with provided randomness",
191            EncapsError::Unknown => "an unknown error occurred",
192            EncapsError::InvalidRandomnessLength => "the provided randomness has the wrong length",
193            EncapsError::InvalidEncapsKeyLength => {
194                "the provided encapsulation key has the wrong length"
195            }
196            EncapsError::InvalidCiphertextLength => "the provided ciphertext has the wrong length",
197            EncapsError::InvalidSharedSecretLength => {
198                "the provided shared secret has the wrong length"
199            }
200        };
201
202        f.write_str(text)
203    }
204}
205
206impl core::fmt::Display for DecapsError {
207    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
208        let text = match self {
209            DecapsError::InvalidDecapsKey => "encapsulation key is invalid",
210            DecapsError::InvalidCiphertext => "ciphertext is invalid",
211            DecapsError::Unknown => "an unknown error occurred",
212            DecapsError::InvalidCiphertextLength => "the provided ciphertext has the wrong length",
213            DecapsError::InvalidSharedSecretLength => {
214                "the provided shared secret has the wrong length"
215            }
216            DecapsError::InvalidDecapsKeyLength => {
217                "the provided decapsulation key has the wrong length"
218            }
219        };
220
221        f.write_str(text)
222    }
223}
224
225#[cfg(feature = "error-in-core")]
226/// Here we implement the Error trait. This has only been added to core relatively recently, so we
227/// are hiding that behind a feature.
228mod error_in_core {
229    impl core::error::Error for super::KeyGenError {}
230    impl core::error::Error for super::EncapsError {}
231    impl core::error::Error for super::DecapsError {}
232}