rc_crypto/aead/
aes_gcm.rs
1use crate::{aead, error::*};
23use nss::aes;
24
25pub static AES_128_GCM: aead::Algorithm = aead::Algorithm {
27 key_len: 16,
28 tag_len: 16,
29 nonce_len: 96 / 8,
30 open,
31 seal,
32};
33
34pub static AES_256_GCM: aead::Algorithm = aead::Algorithm {
36 key_len: 32,
37 tag_len: 16,
38 nonce_len: 96 / 8,
39 open,
40 seal,
41};
42
43pub(crate) fn open(
44 key: &aead::Key,
45 nonce: aead::Nonce,
46 aad: &aead::Aad<'_>,
47 ciphertext_and_tag: &[u8],
48) -> Result<Vec<u8>> {
49 aes_gcm(
50 key,
51 nonce,
52 aad,
53 ciphertext_and_tag,
54 aead::Direction::Opening,
55 )
56}
57
58pub(crate) fn seal(
59 key: &aead::Key,
60 nonce: aead::Nonce,
61 aad: &aead::Aad<'_>,
62 plaintext: &[u8],
63) -> Result<Vec<u8>> {
64 aes_gcm(key, nonce, aad, plaintext, aead::Direction::Sealing)
65}
66
67fn aes_gcm(
68 key: &aead::Key,
69 nonce: aead::Nonce,
70 aad: &aead::Aad<'_>,
71 data: &[u8],
72 direction: aead::Direction,
73) -> Result<Vec<u8>> {
74 Ok(aes::aes_gcm_crypt(
75 &key.key_value,
76 &nonce.0,
77 aad.0,
78 data,
79 direction.to_nss_operation(),
80 )?)
81}
82
83#[cfg(test)]
84mod test {
85 use super::*;
86 use nss::ensure_initialized;
87
88 const NONCE_HEX: &str = "cafebabefacedbaddecaf888";
90 const KEY_HEX: &str = "feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308";
91 const AAD_HEX: &str = "feedfacedeadbeeffeedfacedeadbeefabaddad2";
92 const TAG_HEX: &str = "76fc6ece0f4e1768cddf8853bb2d551b";
93 const CIPHERTEXT_HEX: &str =
94 "522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662";
95 const CLEARTEXT_HEX: &str =
96 "d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39";
97
98 #[test]
99 fn test_decrypt() {
100 ensure_initialized();
101 let key_bytes = hex::decode(KEY_HEX).unwrap();
102 let key = aead::Key::new(&AES_256_GCM, &key_bytes).unwrap();
103 let mut ciphertext_and_tag = hex::decode(CIPHERTEXT_HEX).unwrap();
104 let tag = hex::decode(TAG_HEX).unwrap();
105 ciphertext_and_tag.extend(&tag);
106
107 let iv = hex::decode(NONCE_HEX).unwrap();
108 let nonce = aead::Nonce::try_assume_unique_for_key(&AES_256_GCM, &iv).unwrap();
109 let aad_bytes = hex::decode(AAD_HEX).unwrap();
110 let aad = aead::Aad::from(&aad_bytes);
111 let cleartext_bytes = open(&key, nonce, &aad, &ciphertext_and_tag).unwrap();
112 let encoded_cleartext = hex::encode(cleartext_bytes);
113 assert_eq!(&CLEARTEXT_HEX, &encoded_cleartext);
114 }
115
116 #[test]
117 fn test_encrypt() {
118 ensure_initialized();
119 let key_bytes = hex::decode(KEY_HEX).unwrap();
120 let key = aead::Key::new(&AES_256_GCM, &key_bytes).unwrap();
121 let cleartext = hex::decode(CLEARTEXT_HEX).unwrap();
122
123 let iv = hex::decode(NONCE_HEX).unwrap();
124 let nonce = aead::Nonce::try_assume_unique_for_key(&AES_256_GCM, &iv).unwrap();
125 let aad_bytes = hex::decode(AAD_HEX).unwrap();
126 let aad = aead::Aad::from(&aad_bytes);
127 let ciphertext_bytes = seal(&key, nonce, &aad, &cleartext).unwrap();
128
129 let expected_tag = hex::decode(TAG_HEX).unwrap();
130 let mut expected_ciphertext = hex::decode(CIPHERTEXT_HEX).unwrap();
131 expected_ciphertext.extend(&expected_tag);
132 assert_eq!(&expected_ciphertext, &ciphertext_bytes);
133 }
134
135 #[test]
136 fn test_roundtrip() {
137 ensure_initialized();
138 let key_bytes = hex::decode(KEY_HEX).unwrap();
139 let key = aead::Key::new(&AES_256_GCM, &key_bytes).unwrap();
140 let cleartext = hex::decode(CLEARTEXT_HEX).unwrap();
141
142 let iv = hex::decode(NONCE_HEX).unwrap();
143 let nonce = aead::Nonce::try_assume_unique_for_key(&AES_256_GCM, &iv).unwrap();
144 let ciphertext_bytes = seal(&key, nonce, &aead::Aad::empty(), &cleartext).unwrap();
145 let nonce = aead::Nonce::try_assume_unique_for_key(&AES_256_GCM, &iv).unwrap();
146 let roundtriped_cleartext_bytes =
147 open(&key, nonce, &aead::Aad::empty(), &ciphertext_bytes).unwrap();
148 assert_eq!(roundtriped_cleartext_bytes, cleartext);
149 }
150}