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-2025 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.5.4
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 
401  //Loop through Child SA entries
402  for(i = 0; i < context->numChildSaEntries; i++)
403  {
404  //Point to the current Child SA
405  childSa = &context->childSa[i];
406 
407  //Check whether the current Child SA is free
408  if(childSa->state == IKE_CHILD_SA_STATE_CLOSED)
409  {
410  //Clear Child SA entry
411  osMemset(childSa, 0, sizeof(IkeChildSaEntry));
412 
413  //Attach IKE context
414  childSa->context = context;
415 
416  //Allocate inbound SAD entry
417  childSa->inboundSa = ipsecAllocateSadEntry(netContext.ipsecContext);
418 
419  //Failed to allocated SAD entry?
420  if(childSa->inboundSa < 0)
421  {
422  //The SAD database runs out of space
423  return NULL;
424  }
425 
426  //Allocate outbound SAD entry
427  childSa->outboundSa = ipsecAllocateSadEntry(netContext.ipsecContext);
428 
429  //Failed to allocated SAD entry?
430  if(childSa->outboundSa < 0)
431  {
432  //Clean up side effects
433  ipsecClearSadEntry(netContext.ipsecContext, childSa->inboundSa);
434  //The SAD database runs out of space
435  return NULL;
436  }
437 
438  //Default state
439  childSa->state = IKE_CHILD_SA_STATE_RESERVED;
440 
441  //Return a pointer to the newly created Child SA
442  return childSa;
443  }
444  }
445 
446  //The Child SA table runs out of space
447  return NULL;
448 }
449 
450 
451 /**
452  * @brief Find an Child SA that matches the specified SPI
453  * @param[in] sa Pointer to the IKE SA
454  * @param[in] protocolId Protocol identifier (AH or ESP)
455  * @param[in] spi Security parameter index
456  * @return Pointer to the matching Child SA, if any
457  **/
458 
460  const uint8_t *spi)
461 {
462  uint_t i;
463  IkeContext *context;
464  IkeChildSaEntry *childSa;
465 
466  //Point to the IKE context
467  context = sa->context;
468 
469  //Loop through Child SA entries
470  for(i = 0; i < context->numChildSaEntries; i++)
471  {
472  //Point to the current Child SA
473  childSa = &context->childSa[i];
474 
475  //Check the state of the Child SA
476  if(childSa->state != IKE_CHILD_SA_STATE_CLOSED)
477  {
478  //Matching IKE SA and protocol identifier?
479  if(childSa->sa == sa && childSa->protocol == protocolId)
480  {
481  //Compare SPIs
482  if(osMemcmp(childSa->remoteSpi, spi, IPSEC_SPI_SIZE) == 0)
483  {
484  //A matching Child SA has been found
485  return childSa;
486  }
487  }
488  }
489  }
490 
491  //The specified SPI does not match any Child SA
492  return NULL;
493 }
494 
495 
496 /**
497  * @brief Delete a Child Security Association
498  * @param[in] childSa Pointer to the Child SA
499  **/
500 
502 {
503  //Debug message
504  TRACE_INFO("Deleting Child SA...\r\n");
505 
506  //Close inbound SAD entry
507  if(childSa->inboundSa >= 0)
508  {
509  ipsecClearSadEntry(netContext.ipsecContext, childSa->inboundSa);
510  }
511 
512  //Close outbound SAD entry
513  if(childSa->outboundSa >= 0)
514  {
515  ipsecClearSadEntry(netContext.ipsecContext, childSa->outboundSa);
516  }
517 
518  //Mark the Child SA as closed
519  childSa->state = IKE_CHILD_SA_STATE_CLOSED;
520 }
521 
522 
523 /**
524  * @brief Generate a new IKE SA SPI
525  * @param[in] sa Pointer to the IKE SA
526  * @param[out] spi Pointer to the buffer where to store the resulting SPI
527  * @return Error code
528  **/
529 
531 {
532  error_t error;
533  uint_t i;
534  IkeContext *context;
535  IkeSaEntry *entry;
536 
537  //Debug message
538  TRACE_INFO("Generating new IKE SA SPI (%u bytes)...\r\n", IKE_SPI_SIZE);
539 
540  //Point to the IKE context
541  context = sa->context;
542 
543  //Each endpoint chooses one of the two SPIs and must choose them so as to
544  //be unique identifiers of an IKE SA (refer to RFC 7296, section 2.6)
545  do
546  {
547  //Generate an arbitrary 8-octet value
548  error = context->prngAlgo->generate(context->prngContext, spi,
549  IKE_SPI_SIZE);
550 
551  //Check status code
552  if(!error)
553  {
554  //Non-zero SPI value?
556  {
557  //Loop through IKE SA entries
558  for(i = 0; i < context->numSaEntries && !error; i++)
559  {
560  //Point to the current IKE SA
561  entry = &context->sa[i];
562 
563  //Check the state of the IKE SA
564  if(entry != sa && entry->state != IKE_SA_STATE_CLOSED)
565  {
566  //Check whether the entity is the original initiator of the
567  //IKE SA
568  if(entry->originalInitiator)
569  {
570  //Test whether the SPI is a duplicate
571  if(osMemcmp(spi, entry->initiatorSpi, IKE_SPI_SIZE) == 0)
572  {
573  error = ERROR_INVALID_SPI;
574  }
575  }
576  else
577  {
578  //Test whether the SPI is a duplicate
579  if(osMemcmp(spi, entry->responderSpi, IKE_SPI_SIZE) == 0)
580  {
581  error = ERROR_INVALID_SPI;
582  }
583  }
584  }
585  }
586  }
587  else
588  {
589  //The SPI value must not be zero (refer to RFC 7296, section 3.1)
590  error = ERROR_INVALID_SPI;
591  }
592  }
593 
594  //Repeat as necessary until a unique SPI is generated
595  } while(error == ERROR_INVALID_SPI);
596 
597  //Check status code
598  if(!error)
599  {
600  //Debug message
602  }
603 
604  //Return status code
605  return error;
606 }
607 
608 
609 /**
610  * @brief Generate a new Child SA SPI
611  * @param[in] childSa Pointer to the Child SA
612  * @param[out] spi Pointer to the buffer where to store the resulting SPI
613  * @return Error code
614  **/
615 
617 {
618  error_t error;
619  uint_t i;
620  IkeContext *context;
621  IkeChildSaEntry *entry;
622 
623  //Debug message
624  TRACE_INFO("Generating new Child SA SPI (%u bytes)...\r\n", IKE_SPI_SIZE);
625 
626  //Point to the IKE context
627  context = childSa->context;
628 
629  //Generate a unique SPI value
630  do
631  {
632  //Generate an arbitrary 4-octet value
633  error = context->prngAlgo->generate(context->prngContext, spi,
635 
636  //Check status code
637  if(!error)
638  {
639  //Non-zero SPI value?
641  {
642  //Loop through Child SA entries
643  for(i = 0; i < context->numChildSaEntries && !error; i++)
644  {
645  //Point to the current Child SA
646  entry = &context->childSa[i];
647 
648  //Check the state of the Child SA
649  if(entry != childSa && entry->state != IKE_CHILD_SA_STATE_CLOSED)
650  {
651  //Test whether the SPI is a duplicate
652  if(osMemcmp(spi, entry->localSpi, IPSEC_SPI_SIZE) == 0)
653  {
654  error = ERROR_INVALID_SPI;
655  }
656  }
657  }
658  }
659  else
660  {
661  //The SPI value of zero is reserved and must not be sent on the
662  //wire (refer to RFC 4302, section 2.4 and RFC 4303, section 2.1)
663  error = ERROR_INVALID_SPI;
664  }
665  }
666 
667  //Repeat as necessary until a unique SPI is generated
668  } while(error == ERROR_INVALID_SPI);
669 
670  //Check status code
671  if(!error)
672  {
673  //Debug message
675  }
676 
677  //Return status code
678  return error;
679 }
680 
681 
682 /**
683  * @brief Generate a new nonce
684  * @param[in] context Pointer to the IKE context
685  * @param[out] nonce Pointer to the buffer where to store the resulting nonce
686  * @param[in] length Length of the nonce, in bytes
687  * @return Error code
688  **/
689 
690 error_t ikeGenerateNonce(IkeContext *context, uint8_t *nonce, size_t *length)
691 {
692  error_t error;
693 
694  //Debug message
695  TRACE_INFO("Generating new nonce (%u bytes)...\r\n", IKE_DEFAULT_NONCE_SIZE);
696 
697  //Nonces used in IKEv2 must be randomly chosen and must be at least 128 bits
698  //in size (refer to RFC 7296, section 2.10)
699  error = context->prngAlgo->generate(context->prngContext, nonce,
701 
702  //Check status code
703  if(!error)
704  {
705  //Set the length of the nonce
707 
708  //Debug message
710  }
711 
712  //Return status code
713  return error;
714 }
715 
716 
717 /**
718  * @brief Apply random jitter to a time interval
719  * @param[in] context Pointer to the IKE context
720  * @param[out] delay Time interval to be randomized
721  * @return Randomized time interval
722  **/
723 
725 {
726  error_t error;
729 
730  //Maximum jitter to be applied to the time interval
731  delta = (delay * IKE_RANDOM_JITTER) / 100;
732 
733  //Sanity check
734  if(delta > 0)
735  {
736  //Generate a random value
737  error = context->prngAlgo->generate(context->prngContext,
738  (uint8_t *) &value, sizeof(value));
739 
740  //Check status code
741  if(!error)
742  {
743  //Apply random jitter to the time interval
744  delay -= value % delta;
745  }
746  }
747 
748  //Return the randomized time interval
749  return delay;
750 }
751 
752 
753 /**
754  * @brief Traffic selector selection
755  * @param[in] childSa Pointer to the Child SA
756  * @param[in] tsiPayload Pointer to the TSi payload
757  * @param[in] tsrPayload Pointer to the TSr payload
758  * @return Error code
759  **/
760 
761 error_t ikeSelectTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload,
762  const IkeTsPayload *tsrPayload)
763 {
764  error_t error;
765  size_t n;
766  IkeTsParams localTsParams;
767  IkeTsParams remoteTsParams;
768  IpsecSpdEntry *spdEntry;
769  IpsecSelector selector;
770 
771  //Get the length of the TSi payload
772  n = ntohs(tsiPayload->header.payloadLength);
773 
774  //Malformed TSi payload?
775  if(n < sizeof(IkeTsPayload))
776  return ERROR_INVALID_MESSAGE;
777 
778  //Check the number of traffic selectors
779  if(tsiPayload->numTs < 1)
780  return ERROR_INVALID_MESSAGE;
781 
782  //Parse the first Traffic Selector substructure of the TSi payload
783  error = ikeParseTs(tsiPayload->trafficSelectors, n - sizeof(IkeTsPayload),
784  &remoteTsParams);
785  //Any error to report?
786  if(error)
787  return error;
788 
789  //Get the length of the TSr payload
790  n = ntohs(tsrPayload->header.payloadLength);
791 
792  //Malformed TSi payload?
793  if(n < sizeof(IkeTsPayload))
794  return ERROR_INVALID_MESSAGE;
795 
796  //Check the number of traffic selectors
797  if(tsrPayload->numTs < 1)
798  return ERROR_INVALID_MESSAGE;
799 
800  //Parse the first Traffic Selector substructure of the TSr payload
801  error = ikeParseTs(tsrPayload->trafficSelectors, n - sizeof(IkeTsPayload),
802  &localTsParams);
803  //Any error to report?
804  if(error)
805  return error;
806 
807  //Make sure the IP Protocol ID fields are consistent
808  if(localTsParams.ipProtocolId != remoteTsParams.ipProtocolId)
809  return ERROR_INVALID_PROTOCOL;
810 
811  //Retrieve selector parameters
812  selector.localIpAddr.start = localTsParams.startAddr;
813  selector.localIpAddr.end = localTsParams.endAddr;
814  selector.remoteIpAddr.start = remoteTsParams.startAddr;
815  selector.remoteIpAddr.end = remoteTsParams.endAddr;
816  selector.nextProtocol = localTsParams.ipProtocolId;
817  selector.localPort.start = localTsParams.startPort;
818  selector.localPort.end = localTsParams.endPort;
819  selector.remotePort.start = remoteTsParams.startPort;
820  selector.remotePort.end = remoteTsParams.endPort;
821 
822  //A responder uses the traffic selector proposals it receives via an SA
823  //management protocol to select an appropriate entry in its SPD (refer to
824  //RFC 4301, section 4.4.1)
826  IPSEC_POLICY_ACTION_PROTECT, &selector);
827  //No matching SPD entry?
828  if(spdEntry == NULL)
829  return ERROR_INVALID_SELECTOR;
830 
831  //IKEv2 allows the responder to choose a subset of the traffic proposed by
832  //the initiator (refer to RFC 7296, section 2.9)
833  if(!ipsecIntersectSelectors(&spdEntry->selector, &selector,
834  &childSa->selector))
835  {
836  return ERROR_INVALID_SELECTOR;
837  }
838 
839  //The SPD entry specifies the security protocol (AH or ESP) to employ
840  childSa->protocol = spdEntry->protocol;
841 
842  //Successful processing
843  return NO_ERROR;
844 }
845 
846 
847 /**
848  * @brief Check whether the selected traffic selectors are acceptable
849  * @param[in] childSa Pointer to the Child SA
850  * @param[in] tsiPayload Pointer to the TSi payload
851  * @param[in] tsrPayload Pointer to the TSr payload
852  * @return Error code
853  **/
854 
855 error_t ikeCheckTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload,
856  const IkeTsPayload *tsrPayload)
857 {
858  error_t error;
859  size_t n;
860  IpsecSelector selector;
861  IkeTsParams localTsParams;
862  IkeTsParams remoteTsParams;
863 
864  //Get the length of the TSi payload
865  n = ntohs(tsiPayload->header.payloadLength);
866 
867  //Malformed TSi payload?
868  if(n < sizeof(IkeTsPayload))
869  return ERROR_INVALID_MESSAGE;
870 
871  //Check the number of traffic selectors
872  if(tsiPayload->numTs < 1)
873  return ERROR_INVALID_MESSAGE;
874 
875  //Parse the first Traffic Selector substructure of the TSi payload
876  error = ikeParseTs(tsiPayload->trafficSelectors, n - sizeof(IkeTsPayload),
877  &localTsParams);
878  //Any error to report?
879  if(error)
880  return error;
881 
882  //Get the length of the TSr payload
883  n = ntohs(tsrPayload->header.payloadLength);
884 
885  //Malformed TSi payload?
886  if(n < sizeof(IkeTsPayload))
887  return ERROR_INVALID_MESSAGE;
888 
889  //Check the number of traffic selectors
890  if(tsrPayload->numTs < 1)
891  return ERROR_INVALID_MESSAGE;
892 
893  //Parse the first Traffic Selector substructure of the TSr payload
894  error = ikeParseTs(tsrPayload->trafficSelectors, n - sizeof(IkeTsPayload),
895  &remoteTsParams);
896  //Any error to report?
897  if(error)
898  return error;
899 
900  //Make sure the IP Protocol ID fields are consistent
901  if(localTsParams.ipProtocolId != remoteTsParams.ipProtocolId)
902  return ERROR_INVALID_PROTOCOL;
903 
904  //Retrieve selector parameters
905  selector.localIpAddr.start = localTsParams.startAddr;
906  selector.localIpAddr.end = localTsParams.endAddr;
907  selector.remoteIpAddr.start = remoteTsParams.startAddr;
908  selector.remoteIpAddr.end = remoteTsParams.endAddr;
909  selector.nextProtocol = localTsParams.ipProtocolId;
910  selector.localPort.start = localTsParams.startPort;
911  selector.localPort.end = localTsParams.endPort;
912  selector.remotePort.start = remoteTsParams.startPort;
913  selector.remotePort.end = remoteTsParams.endPort;
914 
915  //IKEv2 allows the responder to choose a subset of the traffic proposed by
916  //the initiator (refer to RFC 7296, section 2.9)
917  if(!ipsecIsSubsetSelector(&selector, &childSa->selector))
918  return ERROR_INVALID_SELECTOR;
919 
920  //Save traffic selector
921  childSa->selector = selector;
922 
923  //The selected traffic selectors are acceptable
924  return NO_ERROR;
925 }
926 
927 
928 /**
929  * @brief Check the length of the nonce
930  * @param[in] sa Pointer to the IKE SA
931  * @param[in] nonceLen Length of the nonce, in bytes
932  * @return Error code
933  **/
934 
936 {
937  size_t prfKeyLen;
938 
939 #if (IKE_CMAC_PRF_SUPPORT == ENABLED && IKE_AES_128_SUPPORT == ENABLED)
940  //AES-CMAC PRF algorithm?
941  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_AES128_CMAC)
942  {
943  prfKeyLen = 16;
944  }
945  else
946 #endif
947 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_MD5_SUPPORT == ENABLED)
948  //HMAC-MD5 PRF algorithm?
949  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_MD5)
950  {
951  prfKeyLen = MD5_DIGEST_SIZE;
952  }
953  else
954 #endif
955 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA1_SUPPORT == ENABLED)
956  //HMAC-SHA1 PRF algorithm?
957  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA1)
958  {
959  prfKeyLen = SHA1_DIGEST_SIZE;
960  }
961  else
962 #endif
963 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA256_SUPPORT == ENABLED)
964  //HMAC-SHA256 PRF algorithm?
965  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA2_256)
966  {
967  prfKeyLen = SHA256_DIGEST_SIZE;
968  }
969  else
970 #endif
971 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA384_SUPPORT == ENABLED)
972  //HMAC-SHA384 PRF algorithm?
973  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA2_384)
974  {
975  prfKeyLen = SHA384_DIGEST_SIZE;
976  }
977  else
978 #endif
979 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA512_SUPPORT == ENABLED)
980  //HMAC-SHA512 PRF algorithm?
981  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA2_512)
982  {
983  prfKeyLen = SHA512_DIGEST_SIZE;
984  }
985  else
986 #endif
987 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_TIGER_SUPPORT == ENABLED)
988  //HMAC-Tiger PRF algorithm?
989  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_TIGER)
990  {
991  prfKeyLen = TIGER_DIGEST_SIZE;
992  }
993  else
994 #endif
995 #if (IKE_XCBC_MAC_PRF_SUPPORT == ENABLED && IKE_AES_128_SUPPORT == ENABLED)
996  //AES-XCBC-MAC PRF algorithm?
997  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_AES128_XCBC)
998  {
999  prfKeyLen = 16;
1000  }
1001  else
1002 #endif
1003  //Unknown PRF algorithm?
1004  {
1005  prfKeyLen = 0;
1006  }
1007 
1008  //Nonces used in IKEv2 must be at least half the key size of the negotiated
1009  //pseudorandom function (refer to RFC 7296, section 2.10)
1010  if(nonceLen >= (prfKeyLen / 2))
1011  {
1012  return NO_ERROR;
1013  }
1014  else
1015  {
1016  return ERROR_INVALID_LENGTH;
1017  }
1018 }
1019 
1020 
1021 /**
1022  * @brief Create AH or ESP SA pair
1023  * @param[in] childSa Pointer to the Child SA
1024  * @return Error code
1025  **/
1026 
1028 {
1029  error_t error;
1030  IpsecSadEntry sadEntry;
1031 
1032  //Debug message
1033  TRACE_INFO("Creating IPsec SA pair...\r\n");
1034  TRACE_INFO(" Outbound SPI = 0x%08" PRIX32 "\r\n", LOAD32BE(childSa->remoteSpi));
1035  TRACE_INFO(" Inbound SPI = 0x%08" PRIX32 "\r\n", LOAD32BE(childSa->localSpi));
1036 
1037  //Set SAD entry parameters (outbound traffic)
1038  osMemset(&sadEntry, 0, sizeof(IpsecSadEntry));
1039  sadEntry.direction = IPSEC_DIR_OUTBOUND;
1040  sadEntry.mode = childSa->mode;
1041  sadEntry.protocol = childSa->protocol;
1042  sadEntry.selector = childSa->selector;
1043  sadEntry.spi = LOAD32BE(childSa->remoteSpi);
1044  sadEntry.authCipherAlgo = childSa->authCipherAlgo;
1045  sadEntry.authHashAlgo = childSa->authHashAlgo;
1046  sadEntry.authKeyLen = childSa->authKeyLen;
1047  sadEntry.icvLen = childSa->icvLen;
1048  sadEntry.esn = (childSa->esn == IKE_TRANSFORM_ID_ESN_YES) ? TRUE : FALSE;
1049  sadEntry.seqNum = 0;
1050  sadEntry.antiReplayEnabled = TRUE;
1051 
1052  //Set integrity protection key
1053  if(childSa->initiator)
1054  {
1055  osMemcpy(sadEntry.authKey, childSa->skai, childSa->authKeyLen);
1056  }
1057  else
1058  {
1059  osMemcpy(sadEntry.authKey, childSa->skar, childSa->authKeyLen);
1060  }
1061 
1062 #if (ESP_SUPPORT == ENABLED)
1063  //Set encryption parameters
1064  sadEntry.cipherMode = childSa->cipherMode;
1065  sadEntry.cipherAlgo = childSa->cipherAlgo;
1066  sadEntry.encKeyLen = childSa->encKeyLen;
1067  sadEntry.saltLen = childSa->saltLen;
1068  sadEntry.ivLen = childSa->ivLen;
1069 
1070  //Set encryption key
1071  if(childSa->initiator)
1072  {
1073  osMemcpy(sadEntry.encKey, childSa->skei, childSa->encKeyLen +
1074  childSa->saltLen);
1075  }
1076  else
1077  {
1078  osMemcpy(sadEntry.encKey, childSa->sker, childSa->encKeyLen +
1079  childSa->saltLen);
1080  }
1081 
1082  //Check encryption mode
1083  if(childSa->protocol == IPSEC_PROTOCOL_ESP &&
1084  childSa->cipherMode != CIPHER_MODE_CBC)
1085  {
1086  //Copy initialization vector
1087  osMemcpy(sadEntry.iv, childSa->iv, childSa->ivLen);
1088  }
1089 #endif
1090 
1091  //Update SAD entry (outbound traffic)
1092  error = ipsecSetSadEntry(netContext.ipsecContext, childSa->outboundSa,
1093  &sadEntry);
1094 
1095  //Check status code
1096  if(!error)
1097  {
1098  //Set SAD entry parameters (inbound traffic)
1099  osMemset(&sadEntry, 0, sizeof(IpsecSadEntry));
1100  sadEntry.direction = IPSEC_DIR_INBOUND;
1101  sadEntry.mode = childSa->mode;
1102  sadEntry.protocol = childSa->protocol;
1103  sadEntry.selector = childSa->selector;
1104  sadEntry.spi = LOAD32BE(childSa->localSpi);
1105  sadEntry.authCipherAlgo = childSa->authCipherAlgo;
1106  sadEntry.authHashAlgo = childSa->authHashAlgo;
1107  sadEntry.authKeyLen = childSa->authKeyLen;
1108  sadEntry.icvLen = childSa->icvLen;
1109  sadEntry.esn = (childSa->esn == IKE_TRANSFORM_ID_ESN_YES) ? TRUE : FALSE;
1110  sadEntry.seqNum = 0;
1111  sadEntry.antiReplayEnabled = TRUE;
1112 
1113  //Set integrity protection key
1114  if(childSa->initiator)
1115  {
1116  osMemcpy(sadEntry.authKey, childSa->skar, childSa->authKeyLen);
1117  }
1118  else
1119  {
1120  osMemcpy(sadEntry.authKey, childSa->skai, childSa->authKeyLen);
1121  }
1122 
1123 #if (ESP_SUPPORT == ENABLED)
1124  //Set encryption parameters
1125  sadEntry.cipherMode = childSa->cipherMode;
1126  sadEntry.cipherAlgo = childSa->cipherAlgo;
1127  sadEntry.encKeyLen = childSa->encKeyLen;
1128  sadEntry.saltLen = childSa->saltLen;
1129  sadEntry.ivLen = childSa->ivLen;
1130 
1131  //Set encryption key
1132  if(childSa->initiator)
1133  {
1134  osMemcpy(sadEntry.encKey, childSa->sker, childSa->encKeyLen +
1135  childSa->saltLen);
1136  }
1137  else
1138  {
1139  osMemcpy(sadEntry.encKey, childSa->skei, childSa->encKeyLen +
1140  childSa->saltLen);
1141  }
1142 #endif
1143 
1144  //Update SAD entry (inbound traffic)
1145  error = ipsecSetSadEntry(netContext.ipsecContext, childSa->inboundSa,
1146  &sadEntry);
1147  }
1148 
1149  //Return status code
1150  return error;
1151 }
1152 
1153 
1154 /**
1155  * @brief Test if the IKE SA is the only currently active with a given peer
1156  * @param[in] sa Pointer to the IKE SA
1157  * @return TRUE if this IKE SA is the only IKE SA currently active between the
1158  * authenticated identities, else FALSE
1159  **/
1160 
1162 {
1163  uint_t i;
1164  IkeContext *context;
1165  IkeSaEntry *entry;
1166 
1167  //Point to the IKE context
1168  context = sa->context;
1169 
1170  //Loop through IKE SA entries
1171  for(i = 0; i < context->numSaEntries; i++)
1172  {
1173  //Point to the current IKE SA
1174  entry = &context->sa[i];
1175 
1176  //Check the state of the IKE SA
1177  if(entry != sa && entry->state != IKE_SA_STATE_CLOSED)
1178  {
1179  //Check whether another IKE SA exists between the authenticated
1180  //identities
1181  if(ipCompAddr(&entry->remoteIpAddr, &sa->remoteIpAddr))
1182  {
1183  return FALSE;
1184  }
1185  }
1186  }
1187 
1188  //This IKE SA is the only IKE SA currently active between the authenticated
1189  //identities
1190  return TRUE;
1191 }
1192 
1193 #endif
#define IPSEC_SPI_SIZE
Definition: ipsec.h:138
Diffie-Hellman key exchange.
int bool_t
Definition: compiler_port.h:61
@ IKE_TRANSFORM_ID_PRF_AES128_CMAC
Definition: ike.h:982
Helper functions for IKEv2.
uint16_t end
Definition: ipsec.h:293
@ CIPHER_MODE_CBC
Definition: crypto.h:1036
@ IPSEC_DIR_INBOUND
Definition: ipsec.h:167
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:302
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:530
#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:724
IpAddr endAddr
Definition: ike.h:1767
IpAddr end
Definition: ipsec.h:282
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
NetContext netContext
Definition: net.c:75
#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:761
@ 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:233
@ IPSEC_PROTOCOL_ESP
Definition: ipsec.h:193
@ IPSEC_DIR_OUTBOUND
Definition: ipsec.h:168
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:305
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:317
IpsecPortRange remotePort
Remote port range.
Definition: ipsec.h:307
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:349
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:459
@ 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:185
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:501
#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:935
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:855
@ IKE_TRANSFORM_ID_PRF_HMAC_SHA2_256
Definition: ike.h:979
@ IKE_CHILD_SA_STATE_CLOSED
Definition: ike.h:1348
void * ipsecContext
IPsec context.
Definition: net.h:339
IpAddr start
Definition: ipsec.h:281
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:292
IKEv2 (Internet Key Exchange Protocol)
error_t ikeCreateIpsecSaPair(IkeChildSaEntry *childSa)
Create AH or ESP SA pair.
Definition: ike_misc.c:1027
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:303
@ 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:616
uint8_t value[]
Definition: tcp.h:376
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:1512
bool_t ikeIsInitialContact(IkeSaEntry *sa)
Test if the IKE SA is the only currently active with a given peer.
Definition: ike_misc.c:1161
#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:690
Security Policy Database (SPD) entry.
Definition: ipsec.h:344
#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:347
#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:268
uint16_t endPort
Definition: ike.h:1770
#define IKE_RANDOM_JITTER
Definition: ike.h:159
IpsecPortRange localPort
Local port range.
Definition: ipsec.h:306
#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:304
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.