1const GCM_NB: usize = 4;
21const GCM_ACCEPTING_HEADER: usize = 0;
22const GCM_ACCEPTING_CIPHER: usize = 1;
23const GCM_NOT_ACCEPTING_MORE: usize = 2;
24const GCM_FINISHED: usize = 3;
25const GCM_ENCRYPTING: usize = 0;
26const GCM_DECRYPTING: usize = 1;
27
28use crate::aes;
29use crate::aes::AES;
30
31pub struct GCM {
32 table: [[u32; 4]; 128],
33 statex: [u8; 16],
34 y_0: [u8; 16],
35 lena: [u32; 2],
37 lenc: [u32; 2],
38 status: usize,
39 a: AES,
40}
41
42impl GCM {
43 fn pack(b: [u8; 4]) -> u32 {
44 return ((((b[0]) & 0xff) as u32) << 24)
46 | ((((b[1]) & 0xff) as u32) << 16)
47 | ((((b[2]) & 0xff) as u32) << 8)
48 | (((b[3]) & 0xff) as u32);
49 }
50
51 fn unpack(a: u32) -> [u8; 4] {
52 let b: [u8; 4] = [
54 ((a >> 24) & 0xff) as u8,
55 ((a >> 16) & 0xff) as u8,
56 ((a >> 8) & 0xff) as u8,
57 (a & 0xff) as u8,
58 ];
59 return b;
60 }
61
62 fn precompute(&mut self, h: &[u8]) {
63 let mut b: [u8; 4] = [0; 4];
64 let mut j = 0;
65 for i in 0..GCM_NB {
66 b[0] = h[j];
67 b[1] = h[j + 1];
68 b[2] = h[j + 2];
69 b[3] = h[j + 3];
70 self.table[0][i] = GCM::pack(b);
71 j += 4;
72 }
73 for i in 1..128 {
74 let mut c: u32 = 0;
75 for j in 0..GCM_NB {
76 self.table[i][j] = c | (self.table[i - 1][j]) >> 1;
77 c = self.table[i - 1][j] << 31;
78 }
79 if c != 0 {
80 self.table[i][0] ^= 0xE1000000
81 } }
83 }
84
85 fn gf2mul(&mut self) {
86 let mut p: [u32; 4] = [0; 4];
88
89 for i in 0..4 {
90 p[i] = 0
91 }
92 let mut j: usize = 8;
93 let mut m = 0;
94 for i in 0..128 {
95 j -= 1;
96 let mut c = ((self.statex[m] >> j) & 1) as u32;
97 c = (!c) + 1;
98 for k in 0..GCM_NB {
99 p[k] ^= self.table[i][k] & c
100 }
101 if j == 0 {
102 j = 8;
103 m += 1;
104 if m == 16 {
105 break;
106 }
107 }
108 }
109 j = 0;
110 for i in 0..GCM_NB {
111 let b = GCM::unpack(p[i]);
112 self.statex[j] = b[0];
113 self.statex[j + 1] = b[1];
114 self.statex[j + 2] = b[2];
115 self.statex[j + 3] = b[3];
116 j += 4;
117 }
118 }
119
120 fn wrap(&mut self) {
121 let mut f: [u32; 4] = [0; 4];
123 let mut el: [u8; 16] = [0; 16];
124
125 f[0] = (self.lena[0] << 3) | (self.lena[1] & 0xE0000000) >> 29;
127 f[1] = self.lena[1] << 3;
128 f[2] = (self.lenc[0] << 3) | (self.lenc[1] & 0xE0000000) >> 29;
129 f[3] = self.lenc[1] << 3;
130 let mut j = 0;
131 for i in 0..GCM_NB {
132 let b = GCM::unpack(f[i]);
133 el[j] = b[0];
134 el[j + 1] = b[1];
135 el[j + 2] = b[2];
136 el[j + 3] = b[3];
137 j += 4;
138 }
139 for i in 0..16 {
140 self.statex[i] ^= el[i]
141 }
142 self.gf2mul();
143 }
144
145 fn ghash(&mut self, plain: &[u8], len: usize) -> bool {
146 if self.status == GCM_ACCEPTING_HEADER {
147 self.status = GCM_ACCEPTING_CIPHER
148 }
149 if self.status != GCM_ACCEPTING_CIPHER {
150 return false;
151 }
152
153 let mut j = 0;
154 while j < len {
155 for i in 0..16 {
156 if j >= len {
157 break;
158 }
159 self.statex[i] ^= plain[j];
160 j += 1;
161 self.lenc[1] += 1;
162 if self.lenc[1] == 0 {
163 self.lenc[0] += 1
164 }
165 }
166 self.gf2mul();
167 }
168 if len % 16 != 0 {
169 self.status = GCM_NOT_ACCEPTING_MORE
170 }
171 return true;
172 }
173
174 pub fn init(&mut self, nk: usize, key: &[u8], niv: usize, iv: &[u8]) {
176 let mut h: [u8; 16] = [0; 16];
178
179 for i in 0..16 {
180 h[i] = 0;
181 self.statex[i] = 0
182 }
183
184 self.a = AES::new();
185
186 self.a.init(aes::ECB, nk, key, None);
187 self.a.ecb_encrypt(&mut h); self.precompute(&h);
189
190 self.lena[0] = 0;
191 self.lenc[0] = 0;
192 self.lena[1] = 0;
193 self.lenc[1] = 0;
194 if niv == 12 {
195 for i in 0..12 {
196 self.a.f[i] = iv[i]
197 }
198 let b = GCM::unpack(1);
199 self.a.f[12] = b[0];
200 self.a.f[13] = b[1];
201 self.a.f[14] = b[2];
202 self.a.f[15] = b[3]; for i in 0..16 {
204 self.y_0[i] = self.a.f[i]
205 }
206 } else {
207 self.status = GCM_ACCEPTING_CIPHER;
208 self.ghash(iv, niv); self.wrap();
210 for i in 0..16 {
211 self.a.f[i] = self.statex[i];
212 self.y_0[i] = self.a.f[i];
213 self.statex[i] = 0
214 }
215 self.lena[0] = 0;
216 self.lenc[0] = 0;
217 self.lena[1] = 0;
218 self.lenc[1] = 0;
219 }
220 self.status = GCM_ACCEPTING_HEADER;
221 }
222
223 pub fn new() -> GCM {
224 GCM {
225 table: [[0; 4]; 128],
226 statex: [0; 16],
227 y_0: [0; 16],
228 lena: [0; 2],
230 lenc: [0; 2],
231 status: 0,
232 a: AES::new(),
233 }
234 }
235
236 pub fn add_header(&mut self, header: &[u8], len: usize) -> bool {
238 if self.status != GCM_ACCEPTING_HEADER {
240 return false;
241 }
242 let mut j = 0;
243 while j < len {
244 for i in 0..16 {
245 if j >= len {
246 break;
247 }
248 self.statex[i] ^= header[j];
249 j += 1;
250 self.lena[1] += 1;
251 if self.lena[1] == 0 {
252 self.lena[0] += 1
253 }
254 }
255 self.gf2mul();
256 }
257 if len % 16 != 0 {
258 self.status = GCM_ACCEPTING_CIPHER
259 }
260 return true;
261 }
262
263 pub fn add_plain(&mut self, cipher: &mut [u8], plain: &[u8], len: usize) -> bool {
265 let mut cb: [u8; 16] = [0; 16];
266 let mut b: [u8; 4] = [0; 4];
267
268 let mut counter: u32;
269 if self.status == GCM_ACCEPTING_HEADER {
270 self.status = GCM_ACCEPTING_CIPHER
271 }
272 if self.status != GCM_ACCEPTING_CIPHER {
273 return false;
274 }
275
276 let mut j = 0;
277 while j < len {
278 b[0] = self.a.f[12];
279 b[1] = self.a.f[13];
280 b[2] = self.a.f[14];
281 b[3] = self.a.f[15];
282 counter = GCM::pack(b);
283 counter += 1;
284 b = GCM::unpack(counter);
285 self.a.f[12] = b[0];
286 self.a.f[13] = b[1];
287 self.a.f[14] = b[2];
288 self.a.f[15] = b[3]; for i in 0..16 {
290 cb[i] = self.a.f[i]
291 }
292 self.a.ecb_encrypt(&mut cb); for i in 0..16 {
295 if j >= len {
296 break;
297 }
298 cipher[j] = plain[j] ^ cb[i];
299 self.statex[i] ^= cipher[j];
300 j += 1;
301 self.lenc[1] += 1;
302 if self.lenc[1] == 0 {
303 self.lenc[0] += 1
304 }
305 }
306 self.gf2mul()
307 }
308 if len % 16 != 0 {
309 self.status = GCM_NOT_ACCEPTING_MORE
310 }
311 return true;
312 }
313
314 pub fn add_cipher(&mut self, plain: &mut [u8], cipher: &[u8], len: usize) -> bool {
316 let mut cb: [u8; 16] = [0; 16];
317 let mut b: [u8; 4] = [0; 4];
318
319 let mut counter: u32;
320
321 if self.status == GCM_ACCEPTING_HEADER {
322 self.status = GCM_ACCEPTING_CIPHER
323 }
324 if self.status != GCM_ACCEPTING_CIPHER {
325 return false;
326 }
327
328 let mut j = 0;
329 while j < len {
330 b[0] = self.a.f[12];
331 b[1] = self.a.f[13];
332 b[2] = self.a.f[14];
333 b[3] = self.a.f[15];
334 counter = GCM::pack(b);
335 counter += 1;
336 b = GCM::unpack(counter);
337 self.a.f[12] = b[0];
338 self.a.f[13] = b[1];
339 self.a.f[14] = b[2];
340 self.a.f[15] = b[3]; for i in 0..16 {
342 cb[i] = self.a.f[i]
343 }
344 self.a.ecb_encrypt(&mut cb); for i in 0..16 {
346 if j >= len {
347 break;
348 }
349 let oc = cipher[j];
350 plain[j] = cipher[j] ^ cb[i];
351 self.statex[i] ^= oc;
352 j += 1;
353 self.lenc[1] += 1;
354 if self.lenc[1] == 0 {
355 self.lenc[0] += 1
356 }
357 }
358 self.gf2mul()
359 }
360 if len % 16 != 0 {
361 self.status = GCM_NOT_ACCEPTING_MORE
362 }
363 return true;
364 }
365
366 pub fn finish(&mut self, extract: bool) -> [u8; 16] {
368 let mut tag: [u8; 16] = [0; 16];
370
371 self.wrap();
372 if extract {
374 self.a.ecb_encrypt(&mut (self.y_0)); for i in 0..16 {
376 self.y_0[i] ^= self.statex[i]
377 }
378 for i in 0..16 {
379 tag[i] = self.y_0[i];
380 self.y_0[i] = 0;
381 self.statex[i] = 0
382 }
383 }
384 self.status = GCM_FINISHED;
385 self.a.end();
386 return tag;
387 }
388
389 pub fn hex2bytes(hex: &[u8], bin: &mut [u8]) {
390 let len = hex.len();
391
392 for i in 0..len / 2 {
393 let mut v: u8;
394 let mut c = hex[2 * i];
395 if c >= b'0' && c <= b'9' {
396 v = c - b'0';
397 } else if c >= b'A' && c <= b'F' {
398 v = c - b'A' + 10;
399 } else if c >= b'a' && c <= b'f' {
400 v = c - b'a' + 10;
401 } else {
402 v = 0;
403 }
404 v <<= 4;
405 c = hex[2 * i + 1];
406 if c >= b'0' && c <= b'9' {
407 v += c - b'0';
408 } else if c >= b'A' && c <= b'F' {
409 v += c - b'A' + 10;
410 } else if c >= b'a' && c <= b'f' {
411 v += c - b'a' + 10;
412 } else {
413 v = 0;
414 }
415 bin[i] = v;
416 }
417 }
418}
419