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