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.6
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 + IKE_PREFIX_SIZE, sa->requestLen);
70 
71 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
72  //IKE packets must be sent from UDP port 500 or 4500
73  if(sa->localNat || sa->remoteNat)
74  {
75  //The UDP payload of all packets containing IKE messages sent on port 4500
76  //must begin with the prefix of four zeros (refer to RFC 7296, section 2)
77  error = socketSendTo(context->altSocket, &sa->remoteIpAddr, IPSEC_NAT_PORT,
78  sa->request, sa->requestLen + IKE_PREFIX_SIZE, NULL, 0);
79  }
80  else
81 #endif
82  {
83  //A retransmission from the initiator must be bitwise identical to the
84  //original request (refer to RFC 7296, section 2.1)
85  error = socketSendTo(context->socket, &sa->remoteIpAddr, IKE_PORT,
86  sa->request + IKE_PREFIX_SIZE, sa->requestLen, NULL, 0);
87  }
88 
89  //Retransmission times must increase exponentially to avoid flooding the
90  //network and making an existing congestion situation worse (refer to
91  //RFC 7296, section 2.4)
92  sa->timeout = MIN(sa->timeout * 2, IKE_MAX_TIMEOUT);
93 
94  //Save the time at which the message was sent
95  sa->timestamp = osGetSystemTime();
96 
97  //Increment retransmission counter
98  sa->retransmitCount++;
99 
100 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
101  //A peer should send a NAT-keepalive packet if no other packet to the peer
102  //has been sent in M seconds (refer to RFC 3948, section 4)
103  sa->natKeepAliveTimestamp = sa->timestamp;
104 #endif
105 
106  //Return status code
107  return error;
108 }
109 
110 
111 /**
112  * @brief Retransmit IKE response message
113  * @param[in] sa Pointer to the IKE SA
114  * @return Error code
115  **/
116 
118 {
119  error_t error;
120  SocketMsg msg;
121  IkeContext *context;
122 
123  //Initialize status code
124  error = NO_ERROR;
125 
126  //Point to the IKE context
127  context = sa->context;
128 
129  //In order to allow saving memory, responders are allowed to forget the
130  //response after a timeout of several minutes
131  if(sa->responseLen > 0)
132  {
133  //Debug message
134  TRACE_INFO("Retransmitting IKE response (%" PRIuSIZE " bytes)...\r\n",
135  sa->responseLen);
136 
137  //Dump IKE message for debugging purpose
138  ikeDumpMessage(sa->response + IKE_PREFIX_SIZE, sa->responseLen);
139 
140  //An implementation must specify the address and port at which the request
141  //was received as the source address and port in the response (refer to
142  //RFC 7296, section 2.11)
143  msg = SOCKET_DEFAULT_MSG;
144  msg.interface = context->localInterface;
145  msg.srcIpAddr = context->localIpAddr;
146  msg.destIpAddr = context->remoteIpAddr;
147  msg.destPort = context->remotePort;
148 
149 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
150  //IKE packets must be sent from UDP port 500 or 4500
151  if(context->localPort == IPSEC_NAT_PORT)
152  {
153  //The UDP payload of all packets containing IKE messages sent on port
154  //4500 must begin with the prefix of four zeros (refer to RFC 7296,
155  //section 2)
156  msg.data = sa->response;
157  msg.length = sa->responseLen + IKE_PREFIX_SIZE;
158 
159  //Retransmit the response from UDP port 4500
160  error = socketSendMsg(context->altSocket, &msg, 0);
161  }
162  else
163 #endif
164  {
165  //Point to the IKE message to be retransmitted
166  msg.data = sa->response + IKE_PREFIX_SIZE;
167  msg.length = sa->responseLen;
168 
169  //Retransmit the response from UDP port 500
170  error = socketSendMsg(context->socket, &msg, 0);
171  }
172  }
173 
174  //Return status code
175  return error;
176 }
177 
178 
179 /**
180  * @brief Create a new IKE Security Association
181  * @param[in] context Pointer to the IKE context
182  * @return Pointer to the newly created IKE SA
183  **/
184 
186 {
187  uint_t i;
188  IkeSaEntry *sa;
189 
190  //Loop through IKE SA entries
191  for(i = 0; i < context->numSaEntries; i++)
192  {
193  //Point to the current IKE SA
194  sa = &context->sa[i];
195 
196  //Check whether the current IKE SA is free
197  if(sa->state == IKE_SA_STATE_CLOSED)
198  {
199  //Clear IKE SA entry
200  osMemset(sa, 0, sizeof(IkeSaEntry));
201 
202  //Attach IKE context
203  sa->context = context;
204 
205  //Initialize IKE SA parameters
206  sa->txMessageId = UINT32_MAX;
207  sa->rxMessageId = UINT32_MAX;
208 
209  //Initialize Diffie-Hellman context
210  ikeInitKeContext(&sa->keContext);
211 
212  //Default state
213  sa->state = IKE_SA_STATE_RESERVED;
214 
215  //Return a pointer to the newly created IKE SA
216  return sa;
217  }
218  }
219 
220  //The IKE SA table runs out of space
221  return NULL;
222 }
223 
224 
225 /**
226  * @brief Find an IKE SA that matches an incoming IKE message
227  * @param[in] context Pointer to the IKE context
228  * @param[in] ikeHeader Pointer to the IKE header
229  * @return Pointer to the matching IKE SA, if any
230  **/
231 
232 IkeSaEntry *ikeFindSaEntry(IkeContext *context, const IkeHeader *ikeHeader)
233 {
234  uint_t i;
235  const uint8_t *spi;
236  IkeSaEntry *sa;
237 
238  //The I bit is used by the recipient to determine which eight octets of the
239  //SPI were generated by the recipient (refer to RFC 7296, section 3.1)
240  if((ikeHeader->flags & IKE_FLAGS_I) != 0)
241  {
242  spi = ikeHeader->responderSpi;
243  }
244  else
245  {
246  spi = ikeHeader->initiatorSpi;
247  }
248 
249  //Loop through IKE SA entries
250  for(i = 0; i < context->numSaEntries; i++)
251  {
252  //Point to the current IKE SA
253  sa = &context->sa[i];
254 
255  //Check whether the current IKE SA is active
256  if(sa->state != IKE_SA_STATE_CLOSED)
257  {
258  //Check whether the entity is the original initiator of the IKE SA
259  if(sa->originalInitiator)
260  {
261  //Compare SPIs
262  if(osMemcmp(sa->initiatorSpi, spi, IKE_SPI_SIZE) == 0)
263  {
264  //A matching IKE SA has been found
265  return sa;
266  }
267  }
268  else
269  {
270  //Compare SPIs
271  if(osMemcmp(sa->responderSpi, spi, IKE_SPI_SIZE) == 0)
272  {
273  //A matching IKE SA has been found
274  return sa;
275  }
276  }
277  }
278  }
279 
280  //The incoming IKE message does not match any IKE SA
281  return NULL;
282 }
283 
284 
285 /**
286  * @brief Find an half-open IKE SA that matches an incoming IKE_SA_INIT request
287  * @param[in] context Pointer to the IKE context
288  * @param[in] ikeHeader Pointer to the IKE header
289  * @param[in] noncePayload Pointer to the Ni payload
290  * @return Pointer to the matching IKE SA, if any
291  **/
292 
294  const IkeHeader *ikeHeader, const IkeNoncePayload *noncePayload)
295 {
296  uint_t i;
297  size_t n;
298  IkeSaEntry *sa;
299 
300  //Retrieve the length of the Ni payload
301  n = ntohs(noncePayload->header.payloadLength);
302 
303  //Check the length of the Ni payload
304  if(n >= sizeof(IkeNoncePayload))
305  {
306  //Determine the length of the nonce
307  n -= sizeof(IkeNoncePayload);
308 
309  //Loop through IKE SA entries
310  for(i = 0; i < context->numSaEntries; i++)
311  {
312  //Point to the current IKE SA
313  sa = &context->sa[i];
314 
315  //Check whether the current IKE SA is active
316  if(sa->state != IKE_SA_STATE_CLOSED)
317  {
318  //Compare SPIs
319  if(osMemcmp(sa->initiatorSpi, ikeHeader->initiatorSpi,
320  IKE_SPI_SIZE) == 0)
321  {
322  //It is not sufficient to use the initiator's SPI to lookup the
323  //IKE SA. Instead, a robust responder will do the IKE SA lookup
324  //using the whole packet, its hash, or the Ni payload (refer to
325  //RFC 7296, section 2.1)
326  if(sa->initiatorNonceLen == n && osMemcmp(sa->initiatorNonce,
327  noncePayload->nonceData, n) == 0)
328  {
329  //A matching IKE SA has been found
330  return sa;
331  }
332  }
333  }
334  }
335  }
336 
337  //The incoming IKE_SA_INIT request does not match any half-open IKE SA
338  return NULL;
339 }
340 
341 
342 /**
343  * @brief Delete an IKE Security Association
344  * @param[in] sa Pointer to the IKE SA
345  **/
346 
348 {
349  uint_t i;
350  IkeContext *context;
351  IkeChildSaEntry *childSa;
352 
353  //Valid IKE SA?
354  if(sa != NULL)
355  {
356  //Debug message
357  TRACE_INFO("Deleting IKE SA...\r\n");
358 
359  //Point to the IKE context
360  context = sa->context;
361 
362  //Achieving perfect forward secrecy requires that when a connection is
363  //closed, each endpoint must forget not only the keys used by the
364  //connection but also any information that could be used to recompute
365  //those keys (refer to RFC 7296, section 2.12)
366  ikeFreeKeContext(&sa->keContext);
367 
368  //Loop through Child SA entries
369  for(i = 0; i < context->numChildSaEntries; i++)
370  {
371  //Point to the current Child SA
372  childSa = &context->childSa[i];
373 
374  //Check the state of the Child SA
375  if(childSa->state != IKE_CHILD_SA_STATE_CLOSED)
376  {
377  //Deleting an IKE SA implicitly closes any remaining Child SAs
378  //negotiated under it (refer to RFC 7296, section 1.4.1)
379  if(childSa->sa == sa)
380  {
381  ikeDeleteChildSaEntry(childSa);
382  }
383  }
384  }
385 
386 #if (IKE_REAUTH_SUPPORT == ENABLED)
387  //Check whether reauthentication is on-going
388  if(sa->oldSa != NULL && sa->oldSa->state != IKE_SA_STATE_CLOSED)
389  {
390  //Close the old IKE SA since reauthentication has failed
391  sa->oldSa->deleteRequest = TRUE;
392  //Notify the IKE context that the IKE SA should be closed
393  osSetEvent(&context->event);
394  }
395 #endif
396 
397  //Mark the IKE SA as closed
398  sa->state = IKE_SA_STATE_CLOSED;
399  }
400 }
401 
402 
403 /**
404  * @brief Delete an duplicate IKE Security Associations
405  * @param[in] sa Pointer to the currently active IKE SA
406  **/
407 
409 {
410  uint_t i;
411  IkeContext *context;
412  IkeSaEntry *entry;
413 
414  //Debug message
415  TRACE_INFO("Deleting duplicate IKE SAs...\r\n");
416 
417  //Point to the IKE context
418  context = sa->context;
419 
420  //Loop through IKE SA entries
421  for(i = 0; i < context->numSaEntries; i++)
422  {
423  //Point to the current IKE SA
424  entry = &context->sa[i];
425 
426  //Check the state of the IKE SA
427  if(entry != sa && entry->state != IKE_SA_STATE_CLOSED)
428  {
429  //Different IKE SA with same authenticated identity?
430  if(entry->peerIdType == sa->peerIdType &&
431  entry->peerIdLen == sa->peerIdLen &&
432  osMemcmp(entry->peerId, sa->peerId, sa->peerIdLen) == 0)
433  {
434  //The recipient of an INITIAL_CONTACT notification may use this
435  //information to delete any other IKE SAs it has to the same
436  //authenticated identity without waiting for a timeout (refer to
437  //RFC 7296, section 2.4)
438  ikeDeleteSaEntry(entry);
439  }
440  }
441  }
442 }
443 
444 
445 /**
446  * @brief Create a new Child Security Association
447  * @param[in] context Pointer to the IKE context
448  * @return Pointer to the newly created Child SA
449  **/
450 
452 {
453  uint_t i;
454  IkeChildSaEntry *childSa;
455  IpsecContext *ipsecContext;
456 
457  //Point to the IPsec context
458  ipsecContext = context->netContext->ipsecContext;
459 
460  //Loop through Child SA entries
461  for(i = 0; i < context->numChildSaEntries; i++)
462  {
463  //Point to the current Child SA
464  childSa = &context->childSa[i];
465 
466  //Check whether the current Child SA is free
467  if(childSa->state == IKE_CHILD_SA_STATE_CLOSED)
468  {
469  //Clear Child SA entry
470  osMemset(childSa, 0, sizeof(IkeChildSaEntry));
471 
472  //Attach IKE context
473  childSa->context = context;
474 
475  //Allocate inbound SAD entry
476  childSa->inboundSa = ipsecAllocateSadEntry(ipsecContext);
477 
478  //Failed to allocated SAD entry?
479  if(childSa->inboundSa < 0)
480  {
481  //The SAD database runs out of space
482  return NULL;
483  }
484 
485  //Allocate outbound SAD entry
486  childSa->outboundSa = ipsecAllocateSadEntry(ipsecContext);
487 
488  //Failed to allocated SAD entry?
489  if(childSa->outboundSa < 0)
490  {
491  //Clean up side effects
492  ipsecClearSadEntry(ipsecContext, childSa->inboundSa);
493  //The SAD database runs out of space
494  return NULL;
495  }
496 
497  //Default state
498  childSa->state = IKE_CHILD_SA_STATE_RESERVED;
499 
500  //Return a pointer to the newly created Child SA
501  return childSa;
502  }
503  }
504 
505  //The Child SA table runs out of space
506  return NULL;
507 }
508 
509 
510 /**
511  * @brief Find an Child SA that matches the specified SPI
512  * @param[in] sa Pointer to the IKE SA
513  * @param[in] protocolId Protocol identifier (AH or ESP)
514  * @param[in] spi Security parameter index
515  * @return Pointer to the matching Child SA, if any
516  **/
517 
519  const uint8_t *spi)
520 {
521  uint_t i;
522  IkeContext *context;
523  IkeChildSaEntry *childSa;
524 
525  //Point to the IKE context
526  context = sa->context;
527 
528  //Loop through Child SA entries
529  for(i = 0; i < context->numChildSaEntries; i++)
530  {
531  //Point to the current Child SA
532  childSa = &context->childSa[i];
533 
534  //Check the state of the Child SA
535  if(childSa->state != IKE_CHILD_SA_STATE_CLOSED)
536  {
537  //Matching IKE SA and protocol identifier?
538  if(childSa->sa == sa && childSa->protocol == protocolId)
539  {
540  //Compare SPIs
541  if(osMemcmp(childSa->remoteSpi, spi, IPSEC_SPI_SIZE) == 0)
542  {
543  //A matching Child SA has been found
544  return childSa;
545  }
546  }
547  }
548  }
549 
550  //The specified SPI does not match any Child SA
551  return NULL;
552 }
553 
554 
555 /**
556  * @brief Delete a Child Security Association
557  * @param[in] childSa Pointer to the Child SA
558  **/
559 
561 {
562  IpsecContext *ipsecContext;
563 
564  //Valid Child SA?
565  if(childSa != NULL)
566  {
567  //Debug message
568  TRACE_INFO("Deleting Child SA...\r\n");
569 
570  //Point to the IPsec context
571  ipsecContext = childSa->context->netContext->ipsecContext;
572 
573  //Close inbound SAD entry
574  if(childSa->inboundSa >= 0)
575  {
576  ipsecClearSadEntry(ipsecContext, childSa->inboundSa);
577  }
578 
579  //Close outbound SAD entry
580  if(childSa->outboundSa >= 0)
581  {
582  ipsecClearSadEntry(ipsecContext, childSa->outboundSa);
583  }
584 
585  //Mark the Child SA as closed
586  childSa->state = IKE_CHILD_SA_STATE_CLOSED;
587  }
588 }
589 
590 
591 /**
592  * @brief Move inherited Child SAs
593  * @param[in] newSa Pointer to the new IKE SA
594  * @param[in] oldSa Pointer to the old IKE SA
595  **/
596 
598 {
599  uint_t i;
600  IkeContext *context;
601  IkeChildSaEntry *childSa;
602 
603  //Point to the IKE context
604  context = newSa->context;
605 
606  //Loop through Child SA entries
607  for(i = 0; i < context->numChildSaEntries; i++)
608  {
609  //Point to the current Child SA
610  childSa = &context->childSa[i];
611 
612  //Check the state of the Child SA
613  if(childSa->state != IKE_CHILD_SA_STATE_CLOSED)
614  {
615  //Move inherited Child SAs
616  if(childSa->sa == oldSa)
617  {
618  childSa->sa = newSa;
619  }
620  }
621  }
622 }
623 
624 
625 /**
626  * @brief Generate a new IKE SA SPI
627  * @param[in] sa Pointer to the IKE SA
628  * @param[out] spi Pointer to the buffer where to store the resulting SPI
629  * @return Error code
630  **/
631 
633 {
634  error_t error;
635  uint_t i;
636  IkeContext *context;
637  IkeSaEntry *entry;
638 
639  //Debug message
640  TRACE_INFO("Generating new IKE SA SPI (%u bytes)...\r\n", IKE_SPI_SIZE);
641 
642  //Point to the IKE context
643  context = sa->context;
644 
645  //Each endpoint chooses one of the two SPIs and must choose them so as to
646  //be unique identifiers of an IKE SA (refer to RFC 7296, section 2.6)
647  do
648  {
649  //Generate an arbitrary 8-octet value
650  error = context->prngAlgo->generate(context->prngContext, spi,
651  IKE_SPI_SIZE);
652 
653  //Check status code
654  if(!error)
655  {
656  //Non-zero SPI value?
658  {
659  //Loop through IKE SA entries
660  for(i = 0; i < context->numSaEntries && !error; i++)
661  {
662  //Point to the current IKE SA
663  entry = &context->sa[i];
664 
665  //Check the state of the IKE SA
666  if(entry != sa && entry->state != IKE_SA_STATE_CLOSED)
667  {
668  //Check whether the entity is the original initiator of the
669  //IKE SA
670  if(entry->originalInitiator)
671  {
672  //Test whether the SPI is a duplicate
673  if(osMemcmp(spi, entry->initiatorSpi, IKE_SPI_SIZE) == 0)
674  {
675  error = ERROR_INVALID_SPI;
676  }
677  }
678  else
679  {
680  //Test whether the SPI is a duplicate
681  if(osMemcmp(spi, entry->responderSpi, IKE_SPI_SIZE) == 0)
682  {
683  error = ERROR_INVALID_SPI;
684  }
685  }
686  }
687  }
688  }
689  else
690  {
691  //The SPI value must not be zero (refer to RFC 7296, section 3.1)
692  error = ERROR_INVALID_SPI;
693  }
694  }
695 
696  //Repeat as necessary until a unique SPI is generated
697  } while(error == ERROR_INVALID_SPI);
698 
699  //Check status code
700  if(!error)
701  {
702  //Debug message
704  }
705 
706  //Return status code
707  return error;
708 }
709 
710 
711 /**
712  * @brief Generate a new Child SA SPI
713  * @param[in] childSa Pointer to the Child SA
714  * @param[out] spi Pointer to the buffer where to store the resulting SPI
715  * @return Error code
716  **/
717 
719 {
720  error_t error;
721  uint_t i;
722  IkeContext *context;
723  IkeChildSaEntry *entry;
724 
725  //Debug message
726  TRACE_INFO("Generating new Child SA SPI (%u bytes)...\r\n", IPSEC_SPI_SIZE);
727 
728  //Point to the IKE context
729  context = childSa->context;
730 
731  //Generate a unique SPI value
732  do
733  {
734  //Generate an arbitrary 4-octet value
735  error = context->prngAlgo->generate(context->prngContext, spi,
737 
738  //Check status code
739  if(!error)
740  {
741  //Non-zero SPI value?
743  {
744  //Loop through Child SA entries
745  for(i = 0; i < context->numChildSaEntries && !error; i++)
746  {
747  //Point to the current Child SA
748  entry = &context->childSa[i];
749 
750  //Check the state of the Child SA
751  if(entry != childSa && entry->state != IKE_CHILD_SA_STATE_CLOSED)
752  {
753  //Test whether the SPI is a duplicate
754  if(osMemcmp(spi, entry->localSpi, IPSEC_SPI_SIZE) == 0)
755  {
756  error = ERROR_INVALID_SPI;
757  }
758  }
759  }
760  }
761  else
762  {
763  //The SPI value of zero is reserved and must not be sent on the
764  //wire (refer to RFC 4302, section 2.4 and RFC 4303, section 2.1)
765  error = ERROR_INVALID_SPI;
766  }
767  }
768 
769  //Repeat as necessary until a unique SPI is generated
770  } while(error == ERROR_INVALID_SPI);
771 
772  //Check status code
773  if(!error)
774  {
775  //Debug message
777  }
778 
779  //Return status code
780  return error;
781 }
782 
783 
784 /**
785  * @brief Generate a new nonce
786  * @param[in] context Pointer to the IKE context
787  * @param[out] nonce Pointer to the buffer where to store the resulting nonce
788  * @param[in] length Length of the nonce, in bytes
789  * @return Error code
790  **/
791 
792 error_t ikeGenerateNonce(IkeContext *context, uint8_t *nonce, size_t *length)
793 {
794  error_t error;
795 
796  //Debug message
797  TRACE_INFO("Generating new nonce (%u bytes)...\r\n", IKE_DEFAULT_NONCE_SIZE);
798 
799  //Nonces used in IKEv2 must be randomly chosen and must be at least 128 bits
800  //in size (refer to RFC 7296, section 2.10)
801  error = context->prngAlgo->generate(context->prngContext, nonce,
803 
804  //Check status code
805  if(!error)
806  {
807  //Set the length of the nonce
809 
810  //Debug message
812  }
813 
814  //Return status code
815  return error;
816 }
817 
818 
819 /**
820  * @brief Apply random jitter to a time interval
821  * @param[in] context Pointer to the IKE context
822  * @param[out] delay Time interval to be randomized
823  * @return Randomized time interval
824  **/
825 
827 {
828  error_t error;
831 
832  //Maximum jitter to be applied to the time interval
833  delta = (delay * IKE_RANDOM_JITTER) / 100;
834 
835  //Sanity check
836  if(delta > 0)
837  {
838  //Generate a random value
839  error = context->prngAlgo->generate(context->prngContext,
840  (uint8_t *) &value, sizeof(value));
841 
842  //Check status code
843  if(!error)
844  {
845  //Apply random jitter to the time interval
846  delay -= value % delta;
847  }
848  }
849 
850  //Return the randomized time interval
851  return delay;
852 }
853 
854 
855 /**
856  * @brief Perform ID substitution
857  * @param[in] sa Pointer to the IKE SA
858  **/
859 
861 {
862 #if (IPV4_SUPPORT == ENABLED)
863  //IPv4 address identity?
864  if(sa->peerIdType == IKE_ID_TYPE_IPV4_ADDR &&
865  sa->peerIdLen == sizeof(Ipv4Addr))
866  {
867  //Perform IPv4 address substitution
868  if(sa->context->remoteIpAddr.length == sizeof(Ipv4Addr))
869  {
870  ipv4CopyAddr(sa->peerId, &sa->context->remoteIpAddr.ipv4Addr);
871  }
872  }
873  else
874 #endif
875 #if (IPV6_SUPPORT == ENABLED)
876  //IPv4 address identity?
877  if(sa->peerIdType == IKE_ID_TYPE_IPV6_ADDR &&
878  sa->peerIdLen == sizeof(Ipv6Addr))
879  {
880  //Perform IPv6 address substitution
881  if(sa->context->remoteIpAddr.length == sizeof(Ipv6Addr))
882  {
883  //Perform IPv6 address substitution
884  ipv6CopyAddr(sa->peerId, &sa->context->remoteIpAddr.ipv6Addr);
885  }
886  }
887  else
888 #endif
889  //Unknown identity type?
890  {
891  //Just for sanity
892  }
893 }
894 
895 
896 /**
897  * @brief Traffic selector selection
898  * @param[in] childSa Pointer to the Child SA
899  * @param[in] tsiPayload Pointer to the TSi payload
900  * @param[in] tsrPayload Pointer to the TSr payload
901  * @return Error code
902  **/
903 
904 error_t ikeSelectTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload,
905  const IkeTsPayload *tsrPayload)
906 {
907  error_t error;
908  uint_t i;
909  IkeTsEntry tsiEntry;
910  IkeTsEntry tsrEntry;
911  IpsecSelector selector;
912  IpsecSelector selector2;
913  IpsecSpdEntry *spdEntry;
914  IkeContext *context;
915 
916  //Point to the IKE context
917  context = childSa->context;
918 
919  //Parse the first Traffic Selector substructure of the TSi payload
920  error = ikeParseTsPayload(tsiPayload, 0, &tsiEntry);
921  //Any error to report?
922  if(error)
923  return error;
924 
925  //Parse the first Traffic Selector substructure of the TSr payload
926  error = ikeParseTsPayload(tsrPayload, 0, &tsrEntry);
927  //Any error to report?
928  if(error)
929  return error;
930 
931  //Make sure the IP Protocol ID fields are consistent
932  if(tsiEntry.ipProtocolId != tsrEntry.ipProtocolId)
933  return ERROR_INVALID_PROTOCOL;
934 
935  //The first values in TSi and TSr can be ranges rather than specific values
936  ikeCopyRemoteTsEntry(childSa, &selector, &tsiEntry);
937  ikeCopyLocalTsEntry(childSa, &selector, &tsrEntry);
938 
939  //Check whether the responder accepts the first selector of TSi and TSr
940  spdEntry = ipsecFindSpdEntry(context->netContext->ipsecContext,
941  IPSEC_POLICY_ACTION_PROTECT, &selector, FALSE);
942 
943  //The TSi payload may contain multiple traffic selectors
944  for(i = 1; i < tsiPayload->numTs; i++)
945  {
946  //Save current traffic selector
947  selector2 = selector;
948 
949  //Parse TSi entry
950  error = ikeParseTsPayload(tsiPayload, i, &tsiEntry);
951  //Any error to report?
952  if(error)
953  return error;
954 
955  //Update traffic selector
956  ikeCopyRemoteTsEntry(childSa, &selector2, &tsiEntry);
957 
958  //Calculate the entire set of traffic covered by TSi entries
959  if(ipsecIsSubsetSelector(&selector, &selector2))
960  {
961  selector = selector2;
962  }
963  }
964 
965  //The TSr payload may contain multiple traffic selectors
966  for(i = 1; i < tsrPayload->numTs; i++)
967  {
968  //Save current traffic selector
969  selector2 = selector;
970 
971  //Parse TSr entry
972  error = ikeParseTsPayload(tsrPayload, i, &tsrEntry);
973  //Any error to report?
974  if(error)
975  return error;
976 
977  //Update traffic selector
978  ikeCopyLocalTsEntry(childSa, &selector2, &tsrEntry);
979 
980  //Calculate the entire set of traffic covered by TSr entries
981  if(ipsecIsSubsetSelector(&selector, &selector2))
982  {
983  selector = selector2;
984  }
985  }
986 
987  //Child SA rekeying?
988  if(childSa->oldChildSa != NULL)
989  {
990  //IKEv2 allows the responder to choose a subset of the traffic proposed by
991  //the initiator (refer to RFC 7296, section 2.9)
992  if(!ipsecIntersectSelectors(&childSa->oldChildSa->selector, &selector,
993  &childSa->selector))
994  {
995  return ERROR_INVALID_SELECTOR;
996  }
997 
998  //Set the security protocol (AH or ESP) to employ
999  childSa->protocol = childSa->oldChildSa->protocol;
1000  }
1001  else
1002  {
1003  //A responder uses the traffic selector proposals it receives via an SA
1004  //management protocol to select an appropriate entry in its SPD (refer to
1005  //RFC 4301, section 4.4.1)
1006  if(spdEntry == NULL)
1007  {
1008  spdEntry = ipsecFindSpdEntry(context->netContext->ipsecContext,
1009  IPSEC_POLICY_ACTION_PROTECT, &selector, FALSE);
1010  }
1011 
1012  //No matching SPD entry?
1013  if(spdEntry == NULL)
1014  return ERROR_INVALID_SELECTOR;
1015 
1016  //Make sure the SPD entry allows the requested mode (tunnel or transport)
1017  if(spdEntry->mode != childSa->mode)
1018  return ERROR_INVALID_SELECTOR;
1019 
1020  //IKEv2 allows the responder to choose a subset of the traffic proposed by
1021  //the initiator (refer to RFC 7296, section 2.9)
1022  if(!ipsecIntersectSelectors(&spdEntry->selector, &selector,
1023  &childSa->selector))
1024  {
1025  return ERROR_INVALID_SELECTOR;
1026  }
1027 
1028  //The SPD entry specifies the security protocol (AH or ESP) to employ
1029  childSa->protocol = spdEntry->protocol;
1030  }
1031 
1032  //Successful processing
1033  return NO_ERROR;
1034 }
1035 
1036 
1037 /**
1038  * @brief Check whether the selected traffic selectors are acceptable
1039  * @param[in] childSa Pointer to the Child SA
1040  * @param[in] tsiPayload Pointer to the TSi payload
1041  * @param[in] tsrPayload Pointer to the TSr payload
1042  * @param[in] rekey Rekeying operation
1043  * @return Error code
1044  **/
1045 
1046 error_t ikeCheckTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload,
1047  const IkeTsPayload *tsrPayload, bool_t rekey)
1048 {
1049  error_t error;
1050  uint_t i;
1051  IkeTsEntry tsiEntry;
1052  IkeTsEntry tsrEntry;
1053  IpsecSelector selector;
1054  IpsecSelector selector2;
1055 
1056  //Parse the first Traffic Selector substructure of the TSi payload
1057  error = ikeParseTsPayload(tsiPayload, 0, &tsiEntry);
1058  //Any error to report?
1059  if(error)
1060  return error;
1061 
1062  //Parse the first Traffic Selector substructure of the TSr payload
1063  error = ikeParseTsPayload(tsrPayload, 0, &tsrEntry);
1064  //Any error to report?
1065  if(error)
1066  return error;
1067 
1068  //Make sure the IP Protocol ID fields are consistent
1069  if(tsiEntry.ipProtocolId != tsrEntry.ipProtocolId)
1070  return ERROR_INVALID_PROTOCOL;
1071 
1072  //The first values in TSi and TSr can be ranges rather than specific values
1073  ikeCopyLocalTsEntry(childSa, &selector, &tsiEntry);
1074  ikeCopyRemoteTsEntry(childSa, &selector, &tsrEntry);
1075 
1076  //The TSi payload may contain multiple traffic selectors
1077  for(i = 1; i < tsiPayload->numTs; i++)
1078  {
1079  //Save current traffic selector
1080  selector2 = selector;
1081 
1082  //Parse TSi entry
1083  error = ikeParseTsPayload(tsiPayload, i, &tsiEntry);
1084  //Any error to report?
1085  if(error)
1086  return error;
1087 
1088  //Update traffic selector
1089  ikeCopyLocalTsEntry(childSa, &selector2, &tsiEntry);
1090 
1091  //Calculate the entire set of traffic covered by TSi entries
1092  if(ipsecIsSubsetSelector(&selector, &selector2))
1093  {
1094  selector = selector2;
1095  }
1096  }
1097 
1098  //The TSr payload may contain multiple traffic selectors
1099  for(i = 1; i < tsrPayload->numTs; i++)
1100  {
1101  //Save traffic selector
1102  selector2 = selector;
1103 
1104  //Parse TSr entry
1105  error = ikeParseTsPayload(tsrPayload, i, &tsrEntry);
1106  //Any error to report?
1107  if(error)
1108  return error;
1109 
1110  //Update traffic selector
1111  ikeCopyRemoteTsEntry(childSa, &selector2, &tsrEntry);
1112 
1113  //Calculate the entire set of traffic covered by TSr entries
1114  if(ipsecIsSubsetSelector(&selector, &selector2))
1115  {
1116  selector = selector2;
1117  }
1118  }
1119 
1120  //IKEv2 allows the responder to choose a subset of the traffic proposed by
1121  //the initiator (refer to RFC 7296, section 2.9)
1122  if(!ipsecIsSubsetSelector(&selector, &childSa->selector))
1123  return ERROR_INVALID_SELECTOR;
1124 
1125  //Rekeying operation?
1126  if(rekey)
1127  {
1128  //A rekeyed Child SA can never have a narrower scope than the one
1129  //currently in use (refer to RFC 7296, section 2.9.2)
1130  if(!ipsecIsSubsetSelector(&childSa->selector, &selector))
1131  return ERROR_INVALID_SELECTOR;
1132  }
1133 
1134  //Save traffic selector
1135  childSa->selector = selector;
1136 
1137  //The selected traffic selectors are acceptable
1138  return NO_ERROR;
1139 }
1140 
1141 
1142 /**
1143  * @brief Copy local traffic selector
1144  * @param[in] childSa Pointer to the Child SA
1145  * @param[in,out] selector Pointer to the IPsec selector
1146  * @param[in] tsEntry Traffic selector entry
1147  **/
1148 
1150  const IkeTsEntry *tsEntry)
1151 {
1152 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
1153  IkeContext *context;
1154  IkeSaEntry *sa;
1155 
1156  //Point to the IKE context
1157  context = childSa->context;
1158  //Point to the IKE SA
1159  sa = childSa->sa;
1160 #endif
1161 
1162  //Copy TS entry
1163  selector->localIpAddr.start = tsEntry->startAddr;
1164  selector->localIpAddr.end = tsEntry->endAddr;
1165  selector->nextProtocol = tsEntry->ipProtocolId;
1166  selector->localPort.start = tsEntry->startPort;
1167  selector->localPort.end = tsEntry->endPort;
1168 
1169 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
1170  //Check if transport mode is selected
1171  if(childSa->mode == IPSEC_MODE_TRANSPORT)
1172  {
1173  //Check if the local endpoint is behind a NAT
1174  if(sa->localNat)
1175  {
1176  //Substitute the IP address in the TS entry with the local address of
1177  //the IKE SA (refer to RFC 7296, section 2.23.1)
1178  selector->localIpAddr.start = context->localIpAddr;
1179  selector->localIpAddr.end = context->localIpAddr;
1180  }
1181  }
1182 #endif
1183 }
1184 
1185 
1186 /**
1187  * @brief Copy remote traffic selector
1188  * @param[in] childSa Pointer to the Child SA
1189  * @param[in,out] selector Pointer to the IPsec selector
1190  * @param[in] tsEntry Traffic selector entry
1191  **/
1192 
1193 
1195  const IkeTsEntry *tsEntry)
1196 {
1197 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
1198  IkeContext *context;
1199  IkeSaEntry *sa;
1200 
1201  //Point to the IKE context
1202  context = childSa->context;
1203  //Point to the IKE SA
1204  sa = childSa->sa;
1205 #endif
1206 
1207  //Copy TS entry
1208  selector->remoteIpAddr.start = tsEntry->startAddr;
1209  selector->remoteIpAddr.end = tsEntry->endAddr;
1210  selector->nextProtocol = tsEntry->ipProtocolId;
1211  selector->remotePort.start = tsEntry->startPort;
1212  selector->remotePort.end = tsEntry->endPort;
1213 
1214 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
1215  //Check if transport mode is selected
1216  if(childSa->mode == IPSEC_MODE_TRANSPORT)
1217  {
1218  //Check if the remote endpoint is behind a NAT
1219  if(sa->remoteNat)
1220  {
1221  //Substitute the IP address in the TS entry with the remote address of
1222  //the IKE SA (refer to RFC 7296, section 2.23.1)
1223  selector->remoteIpAddr.start = context->remoteIpAddr;
1224  selector->remoteIpAddr.end = context->remoteIpAddr;
1225  }
1226  }
1227 #endif
1228 }
1229 
1230 
1231 /**
1232  * @brief Check the length of the nonce
1233  * @param[in] sa Pointer to the IKE SA
1234  * @param[in] nonceLen Length of the nonce, in bytes
1235  * @return Error code
1236  **/
1237 
1239 {
1240  size_t prfKeyLen;
1241 
1242 #if (IKE_CMAC_PRF_SUPPORT == ENABLED && IKE_AES_128_SUPPORT == ENABLED)
1243  //AES-CMAC PRF algorithm?
1244  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_AES128_CMAC)
1245  {
1246  prfKeyLen = 16;
1247  }
1248  else
1249 #endif
1250 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_MD5_SUPPORT == ENABLED)
1251  //HMAC-MD5 PRF algorithm?
1252  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_MD5)
1253  {
1254  prfKeyLen = MD5_DIGEST_SIZE;
1255  }
1256  else
1257 #endif
1258 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA1_SUPPORT == ENABLED)
1259  //HMAC-SHA1 PRF algorithm?
1260  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA1)
1261  {
1262  prfKeyLen = SHA1_DIGEST_SIZE;
1263  }
1264  else
1265 #endif
1266 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA256_SUPPORT == ENABLED)
1267  //HMAC-SHA256 PRF algorithm?
1268  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA2_256)
1269  {
1270  prfKeyLen = SHA256_DIGEST_SIZE;
1271  }
1272  else
1273 #endif
1274 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA384_SUPPORT == ENABLED)
1275  //HMAC-SHA384 PRF algorithm?
1276  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA2_384)
1277  {
1278  prfKeyLen = SHA384_DIGEST_SIZE;
1279  }
1280  else
1281 #endif
1282 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_SHA512_SUPPORT == ENABLED)
1283  //HMAC-SHA512 PRF algorithm?
1284  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_SHA2_512)
1285  {
1286  prfKeyLen = SHA512_DIGEST_SIZE;
1287  }
1288  else
1289 #endif
1290 #if (IKE_HMAC_PRF_SUPPORT == ENABLED && IKE_TIGER_SUPPORT == ENABLED)
1291  //HMAC-Tiger PRF algorithm?
1292  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_HMAC_TIGER)
1293  {
1294  prfKeyLen = TIGER_DIGEST_SIZE;
1295  }
1296  else
1297 #endif
1298 #if (IKE_XCBC_MAC_PRF_SUPPORT == ENABLED && IKE_AES_128_SUPPORT == ENABLED)
1299  //AES-XCBC-MAC PRF algorithm?
1300  if(sa->prfAlgoId == IKE_TRANSFORM_ID_PRF_AES128_XCBC)
1301  {
1302  prfKeyLen = 16;
1303  }
1304  else
1305 #endif
1306  //Unknown PRF algorithm?
1307  {
1308  prfKeyLen = 0;
1309  }
1310 
1311  //Nonces used in IKEv2 must be at least half the key size of the negotiated
1312  //pseudorandom function (refer to RFC 7296, section 2.10)
1313  if(nonceLen >= (prfKeyLen / 2))
1314  {
1315  return NO_ERROR;
1316  }
1317  else
1318  {
1319  return ERROR_INVALID_LENGTH;
1320  }
1321 }
1322 
1323 
1324 /**
1325  * @brief Compare nonces
1326  * @param[in] nonce1 Pointer to the first nonce
1327  * @param[in] nonceLen1 Length of the first nonce, in bytes
1328  * @param[in] nonce2 Pointer to the second nonce
1329  * @param[in] nonceLen2 Length of the second nonce, in bytes
1330  * @return The function returns 0 if the nonces match, -1 if the first nonce is
1331  * lower, or 1 if the second nonce is lower
1332  **/
1333 
1334 int_t ikeCompareNonces(const uint8_t *nonce1, size_t nonceLen1,
1335  const uint8_t *nonce2, size_t nonceLen2)
1336 {
1337  int_t res;
1338  size_t n;
1339 
1340  //Find the length of the shortest nonce
1341  n = MIN(nonceLen1, nonceLen2);
1342 
1343  //Perform octet-by-octet comparison
1344  res = osMemcmp(nonce1, nonce2, n);
1345 
1346  //If the end of one nonce has been reached, that nonce is the lower one
1347  //(refer to RFC 7296, section 2.8.1)
1348  if(res == 0)
1349  {
1350  if(nonceLen1 < nonceLen2)
1351  {
1352  res = -1;
1353  }
1354  else if(nonceLen1 > nonceLen2)
1355  {
1356  res = 1;
1357  }
1358  else
1359  {
1360  }
1361  }
1362 
1363  //Return comparison result
1364  return res;
1365 }
1366 
1367 
1368 /**
1369  * @brief Compare IKE SA nonces
1370  * @param[in] sa1 Pointer to the first IKE SA
1371  * @param[in] sa2 Pointer to the second IKE SA
1372  * @return The function returns -1 if the first one has the lowest of the four
1373  * nonces, or 1 if the second one has the lowest of the four nonces
1374  **/
1375 
1377 {
1378  const uint8_t *nonce1;
1379  size_t nonceLen1;
1380  const uint8_t *nonce2;
1381  size_t nonceLen2;
1382 
1383  //Compare the two nonces of the first IKE SA
1384  if(ikeCompareNonces(sa1->initiatorNonce, sa1->initiatorNonceLen,
1385  sa1->responderNonce, sa1->responderNonceLen) < 0)
1386  {
1387  nonce1 = sa1->initiatorNonce;
1388  nonceLen1 = sa1->initiatorNonceLen;
1389  }
1390  else
1391  {
1392  nonce1 = sa1->responderNonce;
1393  nonceLen1 = sa1->responderNonceLen;
1394  }
1395 
1396  //Compare the two nonces of the second IKE SA
1397  if(ikeCompareNonces(sa2->initiatorNonce, sa2->initiatorNonceLen,
1398  sa2->responderNonce, sa2->responderNonceLen) < 0)
1399  {
1400  nonce2 = sa2->initiatorNonce;
1401  nonceLen2 = sa2->initiatorNonceLen;
1402  }
1403  else
1404  {
1405  nonce2 = sa2->responderNonce;
1406  nonceLen2 = sa2->responderNonceLen;
1407  }
1408 
1409  //Find the IKE SA with the lowest of the four nonces
1410  return ikeCompareNonces(nonce1, nonceLen1, nonce2, nonceLen2);
1411 }
1412 
1413 
1414 /**
1415  * @brief Compare Child SA nonces
1416  * @param[in] childSa1 Pointer to the first Child SA
1417  * @param[in] childSa2 Pointer to the second Child SA
1418  * @return The function returns -1 if the first one has the lowest of the four
1419  * nonces, or 1 if the second one has the lowest of the four nonces
1420  **/
1421 
1423  IkeChildSaEntry *childSa2)
1424 {
1425  const uint8_t *nonce1;
1426  size_t nonceLen1;
1427  const uint8_t *nonce2;
1428  size_t nonceLen2;
1429 
1430  //Compare the two nonces of the first Child SA
1431  if(ikeCompareNonces(childSa1->initiatorNonce, childSa1->initiatorNonceLen,
1432  childSa1->responderNonce, childSa1->responderNonceLen) < 0)
1433  {
1434  nonce1 = childSa1->initiatorNonce;
1435  nonceLen1 = childSa1->initiatorNonceLen;
1436  }
1437  else
1438  {
1439  nonce1 = childSa1->responderNonce;
1440  nonceLen1 = childSa1->responderNonceLen;
1441  }
1442 
1443  //Compare the two nonces of the second Child SA
1444  if(ikeCompareNonces(childSa2->initiatorNonce, childSa2->initiatorNonceLen,
1445  childSa2->responderNonce, childSa2->responderNonceLen) < 0)
1446  {
1447  nonce2 = childSa2->initiatorNonce;
1448  nonceLen2 = childSa2->initiatorNonceLen;
1449  }
1450  else
1451  {
1452  nonce2 = childSa2->responderNonce;
1453  nonceLen2 = childSa2->responderNonceLen;
1454  }
1455 
1456  //Find the Child SA with the lowest of the four nonces
1457  return ikeCompareNonces(nonce1, nonceLen1, nonce2, nonceLen2);
1458 }
1459 
1460 
1461 /**
1462  * @brief Create AH or ESP SA pair
1463  * @param[in] childSa Pointer to the Child SA
1464  * @return Error code
1465  **/
1466 
1468 {
1469  error_t error;
1470  IpsecContext *ipsecContext;
1471  IpsecSadEntry sadEntry;
1472 
1473  //Debug message
1474  TRACE_INFO("Creating IPsec SA pair...\r\n");
1475  TRACE_INFO(" Outbound SPI = 0x%08" PRIX32 "\r\n", LOAD32BE(childSa->remoteSpi));
1476  TRACE_INFO(" Inbound SPI = 0x%08" PRIX32 "\r\n", LOAD32BE(childSa->localSpi));
1477 
1478  //Point to the IPsec context
1479  ipsecContext = childSa->context->netContext->ipsecContext;
1480 
1481  //Set SAD entry parameters (outbound traffic)
1482  osMemset(&sadEntry, 0, sizeof(IpsecSadEntry));
1483  sadEntry.direction = IPSEC_DIR_OUTBOUND;
1484  sadEntry.mode = childSa->mode;
1485  sadEntry.protocol = childSa->protocol;
1486  sadEntry.selector = childSa->selector;
1487  sadEntry.spi = LOAD32BE(childSa->remoteSpi);
1488  sadEntry.authMacAlgo = childSa->authMacAlgo;
1489  sadEntry.authCipherAlgo = childSa->authCipherAlgo;
1490  sadEntry.authHashAlgo = childSa->authHashAlgo;
1491  sadEntry.authKeyLen = childSa->authKeyLen;
1492  sadEntry.icvLen = childSa->icvLen;
1493  sadEntry.esn = (childSa->esn == IKE_TRANSFORM_ID_ESN_YES) ? TRUE : FALSE;
1494  sadEntry.seqNum = 0;
1495  sadEntry.antiReplayEnabled = TRUE;
1496 
1497  //Set integrity protection key
1498  if(childSa->initiator)
1499  {
1500  osMemcpy(sadEntry.authKey, childSa->skai, childSa->authKeyLen);
1501  }
1502  else
1503  {
1504  osMemcpy(sadEntry.authKey, childSa->skar, childSa->authKeyLen);
1505  }
1506 
1507 #if (ESP_SUPPORT == ENABLED)
1508  //Set encryption parameters
1509  sadEntry.cipherMode = childSa->cipherMode;
1510  sadEntry.cipherAlgo = childSa->cipherAlgo;
1511  sadEntry.encKeyLen = childSa->encKeyLen;
1512  sadEntry.saltLen = childSa->saltLen;
1513  sadEntry.ivLen = childSa->ivLen;
1514 
1515  //Set encryption key
1516  if(childSa->initiator)
1517  {
1518  osMemcpy(sadEntry.encKey, childSa->skei, childSa->encKeyLen +
1519  childSa->saltLen);
1520  }
1521  else
1522  {
1523  osMemcpy(sadEntry.encKey, childSa->sker, childSa->encKeyLen +
1524  childSa->saltLen);
1525  }
1526 
1527  //Check encryption mode
1528  if(childSa->protocol == IPSEC_PROTOCOL_ESP &&
1529  childSa->cipherMode != CIPHER_MODE_CBC)
1530  {
1531  //Copy initialization vector
1532  osMemcpy(sadEntry.iv, childSa->iv, childSa->ivLen);
1533  }
1534 #endif
1535 
1536 #if (ESP_SUPPORT == ENABLED && ESP_UDP_ENCAPS_SUPPORT == ENABLED && \
1537  IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
1538  //If a NAT is detected, both devices must use UDP encapsulation for ESP
1539  //(refer to RFC 7296, section 2.23)
1540  if(childSa->sa->localNat || childSa->sa->remoteNat)
1541  {
1542  sadEntry.udpEncapsulation = TRUE;
1543  }
1544 #endif
1545 
1546  //Update SAD entry (outbound traffic)
1547  error = ipsecSetSadEntry(ipsecContext, childSa->outboundSa, &sadEntry);
1548 
1549  //Check status code
1550  if(!error)
1551  {
1552  //Set SAD entry parameters (inbound traffic)
1553  osMemset(&sadEntry, 0, sizeof(IpsecSadEntry));
1554  sadEntry.direction = IPSEC_DIR_INBOUND;
1555  sadEntry.mode = childSa->mode;
1556  sadEntry.protocol = childSa->protocol;
1557  sadEntry.selector = childSa->selector;
1558  sadEntry.spi = LOAD32BE(childSa->localSpi);
1559  sadEntry.authMacAlgo = childSa->authMacAlgo;
1560  sadEntry.authCipherAlgo = childSa->authCipherAlgo;
1561  sadEntry.authHashAlgo = childSa->authHashAlgo;
1562  sadEntry.authKeyLen = childSa->authKeyLen;
1563  sadEntry.icvLen = childSa->icvLen;
1564  sadEntry.esn = (childSa->esn == IKE_TRANSFORM_ID_ESN_YES) ? TRUE : FALSE;
1565  sadEntry.seqNum = 0;
1566  sadEntry.antiReplayEnabled = TRUE;
1567 
1568  //Set integrity protection key
1569  if(childSa->initiator)
1570  {
1571  osMemcpy(sadEntry.authKey, childSa->skar, childSa->authKeyLen);
1572  }
1573  else
1574  {
1575  osMemcpy(sadEntry.authKey, childSa->skai, childSa->authKeyLen);
1576  }
1577 
1578 #if (ESP_SUPPORT == ENABLED)
1579  //Set encryption parameters
1580  sadEntry.cipherMode = childSa->cipherMode;
1581  sadEntry.cipherAlgo = childSa->cipherAlgo;
1582  sadEntry.encKeyLen = childSa->encKeyLen;
1583  sadEntry.saltLen = childSa->saltLen;
1584  sadEntry.ivLen = childSa->ivLen;
1585 
1586  //Set encryption key
1587  if(childSa->initiator)
1588  {
1589  osMemcpy(sadEntry.encKey, childSa->sker, childSa->encKeyLen +
1590  childSa->saltLen);
1591  }
1592  else
1593  {
1594  osMemcpy(sadEntry.encKey, childSa->skei, childSa->encKeyLen +
1595  childSa->saltLen);
1596  }
1597 #endif
1598 
1599 #if (ESP_SUPPORT == ENABLED && ESP_UDP_ENCAPS_SUPPORT == ENABLED && \
1600  IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
1601  //If a NAT is detected, both devices must use UDP encapsulation for ESP
1602  //(refer to RFC 7296, section 2.23)
1603  if(childSa->sa->localNat || childSa->sa->remoteNat)
1604  {
1605  sadEntry.udpEncapsulation = TRUE;
1606  }
1607 #endif
1608 
1609  //Update SAD entry (inbound traffic)
1610  error = ipsecSetSadEntry(ipsecContext, childSa->inboundSa, &sadEntry);
1611  }
1612 
1613  //Return status code
1614  return error;
1615 }
1616 
1617 
1618 /**
1619  * @brief Test if the IKE SA is the only currently active with a given peer
1620  * @param[in] sa Pointer to the IKE SA
1621  * @return TRUE if this IKE SA is the only IKE SA currently active between the
1622  * authenticated identities, else FALSE
1623  **/
1624 
1626 {
1627  uint_t i;
1628  IkeContext *context;
1629  IkeSaEntry *entry;
1630 
1631  //Point to the IKE context
1632  context = sa->context;
1633 
1634  //Loop through IKE SA entries
1635  for(i = 0; i < context->numSaEntries; i++)
1636  {
1637  //Point to the current IKE SA
1638  entry = &context->sa[i];
1639 
1640  //Check the state of the IKE SA
1641  if(entry != sa && entry->state != IKE_SA_STATE_CLOSED)
1642  {
1643  //Check whether another IKE SA exists between the authenticated
1644  //identities
1645  if(ipCompAddr(&entry->remoteIpAddr, &sa->remoteIpAddr))
1646  {
1647  return FALSE;
1648  }
1649  }
1650  }
1651 
1652  //This IKE SA is the only IKE SA currently active between the authenticated
1653  //identities
1654  return TRUE;
1655 }
1656 
1657 #endif
@ CIPHER_MODE_CBC
Definition: cipher_modes.h:82
#define IKE_PREFIX_SIZE
Definition: ike.h:816
int_t ikeCompareChildSaNonces(IkeChildSaEntry *childSa1, IkeChildSaEntry *childSa2)
Compare Child SA nonces.
Definition: ike_misc.c:1422
#define IPSEC_SPI_SIZE
Definition: ipsec.h:145
void ikeFreeKeContext(IkeKeContext *keContext)
Release key exchange context.
Diffie-Hellman key exchange.
void ikeInitKeContext(IkeKeContext *keContext)
Initialize key exchange context.
int bool_t
Definition: compiler_port.h:63
@ IKE_TRANSFORM_ID_PRF_AES128_CMAC
Definition: ike.h:1018
Helper functions for IKEv2.
uint16_t end
Definition: ipsec.h:300
int_t ikeCompareSaNonces(IkeSaEntry *sa1, IkeSaEntry *sa2)
Compare IKE SA nonces.
Definition: ike_misc.c:1376
uint16_t endPort
Definition: ike.h:1806
@ IPSEC_DIR_INBOUND
Definition: ipsec.h:174
error_t ikeRetransmitResponse(IkeSaEntry *sa)
Retransmit IKE response message.
Definition: ike_misc.c:117
signed int int_t
Definition: compiler_port.h:56
#define LOAD32BE(p)
Definition: cpu_endian.h:210
IPsec selector.
Definition: ipsec.h:309
uint32_t spi
Definition: ah.h:175
error_t ikeCheckTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload, const IkeTsPayload *tsrPayload, bool_t rekey)
Check whether the selected traffic selectors are acceptable.
Definition: ike_misc.c:1046
Traffic selector entry.
Definition: ike.h:1801
@ IKE_ID_TYPE_IPV4_ADDR
Definition: ike.h:1123
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:632
#define TRUE
Definition: os_port.h:50
Message and ancillary data.
Definition: socket.h:241
systime_t ikeRandomizeDelay(IkeContext *context, systime_t delay)
Apply random jitter to a time interval.
Definition: ike_misc.c:826
IpAddr end
Definition: ipsec.h:289
const uint8_t IPSEC_INVALID_SPI[4]
Definition: ipsec_misc.c:40
Ipv6Addr
Definition: ipv6.h:282
IkeChildSaEntry * ikeCreateChildSaEntry(IkeContext *context)
Create a new Child Security Association.
Definition: ike_misc.c:451
void * data
Pointer to the payload.
Definition: socket.h:242
#define osMemcmp(p1, p2, length)
Definition: os_port.h:159
#define IKE_MAX_TIMEOUT
Definition: ike.h:180
#define IKE_DEFAULT_NONCE_SIZE
Definition: ike.h:229
error_t ikeSelectTs(IkeChildSaEntry *childSa, const IkeTsPayload *tsiPayload, const IkeTsPayload *tsrPayload)
Traffic selector selection.
Definition: ike_misc.c:904
const uint8_t res[]
int_t ikeCompareNonces(const uint8_t *nonce1, size_t nonceLen1, const uint8_t *nonce2, size_t nonceLen2)
Compare nonces.
Definition: ike_misc.c:1334
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:324
uint16_t startPort
Definition: ike.h:1805
@ IKE_SA_STATE_CLOSED
Definition: ike.h:1354
@ IKE_TRANSFORM_ID_PRF_HMAC_SHA2_384
Definition: ike.h:1016
#define IPSEC_NAT_PORT
Definition: ipsec.h:142
void ikeCopyRemoteTsEntry(IkeChildSaEntry *childSa, IpsecSelector *selector, const IkeTsEntry *tsEntry)
Copy remote traffic selector.
Definition: ike_misc.c:1194
@ IPSEC_POLICY_ACTION_PROTECT
Definition: ipsec.h:240
@ IPSEC_PROTOCOL_ESP
Definition: ipsec.h:200
@ IPSEC_DIR_OUTBOUND
Definition: ipsec.h:175
const uint8_t IKE_INVALID_SPI[8]
Definition: ike_misc.c:47
uint16_t destPort
Destination port.
Definition: socket.h:252
#define IkeContext
Definition: ike.h:832
error_t socketSendMsg(Socket *socket, const SocketMsg *message, uint_t flags)
Send a message to a connectionless socket.
Definition: socket.c:1664
NetInterface * interface
Underlying network interface.
Definition: socket.h:248
@ IKE_ID_TYPE_IPV6_ADDR
Definition: ike.h:1126
#define FALSE
Definition: os_port.h:46
const SocketMsg SOCKET_DEFAULT_MSG
Definition: socket.c:49
size_t length
Actual length of the payload, in bytes.
Definition: socket.h:244
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
IkeSaEntry * ikeCreateSaEntry(IkeContext *context)
Create a new IKE Security Association.
Definition: ike_misc.c:185
Data logging functions for debugging purpose (IKEv2)
@ IKE_SA_STATE_RESERVED
Definition: ike.h:1355
uint8_t nextProtocol
Next layer protocol.
Definition: ipsec.h:312
@ IPSEC_MODE_TRANSPORT
Definition: ipsec.h:212
@ IKE_FLAGS_I
Initiator flag.
Definition: ike.h:876
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:314
uint8_t protocolId[]
IkeTsPayload
Definition: ike.h:1670
IpAddr startAddr
Definition: ike.h:1802
bool_t ipsecIntersectSelectors(const IpsecSelector *selector1, const IpsecSelector *selector2, IpsecSelector *result)
Calculate the intersection of two selectors.
Definition: ipsec_misc.c:605
#define IKE_SPI_SIZE
Definition: ike.h:826
uint8_t ipProtocolId
Definition: ike.h:1804
Helper routines for IPsec.
IpsecProtocol protocol
Security protocol (AH or ESP)
Definition: ipsec.h:356
bool_t ipsecIsSubsetSelector(const IpsecSelector *selector1, const IpsecSelector *selector2)
Test if a selector is a subset of another selector.
Definition: ipsec_misc.c:373
@ IKE_TRANSFORM_ID_PRF_HMAC_MD5
Definition: ike.h:1011
IpAddr srcIpAddr
Source IP address.
Definition: socket.h:249
@ ERROR_INVALID_LENGTH
Definition: error.h:111
IkeChildSaEntry * ikeFindChildSaEntry(IkeSaEntry *sa, uint8_t protocolId, const uint8_t *spi)
Find an Child SA that matches the specified SPI.
Definition: ike_misc.c:518
@ IKE_TRANSFORM_ID_PRF_HMAC_SHA1
Definition: ike.h:1012
void ikeDeleteSaEntry(IkeSaEntry *sa)
Delete an IKE Security Association.
Definition: ike_misc.c:347
error_t ipsecSetSadEntry(IpsecContext *context, uint_t index, IpsecSadEntry *params)
Set entry at specified index in SAD database.
Definition: ipsec.c:202
void ikeCopyLocalTsEntry(IkeChildSaEntry *childSa, IpsecSelector *selector, const IkeTsEntry *tsEntry)
Copy local traffic selector.
Definition: ike_misc.c:1149
void ikeDeleteDuplicateSaEntries(IkeSaEntry *sa)
Delete an duplicate IKE Security Associations.
Definition: ike_misc.c:408
void ikeDeleteChildSaEntry(IkeChildSaEntry *childSa)
Delete a Child Security Association.
Definition: ike_misc.c:560
#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:1238
uint8_t length
Definition: tcp.h:375
@ IKE_TRANSFORM_ID_PRF_AES128_XCBC
Definition: ike.h:1014
IpsecMode mode
IPsec mode (tunnel or transport)
Definition: ipsec.h:355
void ikeInheritChildSas(IkeSaEntry *newSa, IkeSaEntry *oldSa)
Move inherited Child SAs.
Definition: ike_misc.c:597
IkeHeader
Definition: ike.h:1459
@ 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
IpsecSpdEntry * ipsecFindSpdEntry(IpsecContext *context, IpsecPolicyAction policyAction, const IpsecSelector *selector, bool_t subset)
Search the SPD database for a matching entry.
Definition: ipsec_misc.c:52
@ IKE_TRANSFORM_ID_PRF_HMAC_SHA2_256
Definition: ike.h:1015
@ IKE_CHILD_SA_STATE_CLOSED
Definition: ike.h:1384
IpAddr start
Definition: ipsec.h:288
error_t ikeParseTsPayload(const IkeTsPayload *tsPayload, uint_t index, IkeTsEntry *tsEntry)
Parse Traffic Selector payload.
#define IpsecSadEntry
Definition: ipsec.h:36
uint16_t start
Definition: ipsec.h:299
IKEv2 (Internet Key Exchange Protocol)
error_t ikeCreateIpsecSaPair(IkeChildSaEntry *childSa)
Create AH or ESP SA pair.
Definition: ike_misc.c:1467
uint32_t systime_t
System time.
#define ntohs(value)
Definition: cpu_endian.h:421
IpAddr destIpAddr
Destination IP address.
Definition: socket.h:251
int_t ipsecAllocateSadEntry(IpsecContext *context)
Allocate a new entry in the SAD database.
Definition: ipsec_misc.c:107
@ ERROR_INVALID_SELECTOR
Definition: error.h:302
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
IKE payload parsing.
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:132
#define IkeSaEntry
Definition: ike.h:836
@ 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:1013
#define IKE_PORT
Definition: ike.h:813
IkeSaEntry * ikeFindSaEntry(IkeContext *context, const IkeHeader *ikeHeader)
Find an IKE SA that matches an incoming IKE message.
Definition: ike_misc.c:232
IpsecAddrRange localIpAddr
Local IP address range.
Definition: ipsec.h:310
@ IKE_TRANSFORM_ID_ESN_YES
Extended Sequence Numbers.
Definition: ike.h:1091
error_t ikeGenerateChildSaSpi(IkeChildSaEntry *childSa, uint8_t *spi)
Generate a new Child SA SPI.
Definition: ike_misc.c:718
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:1532
bool_t ikeIsInitialContact(IkeSaEntry *sa)
Test if the IKE SA is the only currently active with a given peer.
Definition: ike_misc.c:1625
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:167
#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:293
IkeNoncePayload
Definition: ike.h:1618
error_t ikeGenerateNonce(IkeContext *context, uint8_t *nonce, size_t *length)
Generate a new nonce.
Definition: ike_misc.c:792
IpAddr endAddr
Definition: ike.h:1803
Security Policy Database (SPD) entry.
Definition: ipsec.h:351
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:141
IpsecSelector selector
Traffic selector.
Definition: ipsec.h:354
#define SHA256_DIGEST_SIZE
Definition: sha256.h:45
void ikeDumpMessage(const uint8_t *message, size_t length)
Dump IKE message.
Definition: ike_debug.c:425
void ikeSubstituteId(IkeSaEntry *sa)
Perform ID substitution.
Definition: ike_misc.c:860
#define IkeChildSaEntry
Definition: ike.h:840
error_t ipsecClearSadEntry(IpsecContext *context, uint_t index)
Clear entry at specified index in SAD database.
Definition: ipsec.c:291
#define IKE_RANDOM_JITTER
Definition: ike.h:194
IpsecPortRange localPort
Local port range.
Definition: ipsec.h:313
#define SHA512_DIGEST_SIZE
Definition: sha512.h:45
@ IKE_CHILD_SA_STATE_RESERVED
Definition: ike.h:1385
IpsecAddrRange remoteIpAddr
Remote IP address range.
Definition: ipsec.h:311
uint8_t nonce[]
Definition: ntp_common.h:239
@ IKE_TRANSFORM_ID_PRF_HMAC_SHA2_512
Definition: ike.h:1017
@ 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.