esp_packet_encrypt.c
Go to the documentation of this file.
1 /**
2  * @file esp_packet_encrypt.c
3  * @brief ESP packet encryption
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2022-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneIPSEC 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  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL ESP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ipsec/ipsec.h"
36 #include "esp/esp.h"
37 #include "esp/esp_packet_encrypt.h"
40 #include "aead/aead_algorithms.h"
41 #include "debug.h"
42 
43 //Check IPsec library configuration
44 #if (ESP_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief Encrypt an outgoing ESP packet
49  * @param[in] context Pointer to the IPsec context
50  * @param[in] sa Pointer to the SAD entry
51  * @param[in] espHeader Pointer to the ESP header
52  * @param[in,out] payload Payload data to be encrypted
53  * @param[in,out] payloadLen Actual length of the payload data
54  * @param[in] nextHeader Value of the next header field
55  * @return Error code
56  **/
57 
59  const EspHeader *espHeader, uint8_t *payload, size_t *payloadLen,
60  uint8_t nextHeader)
61 {
62  error_t error;
63  size_t length;
64  uint8_t *data;
65  uint8_t *icv;
66  const CipherAlgo *cipherAlgo;
67 
68  //Get the length of the payload data, in bytes
69  length = *payloadLen;
70 
71  //Point to the plaintext
72  data = payload + sa->ivLen;
73 
74  //The transmitted ESP trailer consists of the Padding, Pad Length, and
75  //Next Header fields (refer to RFC 4303, section 2)
77 
78  //Point to the Integrity Checksum Value (ICV)
79  icv = payload + sa->ivLen + length;
80 
81  //The SAD entry specifies the algorithms and keys to be employed for
82  //encryption (refer to RFC 4303, section 3.4.2)
83  cipherAlgo = sa->cipherAlgo;
84 
85 #if (ESP_CBC_SUPPORT == ENABLED)
86  //CBC cipher mode?
87  if(sa->cipherMode == CIPHER_MODE_CBC)
88  {
89  uint8_t iv[MAX_CIPHER_BLOCK_SIZE];
90 
91  //The IV must be chosen at random, and must be unpredictable
92  error = context->prngAlgo->read(context->prngContext, iv, sa->ivLen);
93  //Any error to report?
94  if(error)
95  return error;
96 
97  //The IV field must be the same size as the block size of the cipher
98  //algorithm being used
99  osMemcpy(payload, iv, sa->ivLen);
100 
101  //Initialize cipher context
102  error = cipherAlgo->init(&sa->cipherContext, sa->encKey, sa->encKeyLen);
103  //Any error to report?
104  if(error)
105  return error;
106 
107  //Perform CBC encryption
108  error = cbcEncrypt(cipherAlgo, &sa->cipherContext, iv, data, data,
109  length);
110  //Any error to report?
111  if(error)
112  return error;
113 
114  //The ICV is a variable-length field computed over the ESP header,
115  //Payload, and ESP trailer fields (refer to RFC 4303, section 2.8)
116  error = espComputeChecksum(context, sa, espHeader, payload,
117  sa->ivLen + length, icv);
118  //Any error to report?
119  if(error)
120  return error;
121  }
122  else
123 #endif
124 #if (ESP_CTR_SUPPORT == ENABLED)
125  //CTR cipher mode?
126  if(sa->cipherMode == CIPHER_MODE_CTR)
127  {
128  uint8_t counter[16];
129 
130  //The IV must be chosen by the encryptor in a manner that ensures that
131  //the same IV value is used only once for a given key (refer to RFC 3686,
132  //section 3.1)
133  espGenerateIv(sa->iv);
134 
135  //The IV field must be 8 octets when the AES-CTR algorithm is used for
136  //IKEv2 encryption
137  osMemcpy(payload, sa->iv, 8);
138 
139  //The counter block is 128 bits, including a 4-octet nonce, 8-octet IV,
140  //and 4-octet block counter, in that order (refer to RFC 3686, section 4)
141  osMemcpy(counter, sa->encKey + sa->encKeyLen, 4);
142  osMemcpy(counter + 4, sa->iv, 8);
143 
144  //The block counter begins with the value of one and increments by one
145  //to generate the next portion of the key stream
146  STORE32BE(1, counter + 12);
147 
148  //Initialize cipher context
149  error = cipherAlgo->init(&sa->cipherContext, sa->encKey, sa->encKeyLen);
150  //Any error to report?
151  if(error)
152  return error;
153 
154  //Perform CTR encryption
155  error = ctrEncrypt(cipherAlgo, &sa->cipherContext,
156  cipherAlgo->blockSize * 8, counter, data, data, length);
157  //Any error to report?
158  if(error)
159  return error;
160 
161  //The ICV is a variable-length field computed over the ESP header,
162  //Payload, and ESP trailer fields (refer to RFC 4303, section 2.8)
163  error = espComputeChecksum(context, sa, espHeader, payload,
164  sa->ivLen + length, icv);
165  //Any error to report?
166  if(error)
167  return error;
168  }
169  else
170 #endif
171 #if (ESP_CCM_8_SUPPORT == ENABLED || ESP_CCM_12_SUPPORT == ENABLED || \
172  ESP_CCM_16_SUPPORT == ENABLED)
173  //CCM AEAD cipher?
174  if(sa->cipherMode == CIPHER_MODE_CCM)
175  {
176  size_t aadLen;
177  uint8_t aad[12];
178  uint8_t nonce[11];
179 
180  //The IV must be chosen by the encryptor in a manner that ensures that
181  //the same IV value is used only once for a given key (refer to RFC 4309,
182  //section 3.1)
183  espGenerateIv(sa->iv);
184 
185  //The Initialization Vector (IV) must be eight octets
186  osMemcpy(payload, sa->iv, 8);
187 
188  //The components of the nonce are the salt with the IV (refer to RFC 4309,
189  //section 4)
190  osMemcpy(nonce, sa->encKey + sa->encKeyLen, 3);
191  osMemcpy(nonce + 3, sa->iv, 8);
192 
193  //Two formats of the AAD are defined (refer to RFC 4309, section 5)
194  if(sa->esn)
195  {
196  //AAD Format with 64-bit sequence number
197  osMemcpy(aad, (uint8_t *) &espHeader->spi, 4);
198  STORE64BE(sa->seqNum, aad + 4);
199  aadLen = 12;
200  }
201  else
202  {
203  //AAD Format with 32-bit sequence number
204  osMemcpy(aad, espHeader, 8);
205  aadLen = 8;
206  }
207 
208  //Initialize cipher context
209  error = cipherAlgo->init(&sa->cipherContext, sa->encKey, sa->encKeyLen);
210  //Any error to report?
211  if(error)
212  return error;
213 
214  //Authenticated encryption using CCM
215  error = ccmEncrypt(sa->cipherAlgo, &sa->cipherContext, nonce, 11, aad,
216  aadLen, data, data, length, icv, sa->icvLen);
217  //Any error to report?
218  if(error)
219  return error;
220  }
221  else
222 #endif
223 #if (ESP_GCM_8_SUPPORT == ENABLED || ESP_GCM_12_SUPPORT == ENABLED || \
224  ESP_GCM_16_SUPPORT == ENABLED)
225  //GCM AEAD cipher?
226  if(sa->cipherMode == CIPHER_MODE_GCM)
227  {
228  size_t aadLen;
229  uint8_t aad[12];
230  uint8_t nonce[12];
231  GcmContext gcmContext;
232 
233  //For a given key, the IV must not repeat. The encrypter can use any IV
234  //generation method that meets the uniqueness requirement, without
235  //coordinating with the decrypter (refer to RFC 4106, section 3.1)
236  espGenerateIv(sa->iv);
237 
238  //The Initialization Vector (IV) must be eight octets
239  osMemcpy(payload, sa->iv, 8);
240 
241  //The components of the nonce are the salt with the IV (refer to RFC 4106,
242  //section 4)
243  osMemcpy(nonce, sa->encKey + sa->encKeyLen, 4);
244  osMemcpy(nonce + 4, sa->iv, 8);
245 
246  //Two formats of the AAD are defined (refer to RFC 4106, section 5)
247  if(sa->esn)
248  {
249  //AAD Format with 64-bit sequence number
250  osMemcpy(aad, (uint8_t *) &espHeader->spi, 4);
251  STORE64BE(sa->seqNum, aad + 4);
252  aadLen = 12;
253  }
254  else
255  {
256  //AAD Format with 32-bit sequence number
257  osMemcpy(aad, espHeader, 8);
258  aadLen = 8;
259  }
260 
261  //Initialize cipher context
262  error = cipherAlgo->init(&sa->cipherContext, sa->encKey, sa->encKeyLen);
263  //Any error to report?
264  if(error)
265  return error;
266 
267  //Initialize GCM context
268  error = gcmInit(&gcmContext, sa->cipherAlgo, &sa->cipherContext);
269  //Any error to report?
270  if(error)
271  return error;
272 
273  //Authenticated encryption using GCM
274  error = gcmEncrypt(&gcmContext, nonce, 12, aad, aadLen, data, data,
275  length, icv, sa->icvLen);
276  //Any error to report?
277  if(error)
278  return error;
279  }
280  else
281 #endif
282 #if (ESP_CHACHA20_POLY1305_SUPPORT == ENABLED)
283  //ChaCha20Poly1305 AEAD cipher?
284  if(sa->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
285  {
286  size_t aadLen;
287  uint8_t aad[12];
288  uint8_t nonce[12];
289 
290  //The IV must be unique for each invocation for a particular security
291  //association (SA) but does not need to be unpredictable (refer to
292  //RFC 7634, section 2)
293  espGenerateIv(sa->iv);
294 
295  //The IV is 64 bits, and is included explicitly in the Encrypted payload
296  osMemcpy(payload, sa->iv, 8);
297 
298  //The 96-bit nonce is formed from a concatenation of the 32-bit salt and
299  //the 64-bit IV (refer to RFC 7634, section 2)
300  osMemcpy(nonce, sa->encKey + sa->encKeyLen, 4);
301  osMemcpy(nonce + 4, sa->iv, 8);
302 
303  //Extended sequence numbers?
304  if(sa->esn)
305  {
306  //For SAs with ESN, the AAD is 12 octets: a 4-octet SPI followed by an
307  //8-octet sequence number as a 64-bit integer in big-endian byte order
308  //(refer to RFC 7634, section 2.1)
309  osMemcpy(aad, (uint8_t *) &espHeader->spi, 4);
310  STORE64BE(sa->seqNum, aad + 4);
311  aadLen = 12;
312  }
313  else
314  {
315  //For SAs with 32-bit sequence numbers, the AAD is 8 octets: a 4-octet
316  //SPI followed by a 4-octet sequence number ordered exactly as it is in
317  //the packet
318  osMemcpy(aad, espHeader, 8);
319  aadLen = 8;
320  }
321 
322  //Authenticated encryption using ChaCha20Poly1305
323  error = chacha20Poly1305Encrypt(sa->encKey, sa->encKeyLen, nonce, 12,
324  aad, aadLen, data, data, length, icv, sa->icvLen);
325  //Any error to report?
326  if(error)
327  return error;
328  }
329  else
330 #endif
331  //Invalid cipher mode?
332  {
333  //The specified cipher mode is not supported
335  }
336 
337  //Total length of the encrypted packet
338  *payloadLen = sa->ivLen + length + sa->icvLen;
339 
340  //Successful processing
341  return NO_ERROR;
342 }
343 
344 
345 /**
346  * @brief Compute ICV checksum
347  * @param[in] context Pointer to the IPsec context
348  * @param[in] sa Pointer to the SAD entry
349  * @param[in] espHeader Pointer to the ESP header
350  * @param[in] payload Pointer to the payload data
351  * @param[in] length Length of the packet, in bytes
352  * @param[out] icv Integrity Checksum Value (ICV)
353  * @return Error code
354  **/
355 
357  const EspHeader *espHeader, const uint8_t *payload, size_t length,
358  uint8_t *icv)
359 {
360  error_t error;
361 
362 #if (ESP_HMAC_SUPPORT == ENABLED)
363  //HMAC integrity algorithm?
364  if(sa->authHashAlgo != NULL)
365  {
366  HmacContext *hmacContext;
367 
368  //Point to the HMAC context
369  hmacContext = &context->hmacContext;
370 
371  //The SAD entry specifies the algorithm employed for ICV computation
372  error = hmacInit(hmacContext, sa->authHashAlgo, sa->authKey,
373  sa->authKeyLen);
374 
375  //Check status code
376  if(!error)
377  {
378  //The checksum must be computed over the encrypted message. Its length
379  //is determined by the integrity algorithm negotiated
380  hmacUpdate(hmacContext, espHeader, sizeof(EspHeader));
381  hmacUpdate(hmacContext, payload, length);
382 
383  //Extended sequence number?
384  if(sa->esn)
385  {
386  //The high-order 32 bits are maintained as part of the sequence
387  //number counter by both transmitter and receiver and are included
388  //in the computation of the ICV (refer to RFC 4303, section 2.2.1)
389  uint32_t h = htonl(sa->seqNum >> 32);
390  hmacUpdate(hmacContext, (uint8_t *) &h, 4);
391  }
392 
393  //Finalize HMAC computation
394  hmacFinal(hmacContext, NULL);
395 
396  //Copy the resulting checksum value
397  osMemcpy(icv, hmacContext->digest, sa->icvLen);
398  }
399  }
400  else
401 #endif
402 #if (ESP_CMAC_SUPPORT == ENABLED)
403  //CMAC integrity algorithm?
404  if(sa->authCipherAlgo != NULL)
405  {
406  CmacContext *cmacContext;
407 
408  //Point to the CMAC context
409  cmacContext = &context->cmacContext;
410 
411  //The SAD entry specifies the algorithm employed for ICV computation
412  error = cmacInit(cmacContext, sa->authCipherAlgo, sa->authKey,
413  sa->authKeyLen);
414 
415  //Check status code
416  if(!error)
417  {
418  //The checksum must be computed over the encrypted message. Its length
419  //is determined by the integrity algorithm negotiated
420  cmacUpdate(cmacContext, espHeader, sizeof(EspHeader));
421  cmacUpdate(cmacContext, payload, length);
422 
423  //Extended sequence number?
424  if(sa->esn)
425  {
426  //The high-order 32 bits are maintained as part of the sequence
427  //number counter by both transmitter and receiver and are included
428  //in the computation of the ICV (refer to RFC 4303, section 2.2.1)
429  uint32_t h = htonl(sa->seqNum >> 32);
430  cmacUpdate(cmacContext, (uint8_t *) &h, 4);
431  }
432 
433  //Finalize CMAC computation
434  cmacFinal(cmacContext, icv, sa->icvLen);
435  }
436  }
437  else
438 #endif
439  //Unknown integrity algorithm?
440  {
441  //Report an error
442  error = ERROR_FAILURE;
443  }
444 
445  //Return status code
446  return error;
447 }
448 
449 
450 /**
451  * @brief Append ESP trailer
452  * @param[in] sa Pointer to the SAD entry
453  * @param[in] data Pointer to the payload data
454  * @param[in] length Length of the payload data, in bytes
455  * @param[in] nextHeader Value of the next header field
456  * @return Length of the resulting payload data
457  **/
458 
459 size_t espAddTrailer(IpsecSadEntry *sa, uint8_t *data, size_t length,
460  uint8_t nextHeader)
461 {
462  size_t i;
463  size_t n;
464  EspTrailer *espTrailer;
465 
466 #if (ESP_CBC_SUPPORT == ENABLED)
467  //CBC cipher mode?
468  if(sa->cipherMode == CIPHER_MODE_CBC)
469  {
470  //For the purpose of ensuring that data to be encrypted are a multiple
471  //of the algorithm's block size, the padding computation applies to the
472  //Payload Data exclusive of any IV, but including the ESP trailer fields
473  //(refer to RFC 4303, section 2.4)
474  n = (length + sizeof(EspTrailer)) % sa->cipherAlgo->blockSize;
475 
476  //Check whether any padding is required
477  if(n != 0)
478  {
479  //Calculate the length of the Padding field
480  n = sa->cipherAlgo->blockSize - n;
481  }
482  }
483  else
484 #endif
485  //AEAD cipher mode?
486  {
487  //Implementations that do not seek to hide the length of the plaintext
488  //should use the minimum amount of padding required, which will be less
489  //than four octets (refer to RFC 4106, section 3.2)
490  n = (length + sizeof(EspTrailer)) % 4;
491 
492  //Check whether any padding is required
493  if(n != 0)
494  {
495  //Calculate the length of the Padding field
496  n = 4 - n;
497  }
498  }
499 
500  //Padding bytes make up a monotonically increasing sequence
501  for(i = 1; i <= n; i++)
502  {
503  data[length++] = (uint8_t) i;
504  }
505 
506  //Point to the ESP trailer
507  espTrailer = (EspTrailer *) (data + length);
508 
509  //The Pad Length field indicates the number of pad bytes immediately
510  //preceding it in the Padding field (refer to RFC 4303, section 2.5)
511  espTrailer->padLength = n;
512 
513  //The Next Header field identifies the type of data contained in the
514  //payload data (refer to RFC 4303, section 2.6)
515  espTrailer->nextHeader = nextHeader;
516 
517  //Return the length of the resulting payload data
518  return length + sizeof(EspTrailer);
519 }
520 
521 
522 /**
523  * @brief IV generation
524  * @param[in,out] iv Pointer to the 8-octet initialization vector
525  **/
526 
527 void espGenerateIv(uint8_t *iv)
528 {
529  uint16_t temp;
530 
531  //The encryptor may generate the IV in any manner that ensures uniqueness.
532  //Common approaches to IV generation include incrementing a counter for each
533  //packet and linear feedback shift registers (refer to RFC 5282, section 3.1)
534  temp = iv[7] + 1;
535  iv[7] = temp & 0xFF;
536  temp = (temp >> 8) + iv[6];
537  iv[6] = temp & 0xFF;
538  temp = (temp >> 8) + iv[5];
539  iv[5] = temp & 0xFF;
540  temp = (temp >> 8) + iv[4];
541  iv[4] = temp & 0xFF;
542  temp = (temp >> 8) + iv[3];
543  iv[3] = temp & 0xFF;
544  temp = (temp >> 8) + iv[2];
545  iv[2] = temp & 0xFF;
546  temp = (temp >> 8) + iv[1];
547  iv[1] = temp & 0xFF;
548  temp = (temp >> 8) + iv[0];
549  iv[0] = temp & 0xFF;
550 }
551 
552 #endif
uint8_t icv[]
Definition: ah.h:145
__weak_func error_t cbcEncrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *p, uint8_t *c, size_t length)
CBC encryption.
Definition: cbc.c:61
__weak_func error_t ccmEncrypt(const CipherAlgo *cipher, void *context, const uint8_t *n, size_t nLen, 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 CCM.
Definition: ccm.c:67
error_t chacha20Poly1305Encrypt(const uint8_t *k, size_t kLen, const uint8_t *n, size_t nLen, 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 ChaCha20Poly1305.
Collection of AEAD algorithms.
#define MAX_CIPHER_BLOCK_SIZE
Block cipher modes of operation.
error_t cmacFinal(CmacContext *context, uint8_t *mac, size_t macLen)
Finish the CMAC calculation.
Definition: cmac.c:237
void cmacUpdate(CmacContext *context, const void *data, size_t dataLen)
Update the CMAC context with a portion of the message being hashed.
Definition: cmac.c:191
error_t cmacInit(CmacContext *context, const CipherAlgo *cipher, const void *key, size_t keyLen)
Initialize CMAC calculation.
Definition: cmac.c:107
#define htonl(value)
Definition: cpu_endian.h:414
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
#define STORE64BE(a, p)
Definition: cpu_endian.h:322
@ CIPHER_MODE_CHACHA20_POLY1305
Definition: crypto.h:951
@ CIPHER_MODE_CCM
Definition: crypto.h:949
@ CIPHER_MODE_CBC
Definition: crypto.h:945
@ CIPHER_MODE_CTR
Definition: crypto.h:948
@ CIPHER_MODE_GCM
Definition: crypto.h:950
__weak_func error_t ctrEncrypt(const CipherAlgo *cipher, void *context, uint_t m, uint8_t *t, const uint8_t *p, uint8_t *c, size_t length)
CTR encryption.
Definition: ctr.c:62
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
@ ERROR_UNSUPPORTED_CIPHER_MODE
Definition: error.h:128
ESP (IP Encapsulating Security Payload)
EspHeader
Definition: esp.h:255
EspTrailer
Definition: esp.h:267
error_t espEncryptPacket(IpsecContext *context, IpsecSadEntry *sa, const EspHeader *espHeader, uint8_t *payload, size_t *payloadLen, uint8_t nextHeader)
Encrypt an outgoing ESP packet.
size_t espAddTrailer(IpsecSadEntry *sa, uint8_t *data, size_t length, uint8_t nextHeader)
Append ESP trailer.
void espGenerateIv(uint8_t *iv)
IV generation.
error_t espComputeChecksum(IpsecContext *context, IpsecSadEntry *sa, const EspHeader *espHeader, const uint8_t *payload, size_t length, uint8_t *icv)
Compute ICV checksum.
ESP packet encryption.
uint8_t data[]
Definition: ethernet.h:222
__weak_func error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo, void *cipherContext)
Initialize GCM context.
Definition: gcm.c:99
__weak_func 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:214
__weak_func error_t hmacInit(HmacContext *context, const HashAlgo *hash, const void *key, size_t keyLen)
Initialize HMAC calculation.
Definition: hmac.c:140
__weak_func void hmacFinal(HmacContext *context, uint8_t *digest)
Finish the HMAC calculation.
Definition: hmac.c:218
__weak_func void hmacUpdate(HmacContext *context, const void *data, size_t length)
Update the HMAC context with a portion of the message being hashed.
Definition: hmac.c:201
uint8_t iv[]
Definition: ike.h:1502
IPsec (IP security)
#define IpsecSadEntry
Definition: ipsec.h:36
uint8_t payload[]
Definition: ipv6.h:277
uint8_t nextHeader
Definition: ipv6.h:273
uint16_t payloadLen
Definition: ipv6.h:272
uint8_t h
Definition: ndp.h:302
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
Common interface for encryption algorithms.
Definition: crypto.h:1036
size_t blockSize
Definition: crypto.h:1040
CipherAlgoInit init
Definition: crypto.h:1041
CMAC algorithm context.
Definition: cmac.h:54
GCM context.
Definition: gcm.h:64
const CipherAlgo * cipherAlgo
Cipher algorithm.
Definition: gcm.h:65
HMAC algorithm context.
Definition: hmac.h:59
uint8_t digest[MAX_HASH_DIGEST_SIZE]
Definition: hmac.h:63
IPsec context.
Definition: ipsec.h:434
const PrngAlgo * prngAlgo
Pseudo-random number generator to be used.
Definition: ipsec.h:435
CmacContext cmacContext
CMAC context.
Definition: ipsec.h:444
HmacContext hmacContext
HMAC context.
Definition: ipsec.h:447
void * prngContext
Pseudo-random number generator context.
Definition: ipsec.h:436
uint8_t length
Definition: tcp.h:368