+gcm128
[avr-crypto-lib.git] / gcm / gcm128.c
1 /* gcm128.c */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2006-2015 Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <inttypes.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <memxor.h>
24 #include <blockcipher_descriptor.h>
25 #include <bcal-basic.h>
26 #include <gcm128.h>
27
28 #include <stdio.h>
29 #include <cli.h>
30 #include <uart.h>
31
32 #define DUMP_LEN_LINE(x, len, line) do { \
33         printf("\n\n (DBG <" __FILE__ " %s " #line ">)" #x ":", __func__); \
34         cli_hexdump_block((x), (len), 4, 16); \
35         uart0_flush(); } while (0)
36
37 #define DUMP_dummy(x, len, v) DUMP_LEN_LINE(x, len, v)
38 #define DUMP_LEN(x, len) DUMP_dummy(x, len, __LINE__)
39
40
41 #define DUMP(x) DUMP_LEN(x, sizeof(x))
42
43
44 #define BLOCK_BYTES GCM128_BLOCK_BYTES
45 #define BLOCK_BITS GCM128_BLOCK_BITS
46
47 #define COUNT_BYTES GCM128_COUNT_BYTES
48 #define COUNT_BITS GCM128_COUNT_BITS
49
50 #define POLY_BYTE 0xE1
51
52
53 static uint8_t shift_block_right(void *a)
54 {
55     uint8_t c1 = 0, c2;
56     uint8_t i = BLOCK_BYTES;
57     uint8_t *p = a;
58     do {
59         c2 = *p & 1;
60         *p = (*p >> 1) | c1;
61         p++;
62         c1 = c2 ? 0x80 : 0;
63     } while (--i);
64     return c2;
65 }
66
67 static void gmul128(
68         void *dest,
69         const void *a,
70         const void *b)
71 {
72     uint8_t c, v[BLOCK_BYTES], t, dummy[BLOCK_BYTES + 1], *(lut[2]);
73     const uint8_t *x = b;
74     uint8_t i, j;
75     memset(dest, 0, BLOCK_BYTES);
76     memset(dummy, 0, BLOCK_BYTES);
77     dummy[BLOCK_BYTES] = POLY_BYTE;
78     memcpy(v, a, BLOCK_BYTES);
79     lut[0] = dummy;
80     lut[1] = v;
81     i = BLOCK_BYTES;
82     do {
83         j = 8;
84         t = *x++;
85         do {
86             memxor(dest, lut[t >> 7], BLOCK_BYTES);
87             t <<= 1;
88             c = shift_block_right(v);
89             v[0] ^= dummy[15 + c];
90         } while (--j);
91     } while (--i);
92 }
93
94 static void ghash128_init(ghash128_ctx_t *ctx)
95 {
96     memset(ctx->tag, 0, 16);
97 }
98
99 static void ghash128_block(
100         ghash128_ctx_t *ctx,
101         const void *block)
102 {
103     uint8_t tmp[BLOCK_BYTES];
104     memcpy(tmp, ctx->tag, BLOCK_BYTES);
105     memxor(tmp, block, BLOCK_BYTES);
106     gmul128(ctx->tag, tmp, ctx->key);
107 }
108
109 static void inc32(void *a)
110 {
111     uint8_t c, *p = a;
112     c = (p[3]++ == 0);
113     c &= ((p[2] += c) == 0);
114     c &= ((p[1] += c) == 0);
115     p[0] +=c;
116 }
117
118 int8_t gcm128_init(
119         gcm128_ctx_t *ctx,
120         const bcdesc_t *cipher,
121         const void *key,
122         uint16_t key_length_b,
123         const void *iv,
124         uint16_t iv_length_b)
125 {
126     uint8_t r;
127     uint8_t tmp[BLOCK_BYTES];
128     if (bcal_cipher_getBlocksize_b(cipher) != BLOCK_BITS) {
129         return -1;
130     }
131     if ((r = bcal_cipher_init(cipher, key, key_length_b, &ctx->cipher_ctx))) {
132         printf_P(PSTR("Error: return code: %"PRId8" key length: %"PRId16" <%s %s %d>\n"), r, key_length_b, __FILE__, __func__, __LINE__);
133         uart0_flush();
134         return -2;
135     }
136     memset(ctx->ghash_ctx.key, 0, BLOCK_BYTES);
137     bcal_cipher_enc(ctx->ghash_ctx.key, &ctx->cipher_ctx);
138     ghash128_init(&ctx->ghash_ctx);
139     if (iv_length_b == BLOCK_BITS - COUNT_BITS) {
140         memcpy(ctx->ctr, iv, (BLOCK_BITS - COUNT_BITS) / 8);
141         memset(&ctx->ctr[BLOCK_BYTES - COUNT_BYTES], 0, COUNT_BYTES - 1);
142         ctx->ctr[BLOCK_BYTES - 1] = 1;
143     } else {
144         uint16_t ctr = iv_length_b / BLOCK_BITS;
145         while (ctr--)
146         {
147             ghash128_block(&ctx->ghash_ctx, iv);
148             iv = &((uint8_t*)iv)[BLOCK_BYTES];
149         }
150         memset(tmp, 0, BLOCK_BYTES);
151         memcpy(tmp, iv, (iv_length_b % BLOCK_BITS + 7) / 8);
152         if (iv_length_b & 7) {
153             tmp[(iv_length_b % BLOCK_BITS) / 8] &= 0xff << (8 - (iv_length_b & 7));
154         }
155         ghash128_block(&ctx->ghash_ctx, tmp);
156         memset(tmp, 0, BLOCK_BYTES);
157         tmp[BLOCK_BYTES - 2] = iv_length_b >> 8;
158         tmp[BLOCK_BYTES - 1] = iv_length_b & 0xff;
159         ghash128_block(&ctx->ghash_ctx, tmp);
160         memcpy(ctx->ctr, ctx->ghash_ctx.tag, BLOCK_BYTES);
161         ghash128_init(&ctx->ghash_ctx);
162     }
163     memcpy(ctx->j0, &ctx->ctr[BLOCK_BYTES - COUNT_BYTES], COUNT_BYTES);
164     ctx->length_a = 0;
165     ctx->length_c = 0;
166     return 0;
167 }
168
169 void gcm128_add_ad_block(
170         gcm128_ctx_t *ctx,
171         const void *block )
172 {
173     ghash128_block(&ctx->ghash_ctx, block);
174     ctx->length_a += BLOCK_BITS;
175 }
176
177 void gcm128_add_ad_final_block(
178         gcm128_ctx_t *ctx,
179         const void *block,
180         uint16_t length_b )
181 {
182     uint8_t tmp[BLOCK_BYTES];
183     while (length_b >= BLOCK_BITS)
184     {
185         gcm128_add_ad_block(ctx, block);
186         length_b -= BLOCK_BITS;
187         block = &((uint8_t*)block)[BLOCK_BYTES];
188     }
189     if (length_b > 0) {
190         memset(tmp, 0, BLOCK_BYTES);
191         memcpy(tmp, block, (length_b + 7) / 8);
192         if (length_b & 7) {
193             tmp[length_b / 8] &= 0xff << (8 - (length_b & 7));
194         }
195         ghash128_block(&ctx->ghash_ctx, tmp);
196         ctx->length_a += length_b;
197     }
198 }
199
200 void gcm128_encrypt_block(
201         gcm128_ctx_t *ctx,
202         void *dest,
203         const void *src)
204 {
205     uint8_t tmp[BLOCK_BYTES];
206     inc32(&ctx->ctr[BLOCK_BYTES - COUNT_BYTES]);
207     memcpy(tmp, ctx->ctr, BLOCK_BYTES);
208     bcal_cipher_enc(tmp, &ctx->cipher_ctx);
209     memxor(tmp, src, BLOCK_BYTES);
210     ghash128_block(&ctx->ghash_ctx, tmp);
211     ctx->length_c += BLOCK_BITS;
212     if (dest) {
213         memcpy(dest, tmp, BLOCK_BYTES);
214     }
215 }
216
217 void gcm128_encrypt_final_block(
218         gcm128_ctx_t *ctx,
219         void *dest,
220         const void *src,
221         uint16_t length_b
222         )
223 {
224     uint8_t tmp[BLOCK_BYTES];
225     while (length_b >= BLOCK_BITS) {
226         gcm128_encrypt_block(ctx, dest, src);
227         length_b -= BLOCK_BITS;
228         if (dest) {
229             dest = &((uint8_t*)dest)[BLOCK_BYTES];
230         }
231         src = &((uint8_t*)src)[BLOCK_BYTES];
232     }
233     if (length_b > 0) {
234         inc32(&ctx->ctr[BLOCK_BYTES - COUNT_BYTES]);
235         memcpy(tmp, ctx->ctr, BLOCK_BYTES);
236         bcal_cipher_enc(tmp, &ctx->cipher_ctx);
237         memxor(tmp, src, BLOCK_BYTES);
238         memset(&tmp[(length_b + 7) / 8], 0, BLOCK_BYTES - (length_b + 7) / 8);
239         if (length_b & 7) {
240             tmp[length_b / 8] &= 0xff << (8 - (length_b & 7));
241         }
242         ghash128_block(&ctx->ghash_ctx, tmp);
243         ctx->length_c += length_b;
244         if (dest) {
245             memcpy(dest, tmp, (length_b + 7) / 8);
246         }
247     }
248 }
249
250 void gcm128_decrypt_block(
251         gcm128_ctx_t *ctx,
252         void *dest,
253         const void *src)
254 {
255     uint8_t tmp[BLOCK_BYTES];
256     ghash128_block(&ctx->ghash_ctx, src);
257     inc32(&ctx->ctr[11]);
258     memcpy(tmp, ctx->ctr, BLOCK_BYTES);
259     bcal_cipher_enc(tmp, &ctx->cipher_ctx);
260     memxor(tmp, src, BLOCK_BYTES);
261     ctx->length_c += BLOCK_BITS;
262     if (dest) {
263         memcpy(dest, tmp, BLOCK_BYTES);
264     }
265 }
266
267 void gcm128_decrypt_final_block(
268         gcm128_ctx_t *ctx,
269         void *dest,
270         const void *src,
271         uint16_t length_b)
272 {
273     uint8_t tmp[BLOCK_BYTES];
274     while (length_b > BLOCK_BITS) {
275         gcm128_decrypt_block(ctx, dest, src);
276         length_b -= BLOCK_BITS;
277         if (dest) {
278             dest = &((uint8_t*)dest)[BLOCK_BYTES];
279         }
280         src = &((uint8_t*)src)[BLOCK_BYTES];
281     }
282     if (length_b > 0) {
283         memcpy(tmp, src, (length_b + 7) / 8);
284         memset(&tmp[(length_b + 7) / 8], 0, BLOCK_BYTES - (length_b + 7) / 8);
285         if (length_b & 7) {
286             tmp[length_b / 8] &= 0xff << (8 - (length_b & 7));
287         }
288         ghash128_block(&ctx->ghash_ctx, tmp);
289         inc32(&ctx->ctr[11]);
290         memcpy(tmp, ctx->ctr, BLOCK_BYTES);
291         bcal_cipher_enc(tmp, &ctx->cipher_ctx);
292         memxor(tmp, src, BLOCK_BYTES);
293         memset(&tmp[(length_b + 7) / 8], 0, BLOCK_BYTES - (length_b + 7) / 8);
294         if (length_b & 7) {
295             tmp[length_b / 8] &= 0xff << (8 - (length_b & 7));
296         }
297         ctx->length_c += length_b;
298         if (dest) {
299             memcpy(dest, tmp, (length_b + 7) / 8);
300         }
301     }
302 }
303
304 void gcm128_finalize(gcm128_ctx_t *ctx, void *tag, uint16_t tag_length_b)
305 {
306     uint8_t tmp[BLOCK_BYTES];
307     memset(tmp, 0, BLOCK_BYTES);
308     tmp[4] = ctx->length_a >> 24;
309     tmp[5] = ctx->length_a >> 16;
310     tmp[6] = ctx->length_a >>  8;
311     tmp[7] = ctx->length_a;
312     tmp[12] = ctx->length_c >> 24;
313     tmp[13] = ctx->length_c >> 16;
314     tmp[14] = ctx->length_c >>  8;
315     tmp[15] = ctx->length_c;
316     ghash128_block(&ctx->ghash_ctx, tmp);
317     memcpy(tmp, ctx->ctr, BLOCK_BYTES - COUNT_BYTES);
318     memcpy(&tmp[BLOCK_BYTES - COUNT_BYTES], ctx->j0, COUNT_BYTES);
319     bcal_cipher_enc(tmp, &ctx->cipher_ctx);
320     bcal_cipher_free(&ctx->cipher_ctx);
321     memxor(tmp, ctx->ghash_ctx.tag, BLOCK_BYTES);
322     if (tag_length_b > BLOCK_BITS) {
323         tag_length_b = BLOCK_BITS;
324     }
325     if (tag_length_b & 7) {
326         tmp[tag_length_b / 8] &= 0xff << (8 - (tag_length_b & 7));
327     }
328     if (tag) {
329         memcpy(tag, tmp, (tag_length_b + 7) / 8);
330     }
331 }