gcm.c
Go to the documentation of this file.
1 /**
2  * @file gcm.c
3  * @brief Galois/Counter Mode (GCM)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCrypto Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @section Description
28  *
29  * The Galois/Counter Mode (GCM) is an authenticated encryption algorithm
30  * designed to provide both data authenticity (integrity) and confidentiality.
31  * Refer to SP 800-38D for more details
32  *
33  * @author Oryx Embedded SARL (www.oryx-embedded.com)
34  * @version 1.9.6
35  **/
36 
37 //Switch to the appropriate trace level
38 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
39 
40 //Dependencies
41 #include "core/crypto.h"
42 #include "aead/gcm.h"
43 #include "debug.h"
44 
45 //Check crypto library configuration
46 #if (GCM_SUPPORT == ENABLED)
47 
48 //Reduction table
49 static const uint32_t r[16] =
50 {
51  0x00000000,
52  0x1C200000,
53  0x38400000,
54  0x24600000,
55  0x70800000,
56  0x6CA00000,
57  0x48C00000,
58  0x54E00000,
59  0xE1000000,
60  0xFD200000,
61  0xD9400000,
62  0xC5600000,
63  0x91800000,
64  0x8DA00000,
65  0xA9C00000,
66  0xB5E00000
67 };
68 
69 
70 /**
71  * @brief Initialize GCM context
72  * @param[in] context Pointer to the GCM context
73  * @param[in] cipherAlgo Cipher algorithm
74  * @param[in] cipherContext Pointer to the cipher algorithm context
75  * @return Error code
76  **/
77 
78 error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo,
79  void *cipherContext)
80 {
81  uint_t i;
82  uint_t j;
83  uint32_t c;
84  uint32_t h[4];
85 
86  //GCM supports only symmetric block ciphers whose block size is 128 bits
87  if(cipherAlgo->type != CIPHER_ALGO_TYPE_BLOCK || cipherAlgo->blockSize != 16)
89 
90  //Save cipher algorithm context
91  context->cipherAlgo = cipherAlgo;
92  context->cipherContext = cipherContext;
93 
94  //Let H = 0
95  h[0] = 0;
96  h[1] = 0;
97  h[2] = 0;
98  h[3] = 0;
99 
100  //Generate the hash subkey H
101  context->cipherAlgo->encryptBlock(context->cipherContext,
102  (uint8_t *) h, (uint8_t *) h);
103 
104  //Pre-compute M(0) = H * 0
105  j = reverseInt4(0);
106  context->m[j][0] = 0;
107  context->m[j][1] = 0;
108  context->m[j][2] = 0;
109  context->m[j][3] = 0;
110 
111  //Pre-compute M(1) = H * 1
112  j = reverseInt4(1);
113  context->m[j][0] = betoh32(h[3]);
114  context->m[j][1] = betoh32(h[2]);
115  context->m[j][2] = betoh32(h[1]);
116  context->m[j][3] = betoh32(h[0]);
117 
118  //Pre-compute all 4-bit multiples of H
119  for(i = 2; i < 16; i++)
120  {
121  //Odd value?
122  if(i & 1)
123  {
124  //Compute M(i) = M(i - 1) + H
125  j = reverseInt4(i - 1);
126  h[0] = context->m[j][0];
127  h[1] = context->m[j][1];
128  h[2] = context->m[j][2];
129  h[3] = context->m[j][3];
130 
131  //An addition in GF(2^128) is identical to a bitwise exclusive-OR
132  //operation
133  j = reverseInt4(1);
134  h[0] ^= context->m[j][0];
135  h[1] ^= context->m[j][1];
136  h[2] ^= context->m[j][2];
137  h[3] ^= context->m[j][3];
138  }
139  //Even value?
140  else
141  {
142  //Compute M(i) = M(i / 2) * x
143  j = reverseInt4(i / 2);
144  h[0] = context->m[j][0];
145  h[1] = context->m[j][1];
146  h[2] = context->m[j][2];
147  h[3] = context->m[j][3];
148 
149  //The multiplication of a polynomial by x in GF(2^128) corresponds
150  //to a shift of indices
151  c = h[0] & 0x01;
152  h[0] = (h[0] >> 1) | (h[1] << 31);
153  h[1] = (h[1] >> 1) | (h[2] << 31);
154  h[2] = (h[2] >> 1) | (h[3] << 31);
155  h[3] >>= 1;
156 
157  //If the highest term of the result is equal to one, then perform
158  //reduction
159  h[3] ^= r[reverseInt4(1)] & ~(c - 1);
160  }
161 
162  //Save M(i)
163  j = reverseInt4(i);
164  context->m[j][0] = h[0];
165  context->m[j][1] = h[1];
166  context->m[j][2] = h[2];
167  context->m[j][3] = h[3];
168  }
169 
170  //Successful initialization
171  return NO_ERROR;
172 }
173 
174 
175 /**
176  * @brief Authenticated encryption using GCM
177  * @param[in] context Pointer to the GCM context
178  * @param[in] iv Initialization vector
179  * @param[in] ivLen Length of the initialization vector
180  * @param[in] a Additional authenticated data
181  * @param[in] aLen Length of the additional data
182  * @param[in] p Plaintext to be encrypted
183  * @param[out] c Ciphertext resulting from the encryption
184  * @param[in] length Total number of data bytes to be encrypted
185  * @param[out] t Authentication tag
186  * @param[in] tLen Length of the authentication tag
187  * @return Error code
188  **/
189 
190 error_t gcmEncrypt(GcmContext *context, const uint8_t *iv,
191  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p,
192  uint8_t *c, size_t length, uint8_t *t, size_t tLen)
193 {
194  size_t k;
195  size_t n;
196  uint8_t b[16];
197  uint8_t j[16];
198  uint8_t s[16];
199 
200  //Make sure the GCM context is valid
201  if(context == NULL)
203 
204  //The length of the IV shall meet SP 800-38D requirements
205  if(ivLen < 1)
206  return ERROR_INVALID_LENGTH;
207 
208  //Check the length of the authentication tag
209  if(tLen < 4 || tLen > 16)
210  return ERROR_INVALID_LENGTH;
211 
212  //Check whether the length of the IV is 96 bits
213  if(ivLen == 12)
214  {
215  //When the length of the IV is 96 bits, the padding string is appended
216  //to the IV to form the pre-counter block
217  cryptoMemcpy(j, iv, 12);
218  STORE32BE(1, j + 12);
219  }
220  else
221  {
222  //Initialize GHASH calculation
223  cryptoMemset(j, 0, 16);
224 
225  //Length of the IV
226  n = ivLen;
227 
228  //Process the initialization vector
229  while(n > 0)
230  {
231  //The IV processed in a block-by-block fashion
232  k = MIN(n, 16);
233 
234  //Apply GHASH function
235  gcmXorBlock(j, j, iv, k);
236  gcmMul(context, j);
237 
238  //Next block
239  iv += k;
240  n -= k;
241  }
242 
243  //The string is appended with 64 additional 0 bits, followed by the
244  //64-bit representation of the length of the IV
245  cryptoMemset(b, 0, 8);
246  STORE64BE(ivLen * 8, b + 8);
247 
248  //The GHASH function is applied to the resulting string to form the
249  //pre-counter block
250  gcmXorBlock(j, j, b, 16);
251  gcmMul(context, j);
252  }
253 
254  //Compute MSB(CIPH(J(0)))
255  context->cipherAlgo->encryptBlock(context->cipherContext, j, b);
256  cryptoMemcpy(t, b, tLen);
257 
258  //Initialize GHASH calculation
259  cryptoMemset(s, 0, 16);
260  //Length of the AAD
261  n = aLen;
262 
263  //Process AAD
264  while(n > 0)
265  {
266  //Additional data are processed in a block-by-block fashion
267  k = MIN(n, 16);
268 
269  //Apply GHASH function
270  gcmXorBlock(s, s, a, k);
271  gcmMul(context, s);
272 
273  //Next block
274  a += k;
275  n -= k;
276  }
277 
278  //Length of the plaintext
279  n = length;
280 
281  //Process plaintext
282  while(n > 0)
283  {
284  //The encryption operates in a block-by-block fashion
285  k = MIN(n, 16);
286 
287  //Increment counter
288  gcmIncCounter(j);
289 
290  //Encrypt plaintext
291  context->cipherAlgo->encryptBlock(context->cipherContext, j, b);
292  gcmXorBlock(c, p, b, k);
293 
294  //Apply GHASH function
295  gcmXorBlock(s, s, c, k);
296  gcmMul(context, s);
297 
298  //Next block
299  p += k;
300  c += k;
301  n -= k;
302  }
303 
304  //Append the 64-bit representation of the length of the AAD and the
305  //ciphertext
306  STORE64BE(aLen * 8, b);
307  STORE64BE(length * 8, b + 8);
308 
309  //The GHASH function is applied to the result to produce a single output
310  //block S
311  gcmXorBlock(s, s, b, 16);
312  gcmMul(context, s);
313 
314  //Let T = MSB(GCTR(J(0), S)
315  gcmXorBlock(t, t, s, tLen);
316 
317  //Successful encryption
318  return NO_ERROR;
319 }
320 
321 
322 /**
323  * @brief Authenticated decryption using GCM
324  * @param[in] context Pointer to the GCM context
325  * @param[in] iv Initialization vector
326  * @param[in] ivLen Length of the initialization vector
327  * @param[in] a Additional authenticated data
328  * @param[in] aLen Length of the additional data
329  * @param[in] c Ciphertext to be decrypted
330  * @param[out] p Plaintext resulting from the decryption
331  * @param[in] length Total number of data bytes to be decrypted
332  * @param[in] t Authentication tag
333  * @param[in] tLen Length of the authentication tag
334  * @return Error code
335  **/
336 
337 error_t gcmDecrypt(GcmContext *context, const uint8_t *iv,
338  size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c,
339  uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
340 {
341  uint8_t mask;
342  size_t k;
343  size_t n;
344  uint8_t b[16];
345  uint8_t j[16];
346  uint8_t r[16];
347  uint8_t s[16];
348 
349  ///Make sure the GCM context is valid
350  if(context == NULL)
352 
353  //The length of the IV shall meet SP 800-38D requirements
354  if(ivLen < 1)
355  return ERROR_INVALID_LENGTH;
356 
357  //Check the length of the authentication tag
358  if(tLen < 4 || tLen > 16)
359  return ERROR_INVALID_LENGTH;
360 
361  //Check whether the length of the IV is 96 bits
362  if(ivLen == 12)
363  {
364  //When the length of the IV is 96 bits, the padding string is appended
365  //to the IV to form the pre-counter block
366  cryptoMemcpy(j, iv, 12);
367  STORE32BE(1, j + 12);
368  }
369  else
370  {
371  //Initialize GHASH calculation
372  cryptoMemset(j, 0, 16);
373 
374  //Length of the IV
375  n = ivLen;
376 
377  //Process the initialization vector
378  while(n > 0)
379  {
380  //The IV processed in a block-by-block fashion
381  k = MIN(n, 16);
382 
383  //Apply GHASH function
384  gcmXorBlock(j, j, iv, k);
385  gcmMul(context, j);
386 
387  //Next block
388  iv += k;
389  n -= k;
390  }
391 
392  //The string is appended with 64 additional 0 bits, followed by the
393  //64-bit representation of the length of the IV
394  cryptoMemset(b, 0, 8);
395  STORE64BE(ivLen * 8, b + 8);
396 
397  //The GHASH function is applied to the resulting string to form the
398  //pre-counter block
399  gcmXorBlock(j, j, b, 16);
400  gcmMul(context, j);
401  }
402 
403  //Compute MSB(CIPH(J(0)))
404  context->cipherAlgo->encryptBlock(context->cipherContext, j, b);
405  cryptoMemcpy(r, b, tLen);
406 
407  //Initialize GHASH calculation
408  cryptoMemset(s, 0, 16);
409  //Length of the AAD
410  n = aLen;
411 
412  //Process AAD
413  while(n > 0)
414  {
415  //Additional data are processed in a block-by-block fashion
416  k = MIN(n, 16);
417 
418  //Apply GHASH function
419  gcmXorBlock(s, s, a, k);
420  gcmMul(context, s);
421 
422  //Next block
423  a += k;
424  n -= k;
425  }
426 
427  //Length of the ciphertext
428  n = length;
429 
430  //Process ciphertext
431  while(n > 0)
432  {
433  //The decryption operates in a block-by-block fashion
434  k = MIN(n, 16);
435 
436  //Apply GHASH function
437  gcmXorBlock(s, s, c, k);
438  gcmMul(context, s);
439 
440  //Increment counter
441  gcmIncCounter(j);
442 
443  //Decrypt ciphertext
444  context->cipherAlgo->encryptBlock(context->cipherContext, j, b);
445  gcmXorBlock(p, c, b, k);
446 
447  //Next block
448  c += k;
449  p += k;
450  n -= k;
451  }
452 
453  //Append the 64-bit representation of the length of the AAD and the
454  //ciphertext
455  STORE64BE(aLen * 8, b);
456  STORE64BE(length * 8, b + 8);
457 
458  //The GHASH function is applied to the result to produce a single output
459  //block S
460  gcmXorBlock(s, s, b, 16);
461  gcmMul(context, s);
462 
463  //Let R = MSB(GCTR(J(0), S))
464  gcmXorBlock(r, r, s, tLen);
465 
466  //The calculated tag is bitwise compared to the received tag. The message
467  //is authenticated if and only if the tags match
468  for(mask = 0, n = 0; n < tLen; n++)
469  {
470  mask |= r[n] ^ t[n];
471  }
472 
473  //Return status code
474  return (mask == 0) ? NO_ERROR : ERROR_FAILURE;
475 }
476 
477 
478 /**
479  * @brief Multiplication operation in GF(2^128)
480  * @param[in] context Pointer to the GCM context
481  * @param[in, out] x 16-byte block to be multiplied by H
482  **/
483 
484 void gcmMul(GcmContext *context, uint8_t *x)
485 {
486  int_t i;
487  uint8_t b;
488  uint8_t c;
489  uint32_t z[4];
490 
491  //Let Z = 0
492  z[0] = 0;
493  z[1] = 0;
494  z[2] = 0;
495  z[3] = 0;
496 
497  //Fast table-driven implementation
498  for(i = 15; i >= 0; i--)
499  {
500  //Get the lower nibble
501  b = x[i] & 0x0F;
502 
503  //Multiply 4 bits at a time
504  c = z[0] & 0x0F;
505  z[0] = (z[0] >> 4) | (z[1] << 28);
506  z[1] = (z[1] >> 4) | (z[2] << 28);
507  z[2] = (z[2] >> 4) | (z[3] << 28);
508  z[3] >>= 4;
509 
510  z[0] ^= context->m[b][0];
511  z[1] ^= context->m[b][1];
512  z[2] ^= context->m[b][2];
513  z[3] ^= context->m[b][3];
514 
515  //Perform reduction
516  z[3] ^= r[c];
517 
518  //Get the upper nibble
519  b = (x[i] >> 4) & 0x0F;
520 
521  //Multiply 4 bits at a time
522  c = z[0] & 0x0F;
523  z[0] = (z[0] >> 4) | (z[1] << 28);
524  z[1] = (z[1] >> 4) | (z[2] << 28);
525  z[2] = (z[2] >> 4) | (z[3] << 28);
526  z[3] >>= 4;
527 
528  z[0] ^= context->m[b][0];
529  z[1] ^= context->m[b][1];
530  z[2] ^= context->m[b][2];
531  z[3] ^= context->m[b][3];
532 
533  //Perform reduction
534  z[3] ^= r[c];
535  }
536 
537  //Save the result
538  STORE32BE(z[3], x);
539  STORE32BE(z[2], x + 4);
540  STORE32BE(z[1], x + 8);
541  STORE32BE(z[0], x + 12);
542 }
543 
544 
545 /**
546  * @brief XOR operation
547  * @param[out] x Block resulting from the XOR operation
548  * @param[in] a First block
549  * @param[in] b Second block
550  * @param[in] n Size of the block
551  **/
552 
553 void gcmXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
554 {
555  size_t i;
556 
557  //Perform XOR operation
558  for(i = 0; i < n; i++)
559  {
560  x[i] = a[i] ^ b[i];
561  }
562 }
563 
564 
565 /**
566  * @brief Increment counter block
567  * @param[in,out] x Pointer to the counter block
568  **/
569 
570 void gcmIncCounter(uint8_t *x)
571 {
572  size_t i;
573 
574  //The function increments the right-most 32 bits of the block. The remaining
575  //left-most 96 bits remain unchanged
576  for(i = 0; i < 4; i++)
577  {
578  //Increment the current byte and propagate the carry if necessary
579  if(++(x[15 - i]) != 0)
580  {
581  break;
582  }
583  }
584 }
585 
586 #endif
#define betoh32(value)
Definition: cpu_endian.h:430
uint8_t length
Definition: dtls_misc.h:149
uint32_t m[16][4]
Precalculated table.
Definition: gcm.h:51
uint8_t a
Definition: ndp.h:410
signed int int_t
Definition: compiler_port.h:44
uint8_t b[6]
Definition: dtls_misc.h:139
uint8_t p
Definition: ndp.h:298
@ CIPHER_ALGO_TYPE_BLOCK
Definition: crypto.h:1069
size_t blockSize
Definition: crypto.h:1155
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1159
error_t gcmDecrypt(GcmContext *context, const uint8_t *iv, size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
Authenticated decryption using GCM.
Definition: gcm.c:337
uint32_t r
Definition: ndp.h:345
uint8_t t
Definition: llmnr_common.h:81
uint8_t h
Definition: ndp.h:300
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:42
CipherAlgoType type
Definition: crypto.h:1154
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ ERROR_INVALID_LENGTH
Definition: error.h:109
General definitions for cryptographic algorithms.
uint8_t mask
Definition: web_socket.h:317
const CipherAlgo * cipherAlgo
Cipher algorithm.
Definition: gcm.h:49
#define MIN(a, b)
Definition: os_port.h:62
uint8_t z
Definition: dns_common.h:175
#define cryptoMemset(p, value, length)
Definition: crypto.h:636
void gcmIncCounter(uint8_t *x)
Increment counter block.
Definition: gcm.c:570
GCM context.
Definition: gcm.h:47
#define STORE64BE(a, p)
Definition: cpu_endian.h:306
error_t gcmEncrypt(GcmContext *context, const uint8_t *iv, size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *p, uint8_t *c, size_t length, uint8_t *t, size_t tLen)
Authenticated encryption using GCM.
Definition: gcm.c:190
uint8_t n
Galois/Counter Mode (GCM)
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:642
error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo, void *cipherContext)
Initialize GCM context.
Definition: gcm.c:78
void gcmXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
XOR operation.
Definition: gcm.c:553
uint8_t s
Common interface for encryption algorithms.
Definition: crypto.h:1150
void gcmMul(GcmContext *context, uint8_t *x)
Multiplication operation in GF(2^128)
Definition: gcm.c:484
uint8_t reverseInt4(uint8_t value)
Reverse bit order in a 4-bit word.
Definition: cpu_endian.c:75
unsigned int uint_t
Definition: compiler_port.h:45
void * cipherContext
Cipher algorithm context.
Definition: gcm.h:50
#define STORE32BE(a, p)
Definition: cpu_endian.h:270
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:513
Debugging facilities.