ike_misc.c
Go to the documentation of this file.
1 /**
2  * @file ike_misc.c
3  * @brief Helper functions for IKEv2
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2022-2026 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.6.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL IKE_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ike/ike.h"
36 #include "ike/ike_key_exchange.h"
37 #include "ike/ike_payload_parse.h"
38 #include "ike/ike_misc.h"
39 #include "ike/ike_debug.h"
40 #include "ipsec/ipsec_misc.h"
41 #include "debug.h"
42 
43 //Check IKEv2 library configuration
44 #if (IKE_SUPPORT == ENABLED)
45 
46 //Invalid IKE SPI value
47 const uint8_t IKE_INVALID_SPI[8] = {0};
48 
49 
50 /**
51  * @brief Retransmit IKE request message
52  * @param[in] sa Pointer to the IKE SA
53  * @return Error code
54  **/
55 
57 {
58  error_t error;
59  IkeContext *context;
60 
61  //Point to the IKE context
62  context = sa->context;
63 
64  //Debug message
65  TRACE_INFO("Retransmitting IKE request (%" PRIuSIZE " bytes)...\r\n",
66  sa->requestLen);
67 
68  //Dump IKE message for debugging purpose
69  ikeDumpMessage(sa->request, sa->requestLen);
70 
71  //A retransmission from the initiator must be bitwise identical to the
72  //original request (refer to RFC 7296, section 2.1)
73  error = socketSendTo(context->socket, &sa->remoteIpAddr, sa->remotePort,
74  sa->request, sa->requestLen, NULL, 0);
75 
76  //Retransmission times must increase exponentially to avoid flooding the
77  //network and making an existing congestion situation worse (refer to
78  //RFC 7296, section 2.4)
79  sa->timeout = MIN(sa->timeout * 2, IKE_MAX_TIMEOUT);
80 
81  //Save the time at which the message was sent
82  sa->timestamp = osGetSystemTime();
83 
84  //Increment retransmission counter
85  sa->retransmitCount++;
86 
87  //Return status code
88  return error;
89 }
90 
91 
92 /**
93  * @brief Retransmit IKE response message
94  * @param[in] sa Pointer to the IKE SA
95  * @return Error code
96  **/
97 
99 {
100  error_t error;
101  IkeContext *context;
102 
103  //Initialize status code
104  error = NO_ERROR;
105 
106  //Point to the IKE context
107  context = sa->context;
108 
109  //In order to allow saving memory, responders are allowed to forget the
110  //response after a timeout of several minutes
111  if(sa->responseLen > 0)
112  {
113  //Debug message
114  TRACE_INFO("Retransmitting IKE response (%" PRIuSIZE " bytes)...\r\n",
115  sa->responseLen);
116 
117  //Dump IKE message for debugging purpose
118  ikeDumpMessage(sa->response, sa->responseLen);
119 
120  //Retransmit the response
121  error = socketSendTo(context->socket, &context->remoteIpAddr,
122  context->remotePort, sa->response, sa->responseLen, NULL, 0);
123  }
124 
125  //Return status code
126  return error;
127 }
128 
129 
130 /**
131  * @brief Create a new IKE Security Association
132  * @param[in] context Pointer to the IKE context
133  * @return Pointer to the newly created IKE SA
134  **/
135 
137 {
138  uint_t i;
139  IkeSaEntry *sa;
140 
141  //Loop through IKE SA entries
142  for(i = 0; i < context->numSaEntries; i++)
143  {
144  //Point to the current IKE SA
145  sa = &context->sa[i];
146 
147  //Check whether the current IKE SA is free
148  if(sa->state == IKE_SA_STATE_CLOSED)
149  {
150  //Clear IKE SA entry
151  osMemset(sa, 0, sizeof(IkeSaEntry));
152 
153  //Attach IKE context
154  sa->context = context;
155 
156  //Initialize IKE SA parameters
157  sa->txMessageId = UINT32_MAX;
158  sa->rxMessageId = UINT32_MAX;
159 
160  //Initialize Diffie-Hellman context
161  ikeInitDhContext(sa);
162 
163  //Default state
164  sa->state = IKE_SA_STATE_RESERVED;
165 
166  //Return a pointer to the newly created IKE SA
167  return sa;
168  }
169  }
170 
171  //The IKE SA table runs out of space
172  return NULL;
173 }
174 
175 
176 /**
177  * @brief Find an IKE SA that matches an incoming IKE message
178  * @param[in] context Pointer to the IKE context
179  * @param[in] ikeHeader Pointer to the IKE header
180  * @return Pointer to the matching IKE SA, if any
181  **/
182 
183 IkeSaEntry *ikeFindSaEntry(IkeContext *context, const IkeHeader *ikeHeader)
184 {
185  uint_t i;
186  const uint8_t *spi;
187  IkeSaEntry *sa;
188 
189  //The I bit is used by the recipient to determine which eight octets of the
190  //SPI were generated by the recipient (refer to RFC 7296, section 3.1)
191  if((ikeHeader->flags & IKE_FLAGS_I) != 0)
192  {
193  spi = ikeHeader->responderSpi;
194  }
195  else
196  {
197  spi = ikeHeader->initiatorSpi;
198  }
199 
200  //Loop through IKE SA entries
201  for(i = 0; i < context->numSaEntries; i++)
202  {
203  //Point to the current IKE SA
204  sa = &context->sa[i];
205 
206  //Check whether the current IKE SA is active
207  if(sa->state != IKE_SA_STATE_CLOSED)
208  {
209  //Check whether the entity is the original initiator of the IKE SA
210  if(sa->originalInitiator)
211  {
212  //Compare SPIs
213  if(osMemcmp(sa->initiatorSpi, spi, IKE_SPI_SIZE) == 0)
214  {
215  //A matching IKE SA has been found
216  return sa;
217  }
218  }
219  else
220  {
221  //Compare SPIs
222  if(osMemcmp(sa->responderSpi, spi, IKE_SPI_SIZE) == 0)
223  {
224  //A matching IKE SA has been found
225  return sa;
226  }
227  }
228  }
229  }
230 
231  //The incoming IKE message does not match any IKE SA
232  return NULL;
233 }
234 
235 
236 /**
237  * @brief Find an half-open IKE SA that matches an incoming IKE_SA_INIT request
238  * @param[in] context Pointer to the IKE context
239  * @param[in] ikeHeader Pointer to the IKE header
240  * @param[in] noncePayload Pointer to the Ni payload
241  * @return Pointer to the matching IKE SA, if any
242  **/
243 
245  const IkeHeader *ikeHeader, const IkeNoncePayload *noncePayload)
246 {
247  uint_t i;
248  size_t n;
249  IkeSaEntry *sa;
250 
251  //Retrieve the length of the Ni payload
252  n = ntohs(noncePayload->header.payloadLength);
253 
254  //Check the length of the Ni payload
255  if(n >= sizeof(IkeNoncePayload))
256  {
257  //Determine the length of the nonce
258  n -= sizeof(IkeNoncePayload);
259 
260  //Loop through IKE SA entries
261  for(i = 0; i < context->numSaEntries; i++)
262  {
263  //Point to the current IKE SA
264  sa = &context->sa[i];
265 
266  //Check whether the current IKE SA is active
267  if(sa->state != IKE_SA_STATE_CLOSED)
268  {
269  //Compare SPIs
270  if(osMemcmp(sa->initiatorSpi, ikeHeader->initiatorSpi,
271  IKE_SPI_SIZE) == 0)
272  {
273  //It is not sufficient to use the initiator's SPI to lookup the
274  //IKE SA. Instead, a robust responder will do the IKE SA lookup
275  //using the whole packet, its hash, or the Ni payload (refer to
276  //RFC 7296, section 2.1)
277  if(sa->initiatorNonceLen == n && osMemcmp(sa->initiatorNonce,
278  noncePayload->nonceData, n) == 0)
279  {
280  //A matching IKE SA has been found
281  return sa;
282  }
283  }
284  }
285  }
286  }
287 
288  //The incoming IKE_SA_INIT request does not match any half-open IKE SA
289  return NULL;
290 }
291 
292 
293 /**
294  * @brief Delete an IKE Security Association
295  * @param[in] sa Pointer to the IKE SA
296  **/
297 
299 {
300  uint_t i;
301  IkeContext *context;
302  IkeChildSaEntry *childSa;
303 
304  //Debug message
305  TRACE_INFO("Deleting IKE SA...\r\n");
306 
307  //Point to the IKE context
308  context = sa->context;
309 
310  //Achieving perfect forward secrecy requires that when a connection is
311  //closed, each endpoint must forget not only the keys used by the
312  //connection but also any information that could be used to recompute
313  //those keys (refer to RFC 7296, section 2.12)
314  ikeFreeDhContext(sa);
315 
316  //Loop through Child SA entries
317  for(i = 0; i < context->numChildSaEntries; i++)
318  {
319  //Point to the current Child SA
320  childSa = &context->childSa[i];
321 
322  //Check the state of the Child SA
323  if(childSa->state != IKE_CHILD_SA_STATE_CLOSED)
324  {
325  //Deleting an IKE SA implicitly closes any remaining Child SAs
326  //negotiated under it (refer to RFC 7296, section 1.4.1)
327  if(childSa->sa == sa)
328  {
329  ikeDeleteChildSaEntry(childSa);
330  }
331  }
332  }
333 
334  //Check whether reauthentication is on-going
335  if(sa->oldSa != NULL && sa->oldSa->state != IKE_SA_STATE_CLOSED)
336  {
337  //Close the old IKE SA since reauthentication has failed
338  sa->oldSa->deleteRequest = TRUE;
339  //Notify the IKE context that the IKE SA should be closed
340  osSetEvent(&context->event);
341  }
342 
343  //Mark the IKE SA as closed
344  sa->state = IKE_SA_STATE_CLOSED;
345 }
346 
347 
348 /**
349  * @brief Delete an duplicate IKE Security Associations
350  * @param[in] sa Pointer to the currently active IKE SA
351  **/
352 
354 {
355  uint_t i;
356  IkeContext *context;
357  IkeSaEntry *entry;
358 
359  //Debug message
360  TRACE_INFO("Deleting duplicate IKE SAs...\r\n");
361 
362  //Point to the IKE context
363  context = sa->context;
364 
365  //Loop through IKE SA entries
366  for(i = 0; i < context->numSaEntries; i++)
367  {
368  //Point to the current IKE SA
369  entry = &context->sa[i];
370 
371  //Check the state of the IKE SA
372  if(entry != sa && entry->state != IKE_SA_STATE_CLOSED)
373  {
374  //Different IKE SA with same authenticated identity?
375  if(entry->peerIdType == sa->peerIdType &&
376  entry->peerIdLen == sa->peerIdLen &&
377  osMemcmp(entry->peerId, sa->peerId, sa->peerIdLen) == 0)
378  {
379  //The recipient of an INITIAL_CONTACT notification may use this
380  //information to delete any other IKE SAs it has to the same
381  //authenticated identity without waiting for a timeout (refer to
382  //RFC 7296, section 2.4)
383  ikeDeleteSaEntry(entry);
384  }
385  }
386  }
387 }
388 
389 
390 /**
391  * @brief Create a new Child Security Association
392  * @param[in] context Pointer to the IKE context
393  * @return Pointer to the newly created Child SA
394  **/
395 
397 {
398  uint_t i;
399  IkeChildSaEntry *childSa;
400  IpsecContext *ipsecContext;
401 
402  //Point to the IPsec context
403  ipsecContext = context->netContext->ipsecContext;
404 
405  //Loop through Child SA entries
406  for(i = 0; i < context->numChildSaEntries; i++)
407  {
408  //Point to the current Child SA
409  childSa = &context->childSa[i];
410 
411  //Check whether the current Child SA is free
412  if(childSa->state == IKE_CHILD_SA_STATE_CLOSED)
413  {
414  //Clear Child SA entry
415  osMemset(childSa, 0, sizeof(IkeChildSaEntry));
416 
417  //Attach IKE context
418  childSa->context = context;
419 
420  //Allocate inbound SAD entry
421  childSa->inboundSa = ipsecAllocateSadEntry(ipsecContext);
422 
423  //Failed to allocated SAD entry?
424  if(childSa->inboundSa < 0)
425  {
426  //The SAD database runs out of space
427  return NULL;
428  }
429 
430  //Allocate outbound SAD entry
431  childSa->outboundSa = ipsecAllocateSadEntry(ipsecContext);
432 
433  //Failed to allocated SAD entry?
434  if(childSa->outboundSa < 0)
435  {
436  //Clean up side effects
437  ipsecClearSadEntry(ipsecContext, childSa->inboundSa);
438  //The SAD database runs out of space
439  return NULL;
440  }
441 
442  //Default state
443  childSa->state = IKE_CHILD_SA_STATE_RESERVED;
444 
445  //Return a pointer to the newly created Child SA
446  return childSa;
447  }
448  }
449 
450  //The Child SA table runs out of space
451  return NULL;
452 }
453 
454 
455 /**
456  * @brief Find an Child SA that matches the specified SPI
457  * @param[in] sa Pointer to the IKE SA
458  * @param[in] protocolId Protocol identifier (AH or ESP)
459  * @param[in] spi Security parameter index
460  * @return Pointer to the matching Child SA, if any
461  **/
462 
464  const uint8_t *spi)
465 {
466  uint_t i;
467  IkeContext *context;
468  IkeChildSaEntry *childSa;
469 
470  //Point to the IKE context
471  context = sa->context;
472 
473  //Loop through Child SA entries
474  for(i = 0; i < context->numChildSaEntries; i++)
475  {
476  //Point to the current Child SA
477  childSa = &context->childSa[i];
478 
479  //Check the state of the Child SA
480  if(childSa->state != IKE_CHILD_SA_STATE_CLOSED)
481  {
482  //Matching IKE SA and protocol identifier?
483  if(childSa->sa == sa && childSa->protocol == protocolId)
484  {
485  //Compare SPIs
486  if(osMemcmp(childSa->remoteSpi, spi, IPSEC_SPI_SIZE) == 0)
487  {
488  //A matching Child SA has been found
489  return childSa;
490  }
491  }
492  }
493  }
494 
495  //The specified SPI does not match any Child SA
496  return NULL;
497 }
498 
499 
500 /**
501  * @brief Delete a Child Security Association
502  * @param[in] childSa Pointer to the Child SA
503  **/
504 
506 {
507  IpsecContext *ipsecContext;
508 
509  //Debug message
510  TRACE_INFO("Deleting Child SA...\r\n");
511 
512  //Point to the IPsec context
513  ipsecContext = childSa->context->netContext->ipsecContext;
514 
515  //Close inbound SAD entry
516  if(childSa->inboundSa >= 0)
517  {
518  ipsecClearSadEntry(ipsecContext, childSa->inboundSa);
519  }
520 
521  //Close outbound SAD entry
522  if(childSa->outboundSa >= 0)
523  {
524  ipsecClearSadEntry(ipsecContext, childSa->outboundSa);
525  }
526 
527  //Mark the Child SA as closed
528  childSa->state = IKE_CHILD_SA_STATE_CLOSED;
529 }
530 
531 
532 /**
533  * @brief Generate a new IKE SA SPI
534  * @param[in] sa Pointer to the IKE SA
535  * @param[out] spi Pointer to the buffer where to store the resulting SPI
536  * @return Error code
537  **/
538 
540 {
541  error_t error;
542  uint_t i;
543  IkeContext *context;
544  IkeSaEntry *entry;
545 
546  //Debug message
547  TRACE_INFO("Generating new IKE SA SPI (%u bytes)...\r\n", IKE_SPI_SIZE);
548 
549  //Point to the IKE context
550  context = sa->context;
551 
552  //Each endpoint chooses one of the two SPIs and must choose them so as to
553  //be unique identifiers of an IKE SA (refer to RFC 7296, section 2.6)
554  do
555  {
556  //Generate an arbitrary 8-octet value
557  error = context->prngAlgo->generate(context->prngContext, spi,
558  IKE_SPI_SIZE);
559 
560  //Check status code
561  if(!error)
562  {
563  //Non-zero SPI value?
565  {
566  //Loop through IKE SA entries
567  for(i = 0; i < context->numSaEntries && !error; i++)
568  {
569  //Point to the current IKE SA
570  entry = &context->sa[i];
571 
572  //Check the state of the IKE SA
573  if(entry != sa && entry->state != IKE_SA_STATE_CLOSED)
574  {
575  //Check whether the entity is the original initiator of the
576  //IKE SA
577  if(entry->originalInitiator)
578  {
579  //Test whether the SPI is a duplicate
580  if(osMemcmp(spi, entry->initiatorSpi, IKE_SPI_SIZE) == 0)
581  {
582  error = ERROR_INVALID_SPI;
583  }
584  }
585  else
586  {
587  //Test whether the SPI is a duplicate
588  if(osMemcmp(spi, entry->responderSpi, IKE_SPI_SIZE) == 0)
589  {
590  error = ERROR_INVALID_SPI;
591  }
592  }
593  }
594  }
595  }
596  else
597  {
598  //The SPI value must not be zero (refer to RFC 7296, section 3.1)
599  error = ERROR_INVALID_SPI;
600  }
601  }
602 
603  //Repeat as necessary until a unique SPI is generated
604  } while(error == ERROR_INVALID_SPI);
605 
606  //Check status code
607  if(!error)
608  {
609  //Debug message
611  }
612 
613  //Return status code
614  return error;
615 }
616 
617 
618 /**
619  * @brief Generate a new Child SA SPI
620  * @param[in] childSa Pointer to the Child SA
621  * @param[out] spi Pointer to the buffer where to store the resulting SPI
622  * @return Error code
623  **/
624 
626 {
627  error_t error;
628  uint_t i;
629  IkeContext *context;
630  IkeChildSaEntry *entry;
631 
632  //Debug message
633  TRACE_INFO("Generating new Child SA SPI (%u bytes)...\r\n", IKE_SPI_SIZE);
634 
635  //Point to the IKE context
636  context = childSa->context;
637 
638  //Generate a unique SPI value
639  do
640  {
641  //Generate an arbitrary 4-octet value
642  error = context->prngAlgo->generate(context->prngContext, spi,
644 
645  //Check status code
646  if(!error)
647  {
648  //Non-zero SPI value?
650  {
651  //Loop through Child SA entries
652  for(i = 0; i < context->numChildSaEntries && !error; i++)
653  {
654  //Point to the current Child SA
655  entry = &context->childSa[i];
656 
657  //Check the state of the Child SA
658  if(entry != childSa && entry->state != IKE_CHILD_SA_STATE_CLOSED)
659  {
660  //Test whether the SPI is a duplicate
661  if(osMemcmp(spi, entry->localSpi, IPSEC_SPI_SIZE) == 0)
662  {
663  error = ERROR_INVALID_SPI;
664  }
665  }
666  }
667  }
668  else
669  {
670  //The SPI value of zero is reserved and must not be sent on the
671  //wire (refer to RFC 4302, section 2.4 and RFC 4303, section 2.1)
672  error = ERROR_INVALID_SPI;
673  }
674  }
675 
676  //Repeat as necessary until a unique SPI is generated
677  } while(error == ERROR_INVALID_SPI);
678 
679  //Check status code
680  if(!error)
681  {
682  //Debug message
684  }
685 
686  //Return status code
687  return error;
688 }
689 
690 
691 /**
692  * @brief Generate a new nonce
693  * @param[in] context Pointer to the IKE context
694  * @param[out] nonce Pointer to the buffer where to store the resulting nonce
695  * @param[in] length Length of the nonce, in bytes
696  * @return Error code
697  **/
698 
699 error_t ikeGenerateNonce(IkeContext *context, uint8_t *nonce, size_t *length)
700 {
701  error_t error;
702 
703  //Debug message
704  TRACE_INFO("Generating new nonce (%u bytes)...\r\n", IKE_DEFAULT_NONCE_SIZE);
705 
706  //Nonces used in IKEv2 must be randomly chosen and must be at least 128 bits
707  //in size (refer to RFC 7296, section 2.10)
708  error = context->prngAlgo->generate(context->prngContext, nonce,
710 
711  //Check status code
712  if(!error)
713  {
714  //Set the length of the nonce
716 
717  //Debug message
719  }
720 
721  //Return status code
722  return error;
723 }
724 
725 
726 /**
727  * @brief Apply random jitter to a time interval
728  * @param[in] context Pointer to the IKE context
729  * @param[out] delay Time interval to be randomized
730  * @return Randomized time interval
731  **/
732 
734 {
735  error_t error;
738 
739  //Maximum jitter to be applied to the time interval
740  delta = (delay * IKE_RANDOM_JITTER) / 100;
741 
742  //Sanity check
743  if(delta > 0)
744  {
745  //Generate a random value
746  error = context->prngAlgo->generate(context->prngContext,
747  (uint8_t *) &value, sizeof(value));
748 
749  //Check status code
750  if(!error)
751  {
752  //Apply random jitter to the time interval
753  delay -= value % delta;
754  }
755  }
756 
757  //Return the randomized time interval
758  return delay;
759 }
760 
761 
762 /**
763  * @brief Traffic selector selection
764  * @param[in] childSa Pointer to the Child SA
765  * @param[in] tsiPayload Pointer to the TSi payload
766  * @param[in] tsrPayload Pointer to the TSr payload
767  * @return Error code
768  **/
769 
770 error_t ikeSelectTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload,
771  const IkeTsPayload *tsrPayload)
772 {
773  error_t error;
774  size_t n;
775  IkeTsParams localTsParams;
776  IkeTsParams remoteTsParams;
777  IpsecSpdEntry *spdEntry;
778  IpsecSelector selector;
779 
780  //Get the length of the TSi payload
781  n = ntohs(tsiPayload->header.payloadLength);
782 
783  //Malformed TSi payload?
784  if(n < sizeof(IkeTsPayload))
785  return ERROR_INVALID_MESSAGE;
786 
787  //Check the number of traffic selectors
788  if(tsiPayload->numTs < 1)
789  return ERROR_INVALID_MESSAGE;
790 
791  //Parse the first Traffic Selector substructure of the TSi payload
792  error = ikeParseTs(tsiPayload->trafficSelectors, n - sizeof(IkeTsPayload),
793  &remoteTsParams);
794  //Any error to report?
795  if(error)
796  return error;
797 
798  //Get the length of the TSr payload
799  n = ntohs(tsrPayload->header.payloadLength);
800 
801  //Malformed TSi payload?
802  if(n < sizeof(IkeTsPayload))
803  return ERROR_INVALID_MESSAGE;
804 
805  //Check the number of traffic selectors
806  if(tsrPayload->numTs < 1)
807  return ERROR_INVALID_MESSAGE;
808 
809  //Parse the first Traffic Selector substructure of the TSr payload
810  error = ikeParseTs(tsrPayload->trafficSelectors, n - sizeof(IkeTsPayload),
811  &localTsParams);
812  //Any error to report?
813  if(error)
814  return error;
815 
816  //Make sure the IP Protocol ID fields are consistent
817  if(localTsParams.ipProtocolId != remoteTsParams.ipProtocolId)
818  return ERROR_INVALID_PROTOCOL;
819 
820  //Retrieve selector parameters
821  selector.localIpAddr.start = localTsParams.startAddr;
822  selector.localIpAddr.end = localTsParams.endAddr;
823  selector.remoteIpAddr.start = remoteTsParams.startAddr;
824  selector.remoteIpAddr.end = remoteTsParams.endAddr;
825  selector.nextProtocol = localTsParams.ipProtocolId;
826  selector.localPort.start = localTsParams.startPort;
827  selector.localPort.end = localTsParams.endPort;
828  selector.remotePort.start = remoteTsParams.startPort;
829  selector.remotePort.end = remoteTsParams.endPort;
830 
831  //A responder uses the traffic selector proposals it receives via an SA
832  //management protocol to select an appropriate entry in its SPD (refer to
833  //RFC 4301, section 4.4.1)
834  spdEntry = ipsecFindSpdEntry(childSa->context->netContext->ipsecContext,
835  IPSEC_POLICY_ACTION_PROTECT, &selector);
836  //No matching SPD entry?
837  if(spdEntry == NULL)
838  return ERROR_INVALID_SELECTOR;
839 
840  //IKEv2 allows the responder to choose a subset of the traffic proposed by
841  //the initiator (refer to RFC 7296, section 2.9)
842  if(!ipsecIntersectSelectors(&spdEntry->selector, &selector,
843  &childSa->selector))
844  {
845  return ERROR_INVALID_SELECTOR;
846  }
847 
848  //The SPD entry specifies the security protocol (AH or ESP) to employ
849  childSa->protocol = spdEntry->protocol;
850 
851  //Successful processing
852  return NO_ERROR;
853 }
854 
855 
856 /**
857  * @brief Check whether the selected traffic selectors are acceptable
858  * @param[in] childSa Pointer to the Child SA
859  * @param[in] tsiPayload Pointer to the TSi payload
860  * @param[in] tsrPayload Pointer to the TSr payload
861  * @return Error code
862  **/
863 
864 error_t ikeCheckTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload,
865  const IkeTsPayload *tsrPayload)
866 {
867  error_t error;
868  size_t n;
869  IpsecSelector selector;
870  IkeTsParams localTsParams;
871  IkeTsParams remoteTsParams;
872 
873  //Get the length of the TSi payload
874  n = ntohs(tsiPayload->header.payloadLength);
875 
876  //Malformed TSi payload?
877  if(n < sizeof(IkeTsPayload))
878  return ERROR_INVALID_MESSAGE;
879 
880  //Check the number of traffic selectors
881  if(tsiPayload->numTs < 1)
882  return ERROR_INVALID_MESSAGE;
883 
884  //Parse the first Traffic Selector substructure of the TSi payload
885  error = ikeParseTs(tsiPayload->trafficSelectors, n - sizeof(IkeTsPayload),
886  &localTsParams);
887  //Any error to report?
888  if(error)
889  return error;
890 
891  //Get the length of the TSr payload
892  n = ntohs(tsrPayload->header.payloadLength);
893 
894  //Malformed TSi payload?
895  if(n < sizeof(IkeTsPayload))
896  return ERROR_INVALID_MESSAGE;
897 
898  //Check the number of traffic selectors
899  if(tsrPayload->numTs < 1)
900  return ERROR_INVALID_MESSAGE;
901 
902  //Parse the first Traffic Selector substructure of the TSr payload
903  error = ikeParseTs(tsrPayload->trafficSelectors, n - sizeof(IkeTsPayload),
904  &remoteTsParams);
905  //Any error to report?
906  if(error)
907  return error;
908 
909  //Make sure the IP Protocol ID fields are consistent
910  if(localTsParams.ipProtocolId != remoteTsParams.ipProtocolId)
911  return ERROR_INVALID_PROTOCOL;
912 
913  //Retrieve selector parameters
914  selector.localIpAddr.start = localTsParams.startAddr;
915  selector.localIpAddr.end = localTsParams.endAddr;
916  selector.remoteIpAddr.start = remoteTsParams.startAddr;
917  selector.remoteIpAddr.end = remoteTsParams.endAddr;
918  selector.nextProtocol = localTsParams.ipProtocolId;
919  selector.localPort.start = localTsParams.startPort;
920  selector.localPort.end = localTsParams.endPort;
921  selector.remotePort.start = remoteTsParams.startPort;
922  selector.remotePort.end = remoteTsParams.endPort;
923 
924  //IKEv2 allows the responder to choose a subset of the traffic proposed by
925  //the initiator (refer to RFC 7296, section 2.9)
926  if(!ipsecIsSubsetSelector(&selector, &childSa->selector))
927  return ERROR_INVALID_SELECTOR;
928 
929  //Save traffic selector
930  childSa->selector = selector;
931 
932  //The selected traffic selectors are acceptable
933  return NO_ERROR;
934 }
935 
936 
937 /**
938  * @brief Check the length of the nonce
939  * @param[in] sa Pointer to the IKE SA
940  * @param[in] nonceLen Length of the nonce, in bytes
941  * @return Error code
942  **/
943 
945 {
946  size_t prfKeyLen;
947 
948 #if (IKE_CMAC_PRF_SUPPORT == ENABLED && IKE_AES_128_SUPPORT == ENABLED)
949  //AES-CMAC PRF algorithm?
950  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_AES128_CMAC)
951  {
952  prfKeyLen = 16;
953  }
954  else
955 #endif
956 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_MD5_SUPPORT == ENABLED)
957  //HMAC-MD5 PRF algorithm?
958  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_MD5)
959  {
960  prfKeyLen = MD5_DIGEST_SIZE;
961  }
962  else
963 #endif
964 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA1_SUPPORT == ENABLED)
965  //HMAC-SHA1 PRF algorithm?
966  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA1)
967  {
968  prfKeyLen = SHA1_DIGEST_SIZE;
969  }
970  else
971 #endif
972 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA256_SUPPORT == ENABLED)
973  //HMAC-SHA256 PRF algorithm?
974  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA2_256)
975  {
976  prfKeyLen = SHA256_DIGEST_SIZE;
977  }
978  else
979 #endif
980 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA384_SUPPORT == ENABLED)
981  //HMAC-SHA384 PRF algorithm?
982  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA2_384)
983  {
984  prfKeyLen = SHA384_DIGEST_SIZE;
985  }
986  else
987 #endif
988 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA512_SUPPORT == ENABLED)
989  //HMAC-SHA512 PRF algorithm?
990  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA2_512)
991  {
992  prfKeyLen = SHA512_DIGEST_SIZE;
993  }
994  else
995 #endif
996 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_TIGER_SUPPORT == ENABLED)
997  //HMAC-Tiger PRF algorithm?
998  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_TIGER)
999  {
1000  prfKeyLen = TIGER_DIGEST_SIZE;
1001  }
1002  else
1003 #endif
1004 #if (IKE_XCBC_MAC_PRF_SUPPORT == ENABLED && IKE_AES_128_SUPPORT == ENABLED)
1005  //AES-XCBC-MAC PRF algorithm?
1006  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_AES128_XCBC)
1007  {
1008  prfKeyLen = 16;
1009  }
1010  else
1011 #endif
1012  //Unknown PRF algorithm?
1013  {
1014  prfKeyLen = 0;
1015  }
1016 
1017  //Nonces used in IKEv2 must be at least half the key size of the negotiated
1018  //pseudorandom function (refer to RFC 7296, section 2.10)
1019  if(nonceLen >= (prfKeyLen / 2))
1020  {
1021  return NO_ERROR;
1022  }
1023  else
1024  {
1025  return ERROR_INVALID_LENGTH;
1026  }
1027 }
1028 
1029 
1030 /**
1031  * @brief Create AH or ESP SA pair
1032  * @param[in] childSa Pointer to the Child SA
1033  * @return Error code
1034  **/
1035 
1037 {
1038  error_t error;
1039  IpsecContext *ipsecContext;
1040  IpsecSadEntry sadEntry;
1041 
1042  //Debug message
1043  TRACE_INFO("Creating IPsec SA pair...\r\n");
1044  TRACE_INFO(" Outbound SPI = 0x%08" PRIX32 "\r\n", LOAD32BE(childSa->remoteSpi));
1045  TRACE_INFO(" Inbound SPI = 0x%08" PRIX32 "\r\n", LOAD32BE(childSa->localSpi));
1046 
1047  //Point to the IPsec context
1048  ipsecContext = childSa->context->netContext->ipsecContext;
1049 
1050  //Set SAD entry parameters (outbound traffic)
1051  osMemset(&sadEntry, 0, sizeof(IpsecSadEntry));
1052  sadEntry.direction = IPSEC_DIR_OUTBOUND;
1053  sadEntry.mode = childSa->mode;
1054  sadEntry.protocol = childSa->protocol;
1055  sadEntry.selector = childSa->selector;
1056  sadEntry.spi = LOAD32BE(childSa->remoteSpi);
1057  sadEntry.authCipherAlgo = childSa->authCipherAlgo;
1058  sadEntry.authHashAlgo = childSa->authHashAlgo;
1059  sadEntry.authKeyLen = childSa->authKeyLen;
1060  sadEntry.icvLen = childSa->icvLen;
1061  sadEntry.esn = (childSa->esn == IKE_TRANSFORM_ID_ESN_YES) ? TRUE : FALSE;
1062  sadEntry.seqNum = 0;
1063  sadEntry.antiReplayEnabled = TRUE;
1064 
1065  //Set integrity protection key
1066  if(childSa->initiator)
1067  {
1068  osMemcpy(sadEntry.authKey, childSa->skai, childSa->authKeyLen);
1069  }
1070  else
1071  {
1072  osMemcpy(sadEntry.authKey, childSa->skar, childSa->authKeyLen);
1073  }
1074 
1075 #if (ESP_SUPPORT == ENABLED)
1076  //Set encryption parameters
1077  sadEntry.cipherMode = childSa->cipherMode;
1078  sadEntry.cipherAlgo = childSa->cipherAlgo;
1079  sadEntry.encKeyLen = childSa->encKeyLen;
1080  sadEntry.saltLen = childSa->saltLen;
1081  sadEntry.ivLen = childSa->ivLen;
1082 
1083  //Set encryption key
1084  if(childSa->initiator)
1085  {
1086  osMemcpy(sadEntry.encKey, childSa->skei, childSa->encKeyLen +
1087  childSa->saltLen);
1088  }
1089  else
1090  {
1091  osMemcpy(sadEntry.encKey, childSa->sker, childSa->encKeyLen +
1092  childSa->saltLen);
1093  }
1094 
1095  //Check encryption mode
1096  if(childSa->protocol == IPSEC_PROTOCOL_ESP &&
1097  childSa->cipherMode != CIPHER_MODE_CBC)
1098  {
1099  //Copy initialization vector
1100  osMemcpy(sadEntry.iv, childSa->iv, childSa->ivLen);
1101  }
1102 #endif
1103 
1104  //Update SAD entry (outbound traffic)
1105  error = ipsecSetSadEntry(ipsecContext, childSa->outboundSa, &sadEntry);
1106 
1107  //Check status code
1108  if(!error)
1109  {
1110  //Set SAD entry parameters (inbound traffic)
1111  osMemset(&sadEntry, 0, sizeof(IpsecSadEntry));
1112  sadEntry.direction = IPSEC_DIR_INBOUND;
1113  sadEntry.mode = childSa->mode;
1114  sadEntry.protocol = childSa->protocol;
1115  sadEntry.selector = childSa->selector;
1116  sadEntry.spi = LOAD32BE(childSa->localSpi);
1117  sadEntry.authCipherAlgo = childSa->authCipherAlgo;
1118  sadEntry.authHashAlgo = childSa->authHashAlgo;
1119  sadEntry.authKeyLen = childSa->authKeyLen;
1120  sadEntry.icvLen = childSa->icvLen;
1121  sadEntry.esn = (childSa->esn == IKE_TRANSFORM_ID_ESN_YES) ? TRUE : FALSE;
1122  sadEntry.seqNum = 0;
1123  sadEntry.antiReplayEnabled = TRUE;
1124 
1125  //Set integrity protection key
1126  if(childSa->initiator)
1127  {
1128  osMemcpy(sadEntry.authKey, childSa->skar, childSa->authKeyLen);
1129  }
1130  else
1131  {
1132  osMemcpy(sadEntry.authKey, childSa->skai, childSa->authKeyLen);
1133  }
1134 
1135 #if (ESP_SUPPORT == ENABLED)
1136  //Set encryption parameters
1137  sadEntry.cipherMode = childSa->cipherMode;
1138  sadEntry.cipherAlgo = childSa->cipherAlgo;
1139  sadEntry.encKeyLen = childSa->encKeyLen;
1140  sadEntry.saltLen = childSa->saltLen;
1141  sadEntry.ivLen = childSa->ivLen;
1142 
1143  //Set encryption key
1144  if(childSa->initiator)
1145  {
1146  osMemcpy(sadEntry.encKey, childSa->sker, childSa->encKeyLen +
1147  childSa->saltLen);
1148  }
1149  else
1150  {
1151  osMemcpy(sadEntry.encKey, childSa->skei, childSa->encKeyLen +
1152  childSa->saltLen);
1153  }
1154 #endif
1155 
1156  //Update SAD entry (inbound traffic)
1157  error = ipsecSetSadEntry(ipsecContext, childSa->inboundSa, &sadEntry);
1158  }
1159 
1160  //Return status code
1161  return error;
1162 }
1163 
1164 
1165 /**
1166  * @brief Test if the IKE SA is the only currently active with a given peer
1167  * @param[in] sa Pointer to the IKE SA
1168  * @return TRUE if this IKE SA is the only IKE SA currently active between the
1169  * authenticated identities, else FALSE
1170  **/
1171 
1173 {
1174  uint_t i;
1175  IkeContext *context;
1176  IkeSaEntry *entry;
1177 
1178  //Point to the IKE context
1179  context = sa->context;
1180 
1181  //Loop through IKE SA entries
1182  for(i = 0; i < context->numSaEntries; i++)
1183  {
1184  //Point to the current IKE SA
1185  entry = &context->sa[i];
1186 
1187  //Check the state of the IKE SA
1188  if(entry != sa && entry->state != IKE_SA_STATE_CLOSED)
1189  {
1190  //Check whether another IKE SA exists between the authenticated
1191  //identities
1192  if(ipCompAddr(&entry->remoteIpAddr, &sa->remoteIpAddr))
1193  {
1194  return FALSE;
1195  }
1196  }
1197  }
1198 
1199  //This IKE SA is the only IKE SA currently active between the authenticated
1200  //identities
1201  return TRUE;
1202 }
1203 
1204 #endif
#define IPSEC_SPI_SIZE
Definition: ipsec.h:142
Diffie-Hellman key exchange.
int bool_t
Definition: compiler_port.h:63
@ IKE_TRANSFORM_ID_PRF_AES128_CMAC
Definition: ike.h:982
Helper functions for IKEv2.
uint16_t end
Definition: ipsec.h:297
@ CIPHER_MODE_CBC
Definition: crypto.h:1063
@ IPSEC_DIR_INBOUND
Definition: ipsec.h:171
error_t ikeRetransmitResponse(IkeSaEntry *sa)
Retransmit IKE response message.
Definition: ike_misc.c:98
#define LOAD32BE(p)
Definition: cpu_endian.h:210
IPsec selector.
Definition: ipsec.h:306
uint32_t spi
Definition: ah.h:196
uint8_t delta
Definition: coap_common.h:196
error_t ikeGenerateSaSpi(IkeSaEntry *sa, uint8_t *spi)
Generate a new IKE SA SPI.
Definition: ike_misc.c:539
#define TRUE
Definition: os_port.h:50
IpAddr startAddr
Definition: ike.h:1766
systime_t ikeRandomizeDelay(IkeContext *context, systime_t delay)
Apply random jitter to a time interval.
Definition: ike_misc.c:733
IpAddr endAddr
Definition: ike.h:1767
IpAddr end
Definition: ipsec.h:286
const uint8_t IPSEC_INVALID_SPI[4]
Definition: ipsec_misc.c:40
IkeChildSaEntry * ikeCreateChildSaEntry(IkeContext *context)
Create a new Child Security Association.
Definition: ike_misc.c:396
#define osMemcmp(p1, p2, length)
Definition: os_port.h:156
#define IKE_MAX_TIMEOUT
Definition: ike.h:145
#define IKE_DEFAULT_NONCE_SIZE
Definition: ike.h:194
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
error_t ikeSelectTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload, const IkeTsPayload *tsrPayload)
Traffic selector selection.
Definition: ike_misc.c:770
@ IKE_SA_STATE_CLOSED
Definition: ike.h:1318
@ IKE_TRANSFORM_ID_PRF_HMAC_SHA2_384
Definition: ike.h:980
@ IPSEC_POLICY_ACTION_PROTECT
Definition: ipsec.h:237
@ IPSEC_PROTOCOL_ESP
Definition: ipsec.h:197
@ IPSEC_DIR_OUTBOUND
Definition: ipsec.h:172
const uint8_t IKE_INVALID_SPI[8]
Definition: ike_misc.c:47
Traffic selector parameters.
Definition: ike.h:1765
#define IkeContext
Definition: ike.h:796
#define FALSE
Definition: os_port.h:46
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
IkeSaEntry * ikeCreateSaEntry(IkeContext *context)
Create a new IKE Security Association.
Definition: ike_misc.c:136
Data logging functions for debugging purpose (IKEv2)
@ IKE_SA_STATE_RESERVED
Definition: ike.h:1319
uint8_t nextProtocol
Next layer protocol.
Definition: ipsec.h:309
void ikeInitDhContext(IkeSaEntry *sa)
Initialize Diffie-Hellman context.
@ IKE_FLAGS_I
Initiator flag.
Definition: ike.h:840
error_t
Error codes.
Definition: error.h:43
bool_t ipCompAddr(const IpAddr *ipAddr1, const IpAddr *ipAddr2)
Compare IP addresses.
Definition: ip.c:318
IpsecPortRange remotePort
Remote port range.
Definition: ipsec.h:311
uint8_t protocolId[]
IkeTsPayload
Definition: ike.h:1634
bool_t ipsecIntersectSelectors(const IpsecSelector *selector1, const IpsecSelector *selector2, IpsecSelector *result)
Calculate the intersection of two selectors.
Definition: ipsec_misc.c:545
uint8_t ipProtocolId
Definition: ike.h:1768
#define IKE_SPI_SIZE
Definition: ike.h:790
Helper routines for IPsec.
IpsecProtocol protocol
Security protocol (AH or ESP)
Definition: ipsec.h:353
bool_t ipsecIsSubsetSelector(const IpsecSelector *selector1, const IpsecSelector *selector2)
Test if a selector is a subset of another selector.
Definition: ipsec_misc.c:362
@ IKE_TRANSFORM_ID_PRF_HMAC_MD5
Definition: ike.h:975
@ ERROR_INVALID_LENGTH
Definition: error.h:111
error_t ikeParseTs(const uint8_t *p, size_t length, IkeTsParams *tsParams)
Parse Traffic Selector substructure.
IkeChildSaEntry * ikeFindChildSaEntry(IkeSaEntry *sa, uint8_t protocolId, const uint8_t *spi)
Find an Child SA that matches the specified SPI.
Definition: ike_misc.c:463
@ IKE_TRANSFORM_ID_PRF_HMAC_SHA1
Definition: ike.h:976
void ikeDeleteSaEntry(IkeSaEntry *sa)
Delete an IKE Security Association.
Definition: ike_misc.c:298
error_t ipsecSetSadEntry(IpsecContext *context, uint_t index, IpsecSadEntry *params)
Set entry at specified index in SAD database.
Definition: ipsec.c:202
void ikeDeleteDuplicateSaEntries(IkeSaEntry *sa)
Delete an duplicate IKE Security Associations.
Definition: ike_misc.c:353
void ikeDeleteChildSaEntry(IkeChildSaEntry *childSa)
Delete a Child Security Association.
Definition: ike_misc.c:505
#define TRACE_INFO(...)
Definition: debug.h:105
error_t ikeCheckNonceLength(IkeSaEntry *sa, size_t nonceLen)
Check the length of the nonce.
Definition: ike_misc.c:944
uint8_t length
Definition: tcp.h:375
@ IKE_TRANSFORM_ID_PRF_AES128_XCBC
Definition: ike.h:978
IkeHeader
Definition: ike.h:1423
@ ERROR_INVALID_PROTOCOL
Definition: error.h:101
#define MIN(a, b)
Definition: os_port.h:63
#define SHA384_DIGEST_SIZE
Definition: sha384.h:41
#define MD5_DIGEST_SIZE
Definition: md5.h:45
error_t ikeCheckTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload, const IkeTsPayload *tsrPayload)
Check whether the selected traffic selectors are acceptable.
Definition: ike_misc.c:864
@ IKE_TRANSFORM_ID_PRF_HMAC_SHA2_256
Definition: ike.h:979
@ IKE_CHILD_SA_STATE_CLOSED
Definition: ike.h:1348
IpAddr start
Definition: ipsec.h:285
IpsecSpdEntry * ipsecFindSpdEntry(IpsecContext *context, IpsecPolicyAction policyAction, const IpsecSelector *selector)
Search the SPD database for a matching entry.
Definition: ipsec_misc.c:51
#define IpsecSadEntry
Definition: ipsec.h:36
uint16_t start
Definition: ipsec.h:296
IKEv2 (Internet Key Exchange Protocol)
error_t ikeCreateIpsecSaPair(IkeChildSaEntry *childSa)
Create AH or ESP SA pair.
Definition: ike_misc.c:1036
uint32_t systime_t
System time.
#define ntohs(value)
Definition: cpu_endian.h:421
uint16_t startPort
Definition: ike.h:1769
int_t ipsecAllocateSadEntry(IpsecContext *context)
Allocate a new entry in the SAD database.
Definition: ipsec_misc.c:96
@ ERROR_INVALID_SELECTOR
Definition: error.h:302
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
IKE payload parsing.
#define IkeSaEntry
Definition: ike.h:800
@ ERROR_INVALID_SPI
Definition: error.h:298
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
uint8_t n
@ IKE_TRANSFORM_ID_PRF_HMAC_TIGER
Definition: ike.h:977
IkeSaEntry * ikeFindSaEntry(IkeContext *context, const IkeHeader *ikeHeader)
Find an IKE SA that matches an incoming IKE message.
Definition: ike_misc.c:183
IpsecAddrRange localIpAddr
Local IP address range.
Definition: ipsec.h:307
@ IKE_TRANSFORM_ID_ESN_YES
Extended Sequence Numbers.
Definition: ike.h:1055
error_t ikeGenerateChildSaSpi(IkeChildSaEntry *childSa, uint8_t *spi)
Generate a new Child SA SPI.
Definition: ike_misc.c:625
uint8_t value[]
Definition: tcp.h:376
#define IpsecContext
Definition: ipsec.h:40
error_t socketSendTo(Socket *socket, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length, size_t *written, uint_t flags)
Send a datagram to a specific destination.
Definition: socket.c:1535
bool_t ikeIsInitialContact(IkeSaEntry *sa)
Test if the IKE SA is the only currently active with a given peer.
Definition: ike_misc.c:1172
#define TIGER_DIGEST_SIZE
Definition: tiger.h:40
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
IkeSaEntry * ikeFindHalfOpenSaEntry(IkeContext *context, const IkeHeader *ikeHeader, const IkeNoncePayload *noncePayload)
Find an half-open IKE SA that matches an incoming IKE_SA_INIT request.
Definition: ike_misc.c:244
IkeNoncePayload
Definition: ike.h:1582
error_t ikeGenerateNonce(IkeContext *context, uint8_t *nonce, size_t *length)
Generate a new nonce.
Definition: ike_misc.c:699
Security Policy Database (SPD) entry.
Definition: ipsec.h:348
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
IpsecSelector selector
Traffic selector.
Definition: ipsec.h:351
#define SHA256_DIGEST_SIZE
Definition: sha256.h:45
void ikeDumpMessage(const uint8_t *message, size_t length)
Dump IKE message.
Definition: ike_debug.c:413
#define IkeChildSaEntry
Definition: ike.h:804
error_t ipsecClearSadEntry(IpsecContext *context, uint_t index)
Clear entry at specified index in SAD database.
Definition: ipsec.c:285
uint16_t endPort
Definition: ike.h:1770
#define IKE_RANDOM_JITTER
Definition: ike.h:159
IpsecPortRange localPort
Local port range.
Definition: ipsec.h:310
#define SHA512_DIGEST_SIZE
Definition: sha512.h:45
@ IKE_CHILD_SA_STATE_RESERVED
Definition: ike.h:1349
IpsecAddrRange remoteIpAddr
Remote IP address range.
Definition: ipsec.h:308
uint8_t nonce[]
Definition: ntp_common.h:239
@ IKE_TRANSFORM_ID_PRF_HMAC_SHA2_512
Definition: ike.h:981
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
error_t ikeRetransmitRequest(IkeSaEntry *sa)
Retransmit IKE request message.
Definition: ike_misc.c:56
systime_t osGetSystemTime(void)
Retrieve system time.
void ikeFreeDhContext(IkeSaEntry *sa)
Release Diffie-Hellman context.