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