ike_request_parse.c
Go to the documentation of this file.
1 /**
2  * @file ike_request_parse.c
3  * @brief IKE request parsing
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 "ipsec/ipsec_misc.h"
36 #include "ike/ike.h"
37 #include "ike/ike_fsm.h"
38 #include "ike/ike_algorithms.h"
39 #include "ike/ike_request_parse.h"
41 #include "ike/ike_payload_parse.h"
42 #include "ike/ike_auth.h"
43 #include "ike/ike_certificate.h"
44 #include "ike/ike_key_exchange.h"
45 #include "ike/ike_key_material.h"
46 #include "ike/ike_misc.h"
47 #include "debug.h"
48 
49 //Check IKEv2 library configuration
50 #if (IKE_SUPPORT == ENABLED)
51 
52 
53 /**
54  * @brief Parse incoming IKE_SA_INIT request
55  * @param[in] context Pointer to the IKE context
56  * @param[in] message Pointer to the received IKE message
57  * @param[in] length Length of the IKE message, in bytes
58  * @return Error code
59  **/
60 
62  size_t length)
63 {
64  error_t error;
65  IkeSaEntry *sa;
66  const IkeHeader *ikeHeader;
67  IkeMessagePayloads payloads;
68 
69  //Each message begins with the IKE header
70  ikeHeader = (IkeHeader *) message;
71 
72  //The initiator's SPI must not be zero (refer to RFC 7296, section 3.1)
73  if(osMemcmp(ikeHeader->initiatorSpi, IKE_INVALID_SPI, IKE_SPI_SIZE) == 0)
74  return ERROR_INVALID_MESSAGE;
75 
76  //The responder's SPI must be zero in the first message of an IKE initial
77  //exchange (including repeats of that message including a cookie)
78  if(osMemcmp(ikeHeader->responderSpi, IKE_INVALID_SPI, IKE_SPI_SIZE) != 0)
79  return ERROR_INVALID_MESSAGE;
80 
81  //The Message ID is a 32-bit quantity, which is zero for the IKE_SA_INIT
82  //messages (including retries of the message due to responses such as
83  //COOKIE and INVALID_KE_PAYLOAD)
84  if(ntohl(ikeHeader->messageId) != 0)
85  return ERROR_INVALID_MESSAGE;
86 
87  //Parse IKE message payloads
89 
90  //Mandatory payloads must be included in the received message
91  if(payloads.sa == NULL || payloads.ke == NULL || payloads.nonce == NULL)
92  return ERROR_INVALID_MESSAGE;
93 
94  //When a responder receives an IKE_SA_INIT request, it has to determine
95  //whether the packet is a retransmission belonging to an existing half-open
96  //IKE SA, or a new request, or it belongs to an existing IKE SA where the
97  //IKE_AUTH request has been already received (refer to RFC 7296, section 2.1)
98  sa = ikeFindHalfOpenSaEntry(context, ikeHeader, payloads.nonce);
99 
100  //Existing IKE SA found?
101  if(sa != NULL)
102  {
103  //Half-open IKE SA?
104  if(sa->state == IKE_SA_STATE_AUTH_REQ)
105  {
106  //If the packet is a retransmission belonging to an existing half-open
107  //IKE SA The responder retransmits the same response
108  return ikeRetransmitResponse(sa);
109  }
110  else
111  {
112  //If the packet belongs to an existing IKE SA where the IKE_AUTH
113  //request has been already received, then the responder ignores it
115  }
116  }
117 
118  //If the packet is a new request, the responder creates a new IKE SA and
119  //sends a fresh response
120  sa = ikeCreateSaEntry(context);
121  //Failed to create IKE SA?
122  if(sa == NULL)
123  return ERROR_OUT_OF_RESOURCES;
124 
125  //Initialize IKE SA
126  sa->remoteIpAddr = context->remoteIpAddr;
127 
128  //The original initiator always refers to the party who initiated the
129  //exchange (refer to RFC 7296, section 2.2)
130  sa->originalInitiator = FALSE;
131 
132  //The Message ID is zero for the IKE_SA_INIT messages
133  sa->rxMessageId = 0;
134 
135  //Save initiator's IKE SPI
136  osMemcpy(sa->initiatorSpi, ikeHeader->initiatorSpi, IKE_SPI_SIZE);
137 
138  //Save the first message (IKE_SA_INIT request), starting with the first
139  //octet of the first SPI in the header and ending with the last octet of
140  //the last payload
141  sa->initiatorSaInit = message;
142  sa->initiatorSaInitLen = length;
143 
144  //Start of exception handling block
145  do
146  {
147  //Check whether the message contains an unsupported critical payload
149  &sa->unsupportedCriticalPayload);
150 
151  //Valid IKE message?
152  if(error == NO_ERROR)
153  {
154  //The message is valid
155  }
156  else if(error == ERROR_UNSUPPORTED_OPTION)
157  {
158  //Reject the message and send an UNSUPPORTED_CRITICAL_PAYLOAD error
160  break;
161  }
162  else
163  {
164  //Reject the message and send an INVALID_SYNTAX error
165  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
166  break;
167  }
168 
169  //Save initiator's nonce
170  error = ikeParseNoncePayload(payloads.nonce, sa->initiatorNonce,
171  &sa->initiatorNonceLen);
172 
173  //Malformed nonce?
174  if(error)
175  {
176  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
177  break;
178  }
179 
180 #if (IKE_COOKIE_SUPPORT == ENABLED)
181  //Any registered callbacks?
182  if(context->cookieVerifyCallback != NULL &&
183  context->cookieGenerateCallback != NULL)
184  {
185  //COOKIE notification received?
186  if(payloads.cookieNotify != NULL)
187  {
188  //Save the received cookie
189  error = ikeParseCookieNotification(sa, payloads.cookieNotify);
190 
191  //Malformed notification?
192  if(error)
193  {
194  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
195  break;
196  }
197  }
198  else
199  {
200  //No cookie has been included in the IKE_SA_INIT message
201  sa->cookieLen = 0;
202  }
203 
204  //The cookie can be recomputed when the IKE_SA_INIT arrives the second
205  //time and compared to the cookie in the received message
206  error = context->cookieVerifyCallback(context,
207  &context->remoteIpAddr, sa->initiatorSpi, sa->initiatorNonce,
208  sa->initiatorNonceLen, sa->cookie, sa->cookieLen);
209 
210  //Check status code
211  if(error == NO_ERROR)
212  {
213  //The received cookie is valid
214  }
215  else if(error == ERROR_WRONG_COOKIE)
216  {
217  //When one party receives an IKE_SA_INIT request containing a cookie
218  //whose contents do not match the value expected, that party must
219  //ignore the cookie and process the message as if no cookie had been
220  //included (refer to RFC 7296, section 2.6)
221  error = context->cookieGenerateCallback(context,
222  &context->remoteIpAddr, sa->initiatorSpi, sa->initiatorNonce,
223  sa->initiatorNonceLen, sa->cookie, &sa->cookieLen);
224 
225  //Check status code
226  if(!error)
227  {
228  //Send a response containing a new cookie
229  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_COOKIE;
230  }
231  else
232  {
233  //Reject the request with a generic error notification
234  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
235  }
236 
237  //Send IKE_SA_INIT response message
238  break;
239  }
240  else
241  {
242  //Reject the request with a generic error notification
243  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
244  break;
245  }
246  }
247 #endif
248 
249  //Check the syntax of the SAi payload
250  error = ikeParseSaPayload(payloads.sa);
251 
252  //Malformed SAi payload?
253  if(error)
254  {
255  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
256  break;
257  }
258 
259  //The responder must choose a single suite, which may be any subset of
260  //the SA proposal (refer to RFC 7296, section 2.7)
261  error = ikeSelectSaProposal(sa, payloads.sa, 0);
262 
263  //The responder must accept a single proposal or reject them all and
264  //return an error. The error is given in a notification of type
265  //NO_PROPOSAL_CHOSEN
266  if(error)
267  {
268  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
269  break;
270  }
271 
272  //Nonces used in IKEv2 must be at least half the key size of the
273  //negotiated pseudorandom function (refer to RFC 7296, section 2.10)
274  error = ikeCheckNonceLength(sa, sa->initiatorNonceLen);
275 
276  //Unacceptable nonce length?
277  if(error)
278  {
279  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
280  break;
281  }
282 
283  //The Key Exchange payload is used to exchange Diffie-Hellman public
284  //numbers as part of a Diffie-Hellman key exchange
285  error = ikeParseKePayload(&sa->keContext, payloads.ke);
286 
287  //Check status code
288  if(error == NO_ERROR)
289  {
290  //The Key Exchange payload is acceptable
291  }
292  else if(error == ERROR_INVALID_SYNTAX)
293  {
294  //The Key Exchange payload is malformed
295  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
296  break;
297  }
298  else if(error == ERROR_INVALID_GROUP)
299  {
300  //If the initiator guesses wrong, the responder will respond with a
301  //Notify payload of type INVALID_KE_PAYLOAD indicating the selected
302  //group (refer to RFC 7296, section 1.2)
303  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_KE_PAYLOAD;
304  sa->preferredGroupNum = sa->keContext.groupNum;
305  break;
306  }
307  else
308  {
309  //Reject the request with a generic error notification
310  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
311  break;
312  }
313 
314 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
315  //NAT_DETECTION_SOURCE_IP notification received?
316  if(payloads.natDetectSrcIpNotify != NULL)
317  {
318  //There MAY be multiple NAT_DETECTION_SOURCE_IP payloads in a message
319  //if the sender does not know which of several network attachments
320  //will be used to send the packet (refer to RFC 7296, section 2.23)
322 
323  //Malformed notification?
324  if(error)
325  {
326  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
327  break;
328  }
329  }
330 
331  //NAT_DETECTION_DESTINATION_IP notification received?
332  if(payloads.natDetectDestIpNotify != NULL)
333  {
334  //The NAT_DETECTION_DESTINATION_IP payloads can be used to detect if
335  //there is NAT between the hosts
337  payloads.natDetectDestIpNotify);
338 
339  //Malformed notification?
340  if(error)
341  {
342  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
343  break;
344  }
345  }
346 #endif
347 
348 #if (IKE_SIGN_HASH_ALGOS_SUPPORT == ENABLED)
349  //SIGNATURE_HASH_ALGORITHMS notification received?
350  if(payloads.signHashAlgosNotify != NULL)
351  {
352  //This notification indicates the list of hash functions supported by
353  //the sending peer (refer to RFC 7427, section 4)
355  payloads.signHashAlgosNotify);
356 
357  //Malformed notification?
358  if(error)
359  {
360  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
361  break;
362  }
363  }
364  else
365  {
366  //The notification is not present in the IKE_SA_INIT message
367  sa->signHashAlgos = 0;
368  }
369 #endif
370 
371  //End of exception handling block
372  } while(0);
373 
374  //An IKE message flow always consists of a request followed by a response
375  return ikeSendIkeSaInitResponse(sa);
376 }
377 
378 
379 /**
380  * @brief Parse incoming IKE_AUTH request
381  * @param[in] sa Pointer to the IKE SA
382  * @param[in] message Pointer to the received IKE message
383  * @param[in] length Length of the IKE message, in bytes
384  * @return Error code
385  **/
386 
388  size_t length)
389 {
390  error_t error;
391  IkeChildSaEntry *childSa;
392  IpsecPadEntry *padEntry;
393  IkeMessagePayloads payloads;
394 
395  //Initialize Child SA
396  childSa = NULL;
397 
398  //Check the state of the IKE SA
399  if(sa->state != IKE_SA_STATE_AUTH_REQ)
401 
402  //Start of exception handling block
403  do
404  {
405  //Check whether the message contains an unsupported critical payload
407  &sa->unsupportedCriticalPayload);
408 
409  //Valid IKE message?
410  if(error == NO_ERROR)
411  {
412  //The message is valid
413  }
414  else if(error == ERROR_UNSUPPORTED_OPTION)
415  {
416  //Reject the message and send an UNSUPPORTED_CRITICAL_PAYLOAD error
418  break;
419  }
420  else
421  {
422  //Reject the message and send an INVALID_SYNTAX error
423  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
424  break;
425  }
426 
427  //Parse IKE message payloads
429 
430  //Mandatory payloads must be included in the received message
431  if(payloads.idi == NULL || payloads.auth == NULL)
432  {
433  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
434  break;
435  }
436 
437  //Parse Identification payload
438  error = ikeParseIdPayload(sa, payloads.idi);
439  //Malformed Identification payload?
440  if(error)
441  {
442  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
443  break;
444  }
445 
446 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
447  //Check if the remote endpoint is behind a NAT
448  if(sa->remoteNat)
449  {
450  //Perform ID substitution
451  ikeSubstituteId(sa);
452  }
453 #endif
454 
455  //Perform lookup in the PAD database based on the ID
456  padEntry = ipsecFindPadEntry(sa->context->netContext->ipsecContext,
457  sa->peerIdType, sa->peerId, sa->peerIdLen);
458 
459  //All errors causing the authentication to fail for whatever reason
460  //(invalid shared secret, invalid ID, untrusted certificate issuer,
461  //revoked or expired certificate, etc.) should result in an
462  //AUTHENTICATION_FAILED notification
463  if(padEntry == NULL)
464  {
465  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_AUTH_FAILED;
466  break;
467  }
468 
469 #if (IKE_CERT_AUTH_SUPPORT == ENABLED)
470  //Check whether a Certificate payload is included
471  if(payloads.cert != NULL)
472  {
473  //Parse the certificate chain
474  error = ikeParseCertificateChain(sa, padEntry, message, length);
475 
476  //Failed to validate certificate chain?
477  if(error)
478  {
479  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_AUTH_FAILED;
480  break;
481  }
482  }
483 #endif
484 
485  //The peers are authenticated by having each sign (or MAC using a padded
486  //shared secret as the key, as described later in this section) a block
487  //of data (refer to RFC 7296, section 2.15)
488  error = ikeVerifyAuth(sa, padEntry, payloads.idi, payloads.cert,
489  payloads.auth);
490 
491  //Authentication failure?
492  if(error)
493  {
494  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_AUTH_FAILED;
495  break;
496  }
497 
498  //The Certificate Request payload is optional
499  if(payloads.certReq != NULL)
500  {
501  //The Certificate Request payload provides a means to request preferred
502  //certificates via IKE (refer to RFC 7296, section 3.7)
503  error = ikeParseCertReqPayload(sa, payloads.certReq);
504 
505  //Malformed Certificate Request payload?
506  if(error)
507  {
508  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
509  break;
510  }
511  }
512 
513  //Child SAs can be created either by being piggybacked on the IKE_AUTH
514  //exchange, or using a separate CREATE_CHILD_SA exchange
515  if(payloads.sa != NULL && payloads.tsi != NULL && payloads.tsr != NULL)
516  {
517  //Piggyback setup of the Child SA
519  }
520 
521 #if (IKE_INITIAL_CONTACT_SUPPORT == ENABLED)
522  //The INITIAL_CONTACT notification asserts that this IKE SA is the only
523  //IKE SA currently active between the authenticated identities
524  if(payloads.initialContactNotify)
525  {
526  //It may be sent when an IKE SA is established after a crash, and the
527  //recipient may use this information to delete any other IKE SAs it
528  //has to the same authenticated identity without waiting for a timeout
529  sa->initialContact = TRUE;
530  }
531 #endif
532 
533  //End of exception handling block
534  } while(0);
535 
536  //An IKE message flow always consists of a request followed by a response
537  return ikeSendIkeAuthResponse(sa);
538 }
539 
540 
541 /**
542  * @brief Parse incoming CREATE_CHILD_SA request
543  * @param[in] sa Pointer to the IKE SA
544  * @param[in] message Pointer to the received IKE message
545  * @param[in] length Length of the IKE message, in bytes
546  * @return Error code
547  **/
548 
550  size_t length)
551 {
552 #if (IKE_CREATE_CHILD_SA_SUPPORT == ENABLED)
553  error_t error;
554  IkeMessagePayloads payloads;
555 
556  //The CREATE_CHILD_SA exchange may be initiated by either end of the IKE SA
557  //after the initial exchanges are completed (refer to RFC 7296, section 1.3)
558  if(sa->state < IKE_SA_STATE_OPEN)
560 
561  //Start of exception handling block
562  do
563  {
564  //Check whether the message contains an unsupported critical payload
566  &sa->unsupportedCriticalPayload);
567 
568  //Valid IKE message?
569  if(error == NO_ERROR)
570  {
571  //The message is valid
572  }
573  else if(error == ERROR_UNSUPPORTED_OPTION)
574  {
575  //Reject the message and send an UNSUPPORTED_CRITICAL_PAYLOAD error
577  break;
578  }
579  else
580  {
581  //Reject the message and send an INVALID_SYNTAX error
582  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
583  break;
584  }
585 
586  //Parse IKE message payloads
588 
589  //The CREATE_CHILD_SA exchange is used to create new Child SAs and to
590  //rekey both IKE SAs and Child SAs (refer to RFC 7296, section 1.3)
591  if(payloads.sa != NULL && payloads.nonce != NULL &&
592  payloads.tsi != NULL && payloads.tsr != NULL &&
593  payloads.rekeySaNotify == NULL)
594  {
595  //Child SA creation
596  ikeProcessChildSaCreateRequest(sa, NULL, &payloads);
597  }
598  else if(payloads.sa != NULL && payloads.nonce != NULL &&
599  payloads.tsi != NULL && payloads.tsr != NULL &&
600  payloads.rekeySaNotify != NULL)
601  {
602  //Child SA rekeying
603  ikeProcessChildSaRekeyRequest(sa, &payloads);
604  }
605  else if(payloads.sa != NULL && payloads.nonce != NULL &&
606  payloads.ke != NULL && payloads.tsi == NULL &&
607  payloads.tsr == NULL && payloads.rekeySaNotify == NULL)
608  {
609  //IKE SA rekeying
610  ikeProcessIkeSaRekeyRequest(sa, &payloads);
611  }
612  else
613  {
614  //The received message does not include mandatory payloads
615  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
616  break;
617  }
618 
619  //End of exception handling block
620  } while(0);
621 
622  //An IKE message flow always consists of a request followed by a response
623  return ikeSendCreateChildSaResponse(sa);
624 #else
625  //The CREATE_CHILD_SA exchange may be initiated by either end of the IKE SA
626  //after the initial exchanges are completed (refer to RFC 7296, section 1.3)
627  if(sa->state < IKE_SA_STATE_OPEN)
629 
630  //A minimal implementation may support the CREATE_CHILD_SA exchange only in
631  //so far as to recognize requests and reject them with a Notify payload of
632  //type NO_ADDITIONAL_SAS (refer to RFC 7296, section 4)
633  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_ADDITIONAL_SAS;
634 
635  //An IKE message flow always consists of a request followed by a response
636  return ikeSendCreateChildSaResponse(sa);
637 #endif
638 }
639 
640 
641 /**
642  * @brief Parse incoming INFORMATIONAL request
643  * @param[in] sa Pointer to the IKE SA
644  * @param[in] message Pointer to the received IKE message
645  * @param[in] length Length of the IKE message, in bytes
646  * @return Error code
647  **/
648 
650  size_t length)
651 {
652  error_t error;
653  uint_t i;
654  uint16_t notifyMsgType;
655  IkeMessagePayloads payloads;
656  const IkeDeletePayload *deletePayload;
657 
658  //INFORMATIONAL exchanges must only occur after the initial exchanges
659  //and are cryptographically protected with the negotiated keys (refer to
660  //RFC 7296, section 1.4)
661  if(sa->state < IKE_SA_STATE_OPEN)
663 
664  //Start of exception handling block
665  do
666  {
667  //Check whether the message contains an unsupported critical payload
669  &sa->unsupportedCriticalPayload);
670 
671  //Valid IKE message?
672  if(error == NO_ERROR)
673  {
674  //The message is valid
675  }
676  else if(error == ERROR_UNSUPPORTED_OPTION)
677  {
678  //Reject the message and send an UNSUPPORTED_CRITICAL_PAYLOAD error
680  break;
681  }
682  else
683  {
684  //Reject the message and send an INVALID_SYNTAX error
685  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
686  break;
687  }
688 
689  //Parse IKE message payloads
691 
692  //Error notification received?
693  if(payloads.errorNotify != NULL)
694  {
695  //Types in the range 0-16383 are intended for reporting errors
696  notifyMsgType = ntohs(payloads.errorNotify->notifyMsgType);
697 
698  //Check error type
701  {
702  //This error notification is considered fatal in both peers
703  sa->deleteReceived = TRUE;
704  }
705  else
706  {
707  //Unrecognized error types in a request must be ignored (refer to
708  //RFC 7296, section 3.10.1)
709  }
710  }
711 
712  //To delete an SA, an INFORMATIONAL exchange with one or more Delete
713  //payloads is sent listing the SPIs of the SAs to be deleted (refer to
714  //RFC 7296, section 1.4.1)
715  for(i = 0; ; i++)
716  {
717  //Extract next Delete payload
718  deletePayload = (IkeDeletePayload *) ikeGetPayload(message, length,
719  IKE_PAYLOAD_TYPE_D, i);
720 
721  //Delete payload not found?
722  if(deletePayload == NULL)
723  break;
724 
725  //The Delete payload list the SPIs to be deleted
726  error = ikeParseDeletePayload(sa, deletePayload, FALSE);
727 
728  //Malformed payload?
729  if(error)
730  {
731  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
732  break;
733  }
734  }
735 
736  //End of exception handling block
737  } while(0);
738 
739  //An IKE message flow always consists of a request followed by a response
740  return ikeSendInfoResponse(sa);
741 }
742 
743 
744 /**
745  * @brief Process initial Child SA creation request
746  * @param[in] sa Pointer to the IKE SA
747  * @param[in] payloads Pointer to the IKE message payloads
748  **/
749 
751  IkeMessagePayloads *payloads)
752 {
753  error_t error;
754  IkeChildSaEntry *childSa;
755 
756  //Create a new Child SA
757  childSa = ikeCreateChildSaEntry(sa->context);
758 
759  //Successful Child SA creation?
760  if(childSa != NULL)
761  {
762  //Start of exception handling block
763  do
764  {
765  //Initialize Child SA
766  childSa->sa = sa;
767  childSa->mode = IPSEC_MODE_TUNNEL;
768  childSa->initiator = FALSE;
769 
770  //Generate a new SPI for the Child SA
771  error = ikeGenerateChildSaSpi(childSa, childSa->localSpi);
772 
773  //Any error to report?
774  if(error)
775  {
776  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
777  break;
778  }
779 
780  //The USE_TRANSPORT_MODE notification may be included in a request
781  //message that also includes an SA payload requesting a Child SA
782  if(payloads->useTransportModeNotify != NULL)
783  {
784  //It requests that the Child SA use transport mode rather than
785  //tunnel mode for the SA created
786  childSa->mode = IPSEC_MODE_TRANSPORT;
787  }
788 
789  //IKEv2 allows the responder to choose a subset of the traffic proposed
790  //by the initiator (refer to RFC 7296, section 2.9)
791  error = ikeSelectTs(childSa, payloads->tsi, payloads->tsr);
792 
793  //Check status code
794  if(error)
795  {
796  //If no SPD entry was found, or (if found) the SPD entry does not
797  //allow transport mode, undo the Traffic Selector substitutions.
798  //Do SPD lookup again using the original traffic selectors, but
799  //also searching for tunnel mode SPD entry (refer to RFC 7296,
800  //section 2.23.1)
801  if(childSa->mode == IPSEC_MODE_TRANSPORT)
802  {
803  //Fall back to tunnel mode
804  childSa->mode = IPSEC_MODE_TUNNEL;
805 
806  //Perform SPD lookup again
807  error = ikeSelectTs(childSa, payloads->tsi, payloads->tsr);
808  }
809  }
810 
811  //If the responder's policy does not allow it to accept any part of
812  //the proposed Traffic Selectors, it responds with a TS_UNACCEPTABLE
813  //Notify message
814  if(error)
815  {
816  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_TS_UNACCEPTABLE;
817  break;
818  }
819 
820  //Check the syntax of the SAi payload
821  error = ikeParseSaPayload(payloads->sa);
822 
823  //Malformed SAi payload?
824  if(error)
825  {
826  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
827  break;
828  }
829 
830  //The responder must choose a single suite, which may be any subset
831  //of the SA proposal (refer to RFC 7296, section 2.7)
832  error = ikeSelectChildSaProposal(childSa, payloads->sa);
833 
834  //The responder must accept a single proposal or reject them all and
835  //return an error. The error is given in a notification of type
836  //NO_PROPOSAL_CHOSEN
837  if(error)
838  {
839  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
840  break;
841  }
842 
843  //Attach the newly created Child SA to the IKE SA
844  sa->childSa2 = childSa;
845 
846  //End of exception handling block
847  } while(0);
848 
849  //Clean up any side effects if an error occurred
850  if(error)
851  {
852  ikeDeleteChildSaEntry(childSa);
853  }
854  }
855  else
856  {
857  //The NO_PROPOSAL_CHOSEN error notification can be used as a generic
858  //error when a Child SA cannot be created for some reason(refer to
859  //RFC 7296, section 3.10.1)
860  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
861  }
862 }
863 
864 
865 /**
866  * @brief Process Child SA creation request
867  * @param[in] sa Pointer to the IKE SA
868  * @param[in] oldChildSa Pointer to the existing Child SA (for rekeying)
869  * @param[in] payloads Pointer to the IKE message payloads
870  **/
871 
873  IkeMessagePayloads *payloads)
874 {
875 #if (IKE_CREATE_CHILD_SA_SUPPORT == ENABLED)
876  error_t error;
877  IkeContext *context;
878  IkeChildSaEntry *childSa;
879 
880  //Point to the IKE context
881  context = sa->context;
882 
883  //If a peer receives a request to create or rekey a Child SA when it is
884  //currently rekeying the IKE SA, it should reply with TEMPORARY_FAILURE
885  //(refer to RFC 7296, section 2.25.2)
886  if(sa->state == IKE_SA_STATE_REKEY_RESP)
887  {
888  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_TEMPORARY_FAILURE;
889  return;
890  }
891 
892  //Create a new Child SA
893  childSa = ikeCreateChildSaEntry(sa->context);
894 
895  //Failed to create Child SA?
896  if(childSa == NULL)
897  {
898  //The NO_PROPOSAL_CHOSEN error notification can be used as a generic
899  //error when a Child SA cannot be created for some reason(refer to
900  //RFC 7296, section 3.10.1)
901  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
902  return;
903  }
904 
905  //Start of exception handling block
906  do
907  {
908  //Initialize Child SA
909  childSa->sa = sa;
910  childSa->oldChildSa = oldChildSa;
911  childSa->mode = IPSEC_MODE_TUNNEL;
912  childSa->initiator = FALSE;
913 
914  //The KEi payload is optional
915  if(payloads->ke != NULL)
916  {
917 #if (IKE_CHILD_SA_PFS_SUPPORT == ENABLED)
918  //The CREATE_CHILD_SA request may optionally contain a KE payload for
919  //an additional Diffie-Hellman exchange to enable stronger guarantees
920  //of forward secrecy for the Child SA (refer to RFC 7296, section 1.3)
921  childSa->pfs = TRUE;
922 #else
923  //Perfect forward secrecy is not supported
924  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
925 
926  //Report an error
927  error = ERROR_INVALID_PROPOSAL;
928  break;
929 #endif
930  }
931 
932  //Save initiator's nonce
933  error = ikeParseNoncePayload(payloads->nonce, childSa->initiatorNonce,
934  &childSa->initiatorNonceLen);
935 
936  //Malformed nonce?
937  if(error)
938  {
939  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
940  break;
941  }
942 
943  //Nonces used in IKEv2 must be at least half the key size of the
944  //negotiated pseudorandom function (refer to RFC 7296, section 2.10)
945  error = ikeCheckNonceLength(sa, childSa->initiatorNonceLen);
946 
947  //Unacceptable nonce length?
948  if(error)
949  {
950  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
951  break;
952  }
953 
954  //Generate a new SPI for the Child SA
955  error = ikeGenerateChildSaSpi(childSa, childSa->localSpi);
956 
957  //Any error to report?
958  if(error)
959  {
960  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
961  break;
962  }
963 
964  //Nonces used in IKEv2 must be randomly chosen and must be at least
965  //128 bits in size (refer to RFC 7296, section 2.10)
966  error = ikeGenerateNonce(context, childSa->responderNonce,
967  &childSa->responderNonceLen);
968 
969  //Any error to report?
970  if(error)
971  {
972  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
973  break;
974  }
975 
976  //The USE_TRANSPORT_MODE notification may be included in a request
977  //message that also includes an SA payload requesting a Child SA
978  if(payloads->useTransportModeNotify != NULL)
979  {
980  //It requests that the Child SA use transport mode rather than
981  //tunnel mode for the SA created
982  childSa->mode = IPSEC_MODE_TRANSPORT;
983  }
984 
985  //IKEv2 allows the responder to choose a subset of the traffic proposed
986  //by the initiator (refer to RFC 7296, section 2.9)
987  error = ikeSelectTs(childSa, payloads->tsi, payloads->tsr);
988 
989  //Check status code
990  if(error)
991  {
992  //If no SPD entry was found, or (if found) the SPD entry does not allow
993  //transport mode, undo the Traffic Selector substitutions. Do SPD
994  //lookup again using the original traffic selectors, but also searching
995  //for tunnel mode SPD entry (refer to RFC 7296, section 2.23.1)
996  if(childSa->mode == IPSEC_MODE_TRANSPORT)
997  {
998  //Fall back to tunnel mode
999  childSa->mode = IPSEC_MODE_TUNNEL;
1000 
1001  //Perform SPD lookup again
1002  error = ikeSelectTs(childSa, payloads->tsi, payloads->tsr);
1003  }
1004  }
1005 
1006  //If the responder's policy does not allow it to accept any part of
1007  //the proposed Traffic Selectors, it responds with a TS_UNACCEPTABLE
1008  //Notify message
1009  if(error)
1010  {
1011  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_TS_UNACCEPTABLE;
1012  break;
1013  }
1014 
1015  //Check the syntax of the SAi payload
1016  error = ikeParseSaPayload(payloads->sa);
1017 
1018  //Malformed SAi payload?
1019  if(error)
1020  {
1021  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
1022  break;
1023  }
1024 
1025  //The responder must choose a single suite, which may be any subset
1026  //of the SA proposal (refer to RFC 7296, section 2.7)
1027  error = ikeSelectChildSaProposal(childSa, payloads->sa);
1028 
1029  //The responder must accept a single proposal or reject them all and
1030  //return an error. The error is given in a notification of type
1031  //NO_PROPOSAL_CHOSEN
1032  if(error)
1033  {
1034  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1035  break;
1036  }
1037 
1038 #if (IKE_CHILD_SA_PFS_SUPPORT == ENABLED)
1039  //Perfect forward secrecy?
1040  if(childSa->pfs)
1041  {
1042  //The Key Exchange payload is used to exchange Diffie-Hellman public
1043  //numbers as part of a Diffie-Hellman key exchange
1044  error = ikeParseKePayload(&childSa->keContext, payloads->ke);
1045 
1046  //Check status code
1047  if(error == NO_ERROR)
1048  {
1049  //The Key Exchange payload is acceptable
1050  }
1051  else if(error == ERROR_INVALID_SYNTAX)
1052  {
1053  //The Key Exchange payload is malformed
1054  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
1055  break;
1056  }
1057  else if(error == ERROR_INVALID_GROUP)
1058  {
1059  //If the responder selects a proposal using a different group, the
1060  //responder must reject the request and indicate its preferred group
1061  //in the INVALID_KE_PAYLOAD Notify payload (refer to RFC 7296,
1062  //section 1.3)
1063  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_KE_PAYLOAD;
1064  sa->preferredGroupNum = childSa->keContext.groupNum;
1065  break;
1066  }
1067  else
1068  {
1069  //Reject the request with a generic error notification
1070  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1071  break;
1072  }
1073 
1074  //Generate an ephemeral key pair
1075  error = ikeGenerateKeyPair(&childSa->keContext, context->prngAlgo,
1076  context->prngContext);
1077 
1078  //Any error to report?
1079  if(error)
1080  {
1081  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1082  break;
1083  }
1084 
1085  //Let g^ir be the Diffie-Hellman shared secret
1086  error = ikeComputeSharedSecret(&childSa->keContext,
1087  childSa->sharedSecret, &childSa->sharedSecretLen);
1088 
1089  //Any error to report?
1090  if(error)
1091  {
1092  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1093  break;
1094  }
1095  }
1096 #endif
1097 
1098  //Additional Child SAs can optionally be created in CREATE_CHILD_SA
1099  //exchanges. Keying material for Child SAs must be taken from the
1100  //expanded KEYMAT (refer to RFC 7296, section 2.17)
1101  error = ikeGenerateChildSaKeyMaterial(childSa);
1102 
1103  //Any error to report?
1104  if(error)
1105  {
1106  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1107  break;
1108  }
1109 
1110  //Simultaneous Child SA rekeying may temporarily result in multiple
1111  //similar SAs between the same pairs of nodes
1112  if(oldChildSa != NULL && oldChildSa->state == IKE_CHILD_SA_STATE_REKEY)
1113  {
1114  //The peer will close the redundant SAs later based on the nonces
1115  //(refer to RFC 7296, section 2.25.1)
1116  }
1117  else
1118  {
1119  //The new Child SA has been successfully created
1121 
1122  //ESP and AH SAs exist in pairs (one in each direction), so two SAs
1123  //are created in a single Child SA negotiation for them
1124  ikeCreateIpsecSaPair(childSa);
1125  }
1126 
1127  //Attach the newly created Child SA to the IKE SA
1128  sa->childSa2 = childSa;
1129 
1130  //End of exception handling block
1131  } while(0);
1132 
1133  //Clean up any side effects if an error occurred
1134  if(error)
1135  {
1136  ikeDeleteChildSaEntry(childSa);
1137  }
1138 #endif
1139 }
1140 
1141 
1142 /**
1143  * @brief Process Child SA rekeying request
1144  * @param[in] sa Pointer to the IKE SA
1145  * @param[in] payloads Pointer to the IKE message payloads
1146  **/
1147 
1149  IkeMessagePayloads *payloads)
1150 {
1151 #if (IKE_CREATE_CHILD_SA_SUPPORT == ENABLED)
1152  IkeChildSaEntry *oldChildSa;
1153 
1154  //The SPI is included only with INVALID_SELECTORS, REKEY_SA, and
1155  //CHILD_SA_NOT_FOUND notifications (refer to RFC 7296, section 3.10)
1156  if(payloads->rekeySaNotify->spiSize != IPSEC_SPI_SIZE)
1157  {
1158  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
1159  return;
1160  }
1161 
1162  //The SA being rekeyed is identified by the SPI field in the Notify payload;
1163  //this is the SPI the exchange initiator would expect in inbound ESP or AH
1164  //packet (refer to RFC 7296, section 1.3.3)
1165  oldChildSa = ikeFindChildSaEntry(sa, payloads->rekeySaNotify->protocolId,
1166  payloads->rekeySaNotify->spi);
1167 
1168  //If a peer receives a request to rekey a Child SA that does not exist, it
1169  //should reply with CHILD_SA_NOT_FOUND (refer to RFC 7296, section 2.25.1)
1170  if(oldChildSa == NULL)
1171  {
1172  //Send a CHILD_SA_NOT_FOUND error notification
1173  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_CHILD_SA_NOT_FOUND;
1174  sa->notifyProtocolId = payloads->rekeySaNotify->protocolId;
1175 
1176  //The SA that the initiator attempted to rekey is indicated by the SPI
1177  //field in the Notify payload, which is copied from the SPI field in the
1178  //REKEY_SA notification (refer to RFC 7296, section 2.25)
1179  osMemcpy(sa->notifySpi, payloads->rekeySaNotify->spi, IPSEC_SPI_SIZE);
1180 
1181  //We are done
1182  return;
1183  }
1184 
1185  //Exchange collision?
1186  if(oldChildSa->state == IKE_CHILD_SA_STATE_REKEY)
1187  {
1188  //If a peer receives a request to rekey a Child SA that it is currently
1189  //rekeying, it should reply as usual, and should prepare to close
1190  //redundant SAs later based on the nonces (refer to RFC 7296, section
1191  //2.25.1)
1192  }
1193  else if(oldChildSa->state == IKE_CHILD_SA_STATE_DELETE)
1194  {
1195  //If a peer receives a request to rekey a Child SA that it is currently
1196  //trying to close, it should reply with TEMPORARY_FAILURE (refer to
1197  //RFC 7296, section 2.25.1)
1198  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_TEMPORARY_FAILURE;
1199  return;
1200  }
1201  else
1202  {
1203  //No collision detected
1204  }
1205 
1206  //Create a new equivalent Child SA
1207  ikeProcessChildSaCreateRequest(sa, oldChildSa, payloads);
1208 #endif
1209 }
1210 
1211 
1212 /**
1213  * @brief Process IKE SA rekeying request
1214  * @param[in] sa Pointer to the IKE SA
1215  * @param[in] payloads Pointer to the IKE message payloads
1216  **/
1217 
1219 {
1220 #if (IKE_CREATE_CHILD_SA_SUPPORT == ENABLED)
1221  error_t error;
1222  IkeContext *context;
1223  IkeSaEntry *newSa;
1224 
1225  //Point to the IKE context
1226  context = sa->context;
1227 
1228  //Exchange collision?
1229  if(sa->state == IKE_SA_STATE_REKEY_RESP)
1230  {
1231  //If a peer receives a request to rekey an IKE SA that it is currently
1232  //rekeying, it should reply as usual, and should prepare to close
1233  //redundant SAs and move inherited Child SAs later based on the nonces
1234  //(refer to RFC 7296, section 2.25.2)
1235  }
1236  else if(sa->state == IKE_SA_STATE_DELETE_RESP)
1237  {
1238  //If a peer receives a request to rekey an IKE SA that it is currently
1239  //trying to close, it should reply with TEMPORARY_FAILURE (refer to
1240  //RFC 7296, section 2.25.2)
1241  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_TEMPORARY_FAILURE;
1242  return;
1243  }
1244  else if(sa->state == IKE_SA_STATE_CREATE_CHILD_RESP ||
1245  sa->state == IKE_SA_STATE_REKEY_CHILD_RESP ||
1246  sa->state == IKE_SA_STATE_DELETE_CHILD_RESP)
1247  {
1248  //If a peer receives a request to rekey the IKE SA, and it is currently
1249  //creating, rekeying, or closing a Child SA of that IKE SA, it should
1250  //reply with TEMPORARY_FAILURE (refer to RFC 7296, section 2.25.1)
1251  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_TEMPORARY_FAILURE;
1252  return;
1253  }
1254  else
1255  {
1256  //No collision detected
1257  }
1258 
1259  //Create a new IKE SA
1260  newSa = ikeCreateSaEntry(context);
1261 
1262  //Failed to create IKE SA?
1263  if(newSa == NULL)
1264  {
1265  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1266  return;
1267  }
1268 
1269  //Start of exception handling block
1270  do
1271  {
1272  //Initialize IKE SA
1273  newSa->remoteIpAddr = sa->remoteIpAddr;
1274 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
1275  newSa->localNat = sa->localNat;
1276  newSa->remoteNat = sa->remoteNat;
1277 #endif
1278 
1279  //The initiator of the rekey exchange is the new "original initiator" of
1280  //the new IKE SA (refer to RFC 7296, section 1.3.2)
1281  newSa->originalInitiator = FALSE;
1282 
1283  //Save initiator's nonce
1284  error = ikeParseNoncePayload(payloads->nonce, newSa->initiatorNonce,
1285  &newSa->initiatorNonceLen);
1286 
1287  //Malformed nonce?
1288  if(error)
1289  {
1290  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
1291  break;
1292  }
1293 
1294  //Check the syntax of the SAi payload
1295  error = ikeParseSaPayload(payloads->sa);
1296 
1297  //Malformed SAi payload?
1298  if(error)
1299  {
1300  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
1301  break;
1302  }
1303 
1304  //The responder must choose a single suite, which may be any subset of
1305  //the SA proposal (refer to RFC 7296, section 2.7)
1306  error = ikeSelectSaProposal(newSa, payloads->sa, IKE_SPI_SIZE);
1307 
1308  //The responder must accept a single proposal or reject them all and
1309  //return an error. The error is given in a notification of type
1310  //NO_PROPOSAL_CHOSEN
1311  if(error)
1312  {
1313  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1314  break;
1315  }
1316 
1317  //Nonces used in IKEv2 must be at least half the key size of the
1318  //negotiated pseudorandom function (refer to RFC 7296, section 2.10)
1319  error = ikeCheckNonceLength(newSa, newSa->initiatorNonceLen);
1320 
1321  //Unacceptable nonce length?
1322  if(error)
1323  {
1324  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
1325  break;
1326  }
1327 
1328  //The Key Exchange payload is used to exchange Diffie-Hellman public
1329  //numbers as part of a Diffie-Hellman key exchange
1330  error = ikeParseKePayload(&newSa->keContext, payloads->ke);
1331 
1332  //Check status code
1333  if(error == NO_ERROR)
1334  {
1335  //The Key Exchange payload is acceptable
1336  }
1337  else if(error == ERROR_INVALID_SYNTAX)
1338  {
1339  //The Key Exchange payload is malformed
1340  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX;
1341  break;
1342  }
1343  else if(error == ERROR_INVALID_GROUP)
1344  {
1345  //If the responder selects a proposal using a different group, the
1346  //responder must reject the request and indicate its preferred group
1347  //in the INVALID_KE_PAYLOAD Notify payload (refer to RFC 7296,
1348  //section 1.3)
1349  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_INVALID_KE_PAYLOAD;
1350  sa->preferredGroupNum = newSa->keContext.groupNum;
1351  break;
1352  }
1353  else
1354  {
1355  //Reject the request with a generic error notification
1356  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1357  break;
1358  }
1359 
1360  //Each endpoint chooses one of the two SPIs and must choose them so as to
1361  //be unique identifiers of an IKE SA (refer to RFC 7296, section 2.6)
1362  error = ikeGenerateSaSpi(newSa, newSa->responderSpi);
1363 
1364  //Any error to report?
1365  if(error)
1366  {
1367  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1368  break;
1369  }
1370 
1371  //Nonces used in IKEv2 must be randomly chosen and must be at least 128
1372  //bits in size (refer to RFC 7296, section 2.10)
1373  error = ikeGenerateNonce(context, newSa->responderNonce,
1374  &newSa->responderNonceLen);
1375 
1376  //Any error to report?
1377  if(error)
1378  {
1379  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1380  break;
1381  }
1382 
1383  //Generate an ephemeral key pair
1384  error = ikeGenerateKeyPair(&newSa->keContext, context->prngAlgo,
1385  context->prngContext);
1386 
1387  //Any error to report?
1388  if(error)
1389  {
1390  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1391  break;
1392  }
1393 
1394  //Let g^ir be the Diffie-Hellman shared secret
1395  error = ikeComputeSharedSecret(&newSa->keContext, newSa->sharedSecret,
1396  &newSa->sharedSecretLen);
1397 
1398  //Any error to report?
1399  if(error)
1400  {
1401  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1402  break;
1403  }
1404 
1405  //At this point in the negotiation, each party can generate a quantity
1406  //called SKEYSEED, from which all keys are derived for that IKE SA (refer
1407  //to RFC 7296, section 1.2)
1408  error = ikeGenerateSaKeyMaterial(newSa, sa);
1409 
1410  //Any error to report?
1411  if(error)
1412  {
1413  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN;
1414  break;
1415  }
1416 
1417  //When both peers try to rekey the IKE SA at the same time, it is
1418  //important to ensure that the Child SAs are inherited by the correct
1419  //IKE SA (refer to RFC 7296, section 2.8.2)
1420  if(sa->state == IKE_SA_STATE_REKEY_RESP)
1421  {
1422  //The peer will move inherited Child SAs later based on the nonces
1423  }
1424  else
1425  {
1426  //The new IKE SA has been successfully created
1428 
1429  //The new IKE SA inherits all of the original IKE SA's Child SAs, and
1430  //is used for all control messages needed to maintain those Child SAs
1431  ikeInheritChildSas(newSa, sa);
1432  }
1433 
1434  //Attach the newly created IKE SA
1435  sa->newSa2 = newSa;
1436 
1437  //End of exception handling block
1438  } while(0);
1439 
1440  //Clean up any side effects if an error occurred
1441  if(error)
1442  {
1443  ikeDeleteSaEntry(newSa);
1444  }
1445 #endif
1446 }
1447 
1448 #endif
@ IKE_CHILD_SA_STATE_DELETE
Definition: ike.h:1389
#define IPSEC_SPI_SIZE
Definition: ipsec.h:145
error_t ikeParseIdPayload(IkeSaEntry *sa, const IkeIdPayload *idPayload)
Parse Identification payload.
Diffie-Hellman key exchange.
Authentication of the IKE SA.
Helper functions for IKEv2.
error_t ikeComputeSharedSecret(IkeKeContext *keContext, uint8_t *output, size_t *outputLen)
Compute shared secret.
const IkeNotifyPayload * initialContactNotify
error_t ikeRetransmitResponse(IkeSaEntry *sa)
Retransmit IKE response message.
Definition: ike_misc.c:117
error_t ikeParseCookieNotification(IkeSaEntry *sa, const IkeNotifyPayload *notifyPayload)
Parse COOKIE notification.
IpsecPadEntry * ipsecFindPadEntry(IpsecContext *context, uint8_t idType, const uint8_t *id, size_t idLen)
Find PAD entry that matches the specified identification data.
Definition: ipsec_misc.c:254
@ IKE_NOTIFY_MSG_TYPE_CHILD_SA_NOT_FOUND
Definition: ike.h:1202
const IkeNotifyPayload * natDetectSrcIpNotify
@ IKE_NOTIFY_MSG_TYPE_NO_PROPOSAL_CHOSEN
Definition: ike.h:1189
void ikeProcessInitialChildSaCreateRequest(IkeSaEntry *sa, IkeMessagePayloads *payloads)
Process initial Child SA creation request.
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:195
const IkeNotifyPayload * errorNotify
error_t ikeCheckCriticalPayloads(const uint8_t *message, size_t length, uint8_t *unsupportedCriticalPayload)
Check whether the message contains an unsupported critical payload.
uint8_t message[]
Definition: chap.h:154
const IkeNotifyPayload * cookieNotify
error_t ikeGenerateSaSpi(IkeSaEntry *sa, uint8_t *spi)
Generate a new IKE SA SPI.
Definition: ike_misc.c:632
error_t ikeParseInfoRequest(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse incoming INFORMATIONAL request.
IKE message payloads.
const IkePayloadHeader * ikeGetPayload(const uint8_t *message, size_t length, uint8_t type, uint_t index)
Search an IKE message for a given payload type.
#define TRUE
Definition: os_port.h:50
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
const IkeNoncePayload * nonce
error_t ikeParseNoncePayload(const IkeNoncePayload *noncePayload, uint8_t *nonce, size_t *nonceLen)
Parse Nonce payload.
error_t ikeSendInfoResponse(IkeSaEntry *sa)
Send INFORMATIONAL response.
IkeChildSaEntry * ikeCreateChildSaEntry(IkeContext *context)
Create a new Child Security Association.
Definition: ike_misc.c:451
const IkeTsPayload * tsr
IKE request parsing.
error_t ikeSelectChildSaProposal(IkeChildSaEntry *childSa, const IkeSaPayload *payload)
Select a single proposal (AH or ESP protocol)
#define osMemcmp(p1, p2, length)
Definition: os_port.h:159
void ikeProcessIkeSaRekeyRequest(IkeSaEntry *sa, IkeMessagePayloads *payloads)
Process IKE SA rekeying request.
const IkeCertPayload * cert
@ ERROR_WRONG_COOKIE
Definition: error.h:92
@ 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:904
IKEv2 finite state machine.
const IkeCertReqPayload * certReq
@ IPSEC_MODE_TUNNEL
Definition: ipsec.h:211
error_t ikeParseSignHashAlgosNotification(IkeSaEntry *sa, const IkeNotifyPayload *notifyPayload)
Parse SIGNATURE_HASH_ALGORITHMS notification.
@ IKE_CHILD_SA_STATE_REKEY
Definition: ike.h:1388
error_t ikeParseKePayload(IkeKeContext *keContext, const IkeKePayload *kePayload)
Parse Key Exchange payload.
@ IKE_NOTIFY_MSG_TYPE_TS_UNACCEPTABLE
Definition: ike.h:1196
void ikeChangeSaState(IkeSaEntry *sa, IkeSaState newState)
Update IKE SA state.
Definition: ike_fsm.c:53
const uint8_t IKE_INVALID_SPI[8]
Definition: ike_misc.c:47
Peer Authorization Database (PAD) entry.
Definition: ipsec.h:412
#define IkeContext
Definition: ike.h:832
@ ERROR_INVALID_GROUP
Definition: error.h:276
@ IKE_SA_STATE_DELETE_CHILD_RESP
Definition: ike.h:1372
#define FALSE
Definition: os_port.h:46
error_t ikeParseNatDetectDestIpNotification(IkeSaEntry *sa, const IkeNotifyPayload *notifyPayload)
Parse NAT_DETECTION_DESTINATION_IP notification.
uint16_t notifyMsgType
Definition: ike.h:1630
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
@ ERROR_INVALID_PROPOSAL
Definition: error.h:301
IkeSaEntry * ikeCreateSaEntry(IkeContext *context)
Create a new IKE Security Association.
Definition: ike_misc.c:185
error_t ikeSendIkeAuthResponse(IkeSaEntry *sa)
Send IKE_AUTH response.
@ IPSEC_MODE_TRANSPORT
Definition: ipsec.h:212
const IkeKePayload * ke
@ IKE_SA_STATE_OPEN
Definition: ike.h:1360
error_t
Error codes.
Definition: error.h:43
@ ERROR_UNSUPPORTED_OPTION
Definition: error.h:297
Key material generation.
#define IKE_SPI_SIZE
Definition: ike.h:826
Helper routines for IPsec.
error_t ikeParseCertificateChain(IkeSaEntry *sa, IpsecPadEntry *padEntry, const uint8_t *message, size_t length)
Parse certificate chain.
@ IKE_SA_STATE_AUTH_REQ
Definition: ike.h:1358
void ikeProcessChildSaRekeyRequest(IkeSaEntry *sa, IkeMessagePayloads *payloads)
Process Child SA rekeying request.
const IkeNotifyPayload * natDetectDestIpNotify
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
void ikeDeleteSaEntry(IkeSaEntry *sa)
Delete an IKE Security Association.
Definition: ike_misc.c:347
IKE response formatting.
const IkeSaPayload * sa
error_t ikeVerifyAuth(IkeSaEntry *sa, IpsecPadEntry *padEntry, const IkeIdPayload *idPayload, const IkeCertPayload *certPayload, const IkeAuthPayload *authPayload)
Verify signature or MAC.
Definition: ike_auth.c:138
error_t ikeParseNatDetectSrcIpNotification(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse NAT_DETECTION_SOURCE_IP notification.
const IkeAuthPayload * auth
error_t ikeSendCreateChildSaResponse(IkeSaEntry *sa)
Send CREATE_CHILD_SA response.
error_t ikeParseIkeSaInitRequest(IkeContext *context, const uint8_t *message, size_t length)
Parse incoming IKE_SA_INIT request.
void ikeDeleteChildSaEntry(IkeChildSaEntry *childSa)
Delete a Child Security Association.
Definition: ike_misc.c:560
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
error_t ikeSendIkeSaInitResponse(IkeSaEntry *sa)
Send IKE_SA_INIT response.
void ikeInheritChildSas(IkeSaEntry *newSa, IkeSaEntry *oldSa)
Move inherited Child SAs.
Definition: ike_misc.c:597
IkeHeader
Definition: ike.h:1459
void ikeChangeChildSaState(IkeChildSaEntry *childSa, IkeChildSaState newState)
Update Child SA state.
Definition: ike_fsm.c:110
error_t ikeParseSaPayload(const IkeSaPayload *saPayload)
Parse Security Association payload.
IkeDeletePayload
Definition: ike.h:1646
IKEv2 (Internet Key Exchange Protocol)
error_t ikeCreateIpsecSaPair(IkeChildSaEntry *childSa)
Create AH or ESP SA pair.
Definition: ike_misc.c:1467
const IkeTsPayload * tsi
#define ntohs(value)
Definition: cpu_endian.h:421
error_t ikeSelectSaProposal(IkeSaEntry *sa, const IkeSaPayload *payload, size_t spiSize)
Select a single proposal (IKE protocol)
@ IKE_NOTIFY_MSG_TYPE_INVALID_KE_PAYLOAD
Definition: ike.h:1190
IKE payload parsing.
void ikeParseIkeMessagePayloads(const uint8_t *message, size_t length, IkeMessagePayloads *payloads)
Parse IKE message payloads.
error_t ikeGenerateKeyPair(IkeKeContext *keContext, const PrngAlgo *prngAlgo, void *prngContext)
Key pair generation.
#define IkeSaEntry
Definition: ike.h:836
@ IKE_NOTIFY_MSG_TYPE_NO_ADDITIONAL_SAS
Definition: ike.h:1193
@ IKE_NOTIFY_MSG_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD
Definition: ike.h:1183
error_t ikeGenerateChildSaKeyMaterial(IkeChildSaEntry *childSa)
Generate keying material for the Child SA.
void ikeProcessChildSaCreateRequest(IkeSaEntry *sa, IkeChildSaEntry *oldChildSa, IkeMessagePayloads *payloads)
Process Child SA creation request.
@ IKE_SA_STATE_REKEY_CHILD_RESP
Definition: ike.h:1370
error_t ikeGenerateSaKeyMaterial(IkeSaEntry *sa, IkeSaEntry *oldSa)
Generate keying material for the IKE SA.
const IkeNotifyPayload * signHashAlgosNotify
error_t ikeGenerateChildSaSpi(IkeChildSaEntry *childSa, uint8_t *spi)
Generate a new Child SA SPI.
Definition: ike_misc.c:718
error_t ikeParseCreateChildSaRequest(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse incoming CREATE_CHILD_SA request.
error_t ikeParseCertReqPayload(IkeSaEntry *sa, const IkeCertReqPayload *certReqPayload)
Parse Certificate Request payload.
@ IKE_SA_STATE_DELETE_RESP
Definition: ike.h:1366
@ IKE_NOTIFY_MSG_TYPE_AUTH_FAILED
Definition: ike.h:1191
X.509 certificate handling.
@ IKE_NOTIFY_MSG_TYPE_TEMPORARY_FAILURE
Definition: ike.h:1201
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
const IkeNotifyPayload * useTransportModeNotify
@ IKE_NOTIFY_MSG_TYPE_COOKIE
Definition: ike.h:1214
@ IKE_SA_STATE_REKEY_RESP
Definition: ike.h:1364
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
error_t ikeGenerateNonce(IkeContext *context, uint8_t *nonce, size_t *length)
Generate a new nonce.
Definition: ike_misc.c:792
error_t ikeParseIkeAuthRequest(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse incoming IKE_AUTH request.
@ IKE_SA_STATE_CREATE_CHILD_RESP
Definition: ike.h:1368
error_t ikeParseDeletePayload(IkeSaEntry *sa, const IkeDeletePayload *deletePayload, bool_t response)
Parse Delete payload.
const IkeNotifyPayload * rekeySaNotify
unsigned int uint_t
Definition: compiler_port.h:57
@ IKE_PAYLOAD_TYPE_D
Delete.
Definition: ike.h:896
const IkeIdPayload * idi
void ikeSubstituteId(IkeSaEntry *sa)
Perform ID substitution.
Definition: ike_misc.c:860
#define IkeChildSaEntry
Definition: ike.h:840
#define ntohl(value)
Definition: cpu_endian.h:422
IKEv2 algorithm negotiation.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
@ IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX
Definition: ike.h:1186
@ IKE_CHILD_SA_STATE_OPEN
Definition: ike.h:1387