gmac.c
Go to the documentation of this file.
1 /**
2  * @file gmac.c
3  * @brief GMAC (Galois Message Authentication Code)
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  * GMAC is a message authentication code (MAC) based on GCM. Refer to
30  * SP 800-38D for more details
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 1.9.6
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/crypto.h"
41 #include "mac/gmac.h"
42 
43 //Check crypto library configuration
44 #if (GMAC_SUPPORT == ENABLED)
45 
46 //Reduction table
47 static const uint32_t r[16] =
48 {
49  0x00000000,
50  0x1C200000,
51  0x38400000,
52  0x24600000,
53  0x70800000,
54  0x6CA00000,
55  0x48C00000,
56  0x54E00000,
57  0xE1000000,
58  0xFD200000,
59  0xD9400000,
60  0xC5600000,
61  0x91800000,
62  0x8DA00000,
63  0xA9C00000,
64  0xB5E00000
65 };
66 
67 
68 /**
69  * @brief Compute GMAC using the specified cipher algorithm
70  * @param[in] cipher Cipher algorithm used to compute GMAC
71  * @param[in] key Pointer to the secret key
72  * @param[in] keyLen Length of the secret key
73  * @param[in] iv Initialization vector
74  * @param[in] ivLen Length of the initialization vector
75  * @param[in] data Pointer to the input message
76  * @param[in] dataLen Length of the input data
77  * @param[out] mac Calculated MAC value
78  * @param[in] macLen Expected length of the MAC
79  * @return Error code
80  **/
81 
82 error_t gmacCompute(const CipherAlgo *cipher, const void *key, size_t keyLen,
83  const uint8_t *iv, size_t ivLen, const void *data, size_t dataLen,
84  uint8_t *mac, size_t macLen)
85 {
86  error_t error;
87  GmacContext *context;
88 
89  //Allocate a memory buffer to hold the GMAC context
90  context = cryptoAllocMem(sizeof(GmacContext));
91 
92  //Successful memory allocation?
93  if(context != NULL)
94  {
95  //Initialize the GMAC context
96  error = gmacInit(context, cipher, key, keyLen);
97 
98  //Check status code
99  if(!error)
100  {
101  //Reset GMAC context
102  error = gmacReset(context, iv, ivLen);
103  }
104 
105  //Check status code
106  if(!error)
107  {
108  //Digest the message
109  gmacUpdate(context, data, dataLen);
110  //Finalize the GMAC computation
111  error = gmacFinal(context, mac, macLen);
112  }
113 
114  //Free previously allocated memory
115  cryptoFreeMem(context);
116  }
117  else
118  {
119  //Failed to allocate memory
120  error = ERROR_OUT_OF_MEMORY;
121  }
122 
123  //Return status code
124  return error;
125 }
126 
127 
128 /**
129  * @brief Initialize GMAC calculation
130  * @param[in] context Pointer to the GMAC context to initialize
131  * @param[in] cipher Cipher algorithm used to compute GMAC
132  * @param[in] key Pointer to the secret key
133  * @param[in] keyLen Length of the secret key
134  * @return Error code
135  **/
136 
137 error_t gmacInit(GmacContext *context, const CipherAlgo *cipher,
138  const void *key, size_t keyLen)
139 {
140  error_t error;
141  uint_t i;
142  uint_t j;
143  uint32_t c;
144  uint32_t h[4];
145 
146  //GMAC supports only symmetric block ciphers whose block size is 128 bits
147  if(cipher->type != CIPHER_ALGO_TYPE_BLOCK || cipher->blockSize != 16)
149 
150  //Cipher algorithm used to compute GMAC
151  context->cipher = cipher;
152 
153  //Initialize cipher context
154  error = cipher->init(context->cipherContext, key, keyLen);
155  //Any error to report?
156  if(error)
157  return error;
158 
159  //Let H = 0
160  h[0] = 0;
161  h[1] = 0;
162  h[2] = 0;
163  h[3] = 0;
164 
165  //Generate the hash subkey H
166  context->cipher->encryptBlock(context->cipherContext,
167  (uint8_t *) h, (uint8_t *) h);
168 
169  //Pre-compute M(0) = H * 0
170  j = reverseInt4(0);
171  context->m[j][0] = 0;
172  context->m[j][1] = 0;
173  context->m[j][2] = 0;
174  context->m[j][3] = 0;
175 
176  //Pre-compute M(1) = H * 1
177  j = reverseInt4(1);
178  context->m[j][0] = betoh32(h[3]);
179  context->m[j][1] = betoh32(h[2]);
180  context->m[j][2] = betoh32(h[1]);
181  context->m[j][3] = betoh32(h[0]);
182 
183  //Pre-compute all 4-bit multiples of H
184  for(i = 2; i < 16; i++)
185  {
186  //Odd value?
187  if(i & 1)
188  {
189  //Compute M(i) = M(i - 1) + H
190  j = reverseInt4(i - 1);
191  h[0] = context->m[j][0];
192  h[1] = context->m[j][1];
193  h[2] = context->m[j][2];
194  h[3] = context->m[j][3];
195 
196  //An addition in GF(2^128) is identical to a bitwise
197  //exclusive-OR operation
198  j = reverseInt4(1);
199  h[0] ^= context->m[j][0];
200  h[1] ^= context->m[j][1];
201  h[2] ^= context->m[j][2];
202  h[3] ^= context->m[j][3];
203  }
204  //Even value?
205  else
206  {
207  //Compute M(i) = M(i / 2) * x
208  j = reverseInt4(i / 2);
209  h[0] = context->m[j][0];
210  h[1] = context->m[j][1];
211  h[2] = context->m[j][2];
212  h[3] = context->m[j][3];
213 
214  //The multiplication of a polynomial by x in GF(2^128) corresponds
215  //to a shift of indices
216  c = h[0] & 0x01;
217  h[0] = (h[0] >> 1) | (h[1] << 31);
218  h[1] = (h[1] >> 1) | (h[2] << 31);
219  h[2] = (h[2] >> 1) | (h[3] << 31);
220  h[3] >>= 1;
221 
222  //If the highest term of the result is equal to one, then perform
223  //reduction
224  h[3] ^= r[reverseInt4(1)] & ~(c - 1);
225  }
226 
227  //Save M(i)
228  j = reverseInt4(i);
229  context->m[j][0] = h[0];
230  context->m[j][1] = h[1];
231  context->m[j][2] = h[2];
232  context->m[j][3] = h[3];
233  }
234 
235  //Clear input buffer
236  cryptoMemset(context->buffer, 0, context->cipher->blockSize);
237  //Number of bytes in the buffer
238  context->bufferLength = 0;
239  //Total number of bytes
240  context->totalLength = 0;
241 
242  //Initialize MAC value
243  cryptoMemset(context->mac, 0, context->cipher->blockSize);
244 
245  //Successful initialization
246  return NO_ERROR;
247 }
248 
249 
250 /**
251  * @brief Reset GMAC context
252  * @param[in] context Pointer to the GMAC context
253  * @param[in] iv Initialization vector
254  * @param[in] ivLen Length of the initialization vector
255  * @return Error code
256  **/
257 
258 error_t gmacReset(GmacContext *context, const uint8_t *iv, size_t ivLen)
259 {
260  size_t k;
261  size_t n;
262  uint8_t b[16];
263  uint8_t j[16];
264 
265  //The length of the IV shall meet SP 800-38D requirements
266  if(ivLen < 1)
268 
269  //Check whether the length of the IV is 96 bits
270  if(ivLen == 12)
271  {
272  //When the length of the IV is 96 bits, the padding string is
273  //appended to the IV to form the pre-counter block
274  cryptoMemcpy(j, iv, 12);
275  STORE32BE(1, j + 12);
276  }
277  else
278  {
279  //Initialize GHASH calculation
280  cryptoMemset(j, 0, 16);
281 
282  //Length of the IV
283  n = ivLen;
284 
285  //Process the initialization vector
286  while(n > 0)
287  {
288  //The IV processed in a block-by-block fashion
289  k = MIN(n, 16);
290 
291  //Apply GHASH function
292  gmacXorBlock(j, j, iv, k);
293  gmacMul(context, j);
294 
295  //Next block
296  iv += k;
297  n -= k;
298  }
299 
300  //The string is appended with 64 additional 0 bits, followed by the
301  //64-bit representation of the length of the IV
302  cryptoMemset(b, 0, 8);
303  STORE64BE(ivLen * 8, b + 8);
304 
305  //The GHASH function is applied to the resulting string to form the
306  //pre-counter block
307  gmacXorBlock(j, j, b, 16);
308  gmacMul(context, j);
309  }
310 
311  //Compute MSB(CIPH(J(0)))
312  context->cipher->encryptBlock(context->cipherContext, j, b);
313  cryptoMemcpy(context->mac, b, 16);
314 
315  //Initialize GHASH calculation
316  cryptoMemset(context->s, 0, 16);
317 
318  //Clear input buffer
319  cryptoMemset(context->buffer, 0, context->cipher->blockSize);
320  //Number of bytes in the buffer
321  context->bufferLength = 0;
322 
323  //Successful processing
324  return NO_ERROR;
325 }
326 
327 
328 /**
329  * @brief Update the GMAC context with a portion of the message being hashed
330  * @param[in] context Pointer to the GMAC context
331  * @param[in] data Pointer to the input data
332  * @param[in] dataLen Length of the buffer
333  **/
334 
335 void gmacUpdate(GmacContext *context, const void *data, size_t dataLen)
336 {
337  size_t n;
338 
339  //Process the incoming data
340  while(dataLen > 0)
341  {
342  //The message is partitioned into complete blocks
343  n = MIN(dataLen, 16 - context->bufferLength);
344 
345  //Copy the data to the buffer
346  cryptoMemcpy(context->buffer + context->bufferLength, data, n);
347  //Update the length of the buffer
348  context->bufferLength += n;
349  //Update the total number of bytes
350  context->totalLength += n;
351 
352  //Advance the data pointer
353  data = (uint8_t *) data + n;
354  //Remaining bytes to process
355  dataLen -= n;
356 
357  //Process message block by block
358  if(context->bufferLength == 16)
359  {
360  //Apply GHASH function
361  gmacXorBlock(context->s, context->s, context->buffer, 16);
362  gmacMul(context, context->s);
363 
364  //Empty the buffer
365  context->bufferLength = 0;
366  }
367  }
368 }
369 
370 
371 /**
372  * @brief Finish the GMAC calculation
373  * @param[in] context Pointer to the GMAC context
374  * @param[out] mac Calculated MAC value
375  * @param[in] macLen Expected length of the MAC
376  **/
377 
378 error_t gmacFinal(GmacContext *context, uint8_t *mac, size_t macLen)
379 {
380  //Check the length of the MAC
381  if(macLen < 4 || macLen > 16)
383 
384  //Process the last block of the message
385  if(context->bufferLength > 0)
386  {
387  //Apply GHASH function
388  gmacXorBlock(context->s, context->s, context->buffer, context->bufferLength);
389  gmacMul(context, context->s);
390  }
391 
392  //Append the 64-bit representation of the length of the message followed
393  //by 64 additional 0 bits
394  STORE64BE(context->totalLength * 8, context->buffer);
395  cryptoMemset(context->buffer + 8, 0, 8);
396 
397  //The GHASH function is applied to the result to produce a single output block S
398  gmacXorBlock(context->s, context->s, context->buffer, 16);
399  gmacMul(context, context->s);
400 
401  //Let T = GCTR(J(0), S)
402  gmacXorBlock(context->mac, context->mac, context->s, 16);
403 
404  //Copy the resulting MAC value
405  if(mac != NULL)
406  {
407  //Output MSB(T)
408  cryptoMemcpy(mac, context->mac, macLen);
409  }
410 
411  //Successful processing
412  return NO_ERROR;
413 }
414 
415 
416 /**
417  * @brief Multiplication operation in GF(2^128)
418  * @param[in] context Pointer to the GMAC context
419  * @param[in, out] x 16-byte block to be multiplied by H
420  **/
421 
422 void gmacMul(GmacContext *context, uint8_t *x)
423 {
424  int_t i;
425  uint8_t b;
426  uint8_t c;
427  uint32_t z[4];
428 
429  //Let Z = 0
430  z[0] = 0;
431  z[1] = 0;
432  z[2] = 0;
433  z[3] = 0;
434 
435  //Fast table-driven implementation
436  for(i = 15; i >= 0; i--)
437  {
438  //Get the lower nibble
439  b = x[i] & 0x0F;
440 
441  //Multiply 4 bits at a time
442  c = z[0] & 0x0F;
443  z[0] = (z[0] >> 4) | (z[1] << 28);
444  z[1] = (z[1] >> 4) | (z[2] << 28);
445  z[2] = (z[2] >> 4) | (z[3] << 28);
446  z[3] >>= 4;
447 
448  z[0] ^= context->m[b][0];
449  z[1] ^= context->m[b][1];
450  z[2] ^= context->m[b][2];
451  z[3] ^= context->m[b][3];
452 
453  //Perform reduction
454  z[3] ^= r[c];
455 
456  //Get the upper nibble
457  b = (x[i] >> 4) & 0x0F;
458 
459  //Multiply 4 bits at a time
460  c = z[0] & 0x0F;
461  z[0] = (z[0] >> 4) | (z[1] << 28);
462  z[1] = (z[1] >> 4) | (z[2] << 28);
463  z[2] = (z[2] >> 4) | (z[3] << 28);
464  z[3] >>= 4;
465 
466  z[0] ^= context->m[b][0];
467  z[1] ^= context->m[b][1];
468  z[2] ^= context->m[b][2];
469  z[3] ^= context->m[b][3];
470 
471  //Perform reduction
472  z[3] ^= r[c];
473  }
474 
475  //Save the result
476  STORE32BE(z[3], x);
477  STORE32BE(z[2], x + 4);
478  STORE32BE(z[1], x + 8);
479  STORE32BE(z[0], x + 12);
480 }
481 
482 
483 /**
484  * @brief XOR operation
485  * @param[out] x Block resulting from the XOR operation
486  * @param[in] a First block
487  * @param[in] b Second block
488  * @param[in] n Size of the block
489  **/
490 
491 void gmacXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
492 {
493  size_t i;
494 
495  //Perform XOR operation
496  for(i = 0; i < n; i++)
497  {
498  x[i] = a[i] ^ b[i];
499  }
500 }
501 
502 
503 /**
504  * @brief Increment counter block
505  * @param[in,out] x Pointer to the counter block
506  **/
507 
508 void gmacIncCounter(uint8_t *x)
509 {
510  size_t i;
511 
512  //The function increments the right-most 32 bits of the block. The remaining
513  //left-most 96 bits remain unchanged
514  for(i = 0; i < 4; i++)
515  {
516  //Increment the current byte and propagate the carry if necessary
517  if(++(x[15 - i]) != 0)
518  {
519  break;
520  }
521  }
522 }
523 
524 #endif
#define betoh32(value)
Definition: cpu_endian.h:430
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
const CipherAlgo * cipher
Definition: gmac.h:104
size_t blockSize
Definition: crypto.h:1155
error_t gmacInit(GmacContext *context, const CipherAlgo *cipher, const void *key, size_t keyLen)
Initialize GMAC calculation.
Definition: gmac.c:137
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1159
uint32_t r
Definition: ndp.h:345
CipherAlgoInit init
Definition: crypto.h:1156
error_t gmacCompute(const CipherAlgo *cipher, const void *key, size_t keyLen, const uint8_t *iv, size_t ivLen, const void *data, size_t dataLen, uint8_t *mac, size_t macLen)
Compute GMAC using the specified cipher algorithm.
Definition: gmac.c:82
uint8_t h
Definition: ndp.h:300
void gmacMul(GmacContext *context, uint8_t *x)
Multiplication operation in GF(2^128)
Definition: gmac.c:422
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:42
CipherAlgoType type
Definition: crypto.h:1154
General definitions for cryptographic algorithms.
void gmacIncCounter(uint8_t *x)
Increment counter block.
Definition: gmac.c:508
#define MIN(a, b)
Definition: os_port.h:62
uint8_t s[16]
Definition: gmac.h:107
uint8_t cipherContext[MAX_CIPHER_CONTEXT_SIZE]
Definition: gmac.h:105
uint8_t z
Definition: dns_common.h:175
#define cryptoMemset(p, value, length)
Definition: crypto.h:636
#define STORE64BE(a, p)
Definition: cpu_endian.h:306
uint8_t n
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:642
#define cryptoFreeMem(p)
Definition: crypto.h:630
GMAC (Galois Message Authentication Code)
void gmacUpdate(GmacContext *context, const void *data, size_t dataLen)
Update the GMAC context with a portion of the message being hashed.
Definition: gmac.c:335
Common interface for encryption algorithms.
Definition: crypto.h:1150
GMAC algorithm context.
Definition: gmac.h:102
#define cryptoAllocMem(size)
Definition: crypto.h:625
uint8_t buffer[16]
Definition: gmac.h:108
error_t gmacReset(GmacContext *context, const uint8_t *iv, size_t ivLen)
Reset GMAC context.
Definition: gmac.c:258
uint64_t totalLength
Definition: gmac.h:110
void gmacXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
XOR operation.
Definition: gmac.c:491
uint8_t reverseInt4(uint8_t value)
Reverse bit order in a 4-bit word.
Definition: cpu_endian.c:75
uint8_t mac[16]
Definition: gmac.h:111
unsigned int uint_t
Definition: compiler_port.h:45
error_t gmacFinal(GmacContext *context, uint8_t *mac, size_t macLen)
Finish the GMAC calculation.
Definition: gmac.c:378
uint8_t data[]
Definition: dtls_misc.h:176
size_t bufferLength
Definition: gmac.h:109
#define STORE32BE(a, p)
Definition: cpu_endian.h:270
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:513
uint32_t m[16][4]
Definition: gmac.h:106