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-2024 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.4.0
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 Security Association payload
54  * @param[in] saPayload Pointer to the Security Association payload
55  * @return Error code
56  **/
57 
59 {
60  error_t error;
61  size_t n;
62  size_t length;
63  const uint8_t *p;
64  const IkeProposal *proposal;
65 
66  //Retrieve the length of the Security Association payload
67  length = ntohs(saPayload->header.payloadLength);
68 
69  //Malformed Security Association payload?
70  if(length < sizeof(IkeSaPayload))
71  return ERROR_INVALID_SYNTAX;
72 
73  //Point to the first byte of the Proposals field
74  p = saPayload->proposals;
75  //Determine the length of the Proposals field
76  length -= sizeof(IkeSaPayload);
77 
78  //The SA payload must contain at least one Proposal substructure
79  if(length == 0)
80  return ERROR_INVALID_SYNTAX;
81 
82  //Loop through the Proposal substructures
83  while(length > 0)
84  {
85  //Malformed payload?
86  if(length < sizeof(IkeProposal))
87  {
88  //Report an error
89  error = ERROR_INVALID_SYNTAX;
90  break;
91  }
92 
93  //Point to the Proposal substructure
94  proposal = (IkeProposal *) p;
95 
96  //The Proposal Length field indicates the length of this proposal,
97  //including all transforms and attributes that follow
98  n = ntohs(proposal->proposalLength);
99 
100  //Check the length of the proposal
101  if(n < sizeof(IkeProposal) || n > length)
102  {
103  //Report an error
104  error = ERROR_INVALID_SYNTAX;
105  break;
106  }
107 
108  //Parse Proposal substructure
109  error = ikeParseProposal(proposal, n);
110  //Any error to report?
111  if(error)
112  break;
113 
114  //Jump to the next proposal
115  p += n;
116  length -= n;
117  }
118 
119  //Return status code
120  return error;
121 }
122 
123 
124 /**
125  * @brief Parse Proposal substructure
126  * @param[in] proposal Pointer to the Proposal substructure
127  * @param[in] length Length of the Proposal substructure, in bytes
128  * @return Error code
129  **/
130 
131 error_t ikeParseProposal(const IkeProposal *proposal, size_t length)
132 {
133  error_t error;
134  uint_t i;
135  size_t n;
136  const uint8_t *p;
137  const IkeTransform *transform;
138 
139  //Check the length of the Proposal substructure
140  if(length < sizeof(IkeProposal))
141  return ERROR_INVALID_SYNTAX;
142 
143  //Malformed substructure?
144  if(length < (sizeof(IkeProposal) + proposal->spiSize))
145  return ERROR_INVALID_SYNTAX;
146 
147  //Get the length of the Proposal substructure
148  length = length - sizeof(IkeProposal) - proposal->spiSize;
149  //Point to the first Transform substructure
150  p = (uint8_t *) proposal + sizeof(IkeProposal) + proposal->spiSize;
151 
152  //The Transforms field must contains at least one Transform substructure
153  if(proposal->numTransforms == 0)
154  return ERROR_INVALID_SYNTAX;
155 
156  //Loop through the Transform substructures
157  for(i = 1; i <= proposal->numTransforms; i++)
158  {
159  //Malformed substructure?
160  if(length < sizeof(IkeTransform))
161  {
162  //Report an error
163  error = ERROR_INVALID_SYNTAX;
164  break;
165  }
166 
167  //Point to the Transform substructure
168  transform = (IkeTransform *) p;
169 
170  //The Transform Length field indicates the length of the Transform
171  //substructure including header and attributes
172  n = ntohs(transform->transformLength);
173 
174  //Check the length of the transform
175  if(n < sizeof(IkeTransform) || n > length)
176  {
177  //Report an error
178  error = ERROR_INVALID_SYNTAX;
179  break;
180  }
181 
182  //Parse Transform substructure
183  error = ikeParseTransform(transform, n);
184  //Any error to report?
185  if(error)
186  break;
187 
188  //Jump to the next transform
189  p += n;
190  length -= n;
191  }
192 
193  //Return status code
194  return error;
195 }
196 
197 
198 /**
199  * @brief Parse Transform substructure
200  * @param[in] transform Pointer to the Transform substructure
201  * @param[in] length Length of the Transform substructure, in bytes
202  * @return Error code
203  **/
204 
205 error_t ikeParseTransform(const IkeTransform *transform, size_t length)
206 {
207  error_t error;
208  size_t n;
209  const uint8_t *p;
210  const IkeTransformAttr *attr;
211 
212  //Check the length of the Transform substructure
213  if(length < sizeof(IkeTransform))
214  return ERROR_INVALID_SYNTAX;
215 
216  //Point to the first byte of the Transform Attributes field
217  p = transform->transformAttr;
218  //Get the length of the Transform Attributes field
219  length -= sizeof(IkeTransform);
220 
221  //The Transform Attributes field is optional
222  if(length > 0)
223  {
224  //The Transform Attributes field contains one or more attributes
225  while(length > 0)
226  {
227  //Malformed attribute?
228  if(length < sizeof(IkeTransformAttr))
229  {
230  //Report an error
231  error = ERROR_INVALID_SYNTAX;
232  break;
233  }
234 
235  //Point to the transform attribute
236  attr = (IkeTransformAttr *) p;
237 
238  //Parse transform attribute
239  error = ikeParseTransformAttr(attr, length, &n);
240  //Any error to report?
241  if(error)
242  break;
243 
244  //Jump to the next attribute
245  p += n;
246  length -= n;
247  }
248  }
249  else
250  {
251  //The Transform Attributes field is not present
252  error = NO_ERROR;
253  }
254 
255  //Return status code
256  return error;
257 }
258 
259 
260 /**
261  * @brief Parse transform attribute
262  * @param[in] attr Pointer to the transform attribute
263  * @param[in] length Number of bytes available in the input stream
264  * @param[out] consumed Total number of characters that have been consumed
265  * @return Error code
266  **/
267 
269  size_t *consumed)
270 {
271  size_t n;
272 
273  //Malformed attribute?
274  if(length < sizeof(IkeTransformAttr))
275  return ERROR_INVALID_SYNTAX;
276 
277  //Check the format of the attribute
278  if((ntohs(attr->type) & IKE_ATTR_FORMAT_TV) != 0)
279  {
280  //If the AF bit is set, then the attribute value has a fixed length
281  n = 0;
282  }
283  else
284  {
285  //If the AF bit is not set, then this attribute has a variable length
286  //defined by the Attribute Length field
287  n = ntohs(attr->length);
288 
289  //Malformed attribute?
290  if(length < (sizeof(IkeTransformAttr) + n))
291  return ERROR_INVALID_SYNTAX;
292  }
293 
294  //Total number of bytes that have been consumed
295  *consumed = sizeof(IkeTransformAttr) + n;
296 
297  //Parsing was successful
298  return NO_ERROR;
299 }
300 
301 
302 /**
303  * @brief Parse Key Exchange payload
304  * @param[in] sa Pointer to the IKE SA
305  * @param[in] kePayload Pointer to the Key Exchange payload
306  * @return Error code
307  **/
308 
310 {
311  error_t error;
312  size_t n;
313  uint16_t dhGroupNum;
314 
315  //Retrieve the length of the Key Exchange payload
316  n = ntohs(kePayload->header.payloadLength);
317 
318  //Malformed Key Exchange payload?
319  if(n < sizeof(IkeKePayload))
320  return ERROR_INVALID_SYNTAX;
321 
322  //Determine the length of the key exchange data
323  n -= sizeof(IkeKePayload);
324 
325  //The Diffie-Hellman Group Num identifies the Diffie-Hellman group in
326  //which the Key Exchange Data was computed
327  dhGroupNum = ntohs(kePayload->dhGroupNum);
328 
329  //Make sure the Diffie-Hellman group is acceptable
330  if(dhGroupNum != sa->dhGroupNum)
331  return ERROR_INVALID_GROUP;
332 
333  //Parse peer's Diffie-Hellman public key
334  error = ikeParseDhPublicKey(sa, kePayload->keyExchangeData, n);
335 
336  //Return status code
337  return error;
338 }
339 
340 
341 /**
342  * @brief Parse Identification payload
343  * @param[in] sa Pointer to the IKE SA
344  * @param[in] idPayload Pointer to the Identification payload
345  * @return Error code
346  **/
347 
349 {
350  size_t n;
351 
352  //Retrieve the length of the Identification payload
353  n = ntohs(idPayload->header.payloadLength);
354 
355  //Malformed Identification payload?
356  if(n < sizeof(IkeIdPayload))
357  return ERROR_INVALID_MESSAGE;
358 
359  //Determine the length of the identification data
360  n -= sizeof(IkeIdPayload);
361 
362  //Check the length of the identification data
363  if(n == 0 || n > IKE_MAX_ID_LEN)
364  return ERROR_INVALID_LENGTH;
365 
366  //Save identification data
367  sa->peerIdType = (IkeIdType) idPayload->idType;
368  osMemcpy(sa->peerId, idPayload->idData, n);
369  sa->peerIdLen = n;
370 
371  //Successful processing
372  return NO_ERROR;
373 }
374 
375 
376 /**
377  * @brief Parse Certificate Request payload
378  * @param[in] sa Pointer to the IKE SA
379  * @param[in] certReqPayload Pointer to the Certificate Request payload
380  * @return Error code
381  **/
382 
384  const IkeCertReqPayload *certReqPayload)
385 {
386 #if (IKE_CERT_AUTH_SUPPORT == ENABLED)
387  size_t n;
388 
389  //Retrieve the length of the Identification payload
390  n = ntohs(certReqPayload->header.payloadLength);
391 
392  //Malformed Identification payload?
393  if(n < sizeof(IkeCertReqPayload))
394  return ERROR_INVALID_MESSAGE;
395 
396  //Determine the length of the Certification Authority field
397  n -= sizeof(IkeCertReqPayload);
398 
399  //Check the length of the Certification Authority field
400  if((n % IKE_SHA1_DIGEST_SIZE) != 0)
401  return ERROR_INVALID_LENGTH;
402 #endif
403 
404  //Successful processing
405  return NO_ERROR;
406 }
407 
408 
409 /**
410  * @brief Parse Nonce payload
411  * @param[in] noncePayload Pointer to the Nonce payload
412  * @param[out] nonce Pointer to the buffer where to store the nonce
413  * @param[out] nonceLen Length of the nonce, in bytes
414  * @return Error code
415  **/
416 
418  uint8_t *nonce, size_t *nonceLen)
419 {
420  size_t n;
421 
422  //Retrieve the length of the Nonce payload
423  n = ntohs(noncePayload->header.payloadLength);
424 
425  //Malformed payload?
426  if(n < sizeof(IkeNoncePayload))
427  return ERROR_INVALID_MESSAGE;
428 
429  //Determine the length of the nonce
430  n -= sizeof(IkeNoncePayload);
431 
432  //Nonces used in IKEv2 must be at least 128 bits in size (refer to
433  //RFC 7296, section 2.10)
434  if(n < IKE_MIN_NONCE_SIZE || n > IKE_MAX_NONCE_SIZE)
435  return ERROR_INVALID_LENGTH;
436 
437  //Save the nonce
438  osMemcpy(nonce, noncePayload->nonceData, n);
439  *nonceLen = n;
440 
441  //Successful processing
442  return NO_ERROR;
443 }
444 
445 
446 /**
447  * @brief Parse Delete payload
448  * @param[in] sa Pointer to the IKE SA
449  * @param[in] deletePayload Pointer to the Delete payload
450  * @param[in] response TRUE if the received INFORMATIONAL message is a response
451  * @return Error code
452  **/
453 
455  const IkeDeletePayload *deletePayload, bool_t response)
456 {
457  uint_t i;
458  size_t n;
459  const uint8_t *spi;
460  IkeChildSaEntry *childSa;
461 
462  //Retrieve the length of the Delete payload
463  n = ntohs(deletePayload->header.payloadLength);
464 
465  //Malformed payload?
466  if(n < sizeof(IkeDeletePayload))
467  return ERROR_INVALID_MESSAGE;
468 
469  //Determine the length of the list
470  n -= sizeof(IkeDeletePayload);
471 
472  //Malformed SPI list?
473  if(n != (deletePayload->spiSize * ntohs(deletePayload->numSpi)))
474  return ERROR_INVALID_MESSAGE;
475 
476  //Check protocol identifier
477  if(deletePayload->protocolId == IKE_PROTOCOL_ID_IKE)
478  {
479  //The SPI Size field must be zero for IKE
480  if(deletePayload->spiSize != 0)
481  return ERROR_INVALID_MESSAGE;
482 
483  //If a peer receives a request to close an IKE SA that it is currently
484  //rekeying, it should reply as usual, and forget about its own rekeying
485  //request (refer to RFC 7296, section 2.25.2)
486 
487  //If a peer receives a request to close an IKE SA that it is currently
488  //trying to close, it should reply as usual, and forget about its own
489  //close request
490  if(!response)
491  sa->deleteReceived = TRUE;
492  }
493  else if(deletePayload->protocolId == IKE_PROTOCOL_ID_AH ||
494  deletePayload->protocolId == IKE_PROTOCOL_ID_ESP)
495  {
496  //The SPI Size field must be four for AH and ESP
497  if(deletePayload->spiSize != 4)
498  return ERROR_INVALID_MESSAGE;
499 
500  //The Delete payload list the SPIs to be deleted
501  for(i = 0; i < ntohs(deletePayload->numSpi); i++)
502  {
503  //Point to the current SPI
504  spi = deletePayload->spi + (i * deletePayload->spiSize);
505 
506  //Perform Child SA lookup
507  childSa = ikeFindChildSaEntry(sa, deletePayload->protocolId, spi);
508 
509  //Child SA found?
510  if(childSa != NULL)
511  {
512  //Check the state of the Child SA
513  if(childSa->state == IKE_CHILD_SA_STATE_REKEY)
514  {
515  //If a peer receives a request to close a Child SA that it is currently
516  //rekeying, it should reply as usual, with a Delete payload (refer to
517  //RFC 7296, section 2.25.1)
518  if(!response)
519  childSa->deleteReceived = TRUE;
520  }
521  else if(childSa->state == IKE_CHILD_SA_STATE_DELETE)
522  {
523  //If a peer receives a request to close a Child SA that it is currently
524  //trying to close, it should reply without a Delete payload
525  if(response)
526  ikeDeleteChildSaEntry(childSa);
527  }
528  else
529  {
530  //If a peer receives a request to delete a Child SA when it is currently
531  //rekeying the IKE SA, it should reply as usual, with a Delete payload
532  //(refer to RFC 7296, section 2.25.2)
533  if(!response)
534  childSa->deleteReceived = TRUE;
535  }
536  }
537  else
538  {
539  //If a peer receives a request to close a Child SA that does not exist,
540  //it should reply without a Delete payload (refer to RFC 7296,
541  //section 2.25.1)
542  }
543  }
544  }
545  else
546  {
547  //Unknown protocol identifier
548  }
549 
550  //Successful processing
551  return NO_ERROR;
552 }
553 
554 
555 /**
556  * @brief Parse INVALID_KE_PAYLOAD notification
557  * @param[in] sa Pointer to the IKE SA
558  * @param[in] notifyPayload Pointer to the Notify payload
559  * @return Error code
560  **/
561 
563  const IkeNotifyPayload *notifyPayload)
564 {
565  size_t n;
566  uint16_t dhGroupNum;
567  const uint8_t *data;
568 
569  //Retrieve the length of the notification data
570  n = ntohs(notifyPayload->header.payloadLength) - sizeof(IkeNotifyPayload) -
571  notifyPayload->spiSize;
572 
573  //There are two octets of data associated with this notification
574  if(n != sizeof(uint16_t))
575  return ERROR_INVALID_MESSAGE;
576 
577  //Point to the notification data
578  data = notifyPayload->spi + notifyPayload->spiSize;
579 
580  //The Diffie-Hellman group number is encoded in big endian order (refer to
581  //RFC 7296, section 1.3)
583 
584  //Ensure the specified group number is supported
586  return ERROR_INVALID_GROUP;
587 
588  //Save the corrected Diffie-Hellman group number
589  sa->dhGroupNum = dhGroupNum;
590 
591  //Successful processing
592  return NO_ERROR;
593 }
594 
595 
596 /**
597  * @brief Parse COOKIE notification
598  * @param[in] sa Pointer to the IKE SA
599  * @param[in] notifyPayload Pointer to the Notify payload
600  * @return Error code
601  **/
602 
604  const IkeNotifyPayload *notifyPayload)
605 {
606  size_t n;
607  const uint8_t *data;
608 
609  //Retrieve the length of the notification data
610  n = ntohs(notifyPayload->header.payloadLength) - sizeof(IkeNotifyPayload) -
611  notifyPayload->spiSize;
612 
613  //The data associated with this notification must be between 1 and 64
614  //octets in length (refer to RFC 7296, section 2.6)
615  if(n < IKE_MIN_COOKIE_SIZE || n > IKE_MAX_COOKIE_SIZE)
616  return ERROR_INVALID_MESSAGE;
617 
618  //Point to the notification data
619  data = notifyPayload->spi + notifyPayload->spiSize;
620 
621  //Save cookie
622  osMemcpy(sa->cookie, data, n);
623  sa->cookieLen = n;
624 
625  //Successful processing
626  return NO_ERROR;
627 }
628 
629 
630 /**
631  * @brief Parse SIGNATURE_HASH_ALGORITHMS notification
632  * @param[in] sa Pointer to the IKE SA
633  * @param[in] notifyPayload Pointer to the Notify payload
634  * @return Error code
635  **/
636 
638  const IkeNotifyPayload *notifyPayload)
639 {
640 #if (IKE_SIGN_HASH_ALGOS_SUPPORT == ENABLED)
641  size_t i;
642  size_t n;
643  uint16_t hashAlgoId;
644  const uint8_t *data;
645 
646  //Retrieve the length of the notification data
647  n = ntohs(notifyPayload->header.payloadLength) - sizeof(IkeNotifyPayload) -
648  notifyPayload->spiSize;
649 
650  //Malformed notification?
651  if((n % sizeof(uint16_t)) != 0)
652  return ERROR_INVALID_MESSAGE;
653 
654  //Point to the notification data
655  data = notifyPayload->spi + notifyPayload->spiSize;
656 
657  //Clear the list of hash algorithms supported by the peer
658  sa->signHashAlgos = 0;
659 
660  //The Notification Data field contains the list of 16-bit hash algorithm
661  //identifiers
662  for(i = 0; i < n; i += sizeof(uint16_t))
663  {
664  //Get the current 16-bit hash algorithm identifier
665  hashAlgoId = LOAD16BE(data + i);
666 
667  //Check whether the hash algorithm is supported
668  if(ikeIsHashAlgoSupported(hashAlgoId))
669  {
670  sa->signHashAlgos |= (1U << hashAlgoId);
671  }
672  }
673 
674  //Successful processing
675  return NO_ERROR;
676 #else
677  //The SIGNATURE_HASH_ALGORITHMS notification is not supported
678  return ERROR_NOT_IMPLEMENTED;
679 #endif
680 }
681 
682 
683 /**
684  * @brief Parse Traffic Selector substructure
685  * @param[in] p Pointer to the input data to parse
686  * @param[in] length Number of bytes available in the input data
687  * @param[out] tsParams Traffic selector parameters
688  * @return Error code
689  **/
690 
691 error_t ikeParseTs(const uint8_t *p, size_t length, IkeTsParams *tsParams)
692 {
693  size_t n;
694  const IkeTs *ts;
695 
696  //Malformed substructure?
697  if(length < sizeof(IkeTs))
698  return ERROR_INVALID_MESSAGE;
699 
700  //Point to the Traffic Selector substructure
701  ts = (IkeTs *) p;
702 
703  //The Selector Length field indicates the length of the Traffic Selector
704  //substructure including the header
705  n = ntohs(ts->selectorLength);
706 
707  //Check the length of the selector
708  if(n < sizeof(IkeTs) || n > length)
709  return ERROR_INVALID_MESSAGE;
710 
711  //The IP protocol ID value specifies the IP protocol ID (such as UDP, TCP,
712  //and ICMP). A value of zero means that the protocol ID is not relevant to
713  //this Traffic Selector
714  tsParams->ipProtocolId = ts->ipProtocolId;
715 
716  //The Start Port value specifies the smallest port number allowed by this
717  //Traffic Selector
718  tsParams->startPort = ntohs(ts->startPort);
719 
720  //The End Port value specifies the smallest port number allowed by this
721  //Traffic Selector
722  tsParams->endPort = ntohs(ts->endPort);
723 
724  //The length of the Starting Address and Ending Address fields depends on
725  //the TS Type field
726  n -= sizeof(IkeTs);
727 
728 #if (IPV4_SUPPORT == ENABLED)
729  //IPv4 address range?
730  if(ts->tsType == IKE_TS_TYPE_IPV4_ADDR_RANGE)
731  {
732  //A range of IPv4 addresses is represented by two four-octet values
733  if(n == (2 * sizeof(Ipv4Addr)))
734  {
735  //The Starting Address field specifies the smallest address included
736  //in this Traffic Selector
737  tsParams->startAddr.length = sizeof(Ipv4Addr);
738  ipv4CopyAddr(&tsParams->startAddr.ipv4Addr, ts->startAddr);
739 
740  //The Ending Address field specifies the smallest address included in
741  //this Traffic Selector
742  tsParams->endAddr.length = sizeof(Ipv4Addr);
743  ipv4CopyAddr(&tsParams->endAddr.ipv4Addr, ts->startAddr + sizeof(Ipv4Addr));
744  }
745  else
746  {
747  //Report an error
748  return ERROR_INVALID_ADDRESS;
749  }
750  }
751  else
752 #endif
753 #if (IPV6_SUPPORT == ENABLED)
754  //IPv6 address range?
755  if(ts->tsType == IKE_TS_TYPE_IPV6_ADDR_RANGE && n == (2 * sizeof(Ipv6Addr)))
756  {
757  //A range of IPv6 addresses is represented by two sixteen-octet values
758  if(n == (2 * sizeof(Ipv6Addr)))
759  {
760  //The Starting Address field specifies the smallest address included
761  //in this Traffic Selector
762  tsParams->startAddr.length = sizeof(Ipv4Addr);
763  ipv6CopyAddr(&tsParams->startAddr.ipv6Addr, ts->startAddr);
764 
765  //The Ending Address field specifies the smallest address included in
766  //this Traffic Selector
767  tsParams->endAddr.length = sizeof(Ipv4Addr);
768  ipv6CopyAddr(&tsParams->endAddr.ipv6Addr, ts->startAddr + sizeof(Ipv6Addr));
769  }
770  else
771  {
772  //Report an error
773  return ERROR_INVALID_ADDRESS;
774  }
775  }
776  else
777 #endif
778  //Unknown Traffic Selector type?
779  {
780  //Report an error
781  return ERROR_INVALID_ADDRESS;
782  }
783 
784  //Successful processing
785  return NO_ERROR;
786 }
787 
788 
789 /**
790  * @brief Search an IKE message for a given payload type
791  * @param[in] message Pointer to the IKE message
792  * @param[in] length Length of the IKE message, in bytes
793  * @param[in] type Payload type
794  * @param[in] index Payload occurrence index
795  * @return If the specified payload type is found, a pointer to the payload
796  * header is returned. Otherwise NULL pointer is returned
797  **/
798 
799 const IkePayloadHeader *ikeGetPayload(const uint8_t *message, size_t length,
800  uint8_t type, uint_t index)
801 {
802  uint_t k;
803  size_t n;
804  uint8_t nextPayload;
805  const uint8_t *p;
806  const IkeHeader *ikeHeader;
807  const IkePayloadHeader *payload;
808 
809  //Point to the IKE header
810  ikeHeader = (IkeHeader *) message;
811 
812  //The Next Payload field indicates the type of payload that immediately
813  //follows the header
814  nextPayload = ikeHeader->nextPayload;
815 
816  //Initialize occurrence index
817  k = 0;
818 
819  //Point to the IKE payloads
820  p = message + sizeof(IkeHeader);
821  //Get the length of the IKE payloads, in bytes
822  length -= sizeof(IkeHeader);
823 
824  //Following the header are one or more IKE payloads each identified by
825  //a Next Payload field in the preceding payload
827  length >= sizeof(IkePayloadHeader))
828  {
829  //Each IKE payload begins with a generic payload header
830  payload = (IkePayloadHeader *) p;
831 
832  //The Payload Length field indicates the length in octets of the current
833  //payload, including the generic payload header
834  n = ntohs(payload->payloadLength);
835 
836  //Check the length of the IKE payload
837  if(n < sizeof(IkePayloadHeader) || n > length)
838  return NULL;
839 
840  //Check IKE payload type
841  if(nextPayload == type)
842  {
843  //Matching occurrence found?
844  if(k++ == index)
845  {
846  return payload;
847  }
848  }
849 
850  //The Next Payload field indicates the payload type of the next payload
851  //in the message
852  nextPayload = payload->nextPayload;
853 
854  //Jump to the next IKE payload
855  p += n;
856  length -= n;
857  }
858 
859  //The specified payload type was not found
860  return NULL;
861 }
862 
863 
864 /**
865  * @brief Search an IKE message for an error Notify payload
866  * @param[in] message Pointer to the received IKE message
867  * @param[in] length Length of the IKE message, in bytes
868  * @return Pointer to the error Notify payload, if any
869  **/
870 
872  size_t length)
873 {
874  size_t n;
875  uint8_t nextPayload;
876  const uint8_t *p;
877  const IkeHeader *ikeHeader;
878  const IkePayloadHeader *payload;
879  const IkeNotifyPayload *notifyPayload;
880 
881  //Point to the IKE header
882  ikeHeader = (IkeHeader *) message;
883 
884  //The Next Payload field indicates the type of payload that immediately
885  //follows the header
886  nextPayload = ikeHeader->nextPayload;
887 
888  //Point to the IKE payloads
889  p = message + sizeof(IkeHeader);
890  //Get the length of the IKE payloads, in bytes
891  length -= sizeof(IkeHeader);
892 
893  //Following the header are one or more IKE payloads each identified by
894  //a Next Payload field in the preceding payload
896  length >= sizeof(IkePayloadHeader))
897  {
898  //Each IKE payload begins with a generic payload header
899  payload = (IkePayloadHeader *) p;
900 
901  //The Payload Length field indicates the length in octets of the current
902  //payload, including the generic payload header
903  n = ntohs(payload->payloadLength);
904 
905  //Check the length of the IKE payload
906  if(n < sizeof(IkePayloadHeader) || n > length)
907  return NULL;
908 
909  //Notify payload?
911  {
912  //Point to the Notify payload
913  notifyPayload = (IkeNotifyPayload *) p;
914 
915  //Malformed Notify payload?
916  if(n < sizeof(IkeNotifyPayload))
917  return NULL;
918 
919  //Check the length of the SPI
920  if(n < (sizeof(IkeNotifyPayload) + notifyPayload->spiSize))
921  return NULL;
922 
923  //Types in the range 0-16383 are intended for reporting errors (refer
924  //to RFC 7296, section 3.10.1)
925  if(ntohs(notifyPayload->notifyMsgType) < 16384)
926  {
927  return notifyPayload;
928  }
929  }
930 
931  //The Next Payload field indicates the payload type of the next payload
932  //in the message
933  nextPayload = payload->nextPayload;
934 
935  //Jump to the next IKE payload
936  p += n;
937  length -= n;
938  }
939 
940  //The specified payload type was not found
941  return NULL;
942 }
943 
944 
945 /**
946  * @brief Search an IKE message for a given status Notify payload
947  * @param[in] message Pointer to the received IKE message
948  * @param[in] length Length of the IKE message, in bytes
949  * @param[in] type Notify message type
950  * @return Pointer to the error Notify payload, if any
951  **/
952 
954  size_t length, uint16_t type)
955 {
956  size_t n;
957  uint8_t nextPayload;
958  const uint8_t *p;
959  const IkeHeader *ikeHeader;
960  const IkePayloadHeader *payload;
961  const IkeNotifyPayload *notifyPayload;
962 
963  //Point to the IKE header
964  ikeHeader = (IkeHeader *) message;
965 
966  //The Next Payload field indicates the type of payload that immediately
967  //follows the header
968  nextPayload = ikeHeader->nextPayload;
969 
970  //Point to the IKE payloads
971  p = message + sizeof(IkeHeader);
972  //Get the length of the IKE payloads, in bytes
973  length -= sizeof(IkeHeader);
974 
975  //Following the header are one or more IKE payloads each identified by
976  //a Next Payload field in the preceding payload
978  length >= sizeof(IkePayloadHeader))
979  {
980  //Each IKE payload begins with a generic payload header
981  payload = (IkePayloadHeader *) p;
982 
983  //The Payload Length field indicates the length in octets of the current
984  //payload, including the generic payload header
985  n = ntohs(payload->payloadLength);
986 
987  //Check the length of the IKE payload
988  if(n < sizeof(IkePayloadHeader) || n > length)
989  return NULL;
990 
991  //Notify payload?
993  {
994  //Point to the Notify payload
995  notifyPayload = (IkeNotifyPayload *) p;
996 
997  //Malformed Notify payload?
998  if(n < sizeof(IkeNotifyPayload))
999  return NULL;
1000 
1001  //Check the length of the SPI
1002  if(n < (sizeof(IkeNotifyPayload) + notifyPayload->spiSize))
1003  return NULL;
1004 
1005  //Check the type of the notification message
1006  if(ntohs(notifyPayload->notifyMsgType) == type)
1007  {
1008  return notifyPayload;
1009  }
1010  }
1011 
1012  //The Next Payload field indicates the payload type of the next payload
1013  //in the message
1014  nextPayload = payload->nextPayload;
1015 
1016  //Jump to the next IKE payload
1017  p += n;
1018  length -= n;
1019  }
1020 
1021  //The specified payload type was not found
1022  return NULL;
1023 }
1024 
1025 
1026 /**
1027  * @brief Check whether the message contains an unsupported critical payload
1028  * @param[in] message Pointer to the IKE message
1029  * @param[in] length Length of the IKE message, in bytes
1030  * @param[out] unsupportedCriticalPayload Type of the unsupported critical
1031  * payload, if any
1032  * @return Error code
1033  **/
1034 
1036  uint8_t *unsupportedCriticalPayload)
1037 {
1038  size_t n;
1039  uint8_t nextPayload;
1040  const uint8_t *p;
1041  const IkeHeader *ikeHeader;
1042  const IkePayloadHeader *payload;
1043 
1044  //Point to the IKE header
1045  ikeHeader = (IkeHeader *) message;
1046 
1047  //Check the length of the IKE message
1048  if(length < ntohl(ikeHeader->length))
1049  return ERROR_INVALID_MESSAGE;
1050 
1051  //The Next Payload field indicates the type of payload that immediately
1052  //follows the header
1053  nextPayload = ikeHeader->nextPayload;
1054 
1055  //Point to the IKE payloads
1056  p = message + sizeof(IkeHeader);
1057  //Get the length of the IKE payloads, in bytes
1058  length -= sizeof(IkeHeader);
1059 
1060  //Following the header are one or more IKE payloads each identified by
1061  //a Next Payload field in the preceding payload
1063  {
1064  //Malformed IKE message?
1065  if(length < sizeof(IkePayloadHeader))
1066  return ERROR_INVALID_MESSAGE;
1067 
1068  //Each IKE payload begins with a generic payload header
1069  payload = (IkePayloadHeader *) p;
1070 
1071  //The Payload Length field indicates the length in octets of the current
1072  //payload, including the generic payload header
1073  n = ntohs(payload->payloadLength);
1074 
1075  //Check the length of the IKE payload
1076  if(n < sizeof(IkePayloadHeader) || n > length)
1077  return ERROR_INVALID_MESSAGE;
1078 
1079  //Check whether the critical flag is set
1080  if(payload->critical)
1081  {
1082  //Unrecognized payload type?
1085  {
1086  //Return the type of the unsupported critical payload
1087  if(unsupportedCriticalPayload != NULL)
1088  {
1089  *unsupportedCriticalPayload = nextPayload;
1090  }
1091 
1092  //The message must be rejected
1093  return ERROR_UNSUPPORTED_OPTION;
1094  }
1095  }
1096 
1097  //The Next Payload field indicates the payload type of the next payload
1098  //in the message
1099  nextPayload = payload->nextPayload;
1100 
1101  //Jump to the next IKE payload
1102  p += n;
1103  length -= n;
1104  }
1105 
1106  //Successful processing
1107  return NO_ERROR;
1108 }
1109 
1110 #endif
uint32_t spi
Definition: ah.h:143
AH algorithm negotiation.
uint8_t message[]
Definition: chap.h:154
uint8_t type
Definition: coap_common.h:176
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define ntohl(value)
Definition: cpu_endian.h:422
#define ntohs(value)
Definition: cpu_endian.h:421
#define LOAD16BE(p)
Definition: cpu_endian.h:186
Debugging facilities.
uint8_t n
error_t
Error codes.
Definition: error.h:43
@ ERROR_INVALID_ADDRESS
Definition: error.h:103
@ ERROR_UNSUPPORTED_OPTION
Definition: error.h:295
@ ERROR_INVALID_GROUP
Definition: error.h:274
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
@ ERROR_INVALID_SYNTAX
Definition: error.h:68
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_LENGTH
Definition: error.h:111
uint8_t data[]
Definition: ethernet.h:222
IKEv2 (Internet Key Exchange Protocol)
@ IKE_CHILD_SA_STATE_DELETE
Definition: ike.h:1199
@ IKE_CHILD_SA_STATE_REKEY
Definition: ike.h:1198
IkeKePayload
Definition: ike.h:1353
IkeProposal
Definition: ike.h:1312
IkeSaPayload
Definition: ike.h:1295
IkeIdPayload
Definition: ike.h:1366
#define IkeChildSaEntry
Definition: ike.h:686
uint16_t dhGroupNum
Definition: ike.h:1350
#define IKE_MAX_ID_LEN
Definition: ike.h:208
#define IKE_MAX_COOKIE_SIZE
Definition: ike.h:180
@ IKE_TS_TYPE_IPV6_ADDR_RANGE
Definition: ike.h:1100
@ IKE_TS_TYPE_IPV4_ADDR_RANGE
Definition: ike.h:1099
IkeNoncePayload
Definition: ike.h:1425
@ IKE_PROTOCOL_ID_AH
AH protocol.
Definition: ike.h:769
@ IKE_PROTOCOL_ID_IKE
IKE protocol.
Definition: ike.h:768
@ IKE_PROTOCOL_ID_ESP
ESP protocol.
Definition: ike.h:770
IkeCertReqPayload
Definition: ike.h:1390
@ IKE_ATTR_FORMAT_TV
shortened Type/Value format
Definition: ike.h:925
@ IKE_PAYLOAD_TYPE_LAST
No Next Payload.
Definition: ike.h:727
@ IKE_PAYLOAD_TYPE_SA
Security Association.
Definition: ike.h:728
@ IKE_PAYLOAD_TYPE_N
Notify.
Definition: ike.h:736
@ IKE_PAYLOAD_TYPE_EAP
Extensible Authentication.
Definition: ike.h:743
#define IkeSaEntry
Definition: ike.h:682
IkePayloadHeader
Definition: ike.h:1284
IkeHeader
Definition: ike.h:1266
IkeIdType
ID types.
Definition: ike.h:944
IkeTransformAttr
Definition: ike.h:1340
#define IKE_MAX_NONCE_SIZE
Definition: ike.h:201
uint8_t nextPayload
Definition: ike.h:1254
IkeTransform
Definition: ike.h:1328
IkeDeletePayload
Definition: ike.h:1453
#define IKE_SHA1_DIGEST_SIZE
Definition: ike.h:674
IkeTs
Definition: ike.h:1492
IkeNotifyPayload
Definition: ike.h:1439
bool_t ikeIsHashAlgoSupported(uint16_t hashAlgoId)
Check whether a given signature hash algorithm is supported.
bool_t ikeIsDhGroupSupported(uint16_t groupNum)
Check whether a given Diffie-Hellman group is supported.
IKEv2 algorithm negotiation.
Authentication of the IKE SA.
X.509 certificate handling.
error_t ikeParseDhPublicKey(IkeSaEntry *sa, const uint8_t *p, size_t length)
Parse peer's Diffie-Hellman public key.
Diffie-Hellman key exchange.
Key material generation.
void ikeDeleteChildSaEntry(IkeChildSaEntry *childSa)
Delete a Child Security Association.
Definition: ike_misc.c:501
IkeChildSaEntry * ikeFindChildSaEntry(IkeSaEntry *sa, uint8_t protocolId, const uint8_t *spi)
Find an Child SA that matches the specified SPI.
Definition: ike_misc.c:459
Helper functions for IKEv2.
error_t ikeParseTransformAttr(const IkeTransformAttr *attr, size_t length, size_t *consumed)
Parse transform attribute.
error_t ikeParseCookieNotification(IkeSaEntry *sa, const IkeNotifyPayload *notifyPayload)
Parse COOKIE notification.
error_t ikeParseProposal(const IkeProposal *proposal, size_t length)
Parse Proposal substructure.
error_t ikeParseTransform(const IkeTransform *transform, size_t length)
Parse Transform substructure.
error_t ikeParseInvalidKeyPayloadNotification(IkeSaEntry *sa, const IkeNotifyPayload *notifyPayload)
Parse INVALID_KE_PAYLOAD notification.
error_t ikeParseKePayload(IkeSaEntry *sa, const IkeKePayload *kePayload)
Parse Key Exchange payload.
error_t ikeParseCertReqPayload(IkeSaEntry *sa, const IkeCertReqPayload *certReqPayload)
Parse Certificate Request payload.
const IkeNotifyPayload * ikeGetStatusNotifyPayload(const uint8_t *message, size_t length, uint16_t type)
Search an IKE message for a given status Notify payload.
error_t ikeParseSignHashAlgosNotification(IkeSaEntry *sa, const IkeNotifyPayload *notifyPayload)
Parse SIGNATURE_HASH_ALGORITHMS notification.
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.
error_t ikeParseIdPayload(IkeSaEntry *sa, const IkeIdPayload *idPayload)
Parse Identification payload.
error_t ikeParseTs(const uint8_t *p, size_t length, IkeTsParams *tsParams)
Parse Traffic Selector substructure.
error_t ikeParseDeletePayload(IkeSaEntry *sa, const IkeDeletePayload *deletePayload, bool_t response)
Parse Delete payload.
error_t ikeCheckCriticalPayloads(const uint8_t *message, size_t length, uint8_t *unsupportedCriticalPayload)
Check whether the message contains an unsupported critical payload.
error_t ikeParseNoncePayload(const IkeNoncePayload *noncePayload, uint8_t *nonce, size_t *nonceLen)
Parse Nonce payload.
const IkeNotifyPayload * ikeGetErrorNotifyPayload(const uint8_t *message, size_t length)
Search an IKE message for an error Notify payload.
error_t ikeParseSaPayload(const IkeSaPayload *saPayload)
Parse Security Association payload.
IKE payload parsing.
Helper functions for signature generation and verification.
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:148
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:267
Ipv6Addr
Definition: ipv6.h:251
uint8_t payload[]
Definition: ipv6.h:277
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:116
uint8_t p
Definition: ndp.h:300
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define TRUE
Definition: os_port.h:50
PEM file import functions.
Traffic selector parameters.
Definition: ike.h:1608
IpAddr endAddr
Definition: ike.h:1610
uint8_t ipProtocolId
Definition: ike.h:1611
uint16_t startPort
Definition: ike.h:1612
uint16_t endPort
Definition: ike.h:1613
IpAddr startAddr
Definition: ike.h:1609
Ipv6Addr ipv6Addr
Definition: ip.h:87
Ipv4Addr ipv4Addr
Definition: ip.h:84
size_t length
Definition: ip.h:80
uint8_t length
Definition: tcp.h:368