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