• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Traits for AES-GCM-SIV.
16 
17 use super::AesKey;
18 extern crate alloc;
19 use alloc::vec::Vec;
20 
21 /// An enum for indicating issues with the GCM-SIV encryption/decryption operations.
22 pub enum GcmSivError {
23     /// Returned if the output buffer is too small to store the resulting ciphertext + tag.
24     EncryptOutBufferTooSmall,
25     /// Returned if the ciphertext + tag combination does not match when decrypting a blob.
26     DecryptTagDoesNotMatch,
27 }
28 
29 /// An implementation of AES-GCM-SIV.
30 ///
31 /// An AesGcmSiv impl may be used for encryption and decryption.
32 pub trait AesGcmSiv {
33     /// The [AesKey] this cipher uses. See [super::Aes128Key] and [super::Aes256Key] for the common AES-128 and
34     /// AES-256 cases.
35     type Key: AesKey;
36 
37     /// Build a `Self` from key material.
new(key: &Self::Key) -> Self38     fn new(key: &Self::Key) -> Self;
39 
40     /// Encrypt the data in place with a nonce to make sure each ciphertext is unique.
41     /// This will need 16 bytes reserved in the data array for the tag.
42     /// Optionally, additional associated data can be passed in for computation of the cryptographic tag.
encrypt(&self, data: &mut Vec<u8>, aad: &[u8], nonce: &[u8]) -> Result<(), GcmSivError>43     fn encrypt(&self, data: &mut Vec<u8>, aad: &[u8], nonce: &[u8]) -> Result<(), GcmSivError>;
44     /// Decrypt the ciphertext concatenated with its tag in place with the nonce used for encryption.
45     /// If associated data was passed in when creating the ciphertext, it should be passed in here as well
46     /// in order to properly decrypt the message.
decrypt(&self, data: &mut Vec<u8>, aad: &[u8], nonce: &[u8]) -> Result<(), GcmSivError>47     fn decrypt(&self, data: &mut Vec<u8>, aad: &[u8], nonce: &[u8]) -> Result<(), GcmSivError>;
48 }
49 
50 /// Module for testing implementations of this crate.
51 #[cfg(feature = "testing")]
52 pub mod testing {
53     extern crate alloc;
54 
55     use alloc::vec::Vec;
56     use core::marker;
57 
58     use hex_literal::hex;
59     use rstest_reuse::template;
60 
61     use crate::aes::{Aes128Key, Aes256Key};
62     pub use crate::testing::prelude;
63 
64     use super::AesGcmSiv;
65 
66     /// Test AES-GCM-SIV-128 encryption/decryption
aes_128_gcm_siv_test<A: AesGcmSiv<Key = Aes128Key>>(_marker: marker::PhantomData<A>)67     pub fn aes_128_gcm_siv_test<A: AesGcmSiv<Key = Aes128Key>>(_marker: marker::PhantomData<A>) {
68         // https://github.com/google/wycheproof/blob/master/testvectors/aes_gcm_siv_test.json
69         // TC1
70         let test_key = hex!("01000000000000000000000000000000");
71         let nonce = hex!("030000000000000000000000");
72         let aes = A::new(&test_key.into());
73         let msg = hex!("");
74         let mut buf = Vec::from(msg.as_slice());
75         let tag = hex!("dc20e2d83f25705bb49e439eca56de25");
76         assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
77         assert_eq!(&buf[..], &tag);
78         // TC2
79         let msg = hex!("0100000000000000");
80         let ct = hex!("b5d839330ac7b786");
81         let tag = hex!("578782fff6013b815b287c22493a364c");
82         let mut buf = Vec::from(msg.as_slice());
83         assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
84         assert_eq!(&buf[..8], &ct);
85         assert_eq!(&buf[8..], &tag);
86         assert!(aes.decrypt(&mut buf, b"", &nonce).is_ok());
87         assert_eq!(&buf[..], &msg);
88     }
89 
90     /// Test AES-256-GCM-SIV encryption/decryption
aes_256_gcm_siv_test<A: AesGcmSiv<Key = Aes256Key>>(_marker: marker::PhantomData<A>)91     pub fn aes_256_gcm_siv_test<A: AesGcmSiv<Key = Aes256Key>>(_marker: marker::PhantomData<A>) {
92         // https://github.com/google/wycheproof/blob/master/testvectors/aes_gcm_siv_test.json
93         // TC77
94         let test_key = hex!("0100000000000000000000000000000000000000000000000000000000000000");
95         let nonce = hex!("030000000000000000000000");
96         let aes = A::new(&test_key.into());
97         let msg = hex!("0100000000000000");
98         let mut buf = Vec::new();
99         buf.extend_from_slice(&msg);
100         let ct = hex!("c2ef328e5c71c83b");
101         let tag = hex!("843122130f7364b761e0b97427e3df28");
102         assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
103         assert_eq!(&buf[..8], &ct);
104         assert_eq!(&buf[8..], &tag);
105         assert!(aes.decrypt(&mut buf, b"", &nonce).is_ok());
106         assert_eq!(&buf[..], &msg);
107         // TC78
108         let msg = hex!("010000000000000000000000");
109         let ct = hex!("9aab2aeb3faa0a34aea8e2b1");
110         let tag = hex!("8ca50da9ae6559e48fd10f6e5c9ca17e");
111         let mut buf = Vec::from(msg.as_slice());
112         assert!(aes.encrypt(&mut buf, b"", &nonce).is_ok());
113         assert_eq!(&buf[..12], &ct);
114         assert_eq!(&buf[12..], &tag);
115         assert!(aes.decrypt(&mut buf, b"", &nonce).is_ok());
116         assert_eq!(&buf[..], &msg);
117     }
118 
119     /// Generates the test cases to validate the AES-128-GCM-SIV implementation.
120     /// For example, to test `MyAesGcmSiv128Impl`:
121     ///
122     /// ```
123     /// use crypto_provider::aes::gcm_siv::testing::*;
124     ///
125     /// mod tests {
126     ///     #[apply(aes_128_gcm_siv_test_cases)]
127     ///     fn aes_128_gcm_siv_tests(testcase: CryptoProviderTestCase<MyAesGcmSivImpl>) {
128     ///         testcase(MyAesGcmSiv128Impl);
129     ///     }
130     /// }
131     /// ```
132     #[template]
133     #[export]
134     #[rstest]
135     #[case::encrypt(aes_128_gcm_siv_test)]
136     #[case::decrypt(aes_128_gcm_siv_test)]
aes_128_gcm_siv_test_cases<F: AesGcmSivFactory<Key = Aes128Key>>( #[case] testcase: CryptoProviderTestCase<F>, )137     fn aes_128_gcm_siv_test_cases<F: AesGcmSivFactory<Key = Aes128Key>>(
138         #[case] testcase: CryptoProviderTestCase<F>,
139     ) {
140     }
141 
142     /// Generates the test cases to validate the AES-256-GCM-SIV implementation.
143     /// For example, to test `MyAesGcmSiv256Impl`:
144     ///
145     /// ```
146     /// use crypto_provider::aes::gcm_siv::testing::*;
147     ///
148     /// mod tests {
149     ///     #[apply(aes_256_gcm_siv_test_cases)]
150     ///     fn aes_256_gcm_siv_tests(testcase: CryptoProviderTestCase<MyAesGcmSiv256Impl>) {
151     ///         testcase(MyAesGcmSiv256Impl);
152     ///     }
153     /// }
154     /// ```
155     #[template]
156     #[export]
157     #[rstest]
158     #[case::encrypt(aes_256_gcm_siv_test)]
159     #[case::decrypt(aes_256_gcm_siv_test)]
aes_256_gcm_siv_test_cases<F: AesGcmSivFactory<Key = Aes256Key>>( #[case] testcase: CryptoProviderTestCase<F>, )160     fn aes_256_gcm_siv_test_cases<F: AesGcmSivFactory<Key = Aes256Key>>(
161         #[case] testcase: CryptoProviderTestCase<F>,
162     ) {
163     }
164 }
165