File Coverage

inc/matrixssl-3-9-3-open/crypto/symmetric/aesGCM.c
Criterion Covered Total %
statement 169 196 86.2
branch 40 52 76.9
condition n/a
subroutine n/a
pod n/a
total 209 248 84.2


line stmt bran cond sub pod time code
1             /**
2             * @file aesGCM.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * AES GCM block cipher implementation.
6             */
7             /*
8             * Copyright (c) 2013-2017 INSIDE Secure Corporation
9             * Copyright (c) PeerSec Networks, 2002-2011
10             * All Rights Reserved
11             *
12             * The latest version of this code is available at http://www.matrixssl.org
13             *
14             * This software is open source; you can redistribute it and/or modify
15             * it under the terms of the GNU General Public License as published by
16             * the Free Software Foundation; either version 2 of the License, or
17             * (at your option) any later version.
18             *
19             * This General Public License does NOT permit incorporating this software
20             * into proprietary programs. If you are unable to comply with the GPL, a
21             * commercial license for this software may be purchased from INSIDE at
22             * http://www.insidesecure.com/
23             *
24             * This program is distributed in WITHOUT ANY WARRANTY; without even the
25             * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26             * See the GNU General Public License for more details.
27             *
28             * You should have received a copy of the GNU General Public License
29             * along with this program; if not, write to the Free Software
30             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31             * http://www.gnu.org/copyleft/gpl.html
32             */
33             /******************************************************************************/
34              
35             #include "../cryptoImpl.h"
36              
37             #ifdef USE_MATRIX_AES_GCM
38              
39             /******************************************************************************/
40              
41             static void psGhashPad(psAesGcm_t *ctx);
42             static void psGhashInit(psAesGcm_t *ctx,
43             const unsigned char *GHASHKey_p);
44             static void psGhashUpdate(psAesGcm_t *ctx, const unsigned char *data,
45             uint32 dataLen, int dataType);
46             static void psGhashFinal(psAesGcm_t *ctx);
47              
48             # define GHASH_DATATYPE_AAD 0
49             # define GHASH_DATATYPE_CIPHERTEXT 2
50              
51             # define FL_GET_BE32(be) \
52             (((uint32) ((be).be_bytes[0]) << 24) | \
53             ((uint32) ((be).be_bytes[1]) << 16) | \
54             ((uint32) ((be).be_bytes[2]) << 8) | \
55             (uint32) ((be).be_bytes[3]))
56              
57             typedef struct { unsigned char be_bytes[4]; } FL_UInt32_BE_UNA_t;
58              
59             # define FLFBLOCKSIZE 128 /* Maximum block size of a hash function. */
60              
61             /******************************************************************************/
62             /*
63             Initialize an AES GCM context
64             */
65 4234           int32_t psAesInitGCM(psAesGcm_t *ctx,
66             const unsigned char key[AES_MAXKEYLEN], uint8_t keylen)
67             {
68             int32_t rc;
69 4234           unsigned char blockIn[16] = { 0 };
70              
71 4234           memset(ctx, 0x0, sizeof(psAesGcm_t));
72             /* GCM always uses AES in ENCRYPT block mode, even for decrypt */
73 4234           rc = psAesInitBlockKey(&ctx->key, key, keylen, PS_AES_ENCRYPT);
74 4234 50         if (rc < 0)
75             {
76 0           return rc;
77             }
78 4234           psAesEncryptBlock(&ctx->key, blockIn, ctx->gInit);
79 4234           return PS_SUCCESS;
80             }
81              
82             /******************************************************************************/
83              
84 0           void psAesClearGCM(psAesGcm_t *ctx)
85             {
86             /* Only need to clear block if it's implemented externally, Matrix block
87             is part of AesGcm_t and will be cleared below */
88             # ifndef USE_MATRIX_AES_BLOCK
89             psAesClearBlockKey(&ctx->key);
90             # endif
91 0           memset_s(ctx, sizeof(psAesGcm_t), 0x0, sizeof(psAesGcm_t));
92 0           }
93              
94             /******************************************************************************/
95             /*
96             Specifiy the IV and additional data to an AES GCM context that was
97             created with psAesInitGCM
98             */
99 12575           void psAesReadyGCM(psAesGcm_t *ctx,
100             const unsigned char IV[AES_IVLEN],
101             const unsigned char *aad, psSize_t aadLen)
102             {
103 12575           psGhashInit(ctx, ctx->gInit);
104             /* Save aside first counter for final use */
105 12575           memset(ctx->IV, 0, 16);
106 12575           memcpy(ctx->IV, IV, 12);
107 12575           ctx->IV[15] = 1;
108              
109             /* Set up crypto counter starting at nonce || 2 */
110 12575           memset(ctx->EncCtr, 0, 16);
111 12575           memcpy(ctx->EncCtr, IV, 12);
112 12575           ctx->EncCtr[15] = 2;
113              
114 12575           psGhashUpdate(ctx, aad, aadLen, GHASH_DATATYPE_AAD);
115 12575           psGhashPad(ctx);
116 12575           }
117              
118 0           int32_t psAesReadyGCMRandomIV(psAesGcm_t *ctx,
119             unsigned char IV[12],
120             const unsigned char *aad, psSize_t aadLen,
121             void *poolUserPtr)
122             {
123             int32_t res;
124              
125 0           res = psGetPrng(NULL, IV, 12, poolUserPtr);
126 0 0         if (res == 12)
127             {
128 0           res = PS_SUCCESS;
129 0           psAesReadyGCM(ctx, IV, aad, aadLen);
130             }
131 0           return res;
132             }
133              
134             /******************************************************************************/
135             /*
136             Internal gcm crypt function that uses direction to determine what gets
137             fed to the GHASH update
138             */
139 12575           static void psAesEncryptGCMx(psAesGcm_t *ctx,
140             const unsigned char *pt, unsigned char *ct,
141             uint32_t len, int8_t direction)
142             {
143             unsigned char *ctStart;
144             uint32_t outLen;
145             int x; /* Must be signed due to positive check below */
146              
147 12575           outLen = len;
148 12575           ctStart = ct;
149 12575 100         if (direction == 0)
150             {
151 6287           psGhashUpdate(ctx, pt, len, GHASH_DATATYPE_CIPHERTEXT);
152             }
153 66259954 100         while (len)
154             {
155 66247379 100         if (ctx->OutputBufferCount == 0)
156             {
157 4148211           ctx->OutputBufferCount = 16;
158 4148211           psAesEncryptBlock(&ctx->key, ctx->EncCtr, ctx->CtrBlock);
159              
160             /* CTR incr */
161 4160631 50         for (x = (AES_BLOCKLEN - 1); x >= 0; x--)
162             {
163 4160631           ctx->EncCtr[x] = (ctx->EncCtr[x] +
164             (unsigned char) 1) & (unsigned char) 255;
165 4160631 100         if (ctx->EncCtr[x] != (unsigned char) 0)
166             {
167 4148211           break;
168             }
169             }
170             }
171              
172 66247379           *(ct++) = *(pt++) ^ ctx->CtrBlock[16 - ctx->OutputBufferCount];
173 66247379           len--;
174 66247379           ctx->OutputBufferCount--;
175             }
176 12575 100         if (direction == 1)
177             {
178 6288           psGhashUpdate(ctx, ctStart, outLen, GHASH_DATATYPE_CIPHERTEXT);
179             }
180 12575           }
181              
182             /******************************************************************************/
183             /*
184             Public GCM encrypt function. This will just perform the encryption. The
185             tag should be fetched with psAesGetGCMTag
186             */
187 6288           void psAesEncryptGCM(psAesGcm_t *ctx,
188             const unsigned char *pt, unsigned char *ct,
189             uint32_t len)
190             {
191 6288           psAesEncryptGCMx(ctx, pt, ct, len, 1);
192 6288           }
193              
194             /******************************************************************************/
195             /*
196             After encryption this function is used to retreive the authentication tag
197             */
198 12575           void psAesGetGCMTag(psAesGcm_t *ctx,
199             uint8_t tagBytes, unsigned char tag[AES_BLOCKLEN])
200             {
201             unsigned char *pt, *ct;
202              
203 12575           psGhashFinal(ctx);
204              
205             /* Encrypt authentication tag */
206 12575           ctx->OutputBufferCount = 0;
207              
208 12575           ct = tag;
209 12575           pt = (unsigned char *) ctx->TagTemp;
210 213775 100         while (tagBytes)
211             {
212 201200 100         if (ctx->OutputBufferCount == 0)
213             {
214 12575           ctx->OutputBufferCount = 16;
215             /* Initial IV has been set aside in IV */
216 12575           psAesEncryptBlock(&ctx->key, ctx->IV, ctx->CtrBlock);
217             /* No need to increment since we know tag bytes will never be
218             larger than 16 */
219             }
220 201200           *(ct++) = *(pt++) ^ ctx->CtrBlock[16 - ctx->OutputBufferCount];
221 201200           tagBytes--;
222 201200           ctx->OutputBufferCount--;
223              
224             }
225 12575           }
226              
227             /* Just does the GCM decrypt portion. Doesn't expect the tag to be at the end
228             of the ct. User will invoke psAesGetGCMTag seperately */
229 0           void psAesDecryptGCMtagless(psAesGcm_t *ctx,
230             const unsigned char *ct, unsigned char *pt,
231             uint32_t len)
232             {
233 0           psAesEncryptGCMx(ctx, ct, pt, len, 0);
234 0           }
235              
236              
237             /******************************************************************************/
238             /*
239             Decrypt will invoke GetGMCTag so the comparison can be done. ctLen
240             will include the appended tag length and ptLen is just the encrypted
241             portion
242             */
243 6287           int32_t psAesDecryptGCM(psAesGcm_t *ctx,
244             const unsigned char *ct, uint32_t ctLen,
245             unsigned char *pt, uint32_t ptLen)
246             {
247             psSize_t tagLen;
248             unsigned char tag[AES_BLOCKLEN];
249              
250 6287 50         if (ctLen > ptLen)
251             {
252 6287           tagLen = ctLen - ptLen;
253             }
254             else
255             {
256 0           return PS_ARG_FAIL;
257             }
258              
259 6287           psAesEncryptGCMx(ctx, ct, pt, ptLen, 0);
260 6287           psAesGetGCMTag(ctx, tagLen, tag);
261              
262 6287 50         if (memcmpct(tag, ct + ptLen, tagLen) != 0)
263             {
264             psTraceCrypto("GCM didn't authenticate\n");
265 0           return PS_AUTH_FAIL;
266             }
267 6287           return PS_SUCCESS;
268             }
269              
270 0           int32_t psAesDecryptGCM2(psAesGcm_t *ctx,
271             const unsigned char *ct,
272             unsigned char *pt, uint32_t len,
273             const unsigned char *tag, uint32_t tagLen)
274             {
275             unsigned char tagTmp[AES_BLOCKLEN];
276              
277 0           psAesEncryptGCMx(ctx, ct, pt, len, 0);
278 0           psAesGetGCMTag(ctx, AES_BLOCKLEN, tagTmp);
279              
280 0 0         if (memcmpct(tag, tagTmp, tagLen) != 0)
281             {
282             psTraceCrypto("GCM didn't authenticate\n");
283 0           return PS_AUTH_FAIL;
284             }
285 0           return PS_SUCCESS;
286             }
287              
288             /******************************************************************************/
289             /*
290             Ghash code taken from FL
291             */
292 534190208           static void FLA_GHASH_128_mul_base(uint32 *op, uint32 moduli)
293             {
294 534190208           int carry_bit = op[3] & 0x1;
295              
296 534190208           op[3] = op[3] >> 1 | (op[2] & 0x1) << 31;
297 534190208           op[2] = op[2] >> 1 | (op[1] & 0x1) << 31;
298 534190208           op[1] = op[1] >> 1 | (op[0] & 0x1) << 31;
299 534190208           op[0] = op[0] >> 1;
300              
301 534190208 100         if (carry_bit)
302             {
303 266434420           op[0] ^= moduli;
304             }
305 534190208           }
306              
307             /* Multiplication of X by Y, storing the result to X. */
308 4173361           static void FLA_GHASH_128_mul(uint32 *X, const uint32 *Y, uint32 moduli)
309             {
310             uint32 t[4];
311             int i;
312              
313 4173361           t[0] = X[0];
314 4173361           t[1] = X[1];
315 4173361           t[2] = X[2];
316 4173361           t[3] = X[3];
317              
318 4173361           X[0] = X[1] = X[2] = X[3] = 0;
319              
320 538363569 100         for (i = 0; i < 128; i++)
321             {
322 534190208 100         if (Y[i / 32] & (1 << (31 - i % 32)))
323             {
324 265932263           X[0] ^= t[0];
325 265932263           X[1] ^= t[1];
326 265932263           X[2] ^= t[2];
327 265932263           X[3] ^= t[3];
328             }
329              
330 534190208           FLA_GHASH_128_mul_base(t, moduli);
331             }
332 4173361           }
333              
334 25150           static int FLFIncreaseCountBits(psAesGcm_t *ctx, unsigned int CounterId,
335             int32 NBits)
336             {
337             int32 Lo, Hi;
338             int32 Temp;
339              
340 25150           Lo = NBits;
341 25150           Hi = 0;
342              
343 25150           Temp = ctx->ProcessedBitCount[CounterId];
344 25150           ctx->ProcessedBitCount[CounterId] += Lo;
345              
346 25150 50         if (Temp > (int32) ctx->ProcessedBitCount[CounterId])
347             {
348 0           Hi += 1;
349             }
350              
351 25150 50         if (Hi)
352             {
353 0           Temp = ctx->ProcessedBitCount[CounterId + 1];
354 0           ctx->ProcessedBitCount[CounterId + 1] += Hi;
355              
356             /* Returns true if carry out of highest bits. */
357 0           return Temp > (int32) ctx->ProcessedBitCount[CounterId + 1];
358             }
359              
360             /* No update of high order bits => No carry. */
361 25150           return 0; /* false */
362             }
363              
364 25150           static int increaseCountBytes(psAesGcm_t *ctx, int32 NBytes,
365             int CounterId)
366             {
367             int carry;
368              
369             /* COVN: Test this code with > 2^31 bits. */
370              
371             /* Process NBytes (assuming NBytes < 0x10000000) */
372 25150           carry = FLFIncreaseCountBits(ctx, CounterId, (NBytes & 0x0FFFFFFF) << 3);
373              
374 25150           NBytes &= 0x0FFFFFFF;
375              
376             /* For unusually large values of NBytes, process the remaining bytes
377             to add 0x10000000 at time. This ensure the value of bytes,
378             once converted to bits, does not overflow 32-bit value.
379              
380             PORTN: It is assumed NBytes <= 2**61. This is true on 32-bit APIs as
381             FL_DataLen_t cannot represent such large value. */
382 25150 50         while (NBytes >= 0x10000000)
383             {
384 0           carry |= FLFIncreaseCountBits(ctx, CounterId, 0x10000000U * 8);
385 0           NBytes -= 0x10000000;
386             }
387              
388 25150           return carry;
389             }
390              
391 4173361           static void FLAGcmProcessBlock(uint32 *H, FL_UInt32_BE_UNA_t *Buf_p,
392             uint32 *InOut)
393             {
394             /* PORTN: Requires sizeof(FL_UInt32_BE_UNA_t) to be 4.
395             Some platforms may add padding to FL_UInt32_BE_UNA_t if
396             it is represented as a structure. */
397              
398 4173361           InOut[0] ^= FL_GET_BE32(Buf_p[0]);
399 4173361           InOut[1] ^= FL_GET_BE32(Buf_p[1]);
400 4173361           InOut[2] ^= FL_GET_BE32(Buf_p[2]);
401 4173361           InOut[3] ^= FL_GET_BE32(Buf_p[3]);
402              
403 4173361           FLA_GHASH_128_mul(InOut, H, (1U << 31) + (1 << 30) + (1 << 29) + (1 << 24));
404 4173361           }
405              
406 541077           static void UpdateFunc(psAesGcm_t *ctx, const unsigned char *Buf_p,
407             int32 Size)
408             {
409 4714438 100         while (Size >= 16)
410             {
411 4173361           FLAGcmProcessBlock((uint32 *) ctx->Hash_SubKey,
412 4173361           (FL_UInt32_BE_UNA_t *) Buf_p, (uint32 *) ctx->TagTemp);
413 4173361           Buf_p += 16;
414 4173361           Size -= 16;
415             }
416 541077           }
417              
418 186872           static void flf_blocker(psAesGcm_t *ctx, const unsigned char *Data_p,
419             uint32 DataCount)
420             {
421 889671 100         while (DataCount > 0)
422             {
423 702799 100         if (ctx->InputBufferCount == FLFBLOCKSIZE)
424             {
425 515927           UpdateFunc(ctx,
426 515927           ctx->Input.Buffer,
427 515927           ctx->InputBufferCount);
428 515927           ctx->InputBufferCount = 0;
429             }
430 702799 50         if (ctx->InputBufferCount < FLFBLOCKSIZE)
431             {
432 702799           uint32 BytesProcess = min((uint32) DataCount,
433             FLFBLOCKSIZE - ctx->InputBufferCount);
434              
435 2108397           memcpy(ctx->Input.Buffer
436 1405598           + ctx->InputBufferCount, Data_p, BytesProcess);
437 702799           DataCount -= BytesProcess;
438 702799           ctx->InputBufferCount += BytesProcess;
439 702799           Data_p += BytesProcess;
440             }
441             }
442              
443 186872           }
444              
445 12575           static void psGhashInit(psAesGcm_t *ctx,
446             const unsigned char *GHASHKey_p)
447             {
448 12575           uint32 *Key_p = (uint32 *) ctx->Hash_SubKey;
449              
450 12575           memset(&ctx->ProcessedBitCount, 0x0,
451             sizeof(ctx->ProcessedBitCount));
452 12575           ctx->InputBufferCount = 0;
453 12575           Key_p[0] = FL_GET_BE32(*(FL_UInt32_BE_UNA_t *) GHASHKey_p);
454 12575           Key_p[1] = FL_GET_BE32(*(FL_UInt32_BE_UNA_t *) (GHASHKey_p + 4));
455 12575           Key_p[2] = FL_GET_BE32(*(FL_UInt32_BE_UNA_t *) (GHASHKey_p + 8));
456 12575           Key_p[3] = FL_GET_BE32(*(FL_UInt32_BE_UNA_t *) (GHASHKey_p + 12));
457 12575           memset(ctx->TagTemp, 0x0, 16);
458 12575           }
459              
460 25150           static void psGhashUpdate(psAesGcm_t *ctx, const unsigned char *data,
461             uint32 dataLen, int dataType)
462             {
463 25150           increaseCountBytes(ctx, dataLen, dataType);
464 25150           flf_blocker(ctx, data, dataLen);
465              
466 25150           }
467              
468 25150           static void psGhashPad(psAesGcm_t *ctx)
469             {
470 186872 100         while ((ctx->InputBufferCount & 15) != 0)
471             {
472 161722           unsigned char z = 0;
473 161722           flf_blocker(ctx, &z, 1);
474             }
475 25150           }
476              
477             # ifndef ENDIAN_BIG
478             # ifdef ENDIAN_NEUTRAL
479             # warning ENDIAN_NEUTRAL untested for AES-GCM
480             # endif
481              
482             /* On little endian (and endian neutral untested), we need to reverse bytes
483             to big endian mode for GhashFinal */
484 100600           static uint32 FLM_ReverseBytes32(uint32 Value)
485             {
486 100600           Value = (((Value & 0xff00ff00UL) >> 8) | ((Value & 0x00ff00ffUL) << 8));
487 100600           return (Value >> 16) | (Value << 16);
488             }
489 12575           static void FLF_ConvertToBE64(uint32 *Swap_p, uint32 num)
490             {
491             uint32 tmp;
492              
493 37725 100         while (num)
494             {
495 25150           num--;
496 25150           tmp = FLM_ReverseBytes32(Swap_p[num * 2]);
497 25150           Swap_p[num * 2] = FLM_ReverseBytes32(Swap_p[num * 2 + 1]);
498 25150           Swap_p[num * 2 + 1] = tmp;
499             }
500 12575           }
501 12575           static void FLF_ConvertToBE32(uint32 *Swap_p, uint32 num)
502             {
503             /* PORTN: Byte order specific function. */
504 62875 100         while (num)
505             {
506 50300           num--;
507 50300           Swap_p[num] = FLM_ReverseBytes32(Swap_p[num]);
508             }
509 12575           }
510              
511             # else
512              
513             /* On big endian, the 4 bytes in a uint32 are already in the right order! */
514             static void FLF_ConvertToBE64(uint32 *Swap_p, uint32 num)
515             {
516             uint32 tmp;
517              
518             while (num)
519             {
520             num--;
521             tmp = Swap_p[num * 2];
522             Swap_p[num * 2] = Swap_p[num * 2 + 1];
523             Swap_p[num * 2 + 1] = tmp;
524             }
525             }
526             # define FLF_ConvertToBE32(A, B)
527              
528             # endif /* !ENDIAN_BIG */
529              
530 12575           static void psGhashFinal(psAesGcm_t *ctx)
531             {
532 12575           psGhashPad(ctx);
533              
534             /* TODO COVN: Check GHASH with data > 2^32 bits for word swap logic. */
535             /* Swap 32 bit words 0 & 1 and 2 & 3, on ENDIAN_LITTLE, swap bytes too */
536 12575           FLF_ConvertToBE64(&ctx->ProcessedBitCount[0], 2);
537              
538 12575           UpdateFunc(ctx, ctx->Input.Buffer,
539 12575           ctx->InputBufferCount);
540 12575           ctx->InputBufferCount = 0;
541              
542 12575           UpdateFunc(ctx,
543 12575           (const unsigned char *) &ctx->ProcessedBitCount[0], 16);
544              
545             /* Convert temporary Tag Value to final Tag Value. NOOP on ENDIAN_BIG */
546 12575           FLF_ConvertToBE32(ctx->TagTemp, 4);
547 12575           }
548              
549             #endif /* USE_MATRIX_AES_GCM */
550              
551             /******************************************************************************/
552