ike_message_dispatch.c
Go to the documentation of this file.
1 /**
2  * @file ike_message_dispatch.c
3  * @brief IKE message dispatching
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"
38 #include "ike/ike_request_parse.h"
40 #include "ike/ike_response_parse.h"
41 #include "ike/ike_misc.h"
42 #include "ike/ike_debug.h"
43 #include "debug.h"
44 
45 //Check IKEv2 library configuration
46 #if (IKE_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Dispatch incoming IKE message
51  * @param[in] context Pointer to the IKE context
52  * @param[in] message Pointer to the received IKE message
53  * @param[in] length Length of the IKE message, in bytes
54  * @return Error code
55  **/
56 
57 error_t ikeDispatchMessage(IkeContext *context, uint8_t *message, size_t length)
58 {
59  error_t error;
60  IkeHeader *ikeHeader;
61 
62 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
63  //Port 4500 is reserved for UDP-encapsulated ESP and IKE
64  if(context->localPort == IPSEC_NAT_PORT)
65  {
66  //The receiver should ignore a received NAT-keepalive packet (refer to
67  //RFC 3948, section 2.3)
70  {
71  return NO_ERROR;
72  }
73 
74  //Malformed IKE message?
76  return ERROR_INVALID_LENGTH;
77 
78  //The UDP payload of all packets containing IKE messages sent on port 4500
79  //must begin with the prefix of four zeros (refer to RFC 7296, section 2)
81  return ERROR_INVALID_MESSAGE;
82 
83  //These four octets of zeros are not part of the IKE message and are not
84  //included in any of the length fields or checksums defined by IKE
87  }
88 #endif
89 
90  //Malformed IKE message?
91  if(length < sizeof(IkeHeader))
92  return ERROR_INVALID_LENGTH;
93 
94  //Each message begins with the IKE header
95  ikeHeader = (IkeHeader *) message;
96 
97  //Debug message
98  TRACE_INFO("IKE message received (%" PRIuSIZE " bytes)...\r\n", length);
99  //Dump IKE message for debugging purpose
101 
102  //Check the length of the IKE message
103  if(length < ntohl(ikeHeader->length))
104  return ERROR_INVALID_LENGTH;
105 
106  //The Length field indicates the total length of the IKE message in octets
107  length = ntohl(ikeHeader->length);
108 
109  //The R bit indicates whether the message is a request or response
110  if((ikeHeader->flags & IKE_FLAGS_R) == 0)
111  {
112  //Process IKE request
113  error = ikeDispatchRequest(context, message, length);
114  }
115  else
116  {
117  //Process IKE response
118  error = ikeDispatchResponse(context, message, length);
119  }
120 
121  //Return status code
122  return error;
123 }
124 
125 
126 /**
127  * @brief Dispatch incoming IKE request
128  * @param[in] context Pointer to the IKE context
129  * @param[in] message Pointer to the received IKE message
130  * @param[in] length Length of the IKE message, in bytes
131  * @return Error code
132  **/
133 
135 {
136  error_t error;
137  uint8_t exchangeType;
138  IkeHeader *ikeHeader;
139  IkeSaEntry *sa;
140 
141  //Each message begins with the IKE header
142  ikeHeader = (IkeHeader *) message;
143  //The Exchange Type field indicates the type of exchange being used
144  exchangeType = ikeHeader->exchangeType;
145 
146  //Check the major version number
147  if(ikeHeader->majorVersion <= IKE_MAJOR_VERSION)
148  {
149  //Initial exchange?
151  {
152  //Process IKE_SA_INIT request
153  error = ikeParseIkeSaInitRequest(context, message, length);
154  }
155  else
156  {
157  //Perform IKE SA lookup
158  sa = ikeFindSaEntry(context, ikeHeader);
159 
160  //Check whether the receiving node has an active IKE SA
161  if(sa != NULL)
162  {
163  //All messages following the initial exchange are cryptographically
164  //protected using the cryptographic algorithms and keys negotiated
165  //in the IKE_SA_INIT exchange (refer to RFC 7296, section 1.2)
166  error = ikeDecryptMessage(sa, message, &length);
167 
168  //Check status code
169  if(!error)
170  {
171  //The responder must remember each response until it receives a
172  //request whose sequence number is larger than or equal to the
173  //sequence number in the response plus its window size
174  if(ntohl(ikeHeader->messageId) < sa->rxMessageId &&
175  sa->rxMessageId != UINT32_MAX)
176  {
177  //If the responder receives a retransmitted request for which
178  //it has already forgotten the response, it must ignore the
179  //request
180  }
181  else if(ntohl(ikeHeader->messageId) == sa->rxMessageId &&
182  sa->rxMessageId != UINT32_MAX)
183  {
184  //The responder has received a retransmission of the request
185  error = ikeRetransmitResponse(sa);
186  }
187  else if(ntohl(ikeHeader->messageId) == (sa->rxMessageId + 1))
188  {
189  //The counter increments as requests are received
190  sa->rxMessageId++;
191 
192  //In the unlikely event that Message IDs grow too large to fit
193  //in 32 bits, the IKE SA must be closed or rekeyed (refer to
194  //RFC 7296, section 2.2)
195  if(sa->rxMessageId == UINT32_MAX)
196  {
197  //Delete the IKE SA
198  ikeDeleteSaEntry(sa);
199  }
200  else
201  {
202  //Forget the previous response
203  sa->responseLen = 0;
204  //Clear error notification
205  sa->notifyMsgType = IKE_NOTIFY_MSG_TYPE_NONE;
206 
207  //Check IKE exchange type
209  {
210  //Process IKE_AUTH request
211  error = ikeParseIkeAuthRequest(sa, message, length);
212  }
214  {
215  //Process CREATE_CHILD_SA request
217  length);
218  }
220  {
221  //Process INFORMATIONAL request
222  error = ikeParseInfoRequest(sa, message, length);
223  }
224  else
225  {
226  //Unknown exchange type
227  error = ERROR_UNKNOWN_TYPE;
228  }
229 
230  //Check the state of the IKE SA
231  if(sa->state != IKE_SA_STATE_CLOSED)
232  {
233  //Only authentication failures (AUTHENTICATION_FAILED)
234  //and malformed messages (INVALID_SYNTAX) lead to a
235  //deletion of the IKE SA without requiring an explicit
236  //INFORMATIONAL exchange carrying a Delete payload
237  if(sa->notifyMsgType == IKE_NOTIFY_MSG_TYPE_AUTH_FAILED ||
238  sa->notifyMsgType == IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX)
239  {
240  //This error notification is considered fatal in both
241  //peers
242  ikeDeleteSaEntry(sa);
243  }
244  }
245  }
246  }
247  else
248  {
249  //Discard the request since the message ID is outside the
250  //supported window
251  }
252  }
253  }
254  else
255  {
256  //If a node receives a message on UDP port 500 or 4500 outside the
257  //context of an IKE SA known to it (and the message is not a request
258  //to start an IKE SA), this may be the result of a recent crash of
259  //the node. If the message is marked as a request, the node can
260  //audit the suspicious event and may send a response
261  error = ikeSendErrorResponse(context, message, length);
262  }
263  }
264  }
265  else
266  {
267  //If an IKE request packet arrives with a higher major version number
268  //than the implementation supports, the node notifies the sender about
269  //this situation (refer to RFC 7296, section 1.5)
270  error = ikeSendErrorResponse(context, message, length);
271  }
272 
273  //Return status code
274  return error;
275 }
276 
277 
278 /**
279  * @brief Dispatch incoming IKE response
280  * @param[in] context Pointer to the IKE context
281  * @param[in] message Pointer to the received IKE message
282  * @param[in] length Length of the IKE message, in bytes
283  * @return Error code
284  **/
285 
287 {
288  error_t error;
289  uint8_t exchangeType;
290  IkeHeader *ikeHeader;
291  IkeSaEntry *sa;
292 
293  //Initialize status code
294  error = NO_ERROR;
295 
296  //Each message begins with the IKE header
297  ikeHeader = (IkeHeader *) message;
298  //The Exchange Type field indicates the type of exchange being used
299  exchangeType = ikeHeader->exchangeType;
300 
301  //Check the major version number
302  if(ikeHeader->majorVersion <= IKE_MAJOR_VERSION)
303  {
304  //Perform IKE SA lookup
305  sa = ikeFindSaEntry(context, ikeHeader);
306 
307  //Check whether the receiving node has an active IKE SA
308  if(sa != NULL)
309  {
310  //Check the state of the IKE SA
311  if(sa->state == IKE_SA_STATE_INIT_RESP ||
312  sa->state == IKE_SA_STATE_AUTH_RESP ||
313  sa->state == IKE_SA_STATE_DPD_RESP ||
314  sa->state == IKE_SA_STATE_REKEY_RESP ||
315  sa->state == IKE_SA_STATE_DELETE_RESP ||
316  sa->state == IKE_SA_STATE_CREATE_CHILD_RESP ||
317  sa->state == IKE_SA_STATE_REKEY_CHILD_RESP ||
318  sa->state == IKE_SA_STATE_DELETE_CHILD_RESP ||
319  sa->state == IKE_SA_STATE_AUTH_FAILURE_RESP)
320  {
321  //The Message ID field is used to match requests and responses
322  if(ntohl(ikeHeader->messageId) == sa->txMessageId)
323  {
324  //All messages following the initial exchange are cryptographically
325  //protected using the cryptographic algorithms and keys negotiated
326  //in the IKE_SA_INIT exchange (refer to RFC 7296, section 1.2)
328  {
329  //Decrypt IKE message
330  error = ikeDecryptMessage(sa, message, &length);
331  }
332 
333  //Check status code
334  if(!error)
335  {
336  //Check IKE exchange type
338  {
339  //Process IKE_SA_INIT response
341  }
343  {
344  //Process IKE_AUTH response
345  error = ikeParseIkeAuthResponse(sa, message, length);
346  }
348  {
349  //Process CREATE_CHILD_SA response
351  }
353  {
354  //Process INFORMATIONAL response
355  error = ikeParseInfoResponse(sa, message, length);
356  }
357  else
358  {
359  //Unknown exchange type
360  error = ERROR_UNKNOWN_TYPE;
361  }
362  }
363  }
364  else
365  {
366  //Unexpected Message ID
367  error = ERROR_WRONG_IDENTIFIER;
368  }
369  }
370  else
371  {
372  //Unexpected response
373  error = ERROR_UNEXPECTED_MESSAGE;
374  }
375  }
376  else
377  {
378  //If a node receives a message on UDP port 500 or 4500 outside the
379  //context of an IKE SA known to it, this may be the result of a
380  //recent crash of the node. If the message is marked as a response,
381  //the node can audit the suspicious event but must not respond
382  error = ERROR_INVALID_SPI;
383  }
384  }
385  else
386  {
387  //If an endpoint receives a message with a higher major version number,
388  //it must drop the message
389  error = ERROR_INVALID_VERSION;
390  }
391 
392  //Return status code
393  return error;
394 }
395 
396 #endif
#define IKE_PREFIX_SIZE
Definition: ike.h:816
error_t ikeSendErrorResponse(IkeContext *context, uint8_t *message, size_t length)
Send INFORMATIONAL response (outside of an IKE SA)
Helper functions for IKEv2.
error_t ikeRetransmitResponse(IkeSaEntry *sa)
Retransmit IKE response message.
Definition: ike_misc.c:117
#define LOAD32BE(p)
Definition: cpu_endian.h:210
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:195
uint8_t message[]
Definition: chap.h:154
error_t ikeParseInfoRequest(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse incoming INFORMATIONAL request.
error_t ikeDispatchMessage(IkeContext *context, uint8_t *message, size_t length)
Dispatch incoming IKE message.
IKE request parsing.
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
IKE message dispatching.
@ ERROR_INVALID_VERSION
Definition: error.h:118
IKE response parsing.
@ IKE_SA_STATE_CLOSED
Definition: ike.h:1354
error_t ikeDecryptMessage(IkeSaEntry *sa, uint8_t *message, size_t *messageLen)
Decrypt an incoming IKE message.
#define IPSEC_NAT_PORT
Definition: ipsec.h:142
error_t ikeParseCreateChildSaResponse(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse incoming CREATE_CHILD_SA response.
#define IkeContext
Definition: ike.h:832
@ IKE_EXCHANGE_TYPE_IKE_AUTH
IKE_AUTH.
Definition: ike.h:855
@ IKE_SA_STATE_DELETE_CHILD_RESP
Definition: ike.h:1372
error_t ikeDispatchRequest(IkeContext *context, uint8_t *message, size_t length)
Dispatch incoming IKE request.
Data logging functions for debugging purpose (IKEv2)
error_t
Error codes.
Definition: error.h:43
error_t ikeDispatchResponse(IkeContext *context, uint8_t *message, size_t length)
Dispatch incoming IKE response.
@ IKE_SA_STATE_AUTH_FAILURE_RESP
Definition: ike.h:1374
#define IKE_NAT_KEEPALIVE_PACKET_VALUE
Definition: ike.h:823
#define IKE_MAJOR_VERSION
Definition: ike.h:808
#define IKE_PREFIX_VALUE
Definition: ike.h:818
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint8_t exchangeType
Definition: ike.h:1455
error_t ikeParseInfoResponse(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse incoming INFORMATIONAL response.
void ikeDeleteSaEntry(IkeSaEntry *sa)
Delete an IKE Security Association.
Definition: ike_misc.c:347
IKE response formatting.
@ ERROR_UNKNOWN_TYPE
Definition: error.h:296
error_t ikeParseIkeSaInitRequest(IkeContext *context, const uint8_t *message, size_t length)
Parse incoming IKE_SA_INIT request.
#define TRACE_INFO(...)
Definition: debug.h:105
uint8_t length
Definition: tcp.h:375
IkeHeader
Definition: ike.h:1459
@ IKE_EXCHANGE_TYPE_CREATE_CHILD_SA
CREATE_CHILD_SA.
Definition: ike.h:856
IKEv2 (Internet Key Exchange Protocol)
@ IKE_EXCHANGE_TYPE_IKE_SA_INIT
IKE_SA_INIT.
Definition: ike.h:854
#define IkeSaEntry
Definition: ike.h:836
@ ERROR_INVALID_SPI
Definition: error.h:298
@ IKE_NOTIFY_MSG_TYPE_NONE
Definition: ike.h:1182
error_t ikeParseIkeSaInitResponse(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse incoming IKE_SA_INIT response.
@ IKE_SA_STATE_REKEY_CHILD_RESP
Definition: ike.h:1370
IkeSaEntry * ikeFindSaEntry(IkeContext *context, const IkeHeader *ikeHeader)
Find an IKE SA that matches an incoming IKE message.
Definition: ike_misc.c:232
error_t ikeParseCreateChildSaRequest(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse incoming CREATE_CHILD_SA request.
error_t ikeParseIkeAuthResponse(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse incoming IKE_AUTH response.
@ IKE_SA_STATE_DELETE_RESP
Definition: ike.h:1366
@ IKE_NOTIFY_MSG_TYPE_AUTH_FAILED
Definition: ike.h:1191
@ IKE_SA_STATE_AUTH_RESP
Definition: ike.h:1359
@ IKE_EXCHANGE_TYPE_INFORMATIONAL
INFORMATIONAL.
Definition: ike.h:857
@ IKE_SA_STATE_INIT_RESP
Definition: ike.h:1357
@ ERROR_WRONG_IDENTIFIER
Definition: error.h:89
@ IKE_FLAGS_R
Response flag.
Definition: ike.h:874
@ IKE_SA_STATE_REKEY_RESP
Definition: ike.h:1364
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
@ IKE_SA_STATE_DPD_RESP
Definition: ike.h:1362
#define PRIuSIZE
#define IKE_NAT_KEEPALIVE_PACKET_SIZE
Definition: ike.h:821
void ikeDumpMessage(const uint8_t *message, size_t length)
Dump IKE message.
Definition: ike_debug.c:425
#define ntohl(value)
Definition: cpu_endian.h:422
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
IKE message decryption.
@ IKE_NOTIFY_MSG_TYPE_INVALID_SYNTAX
Definition: ike.h:1186