kms_aead/
ring_encryption.rs1use crate::ring_support::*;
2use crate::{AeadEncryption, CipherText, DataEncryptionKey, KmsAeadResult};
3use async_trait::*;
4use ring::rand::SystemRandom;
5use rsb_derive::*;
6use rvstruct::ValueStruct;
7use secret_vault_value::SecretValue;
8
9#[derive(Debug, Clone, Builder)]
10pub struct RingAeadEncryptionOptions {
11 #[default = "RingAeadEncryptionNonceKind::TimeRandom"]
12 pub nonce_kind: RingAeadEncryptionNonceKind,
13}
14
15#[derive(Debug, Clone)]
16pub enum RingAeadEncryptionNonceKind {
17 Random,
18 TimeRandom,
19}
20
21pub struct RingAeadEncryption {
22 pub algo: &'static ring::aead::Algorithm,
23 secure_rand: SystemRandom,
24 pub options: RingAeadEncryptionOptions,
25}
26
27impl RingAeadEncryption {
28 pub fn new() -> KmsAeadResult<Self> {
29 Self::with_rand(SystemRandom::new())
30 }
31
32 pub fn with_rand(secure_rand: SystemRandom) -> KmsAeadResult<Self> {
33 Self::with_algorithm(&ring::aead::CHACHA20_POLY1305, secure_rand)
34 }
35
36 pub fn with_algorithm(
37 algo: &'static ring::aead::Algorithm,
38 secure_rand: SystemRandom,
39 ) -> KmsAeadResult<Self> {
40 Self::with_algorithm_options(algo, secure_rand, RingAeadEncryptionOptions::new())
41 }
42
43 pub fn with_options(
44 secure_rand: SystemRandom,
45 options: RingAeadEncryptionOptions,
46 ) -> KmsAeadResult<Self> {
47 Self::with_algorithm_options(&ring::aead::CHACHA20_POLY1305, secure_rand, options)
48 }
49
50 pub fn with_algorithm_options(
51 algo: &'static ring::aead::Algorithm,
52 secure_rand: SystemRandom,
53 options: RingAeadEncryptionOptions,
54 ) -> KmsAeadResult<Self> {
55 Ok(Self {
56 algo,
57 secure_rand,
58 options,
59 })
60 }
61
62 pub fn generate_data_encryption_key(&self) -> KmsAeadResult<DataEncryptionKey> {
63 generate_secret_key(&self.secure_rand, self.algo.key_len())
64 }
65}
66
67#[async_trait]
68impl<Aad> AeadEncryption<Aad> for RingAeadEncryption
69where
70 Aad: AsRef<[u8]> + Send + Sync + 'static,
71{
72 async fn encrypt_value(
73 &self,
74 aad: &Aad,
75 plain_text: &SecretValue,
76 encryption_key: &DataEncryptionKey,
77 ) -> KmsAeadResult<CipherText> {
78 let nonce_data = match self.options.nonce_kind {
79 RingAeadEncryptionNonceKind::Random => generate_random_nonce(&self.secure_rand)?,
80 RingAeadEncryptionNonceKind::TimeRandom => {
81 generate_time_random_nonce(&self.secure_rand)?
82 }
83 };
84
85 let encrypted_value = encrypt_with_sealing_key(
86 self.algo,
87 encryption_key,
88 nonce_data.as_slice(),
89 ring::aead::Aad::from(aad),
90 plain_text.ref_sensitive_value().as_slice(),
91 )?;
92
93 let mut encrypted_value_with_nonce: Vec<u8> =
94 Vec::with_capacity(nonce_data.len() + encrypted_value.value().len());
95
96 encrypted_value_with_nonce.extend_from_slice(nonce_data.as_slice());
97
98 encrypted_value_with_nonce.extend_from_slice(encrypted_value.value().as_slice());
99
100 Ok(CipherText(encrypted_value_with_nonce))
101 }
102
103 async fn decrypt_value(
104 &self,
105 aad: &Aad,
106 cipher_text: &CipherText,
107 encryption_key: &DataEncryptionKey,
108 ) -> KmsAeadResult<SecretValue> {
109 let (nonce_data, encrypted_part) = cipher_text.value().split_at(ring::aead::NONCE_LEN);
110
111 decrypt_with_opening_key(
112 self.algo,
113 encryption_key,
114 nonce_data,
115 ring::aead::Aad::from(aad),
116 encrypted_part,
117 )
118 }
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use proptest::prelude::*;
125 use proptest::strategy::ValueTree;
126 use proptest::test_runner::TestRunner;
127
128 pub fn generate_secret_value() -> BoxedStrategy<SecretValue> {
129 ("[a-zA-Z0-9]+")
130 .prop_map(|(mock_secret_str)| SecretValue::new(mock_secret_str.as_bytes().to_vec()))
131 .boxed()
132 }
133
134 async fn encryption_test_for(mock_secret_value: SecretValue) {
135 let mock_aad: String = "test".to_string();
136 let secure_rand: SystemRandom = SystemRandom::new();
137
138 let encryption = RingAeadEncryption::with_rand(secure_rand).unwrap();
139
140 let secret_key = encryption.generate_data_encryption_key().unwrap();
141
142 let encrypted_value = encryption
143 .encrypt_value(&mock_aad, &mock_secret_value, &secret_key)
144 .await
145 .unwrap();
146
147 assert_ne!(
148 encrypted_value.value(),
149 mock_secret_value.ref_sensitive_value()
150 );
151
152 let decrypted_value = encryption
153 .decrypt_value(&mock_aad, &encrypted_value, &secret_key)
154 .await
155 .unwrap();
156 assert_eq!(
157 decrypted_value.ref_sensitive_value(),
158 mock_secret_value.ref_sensitive_value()
159 );
160 }
161
162 #[tokio::test]
163 async fn secret_encryption_test() {
164 let mut runner = TestRunner::default();
165 encryption_test_for(
166 generate_secret_value()
167 .new_tree(&mut runner)
168 .unwrap()
169 .current(),
170 )
171 .await
172 }
173
174 #[tokio::test]
175 async fn big_secret_encryption_test() {
176 for sz in vec![5000, 32768, 65535] {
177 encryption_test_for(SecretValue::new("42".repeat(sz).as_bytes().to_vec())).await
178 }
179 }
180
181 #[tokio::test]
182 async fn wrong_secret_name_test_attest() {
183 let mock_aad1: String = "test1".to_string();
184 let mock_aad2: String = "test2".to_string();
185
186 let mock_secret_value = SecretValue::new("42".repeat(1024).as_bytes().to_vec());
187
188 let secure_rand: SystemRandom = SystemRandom::new();
189
190 let encryption = RingAeadEncryption::with_rand(secure_rand).unwrap();
191
192 let secret_key = encryption.generate_data_encryption_key().unwrap();
193
194 let encrypted_value = encryption
195 .encrypt_value(&mock_aad1, &mock_secret_value, &secret_key)
196 .await
197 .unwrap();
198 encryption
199 .decrypt_value(&mock_aad2, &encrypted_value, &secret_key)
200 .await
201 .expect_err("Unable to decrypt data");
202 }
203
204 #[tokio::test]
205 async fn different_encryption_instances_test() {
206 let mock_aad: String = "test1".to_string();
207 let mock_secret_value = SecretValue::new("42".repeat(1024).as_bytes().to_vec());
208
209 let secure_rand: SystemRandom = SystemRandom::new();
210
211 let secret_key =
212 generate_secret_key(&secure_rand, ring::aead::CHACHA20_POLY1305.key_len()).unwrap();
213
214 let encrypted_value = {
215 let encryption = RingAeadEncryption::with_rand(secure_rand.clone()).unwrap();
216 encryption
217 .encrypt_value(&mock_aad, &mock_secret_value, &secret_key)
218 .await
219 .unwrap()
220 };
221
222 let decrypted_value = {
223 let encryption = RingAeadEncryption::with_rand(secure_rand.clone()).unwrap();
224 encryption
225 .decrypt_value(&mock_aad, &encrypted_value, &secret_key)
226 .await
227 .unwrap()
228 };
229
230 assert_eq!(decrypted_value, mock_secret_value)
231 }
232}