1#![deny(unsafe_code)]
4
5use aead::consts::{
6 U0,
7 U16,
8};
9use aead::{
10 AeadCore,
11 AeadInPlace,
12 Error,
13 Key,
14 KeyInit,
15 KeySizeUser,
16 Nonce,
17 Tag,
18};
19use subtle::ConstantTimeEq;
20use zeroize::Zeroize;
21
22use crate::backend::{
23 AD_BLK_EVN,
24 AD_BLK_ODD,
25 MSG_BLK,
26 ad_encryption,
27 g8a,
28 lfsr_gf56,
29 msg_encryption_n_inplace,
30 nonce_encryption,
31 reset_lfsr_gf56,
32};
33
34#[derive(Clone)]
36pub struct RomulusN {
37 key: Key<Self>,
38}
39
40impl Drop for RomulusN {
41 fn drop(&mut self) {
42 self.key.as_mut_slice().zeroize();
43 }
44}
45
46impl KeySizeUser for RomulusN {
47 type KeySize = U16;
48}
49
50impl KeyInit for RomulusN {
51 fn new(key: &Key<Self>) -> Self {
52 Self { key: *key }
53 }
54}
55
56impl AeadCore for RomulusN {
57 type NonceSize = U16;
58 type TagSize = U16;
59 type CiphertextOverhead = U0;
60}
61
62impl AeadInPlace for RomulusN {
63 fn encrypt_in_place_detached(
64 &self,
65 nonce: &Nonce<Self>,
66 associated_data: &[u8],
67 buffer: &mut [u8],
68 ) -> Result<Tag<Self>, Error> {
69 let k = crate::stack_secret::zeroizing_copy_16(self.key.as_slice());
70 let n = crate::stack_secret::zeroizing_copy_16(nonce.as_slice());
71 let tag = romulus_n_encrypt(&k, &n, associated_data, buffer)?;
72 Ok(Tag::<Self>::from(tag))
73 }
74
75 fn decrypt_in_place_detached(
76 &self,
77 nonce: &Nonce<Self>,
78 associated_data: &[u8],
79 buffer: &mut [u8],
80 tag: &Tag<Self>,
81 ) -> Result<(), Error> {
82 let k = crate::stack_secret::zeroizing_copy_16(self.key.as_slice());
83 let n = crate::stack_secret::zeroizing_copy_16(nonce.as_slice());
84 let tg = crate::stack_secret::zeroizing_copy_16(tag.as_slice());
85 romulus_n_decrypt(&k, &n, associated_data, buffer, &tg)
86 }
87}
88
89pub(crate) fn romulus_n_encrypt(
91 key: &[u8; 16],
92 nonce: &[u8; 16],
93 ad: &[u8],
94 buf: &mut [u8],
95) -> Result<[u8; 16], Error> {
96 let mut s = [0u8; 16];
97 let mut cnt = [0u8; 7];
98 reset_lfsr_gf56(&mut cnt);
99 let n_ad = AD_BLK_ODD;
100 let t_ad = AD_BLK_EVN;
101 let mut a_off = 0usize;
102 let mut adlen = ad.len() as u64;
103
104 if adlen == 0 {
105 lfsr_gf56(&mut cnt);
106 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x1A);
107 } else {
108 while adlen > 0 {
109 if adlen < n_ad as u64 {
110 adlen = ad_encryption(
111 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
112 );
113 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x1A);
114 } else if adlen == n_ad as u64 {
115 adlen = ad_encryption(
116 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
117 );
118 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x18);
119 } else if adlen < (n_ad + t_ad) as u64 {
120 adlen = ad_encryption(
121 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
122 );
123 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x1A);
124 } else if adlen == (n_ad + t_ad) as u64 {
125 adlen = ad_encryption(
126 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
127 );
128 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x18);
129 } else {
130 adlen = ad_encryption(
131 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
132 );
133 }
134 }
135 }
136
137 reset_lfsr_gf56(&mut cnt);
138 let msg_n = MSG_BLK;
139 let mut mlen = buf.len() as u64;
140 let mut off = 0usize;
141
142 if mlen == 0 {
143 lfsr_gf56(&mut cnt);
144 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x15);
145 } else {
146 while mlen > 0 {
147 if mlen < msg_n as u64 {
148 mlen = msg_encryption_n_inplace(
149 buf, &mut off, nonce, &mut cnt, &mut s, key, msg_n, t_ad, 0x15, mlen, false,
150 );
151 } else if mlen == msg_n as u64 {
152 mlen = msg_encryption_n_inplace(
153 buf, &mut off, nonce, &mut cnt, &mut s, key, msg_n, t_ad, 0x14, mlen, false,
154 );
155 } else {
156 mlen = msg_encryption_n_inplace(
157 buf, &mut off, nonce, &mut cnt, &mut s, key, msg_n, t_ad, 0x04, mlen, false,
158 );
159 }
160 }
161 }
162
163 let mut tag = [0u8; 16];
164 g8a(&s, &mut tag);
165 Ok(tag)
166}
167
168pub(crate) fn romulus_n_decrypt(
173 key: &[u8; 16],
174 nonce: &[u8; 16],
175 ad: &[u8],
176 ct: &mut [u8],
177 tag: &[u8; 16],
178) -> Result<(), Error> {
179 let ok = romulus_n_decrypt_core(key, nonce, ad, ct, tag);
180 if ok {
181 Ok(())
182 } else {
183 ct.zeroize();
184 Err(Error)
185 }
186}
187
188pub(crate) fn romulus_n_decrypt_core(
190 key: &[u8; 16],
191 nonce: &[u8; 16],
192 ad: &[u8],
193 ct: &mut [u8],
194 tag: &[u8; 16],
195) -> bool {
196 let mut s = [0u8; 16];
197 let mut cnt = [0u8; 7];
198 reset_lfsr_gf56(&mut cnt);
199 let n_ad = AD_BLK_ODD;
200 let t_ad = AD_BLK_EVN;
201 let mut a_off = 0usize;
202 let mut adlen = ad.len() as u64;
203
204 if adlen == 0 {
205 lfsr_gf56(&mut cnt);
206 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x1A);
207 } else {
208 while adlen > 0 {
209 if adlen < n_ad as u64 {
210 adlen = ad_encryption(
211 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
212 );
213 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x1A);
214 } else if adlen == n_ad as u64 {
215 adlen = ad_encryption(
216 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
217 );
218 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x18);
219 } else if adlen < (n_ad + t_ad) as u64 {
220 adlen = ad_encryption(
221 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
222 );
223 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x1A);
224 } else if adlen == (n_ad + t_ad) as u64 {
225 adlen = ad_encryption(
226 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
227 );
228 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x18);
229 } else {
230 adlen = ad_encryption(
231 ad, &mut a_off, &mut s, key, adlen, &mut cnt, 0x08, n_ad, t_ad,
232 );
233 }
234 }
235 }
236
237 reset_lfsr_gf56(&mut cnt);
238 let msg_n = MSG_BLK;
239 let mut mlen = ct.len() as u64;
240 let mut off = 0usize;
241
242 if mlen == 0 {
243 lfsr_gf56(&mut cnt);
244 nonce_encryption(nonce, &mut cnt, &mut s, key, t_ad, 0x15);
245 } else {
246 while mlen > 0 {
247 if mlen < msg_n as u64 {
248 mlen = msg_encryption_n_inplace(
249 ct, &mut off, nonce, &mut cnt, &mut s, key, msg_n, t_ad, 0x15, mlen, true,
250 );
251 } else if mlen == msg_n as u64 {
252 mlen = msg_encryption_n_inplace(
253 ct, &mut off, nonce, &mut cnt, &mut s, key, msg_n, t_ad, 0x14, mlen, true,
254 );
255 } else {
256 mlen = msg_encryption_n_inplace(
257 ct, &mut off, nonce, &mut cnt, &mut s, key, msg_n, t_ad, 0x04, mlen, true,
258 );
259 }
260 }
261 }
262
263 let mut calc = [0u8; 16];
264 g8a(&s, &mut calc);
265 bool::from(calc.ct_eq(tag))
266}