1 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 // Copyright by contributors to this project.
3 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
4 
5 #[cfg(feature = "mock")]
6 use mockall::automock;
7 
8 use alloc::vec::Vec;
9 use mls_rs_core::{crypto::CipherSuite, error::IntoAnyError};
10 
11 pub const AEAD_ID_EXPORT_ONLY: u16 = 0xFFFF;
12 pub const AES_TAG_LEN: usize = 16;
13 
14 /// A trait that provides the required AEAD functions
15 #[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
16 #[cfg_attr(all(target_arch = "wasm32", mls_build_async), maybe_async::must_be_async(?Send))]
17 #[cfg_attr(
18     all(not(target_arch = "wasm32"), mls_build_async),
19     maybe_async::must_be_async
20 )]
21 #[cfg_attr(feature = "mock", automock(type Error = crate::mock::TestError;))]
22 pub trait AeadType: Send + Sync {
23     type Error: IntoAnyError;
24 
aead_id(&self) -> u1625     fn aead_id(&self) -> u16;
26 
27     #[allow(clippy::needless_lifetimes)]
seal<'a>( &self, key: &[u8], data: &[u8], aad: Option<&'a [u8]>, nonce: &[u8], ) -> Result<Vec<u8>, Self::Error>28     async fn seal<'a>(
29         &self,
30         key: &[u8],
31         data: &[u8],
32         aad: Option<&'a [u8]>,
33         nonce: &[u8],
34     ) -> Result<Vec<u8>, Self::Error>;
35 
36     #[allow(clippy::needless_lifetimes)]
open<'a>( &self, key: &[u8], ciphertext: &[u8], aad: Option<&'a [u8]>, nonce: &[u8], ) -> Result<Vec<u8>, Self::Error>37     async fn open<'a>(
38         &self,
39         key: &[u8],
40         ciphertext: &[u8],
41         aad: Option<&'a [u8]>,
42         nonce: &[u8],
43     ) -> Result<Vec<u8>, Self::Error>;
44 
key_size(&self) -> usize45     fn key_size(&self) -> usize;
nonce_size(&self) -> usize46     fn nonce_size(&self) -> usize;
47 }
48 
49 /// AEAD Id, as specified in RFC 9180, Section 5.1 and Table 5.
50 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
51 #[repr(u16)]
52 #[non_exhaustive]
53 pub enum AeadId {
54     /// AES-128-GCM: 16 byte key, 12 byte nonce, 16 byte tag
55     Aes128Gcm = 0x0001,
56     /// AES-256-GCM: 32 byte key, 12 byte nonce, 16 byte tag
57     Aes256Gcm = 0x0002,
58     /// ChaCha20-Poly1305: 32 byte key, 12 byte nonce, 16 byte tag
59     Chacha20Poly1305 = 0x0003,
60 }
61 
62 impl AeadId {
new(cipher_suite: CipherSuite) -> Option<Self>63     pub fn new(cipher_suite: CipherSuite) -> Option<Self> {
64         match cipher_suite {
65             CipherSuite::P256_AES128 | CipherSuite::CURVE25519_AES128 => Some(AeadId::Aes128Gcm),
66             CipherSuite::CURVE448_AES256 | CipherSuite::P384_AES256 | CipherSuite::P521_AES256 => {
67                 Some(AeadId::Aes256Gcm)
68             }
69             CipherSuite::CURVE25519_CHACHA | CipherSuite::CURVE448_CHACHA => {
70                 Some(AeadId::Chacha20Poly1305)
71             }
72             _ => None,
73         }
74     }
75 
key_size(&self) -> usize76     pub fn key_size(&self) -> usize {
77         match self {
78             AeadId::Aes128Gcm => 16,
79             AeadId::Aes256Gcm => 32,
80             AeadId::Chacha20Poly1305 => 32,
81         }
82     }
83 
nonce_size(&self) -> usize84     pub fn nonce_size(&self) -> usize {
85         12
86     }
87 }
88