1pub mod aead;
6mod ec;
7pub mod ec_signer;
8pub mod ecdh;
9pub mod kdf;
10pub mod mac;
11
12#[cfg(feature = "x509")]
13pub mod x509;
14
15use aead::Aead;
16use mls_rs_crypto_hpke::{
17 context::{ContextR, ContextS},
18 dhkem::DhKem,
19 hpke::{Hpke, HpkeError},
20};
21use mls_rs_crypto_traits::{AeadType, KdfType, KemId, KemType};
22
23use ec::EcError;
24use ec_signer::{EcSigner, EcSignerError};
25use ecdh::Ecdh;
26use kdf::Kdf;
27use mac::{Hash, HashError};
28use openssl::error::ErrorStack;
29use thiserror::Error;
30
31use mls_rs_core::{
32 crypto::{
33 CipherSuite, CipherSuiteProvider, CryptoProvider, HpkeCiphertext, HpkePublicKey,
34 HpkeSecretKey, SignaturePublicKey, SignatureSecretKey,
35 },
36 error::{AnyError, IntoAnyError},
37};
38
39pub use openssl;
40use zeroize::Zeroizing;
41
42#[derive(Debug, Error)]
43pub enum OpensslCryptoError {
44 #[error(transparent)]
45 AeadError(AnyError),
46 #[error(transparent)]
47 HpkeError(#[from] HpkeError),
48 #[error(transparent)]
49 KdfError(AnyError),
50 #[error(transparent)]
51 HashError(#[from] HashError),
52 #[error(transparent)]
53 EcSignerError(#[from] EcSignerError),
54 #[error(transparent)]
55 OpensslError(#[from] ErrorStack),
56 #[error(transparent)]
57 EcError(#[from] EcError),
58}
59
60impl IntoAnyError for OpensslCryptoError {
61 fn into_dyn_error(self) -> Result<Box<dyn std::error::Error + Send + Sync>, Self> {
62 Ok(self.into())
63 }
64}
65
66#[derive(Debug, Clone)]
67#[non_exhaustive]
68pub struct OpensslCryptoProvider {
69 pub enabled_cipher_suites: Vec<CipherSuite>,
70}
71
72impl OpensslCryptoProvider {
73 pub fn new() -> Self {
74 Default::default()
75 }
76
77 pub fn with_enabled_cipher_suites(enabled_cipher_suites: Vec<CipherSuite>) -> Self {
78 Self {
79 enabled_cipher_suites,
80 }
81 }
82
83 pub fn all_supported_cipher_suites() -> Vec<CipherSuite> {
84 CipherSuite::all().collect()
85 }
86}
87
88impl Default for OpensslCryptoProvider {
89 fn default() -> Self {
90 Self {
91 enabled_cipher_suites: Self::all_supported_cipher_suites(),
92 }
93 }
94}
95
96impl CryptoProvider for OpensslCryptoProvider {
97 type CipherSuiteProvider = OpensslCipherSuite<DhKem<Ecdh, Kdf>, Kdf, Aead>;
98
99 fn supported_cipher_suites(&self) -> Vec<CipherSuite> {
100 self.enabled_cipher_suites.clone()
101 }
102
103 fn cipher_suite_provider(
104 &self,
105 cipher_suite: CipherSuite,
106 ) -> Option<Self::CipherSuiteProvider> {
107 if !self.enabled_cipher_suites.contains(&cipher_suite) {
108 return None;
109 }
110
111 let kdf = Kdf::new(cipher_suite)?;
112 let ecdh = Ecdh::new(cipher_suite)?;
113 let kem_id = KemId::new(cipher_suite)?;
114 let kem = DhKem::new(ecdh, kdf.clone(), kem_id as u16, kem_id.n_secret());
115 let aead = Aead::new(cipher_suite)?;
116
117 OpensslCipherSuite::new(cipher_suite, kem, kdf, aead)
118 }
119}
120
121#[derive(Clone)]
122pub struct OpensslCipherSuite<KEM, KDF, AEAD>
123where
124 KEM: KemType + Clone,
125 KDF: KdfType + Clone,
126 AEAD: AeadType + Clone,
127{
128 cipher_suite: CipherSuite,
129 aead: AEAD,
130 kdf: KDF,
131 hash: Hash,
132 hpke: Hpke<KEM, KDF, AEAD>,
133 ec_signer: EcSigner,
134}
135
136impl<KEM, KDF, AEAD> OpensslCipherSuite<KEM, KDF, AEAD>
137where
138 KEM: KemType + Clone,
139 KDF: KdfType + Clone,
140 AEAD: AeadType + Clone,
141{
142 pub fn new(cipher_suite: CipherSuite, kem: KEM, kdf: KDF, aead: AEAD) -> Option<Self> {
143 let hpke = Hpke::new(kem, kdf.clone(), Some(aead.clone()));
144
145 Some(Self {
146 cipher_suite,
147 kdf,
148 aead,
149 hash: Hash::new(cipher_suite).ok()?,
150 hpke,
151 ec_signer: EcSigner::new(cipher_suite)?,
152 })
153 }
154
155 pub fn random_bytes(&self, out: &mut [u8]) -> Result<(), OpensslCryptoError> {
156 Ok(openssl::rand::rand_bytes(out)?)
157 }
158
159 pub fn import_der_public_signing_key(
160 &self,
161 der_data: &[u8],
162 ) -> Result<SignaturePublicKey, OpensslCryptoError> {
163 self.ec_signer
164 .signature_key_import_der_public(der_data)
165 .map_err(Into::into)
166 }
167
168 pub fn import_der_private_signing_key(
169 &self,
170 der_data: &[u8],
171 ) -> Result<SignatureSecretKey, OpensslCryptoError> {
172 self.ec_signer
173 .signature_key_import_der_private(der_data)
174 .map_err(Into::into)
175 }
176}
177
178#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
179#[cfg_attr(all(target_arch = "wasm32", mls_build_async), maybe_async::must_be_async(?Send))]
180#[cfg_attr(
181 all(not(target_arch = "wasm32"), mls_build_async),
182 maybe_async::must_be_async
183)]
184impl<KEM, KDF, AEAD> CipherSuiteProvider for OpensslCipherSuite<KEM, KDF, AEAD>
185where
186 KEM: KemType + Clone + Send + Sync,
187 KDF: KdfType + Clone + Send + Sync,
188 AEAD: AeadType + Clone + Send + Sync,
189{
190 type Error = OpensslCryptoError;
191 type HpkeContextS = ContextS<KDF, AEAD>;
193 type HpkeContextR = ContextR<KDF, AEAD>;
194
195 async fn hash(&self, data: &[u8]) -> Result<Vec<u8>, Self::Error> {
196 Ok(self.hash.hash(data)?)
197 }
198
199 async fn mac(&self, key: &[u8], data: &[u8]) -> Result<Vec<u8>, Self::Error> {
200 Ok(self.hash.mac(key, data)?)
201 }
202
203 async fn aead_seal(
204 &self,
205 key: &[u8],
206 data: &[u8],
207 aad: Option<&[u8]>,
208 nonce: &[u8],
209 ) -> Result<Vec<u8>, Self::Error> {
210 self.aead
211 .seal(key, data, aad, nonce)
212 .await
213 .map_err(|e| OpensslCryptoError::AeadError(e.into_any_error()))
214 }
215
216 async fn aead_open(
217 &self,
218 key: &[u8],
219 cipher_text: &[u8],
220 aad: Option<&[u8]>,
221 nonce: &[u8],
222 ) -> Result<Zeroizing<Vec<u8>>, Self::Error> {
223 self.aead
224 .open(key, cipher_text, aad, nonce)
225 .await
226 .map_err(|e| OpensslCryptoError::AeadError(e.into_any_error()))
227 .map(Zeroizing::new)
228 }
229
230 fn aead_key_size(&self) -> usize {
231 self.aead.key_size()
232 }
233
234 fn aead_nonce_size(&self) -> usize {
235 self.aead.nonce_size()
236 }
237
238 async fn kdf_expand(
239 &self,
240 prk: &[u8],
241 info: &[u8],
242 len: usize,
243 ) -> Result<Zeroizing<Vec<u8>>, Self::Error> {
244 self.kdf
245 .expand(prk, info, len)
246 .await
247 .map_err(|e| OpensslCryptoError::KdfError(e.into_any_error()))
248 .map(Zeroizing::new)
249 }
250
251 async fn kdf_extract(
252 &self,
253 salt: &[u8],
254 ikm: &[u8],
255 ) -> Result<Zeroizing<Vec<u8>>, Self::Error> {
256 self.kdf
257 .extract(salt, ikm)
258 .await
259 .map_err(|e| OpensslCryptoError::KdfError(e.into_any_error()))
260 .map(Zeroizing::new)
261 }
262
263 fn kdf_extract_size(&self) -> usize {
264 self.kdf.extract_size()
265 }
266
267 async fn hpke_seal(
268 &self,
269 remote_key: &HpkePublicKey,
270 info: &[u8],
271 aad: Option<&[u8]>,
272 pt: &[u8],
273 ) -> Result<HpkeCiphertext, Self::Error> {
274 Ok(self.hpke.seal(remote_key, info, None, aad, pt).await?)
275 }
276
277 async fn hpke_open(
278 &self,
279 ciphertext: &HpkeCiphertext,
280 local_secret: &HpkeSecretKey,
281 local_public: &HpkePublicKey,
282 info: &[u8],
283 aad: Option<&[u8]>,
284 ) -> Result<Vec<u8>, Self::Error> {
285 Ok(self
286 .hpke
287 .open(ciphertext, local_secret, local_public, info, None, aad)
288 .await?)
289 }
290
291 async fn hpke_setup_r(
292 &self,
293 enc: &[u8],
294 local_secret: &HpkeSecretKey,
295 local_public: &HpkePublicKey,
296 info: &[u8],
297 ) -> Result<Self::HpkeContextR, Self::Error> {
298 Ok(self
299 .hpke
300 .setup_receiver(enc, local_secret, local_public, info, None)
301 .await?)
302 }
303
304 async fn hpke_setup_s(
305 &self,
306 remote_key: &HpkePublicKey,
307 info: &[u8],
308 ) -> Result<(Vec<u8>, Self::HpkeContextS), Self::Error> {
309 Ok(self.hpke.setup_sender(remote_key, info, None).await?)
310 }
311
312 async fn kem_derive(&self, ikm: &[u8]) -> Result<(HpkeSecretKey, HpkePublicKey), Self::Error> {
313 Ok(self.hpke.derive(ikm).await?)
314 }
315
316 async fn kem_generate(&self) -> Result<(HpkeSecretKey, HpkePublicKey), Self::Error> {
317 Ok(self.hpke.generate().await?)
318 }
319
320 fn kem_public_key_validate(&self, key: &HpkePublicKey) -> Result<(), Self::Error> {
321 Ok(self.hpke.public_key_validate(key)?)
322 }
323
324 fn random_bytes(&self, out: &mut [u8]) -> Result<(), Self::Error> {
325 self.random_bytes(out)
326 }
327
328 fn cipher_suite(&self) -> CipherSuite {
329 self.cipher_suite
330 }
331
332 async fn sign(
333 &self,
334 secret_key: &SignatureSecretKey,
335 data: &[u8],
336 ) -> Result<Vec<u8>, Self::Error> {
337 Ok(self.ec_signer.sign(secret_key, data)?)
338 }
339
340 async fn verify(
341 &self,
342 public_key: &SignaturePublicKey,
343 signature: &[u8],
344 data: &[u8],
345 ) -> Result<(), Self::Error> {
346 Ok(self.ec_signer.verify(public_key, signature, data)?)
347 }
348
349 async fn signature_key_generate(
350 &self,
351 ) -> Result<(SignatureSecretKey, SignaturePublicKey), Self::Error> {
352 Ok(self.ec_signer.signature_key_generate()?)
353 }
354
355 async fn signature_key_derive_public(
356 &self,
357 secret_key: &SignatureSecretKey,
358 ) -> Result<SignaturePublicKey, Self::Error> {
359 Ok(self.ec_signer.signature_key_derive_public(secret_key)?)
360 }
361}
362
363#[cfg(not(mls_build_async))]
364#[test]
365fn mls_core_tests() {
366 let provider = OpensslCryptoProvider::new();
369
370 mls_rs_core::crypto::test_suite::verify_tests(&provider, true);
371
372 for cs in OpensslCryptoProvider::all_supported_cipher_suites() {
373 let mut hpke = provider.cipher_suite_provider(cs).unwrap().hpke;
374
375 mls_rs_core::crypto::test_suite::verify_hpke_context_tests(&hpke, cs);
376 mls_rs_core::crypto::test_suite::verify_hpke_encap_tests(&mut hpke, cs);
377 }
378}