esp_algorithms.c
Go to the documentation of this file.
1 /**
2  * @file esp_algorithms.c
3  * @brief ESP algorithm negotiation
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.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL ESP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ipsec/ipsec.h"
36 #include "ipsec/ipsec_misc.h"
37 #include "esp/esp.h"
38 #include "esp/esp_algorithms.h"
39 #include "ike/ike_algorithms.h"
40 #include "hash/hash_algorithms.h"
41 #include "debug.h"
42 
43 //Check IPsec library configuration
44 #if (ESP_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief List of supported encryption algorithms
49  **/
50 
51 static const IkeEncAlgo espSupportedEncAlgos[] =
52 {
53 #if (ESP_CHACHA20_POLY1305_SUPPORT == ENABLED)
55 #endif
56 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_GCM_16_SUPPORT == ENABLED)
58 #endif
59 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_GCM_16_SUPPORT == ENABLED)
61 #endif
62 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_GCM_16_SUPPORT == ENABLED)
64 #endif
65 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_GCM_12_SUPPORT == ENABLED)
67 #endif
68 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_GCM_12_SUPPORT == ENABLED)
70 #endif
71 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_GCM_12_SUPPORT == ENABLED)
73 #endif
74 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_GCM_8_SUPPORT == ENABLED)
76 #endif
77 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_GCM_8_SUPPORT == ENABLED)
79 #endif
80 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_GCM_8_SUPPORT == ENABLED)
82 #endif
83 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
85 #endif
86 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
88 #endif
89 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
91 #endif
92 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
94 #endif
95 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
97 #endif
98 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
100 #endif
101 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
103 #endif
104 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
106 #endif
107 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
109 #endif
110 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
112 #endif
113 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
115 #endif
116 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
118 #endif
119 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
121 #endif
122 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
124 #endif
125 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
127 #endif
128 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
130 #endif
131 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
133 #endif
134 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
136 #endif
137 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
139 #endif
140 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
142 #endif
143 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
145 #endif
146 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
148 #endif
149 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
151 #endif
152 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
154 #endif
155 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
157 #endif
158 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
160 #endif
161 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
163 #endif
164 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
166 #endif
167 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
169 #endif
170 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
172 #endif
173 #if (ESP_3DES_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
175 #endif
176 #if (ESP_DES_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
178 #endif
179 #if (ESP_IDEA_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
181 #endif
182 };
183 
184 
185 /**
186  * @brief List of supported integrity algorithms
187  **/
188 
189 static const uint16_t espSupportedAuthAlgos[] =
190 {
191 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_SHA256_SUPPORT == ENABLED)
193 #endif
194 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_SHA384_SUPPORT == ENABLED)
196 #endif
197 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_SHA512_SUPPORT == ENABLED)
199 #endif
200 #if (ESP_CMAC_SUPPORT == ENABLED && ESP_AES_128_SUPPORT == ENABLED)
202 #endif
203 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_SHA1_SUPPORT == ENABLED)
205 #endif
206 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_MD5_SUPPORT == ENABLED)
208 #endif
209  0
210 };
211 
212 
213 /**
214  * @brief List of supported ESN transforms
215  **/
216 
217 static const uint16_t espSupportedEsnTranforms[] =
218 {
219 #if (ESP_ESN_SUPPORT == ENABLED)
221 #endif
223 };
224 
225 
226 /**
227  * @brief Select the relevant encryption algorithm
228  * @param[in] childSa Pointer to the Child SA
229  * @param[in] encAlgoId Encryption algorithm identifier
230  * @param[in] encKeyLen Length of the encryption key, in bytes
231  * @return Error code
232  **/
233 
234 error_t espSelectEncAlgo(IkeChildSaEntry *childSa, uint16_t encAlgoId,
235  size_t encKeyLen)
236 {
237  error_t error;
238 
239  //Initialize status code
240  error = NO_ERROR;
241 
242 #if (ESP_IDEA_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
243  //IDEA-CBC encryption algorithm?
244  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_IDEA)
245  {
246  childSa->cipherMode = CIPHER_MODE_CBC;
247  childSa->cipherAlgo = IDEA_CIPHER_ALGO;
248  childSa->encKeyLen = 16;
249  childSa->ivLen = IDEA_BLOCK_SIZE;
250  }
251  else
252 #endif
253 #if (ESP_DES_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
254  //DES-CBC encryption algorithm?
255  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_DES)
256  {
257  childSa->cipherMode = CIPHER_MODE_CBC;
258  childSa->cipherAlgo = DES_CIPHER_ALGO;
259  childSa->encKeyLen = 8;
260  childSa->ivLen = DES_BLOCK_SIZE;
261  }
262  else
263 #endif
264 #if (ESP_3DES_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
265  //3DES-CBC encryption algorithm?
266  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_3DES)
267  {
268  childSa->cipherMode = CIPHER_MODE_CBC;
269  childSa->cipherAlgo = DES3_CIPHER_ALGO;
270  childSa->encKeyLen = 24;
271  childSa->ivLen = DES3_BLOCK_SIZE;
272  }
273  else
274 #endif
275 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
276  //AES-CBC with 128-bit key encryption algorithm?
277  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CBC && encKeyLen == 16)
278  {
279  childSa->cipherMode = CIPHER_MODE_CBC;
280  childSa->cipherAlgo = AES_CIPHER_ALGO;
281  childSa->encKeyLen = 16;
282  childSa->ivLen = AES_BLOCK_SIZE;
283  }
284  else
285 #endif
286 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
287  //AES-CBC with 192-bit key encryption algorithm?
288  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CBC && encKeyLen == 24)
289  {
290  childSa->cipherMode = CIPHER_MODE_CBC;
291  childSa->cipherAlgo = AES_CIPHER_ALGO;
292  childSa->encKeyLen = 24;
293  childSa->ivLen = AES_BLOCK_SIZE;
294  }
295  else
296 #endif
297 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
298  //AES-CBC with 256-bit key encryption algorithm?
299  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CBC && encKeyLen == 32)
300  {
301  childSa->cipherMode = CIPHER_MODE_CBC;
302  childSa->cipherAlgo = AES_CIPHER_ALGO;
303  childSa->encKeyLen = 32;
304  childSa->ivLen = AES_BLOCK_SIZE;
305  }
306  else
307 #endif
308 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
309  //AES-CTR with 128-bit key encryption algorithm?
310  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CTR && encKeyLen == 16)
311  {
312  childSa->cipherMode = CIPHER_MODE_CTR;
313  childSa->cipherAlgo = AES_CIPHER_ALGO;
314  childSa->encKeyLen = 16;
315  childSa->saltLen = 4;
316  childSa->ivLen = 8;
317  }
318  else
319 #endif
320 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
321  //AES-CTR with 192-bit key encryption algorithm?
322  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CTR && encKeyLen == 24)
323  {
324  childSa->cipherMode = CIPHER_MODE_CTR;
325  childSa->cipherAlgo = AES_CIPHER_ALGO;
326  childSa->encKeyLen = 24;
327  childSa->saltLen = 4;
328  childSa->ivLen = 8;
329  }
330  else
331 #endif
332 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
333  //AES-CTR with 256-bit key encryption algorithm?
334  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CTR && encKeyLen == 32)
335  {
336  childSa->cipherMode = CIPHER_MODE_CTR;
337  childSa->cipherAlgo = AES_CIPHER_ALGO;
338  childSa->encKeyLen = 32;
339  childSa->saltLen = 4;
340  childSa->ivLen = 8;
341  }
342  else
343 #endif
344 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
345  //AES-CCM with 128-bit key and 8-octet ICV encryption algorithm?
346  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CCM_8 && encKeyLen == 16)
347  {
348  childSa->cipherMode = CIPHER_MODE_CCM;
349  childSa->cipherAlgo = AES_CIPHER_ALGO;
350  childSa->encKeyLen = 16;
351  childSa->authKeyLen = 0;
352  childSa->saltLen = 3;
353  childSa->ivLen = 8;
354  childSa->icvLen = 8;
355  }
356  else
357 #endif
358 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
359  //AES-CCM with 192-bit key and 8-octet ICV encryption algorithm?
360  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CCM_8 && encKeyLen == 24)
361  {
362  childSa->cipherMode = CIPHER_MODE_CCM;
363  childSa->cipherAlgo = AES_CIPHER_ALGO;
364  childSa->encKeyLen = 24;
365  childSa->authKeyLen = 0;
366  childSa->saltLen = 3;
367  childSa->ivLen = 8;
368  childSa->icvLen = 8;
369  }
370  else
371 #endif
372 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
373  //AES-CCM with 256-bit key and 8-octet ICV encryption algorithm?
374  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CCM_8 && encKeyLen == 32)
375  {
376  childSa->cipherMode = CIPHER_MODE_CCM;
377  childSa->cipherAlgo = AES_CIPHER_ALGO;
378  childSa->encKeyLen = 32;
379  childSa->authKeyLen = 0;
380  childSa->saltLen = 3;
381  childSa->ivLen = 8;
382  childSa->icvLen = 8;
383  }
384  else
385 #endif
386 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
387  //AES-CCM with 128-bit key and 12-octet ICV encryption algorithm?
388  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CCM_12 && encKeyLen == 16)
389  {
390  childSa->cipherMode = CIPHER_MODE_CCM;
391  childSa->cipherAlgo = AES_CIPHER_ALGO;
392  childSa->encKeyLen = 16;
393  childSa->authKeyLen = 0;
394  childSa->saltLen = 3;
395  childSa->ivLen = 8;
396  childSa->icvLen = 12;
397  }
398  else
399 #endif
400 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
401  //AES-CCM with 192-bit key and 12-octet ICV encryption algorithm?
402  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CCM_12 && encKeyLen == 24)
403  {
404  childSa->cipherMode = CIPHER_MODE_CCM;
405  childSa->cipherAlgo = AES_CIPHER_ALGO;
406  childSa->encKeyLen = 24;
407  childSa->authKeyLen = 0;
408  childSa->saltLen = 3;
409  childSa->ivLen = 8;
410  childSa->icvLen = 12;
411  }
412  else
413 #endif
414 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
415  //AES-CCM with 256-bit key and 12-octet ICV encryption algorithm?
416  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CCM_12 && encKeyLen == 32)
417  {
418  childSa->cipherMode = CIPHER_MODE_CCM;
419  childSa->cipherAlgo = AES_CIPHER_ALGO;
420  childSa->encKeyLen = 32;
421  childSa->authKeyLen = 0;
422  childSa->saltLen = 3;
423  childSa->ivLen = 8;
424  childSa->icvLen = 12;
425  }
426  else
427 #endif
428 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
429  //AES-CCM with 128-bit key and 16-octet ICV encryption algorithm?
430  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CCM_16 && encKeyLen == 16)
431  {
432  childSa->cipherMode = CIPHER_MODE_CCM;
433  childSa->cipherAlgo = AES_CIPHER_ALGO;
434  childSa->encKeyLen = 16;
435  childSa->authKeyLen = 0;
436  childSa->saltLen = 3;
437  childSa->ivLen = 8;
438  childSa->icvLen = 16;
439  }
440  else
441 #endif
442 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
443  //AES-CCM with 192-bit key and 16-octet ICV encryption algorithm?
444  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CCM_16 && encKeyLen == 24)
445  {
446  childSa->cipherMode = CIPHER_MODE_CCM;
447  childSa->cipherAlgo = AES_CIPHER_ALGO;
448  childSa->encKeyLen = 24;
449  childSa->authKeyLen = 0;
450  childSa->saltLen = 3;
451  childSa->ivLen = 8;
452  childSa->icvLen = 16;
453  }
454  else
455 #endif
456 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
457  //AES-CCM with 256-bit key and 16-octet ICV encryption algorithm?
458  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_CCM_16 && encKeyLen == 32)
459  {
460  childSa->cipherMode = CIPHER_MODE_CCM;
461  childSa->cipherAlgo = AES_CIPHER_ALGO;
462  childSa->encKeyLen = 32;
463  childSa->authKeyLen = 0;
464  childSa->saltLen = 3;
465  childSa->ivLen = 8;
466  childSa->icvLen = 16;
467  }
468  else
469 #endif
470 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_GCM_8_SUPPORT == ENABLED)
471  //AES-GCM with 128-bit key and 8-octet ICV encryption algorithm?
472  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_GCM_8 && encKeyLen == 16)
473  {
474  childSa->cipherMode = CIPHER_MODE_GCM;
475  childSa->cipherAlgo = AES_CIPHER_ALGO;
476  childSa->encKeyLen = 16;
477  childSa->authKeyLen = 0;
478  childSa->saltLen = 4;
479  childSa->ivLen = 8;
480  childSa->icvLen = 8;
481  }
482  else
483 #endif
484 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_GCM_8_SUPPORT == ENABLED)
485  //AES-GCM with 192-bit key and 8-octet ICV encryption algorithm?
486  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_GCM_8 && encKeyLen == 24)
487  {
488  childSa->cipherMode = CIPHER_MODE_GCM;
489  childSa->cipherAlgo = AES_CIPHER_ALGO;
490  childSa->encKeyLen = 24;
491  childSa->authKeyLen = 0;
492  childSa->saltLen = 4;
493  childSa->ivLen = 8;
494  childSa->icvLen = 8;
495  }
496  else
497 #endif
498 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_GCM_8_SUPPORT == ENABLED)
499  //AES-GCM with 256-bit key and 8-octet ICV encryption algorithm?
500  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_GCM_8 && encKeyLen == 32)
501  {
502  childSa->cipherMode = CIPHER_MODE_GCM;
503  childSa->cipherAlgo = AES_CIPHER_ALGO;
504  childSa->encKeyLen = 32;
505  childSa->authKeyLen = 0;
506  childSa->saltLen = 4;
507  childSa->ivLen = 8;
508  childSa->icvLen = 8;
509  }
510  else
511 #endif
512 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_GCM_12_SUPPORT == ENABLED)
513  //AES-GCM with 128-bit key and 12-octet ICV encryption algorithm?
514  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_GCM_12 && encKeyLen == 16)
515  {
516  childSa->cipherMode = CIPHER_MODE_GCM;
517  childSa->cipherAlgo = AES_CIPHER_ALGO;
518  childSa->encKeyLen = 16;
519  childSa->authKeyLen = 0;
520  childSa->saltLen = 4;
521  childSa->ivLen = 8;
522  childSa->icvLen = 12;
523  }
524  else
525 #endif
526 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_GCM_12_SUPPORT == ENABLED)
527  //AES-GCM with 192-bit key and 12-octet ICV encryption algorithm?
528  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_GCM_12 && encKeyLen == 24)
529  {
530  childSa->cipherMode = CIPHER_MODE_GCM;
531  childSa->cipherAlgo = AES_CIPHER_ALGO;
532  childSa->encKeyLen = 24;
533  childSa->authKeyLen = 0;
534  childSa->saltLen = 4;
535  childSa->ivLen = 8;
536  childSa->icvLen = 12;
537  }
538  else
539 #endif
540 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_GCM_12_SUPPORT == ENABLED)
541  //AES-GCM with 256-bit key and 12-octet ICV encryption algorithm?
542  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_GCM_12 && encKeyLen == 32)
543  {
544  childSa->cipherMode = CIPHER_MODE_GCM;
545  childSa->cipherAlgo = AES_CIPHER_ALGO;
546  childSa->encKeyLen = 32;
547  childSa->authKeyLen = 0;
548  childSa->saltLen = 4;
549  childSa->ivLen = 8;
550  childSa->icvLen = 12;
551  }
552  else
553 #endif
554 #if (ESP_AES_128_SUPPORT == ENABLED && ESP_GCM_16_SUPPORT == ENABLED)
555  //AES-GCM with 128-bit key and 16-octet ICV encryption algorithm?
556  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_GCM_16 && encKeyLen == 16)
557  {
558  childSa->cipherMode = CIPHER_MODE_GCM;
559  childSa->cipherAlgo = AES_CIPHER_ALGO;
560  childSa->encKeyLen = 16;
561  childSa->authKeyLen = 0;
562  childSa->saltLen = 4;
563  childSa->ivLen = 8;
564  childSa->icvLen = 16;
565  }
566  else
567 #endif
568 #if (ESP_AES_192_SUPPORT == ENABLED && ESP_GCM_16_SUPPORT == ENABLED)
569  //AES-GCM with 192-bit key and 16-octet ICV encryption algorithm?
570  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_GCM_16 && encKeyLen == 24)
571  {
572  childSa->cipherMode = CIPHER_MODE_GCM;
573  childSa->cipherAlgo = AES_CIPHER_ALGO;
574  childSa->encKeyLen = 24;
575  childSa->authKeyLen = 0;
576  childSa->saltLen = 4;
577  childSa->ivLen = 8;
578  childSa->icvLen = 16;
579  }
580  else
581 #endif
582 #if (ESP_AES_256_SUPPORT == ENABLED && ESP_GCM_16_SUPPORT == ENABLED)
583  //AES-GCM with 256-bit key and 16-octet ICV encryption algorithm?
584  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_AES_GCM_16 && encKeyLen == 32)
585  {
586  childSa->cipherMode = CIPHER_MODE_GCM;
587  childSa->cipherAlgo = AES_CIPHER_ALGO;
588  childSa->encKeyLen = 32;
589  childSa->authKeyLen = 0;
590  childSa->saltLen = 4;
591  childSa->ivLen = 8;
592  childSa->icvLen = 16;
593  }
594  else
595 #endif
596 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
597  //Camellia-CBC with 128-bit key encryption algorithm?
598  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CBC && encKeyLen == 16)
599  {
600  childSa->cipherMode = CIPHER_MODE_CBC;
601  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
602  childSa->encKeyLen = 16;
603  childSa->ivLen = CAMELLIA_BLOCK_SIZE;
604  }
605  else
606 #endif
607 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
608  //Camellia-CBC with 192-bit key encryption algorithm?
609  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CBC && encKeyLen == 24)
610  {
611  childSa->cipherMode = CIPHER_MODE_CBC;
612  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
613  childSa->encKeyLen = 24;
614  childSa->ivLen = CAMELLIA_BLOCK_SIZE;
615  }
616  else
617 #endif
618 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
619  //Camellia-CBC with 256-bit key encryption algorithm?
620  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CBC && encKeyLen == 32)
621  {
622  childSa->cipherMode = CIPHER_MODE_CBC;
623  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
624  childSa->encKeyLen = 32;
625  childSa->ivLen = CAMELLIA_BLOCK_SIZE;
626  }
627  else
628 #endif
629 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
630  //Camellia-CTR with 128-bit key encryption algorithm?
631  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CTR && encKeyLen == 16)
632  {
633  childSa->cipherMode = CIPHER_MODE_CTR;
634  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
635  childSa->encKeyLen = 16;
636  childSa->saltLen = 4;
637  childSa->ivLen = 8;
638  }
639  else
640 #endif
641 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
642  //Camellia-CTR with 192-bit key encryption algorithm?
643  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CTR && encKeyLen == 24)
644  {
645  childSa->cipherMode = CIPHER_MODE_CTR;
646  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
647  childSa->encKeyLen = 24;
648  childSa->saltLen = 4;
649  childSa->ivLen = 8;
650  }
651  else
652 #endif
653 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CTR_SUPPORT == ENABLED)
654  //Camellia-CTR with 256-bit key encryption algorithm?
655  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CTR && encKeyLen == 32)
656  {
657  childSa->cipherMode = CIPHER_MODE_CTR;
658  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
659  childSa->encKeyLen = 32;
660  childSa->saltLen = 4;
661  childSa->ivLen = 8;
662  }
663  else
664 #endif
665 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
666  //Camellia-CCM with 128-bit key and 8-octet ICV encryption algorithm?
667  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_8 && encKeyLen == 16)
668  {
669  childSa->cipherMode = CIPHER_MODE_CCM;
670  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
671  childSa->encKeyLen = 16;
672  childSa->authKeyLen = 0;
673  childSa->saltLen = 3;
674  childSa->ivLen = 8;
675  childSa->icvLen = 8;
676  }
677  else
678 #endif
679 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
680  //Camellia-CCM with 192-bit key and 8-octet ICV encryption algorithm?
681  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_8 && encKeyLen == 24)
682  {
683  childSa->cipherMode = CIPHER_MODE_CCM;
684  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
685  childSa->encKeyLen = 24;
686  childSa->authKeyLen = 0;
687  childSa->saltLen = 3;
688  childSa->ivLen = 8;
689  childSa->icvLen = 8;
690  }
691  else
692 #endif
693 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CCM_8_SUPPORT == ENABLED)
694  //Camellia-CCM with 256-bit key and 8-octet ICV encryption algorithm?
695  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_8 && encKeyLen == 32)
696  {
697  childSa->cipherMode = CIPHER_MODE_CCM;
698  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
699  childSa->encKeyLen = 32;
700  childSa->authKeyLen = 0;
701  childSa->saltLen = 3;
702  childSa->ivLen = 8;
703  childSa->icvLen = 8;
704  }
705  else
706 #endif
707 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
708  //Camellia-CCM with 128-bit key and 12-octet ICV encryption algorithm?
709  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_12 && encKeyLen == 16)
710  {
711  childSa->cipherMode = CIPHER_MODE_CCM;
712  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
713  childSa->encKeyLen = 16;
714  childSa->authKeyLen = 0;
715  childSa->saltLen = 3;
716  childSa->ivLen = 8;
717  childSa->icvLen = 12;
718  }
719  else
720 #endif
721 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
722  //Camellia-CCM with 192-bit key and 12-octet ICV encryption algorithm?
723  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_12 && encKeyLen == 24)
724  {
725  childSa->cipherMode = CIPHER_MODE_CCM;
726  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
727  childSa->encKeyLen = 24;
728  childSa->authKeyLen = 0;
729  childSa->saltLen = 3;
730  childSa->ivLen = 8;
731  childSa->icvLen = 12;
732  }
733  else
734 #endif
735 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CCM_12_SUPPORT == ENABLED)
736  //Camellia-CCM with 256-bit key and 12-octet ICV encryption algorithm?
737  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_12 && encKeyLen == 32)
738  {
739  childSa->cipherMode = CIPHER_MODE_CCM;
740  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
741  childSa->encKeyLen = 32;
742  childSa->authKeyLen = 0;
743  childSa->saltLen = 3;
744  childSa->ivLen = 8;
745  childSa->icvLen = 12;
746  }
747  else
748 #endif
749 #if (ESP_CAMELLIA_128_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
750  //Camellia-CCM with 128-bit key and 16-octet ICV encryption algorithm?
751  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_16 && encKeyLen == 16)
752  {
753  childSa->cipherMode = CIPHER_MODE_CCM;
754  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
755  childSa->encKeyLen = 16;
756  childSa->authKeyLen = 0;
757  childSa->saltLen = 3;
758  childSa->ivLen = 8;
759  childSa->icvLen = 16;
760  }
761  else
762 #endif
763 #if (ESP_CAMELLIA_192_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
764  //Camellia-CCM with 192-bit key and 16-octet ICV encryption algorithm?
765  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_16 && encKeyLen == 24)
766  {
767  childSa->cipherMode = CIPHER_MODE_CCM;
768  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
769  childSa->encKeyLen = 24;
770  childSa->authKeyLen = 0;
771  childSa->saltLen = 3;
772  childSa->ivLen = 8;
773  childSa->icvLen = 16;
774  }
775  else
776 #endif
777 #if (ESP_CAMELLIA_256_SUPPORT == ENABLED && ESP_CCM_16_SUPPORT == ENABLED)
778  //Camellia-CCM with 256-bit key and 16-octet ICV encryption algorithm?
779  if(encAlgoId == IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_16 && encKeyLen == 32)
780  {
781  childSa->cipherMode = CIPHER_MODE_CCM;
782  childSa->cipherAlgo = CAMELLIA_CIPHER_ALGO;
783  childSa->encKeyLen = 32;
784  childSa->authKeyLen = 0;
785  childSa->saltLen = 3;
786  childSa->ivLen = 8;
787  childSa->icvLen = 16;
788  }
789  else
790 #endif
791 #if (ESP_CHACHA20_POLY1305_SUPPORT == ENABLED)
792  //ChaCha20Poly1305 encryption algorithm?
794  {
795  childSa->cipherMode = CIPHER_MODE_CHACHA20_POLY1305;
796  childSa->cipherAlgo = NULL;
797  childSa->encKeyLen = 32;
798  childSa->authKeyLen = 0;
799  childSa->saltLen = 4;
800  childSa->ivLen = 8;
801  childSa->icvLen = 16;
802  }
803  else
804 #endif
805  //Unknown encryption algorithm?
806  {
807  //Report an error
808  error = ERROR_UNSUPPORTED_ALGO;
809  }
810 
811  //Return status code
812  return error;
813 }
814 
815 
816 /**
817  * @brief Select the relevant MAC algorithm
818  * @param[in] childSa Pointer to the Child SA
819  * @param[in] authAlgoId Authentication algorithm identifier
820  * @return Error code
821  **/
822 
823 error_t espSelectAuthAlgo(IkeChildSaEntry *childSa, uint16_t authAlgoId)
824 {
825  error_t error;
826 
827  //Initialize status code
828  error = NO_ERROR;
829 
830 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_MD5_SUPPORT == ENABLED)
831  //HMAC-MD5-96 authentication algorithm?
832  if(authAlgoId == IKE_TRANSFORM_ID_AUTH_HMAC_MD5_96)
833  {
834  childSa->authHashAlgo = MD5_HASH_ALGO;
835  childSa->authCipherAlgo = NULL;
836  childSa->authKeyLen = MD5_DIGEST_SIZE;
837  childSa->icvLen = 12;
838  }
839  else
840 #endif
841 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_SHA1_SUPPORT == ENABLED)
842  //HMAC-SHA1-96 authentication algorithm?
843  if(authAlgoId == IKE_TRANSFORM_ID_AUTH_HMAC_SHA1_96)
844  {
845  childSa->authHashAlgo = SHA1_HASH_ALGO;
846  childSa->authCipherAlgo = NULL;
847  childSa->authKeyLen = SHA1_DIGEST_SIZE;
848  childSa->icvLen = 12;
849  }
850  else
851 #endif
852 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_SHA256_SUPPORT == ENABLED)
853  //HMAC-SHA256-128 authentication algorithm?
855  {
856  childSa->authHashAlgo = SHA256_HASH_ALGO;
857  childSa->authCipherAlgo = NULL;
858  childSa->authKeyLen = SHA256_DIGEST_SIZE;
859  childSa->icvLen = 16;
860  }
861  else
862 #endif
863 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_SHA384_SUPPORT == ENABLED)
864  //HMAC-SHA384-192 authentication algorithm?
866  {
867  childSa->authHashAlgo = SHA384_HASH_ALGO;
868  childSa->authCipherAlgo = NULL;
869  childSa->authKeyLen = SHA384_DIGEST_SIZE;
870  childSa->icvLen = 24;
871  }
872  else
873 #endif
874 #if (ESP_HMAC_SUPPORT == ENABLED && ESP_SHA512_SUPPORT == ENABLED)
875  //HMAC-SHA512-256 authentication algorithm?
877  {
878  childSa->authHashAlgo = SHA512_HASH_ALGO;
879  childSa->authCipherAlgo = NULL;
880  childSa->authKeyLen = SHA512_DIGEST_SIZE;
881  childSa->icvLen = 32;
882  }
883  else
884 #endif
885 #if (ESP_CMAC_SUPPORT == ENABLED && ESP_AES_128_SUPPORT == ENABLED)
886  //AES-CMAC-96 authentication algorithm?
887  if(authAlgoId == IKE_TRANSFORM_ID_AUTH_AES_CMAC_96)
888  {
889  childSa->authHashAlgo = NULL;
890  childSa->authCipherAlgo = AES_CIPHER_ALGO;
891  childSa->authKeyLen = 16;
892  childSa->icvLen = 12;
893  }
894  else
895 #endif
896  //Unknown authentication algorithm?
897  {
898  //Report an error
899  error = ERROR_UNSUPPORTED_ALGO;
900  }
901 
902  //Return status code
903  return error;
904 }
905 
906 
907 /**
908  * @brief Add the supported ESP transforms to the proposal
909  * @param[in] context Pointer to the IKE context
910  * @param[in,out] proposal Pointer to the Proposal substructure
911  * @param[in,out] lastSubstruc Pointer to the Last Substruc field
912  * @return Error code
913  **/
914 
916  uint8_t **lastSubstruc)
917 {
918  error_t error;
919 
920  //Add supported encryption transforms
921  error = espAddSupportedEncTransforms(context, proposal, lastSubstruc);
922 
923  //Check status code
924  if(!error)
925  {
926  //Add supported integrity transforms
927  error = espAddSupportedAuthTransforms(context, proposal, lastSubstruc);
928  }
929 
930  //Check status code
931  if(!error)
932  {
933  //An initiator who supports ESNs will usually include two ESN transforms,
934  //with values "0" and "1", in its proposals (refer to RFC 7296,
935  //section 3.3.2)
936  error = espAddSupportedEsnTransforms(context, proposal, lastSubstruc);
937  }
938 
939  //Return status code
940  return error;
941 }
942 
943 
944 /**
945  * @brief Add the supported encryption transforms to the proposal
946  * @param[in] context Pointer to the IKE context
947  * @param[in,out] proposal Pointer to the Proposal substructure
948  * @param[in,out] lastSubstruc Pointer to the Last Substruc field
949  * @return Error code
950  **/
951 
953  IkeProposal *proposal, uint8_t **lastSubstruc)
954 {
955  error_t error;
956  uint_t i;
957 
958  //Initialize status code
959  error = NO_ERROR;
960 
961  //Loop through the list of supported encryption transforms
962  for(i = 0; i < arraysize(espSupportedEncAlgos) && !error; i++)
963  {
964  //Add a new transform to the proposal
966  espSupportedEncAlgos[i].id, espSupportedEncAlgos[i].keyLen,
967  proposal, lastSubstruc);
968  }
969 
970  //Return status code
971  return error;
972 }
973 
974 
975 /**
976  * @brief Add the supported integrity transforms to the proposal
977  * @param[in] context Pointer to the IKE context
978  * @param[in,out] proposal Pointer to the Proposal substructure
979  * @param[in,out] lastSubstruc Pointer to the Last Substruc field
980  * @return Error code
981  **/
982 
984  IkeProposal *proposal, uint8_t **lastSubstruc)
985 {
986  error_t error;
987  uint_t i;
988 
989  //Initialize status code
990  error = NO_ERROR;
991 
992  //Loop through the list of supported integrity transforms
993  for(i = 0; i < (arraysize(espSupportedAuthAlgos) - 1) && !error; i++)
994  {
995  //Add a new transform to the proposal
997  espSupportedAuthAlgos[i], 0, proposal, lastSubstruc);
998  }
999 
1000  //Return status code
1001  return error;
1002 }
1003 
1004 
1005 /**
1006  * @brief Add the supported ESN transforms to the proposal
1007  * @param[in] context Pointer to the IKE context
1008  * @param[in,out] proposal Pointer to the Proposal substructure
1009  * @param[in,out] lastSubstruc Pointer to the Last Substruc field
1010  * @return Error code
1011  **/
1012 
1014  IkeProposal *proposal, uint8_t **lastSubstruc)
1015 {
1016  error_t error;
1017  uint_t i;
1018 
1019  //Initialize status code
1020  error = NO_ERROR;
1021 
1022  //Loop through the list of supported ESN transforms
1023  for(i = 0; i < arraysize(espSupportedEsnTranforms) && !error; i++)
1024  {
1025  //Add a new transform to the proposal
1027  espSupportedEsnTranforms[i], 0, proposal, lastSubstruc);
1028  }
1029 
1030  //Return status code
1031  return error;
1032 }
1033 
1034 
1035 /**
1036  * @brief Encryption transform negotiation
1037  * @param[in] context Pointer to the IKE context
1038  * @param[in] proposal Pointer to the Proposal substructure
1039  * @param[in] proposalLen Length of the Proposal substructure, in bytes
1040  * @return Selected encryption transform, if any
1041  **/
1042 
1044  const IkeProposal *proposal, size_t proposalLen)
1045 {
1046  uint_t i;
1047  uint_t j;
1048  size_t n;
1049  size_t length;
1050  uint8_t *p;
1051  uint16_t transformId;
1052  const IkeEncAlgo *selectedAlgo;
1053  const IkeTransform *transform;
1054  const IkeTransformAttr *attr;
1055 
1056  //Chosen algorithm
1057  selectedAlgo = NULL;
1058 
1059  //Check the length of the Proposal substructure
1060  if(proposalLen >= sizeof(IkeProposal) &&
1061  proposalLen >= (sizeof(IkeProposal) + proposal->spiSize))
1062  {
1063  //Loop through the list of algorithms supported by the entity
1064  for(i = 0; i < arraysize(espSupportedEncAlgos) && selectedAlgo == NULL; i++)
1065  {
1066  //Get the length of the Proposal substructure
1067  length = proposalLen - sizeof(IkeProposal) - proposal->spiSize;
1068  //Point to the first Transform substructure
1069  p = (uint8_t *) proposal + sizeof(IkeProposal) + proposal->spiSize;
1070 
1071  //Loop through the list of algorithms supported by the peer
1072  for(j = 0; j < proposal->numTransforms && selectedAlgo == NULL; j++)
1073  {
1074  //Malformed substructure?
1075  if(length < sizeof(IkeTransform))
1076  break;
1077 
1078  //Point to the Transform substructure
1079  transform = (IkeTransform *) p;
1080 
1081  //The Transform Length field indicates the length of the Transform
1082  //substructure including header and attributes
1083  n = ntohs(transform->transformLength);
1084 
1085  //Check the length of the transform
1086  if(n < sizeof(IkeTransform) || n > length)
1087  break;
1088 
1089  //Check transform type
1090  if(transform->transformType == IKE_TRANSFORM_TYPE_ENCR)
1091  {
1092  //Convert the Transform ID field to host byte order
1093  transformId = ntohs(transform->transformId);
1094 
1095  //Variable-length key encryption algorithm?
1097  {
1098  //For algorithms that accept a variable-length key, a fixed
1099  //key size must be specified as part of the cryptographic
1100  //transform negotiated (refer to RFC 7296, section 2.13)
1101  if(n == (sizeof(IkeTransform) + sizeof(IkeTransformAttr)))
1102  {
1103  //Point to the transform attribute
1104  attr = (IkeTransformAttr *) transform->transformAttr;
1105 
1106  //Check attribute format and type
1107  if(ntohs(attr->type) == ((uint16_t) IKE_ATTR_FORMAT_TV |
1108  (uint16_t) IKE_TRANSFORM_ATTR_TYPE_KEY_LEN))
1109  {
1110  //Check transform identifier and key length
1111  if(transformId == espSupportedEncAlgos[i].id &&
1112  ntohs(attr->length) == (espSupportedEncAlgos[i].keyLen * 8))
1113  {
1114  selectedAlgo = &espSupportedEncAlgos[i];
1115  }
1116  }
1117  }
1118  }
1119  else
1120  {
1121  //The Key Length attribute must not be used with transforms
1122  //that use a fixed-length key (refer to RFC 7296, section 3.3.5)
1123  if(n == sizeof(IkeTransform))
1124  {
1125  //Check transform identifier
1126  if(transformId == espSupportedEncAlgos[i].id)
1127  {
1128  selectedAlgo = &espSupportedEncAlgos[i];
1129  }
1130  }
1131  }
1132  }
1133 
1134  //The Last Substruc field has a value of 0 if this was the last
1135  //Transform Substructure
1136  if(transform->lastSubstruc == IKE_LAST_SUBSTRUC_LAST)
1137  break;
1138 
1139  //Jump to the next Transform substructure
1140  p += n;
1141  length -= n;
1142  }
1143  }
1144  }
1145 
1146  //Return the chosen algorithm, if any
1147  return selectedAlgo;
1148 }
1149 
1150 
1151 /**
1152  * @brief Integrity transform negotiation
1153  * @param[in] context Pointer to the IKE context
1154  * @param[in] proposal Pointer to the Proposal substructure
1155  * @param[in] proposalLen Length of the Proposal substructure, in bytes
1156  * @return Selected integrity transform, if any
1157  **/
1158 
1159 uint16_t espSelectAuthTransform(IkeContext *context, const IkeProposal *proposal,
1160  size_t proposalLen)
1161 {
1162  //Select the integrity transform to use
1163  return ikeSelectTransform(IKE_TRANSFORM_TYPE_INTEG, espSupportedAuthAlgos,
1164  arraysize(espSupportedAuthAlgos) - 1, proposal, proposalLen);
1165 }
1166 
1167 
1168 /**
1169  * @brief ESN transform negotiation
1170  * @param[in] context Pointer to the IKE context
1171  * @param[in] proposal Pointer to the Proposal substructure
1172  * @param[in] proposalLen Length of the Proposal substructure, in bytes
1173  * @return Selected ESN transform, if any
1174  **/
1175 
1176 uint16_t espSelectEsnTransform(IkeContext *context, const IkeProposal *proposal,
1177  size_t proposalLen)
1178 {
1179  //Select the ESN transform to use
1180  return ikeSelectTransform(IKE_TRANSFORM_TYPE_ESN, espSupportedEsnTranforms,
1181  arraysize(espSupportedEsnTranforms), proposal, proposalLen);
1182 }
1183 
1184 
1185 /**
1186  * @brief Select a single proposal
1187  * @param[in] childSa Pointer to the Child SA
1188  * @param[in] payload Pointer to the Security Association payload
1189  * @return Error code
1190  **/
1191 
1193 {
1194  error_t error;
1195  size_t n;
1196  size_t length;
1197  const uint8_t *p;
1198  const IkeProposal *proposal;
1199  const IkeEncAlgo *encAlgo;
1200 
1201  //Clear the set of parameters
1202  childSa->protocol = IPSEC_PROTOCOL_INVALID;
1203  childSa->encAlgoId = IKE_TRANSFORM_ID_INVALID;
1204  childSa->encKeyLen = 0;
1205  childSa->authAlgoId = IKE_TRANSFORM_ID_INVALID;
1206  childSa->esn = IKE_TRANSFORM_ID_INVALID;
1207 
1208  //Retrieve the length of the SA payload
1209  length = ntohs(payload->header.payloadLength);
1210 
1211  //Malformed payload?
1212  if(length < sizeof(IkeSaPayload))
1213  return ERROR_INVALID_MESSAGE;
1214 
1215  //Point to the first byte of the Proposals field
1216  p = payload->proposals;
1217  //Determine the length of the Proposals field
1218  length -= sizeof(IkeSaPayload);
1219 
1220  //Initialize status code
1221  error = ERROR_INVALID_PROPOSAL;
1222 
1223  //The Security Association payload contains one or more Proposal
1224  //substructures
1225  while(1)
1226  {
1227  //Malformed payload?
1228  if(length < sizeof(IkeProposal))
1229  {
1230  //Report an error
1231  error = ERROR_INVALID_MESSAGE;
1232  break;
1233  }
1234 
1235  //Point to the Proposal substructure
1236  proposal = (IkeProposal *) p;
1237 
1238  //The Proposal Length field indicates the length of this proposal,
1239  //including all transforms and attributes that follow
1240  n = ntohs(proposal->proposalLength);
1241 
1242  //Check the length of the proposal
1243  if(n < sizeof(IkeProposal) || n > length)
1244  {
1245  //Report an error
1246  error = ERROR_INVALID_MESSAGE;
1247  break;
1248  }
1249 
1250  //Check protocol identifier
1251  if(proposal->protocolId == IKE_PROTOCOL_ID_ESP)
1252  {
1253  //Valid SPI value?
1254  if(proposal->spiSize == IPSEC_SPI_SIZE &&
1255  osMemcmp(proposal->spi, IPSEC_INVALID_SPI, IPSEC_SPI_SIZE) != 0)
1256  {
1257  //Encryption transform negotiation
1258  encAlgo = espSelectEncTransform(childSa->context, proposal, n);
1259 
1260  //Valid encryption transform?
1261  if(encAlgo != NULL)
1262  {
1263  childSa->encAlgoId = encAlgo->id;
1264  childSa->encKeyLen = encAlgo->keyLen;
1265  }
1266 
1267  //AEAD algorithm?
1268  if(ikeIsAeadEncAlgo(childSa->encAlgoId))
1269  {
1270  //When an authenticated encryption algorithm is selected as the
1271  //encryption algorithm for any SA, an integrity algorithm must
1272  //not be selected for that SA (refer to RFC 5282, section 8)
1273  childSa->authAlgoId = IKE_TRANSFORM_ID_AUTH_NONE;
1274  }
1275  else
1276  {
1277  //Integrity transform negotiation
1278  childSa->authAlgoId = espSelectAuthTransform(childSa->context,
1279  proposal, n);
1280  }
1281 
1282  //ESN transform negotiation
1283  childSa->esn = espSelectEsnTransform(childSa->context, proposal, n);
1284 
1285  //Valid proposal?
1286  if(childSa->encAlgoId != IKE_TRANSFORM_ID_INVALID &&
1287  childSa->authAlgoId != IKE_TRANSFORM_ID_INVALID &&
1288  childSa->esn != IKE_TRANSFORM_ID_INVALID)
1289  {
1290  //Select ESP security protocol
1291  childSa->protocol = IPSEC_PROTOCOL_ESP;
1292 
1293  //The initiator SPI is supplied in the SPI field of the SA
1294  //payload
1295  osMemcpy(childSa->remoteSpi, proposal->spi, proposal->spiSize);
1296 
1297  //Successful negotiation
1298  error = NO_ERROR;
1299  break;
1300  }
1301  }
1302  }
1303 
1304  //Jump to the next proposal
1305  p += n;
1306  length -= n;
1307  }
1308 
1309  //Return status code
1310  return error;
1311 }
1312 
1313 
1314 /**
1315  * @brief Check whether the selected proposal is acceptable
1316  * @param[in] childSa Pointer to the Child SA
1317  * @param[in] payload Pointer to the Security Association payload
1318  * @return Error code
1319  **/
1320 
1322 {
1323  size_t n;
1324  size_t length;
1325  const uint8_t *p;
1326  const IkeProposal *proposal;
1327  const IkeEncAlgo *encAlgo;
1328 
1329  //Clear the set of parameters
1330  childSa->encAlgoId = IKE_TRANSFORM_ID_INVALID;
1331  childSa->encKeyLen = 0;
1332  childSa->authAlgoId = IKE_TRANSFORM_ID_INVALID;
1333  childSa->esn = IKE_TRANSFORM_ID_INVALID;
1334 
1335  //Retrieve the length of the SA payload
1336  length = ntohs(payload->header.payloadLength);
1337 
1338  //Malformed payload?
1339  if(length < sizeof(IkeSaPayload))
1340  return ERROR_INVALID_MESSAGE;
1341 
1342  //Point to the first byte of the Proposals field
1343  p = payload->proposals;
1344  //Determine the length of the Proposals field
1345  length -= sizeof(IkeSaPayload);
1346 
1347  //Malformed payload?
1348  if(length < sizeof(IkeProposal))
1349  return ERROR_INVALID_MESSAGE;
1350 
1351  //Point to the Proposal substructure
1352  proposal = (IkeProposal *) p;
1353 
1354  //The Proposal Length field indicates the length of this proposal,
1355  //including all transforms and attributes that follow
1356  n = ntohs(proposal->proposalLength);
1357 
1358  //The responder must accept a single proposal (refer to RFC 7296,
1359  //section 2.7)
1360  if(n != length)
1361  return ERROR_INVALID_MESSAGE;
1362 
1363  //Check protocol identifier
1364  if(proposal->protocolId != IKE_PROTOCOL_ID_ESP)
1365  return ERROR_INVALID_MESSAGE;
1366 
1367  //During subsequent negotiations, the SPI Size field is equal to the size,
1368  //in octets, of the SPI of the corresponding protocol (4 for ESP and AH)
1369  if(proposal->spiSize != IPSEC_SPI_SIZE)
1370  return ERROR_INVALID_MESSAGE;
1371 
1372  //The SPI value of zero is reserved and must not be sent on the wire (refer
1373  //to RFC 4303, section 2.1)
1374  if(osMemcmp(proposal->spi, IPSEC_INVALID_SPI, IPSEC_SPI_SIZE) == 0)
1375  return ERROR_INVALID_MESSAGE;
1376 
1377  //The responder SPI is supplied in the SPI field of the SA payload
1378  osMemcpy(childSa->remoteSpi, proposal->spi, proposal->spiSize);
1379 
1380  //The accepted cryptographic suite must contain exactly one transform of
1381  //each type included in the proposal (refer to RFC 7296, section 2.7)
1382  if(ikeGetNumTransforms(IKE_TRANSFORM_TYPE_ENCR, proposal, n) != 1 ||
1383  ikeGetNumTransforms(IKE_TRANSFORM_TYPE_ESN, proposal, n) != 1)
1384  {
1385  return ERROR_INVALID_PROPOSAL;
1386  }
1387 
1388  //Get the selected encryption transform
1389  encAlgo = espSelectEncTransform(childSa->context, proposal, n);
1390 
1391  //Valid encryption transform?
1392  if(encAlgo != NULL)
1393  {
1394  childSa->encAlgoId = encAlgo->id;
1395  childSa->encKeyLen = encAlgo->keyLen;
1396  }
1397 
1398  //AEAD algorithm?
1399  if(ikeIsAeadEncAlgo(childSa->encAlgoId))
1400  {
1401  //When an authenticated encryption algorithm is selected as the encryption
1402  //algorithm for any SA, an integrity algorithm must not be selected for
1403  //that SA (refer to RFC 5282, section 8)
1404  if(ikeGetNumTransforms(IKE_TRANSFORM_TYPE_INTEG, proposal, n) != 0)
1405  return ERROR_INVALID_PROPOSAL;
1406 
1407  //AEAD algorithms combine encryption and integrity into a single operation
1408  childSa->authAlgoId = IKE_TRANSFORM_ID_AUTH_NONE;
1409  }
1410  else
1411  {
1412  //Exactly one integrity transform must be included in the proposal
1413  if(ikeGetNumTransforms(IKE_TRANSFORM_TYPE_INTEG, proposal, n) != 1)
1414  return ERROR_INVALID_PROPOSAL;
1415 
1416  //Get the selected integrity transform
1417  childSa->authAlgoId = ikeSelectAuthTransform(childSa->context, proposal,
1418  n);
1419  }
1420 
1421  //Get the selected ESN transform
1422  childSa->esn = espSelectEsnTransform(childSa->context, proposal, n);
1423 
1424  //The initiator of an exchange must check that the accepted offer is
1425  //consistent with one of its proposals, and if not must terminate the
1426  //exchange (refer to RFC 7296, section 3.3.6)
1427  if(childSa->encAlgoId != IKE_TRANSFORM_ID_INVALID &&
1428  childSa->authAlgoId != IKE_TRANSFORM_ID_INVALID &&
1429  childSa->esn != IKE_TRANSFORM_ID_INVALID)
1430  {
1431  return NO_ERROR;
1432  }
1433  else
1434  {
1435  return ERROR_INVALID_PROPOSAL;
1436  }
1437 }
1438 
1439 #endif
@ IKE_TRANSFORM_ID_ENCR_AES_GCM_8
Definition: ike.h:810
@ IKE_TRANSFORM_ID_AUTH_AES_CMAC_96
Definition: ike.h:863
uint_t ikeGetNumTransforms(IkeTransformType transformType, const IkeProposal *proposal, size_t proposalLen)
Get the number of transforms that match a given transform type.
#define IPSEC_SPI_SIZE
Definition: ipsec.h:138
@ IKE_TRANSFORM_ID_AUTH_HMAC_SHA2_384_192
Definition: ike.h:868
@ IKE_TRANSFORM_ID_AUTH_HMAC_SHA1_96
Definition: ike.h:857
#define SHA256_HASH_ALGO
Definition: sha256.h:49
@ IKE_TRANSFORM_ID_ENCR_AES_CCM_16
Definition: ike.h:809
#define SHA1_HASH_ALGO
Definition: sha1.h:49
@ IKE_TRANSFORM_ID_ENCR_AES_CTR
Definition: ike.h:806
@ CIPHER_MODE_CBC
Definition: crypto.h:966
#define SHA512_HASH_ALGO
Definition: sha512.h:49
#define IDEA_BLOCK_SIZE
Definition: idea.h:38
@ IKE_TRANSFORM_ID_ENCR_CAMELLIA_CBC
Definition: ike.h:814
uint8_t p
Definition: ndp.h:300
@ CIPHER_MODE_GCM
Definition: crypto.h:971
@ IKE_TRANSFORM_ID_ENCR_IDEA
Definition: ike.h:799
@ IKE_TRANSFORM_ID_AUTH_HMAC_MD5_96
Definition: ike.h:856
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.
uint8_t numTransforms
Definition: ike.h:1310
@ IKE_TRANSFORM_ID_ESN_NO
No Extended Sequence Numbers.
Definition: ike.h:913
ESP algorithm negotiation.
#define IDEA_CIPHER_ALGO
Definition: idea.h:40
@ IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_8
Definition: ike.h:816
const uint8_t IPSEC_INVALID_SPI[4]
Definition: ipsec_misc.c:40
@ IKE_LAST_SUBSTRUC_LAST
Last proposal/transform substructure.
Definition: ike.h:756
#define osMemcmp(p1, p2, length)
Definition: os_port.h:153
@ IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_16
Definition: ike.h:818
@ ERROR_INVALID_MESSAGE
Definition: error.h:105
IkeTransform
Definition: ike.h:1328
uint16_t ikeSelectTransform(IkeTransformType transformType, const uint16_t *algoList, uint_t algoListLen, const IkeProposal *proposal, size_t proposalLen)
Transform negotiation.
@ CIPHER_MODE_CTR
Definition: crypto.h:969
@ IKE_TRANSFORM_ID_ENCR_CHACHA20_POLY1305
Definition: ike.h:819
@ IKE_ATTR_FORMAT_TV
shortened Type/Value format
Definition: ike.h:925
error_t espSelectSaProposal(IkeChildSaEntry *childSa, const IkeSaPayload *payload)
Select a single proposal.
#define DES3_BLOCK_SIZE
Definition: des3.h:44
@ IPSEC_PROTOCOL_ESP
Definition: ipsec.h:193
@ IKE_TRANSFORM_TYPE_ESN
Extended Sequence Numbers.
Definition: ike.h:784
#define IKE_TRANSFORM_ID_INVALID
#define AES_BLOCK_SIZE
Definition: aes.h:43
@ IKE_TRANSFORM_ID_ENCR_AES_CBC
Definition: ike.h:805
@ IKE_TRANSFORM_ATTR_TYPE_KEY_LEN
Key Length (in bits)
Definition: ike.h:935
#define IkeContext
Definition: ike.h:678
uint16_t espSelectAuthTransform(IkeContext *context, const IkeProposal *proposal, size_t proposalLen)
Integrity transform negotiation.
ESP (IP Encapsulating Security Payload)
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
@ ERROR_INVALID_PROPOSAL
Definition: error.h:300
error_t
Error codes.
Definition: error.h:43
error_t espAddSupportedEncTransforms(IkeContext *context, IkeProposal *proposal, uint8_t **lastSubstruc)
Add the supported encryption transforms to the proposal.
@ ERROR_UNSUPPORTED_ALGO
Definition: error.h:126
error_t espAddSupportedTransforms(IkeContext *context, IkeProposal *proposal, uint8_t **lastSubstruc)
Add the supported ESP transforms to the proposal.
Helper routines for IPsec.
@ IKE_PROTOCOL_ID_ESP
ESP protocol.
Definition: ike.h:770
#define MD5_HASH_ALGO
Definition: md5.h:49
error_t espSelectEncAlgo(IkeChildSaEntry *childSa, uint16_t encAlgoId, size_t encKeyLen)
Select the relevant encryption algorithm.
@ IKE_TRANSFORM_ID_ENCR_AES_GCM_12
Definition: ike.h:811
#define CAMELLIA_CIPHER_ALGO
Definition: camellia.h:40
uint16_t espSelectEsnTransform(IkeContext *context, const IkeProposal *proposal, size_t proposalLen)
ESN transform negotiation.
IkeTransformAttr
Definition: ike.h:1340
uint16_t keyLen
#define DES_CIPHER_ALGO
Definition: des.h:45
uint16_t ikeSelectAuthTransform(IkeContext *context, const IkeProposal *proposal, size_t proposalLen)
Integrity transform negotiation.
error_t espCheckSaProposal(IkeChildSaEntry *childSa, const IkeSaPayload *payload)
Check whether the selected proposal is acceptable.
@ IKE_TRANSFORM_TYPE_ENCR
Encryption Algorithm.
Definition: ike.h:780
uint8_t length
Definition: tcp.h:368
const IkeEncAlgo * espSelectEncTransform(IkeContext *context, const IkeProposal *proposal, size_t proposalLen)
Encryption transform negotiation.
bool_t ikeIsAeadEncAlgo(uint16_t encAlgoId)
Test if the transform ID identifies an AEAD encryption algorithm.
#define SHA384_DIGEST_SIZE
Definition: sha384.h:41
#define MD5_DIGEST_SIZE
Definition: md5.h:45
@ IKE_TRANSFORM_ID_AUTH_HMAC_SHA2_256_128
Definition: ike.h:867
@ IKE_TRANSFORM_ID_ENCR_DES
Definition: ike.h:796
Collection of hash algorithms.
#define ntohs(value)
Definition: cpu_endian.h:421
error_t espAddSupportedAuthTransforms(IkeContext *context, IkeProposal *proposal, uint8_t **lastSubstruc)
Add the supported integrity transforms to the proposal.
#define SHA384_HASH_ALGO
Definition: sha384.h:45
IkeProposal
Definition: ike.h:1312
#define SHA1_DIGEST_SIZE
Definition: sha1.h:45
@ CIPHER_MODE_CCM
Definition: crypto.h:970
@ IKE_TRANSFORM_ID_ENCR_3DES
Definition: ike.h:797
@ IKE_TRANSFORM_ID_ENCR_AES_GCM_16
Definition: ike.h:812
IPsec (IP security)
uint8_t n
uint8_t payload[]
Definition: ipv6.h:286
@ IKE_TRANSFORM_ID_ENCR_AES_CCM_12
Definition: ike.h:808
@ IKE_TRANSFORM_ID_ESN_YES
Extended Sequence Numbers.
Definition: ike.h:914
#define DES_BLOCK_SIZE
Definition: des.h:43
@ IKE_TRANSFORM_ID_ENCR_CAMELLIA_CTR
Definition: ike.h:815
uint16_t transformId
Definition: ike.h:1326
#define CAMELLIA_BLOCK_SIZE
Definition: camellia.h:38
#define AES_CIPHER_ALGO
Definition: aes.h:45
error_t espAddSupportedEsnTransforms(IkeContext *context, IkeProposal *proposal, uint8_t **lastSubstruc)
Add the supported ESN transforms to the proposal.
bool_t ikeIsVariableLengthKeyEncAlgo(uint16_t encAlgoId)
Test if the transform ID identifies a variable-length key encryption algorithm.
@ CIPHER_MODE_CHACHA20_POLY1305
Definition: crypto.h:972
error_t espSelectAuthAlgo(IkeChildSaEntry *childSa, uint16_t authAlgoId)
Select the relevant MAC algorithm.
#define DES3_CIPHER_ALGO
Definition: des3.h:46
@ IKE_TRANSFORM_ID_AUTH_HMAC_SHA2_512_256
Definition: ike.h:869
unsigned int uint_t
Definition: compiler_port.h:50
@ IKE_TRANSFORM_ID_AUTH_NONE
Definition: ike.h:855
#define SHA256_DIGEST_SIZE
Definition: sha256.h:45
uint16_t id
#define IkeChildSaEntry
Definition: ike.h:686
@ IPSEC_PROTOCOL_INVALID
Definition: ipsec.h:191
#define SHA512_DIGEST_SIZE
Definition: sha512.h:45
IKEv2 algorithm negotiation.
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
IkeSaPayload
Definition: ike.h:1295
#define arraysize(a)
Definition: os_port.h:71
@ IKE_TRANSFORM_ID_ENCR_CAMELLIA_CCM_12
Definition: ike.h:817
@ IKE_TRANSFORM_ID_ENCR_AES_CCM_8
Definition: ike.h:807
@ IKE_TRANSFORM_TYPE_INTEG
Integrity Algorithm.
Definition: ike.h:782