ike_payload_format.c
Go to the documentation of this file.
1 /**
2  * @file ike_payload_format.c
3  * @brief IKE payload formatting
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2022-2025 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.5.2
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_format.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 "ah/ah_algorithms.h"
43 #include "esp/esp_algorithms.h"
44 #include "pkix/pem_import.h"
45 #include "debug.h"
46 
47 //Check IKEv2 library configuration
48 #if (IKE_SUPPORT == ENABLED)
49 
50 
51 /**
52  * @brief Format Security Association payload
53  * @param[in] sa Pointer to the IKE SA
54  * @param[in] childSa Pointer to the Child SA
55  * @param[out] p Buffer where to format the payload
56  * @param[out] written Length of the resulting payload
57  * @param[in,out] nextPayload Pointer to the Next Payload field
58  * @return Error code
59  **/
60 
62  uint8_t *p, size_t *written, uint8_t **nextPayload)
63 {
64  error_t error;
65  size_t n;
66  IkeSaPayload *saPayload;
67 
68  //Fix the Next Payload field of the previous payload
70 
71  //Point to the Security Association payload header
72  saPayload = (IkeSaPayload *) p;
73 
74  //Format Security Association payload header
75  saPayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
76  saPayload->header.critical = FALSE;
77  saPayload->header.reserved = 0;
78 
79  //Length of the payload header
80  *written = sizeof(IkeSaPayload);
81 
82  //Point to the Proposals field
83  p = saPayload->proposals;
84 
85  //Valid Child SA?
86  if(childSa != NULL)
87  {
88  //Format Proposal substructure (AH or ESP protocol)
89  error = ikeFormatChildSaProposal(childSa, childSa->protocol,
90  childSa->localSpi, p, &n);
91  }
92  else
93  {
94  //Format Proposal substructure (IKE protocol)
95  if(sa->state == IKE_SA_STATE_REKEY_REQ && sa->newSa != NULL)
96  {
97  error = ikeFormatSaProposal(sa, sa->newSa->initiatorSpi, p, &n);
98  }
99  else if(sa->state == IKE_SA_STATE_OPEN && sa->newSa != NULL)
100  {
101  error = ikeFormatSaProposal(sa, sa->newSa->responderSpi, p, &n);
102  }
103  else
104  {
105  error = ikeFormatSaProposal(sa, NULL, p, &n);
106  }
107  }
108 
109  //Any error to report?
110  if(error)
111  return error;
112 
113  //Total length of the payload
114  *written += n;
115 
116  //Fix the Payload Length field of the payload header
117  saPayload->header.payloadLength = htons(*written);
118 
119  //Keep track of the Next Payload field
120  *nextPayload = &saPayload->header.nextPayload;
121 
122  //Successful processing
123  return NO_ERROR;
124 }
125 
126 
127 /**
128  * @brief Format Proposal substructure (IKE protocol)
129  * @param[in] sa Pointer to the IKE SA
130  * @param[in] spi Security parameter index (optional parameter)
131  * @param[out] p Buffer where to format the Proposal substructure
132  * @param[out] written Length of the resulting Proposal substructure
133  * @return Error code
134  **/
135 
136 error_t ikeFormatSaProposal(IkeSaEntry *sa, const uint8_t *spi, uint8_t *p,
137  size_t *written)
138 {
139  error_t error;
140  size_t n;
141  uint8_t *lastSubstruc;
142  IkeContext *context;
143  IkeProposal *proposal;
144 
145  //Point to the IKE context
146  context = sa->context;
147 
148  //Point to the Proposal substructure
149  proposal = (IkeProposal *) p;
150 
151  //Format Proposal substructure
152  proposal->lastSubstruc = IKE_LAST_SUBSTRUC_LAST;
153  proposal->reserved = 0;
154  proposal->proposalLength = 0;
155  proposal->protocolId = IKE_PROTOCOL_ID_IKE;
156  proposal->spiSize = (spi != NULL) ? IKE_SPI_SIZE : 0;
157  proposal->numTransforms = 0;
158 
159  //Length of the Proposal substructure
160  n = sizeof(IkeProposal);
161 
162  //When the SPI Size field is zero, the SPI field is not present
163  if(spi != NULL)
164  {
165  //Copy the sending entity's SPI
166  osMemcpy(proposal->spi, spi, IKE_SPI_SIZE);
167  //Adjust the length of the Proposal substructure
168  n += IKE_SPI_SIZE;
169  }
170 
171  //The Proposal Length field indicates the length of the proposal, including
172  //all transforms and attributes that follow
173  proposal->proposalLength = htons(n);
174 
175  //The Last Substruc field has a value of 0 if this was the last Transform
176  //Substructure, and a value of 3 if there are more Transform Substructures
177  lastSubstruc = NULL;
178 
179  //Check whether the entity is the original initiator of the IKE SA
180  if(sa->originalInitiator)
181  {
182  //When a proposal is made, the first proposal in an SA payload must be 1,
183  //and subsequent proposals must be one more than the previous proposal
184  //(refer to RFC 7296, section 3.3.1)
185  proposal->proposalNum = 1;
186 
187  //IKE generally has four transforms: a Diffie-Hellman group, an
188  //integrity check algorithm, a PRF algorithm, and an encryption
189  //algorithm
190  error = ikeAddSupportedTransforms(context, proposal, &lastSubstruc);
191  //Any error to report?
192  if(error)
193  return error;
194  }
195  else
196  {
197  //When a proposal is accepted, the proposal number in the SA payload must
198  //match the number on the proposal sent that was accepted (refer to
199  //RFC 7296, section 3.3.1)
200  proposal->proposalNum = sa->acceptedProposalNum;
201 
202  //The accepted cryptographic suite must contain exactly one encryption
203  //transform
204  error = ikeAddTransform(IKE_TRANSFORM_TYPE_ENCR, sa->encAlgoId,
205  sa->encKeyLen, proposal, &lastSubstruc);
206  //Any error to report?
207  if(error)
208  return error;
209 
210  //The accepted cryptographic suite must contain exactly one PRF
211  //transform
212  error = ikeAddTransform(IKE_TRANSFORM_TYPE_PRF, sa->prfAlgoId, 0,
213  proposal, &lastSubstruc);
214  //Any error to report?
215  if(error)
216  return error;
217 
218  //AEAD encryption algorithm?
219  if(ikeIsAeadEncAlgo(sa->encAlgoId))
220  {
221  //If all of the encryption algorithms in any proposal are
222  //authenticated encryption algorithms, then the proposal must not
223  //propose any integrity transforms (refer to RFC 5282, section 8)
224  error = NO_ERROR;
225  }
226  else
227  {
228  //The accepted cryptographic suite must contain exactly one
229  //integrity transform
230  error = ikeAddTransform(IKE_TRANSFORM_TYPE_INTEG, sa->authAlgoId, 0,
231  proposal, &lastSubstruc);
232  }
233 
234  //Any error to report?
235  if(error)
236  return error;
237 
238  //The accepted cryptographic suite must contain exactly one key
239  //exchange transform
240  error = ikeAddTransform(IKE_TRANSFORM_TYPE_DH, sa->dhGroupNum, 0,
241  proposal, &lastSubstruc);
242  //Any error to report?
243  if(error)
244  return error;
245  }
246 
247  //Total length of the Proposal substructure
248  *written = ntohs(proposal->proposalLength);
249 
250  //Successful processing
251  return NO_ERROR;
252 }
253 
254 
255 /**
256  * @brief Format Proposal substructure (AH or ESP protocol)
257  * @param[in] childSa Pointer to the Child SA
258  * @param[in] protocolId Protocol identifier (AH or ESP)
259  * @param[in] spi Security parameter index
260  * @param[out] p Buffer where to format the Proposal substructure
261  * @param[out] written Length of the resulting Proposal substructure
262  * @return Error code
263  **/
264 
266  IpsecProtocol protocolId, const uint8_t *spi, uint8_t *p, size_t *written)
267 {
268  error_t error;
269  size_t n;
270  uint8_t *lastSubstruc;
271  IkeContext *context;
272  IkeProposal *proposal;
273 
274  //Point to the IKE context
275  context = childSa->context;
276 
277  //Point to the Proposal substructure
278  proposal = (IkeProposal *) p;
279 
280  //Format Proposal substructure
281  proposal->lastSubstruc = IKE_LAST_SUBSTRUC_LAST;
282  proposal->reserved = 0;
283  proposal->proposalLength = 0;
284  proposal->protocolId = protocolId;
285  proposal->spiSize = IPSEC_SPI_SIZE;
286  proposal->numTransforms = 0;
287 
288  //Length of the Proposal substructure
289  n = sizeof(IkeProposal);
290 
291  //Copy the sending entity's SPI
292  osMemcpy(proposal->spi, spi, IPSEC_SPI_SIZE);
293  //Adjust the length of the Proposal substructure
294  n += IPSEC_SPI_SIZE;
295 
296  //The Proposal Length field indicates the length of the proposal, including
297  //all transforms and attributes that follow
298  proposal->proposalLength = htons(n);
299 
300  //The Last Substruc field has a value of 0 if this was the last Transform
301  //Substructure, and a value of 3 if there are more Transform Substructures
302  lastSubstruc = NULL;
303 
304  //Check whether the entity is the initiator of the CREATE_CHILD_SA
305  //exchange
306  if(childSa->initiator)
307  {
308  //When a proposal is made, the first proposal in an SA payload must be 1,
309  //and subsequent proposals must be one more than the previous proposal
310  //(refer to RFC 7296, section 3.3.1)
311  proposal->proposalNum = 1;
312 
313 #if (AH_SUPPORT == ENABLED)
314  //AH protocol identifier?
316  {
317  //AH generally has two transforms: ESN and an integrity check
318  //algorithm
319  error = ahAddSupportedTransforms(context, proposal, &lastSubstruc);
320  //Any error to report?
321  if(error)
322  return error;
323  }
324  else
325 #endif
326 #if (ESP_SUPPORT == ENABLED)
327  //ESP protocol identifier?
329  {
330  //ESP generally has three transforms: ESN, an encryption algorithm
331  //and an integrity check algorithm
332  error = espAddSupportedTransforms(context, proposal, &lastSubstruc);
333  //Any error to report?
334  if(error)
335  return error;
336  }
337  else
338 #endif
339  //Unknown protocol identifier?
340  {
341  //Report an error
342  return ERROR_FAILURE;
343  }
344  }
345  else
346  {
347  //When a proposal is accepted, the proposal number in the SA payload must
348  //match the number on the proposal sent that was accepted (refer to
349  //RFC 7296, section 3.3.1)
350  proposal->proposalNum = childSa->acceptedProposalNum;
351 
352 #if (AH_SUPPORT == ENABLED)
353  //AH protocol identifier?
355  {
356  //The accepted proposal contains a single integrity transform
358  childSa->authAlgoId, 0, proposal, &lastSubstruc);
359  //Any error to report?
360  if(error)
361  return error;
362 
363  //The accepted proposal contains a single ESN transform
364  error = ikeAddTransform(IKE_TRANSFORM_TYPE_ESN, childSa->esn,
365  0, proposal, &lastSubstruc);
366  //Any error to report?
367  if(error)
368  return error;
369  }
370  else
371 #endif
372 #if (ESP_SUPPORT == ENABLED)
373  //ESP protocol identifier?
375  {
376  //The accepted proposal contains a single encryption transform
377  error = ikeAddTransform(IKE_TRANSFORM_TYPE_ENCR, childSa->encAlgoId,
378  childSa->encKeyLen, proposal, &lastSubstruc);
379  //Any error to report?
380  if(error)
381  return error;
382 
383  //AEAD encryption algorithm?
384  if(ikeIsAeadEncAlgo(childSa->encAlgoId))
385  {
386  //If all of the encryption algorithms in any proposal are
387  //authenticated encryption algorithms, then the proposal must not
388  //propose any integrity transforms (refer to RFC 5282, section 8)
389  error = NO_ERROR;
390  }
391  else
392  {
393  //The accepted proposal contains a single integrity transform
395  childSa->authAlgoId, 0, proposal, &lastSubstruc);
396  }
397 
398  //Any error to report?
399  if(error)
400  return error;
401 
402  //The accepted proposal contains a single ESN transform
403  error = ikeAddTransform(IKE_TRANSFORM_TYPE_ESN, childSa->esn,
404  0, proposal, &lastSubstruc);
405  //Any error to report?
406  if(error)
407  return error;
408  }
409  else
410 #endif
411  //Unknown protocol identifier?
412  {
413  //Report an error
414  return ERROR_FAILURE;
415  }
416  }
417 
418  //Total length of the Proposal substructure
419  *written = ntohs(proposal->proposalLength);
420 
421  //Successful processing
422  return NO_ERROR;
423 }
424 
425 
426 /**
427  * @brief Format Key Exchange payload
428  * @param[in] sa Pointer to the IKE SA
429  * @param[out] p Buffer where to format the payload
430  * @param[out] written Length of the resulting payload
431  * @param[in,out] nextPayload Pointer to the Next Payload field
432  * @return Error code
433  **/
434 
435 error_t ikeFormatKePayload(IkeSaEntry *sa, uint8_t *p, size_t *written,
436  uint8_t **nextPayload)
437 {
438  error_t error;
439  size_t n;
440  IkeKePayload *kePayload;
441 
442  //Fix the Next Payload field of the previous payload
444 
445  //Point to the Key Exchange payload header
446  kePayload = (IkeKePayload *) p;
447 
448  //Format Key Exchange payload header
449  kePayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
450  kePayload->header.critical = FALSE;
451  kePayload->header.reserved = 0;
452 
453  //The Diffie-Hellman Group Num identifies the Diffie-Hellman group in
454  //which the Key Exchange Data was computed
455  kePayload->dhGroupNum = htons(sa->dhGroupNum);
456 
457  //For forward compatibility, all fields marked RESERVED must be set to
458  //zero (refer to RFC 7296, section 2.5)
459  kePayload->reserved = 0;
460 
461  //A Key Exchange payload is constructed by copying one's Diffie-Hellman
462  //public value into the Key Exchange Data portion of the payload
463  error = ikeFormatDhPublicKey(sa, kePayload->keyExchangeData, &n);
464  //Any error to report?
465  if(error)
466  return error;
467 
468  //Total length of payload
469  *written = sizeof(IkeKePayload) + n;
470  //Fix the Payload Length field of the payload header
471  kePayload->header.payloadLength = htons(*written);
472 
473  //Keep track of the Next Payload field
474  *nextPayload = &kePayload->header.nextPayload;
475 
476  //Successful processing
477  return NO_ERROR;
478 }
479 
480 
481 /**
482  * @brief Format Identification payload
483  * @param[in] sa Pointer to the IKE SA
484  * @param[out] p Buffer where to format the payload
485  * @param[out] written Length of the resulting payload
486  * @param[in,out] nextPayload Pointer to the Next Payload field
487  * @return Error code
488  **/
489 
490 error_t ikeFormatIdPayload(IkeSaEntry *sa, uint8_t *p, size_t *written,
491  uint8_t **nextPayload)
492 {
493  error_t error;
494  IkeContext *context;
495  IkeIdPayload *idPayload;
496 
497  //Initialize status code
498  error = NO_ERROR;
499 
500  //Point to the IKE context
501  context = sa->context;
502 
503  //Fix the Next Payload field of the previous payload
504  if(sa->originalInitiator)
505  {
507  }
508  else
509  {
511  }
512 
513  //Point to the Identification payload header
514  idPayload = (IkeIdPayload *) p;
515 
516  //Format Identification payload header
517  idPayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
518  idPayload->header.critical = FALSE;
519  idPayload->header.reserved = 0;
520 
521  //For forward compatibility, all fields marked RESERVED must be set to
522  //zero (refer to RFC 7296, section 2.5)
523  osMemset(idPayload->reserved, 0, 3);
524 
525  //Length of the payload header
526  *written = sizeof(IkeIdPayload);
527 
528  //Check the type of identification being used
529  if(context->idType != IKE_ID_TYPE_INVALID)
530  {
531  //Set ID type
532  idPayload->idType = context->idType;
533 
534  //Copy identification data
535  osMemcpy(idPayload->idData, context->id, context->idLen);
536  //Total length of the payload
537  *written += context->idLen;
538  }
539  else
540  {
541 #if (IKE_CERT_AUTH_SUPPORT == ENABLED)
542  //Check whether an end-entity's certificate exists
543  if(context->certChain != NULL && context->certChainLen > 0)
544  {
545  size_t n;
546 
547  //Set ID type
548  idPayload->idType = IKE_ID_TYPE_DER_ASN1_DN;
549 
550  //Extract the subject's distinguished name from the certificate
551  error = ikeGetCertSubjectDn(context->certChain, context->certChainLen,
552  idPayload->idData, &n);
553 
554  //Check status code
555  if(!error)
556  {
557  //Total length of the payload
558  *written += n;
559  }
560  }
561  else
562 #endif
563  {
564  //Report an error
565  error = ERROR_INVALID_TYPE;
566  }
567  }
568 
569  //Check status code
570  if(!error)
571  {
572  //Fix the Payload Length field of the payload header
573  idPayload->header.payloadLength = htons(*written);
574 
575  //Keep track of the Next Payload field
576  *nextPayload = &idPayload->header.nextPayload;
577  }
578 
579  //Return status code
580  return error;
581 }
582 
583 
584 /**
585  * @brief Format Certificate payloads
586  * @param[in] sa Pointer to the IKE SA
587  * @param[out] p Buffer where to format the payloads
588  * @param[out] written Length of the resulting payloads
589  * @param[in,out] nextPayload Pointer to the Next Payload field
590  * @return Error code
591  **/
592 
593 error_t ikeFormatCertPayloads(IkeSaEntry *sa, uint8_t *p, size_t *written,
594  uint8_t **nextPayload)
595 {
596 #if (IKE_CERT_AUTH_SUPPORT == ENABLED)
597  error_t error;
598  size_t m;
599  size_t n;
600  size_t certChainLen;
601  const char_t *certChain;
602  IkeContext *context;
603 
604  //Initialize status code
605  error = NO_ERROR;
606 
607  //Point to the IKE context
608  context = sa->context;
609 
610  //Total length of the Certificate payloads
611  *written = 0;
612 
613  //Check whether an end-entity's certificate exists
614  if(context->certChain != NULL && context->certChainLen > 0)
615  {
616  //Point to the certificate chain
617  certChain = context->certChain;
618  //Get the total length, in bytes, of the certificate chain
619  certChainLen = context->certChainLen;
620 
621  //If multiple certificates are sent, the first certificate must contain
622  //the public key associated with the private key used to sign the AUTH
623  //payload (refer to RFC 7296, section 3.6)
624  error = ikeFormatCertPayload(certChain, certChainLen, &m, p, &n,
625  nextPayload);
626 
627  //Check status code
628  if(!error)
629  {
630  //Point to the next payload
631  p += n;
632  *written += n;
633 
634  //Move to the next certificate of the chain
635  certChain += m;
636  certChainLen -= m;
637 
638  //If a chain of certificates needs to be sent, multiple Certificate
639  //payloads are used
640  while(certChainLen > 0 && !error)
641  {
642  //Format Certificate payload
643  error = ikeFormatCertPayload(certChain, certChainLen, &m, p, &n,
644  nextPayload);
645 
646  //Check status code
647  if(!error)
648  {
649  //Point to the next payload
650  p += n;
651  *written += n;
652 
653  //Move to the next certificate of the chain
654  certChain += m;
655  certChainLen -= m;
656  }
657  }
658 
659  //The end of the certificate chain has been reached
660  error = NO_ERROR;
661  }
662  }
663 
664  //Return status code
665  return error;
666 #else
667  //Certificate authentication is not supported
668  *written = 0;
669  //Successful processing
670  return NO_ERROR;
671 #endif
672 }
673 
674 
675 /**
676  * @brief Format Certificate payload
677  * @param[in] certChain Pointer to the certificate chain (PEM format)
678  * @param[in] certChainLen Length of the certificate chain, in bytes
679  * @param[out] consumed Total number of characters that have been consumed
680  * @param[out] p Buffer where to format the payload
681  * @param[out] written Length of the resulting payload
682  * @param[in,out] nextPayload Pointer to the Next Payload field
683  * @return Error code
684  **/
685 
686 error_t ikeFormatCertPayload(const char_t *certChain, size_t certChainLen,
687  size_t *consumed, uint8_t *p, size_t *written, uint8_t **nextPayload)
688 {
689 #if (IKE_CERT_AUTH_SUPPORT == ENABLED)
690  error_t error;
691  size_t n;
692  IkeCertPayload *certPayload;
693 
694  //Point to the Certificate payload header
695  certPayload = (IkeCertPayload *) p;
696 
697  //The Certificate Data field Extract the DER-encoded certificate
698  error = pemImportCertificate(certChain, certChainLen, certPayload->certData,
699  &n, consumed);
700 
701  //Check status code
702  if(!error)
703  {
704  //Fix the Next Payload field of the previous payload
706 
707  //Format Certificate payload header
708  certPayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
709  certPayload->header.critical = FALSE;
710  certPayload->header.reserved = 0;
711  certPayload->certEncoding = IKE_CERT_ENCODING_X509_CERT_SIGN;
712 
713  //Total length of the payload
714  *written = sizeof(IkeCertPayload) + n;
715  //Fix the Payload Length field of the payload header
716  certPayload->header.payloadLength = htons(*written);
717 
718  //Keep track of the Next Payload field
719  *nextPayload = &certPayload->header.nextPayload;
720  }
721  else
722  {
723  //End of file detected
724  *written = 0;
725  }
726 
727  //Return status code
728  return error;
729 #else
730  //Certificate authentication is not supported
731  *written = 0;
732  //Successful processing
733  return NO_ERROR;
734 #endif
735 }
736 
737 
738 /**
739  * @brief Format Certificate Request payload
740  * @param[in] sa Pointer to the IKE SA
741  * @param[out] p Buffer where to format the payload
742  * @param[out] written Length of the resulting payload
743  * @param[in,out] nextPayload Pointer to the Next Payload field
744  * @return Error code
745  **/
746 
747 error_t ikeFormatCertReqPayload(IkeSaEntry *sa, uint8_t *p, size_t *written,
748  uint8_t **nextPayload)
749 {
750 #if (IKE_CERT_AUTH_SUPPORT == ENABLED)
751  error_t error;
752  uint_t i;
753  size_t n;
754  IpsecPadEntry *entry;
755  IpsecContext *ipsecContext;
756  IkeCertReqPayload *certReqPayload;
757 
758  //Initialize status code
759  error = NO_ERROR;
760 
761  //Point to the IPsec context
762  ipsecContext = netContext.ipsecContext;
763  //Any error to report?
764  if(ipsecContext == NULL)
765  return ERROR_FAILURE;
766 
767  //Point to the Certificate Request payload header
768  certReqPayload = (IkeCertReqPayload *) p;
769 
770  //Length of the Certification Authority field
771  n = 0;
772 
773  //Loop through PAD entries
774  for(i = 0; i < ipsecContext->numPadEntries && !error; i++)
775  {
776  //Point to the current PAD entry
777  entry = &ipsecContext->pad[i];
778 
779  //Valid authentication method?
780  if(entry->authMethod == IPSEC_AUTH_METHOD_IKEV2)
781  {
782  //Valid trusted CA list?
783  if(entry->trustedCaList != NULL && entry->trustedCaListLen > 0)
784  {
785  //The Certification Authority value is a concatenated list of
786  //SHA-1 hashes of the public keys of trusted Certification
787  //Authorities (CAs)
789  entry->trustedCaListLen, certReqPayload->certAuthority, &n);
790  }
791  }
792  }
793 
794  //Check status code
795  if(!error)
796  {
797  //Check the length of the Certification Authority field
798  if(n > 0)
799  {
800  //Fix the Next Payload field of the previous payload
802 
803  //Format Certificate payload header
804  certReqPayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
805  certReqPayload->header.critical = FALSE;
806  certReqPayload->header.reserved = 0;
807  certReqPayload->certEncoding = IKE_CERT_ENCODING_X509_CERT_SIGN;
808 
809  //Total length of the payload
810  *written = sizeof(IkeCertReqPayload) + n;
811  //Fix the Payload Length field of the payload header
812  certReqPayload->header.payloadLength = htons(*written);
813 
814  //Keep track of the Next Payload field
815  *nextPayload = &certReqPayload->header.nextPayload;
816  }
817  else
818  {
819  //The Certification Authority field is empty
820  *written = 0;
821  }
822  }
823 
824  //Return status code
825  return error;
826 #else
827  //Certificate authentication is not supported
828  *written = 0;
829  //Successful processing
830  return NO_ERROR;
831 #endif
832 }
833 
834 
835 /**
836  * @brief Format Authentication payload
837  * @param[in] sa Pointer to the IKE SA
838  * @param[in] idPayload Pointer to the Identification payload
839  * @param[out] p Buffer where to format the payload
840  * @param[out] written Length of the resulting payload
841  * @param[in,out] nextPayload Pointer to the Next Payload field
842  * @return Error code
843  **/
844 
846  uint8_t *p, size_t *written, uint8_t **nextPayload)
847 {
848  error_t error;
849  size_t n;
850  IkeAuthPayload *authPayload;
851 
852  //Fix the Next Payload field of the previous payload
854 
855  //Point to the Authentication payload header
856  authPayload = (IkeAuthPayload *) p;
857 
858  //Format Authentication payload header
859  authPayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
860  authPayload->header.critical = FALSE;
861  authPayload->header.reserved = 0;
862 
863  //For forward compatibility, all fields marked RESERVED must be set to
864  //zero (refer to RFC 7296, section 2.5)
865  osMemset(authPayload->reserved, 0, 3);
866 
867  //Generate AUTH value
868  error = ikeGenerateAuth(sa, idPayload, &authPayload->authMethod,
869  authPayload->authData, &n);
870 
871  //Check status code
872  if(!error)
873  {
874  //Total length of the payload
875  *written = sizeof(IkeAuthPayload) + n;
876  //Fix the Payload Length field of the payload header
877  authPayload->header.payloadLength = htons(*written);
878 
879  //Keep track of the Next Payload field
880  *nextPayload = &authPayload->header.nextPayload;
881  }
882 
883  //Return status code
884  return error;
885 }
886 
887 
888 /**
889  * @brief Format Nonce payload
890  * @param[in] sa Pointer to the IKE SA
891  * @param[in] childSa Pointer to the Child SA
892  * @param[out] p Buffer where to format the payload
893  * @param[out] written Length of the resulting payload
894  * @param[in,out] nextPayload Pointer to the Next Payload field
895  * @return Error code
896  **/
897 
899  uint8_t *p, size_t *written, uint8_t **nextPayload)
900 {
901  IkeNoncePayload *noncePayload;
902 
903  //Fix the Next Payload field of the previous payload
905 
906  //Point to the Nonce payload header
907  noncePayload = (IkeNoncePayload *) p;
908 
909  //Format Nonce payload header
910  noncePayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
911  noncePayload->header.critical = FALSE;
912  noncePayload->header.reserved = 0;
913 
914  //Length of the payload header
915  *written = sizeof(IkeNoncePayload);
916 
917  //Valid Child SA?
918  if(childSa != NULL)
919  {
920  //Check whether the entity is the initiator of the CREATE_CHILD_SA
921  //exchange
922  if(childSa->initiator)
923  {
924  //Copy the initiator's nonce
925  osMemcpy(noncePayload->nonceData, childSa->initiatorNonce,
926  childSa->initiatorNonceLen);
927 
928  //The size of the Nonce Data must be between 16 and 256 octets
929  *written += childSa->initiatorNonceLen;
930  }
931  else
932  {
933  //Copy the responder's nonce
934  osMemcpy(noncePayload->nonceData, childSa->responderNonce,
935  childSa->responderNonceLen);
936 
937  //The size of the Nonce Data must be between 16 and 256 octets
938  *written += childSa->responderNonceLen;
939  }
940  }
941  else
942  {
943  //Check whether the entity is the original initiator of the IKE SA
944  if(sa->originalInitiator)
945  {
946  //Copy the initiator's nonce
947  osMemcpy(noncePayload->nonceData, sa->initiatorNonce,
948  sa->initiatorNonceLen);
949 
950  //The size of the Nonce Data must be between 16 and 256 octets
951  *written += sa->initiatorNonceLen;
952  }
953  else
954  {
955  //Copy the responder's nonce
956  osMemcpy(noncePayload->nonceData, sa->responderNonce,
957  sa->responderNonceLen);
958 
959  //The size of the Nonce Data must be between 16 and 256 octets
960  *written += sa->responderNonceLen;
961  }
962  }
963 
964  //Fix the Payload Length field of the payload header
965  noncePayload->header.payloadLength = htons(*written);
966 
967  //Keep track of the Next Payload field
968  *nextPayload = &noncePayload->header.nextPayload;
969 
970  //Successful processing
971  return NO_ERROR;
972 }
973 
974 
975 /**
976  * @brief Format Notify payload
977  * @param[in] sa Pointer to the IKE SA
978  * @param[in] childSa Pointer to the Child SA
979  * @param[in] notifyMsgType Type of notification
980  * @param[out] p Buffer where to format the payload
981  * @param[out] written Length of the resulting payload
982  * @param[in,out] nextPayload Pointer to the Next Payload field
983  * @return Error code
984  **/
985 
987  IkeNotifyMsgType notifyMsgType, uint8_t *p, size_t *written,
988  uint8_t **nextPayload)
989 {
990  error_t error;
991  size_t n;
992  IkeNotifyPayload *notifyPayload;
993 
994  //Initialize status code
995  error = NO_ERROR;
996 
997  //Fix the Next Payload field of the previous payload
999 
1000  //Point to the Notify payload header
1001  notifyPayload = (IkeNotifyPayload *) p;
1002 
1003  //Format Notify payload header
1004  notifyPayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
1005  notifyPayload->header.critical = FALSE;
1006  notifyPayload->header.reserved = 0;
1007 
1008  //If the SPI field is empty, the Protocol ID field must be sent as zero and
1009  //must be ignored on receipt (refer to RFC 7296, section 3.10)
1010  notifyPayload->protocolId = 0;
1011  notifyPayload->spiSize = 0;
1012 
1013  //The Notify Message Type field specifies the type of notification message
1014  notifyPayload->notifyMsgType = htons(notifyMsgType);
1015 
1016  //Length of the payload header
1017  *written = sizeof(IkeNotifyPayload);
1018 
1019  //The notification may include additional data
1021  {
1022  //In that Notify payload, the Notification Data contains the one-octet
1023  //payload type (refer to RFC 7296, section 2.5)
1024  notifyPayload->spi[0] = sa->unsupportedCriticalPayload;
1025 
1026  //Total length of the payload
1027  *written += sizeof(uint8_t);
1028  }
1030  {
1031  //The responder indicate its preferred Diffie-Hellman group in the
1032  //INVALID_KE_PAYLOAD Notify payload
1033  STORE16BE(sa->dhGroupNum, notifyPayload->spi);
1034 
1035  //Total length of the payload
1036  *written += sizeof(uint16_t);
1037  }
1039  {
1040  //The Protocol ID field must contain either 2 to indicate AH or 3 to
1041  //indicate ESP
1042  notifyPayload->protocolId = sa->notifyProtocolId;
1043 
1044  //The SPI Size field specifies the length in octets of the SPI as
1045  //defined by the IPsec protocol ID
1046  notifyPayload->spiSize = IPSEC_SPI_SIZE;
1047 
1048  //The SPI is included only with INVALID_SELECTORS, REKEY_SA, and
1049  //CHILD_SA_NOT_FOUND notifications (refer to RFC 7296, section 3.10)
1050  osMemcpy(notifyPayload->spi, sa->notifySpi, IPSEC_SPI_SIZE);
1051 
1052  //Total length of the payload
1053  *written += notifyPayload->spiSize;
1054  }
1056  {
1057  //The data associated with this notification must be between 1 and 64
1058  //octets in length (refer to RFC 7296, section 2.6)
1059  osMemcpy(notifyPayload->spi, sa->cookie, sa->cookieLen);
1060 
1061  //Adjust the length of the Notify payload
1062  *written += sa->cookieLen;
1063  }
1065  {
1066  //The Protocol ID field must contain either 2 to indicate AH or 3 to
1067  //indicate ESP
1068  notifyPayload->protocolId = childSa->protocol;
1069 
1070  //The SPI Size field specifies the length in octets of the SPI as
1071  //defined by the IPsec protocol ID
1072  notifyPayload->spiSize = IPSEC_SPI_SIZE;
1073 
1074  //The SA being rekeyed is identified by the SPI field in the Notify
1075  //payload; this is the SPI the exchange initiator would expect in
1076  //inbound ESP or AH packets. There is no data associated with this
1077  //Notify message type (refer to RFC 7296, section 1.3.3)
1078  osMemcpy(notifyPayload->spi, childSa->oldChildSa->localSpi,
1079  IPSEC_SPI_SIZE);
1080 
1081  //Total length of the payload
1082  *written += notifyPayload->spiSize;
1083  }
1085  {
1086  //The Notification Data field contains the list of 16-bit hash algorithm
1087  //identifiers (refer to RFC 7427, section 4)
1088  error = ikeFormatSignHashAlgosNotificationData(sa, notifyPayload->spi,
1089  &n);
1090 
1091  //Check status code
1092  if(!error)
1093  {
1094  //Total length of the payload
1095  *written += n;
1096  }
1097  }
1098  else
1099  {
1100  //Just for sanity
1101  }
1102 
1103  //Check status code
1104  if(!error)
1105  {
1106  //Fix the Payload Length field of the payload header
1107  notifyPayload->header.payloadLength = htons(*written);
1108 
1109  //Keep track of the Next Payload field
1110  *nextPayload = &notifyPayload->header.nextPayload;
1111  }
1112 
1113  //Return status code
1114  return error;
1115 }
1116 
1117 
1118 /**
1119  * @brief Format SIGNATURE_HASH_ALGORITHMS notification data
1120  * @param[in] sa Pointer to the IKE SA
1121  * @param[out] p Buffer where to format the notification data
1122  * @param[out] written Length of the notification data, in bytes
1123  * @return Error code
1124  **/
1125 
1127  size_t *written)
1128 {
1129  //The Notification Data field contains the list of 16-bit hash algorithm
1130  //identifiers
1131  *written = 0;
1132 
1133 #if (IKE_SHA1_SUPPORT == ENABLED)
1134  //SHA-1 hash algorithm is supported
1136 
1137  //Adjust the length of the notification data
1138  p += sizeof(uint16_t);
1139  *written += sizeof(uint16_t);
1140 #endif
1141 
1142 #if (IKE_SHA256_SUPPORT == ENABLED)
1143  //SHA-256 hash algorithm is supported
1145 
1146  //Adjust the length of the notification data
1147  p += sizeof(uint16_t);
1148  *written += sizeof(uint16_t);
1149 #endif
1150 
1151 #if (IKE_SHA384_SUPPORT == ENABLED)
1152  //SHA-384 hash algorithm is supported
1154 
1155  //Adjust the length of the notification data
1156  p += sizeof(uint16_t);
1157  *written += sizeof(uint16_t);
1158 #endif
1159 
1160 #if (IKE_SHA512_SUPPORT == ENABLED)
1161  //SHA-512 hash algorithm is supported
1163 
1164  //Adjust the length of the notification data
1165  p += sizeof(uint16_t);
1166  *written += sizeof(uint16_t);
1167 #endif
1168 
1169 #if (IKE_ED25519_SIGN_SUPPORT == ENABLED || IKE_ED448_SIGN_SUPPORT == ENABLED)
1170  //Inserting "Identity" hash identifier indicates that the receiver supports
1171  //at least one signature algorithm that accepts messages of arbitrary size
1172  //such as Ed25519 and Ed448 (refer to RFC 8420, section 2)
1174 
1175  //Adjust the length of the notification data
1176  p += sizeof(uint16_t);
1177  *written += sizeof(uint16_t);
1178 #endif
1179 
1180  //Successful processing
1181  return NO_ERROR;
1182 }
1183 
1184 
1185 /**
1186  * @brief Format Delete payload
1187  * @param[in] sa Pointer to the IKE SA
1188  * @param[in] childSa Pointer to the Child SA
1189  * @param[out] p Buffer where to format the payload
1190  * @param[out] written Length of the resulting payload
1191  * @param[in,out] nextPayload Pointer to the Next Payload field
1192  * @return Error code
1193  **/
1194 
1196  uint8_t *p, size_t *written, uint8_t **nextPayload)
1197 {
1198  IkeDeletePayload *deletePayload;
1199 
1200  //Fix the Next Payload field of the previous payload
1202 
1203  //Point to the Delete payload header
1204  deletePayload = (IkeDeletePayload *) p;
1205 
1206  //Format Delete payload header
1207  deletePayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
1208  deletePayload->header.critical = FALSE;
1209  deletePayload->header.reserved = 0;
1210 
1211  //Length of the payload header
1212  *written = sizeof(IkeDeletePayload);
1213 
1214  //Valid Child SA?
1215  if(childSa != NULL)
1216  {
1217  deletePayload->protocolId = childSa->protocol;
1218  deletePayload->spiSize = IPSEC_SPI_SIZE;
1219  deletePayload->numSpi = HTONS(1);
1220 
1221  //Deletion of a Child SA, such as ESP or AH, will contain the IPsec
1222  //protocol ID of that protocol (2 for AH, 3 for ESP), and the SPI is the
1223  //SPI the sending endpoint would expect in inbound ESP or AH packets
1224  osMemcpy(deletePayload->spi, childSa->localSpi, IPSEC_SPI_SIZE);
1225 
1226  //Total length of the payload
1227  *written += IPSEC_SPI_SIZE;
1228  }
1229  else
1230  {
1231  //Deletion of the IKE SA is indicated by a protocol ID of 1 (IKE) but
1232  //no SPIs
1233  deletePayload->protocolId = IKE_PROTOCOL_ID_IKE;
1234  deletePayload->spiSize = 0;
1235  deletePayload->numSpi = HTONS(0);
1236  }
1237 
1238  //Fix the Payload Length field of the payload header
1239  deletePayload->header.payloadLength = htons(*written);
1240 
1241  //Keep track of the Next Payload field
1242  *nextPayload = &deletePayload->header.nextPayload;
1243 
1244  //Successful processing
1245  return NO_ERROR;
1246 }
1247 
1248 
1249 /**
1250  * @brief Format Traffic Selector payload (initiator)
1251  * @param[in] childSa Pointer to the Child SA
1252  * @param[out] p Buffer where to format the payload
1253  * @param[out] written Length of the resulting payload
1254  * @param[in,out] nextPayload Pointer to the Next Payload field
1255  * @return Error code
1256  **/
1257 
1259  size_t *written, uint8_t **nextPayload)
1260 {
1261  error_t error;
1262  size_t n;
1263  IkeTsParams tsParams;
1264  IkeTsPayload *tsPayload;
1265  IpsecSelector *selector;
1266 
1267  //Get selector parameters
1268  selector = &childSa->selector;
1269 
1270  //Fix the Next Payload field of the previous payload
1272 
1273  //Point to the Traffic Selector payload header
1274  tsPayload = (IkeTsPayload *) p;
1275 
1276  //Format Traffic Selector payload header
1277  tsPayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
1278  tsPayload->header.critical = FALSE;
1279  tsPayload->header.reserved = 0;
1280 
1281  //Set the number of Traffic Selectors being provided
1282  tsPayload->numTs = 1;
1283  //The reserved field must be sent as zero
1284  osMemset(tsPayload->reserved, 0, 3);
1285 
1286  //Length of the payload header
1287  *written = sizeof(IkeTsPayload);
1288 
1289  //Point to the Traffic Selectors field
1290  p = tsPayload->trafficSelectors;
1291 
1292  //TSi specifies the source address of traffic forwarded from (or the
1293  //destination address of traffic forwarded to) the initiator of the
1294  //Child SA pair (refer to RFC 7296, section 2.9)
1295  if(childSa->initiator)
1296  {
1297  tsParams.startAddr = selector->localIpAddr.start;
1298  tsParams.endAddr = selector->localIpAddr.end;
1299  tsParams.ipProtocolId = selector->nextProtocol;
1300  tsParams.startPort = selector->localPort.start;
1301  tsParams.endPort = selector->localPort.end;
1302  }
1303  else
1304  {
1305  tsParams.startAddr = selector->remoteIpAddr.start;
1306  tsParams.endAddr = selector->remoteIpAddr.end;
1307  tsParams.ipProtocolId = selector->nextProtocol;
1308  tsParams.startPort = selector->remotePort.start;
1309  tsParams.endPort = selector->remotePort.end;
1310  }
1311 
1312  //Format Traffic Selector substructure
1313  error = ikeFormatTs(&tsParams, p, &n);
1314 
1315  //Check status code
1316  if(!error)
1317  {
1318  //Total length of the payload
1319  *written += n;
1320 
1321  //Fix the Payload Length field of the payload header
1322  tsPayload->header.payloadLength = htons(*written);
1323 
1324  //Keep track of the Next Payload field
1325  *nextPayload = &tsPayload->header.nextPayload;
1326  }
1327 
1328  //Return status code
1329  return error;
1330 }
1331 
1332 
1333 /**
1334  * @brief Format Traffic Selector payload (responder)
1335  * @param[in] childSa Pointer to the Child SA
1336  * @param[out] p Buffer where to format the payload
1337  * @param[out] written Length of the resulting payload
1338  * @param[in,out] nextPayload Pointer to the Next Payload field
1339  * @return Error code
1340  **/
1341 
1343  size_t *written, uint8_t **nextPayload)
1344 {
1345  error_t error;
1346  size_t n;
1347  IkeTsParams tsParams;
1348  IkeTsPayload *tsPayload;
1349  IpsecSelector *selector;
1350 
1351  //Get selector parameters
1352  selector = &childSa->selector;
1353 
1354  //Fix the Next Payload field of the previous payload
1356 
1357  //Point to the Traffic Selector payload header
1358  tsPayload = (IkeTsPayload *) p;
1359 
1360  //Format Traffic Selector payload header
1361  tsPayload->header.nextPayload = IKE_PAYLOAD_TYPE_LAST;
1362  tsPayload->header.critical = FALSE;
1363  tsPayload->header.reserved = 0;
1364 
1365  //Set the number of Traffic Selectors being provided
1366  tsPayload->numTs = 1;
1367  //The reserved field must be sent as zero
1368  osMemset(tsPayload->reserved, 0, 3);
1369 
1370  //Length of the payload header
1371  *written = sizeof(IkeTsPayload);
1372 
1373  //Point to the Traffic Selectors field
1374  p = tsPayload->trafficSelectors;
1375 
1376  //TSr specifies the source address of traffic forwarded from (or the
1377  //destination address of traffic forwarded to) the responder of the
1378  //Child SA pair (refer to RFC 7296, section 2.9)
1379  if(childSa->initiator)
1380  {
1381  tsParams.startAddr = selector->remoteIpAddr.start;
1382  tsParams.endAddr = selector->remoteIpAddr.end;
1383  tsParams.ipProtocolId = selector->nextProtocol;
1384  tsParams.startPort = selector->remotePort.start;
1385  tsParams.endPort = selector->remotePort.end;
1386  }
1387  else
1388  {
1389  tsParams.startAddr = selector->localIpAddr.start;
1390  tsParams.endAddr = selector->localIpAddr.end;
1391  tsParams.ipProtocolId = selector->nextProtocol;
1392  tsParams.startPort = selector->localPort.start;
1393  tsParams.endPort = selector->localPort.end;
1394  }
1395 
1396  //Format Traffic Selector substructure
1397  error = ikeFormatTs(&tsParams, p, &n);
1398 
1399  //Check status code
1400  if(!error)
1401  {
1402  //Total length of the payload
1403  *written += n;
1404 
1405  //Fix the Payload Length field of the payload header
1406  tsPayload->header.payloadLength = htons(*written);
1407 
1408  //Keep track of the Next Payload field
1409  *nextPayload = &tsPayload->header.nextPayload;
1410  }
1411 
1412  //Return status code
1413  return error;
1414 }
1415 
1416 
1417 /**
1418  * @brief Format Traffic Selector substructure
1419  * @param[in] tsParams Traffic selector parameters
1420  * @param[out] p Buffer where to format the Traffic Selector substructure
1421  * @param[out] written Length of the resulting Traffic Selector substructure
1422  * @return Error code
1423  **/
1424 
1425 error_t ikeFormatTs(const IkeTsParams *tsParams, uint8_t *p, size_t *written)
1426 {
1427  error_t error;
1428  IkeTs *ts;
1429 
1430  //Initialize status code
1431  error = NO_ERROR;
1432 
1433  //Point to the Traffic Selector substructure
1434  ts = (IkeTs *) p;
1435 
1436  //Format Traffic Selector substructure
1437  ts->ipProtocolId = tsParams->ipProtocolId;
1438  ts->startPort = htons(tsParams->startPort);
1439  ts->endPort = htons(tsParams->endPort);
1440 
1441  //Length of the substructure
1442  *written = sizeof(IkeTs);
1443 
1444 #if (IPV4_SUPPORT == ENABLED)
1445  //IPv4 address range?
1446  if(tsParams->startAddr.length == sizeof(Ipv4Addr) &&
1447  tsParams->endAddr.length == sizeof(Ipv4Addr))
1448  {
1449  //Specify the type of Traffic Selector
1450  ts->tsType = IKE_TS_TYPE_IPV4_ADDR_RANGE;
1451 
1452  //A range of IPv4 addresses is represented by two four-octet values
1453  ipv4CopyAddr(ts->startAddr, &tsParams->startAddr.ipv4Addr);
1454  ipv4CopyAddr(ts->startAddr + sizeof(Ipv4Addr), &tsParams->endAddr.ipv4Addr);
1455 
1456  //The length of the selector depends on the TS Type field
1457  *written += 2 * sizeof(Ipv4Addr);
1458  }
1459  else
1460 #endif
1461 #if (IPV6_SUPPORT == ENABLED)
1462  //IPv6 address range?
1463  if(tsParams->startAddr.length == sizeof(Ipv6Addr) &&
1464  tsParams->endAddr.length == sizeof(Ipv6Addr))
1465  {
1466  //Specify the type of Traffic Selector
1467  ts->tsType = IKE_TS_TYPE_IPV6_ADDR_RANGE;
1468 
1469  //A range of IPv6 addresses is represented by two sixteen-octet values
1470  ipv6CopyAddr(ts->startAddr, &tsParams->startAddr.ipv6Addr);
1471  ipv6CopyAddr(ts->startAddr + sizeof(Ipv6Addr), &tsParams->endAddr.ipv6Addr);
1472 
1473  //The length of the selector depends on the TS Type field
1474  *written += 2 * sizeof(Ipv6Addr);
1475  }
1476  else
1477 #endif
1478  //Unknown Traffic Selector type?
1479  {
1480  //Report an error
1481  error = ERROR_INVALID_TYPE;
1482  }
1483 
1484  //Check status code
1485  if(!error)
1486  {
1487  //The Selector Length field specifies the length of this Traffic Selector
1488  //substructure including the header
1489  ts->selectorLength = htons(*written);
1490  }
1491 
1492  //Return status code
1493  return error;
1494 }
1495 
1496 #endif
AH algorithm negotiation.
#define htons(value)
Definition: cpu_endian.h:413
#define IPSEC_SPI_SIZE
Definition: ipsec.h:138
Diffie-Hellman key exchange.
error_t ikeFormatNoncePayload(IkeSaEntry *sa, IkeChildSaEntry *childSa, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Nonce payload.
@ IKE_TS_TYPE_IPV4_ADDR_RANGE
Definition: ike.h:1220
Authentication of the IKE SA.
error_t ikeFormatTs(const IkeTsParams *tsParams, uint8_t *p, size_t *written)
Format Traffic Selector substructure.
uint16_t end
Definition: ipsec.h:293
IkeCertReqPayload
Definition: ike.h:1514
error_t ahAddSupportedTransforms(IkeContext *context, IkeProposal *proposal, uint8_t **lastSubstruc)
Add the supported AH transforms to the proposal.
uint_t numPadEntries
Number of entries in the PAD database.
Definition: ipsec.h:442
@ IPSEC_PROTOCOL_AH
Definition: ipsec.h:192
@ IKE_HASH_ALGO_SHA256
Definition: ike.h:1331
IKE payload formatting.
@ IKE_NOTIFY_MSG_TYPE_REKEY_SA
Definition: ike.h:1159
@ IKE_NOTIFY_MSG_TYPE_CHILD_SA_NOT_FOUND
Definition: ike.h:1146
IPsec selector.
Definition: ipsec.h:302
uint32_t spi
Definition: ah.h:196
@ IKE_HASH_ALGO_SHA1
Definition: ike.h:1330
IkeKePayload
Definition: ike.h:1477
uint8_t p
Definition: ndp.h:300
@ IKE_ID_TYPE_DER_ASN1_DN
Definition: ike.h:1071
IpAddr startAddr
Definition: ike.h:1733
error_t ikeAddTransform(IkeTransformType transformType, uint16_t transformId, uint16_t keyLen, IkeProposal *proposal, uint8_t **lastSubstruc)
Add the supported transforms to the proposal.
IkeNotifyPayload
Definition: ike.h:1563
@ IKE_TRANSFORM_TYPE_DH
Diffie-Hellman Group.
Definition: ike.h:901
ESP algorithm negotiation.
error_t ikeFormatChildSaProposal(IkeChildSaEntry *childSa, IpsecProtocol protocolId, const uint8_t *spi, uint8_t *p, size_t *written)
Format Proposal substructure (AH or ESP protocol)
IpAddr endAddr
Definition: ike.h:1734
IpAddr end
Definition: ipsec.h:282
Ipv6Addr
Definition: ipv6.h:260
@ IKE_LAST_SUBSTRUC_LAST
Last proposal/transform substructure.
Definition: ike.h:874
error_t ikeFormatSaPayload(IkeSaEntry *sa, IkeChildSaEntry *childSa, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Security Association payload.
@ IKE_PAYLOAD_TYPE_CERTREQ
Certificate Request.
Definition: ike.h:851
error_t ikeFormatAuthPayload(IkeSaEntry *sa, const IkeIdPayload *idPayload, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Authentication payload.
NetContext netContext
Definition: net.c:75
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:298
@ IKE_NOTIFY_MSG_TYPE_SIGNATURE_HASH_ALGORITHMS
Definition: ike.h:1197
error_t ikeFormatDeletePayload(IkeSaEntry *sa, IkeChildSaEntry *childSa, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Delete payload.
@ IKE_SA_STATE_REKEY_REQ
Definition: ike.h:1294
@ IPSEC_PROTOCOL_ESP
Definition: ipsec.h:193
@ IKE_TRANSFORM_TYPE_ESN
Extended Sequence Numbers.
Definition: ike.h:902
error_t ikeGenerateAuth(IkeSaEntry *sa, const IkeIdPayload *idPayload, uint8_t *authMethod, uint8_t *authData, size_t *authDataLen)
Generate signature or MAC.
Definition: ike_auth.c:59
Traffic selector parameters.
Definition: ike.h:1732
Peer Authorization Database (PAD) entry.
Definition: ipsec.h:400
#define IkeContext
Definition: ike.h:796
IkeAuthPayload
Definition: ike.h:1527
error_t ikeFormatCertAuthorities(const char_t *trustedCaList, size_t trustedCaListLen, uint8_t *certAuth, size_t *certAuthLen)
Format list of acceptable certification authorities.
#define FALSE
Definition: os_port.h:46
error_t pemImportCertificate(const char_t *input, size_t inputLen, uint8_t *output, size_t *outputLen, size_t *consumed)
Decode a PEM file containing a certificate.
Definition: pem_import.c:55
PEM file import functions.
uint16_t notifyMsgType
Definition: ike.h:1561
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
IpsecAuthMethod authMethod
Authentication method (IKEv1, IKEv2, KINK)
Definition: ipsec.h:401
uint8_t nextProtocol
Next layer protocol.
Definition: ipsec.h:305
@ IKE_SA_STATE_OPEN
Definition: ike.h:1291
error_t
Error codes.
Definition: error.h:43
IkeIdPayload
Definition: ike.h:1490
@ IKE_PAYLOAD_TYPE_AUTH
Authentication.
Definition: ike.h:852
IpsecPortRange remotePort
Remote port range.
Definition: ipsec.h:307
@ IKE_PAYLOAD_TYPE_CERT
Certificate.
Definition: ike.h:850
uint8_t protocolId[]
IkeTsPayload
Definition: ike.h:1601
error_t espAddSupportedTransforms(IkeContext *context, IkeProposal *proposal, uint8_t **lastSubstruc)
Add the supported ESP transforms to the proposal.
uint8_t ipProtocolId
Definition: ike.h:1735
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
Key material generation.
@ IKE_HASH_ALGO_SHA512
Definition: ike.h:1333
#define IKE_SPI_SIZE
Definition: ike.h:790
IpsecPadEntry * pad
Peer Authorization Database (PAD)
Definition: ipsec.h:441
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
error_t ikeFormatNotifyPayload(IkeSaEntry *sa, IkeChildSaEntry *childSa, IkeNotifyMsgType notifyMsgType, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Notify payload.
@ IKE_PAYLOAD_TYPE_IDI
Identification - Initiator.
Definition: ike.h:848
@ IPSEC_AUTH_METHOD_IKEV2
Definition: ipsec.h:180
@ ERROR_INVALID_TYPE
Definition: error.h:115
IPsec context.
Definition: ipsec.h:434
error_t ikeFormatTsiPayload(IkeChildSaEntry *childSa, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Traffic Selector payload (initiator)
@ IKE_TRANSFORM_TYPE_ENCR
Encryption Algorithm.
Definition: ike.h:898
size_t trustedCaListLen
Trusted CA list (PEM format)
Definition: ipsec.h:408
bool_t ikeIsAeadEncAlgo(uint16_t encAlgoId)
Test if the transform ID identifies an AEAD encryption algorithm.
error_t ikeFormatIdPayload(IkeSaEntry *sa, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Identification payload.
size_t length
Definition: ip.h:91
error_t ikeFormatCertPayloads(IkeSaEntry *sa, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Certificate payloads.
void * ipsecContext
IPsec context.
Definition: net.h:339
IpsecProtocol
Security protocols.
Definition: ipsec.h:190
IpAddr start
Definition: ipsec.h:281
IkeDeletePayload
Definition: ike.h:1577
const char_t * trustedCaList
Definition: ipsec.h:407
uint16_t start
Definition: ipsec.h:292
IKEv2 (Internet Key Exchange Protocol)
error_t ikeFormatCertPayload(const char_t *certChain, size_t certChainLen, size_t *consumed, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Certificate payload.
#define ntohs(value)
Definition: cpu_endian.h:421
uint16_t startPort
Definition: ike.h:1736
IkeTs
Definition: ike.h:1616
IkeProposal
Definition: ike.h:1436
char char_t
Definition: compiler_port.h:55
Ipv4Addr ipv4Addr
Definition: ip.h:95
@ IKE_PAYLOAD_TYPE_NONCE
Nonce.
Definition: ike.h:853
@ IKE_NOTIFY_MSG_TYPE_INVALID_KE_PAYLOAD
Definition: ike.h:1134
#define ipv6CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv6.h:123
#define IkeSaEntry
Definition: ike.h:800
error_t ikeGetCertSubjectDn(const char_t *cert, size_t certLen, uint8_t *subjectDn, size_t *subjectDnLen)
Extract subject's DN from certificate.
@ IKE_NOTIFY_MSG_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD
Definition: ike.h:1127
uint8_t m
Definition: ndp.h:304
#define HTONS(value)
Definition: cpu_endian.h:410
uint8_t n
error_t ikeFormatKePayload(IkeSaEntry *sa, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Key Exchange payload.
IkeCertPayload
Definition: ike.h:1502
error_t ikeAddSupportedTransforms(IkeContext *context, IkeProposal *proposal, uint8_t **lastSubstruc)
Add the supported IKE transforms to the proposal.
IpsecAddrRange localIpAddr
Local IP address range.
Definition: ipsec.h:303
@ IKE_TRANSFORM_TYPE_PRF
Pseudorandom Function.
Definition: ike.h:899
@ IKE_PROTOCOL_ID_IKE
IKE protocol.
Definition: ike.h:886
@ IKE_ID_TYPE_INVALID
Definition: ike.h:1066
X.509 certificate handling.
@ IKE_PAYLOAD_TYPE_LAST
No Next Payload.
Definition: ike.h:845
IkeNotifyMsgType
Notify message types.
Definition: ike.h:1125
error_t ikeFormatDhPublicKey(IkeSaEntry *sa, uint8_t *p, size_t *written)
Format Diffie-Hellman public key.
@ IKE_PAYLOAD_TYPE_KE
Key Exchange.
Definition: ike.h:847
uint8_t nextPayload
Definition: ike.h:1378
@ IKE_NOTIFY_MSG_TYPE_COOKIE
Definition: ike.h:1156
#define ipv4CopyAddr(destIpAddr, srcIpAddr)
Definition: ipv4.h:155
@ IKE_PAYLOAD_TYPE_TSI
Traffic Selector - Initiator.
Definition: ike.h:857
@ IKE_CERT_ENCODING_X509_CERT_SIGN
X.509 certificate - signature.
Definition: ike.h:1088
IkeNoncePayload
Definition: ike.h:1549
@ IKE_PAYLOAD_TYPE_IDR
Identification - Responder.
Definition: ike.h:849
Ipv6Addr ipv6Addr
Definition: ip.h:98
unsigned int uint_t
Definition: compiler_port.h:57
@ IKE_PAYLOAD_TYPE_D
Delete.
Definition: ike.h:855
#define osMemset(p, value, length)
Definition: os_port.h:138
@ IKE_PAYLOAD_TYPE_SA
Security Association.
Definition: ike.h:846
error_t ikeFormatSaProposal(IkeSaEntry *sa, const uint8_t *spi, uint8_t *p, size_t *written)
Format Proposal substructure (IKE protocol)
error_t ikeFormatCertReqPayload(IkeSaEntry *sa, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Certificate Request payload.
#define IkeChildSaEntry
Definition: ike.h:804
uint16_t endPort
Definition: ike.h:1737
@ IKE_HASH_ALGO_SHA384
Definition: ike.h:1332
@ IKE_HASH_ALGO_IDENTITY
Definition: ike.h:1334
IpsecPortRange localPort
Local port range.
Definition: ipsec.h:306
@ IKE_PAYLOAD_TYPE_N
Notify.
Definition: ike.h:854
IKEv2 algorithm negotiation.
IpsecAddrRange remoteIpAddr
Remote IP address range.
Definition: ipsec.h:304
@ NO_ERROR
Success.
Definition: error.h:44
error_t ikeFormatTsrPayload(IkeChildSaEntry *childSa, uint8_t *p, size_t *written, uint8_t **nextPayload)
Format Traffic Selector payload (responder)
@ IKE_TS_TYPE_IPV6_ADDR_RANGE
Definition: ike.h:1221
Debugging facilities.
IkeSaPayload
Definition: ike.h:1419
@ IKE_PAYLOAD_TYPE_TSR
Traffic Selector - Responder.
Definition: ike.h:858
error_t ikeFormatSignHashAlgosNotificationData(IkeSaEntry *sa, uint8_t *p, size_t *written)
Format SIGNATURE_HASH_ALGORITHMS notification data.
@ IKE_TRANSFORM_TYPE_INTEG
Integrity Algorithm.
Definition: ike.h:900