ike_payload_parse.c
Go to the documentation of this file.
1 /**
2  * @file ike_payload_parse.c
3  * @brief IKE payload 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 "ike/ike.h"
36 #include "ike/ike_algorithms.h"
37 #include "ike/ike_payload_parse.h"
38 #include "ike/ike_auth.h"
39 #include "ike/ike_certificate.h"
40 #include "ike/ike_key_exchange.h"
41 #include "ike/ike_key_material.h"
42 #include "ike/ike_sign_misc.h"
43 #include "ike/ike_misc.h"
44 #include "ah/ah_algorithms.h"
45 #include "pkix/pem_import.h"
46 #include "debug.h"
47 
48 //Check IKEv2 library configuration
49 #if (IKE_SUPPORT == ENABLED)
50 
51 
52 /**
53  * @brief Parse IKE message payloads
54  * @param[in] message Pointer to the IKE message
55  * @param[in] length Length of the IKE message, in bytes
56  * @param[out] payloads IKE message payloads
57  **/
58 
59 void ikeParseIkeMessagePayloads(const uint8_t *message, size_t length,
60  IkeMessagePayloads *payloads)
61 {
62  //The Security Association payload, denoted SA, is used to negotiate
63  //attributes of a Security Association (refer to RFC 7296, section 3.3)
64  payloads->sa = (IkeSaPayload *) ikeGetPayload(message, length,
66 
67  //The Key Exchange payload, denoted KE, is used to exchange Diffie-Hellman
68  //public numbers as part of a Diffie-Hellman key exchange (refer to RFC 7296,
69  //section 3.4)
70  payloads->ke = (IkeKePayload *) ikeGetPayload(message, length,
72 
73  //The Identification payloads, denoted IDi and IDr, allow peers to assert an
74  //identity to one another (refer to RFC 7296, section 3.5)
75  payloads->idi = (IkeIdPayload *) ikeGetPayload(message, length,
77 
78  payloads->idr = (IkeIdPayload *) ikeGetPayload(message, length,
80 
81  //The Certificate payload, denoted CERT, provides a means to transport
82  //certificates or other authentication-related information via IKE (refer
83  //to RFC 7296, section 3.6)
86 
87  //The Certificate Request payload, denoted CERTREQ, provides a means to
88  //request preferred certificates via IKE (refer to RFC 7296, section 3.7)
91 
92  //The Authentication payload, denoted AUTH, contains data used for
93  //authentication purposes (refer to RFC 7296, section 3.8)
96 
97  //The Nonce payload, denoted as Ni and Nr, contains random data used to
98  //guarantee liveness during an exchange and protect against replay attacks
99  //(Refer to RFC 7296, section 3.9)
102 
103  //The Traffic Selector payload, denoted TSi and TSr, allows peers to identify
104  //packet flows for processing by IPsec security services (refer to RFC 7296,
105  //section 3.13
106  payloads->tsi = (IkeTsPayload *) ikeGetPayload(message, length,
108 
109  payloads->tsr = (IkeTsPayload *) ikeGetPayload(message, length,
111 
112  //The USE_TRANSPORT_MODE notification may be included in a request
113  //message that also includes an SA payload requesting a Child SA
116 
117  //The REKEY_SA notification is included in a CREATE_CHILD_SA exchange if the
118  //purpose of the exchange is to replace an existing ESP or AH SA
121 
122 #if (IKE_COOKIE_SUPPORT == ENABLED)
123  //Check whether the message includes a COOKIE notification
126 #endif
127 
128 #if (IKE_INITIAL_CONTACT_SUPPORT == ENABLED)
129  //The INITIAL_CONTACT notification asserts that this IKE SA is the only IKE
130  //SA currently active between the authenticated identities
133 #endif
134 
135 #if (IKE_SIGN_HASH_ALGOS_SUPPORT == ENABLED)
136  //The supported hash algorithms that can be used for the signature algorithms
137  //are indicated with a Notify payload of type SIGNATURE_HASH_ALGORITHMS sent
138  //inside the IKE_SA_INIT exchange (refer to RFC 7427, section 4)
141 #endif
142 
143 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
144  //The NAT_DETECTION_SOURCE_IP and NAT_DETECTION_DESTINATION_IP payloads can
145  //be used to detect if there is NAT between the hosts, and which end is
146  //behind the NAT (refer to RFC 7296, section 2.23)
149 
152 #endif
153 
154  //Check whether the message includes an error notification
156 }
157 
158 
159 /**
160  * @brief Parse Security Association payload
161  * @param[in] saPayload Pointer to the Security Association payload
162  * @return Error code
163  **/
164 
166 {
167  error_t error;
168  size_t n;
169  size_t length;
170  const uint8_t *p;
171  const IkeProposal *proposal;
172 
173  //Retrieve the length of the Security Association payload
174  length = ntohs(saPayload->header.payloadLength);
175 
176  //Malformed Security Association payload?
177  if(length < sizeof(IkeSaPayload))
178  return ERROR_INVALID_SYNTAX;
179 
180  //Point to the first byte of the Proposals field
181  p = saPayload->proposals;
182  //Determine the length of the Proposals field
183  length -= sizeof(IkeSaPayload);
184 
185  //The SA payload must contain at least one Proposal substructure
186  if(length == 0)
187  return ERROR_INVALID_SYNTAX;
188 
189  //Loop through the Proposal substructures
190  while(length > 0)
191  {
192  //Malformed payload?
193  if(length < sizeof(IkeProposal))
194  {
195  //Report an error
196  error = ERROR_INVALID_SYNTAX;
197  break;
198  }
199 
200  //Point to the Proposal substructure
201  proposal = (IkeProposal *) p;
202 
203  //The Proposal Length field indicates the length of this proposal,
204  //including all transforms and attributes that follow
205  n = ntohs(proposal->proposalLength);
206 
207  //Check the length of the proposal
208  if(n < sizeof(IkeProposal) || n > length)
209  {
210  //Report an error
211  error = ERROR_INVALID_SYNTAX;
212  break;
213  }
214 
215  //Parse Proposal substructure
216  error = ikeParseProposal(proposal, n);
217  //Any error to report?
218  if(error)
219  break;
220 
221  //Jump to the next proposal
222  p += n;
223  length -= n;
224  }
225 
226  //Return status code
227  return error;
228 }
229 
230 
231 /**
232  * @brief Parse Proposal substructure
233  * @param[in] proposal Pointer to the Proposal substructure
234  * @param[in] length Length of the Proposal substructure, in bytes
235  * @return Error code
236  **/
237 
238 error_t ikeParseProposal(const IkeProposal *proposal, size_t length)
239 {
240  error_t error;
241  uint_t i;
242  size_t n;
243  const uint8_t *p;
244  const IkeTransform *transform;
245 
246  //Check the length of the Proposal substructure
247  if(length < sizeof(IkeProposal))
248  return ERROR_INVALID_SYNTAX;
249 
250  //Malformed substructure?
251  if(length < (sizeof(IkeProposal) + proposal->spiSize))
252  return ERROR_INVALID_SYNTAX;
253 
254  //Get the length of the Proposal substructure
255  length = length - sizeof(IkeProposal) - proposal->spiSize;
256  //Point to the first Transform substructure
257  p = (uint8_t *) proposal + sizeof(IkeProposal) + proposal->spiSize;
258 
259  //The Transforms field must contains at least one Transform substructure
260  if(proposal->numTransforms == 0)
261  return ERROR_INVALID_SYNTAX;
262 
263  //Loop through the Transform substructures
264  for(i = 1; i <= proposal->numTransforms; i++)
265  {
266  //Malformed substructure?
267  if(length < sizeof(IkeTransform))
268  {
269  //Report an error
270  error = ERROR_INVALID_SYNTAX;
271  break;
272  }
273 
274  //Point to the Transform substructure
275  transform = (IkeTransform *) p;
276 
277  //The Transform Length field indicates the length of the Transform
278  //substructure including header and attributes
279  n = ntohs(transform->transformLength);
280 
281  //Check the length of the transform
282  if(n < sizeof(IkeTransform) || n > length)
283  {
284  //Report an error
285  error = ERROR_INVALID_SYNTAX;
286  break;
287  }
288 
289  //Parse Transform substructure
290  error = ikeParseTransform(transform, n);
291  //Any error to report?
292  if(error)
293  break;
294 
295  //Jump to the next transform
296  p += n;
297  length -= n;
298  }
299 
300  //Return status code
301  return error;
302 }
303 
304 
305 /**
306  * @brief Parse Transform substructure
307  * @param[in] transform Pointer to the Transform substructure
308  * @param[in] length Length of the Transform substructure, in bytes
309  * @return Error code
310  **/
311 
312 error_t ikeParseTransform(const IkeTransform *transform, size_t length)
313 {
314  error_t error;
315  size_t n;
316  const uint8_t *p;
317  const IkeTransformAttr *attr;
318 
319  //Check the length of the Transform substructure
320  if(length < sizeof(IkeTransform))
321  return ERROR_INVALID_SYNTAX;
322 
323  //Point to the first byte of the Transform Attributes field
324  p = transform->transformAttr;
325  //Get the length of the Transform Attributes field
326  length -= sizeof(IkeTransform);
327 
328  //The Transform Attributes field is optional
329  if(length > 0)
330  {
331  //The Transform Attributes field contains one or more attributes
332  while(length > 0)
333  {
334  //Malformed attribute?
335  if(length < sizeof(IkeTransformAttr))
336  {
337  //Report an error
338  error = ERROR_INVALID_SYNTAX;
339  break;
340  }
341 
342  //Point to the transform attribute
343  attr = (IkeTransformAttr *) p;
344 
345  //Parse transform attribute
346  error = ikeParseTransformAttr(attr, length, &n);
347  //Any error to report?
348  if(error)
349  break;
350 
351  //Jump to the next attribute
352  p += n;
353  length -= n;
354  }
355  }
356  else
357  {
358  //The Transform Attributes field is not present
359  error = NO_ERROR;
360  }
361 
362  //Return status code
363  return error;
364 }
365 
366 
367 /**
368  * @brief Parse transform attribute
369  * @param[in] attr Pointer to the transform attribute
370  * @param[in] length Number of bytes available in the input stream
371  * @param[out] consumed Total number of characters that have been consumed
372  * @return Error code
373  **/
374 
376  size_t *consumed)
377 {
378  size_t n;
379 
380  //Malformed attribute?
381  if(length < sizeof(IkeTransformAttr))
382  return ERROR_INVALID_SYNTAX;
383 
384  //Check the format of the attribute
385  if((ntohs(attr->type) & IKE_ATTR_FORMAT_TV) != 0)
386  {
387  //If the AF bit is set, then the attribute value has a fixed length
388  n = 0;
389  }
390  else
391  {
392  //If the AF bit is not set, then this attribute has a variable length
393  //defined by the Attribute Length field
394  n = ntohs(attr->length);
395 
396  //Malformed attribute?
397  if(length < (sizeof(IkeTransformAttr) + n))
398  return ERROR_INVALID_SYNTAX;
399  }
400 
401  //Total number of bytes that have been consumed
402  *consumed = sizeof(IkeTransformAttr) + n;
403 
404  //Parsing was successful
405  return NO_ERROR;
406 }
407 
408 
409 /**
410  * @brief Parse Key Exchange payload
411  * @param[in] keContext Pointer to the key exchange context
412  * @param[in] kePayload Pointer to the Key Exchange payload
413  * @return Error code
414  **/
415 
417  const IkeKePayload *kePayload)
418 {
419  error_t error;
420  size_t n;
421  uint16_t groupNum;
422 
423  //Retrieve the length of the Key Exchange payload
424  n = ntohs(kePayload->header.payloadLength);
425 
426  //Malformed Key Exchange payload?
427  if(n < sizeof(IkeKePayload))
428  return ERROR_INVALID_SYNTAX;
429 
430  //Determine the length of the key exchange data
431  n -= sizeof(IkeKePayload);
432 
433  //The Key Exchange Method identifies the Diffie-Hellman group in which the
434  //Key Exchange Data was computed
435  groupNum = ntohs(kePayload->keyExchangeMethod);
436 
437  //Make sure the key exchange method is acceptable
438  if(groupNum != keContext->groupNum)
439  return ERROR_INVALID_GROUP;
440 
441  //Parse peer's Diffie-Hellman public key
442  error = ikeParsePublicKey(keContext, kePayload->keyExchangeData, n);
443 
444  //Return status code
445  return error;
446 }
447 
448 
449 /**
450  * @brief Parse Identification payload
451  * @param[in] sa Pointer to the IKE SA
452  * @param[in] idPayload Pointer to the Identification payload
453  * @return Error code
454  **/
455 
457 {
458  size_t n;
459 
460  //Retrieve the length of the Identification payload
461  n = ntohs(idPayload->header.payloadLength);
462 
463  //Malformed Identification payload?
464  if(n < sizeof(IkeIdPayload))
465  return ERROR_INVALID_SYNTAX;
466 
467  //Determine the length of the identification data
468  n -= sizeof(IkeIdPayload);
469 
470  //Check the length of the identification data
471  if(n == 0 || n > IKE_MAX_ID_LEN)
472  return ERROR_INVALID_LENGTH;
473 
474  //Save identification data
475  sa->peerIdType = (IkeIdType) idPayload->idType;
476  osMemcpy(sa->peerId, idPayload->idData, n);
477  sa->peerIdLen = n;
478 
479  //Successful processing
480  return NO_ERROR;
481 }
482 
483 
484 /**
485  * @brief Parse Certificate Request payload
486  * @param[in] sa Pointer to the IKE SA
487  * @param[in] certReqPayload Pointer to the Certificate Request payload
488  * @return Error code
489  **/
490 
492  const IkeCertReqPayload *certReqPayload)
493 {
494 #if (IKE_CERT_AUTH_SUPPORT == ENABLED)
495  size_t n;
496 
497  //Retrieve the length of the Identification payload
498  n = ntohs(certReqPayload->header.payloadLength);
499 
500  //Malformed Identification payload?
501  if(n < sizeof(IkeCertReqPayload))
502  return ERROR_INVALID_SYNTAX;
503 
504  //Determine the length of the Certification Authority field
505  n -= sizeof(IkeCertReqPayload);
506 
507  //Check the length of the Certification Authority field
508  if((n % IKE_SHA1_DIGEST_SIZE) != 0)
509  return ERROR_INVALID_LENGTH;
510 #endif
511 
512  //Successful processing
513  return NO_ERROR;
514 }
515 
516 
517 /**
518  * @brief Parse Nonce payload
519  * @param[in] noncePayload Pointer to the Nonce payload
520  * @param[out] nonce Pointer to the buffer where to store the nonce
521  * @param[out] nonceLen Length of the nonce, in bytes
522  * @return Error code
523  **/
524 
526  uint8_t *nonce, size_t *nonceLen)
527 {
528  size_t n;
529 
530  //Retrieve the length of the Nonce payload
531  n = ntohs(noncePayload->header.payloadLength);
532 
533  //Malformed payload?
534  if(n < sizeof(IkeNoncePayload))
535  return ERROR_INVALID_SYNTAX;
536 
537  //Determine the length of the nonce
538  n -= sizeof(IkeNoncePayload);
539 
540  //Nonces used in IKEv2 must be at least 128 bits in size (refer to RFC 7296,
541  //section 2.10)
542  if(n < IKE_MIN_NONCE_SIZE || n > IKE_MAX_NONCE_SIZE)
543  return ERROR_INVALID_LENGTH;
544 
545  //Save the nonce
546  osMemcpy(nonce, noncePayload->nonceData, n);
547  *nonceLen = n;
548 
549  //Successful processing
550  return NO_ERROR;
551 }
552 
553 
554 /**
555  * @brief Parse INVALID_KE_PAYLOAD notification
556  * @param[in] keContext Pointer to the key exchange context
557  * @param[in] notifyPayload Pointer to the Notify payload
558  * @return Error code
559  **/
560 
562  const IkeNotifyPayload *notifyPayload)
563 {
564  size_t n;
565  uint16_t groupNum;
566  const uint8_t *data;
567 
568  //Retrieve the length of the notification data
569  n = ntohs(notifyPayload->header.payloadLength) - sizeof(IkeNotifyPayload) -
570  notifyPayload->spiSize;
571 
572  //There are two octets of data associated with this notification
573  if(n != sizeof(uint16_t))
574  return ERROR_INVALID_SYNTAX;
575 
576  //Point to the notification data
577  data = notifyPayload->spi + notifyPayload->spiSize;
578 
579  //The Diffie-Hellman group number is encoded in big endian order (refer to
580  //RFC 7296, section 1.3)
581  groupNum = LOAD16BE(data);
582 
583  //Ensure the specified key exchange method is supported
584  if(!ikeIsGroupSupported(groupNum))
585  return ERROR_INVALID_GROUP;
586 
587  //Save the corrected group number
588  keContext->groupNum = groupNum;
589 
590  //Successful processing
591  return NO_ERROR;
592 }
593 
594 
595 /**
596  * @brief Parse COOKIE notification
597  * @param[in] sa Pointer to the IKE SA
598  * @param[in] notifyPayload Pointer to the Notify payload
599  * @return Error code
600  **/
601 
603  const IkeNotifyPayload *notifyPayload)
604 {
605  size_t n;
606  const uint8_t *data;
607 
608  //Retrieve the length of the notification data
609  n = ntohs(notifyPayload->header.payloadLength) - sizeof(IkeNotifyPayload) -
610  notifyPayload->spiSize;
611 
612  //The data associated with this notification must be between 1 and 64
613  //octets in length (refer to RFC 7296, section 2.6)
614  if(n < IKE_MIN_COOKIE_SIZE || n > IKE_MAX_COOKIE_SIZE)
615  return ERROR_INVALID_SYNTAX;
616 
617  //Point to the notification data
618  data = notifyPayload->spi + notifyPayload->spiSize;
619 
620  //Save cookie
621  osMemcpy(sa->cookie, data, n);
622  sa->cookieLen = n;
623 
624  //Successful processing
625  return NO_ERROR;
626 }
627 
628 
629 /**
630  * @brief Parse SIGNATURE_HASH_ALGORITHMS notification
631  * @param[in] sa Pointer to the IKE SA
632  * @param[in] notifyPayload Pointer to the Notify payload
633  * @return Error code
634  **/
635 
637  const IkeNotifyPayload *notifyPayload)
638 {
639 #if (IKE_SIGN_HASH_ALGOS_SUPPORT == ENABLED)
640  size_t i;
641  size_t n;
642  uint16_t hashAlgoId;
643  const uint8_t *data;
644 
645  //Retrieve the length of the notification data
646  n = ntohs(notifyPayload->header.payloadLength) - sizeof(IkeNotifyPayload) -
647  notifyPayload->spiSize;
648 
649  //Malformed notification?
650  if((n % sizeof(uint16_t)) != 0)
651  return ERROR_INVALID_SYNTAX;
652 
653  //Point to the notification data
654  data = notifyPayload->spi + notifyPayload->spiSize;
655 
656  //Clear the list of hash algorithms supported by the peer
657  sa->signHashAlgos = 0;
658 
659  //The Notification Data field contains the list of 16-bit hash algorithm
660  //identifiers
661  for(i = 0; i < n; i += sizeof(uint16_t))
662  {
663  //Get the current 16-bit hash algorithm identifier
664  hashAlgoId = LOAD16BE(data + i);
665 
666  //Check whether the hash algorithm is supported
667  if(ikeIsHashAlgoSupported(hashAlgoId))
668  {
669  sa->signHashAlgos |= (1U << hashAlgoId);
670  }
671  }
672 
673  //Successful processing
674  return NO_ERROR;
675 #else
676  //The SIGNATURE_HASH_ALGORITHMS notification is not supported
677  return ERROR_NOT_IMPLEMENTED;
678 #endif
679 }
680 
681 
682 /**
683  * @brief Parse NAT_DETECTION_SOURCE_IP notification
684  * @param[in] sa Pointer to the IKE SA
685  * @param[in] message Pointer to the received IKE message
686  * @param[in] length Length of the IKE message, in bytes
687  * @return Error code
688  **/
689 
691  const uint8_t *message, size_t length)
692 {
693 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
694  uint_t i;
695  size_t n;
696  bool_t match;
697  const uint8_t *data;
698  IkeContext *context;
699  const IkeNotifyPayload *notifyPayload;
700  Sha1Context sha1Context;
701  uint8_t temp[SHA1_DIGEST_SIZE];
702 
703  //Point to the IKE context
704  context = sa->context;
705 
706  //Initialize variable
707  match = FALSE;
708 
709  //There MAY be multiple NAT_DETECTION_SOURCE_IP payloads in a message if the
710  //sender does not know which of several network attachments will be used to
711  //send the packet (refer to RFC 7296, section 2.23)
712  for(i = 0; ; i++)
713  {
714  //Point to the NAT_DETECTION_SOURCE_IP notification
715  notifyPayload = ikeGetStatusNotifyPayload(message, length,
717 
718  //NAT_DETECTION_SOURCE_IP notification not found?
719  if(notifyPayload == NULL)
720  break;
721 
722  //Retrieve the length of the notification data
723  n = ntohs(notifyPayload->header.payloadLength) -
724  sizeof(IkeNotifyPayload) - notifyPayload->spiSize;
725 
726  //Malformed notification?
727  if(n != SHA1_DIGEST_SIZE)
728  return ERROR_INVALID_SYNTAX;
729 
730  //The data associated with the NAT_DETECTION_SOURCE_IP notification is a
731  //SHA-1 digest of the SPIs (in the order they appear in the header), IP
732  //address, and port from which this packet was sent
733  data = notifyPayload->spi + notifyPayload->spiSize;
734 
735  //Retrieve the length of the source IP address
736  n = context->remoteIpAddr.length;
737  //Convert the source port number to network byte order
738  STORE16BE(context->remotePort, temp);
739 
740  //Compute the SHA-1 hash of the SPIs, source IP address, and port
741  sha1Init(&sha1Context);
742  sha1Update(&sha1Context, sa->initiatorSpi, IKE_SPI_SIZE);
743  sha1Update(&sha1Context, sa->responderSpi, IKE_SPI_SIZE);
744  sha1Update(&sha1Context, context->remoteIpAddr.addr, n);
745  sha1Update(&sha1Context, temp, sizeof(uint16_t));
746  sha1Final(&sha1Context, temp);
747 
748  //Compares the supplied value to the calculated SHA-1 hash
749  if(osMemcmp(data, temp, SHA1_DIGEST_SIZE) == 0)
750  {
751  match = TRUE;
752  }
753  }
754 
755  //If none of the NAT_DETECTION_SOURCE_IP payload(s) received matches the
756  //expected value of the source IP and port found from the IP header of the
757  //packet containing the payload, it means that the system sending those
758  //payloads is behind a NAT
759  if(!match)
760  {
761  //A NAT has been detected in front of the remote security endpoint
762  sa->remoteNat = TRUE;
763  }
764 
765  //The IKE_SA_INIT message contains a NAT_DETECTION_SOURCE_IP notification
766  sa->natDetectSrcIp = TRUE;
767 
768  //Sucessful processing
769  return NO_ERROR;
770 #else
771  //Minimal implementations are not required to support NAT traversal
772  return ERROR_NOT_IMPLEMENTED;
773 #endif
774 }
775 
776 
777 /**
778  * @brief Parse NAT_DETECTION_DESTINATION_IP notification
779  * @param[in] sa Pointer to the IKE SA
780  * @param[in] notifyPayload Pointer to the Notify payload
781  * @return Error code
782  **/
783 
785  const IkeNotifyPayload *notifyPayload)
786 {
787 #if (IKE_NAT_TRAVERSAL_SUPPORT == ENABLED)
788  size_t n;
789  const uint8_t *data;
790  IkeContext *context;
791  Sha1Context sha1Context;
792  uint8_t temp[SHA1_DIGEST_SIZE];
793 
794  //Point to the IKE context
795  context = sa->context;
796 
797  //Retrieve the length of the notification data
798  n = ntohs(notifyPayload->header.payloadLength) - sizeof(IkeNotifyPayload) -
799  notifyPayload->spiSize;
800 
801  //Malformed notification?
802  if(n != SHA1_DIGEST_SIZE)
803  return ERROR_INVALID_SYNTAX;
804 
805  //The data associated with the NAT_DETECTION_DESTINATION_IP notification is
806  //a SHA-1 digest of the SPIs (in the order they appear in the header), IP
807  //address, and port to which this packet was sent
808  data = notifyPayload->spi + notifyPayload->spiSize;
809 
810  //Retrieve the length of the recipient IP address
811  n = context->localIpAddr.length;
812  //Convert the recipient port number to network byte order
813  STORE16BE(context->localPort, temp);
814 
815  //Compute the SHA-1 hash of the SPIs, recipient IP address, and port
816  sha1Init(&sha1Context);
817  sha1Update(&sha1Context, sa->initiatorSpi, IKE_SPI_SIZE);
818  sha1Update(&sha1Context, sa->responderSpi, IKE_SPI_SIZE);
819  sha1Update(&sha1Context, context->localIpAddr.addr, n);
820  sha1Update(&sha1Context, temp, sizeof(uint16_t));
821  sha1Final(&sha1Context, temp);
822 
823  //In the case of a mismatching NAT_DETECTION_DESTINATION_IP hash, it means
824  //that the system receiving the NAT_DETECTION_DESTINATION_IP payload is
825  //behind a NAT
826  if(osMemcmp(data, temp, SHA1_DIGEST_SIZE) != 0)
827  {
828  //A NAT has been detected in front of the local security endpoint
829  sa->localNat = TRUE;
830 
831  //The system should start sending keepalive packets (refer to RFC 7296,
832  //section 2.23)
833  sa->natKeepAliveTimestamp = osGetSystemTime();
834  }
835 
836  //The IKE_SA_INIT message contains a NAT_DETECTION_DESTINATION_IP notification
837  sa->natDetectDestIp = TRUE;
838 
839  //Sucessful processing
840  return NO_ERROR;
841 #else
842  //Minimal implementations are not required to support NAT traversal
843  return ERROR_NOT_IMPLEMENTED;
844 #endif
845 }
846 
847 
848 /**
849  * @brief Parse Delete payload
850  * @param[in] sa Pointer to the IKE SA
851  * @param[in] deletePayload Pointer to the Delete payload
852  * @param[in] response TRUE if the received INFORMATIONAL message is a response
853  * @return Error code
854  **/
855 
857  const IkeDeletePayload *deletePayload, bool_t response)
858 {
859  uint_t i;
860  size_t n;
861  const uint8_t *spi;
862  IkeChildSaEntry *childSa;
863 
864  //Retrieve the length of the Delete payload
865  n = ntohs(deletePayload->header.payloadLength);
866 
867  //Malformed payload?
868  if(n < sizeof(IkeDeletePayload))
869  return ERROR_INVALID_SYNTAX;
870 
871  //Determine the length of the list
872  n -= sizeof(IkeDeletePayload);
873 
874  //Malformed SPI list?
875  if(n != (deletePayload->spiSize * ntohs(deletePayload->numSpi)))
876  return ERROR_INVALID_SYNTAX;
877 
878  //Check protocol identifier
879  if(deletePayload->protocolId == IKE_PROTOCOL_ID_IKE)
880  {
881  //The SPI Size field must be zero for IKE
882  if(deletePayload->spiSize != 0)
883  return ERROR_INVALID_SYNTAX;
884 
885  //If a peer receives a request to close an IKE SA that it is currently
886  //rekeying, it should reply as usual, and forget about its own rekeying
887  //request (refer to RFC 7296, section 2.25.2)
888 
889  //If a peer receives a request to close an IKE SA that it is currently
890  //trying to close, it should reply as usual, and forget about its own
891  //close request
892  if(!response)
893  {
894  sa->deleteReceived = TRUE;
895  }
896  }
897  else if(deletePayload->protocolId == IKE_PROTOCOL_ID_AH ||
898  deletePayload->protocolId == IKE_PROTOCOL_ID_ESP)
899  {
900  //The SPI Size field must be four for AH and ESP
901  if(deletePayload->spiSize != IPSEC_SPI_SIZE)
902  return ERROR_INVALID_SYNTAX;
903 
904  //The Delete payload list the SPIs to be deleted
905  for(i = 0; i < ntohs(deletePayload->numSpi); i++)
906  {
907  //Point to the current SPI
908  spi = deletePayload->spi + (i * deletePayload->spiSize);
909 
910  //Perform Child SA lookup
911  childSa = ikeFindChildSaEntry(sa, deletePayload->protocolId, spi);
912 
913  //Child SA found?
914  if(childSa != NULL)
915  {
916  //Check the state of the Child SA
917  if(childSa->state == IKE_CHILD_SA_STATE_REKEY)
918  {
919  //If a peer receives a request to close a Child SA that it is
920  //currently rekeying, it should reply as usual, with a Delete
921  //payload (refer to RFC 7296, section 2.25.1)
922  if(!response)
923  {
924  childSa->deleteReceived = TRUE;
925  }
926  }
927  else if(childSa->state == IKE_CHILD_SA_STATE_DELETE)
928  {
929  //If a peer receives a request to close a Child SA that it is
930  //currently trying to close, it should reply without a Delete
931  //payload
932  if(response)
933  {
934  ikeDeleteChildSaEntry(childSa);
935  }
936  }
937  else
938  {
939  //If a peer receives a request to delete a Child SA when it is
940  //currently rekeying the IKE SA, it should reply as usual, with
941  //a Delete payload (refer to RFC 7296, section 2.25.2)
942  if(!response)
943  {
944  childSa->deleteReceived = TRUE;
945  }
946  }
947  }
948  else
949  {
950  //If a peer receives a request to close a Child SA that does not
951  //exist, it should reply without a Delete payload (refer to
952  //RFC 7296, section 2.25.1)
953  }
954  }
955  }
956  else
957  {
958  //Unknown protocol identifier
959  }
960 
961  //Successful processing
962  return NO_ERROR;
963 }
964 
965 
966 /**
967  * @brief Parse Traffic Selector payload
968  * @param[in] tsPayload Pointer to the Traffic Selector payload
969  * @param[in] index Index of the Traffic Selector substructure to parse
970  * @param[out] tsEntry Traffic selector entry
971  * @return Error code
972  **/
973 
975  IkeTsEntry *tsEntry)
976 {
977  error_t error;
978  uint_t i;
979  size_t n;
980  size_t length;
981  const uint8_t *p;
982  const IkeTs *ts;
983 
984  //Get the length of the TS payload
985  length = ntohs(tsPayload->header.payloadLength);
986 
987  //Malformed TS payload?
988  if(length < sizeof(IkeTsPayload))
989  return ERROR_INVALID_SYNTAX;
990 
991  //The Traffic Selectors field must contains at least one Traffic Selector
992  //substructure (refer to RFC 7296, section 3.13)
993  if(tsPayload->numTs == 0)
994  return ERROR_INVALID_SYNTAX;
995 
996  //Invalid index?
997  if(index >= tsPayload->numTs)
998  return ERROR_NOT_FOUND;
999 
1000  //Point to the first byte of the Traffic Selectors field
1001  p = tsPayload->trafficSelectors;
1002  //Determine the length of the Traffic Selectors field
1003  length -= sizeof(IkeTsPayload);
1004 
1005  //Loop through the Traffic Selector substructures
1006  for(i = 0; i <= index; i++)
1007  {
1008  //Malformed substructure?
1009  if(length < sizeof(IkeTs))
1010  {
1011  //Report an error
1012  error = ERROR_INVALID_SYNTAX;
1013  break;
1014  }
1015 
1016  //Point to the Traffic Selector substructure
1017  ts = (IkeTs *) p;
1018 
1019  //The Selector Length field indicates the length of the Traffic Selector
1020  //substructure including the header (refer to RFC 7296, section 3.13.1)
1021  n = ntohs(ts->selectorLength);
1022 
1023  //Check the length of the selector
1024  if(n < sizeof(IkeTs) || n > length)
1025  {
1026  //Report an error
1027  error = ERROR_INVALID_SYNTAX;
1028  break;
1029  }
1030 
1031  //Parse Traffic Selector substructure
1032  error = ikeParseTsEntry(ts, n, tsEntry);
1033  //Any error to report?
1034  if(error)
1035  break;
1036 
1037  //Jump to the next substructure
1038  p += n;
1039  length -= n;
1040  }
1041 
1042  //Return status code
1043  return error;
1044 }
1045 
1046 
1047 /**
1048  * @brief Parse Traffic Selector substructure
1049  * @param[in] ts Pointer to the Traffic Selector substructure
1050  * @param[in] length Length of the Traffic Selector substructure, in bytes
1051  * @param[out] tsEntry Traffic selector entry
1052  * @return Error code
1053  **/
1054 
1055 error_t ikeParseTsEntry(const IkeTs *ts, size_t length, IkeTsEntry *tsEntry)
1056 {
1057  error_t error;
1058  size_t n;
1059 
1060  //Malformed substructure?
1061  if(length < sizeof(IkeTs))
1062  return ERROR_INVALID_SYNTAX;
1063 
1064  //Initialize status code
1065  error = NO_ERROR;
1066 
1067  //The IP protocol ID value specifies the IP protocol ID (such as UDP, TCP,
1068  //and ICMP). A value of zero means that the protocol ID is not relevant to
1069  //this Traffic Selector
1070  tsEntry->ipProtocolId = ts->ipProtocolId;
1071 
1072  //The Start Port value specifies the smallest port number allowed by this
1073  //Traffic Selector
1074  tsEntry->startPort = ntohs(ts->startPort);
1075 
1076  //The End Port value specifies the smallest port number allowed by this
1077  //Traffic Selector
1078  tsEntry->endPort = ntohs(ts->endPort);
1079 
1080  //The length of the Starting Address and Ending Address fields depends on
1081  //the TS Type field
1082  length -= sizeof(IkeTs);
1083 
1084 #if (IPV4_SUPPORT == ENABLED)
1085  //IPv4 address range?
1086  if(ts->tsType == IKE_TS_TYPE_IPV4_ADDR_RANGE)
1087  {
1088  //A range of IPv4 addresses is represented by two four-octet values
1089  n = sizeof(Ipv4Addr);
1090 
1091  //Valid length?
1092  if(length == (2 * n))
1093  {
1094  //The Starting Address field specifies the smallest address included
1095  //in this Traffic Selector
1096  tsEntry->startAddr.length = n;
1097  ipv4CopyAddr(&tsEntry->startAddr.ipv4Addr, ts->startAddr);
1098 
1099  //The Ending Address field specifies the smallest address included in
1100  //this Traffic Selector
1101  tsEntry->endAddr.length = n;
1102  ipv4CopyAddr(&tsEntry->endAddr.ipv4Addr, ts->startAddr + n);
1103  }
1104  else
1105  {
1106  //Report an error
1107  error = ERROR_INVALID_ADDRESS;
1108  }
1109  }
1110  else
1111 #endif
1112 #if (IPV6_SUPPORT == ENABLED)
1113  //IPv6 address range?
1114  if(ts->tsType == IKE_TS_TYPE_IPV6_ADDR_RANGE)
1115  {
1116  //A range of IPv6 addresses is represented by two sixteen-octet values
1117  n = sizeof(Ipv6Addr);
1118 
1119  //Valid length?
1120  if(length == (2 * n))
1121  {
1122  //The Starting Address field specifies the smallest address included
1123  //in this Traffic Selector
1124  tsEntry->startAddr.length = n;
1125  ipv6CopyAddr(&tsEntry->startAddr.ipv6Addr, ts->startAddr);
1126 
1127  //The Ending Address field specifies the smallest address included in
1128  //this Traffic Selector
1129  tsEntry->endAddr.length = n;
1130  ipv6CopyAddr(&tsEntry->endAddr.ipv6Addr, ts->startAddr + n);
1131  }
1132  else
1133  {
1134  //Report an error
1135  error = ERROR_INVALID_ADDRESS;
1136  }
1137  }
1138  else
1139 #endif
1140  //Unknown Traffic Selector type?
1141  {
1142  //Report an error
1143  error = ERROR_INVALID_ADDRESS;
1144  }
1145 
1146  //Return status code
1147  return error;
1148 }
1149 
1150 
1151 /**
1152  * @brief Search an IKE message for a given payload type
1153  * @param[in] message Pointer to the IKE message
1154  * @param[in] length Length of the IKE message, in bytes
1155  * @param[in] type Payload type
1156  * @param[in] index Payload occurrence index
1157  * @return If the specified payload type is found, a pointer to the payload
1158  * header is returned. Otherwise NULL pointer is returned
1159  **/
1160 
1161 const IkePayloadHeader *ikeGetPayload(const uint8_t *message, size_t length,
1162  uint8_t type, uint_t index)
1163 {
1164  uint_t i;
1165  size_t n;
1166  uint8_t nextPayload;
1167  const uint8_t *p;
1168  const IkeHeader *ikeHeader;
1169  const IkePayloadHeader *payload;
1170 
1171  //Point to the IKE header
1172  ikeHeader = (IkeHeader *) message;
1173 
1174  //The Next Payload field indicates the type of payload that immediately
1175  //follows the header
1176  nextPayload = ikeHeader->nextPayload;
1177 
1178  //Initialize occurrence index
1179  i = 0;
1180 
1181  //Point to the IKE payloads
1182  p = message + sizeof(IkeHeader);
1183  //Get the length of the IKE payloads, in bytes
1184  length -= sizeof(IkeHeader);
1185 
1186  //Following the header are one or more IKE payloads each identified by
1187  //a Next Payload field in the preceding payload
1189  length >= sizeof(IkePayloadHeader))
1190  {
1191  //Each IKE payload begins with a generic payload header
1192  payload = (IkePayloadHeader *) p;
1193 
1194  //The Payload Length field indicates the length in octets of the current
1195  //payload, including the generic payload header
1196  n = ntohs(payload->payloadLength);
1197 
1198  //Check the length of the IKE payload
1199  if(n < sizeof(IkePayloadHeader) || n > length)
1200  return NULL;
1201 
1202  //Check IKE payload type
1203  if(nextPayload == type)
1204  {
1205  //Matching occurrence found?
1206  if(i++ == index)
1207  {
1208  return payload;
1209  }
1210  }
1211 
1212  //The Next Payload field indicates the payload type of the next payload
1213  //in the message
1214  nextPayload = payload->nextPayload;
1215 
1216  //Jump to the next IKE payload
1217  p += n;
1218  length -= n;
1219  }
1220 
1221  //The specified payload type was not found
1222  return NULL;
1223 }
1224 
1225 
1226 /**
1227  * @brief Search an IKE message for an error Notify payload
1228  * @param[in] message Pointer to the received IKE message
1229  * @param[in] length Length of the IKE message, in bytes
1230  * @return Pointer to the error Notify payload, if any
1231  **/
1232 
1234  size_t length)
1235 {
1236  size_t n;
1237  uint8_t nextPayload;
1238  const uint8_t *p;
1239  const IkeHeader *ikeHeader;
1240  const IkePayloadHeader *payload;
1241  const IkeNotifyPayload *notifyPayload;
1242 
1243  //Point to the IKE header
1244  ikeHeader = (IkeHeader *) message;
1245 
1246  //The Next Payload field indicates the type of payload that immediately
1247  //follows the header
1248  nextPayload = ikeHeader->nextPayload;
1249 
1250  //Point to the IKE payloads
1251  p = message + sizeof(IkeHeader);
1252  //Get the length of the IKE payloads, in bytes
1253  length -= sizeof(IkeHeader);
1254 
1255  //Following the header are one or more IKE payloads each identified by
1256  //a Next Payload field in the preceding payload
1258  length >= sizeof(IkePayloadHeader))
1259  {
1260  //Each IKE payload begins with a generic payload header
1261  payload = (IkePayloadHeader *) p;
1262 
1263  //The Payload Length field indicates the length in octets of the current
1264  //payload, including the generic payload header
1265  n = ntohs(payload->payloadLength);
1266 
1267  //Check the length of the IKE payload
1268  if(n < sizeof(IkePayloadHeader) || n > length)
1269  return NULL;
1270 
1271  //Notify payload?
1273  {
1274  //Point to the Notify payload
1275  notifyPayload = (IkeNotifyPayload *) p;
1276 
1277  //Malformed Notify payload?
1278  if(n < sizeof(IkeNotifyPayload))
1279  return NULL;
1280 
1281  //Check the length of the SPI
1282  if(n < (sizeof(IkeNotifyPayload) + notifyPayload->spiSize))
1283  return NULL;
1284 
1285  //Types in the range 0-16383 are intended for reporting errors (refer
1286  //to RFC 7296, section 3.10.1)
1287  if(ntohs(notifyPayload->notifyMsgType) < 16384)
1288  {
1289  return notifyPayload;
1290  }
1291  }
1292 
1293  //The Next Payload field indicates the payload type of the next payload
1294  //in the message
1295  nextPayload = payload->nextPayload;
1296 
1297  //Jump to the next IKE payload
1298  p += n;
1299  length -= n;
1300  }
1301 
1302  //The specified payload type was not found
1303  return NULL;
1304 }
1305 
1306 
1307 /**
1308  * @brief Search an IKE message for a given status Notify payload
1309  * @param[in] message Pointer to the received IKE message
1310  * @param[in] length Length of the IKE message, in bytes
1311  * @param[in] type Notify message type
1312  * @param[in] index Notification occurrence index
1313  * @return Pointer to the error Notify payload, if any
1314  **/
1315 
1317  size_t length, uint16_t type, uint_t index)
1318 {
1319  uint_t i;
1320  size_t n;
1321  uint8_t nextPayload;
1322  const uint8_t *p;
1323  const IkeHeader *ikeHeader;
1324  const IkePayloadHeader *payload;
1325  const IkeNotifyPayload *notifyPayload;
1326 
1327  //Point to the IKE header
1328  ikeHeader = (IkeHeader *) message;
1329 
1330  //The Next Payload field indicates the type of payload that immediately
1331  //follows the header
1332  nextPayload = ikeHeader->nextPayload;
1333 
1334  //Initialize occurrence index
1335  i = 0;
1336 
1337  //Point to the IKE payloads
1338  p = message + sizeof(IkeHeader);
1339  //Get the length of the IKE payloads, in bytes
1340  length -= sizeof(IkeHeader);
1341 
1342  //Following the header are one or more IKE payloads each identified by
1343  //a Next Payload field in the preceding payload
1345  length >= sizeof(IkePayloadHeader))
1346  {
1347  //Each IKE payload begins with a generic payload header
1348  payload = (IkePayloadHeader *) p;
1349 
1350  //The Payload Length field indicates the length in octets of the current
1351  //payload, including the generic payload header
1352  n = ntohs(payload->payloadLength);
1353 
1354  //Check the length of the IKE payload
1355  if(n < sizeof(IkePayloadHeader) || n > length)
1356  return NULL;
1357 
1358  //Notify payload?
1360  {
1361  //Point to the Notify payload
1362  notifyPayload = (IkeNotifyPayload *) p;
1363 
1364  //Malformed Notify payload?
1365  if(n < sizeof(IkeNotifyPayload))
1366  return NULL;
1367 
1368  //Check the length of the SPI
1369  if(n < (sizeof(IkeNotifyPayload) + notifyPayload->spiSize))
1370  return NULL;
1371 
1372  //Check the type of the notification message
1373  if(ntohs(notifyPayload->notifyMsgType) == type)
1374  {
1375  //Matching occurrence found?
1376  if(i++ == index)
1377  {
1378  return notifyPayload;
1379  }
1380  }
1381  }
1382 
1383  //The Next Payload field indicates the payload type of the next payload
1384  //in the message
1385  nextPayload = payload->nextPayload;
1386 
1387  //Jump to the next IKE payload
1388  p += n;
1389  length -= n;
1390  }
1391 
1392  //The specified payload type was not found
1393  return NULL;
1394 }
1395 
1396 
1397 /**
1398  * @brief Check whether the message contains an unsupported critical payload
1399  * @param[in] message Pointer to the IKE message
1400  * @param[in] length Length of the IKE message, in bytes
1401  * @param[out] unsupportedCriticalPayload Type of the unsupported critical
1402  * payload, if any
1403  * @return Error code
1404  **/
1405 
1407  uint8_t *unsupportedCriticalPayload)
1408 {
1409  size_t n;
1410  uint8_t nextPayload;
1411  const uint8_t *p;
1412  const IkeHeader *ikeHeader;
1413  const IkePayloadHeader *payload;
1414 
1415  //Point to the IKE header
1416  ikeHeader = (IkeHeader *) message;
1417 
1418  //Check the length of the IKE message
1419  if(length < ntohl(ikeHeader->length))
1420  return ERROR_INVALID_SYNTAX;
1421 
1422  //The Next Payload field indicates the type of payload that immediately
1423  //follows the header
1424  nextPayload = ikeHeader->nextPayload;
1425 
1426  //Point to the IKE payloads
1427  p = message + sizeof(IkeHeader);
1428  //Get the length of the IKE payloads, in bytes
1429  length -= sizeof(IkeHeader);
1430 
1431  //Following the header are one or more IKE payloads each identified by
1432  //a Next Payload field in the preceding payload
1434  {
1435  //Malformed IKE message?
1436  if(length < sizeof(IkePayloadHeader))
1437  return ERROR_INVALID_SYNTAX;
1438 
1439  //Each IKE payload begins with a generic payload header
1440  payload = (IkePayloadHeader *) p;
1441 
1442  //The Payload Length field indicates the length in octets of the current
1443  //payload, including the generic payload header
1444  n = ntohs(payload->payloadLength);
1445 
1446  //Check the length of the IKE payload
1447  if(n < sizeof(IkePayloadHeader) || n > length)
1448  return ERROR_INVALID_SYNTAX;
1449 
1450  //Check whether the critical flag is set
1451  if(payload->critical)
1452  {
1453  //Unrecognized payload type?
1456  {
1457  //Return the type of the unsupported critical payload
1458  if(unsupportedCriticalPayload != NULL)
1459  {
1460  *unsupportedCriticalPayload = nextPayload;
1461  }
1462 
1463  //The message must be rejected
1464  return ERROR_UNSUPPORTED_OPTION;
1465  }
1466  }
1467 
1468  //The Next Payload field indicates the payload type of the next payload
1469  //in the message
1470  nextPayload = payload->nextPayload;
1471 
1472  //Jump to the next IKE payload
1473  p += n;
1474  length -= n;
1475  }
1476 
1477  //Successful processing
1478  return NO_ERROR;
1479 }
1480 
1481 #endif
@ IKE_CHILD_SA_STATE_DELETE
Definition: ike.h:1389
AH algorithm negotiation.
#define IPSEC_SPI_SIZE
Definition: ipsec.h:145
error_t ikeParseIdPayload(IkeSaEntry *sa, const IkeIdPayload *idPayload)
Parse Identification payload.
Diffie-Hellman key exchange.
@ IKE_TS_TYPE_IPV4_ADDR_RANGE
TS_IPV4_ADDR_RANGE.
Definition: ike.h:1280
int bool_t
Definition: compiler_port.h:63
@ ERROR_NOT_FOUND
Definition: error.h:148
Authentication of the IKE SA.
Helper functions for IKEv2.
error_t ikeParseTsEntry(const IkeTs *ts, size_t length, IkeTsEntry *tsEntry)
Parse Traffic Selector substructure.
const IkeNotifyPayload * initialContactNotify
IkeCertReqPayload
Definition: ike.h:1583
uint16_t endPort
Definition: ike.h:1806
error_t ikeParseCookieNotification(IkeSaEntry *sa, const IkeNotifyPayload *notifyPayload)
Parse COOKIE notification.
void sha1Update(Sha1Context *context, const void *data, size_t length)
Update the SHA-1 context with a portion of the message being hashed.
@ IKE_NOTIFY_MSG_TYPE_REKEY_SA
Definition: ike.h:1217
const IkeNotifyPayload * natDetectSrcIpNotify
uint32_t spi
Definition: ah.h:175
Traffic selector entry.
Definition: ike.h:1801
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
const IkeNotifyPayload * errorNotify
IkeKePayload
Definition: ike.h:1546
uint8_t p
Definition: ndp.h:300
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
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
uint8_t data[]
Definition: ethernet.h:224
IkeNotifyPayload
Definition: ike.h:1632
const IkeNoncePayload * nonce
error_t ikeParseNoncePayload(const IkeNoncePayload *noncePayload, uint8_t *nonce, size_t *nonceLen)
Parse Nonce payload.
@ IKE_PROTOCOL_ID_AH
AH.
Definition: ike.h:931
Ipv6Addr
Definition: ipv6.h:282
const IkeTsPayload * tsr
IkePayloadHeader
Definition: ike.h:1477
uint8_t type
Definition: coap_common.h:176
@ IKE_PAYLOAD_TYPE_CERTREQ
Certificate Request.
Definition: ike.h:892
#define osMemcmp(p1, p2, length)
Definition: os_port.h:159
const IkeNotifyPayload * ikeGetErrorNotifyPayload(const uint8_t *message, size_t length)
Search an IKE message for an error Notify payload.
const IkeCertPayload * cert
IkeIdType
ID types.
Definition: ike.h:1121
bool_t ikeIsHashAlgoSupported(uint16_t hashAlgoId)
Check whether a given signature hash algorithm is supported.
IkeTransform
Definition: ike.h:1521
const IkeCertReqPayload * certReq
error_t ikeParseSignHashAlgosNotification(IkeSaEntry *sa, const IkeNotifyPayload *notifyPayload)
Parse SIGNATURE_HASH_ALGORITHMS notification.
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:324
@ IKE_NOTIFY_MSG_TYPE_SIGNATURE_HASH_ALGORITHMS
Definition: ike.h:1255
@ IKE_ATTR_FORMAT_TV
shortened Type/Value format
Definition: ike.h:1102
uint16_t startPort
Definition: ike.h:1805
@ IKE_CHILD_SA_STATE_REKEY
Definition: ike.h:1388
@ IKE_NOTIFY_MSG_TYPE_NAT_DETECTION_SOURCE_IP
Definition: ike.h:1212
error_t ikeParseKePayload(IkeKeContext *keContext, const IkeKePayload *kePayload)
Parse Key Exchange payload.
@ IKE_NOTIFY_MSG_TYPE_NAT_DETECTION_DESTINATION_IP
Definition: ike.h:1213
@ IKE_PAYLOAD_TYPE_EAP
Extensible Authentication.
Definition: ike.h:902
#define IkeContext
Definition: ike.h:832
IkeAuthPayload
Definition: ike.h:1596
@ ERROR_INVALID_GROUP
Definition: error.h:276
#define FALSE
Definition: os_port.h:46
PEM file import functions.
error_t ikeParseNatDetectDestIpNotification(IkeSaEntry *sa, const IkeNotifyPayload *notifyPayload)
Parse NAT_DETECTION_DESTINATION_IP notification.
void sha1Init(Sha1Context *context)
Initialize SHA-1 message digest context.
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
Helper functions for signature generation and verification.
const IkeKePayload * ke
error_t
Error codes.
Definition: error.h:43
IkeIdPayload
Definition: ike.h:1559
@ IKE_PAYLOAD_TYPE_AUTH
Authentication.
Definition: ike.h:893
@ IKE_PAYLOAD_TYPE_CERT
Certificate.
Definition: ike.h:891
IkeTsPayload
Definition: ike.h:1670
bool_t ikeIsGroupSupported(uint16_t groupNum)
Check whether a given key exchange method is supported.
IpAddr startAddr
Definition: ike.h:1802
@ ERROR_UNSUPPORTED_OPTION
Definition: error.h:297
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
Key material generation.
#define IKE_SPI_SIZE
Definition: ike.h:826
uint8_t ipProtocolId
Definition: ike.h:1804
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
@ IKE_PROTOCOL_ID_ESP
ESP.
Definition: ike.h:932
#define IKE_MAX_NONCE_SIZE
Definition: ike.h:236
const IkeNotifyPayload * natDetectDestIpNotify
@ 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
#define IKE_MAX_ID_LEN
Definition: ike.h:243
const IkeSaPayload * sa
IkeTransformAttr
Definition: ike.h:1533
@ IKE_PAYLOAD_TYPE_IDI
Identification - Initiator.
Definition: ike.h:889
error_t ikeParseNatDetectSrcIpNotification(IkeSaEntry *sa, const uint8_t *message, size_t length)
Parse NAT_DETECTION_SOURCE_IP notification.
const IkeAuthPayload * auth
void ikeDeleteChildSaEntry(IkeChildSaEntry *childSa)
Delete a Child Security Association.
Definition: ike_misc.c:560
error_t ikeParseInvalidKePayloadNotification(IkeKeContext *keContext, const IkeNotifyPayload *notifyPayload)
Parse INVALID_KE_PAYLOAD notification.
uint8_t length
Definition: tcp.h:375
IkeHeader
Definition: ike.h:1459
size_t length
Definition: ip.h:95
error_t ikeParseSaPayload(const IkeSaPayload *saPayload)
Parse Security Association payload.
IkeDeletePayload
Definition: ike.h:1646
#define IKE_MAX_COOKIE_SIZE
Definition: ike.h:215
error_t ikeParseTsPayload(const IkeTsPayload *tsPayload, uint_t index, IkeTsEntry *tsEntry)
Parse Traffic Selector payload.
IKEv2 (Internet Key Exchange Protocol)
const IkeTsPayload * tsi
#define ntohs(value)
Definition: cpu_endian.h:421
IkeTs
Definition: ike.h:1685
IkeProposal
Definition: ike.h:1505
Ipv4Addr ipv4Addr
Definition: ip.h:99
@ IKE_PAYLOAD_TYPE_NONCE
Nonce.
Definition: ike.h:894
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
IKE payload parsing.
void ikeParseIkeMessagePayloads(const uint8_t *message, size_t length, IkeMessagePayloads *payloads)
Parse IKE message payloads.
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:132
#define IkeSaEntry
Definition: ike.h:836
error_t ikeParseTransform(const IkeTransform *transform, size_t length)
Parse Transform substructure.
uint8_t n
IkeCertPayload
Definition: ike.h:1571
uint8_t payload[]
Definition: ipv6.h:308
const IkeNotifyPayload * signHashAlgosNotify
#define IKE_SHA1_DIGEST_SIZE
Definition: ike.h:828
error_t ikeParseCertReqPayload(IkeSaEntry *sa, const IkeCertReqPayload *certReqPayload)
Parse Certificate Request payload.
@ IKE_PROTOCOL_ID_IKE
IKE.
Definition: ike.h:930
X.509 certificate handling.
@ IKE_PAYLOAD_TYPE_LAST
No Next Payload.
Definition: ike.h:886
@ IKE_NOTIFY_MSG_TYPE_INITIAL_CONTACT
Definition: ike.h:1208
@ IKE_PAYLOAD_TYPE_KE
Key Exchange.
Definition: ike.h:888
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
const IkeNotifyPayload * useTransportModeNotify
SHA-1 algorithm context.
Definition: sha1.h:62
uint8_t nextPayload
Definition: ike.h:1447
@ IKE_NOTIFY_MSG_TYPE_COOKIE
Definition: ike.h:1214
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:167
@ IKE_PAYLOAD_TYPE_TSI
Traffic Selector - Initiator.
Definition: ike.h:898
@ IKE_NOTIFY_MSG_TYPE_USE_TRANSPORT_MODE
Definition: ike.h:1215
IkeNoncePayload
Definition: ike.h:1618
error_t ikeParseProposal(const IkeProposal *proposal, size_t length)
Parse Proposal substructure.
error_t ikeParseDeletePayload(IkeSaEntry *sa, const IkeDeletePayload *deletePayload, bool_t response)
Parse Delete payload.
IpAddr endAddr
Definition: ike.h:1803
error_t ikeParsePublicKey(IkeKeContext *keContext, const uint8_t *p, size_t length)
Parse peer's public key.
uint16_t groupNum
Key exchange method.
Definition: ike.h:1816
@ IKE_PAYLOAD_TYPE_IDR
Identification - Responder.
Definition: ike.h:890
Ipv6Addr ipv6Addr
Definition: ip.h:102
const IkeNotifyPayload * rekeySaNotify
Key exchange context.
Definition: ike.h:1815
unsigned int uint_t
Definition: compiler_port.h:57
#define LOAD16BE(p)
Definition: cpu_endian.h:186
error_t ikeParseTransformAttr(const IkeTransformAttr *attr, size_t length, size_t *consumed)
Parse transform attribute.
void sha1Final(Sha1Context *context, uint8_t *digest)
Finish the SHA-1 message digest.
@ IKE_PAYLOAD_TYPE_SA
Security Association.
Definition: ike.h:887
const IkeIdPayload * idi
#define IkeChildSaEntry
Definition: ike.h:840
@ IKE_PAYLOAD_TYPE_N
Notify.
Definition: ike.h:895
#define ntohl(value)
Definition: cpu_endian.h:422
IKEv2 algorithm negotiation.
uint8_t nonce[]
Definition: ntp_common.h:239
@ NO_ERROR
Success.
Definition: error.h:44
@ IKE_TS_TYPE_IPV6_ADDR_RANGE
TS_IPV6_ADDR_RANGE.
Definition: ike.h:1281
Debugging facilities.
IkeSaPayload
Definition: ike.h:1488
const IkeNotifyPayload * ikeGetStatusNotifyPayload(const uint8_t *message, size_t length, uint16_t type, uint_t index)
Search an IKE message for a given status Notify payload.
const IkeIdPayload * idr
@ IKE_PAYLOAD_TYPE_TSR
Traffic Selector - Responder.
Definition: ike.h:899
systime_t osGetSystemTime(void)
Retrieve system time.