ipsec_misc.c
Go to the documentation of this file.
1 /**
2  * @file ipsec_misc.c
3  * @brief Helper routines for IPsec
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 //Dependencies
32 #include "ipsec/ipsec.h"
33 #include "ipsec/ipsec_misc.h"
34 #include "debug.h"
35 
36 //Check IPsec library configuration
37 #if (IPSEC_SUPPORT == ENABLED)
38 
39 //Invalid SPI value
40 const uint8_t IPSEC_INVALID_SPI[4] = {0};
41 
42 
43 /**
44  * @brief Search the SPD database for a matching entry
45  * @param[in] context Pointer to the IPsec context
46  * @param[in] policyAction Policy action
47  * @param[in] selector Pointer to the IPsec selector
48  * @return Pointer to the matching SPD entry, if any
49  **/
50 
52  IpsecPolicyAction policyAction, const IpsecSelector *selector)
53 {
54  uint_t i;
55  IpsecSelector temp;
56  IpsecSpdEntry *entry;
57 
58  //Valid parameters?
59  if(context != NULL && selector != NULL)
60  {
61  //Loop through SPD entries
62  for(i = 0; i < context->numSpdEntries; i++)
63  {
64  //Point to the current SPD entry
65  entry = &context->spd[i];
66 
67  //Valid entry?
69  {
70  //Matching policy action
71  if(policyAction == IPSEC_POLICY_ACTION_INVALID ||
72  entry->policyAction == policyAction)
73  {
74  //Check if there is a non-null intersection between the values of
75  //the selectors
76  if(ipsecIntersectSelectors(&entry->selector, selector, &temp))
77  {
78  return entry;
79  }
80  }
81  }
82  }
83  }
84 
85  //No matching entry in the SPD database
86  return NULL;
87 }
88 
89 
90 /**
91  * @brief Allocate a new entry in the SAD database
92  * @param[in] context Pointer to the IPsec context
93  * @return Index of the newly allocated entry
94  **/
95 
97 {
98  uint_t i;
99  IpsecSadEntry *sa;
100 
101  //Valid parameters?
102  if(context != NULL)
103  {
104  //Loop through SAD entries
105  for(i = 0; i < context->numSadEntries; i++)
106  {
107  //Point to the current SAD entry
108  sa = &context->sad[i];
109 
110  //Check whether the current entry is available for use
111  if(sa->state == IPSEC_SA_STATE_CLOSED)
112  {
113  //Default state
114  sa->state = IPSEC_SA_STATE_RESERVED;
115  //Return the index of the newly allocated entry
116  return i;
117  }
118  }
119  }
120 
121  //Failed to allocate a new entry in the SAD database
122  return -1;
123 }
124 
125 
126 /**
127  * @brief Search the SAD database for a matching inbound entry
128  * @param[in] context Pointer to the IPsec context
129  * @param[in] protocol Security protocol (AH or ESP)
130  * @param[in] spi Security parameter index
131  * @return Pointer to the matching SAD entry, if any
132  **/
133 
135  IpsecProtocol protocol, uint32_t spi)
136 {
137  uint_t i;
138  IpsecSadEntry *sa;
139 
140  //Valid IPsec context?
141  if(context != NULL)
142  {
143  //Loop through SAD entries
144  for(i = 0; i < context->numSadEntries; i++)
145  {
146  //Point to the current SAD entry
147  sa = &context->sad[i];
148 
149  //Inbound entry?
150  if(sa->state == IPSEC_SA_STATE_OPEN &&
151  sa->direction == IPSEC_DIR_INBOUND)
152  {
153  //Matching protocol and SPI?
154  if(sa->protocol == protocol && sa->spi == spi)
155  {
156  return sa;
157  }
158  }
159  }
160  }
161 
162  //No matching entry in the SAD database
163  return NULL;
164 }
165 
166 
167 /**
168  * @brief Search the SAD database for a matching outbound entry
169  * @param[in] context Pointer to the IPsec context
170  * @param[in] selector Pointer to the IPsec selector
171  * @return Pointer to the SAD entry, if any
172  **/
173 
175  const IpsecSelector *selector)
176 {
177  uint_t i;
178  systime_t time;
179  IpsecSadEntry *sa;
180  IpsecSadEntry *bestSa;
181 
182  //Initialize pointer
183  bestSa = NULL;
184 
185  //Get current time
186  time = osGetSystemTime();
187 
188  //Valid parameters?
189  if(context != NULL && selector != NULL)
190  {
191  //Loop through SAD entries
192  for(i = 0; i < context->numSadEntries; i++)
193  {
194  //Point to the current SAD entry
195  sa = &context->sad[i];
196 
197  //Outbound entry?
198  if(sa->state != IPSEC_SA_STATE_CLOSED &&
199  sa->direction == IPSEC_DIR_OUTBOUND)
200  {
201  //Matching traffic selector?
202  if(ipsecIsSubsetSelector(selector, &sa->selector))
203  {
204  if(bestSa == NULL)
205  {
206  bestSa = sa;
207  }
208  else if(sa->state == IPSEC_SA_STATE_OPEN &&
209  bestSa->state == IPSEC_SA_STATE_RESERVED)
210  {
211  bestSa = sa;
212  }
213  else if(sa->state == IPSEC_SA_STATE_RESERVED &&
214  bestSa->state == IPSEC_SA_STATE_OPEN)
215  {
216  }
217  else if((time - sa->lifetimeStart) < (time - bestSa->lifetimeStart))
218  {
219  bestSa = sa;
220  }
221  else
222  {
223  }
224  }
225  }
226  }
227  }
228 
229  //Return a pointer to the SAD entry
230  return bestSa;
231 }
232 
233 
234 /**
235  * @brief Find PAD entry that matches the specified identification data
236  * @param[in] context Pointer to the IPsec context
237  * @param[in] idType ID type
238  * @param[in] id Pointer to the identification data
239  * @param[in] idLen Length of the identification data, in bytes
240  * @return Pointer to the matching PAD entry, if any
241  **/
242 
244  const uint8_t *id, size_t idLen)
245 {
246  uint_t i;
247  IpsecPadEntry *entry;
248 
249  //Valid parameters
250  if(context != NULL && id != NULL)
251  {
252  //Loop through PAD entries
253  for(i = 0; i < context->numPadEntries; i++)
254  {
255  //Point to the current PAD entry
256  entry = &context->pad[i];
257 
258  //Valid authentication method and ID type?
259  if(entry->authMethod == IPSEC_AUTH_METHOD_IKEV2 &&
260  entry->idType == idType)
261  {
262  //Fully-qualified domain name?
264  {
265  //Compare DNS names
266  if(idLen == entry->idLen &&
267  osMemcmp(id, entry->id.fqdn, idLen) == 0)
268  {
269  //A matching PAD entry has been found
270  return entry;
271  }
272  }
273  //RFC 822 email address?
275  {
276  //Compare email addresses
277  if(idLen == entry->idLen &&
278  osMemcmp(id, entry->id.email, idLen) == 0)
279  {
280  //A matching PAD entry has been found
281  return entry;
282  }
283  }
284  //X.500 Distinguished Name?
285  else if(idType == IPSEC_ID_TYPE_DN)
286  {
287  //Compare DNs
288  if(idLen == entry->idLen &&
289  osMemcmp(id, entry->id.dn, idLen) == 0)
290  {
291  //A matching PAD entry has been found
292  return entry;
293  }
294  }
295  //Key ID?
296  else if(idType == IPSEC_ID_TYPE_KEY_ID)
297  {
298  //Compare key IDs
299  if(idLen == entry->idLen &&
300  osMemcmp(id, entry->id.keyId, idLen) == 0)
301  {
302  //A matching PAD entry has been found
303  return entry;
304  }
305  }
306 #if (IPV4_SUPPORT == ENABLED)
307  //IPv4 address?
308  else if(idType == IPSEC_ID_TYPE_IPV4_ADDR)
309  {
310  //For IPv4 addresses, the same address range syntax used for SPD
311  //entries must be supported. This allows specification of an
312  //individual address, an address prefix, or an arbitrary address
313  //range (refer to RFC 4301, section 4.4.3.1)
314  if(idLen == sizeof(Ipv4Addr) &&
315  osMemcmp(id, &entry->id.ipAddr.start.ipv4Addr, 4) >= 0 &&
316  osMemcmp(id, &entry->id.ipAddr.end.ipv4Addr, 4) <= 0)
317  {
318  //A matching PAD entry has been found
319  return entry;
320  }
321  }
322 #endif
323 #if (IPV6_SUPPORT == ENABLED)
324  //IPv6 address?
325  else if(idType == IPSEC_ID_TYPE_IPV6_ADDR)
326  {
327  //For IPv6 addresses, the same address range syntax used for SPD
328  //entries must be supported. This allows specification of an
329  //individual address, an address prefix, or an arbitrary address
330  //range (refer to RFC 4301, section 4.4.3.1)
331  if(idLen == sizeof(Ipv6Addr) &&
332  osMemcmp(id, &entry->id.ipAddr.start.ipv6Addr, 16) >= 0 &&
333  osMemcmp(id, &entry->id.ipAddr.end.ipv6Addr, 16) <= 0)
334  {
335  //A matching PAD entry has been found
336  return entry;
337  }
338  }
339 #endif
340  //Unknown ID type?
341  else
342  {
343  //Just for sanity
344  }
345  }
346  }
347  }
348 
349  //The specified identification data does not match any PAD entry
350  return NULL;
351 }
352 
353 
354 /**
355  * @brief Test if a selector is a subset of another selector
356  * @param[in] selector1 Pointer to the first IPsec selector
357  * @param[in] selector2 Pointer to the second IPsec selector
358  * @return TRUE is the first selector is a subset of the second selector,
359  * else FALSE
360  **/
361 
363  const IpsecSelector *selector2)
364 {
365 #if (IPV4_SUPPORT == ENABLED)
366  //IPv4 address range?
367  if(selector1->localIpAddr.start.length == sizeof(Ipv4Addr) &&
368  selector1->localIpAddr.end.length == sizeof(Ipv4Addr) &&
369  selector1->remoteIpAddr.start.length == sizeof(Ipv4Addr) &&
370  selector1->remoteIpAddr.end.length == sizeof(Ipv4Addr) &&
371  selector2->localIpAddr.start.length == sizeof(Ipv4Addr) &&
372  selector2->localIpAddr.end.length == sizeof(Ipv4Addr) &&
373  selector2->remoteIpAddr.start.length == sizeof(Ipv4Addr) &&
374  selector2->remoteIpAddr.end.length == sizeof(Ipv4Addr))
375  {
376  //Check whether the first selector is valid
377  if(ntohl(selector1->localIpAddr.start.ipv4Addr) >
378  ntohl(selector1->localIpAddr.end.ipv4Addr))
379  {
380  return FALSE;
381  }
382 
383  if(ntohl(selector1->remoteIpAddr.start.ipv4Addr) >
384  ntohl(selector1->remoteIpAddr.end.ipv4Addr))
385  {
386  return FALSE;
387  }
388 
389  //Check whether the second selector is valid
390  if(ntohl(selector2->localIpAddr.start.ipv4Addr) >
391  ntohl(selector2->localIpAddr.end.ipv4Addr))
392  {
393  return FALSE;
394  }
395 
396  if(ntohl(selector2->remoteIpAddr.start.ipv4Addr) >
397  ntohl(selector2->remoteIpAddr.end.ipv4Addr))
398  {
399  return FALSE;
400  }
401 
402  //Compare local IP address ranges
403  if(ntohl(selector1->localIpAddr.start.ipv4Addr) <
404  ntohl(selector2->localIpAddr.start.ipv4Addr))
405  {
406  return FALSE;
407  }
408 
409  if(ntohl(selector1->localIpAddr.end.ipv4Addr) >
410  ntohl(selector2->localIpAddr.end.ipv4Addr))
411  {
412  return FALSE;
413  }
414 
415  //Compare remote IP address ranges
416  if(ntohl(selector1->remoteIpAddr.start.ipv4Addr) <
417  ntohl(selector2->remoteIpAddr.start.ipv4Addr))
418  {
419  return FALSE;
420  }
421 
422  if(ntohl(selector1->remoteIpAddr.end.ipv4Addr) >
423  ntohl(selector2->remoteIpAddr.end.ipv4Addr))
424  {
425  return FALSE;
426  }
427  }
428  else
429 #endif
430 #if (IPV6_SUPPORT == ENABLED)
431  //IPv6 address range?
432  if(selector1->localIpAddr.start.length == sizeof(Ipv6Addr) &&
433  selector1->localIpAddr.end.length == sizeof(Ipv6Addr) &&
434  selector1->remoteIpAddr.start.length == sizeof(Ipv6Addr) &&
435  selector1->remoteIpAddr.end.length == sizeof(Ipv6Addr) &&
436  selector2->localIpAddr.start.length == sizeof(Ipv6Addr) &&
437  selector2->localIpAddr.end.length == sizeof(Ipv6Addr) &&
438  selector2->remoteIpAddr.start.length == sizeof(Ipv6Addr) &&
439  selector2->remoteIpAddr.end.length == sizeof(Ipv6Addr))
440  {
441  return FALSE;
442  }
443  else
444 #endif
445  //Unknown Traffic Selector type?
446  {
447  return FALSE;
448  }
449 
450  //Check Next Layer Protocol value
451  if(selector2->nextProtocol == IPSEC_PROTOCOL_ANY)
452  {
453  //ANY is a wildcard that matches any value protocol value
454  }
455  else
456  {
457  //Compare Next Layer Protocol value
458  if(selector1->nextProtocol != selector2->nextProtocol)
459  {
460  return FALSE;
461  }
462  }
463 
464  //Check local port ranges
465  if(selector1->localPort.start == IPSEC_PORT_START_OPAQUE &&
466  selector1->localPort.end == IPSEC_PORT_END_OPAQUE &&
467  selector2->localPort.start == IPSEC_PORT_START_OPAQUE &&
468  selector2->localPort.end == IPSEC_PORT_END_OPAQUE)
469  {
470  //OPAQUE indicates that the corresponding selector field is not
471  //available for examination
472  }
473  else if(selector1->localPort.start == IPSEC_PORT_START_OPAQUE &&
474  selector1->localPort.end == IPSEC_PORT_END_OPAQUE &&
475  selector2->localPort.start == IPSEC_PORT_START_ANY &&
476  selector2->localPort.end == IPSEC_PORT_END_ANY)
477  {
478  //The ANY value encompasses the OPAQUE value (refer to RFC 4301,
479  //section 4.4.1)
480  }
481  else
482  {
483  //Check whether the selectors are valid
484  if(selector1->localPort.start > selector1->localPort.end ||
485  selector2->localPort.start > selector2->localPort.end)
486  {
487  return FALSE;
488  }
489 
490  //Compare local port ranges
491  if(selector1->localPort.start < selector2->localPort.start ||
492  selector1->localPort.end > selector2->localPort.end)
493  {
494  return FALSE;
495  }
496  }
497 
498  //Check remote port ranges
499  if(selector1->remotePort.start == IPSEC_PORT_START_OPAQUE &&
500  selector1->remotePort.end == IPSEC_PORT_END_OPAQUE &&
501  selector2->remotePort.start == IPSEC_PORT_START_OPAQUE &&
502  selector2->remotePort.end == IPSEC_PORT_END_OPAQUE)
503  {
504  //OPAQUE indicates that the corresponding selector field is not
505  //available for examination
506  }
507  else if(selector1->remotePort.start == IPSEC_PORT_START_OPAQUE &&
508  selector1->remotePort.end == IPSEC_PORT_END_OPAQUE &&
509  selector2->remotePort.start == IPSEC_PORT_START_ANY &&
510  selector2->remotePort.end == IPSEC_PORT_END_ANY)
511  {
512  //The ANY value encompasses the OPAQUE value (refer to RFC 4301,
513  //section 4.4.1)
514  }
515  else
516  {
517  //Check whether the selectors are valid
518  if(selector1->remotePort.start > selector1->remotePort.end ||
519  selector2->remotePort.start > selector2->remotePort.end)
520  {
521  return FALSE;
522  }
523 
524  //Compare remote port ranges
525  if(selector1->remotePort.start < selector2->remotePort.start ||
526  selector1->remotePort.end > selector2->remotePort.end)
527  {
528  return FALSE;
529  }
530  }
531 
532  //The first selector is a subset of the second selector
533  return TRUE;
534 }
535 
536 
537 /**
538  * @brief Calculate the intersection of two selectors
539  * @param[in] selector1 Pointer to the first IPsec selector
540  * @param[in] selector2 Pointer to the second IPsec selector
541  * @param[out] result Resulting IPsec selector
542  * @return TRUE if there is a non-null intersection, else FALSE
543  **/
544 
546  const IpsecSelector *selector2, IpsecSelector *result)
547 {
548 #if (IPV4_SUPPORT == ENABLED)
549  //IPv4 address range?
550  if(selector1->localIpAddr.start.length == sizeof(Ipv4Addr) &&
551  selector1->localIpAddr.end.length == sizeof(Ipv4Addr) &&
552  selector1->remoteIpAddr.start.length == sizeof(Ipv4Addr) &&
553  selector1->remoteIpAddr.end.length == sizeof(Ipv4Addr) &&
554  selector2->localIpAddr.start.length == sizeof(Ipv4Addr) &&
555  selector2->localIpAddr.end.length == sizeof(Ipv4Addr) &&
556  selector2->remoteIpAddr.start.length == sizeof(Ipv4Addr) &&
557  selector2->remoteIpAddr.end.length == sizeof(Ipv4Addr))
558  {
559  //Check whether the first selector is valid
560  if(ntohl(selector1->localIpAddr.start.ipv4Addr) >
561  ntohl(selector1->localIpAddr.end.ipv4Addr))
562  {
563  return FALSE;
564  }
565 
566  if(ntohl(selector1->remoteIpAddr.start.ipv4Addr) >
567  ntohl(selector1->remoteIpAddr.end.ipv4Addr))
568  {
569  return FALSE;
570  }
571 
572  //Check whether the second selector is valid
573  if(ntohl(selector2->localIpAddr.start.ipv4Addr) >
574  ntohl(selector2->localIpAddr.end.ipv4Addr))
575  {
576  return FALSE;
577  }
578 
579  if(ntohl(selector2->remoteIpAddr.start.ipv4Addr) >
580  ntohl(selector2->remoteIpAddr.end.ipv4Addr))
581  {
582  return FALSE;
583  }
584 
585  //Check local IP address ranges
586  if(ntohl(selector1->localIpAddr.start.ipv4Addr) >
587  ntohl(selector2->localIpAddr.end.ipv4Addr))
588  {
589  return FALSE;
590  }
591 
592  if(ntohl(selector1->localIpAddr.end.ipv4Addr) <
593  ntohl(selector2->localIpAddr.start.ipv4Addr))
594  {
595  return FALSE;
596  }
597 
598  //Calculate the intersection of the local IP address ranges
599  result->localIpAddr.start.length = sizeof(Ipv4Addr);
600 
601  result->localIpAddr.start.ipv4Addr = htonl(MAX(
602  ntohl(selector1->localIpAddr.start.ipv4Addr),
603  ntohl(selector2->localIpAddr.start.ipv4Addr)));
604 
605  result->localIpAddr.end.length = sizeof(Ipv4Addr);
606 
607  result->localIpAddr.end.ipv4Addr = htonl(MIN(
608  ntohl(selector1->localIpAddr.end.ipv4Addr),
609  ntohl(selector2->localIpAddr.end.ipv4Addr)));
610 
611  //Check remote IP address ranges
612  if(ntohl(selector1->remoteIpAddr.start.ipv4Addr) >
613  ntohl(selector2->remoteIpAddr.end.ipv4Addr))
614  {
615  return FALSE;
616  }
617 
618  if(ntohl(selector1->remoteIpAddr.end.ipv4Addr) <
619  ntohl(selector2->remoteIpAddr.start.ipv4Addr))
620  {
621  return FALSE;
622  }
623 
624  //Calculate the intersection of the remote IP address ranges
625  result->remoteIpAddr.start.length = sizeof(Ipv4Addr);
626 
627  result->remoteIpAddr.start.ipv4Addr = htonl(MAX(
628  ntohl(selector1->remoteIpAddr.start.ipv4Addr),
629  ntohl(selector2->remoteIpAddr.start.ipv4Addr)));
630 
631  result->remoteIpAddr.end.length = sizeof(Ipv4Addr);
632 
633  result->remoteIpAddr.end.ipv4Addr = htonl(MIN(
634  ntohl(selector1->remoteIpAddr.end.ipv4Addr),
635  ntohl(selector2->remoteIpAddr.end.ipv4Addr)));
636  }
637  else
638 #endif
639 #if (IPV6_SUPPORT == ENABLED)
640  //IPv6 address range?
641  if(selector1->localIpAddr.start.length == sizeof(Ipv6Addr) &&
642  selector1->localIpAddr.end.length == sizeof(Ipv6Addr) &&
643  selector1->remoteIpAddr.start.length == sizeof(Ipv6Addr) &&
644  selector1->remoteIpAddr.end.length == sizeof(Ipv6Addr) &&
645  selector2->localIpAddr.start.length == sizeof(Ipv6Addr) &&
646  selector2->localIpAddr.end.length == sizeof(Ipv6Addr) &&
647  selector2->remoteIpAddr.start.length == sizeof(Ipv6Addr) &&
648  selector2->remoteIpAddr.end.length == sizeof(Ipv6Addr))
649  {
650  return FALSE;
651  }
652  else
653 #endif
654  //Unknown Traffic Selector type?
655  {
656  return FALSE;
657  }
658 
659  //Check Next Layer Protocol values
660  if(selector1->nextProtocol == IPSEC_PROTOCOL_ANY)
661  {
662  //ANY is a wildcard that matches any value protocol value
663  result->nextProtocol = selector2->nextProtocol;
664  }
665  else if(selector2->nextProtocol == IPSEC_PROTOCOL_ANY)
666  {
667  //ANY is a wildcard that matches any value protocol value
668  result->nextProtocol = selector1->nextProtocol;
669  }
670  else if(selector1->nextProtocol == selector2->nextProtocol)
671  {
672  result->nextProtocol = selector1->nextProtocol;
673  }
674  else
675  {
676  return FALSE;
677  }
678 
679  //Check local port ranges
680  if(selector1->localPort.start == IPSEC_PORT_START_OPAQUE &&
681  selector1->localPort.end == IPSEC_PORT_END_OPAQUE &&
682  selector2->localPort.start == IPSEC_PORT_START_OPAQUE &&
683  selector2->localPort.end == IPSEC_PORT_END_OPAQUE)
684  {
685  //OPAQUE indicates that the corresponding selector field is not
686  //available for examination
689  }
690  else if(selector1->localPort.start == IPSEC_PORT_START_OPAQUE &&
691  selector1->localPort.end == IPSEC_PORT_END_OPAQUE &&
692  selector2->localPort.start == IPSEC_PORT_START_ANY &&
693  selector2->localPort.end == IPSEC_PORT_END_ANY)
694  {
695  //The ANY value encompasses the OPAQUE value (refer to RFC 4301,
696  //section 4.4.1)
699  }
700  else if(selector1->localPort.start == IPSEC_PORT_START_ANY &&
701  selector1->localPort.end == IPSEC_PORT_END_ANY &&
702  selector2->localPort.start == IPSEC_PORT_START_OPAQUE &&
703  selector2->localPort.end == IPSEC_PORT_END_OPAQUE)
704  {
705  //The ANY value encompasses the OPAQUE value (refer to RFC 4301,
706  //section 4.4.1)
709  }
710  else
711  {
712  //Check whether the selectors are valid
713  if(selector1->localPort.start > selector1->localPort.end ||
714  selector2->localPort.start > selector2->localPort.end)
715  {
716  return FALSE;
717  }
718 
719  //Check local port ranges
720  if(selector1->localPort.start > selector2->localPort.end ||
721  selector1->localPort.end < selector2->localPort.start)
722  {
723  return FALSE;
724  }
725 
726  //Calculate the intersection of the local port ranges
727  result->localPort.start = MAX(selector1->localPort.start,
728  selector2->localPort.start);
729 
730  result->localPort.end = MIN(selector1->localPort.end,
731  selector2->localPort.end);
732  }
733 
734  //Check remote port ranges
735  if(selector1->remotePort.start == IPSEC_PORT_START_OPAQUE &&
736  selector1->remotePort.end == IPSEC_PORT_END_OPAQUE &&
737  selector2->remotePort.start == IPSEC_PORT_START_OPAQUE &&
738  selector2->remotePort.end == IPSEC_PORT_END_OPAQUE)
739  {
740  //OPAQUE indicates that the corresponding selector field is not
741  //available for examination
744  }
745  else if(selector1->remotePort.start == IPSEC_PORT_START_OPAQUE &&
746  selector1->remotePort.end == IPSEC_PORT_END_OPAQUE &&
747  selector2->remotePort.start == IPSEC_PORT_START_ANY &&
748  selector2->remotePort.end == IPSEC_PORT_END_ANY)
749  {
750  //The ANY value encompasses the OPAQUE value (refer to RFC 4301,
751  //section 4.4.1)
754  }
755  else if(selector1->remotePort.start == IPSEC_PORT_START_ANY &&
756  selector1->remotePort.end == IPSEC_PORT_END_ANY &&
757  selector2->remotePort.start == IPSEC_PORT_START_OPAQUE &&
758  selector2->remotePort.end == IPSEC_PORT_END_OPAQUE)
759  {
760  //The ANY value encompasses the OPAQUE value (refer to RFC 4301,
761  //section 4.4.1)
764  }
765  else
766  {
767  //Check whether the selectors are valid
768  if(selector1->remotePort.start > selector1->remotePort.end ||
769  selector2->remotePort.start > selector2->remotePort.end)
770  {
771  return FALSE;
772  }
773 
774  //Check remote port ranges
775  if(selector1->remotePort.start > selector2->remotePort.end ||
776  selector1->remotePort.end < selector2->remotePort.start)
777  {
778  return FALSE;
779  }
780 
781  //Calculate the intersection of the remote port ranges
782  result->remotePort.start = MAX(selector1->remotePort.start,
783  selector2->remotePort.start);
784 
785  result->remotePort.end = MIN(selector1->remotePort.end,
786  selector2->remotePort.end);
787  }
788 
789  //Return TRUE if there is a non-null intersection
790  return TRUE;
791 }
792 
793 
794 /**
795  * @brief Derive SAD selector from SPD entry and triggering packet
796  * @param[in] spdEntry Pointer to the SPD entry
797  * @param[in] packet Triggering packet
798  * @param[out] selector SAD selector
799  * @return Error code
800  **/
801 
803  const IpsecPacketInfo *packet, IpsecSelector *selector)
804 {
805  //Select local IP address range
806  if((spdEntry->pfpFlags & IPSEC_PFP_FLAG_LOCAL_ADDR) != 0)
807  {
808  selector->localIpAddr.start = packet->localIpAddr;
809  selector->localIpAddr.end = packet->localIpAddr;
810  }
811  else
812  {
813  selector->localIpAddr.start = spdEntry->selector.localIpAddr.start;
814  selector->localIpAddr.end = spdEntry->selector.localIpAddr.end;
815  }
816 
817  //Select remote IP address range
818  if((spdEntry->pfpFlags & IPSEC_PFP_FLAG_REMOTE_ADDR) != 0)
819  {
820  selector->remoteIpAddr.start = packet->remoteIpAddr;
821  selector->remoteIpAddr.end = packet->remoteIpAddr;
822  }
823  else
824  {
825  selector->remoteIpAddr.start = spdEntry->selector.remoteIpAddr.start;
826  selector->remoteIpAddr.end = spdEntry->selector.remoteIpAddr.end;
827  }
828 
829  //Select Next Layer Protocol value
830  if((spdEntry->pfpFlags & IPSEC_PFP_FLAG_NEXT_PROTOCOL) != 0)
831  {
832  selector->nextProtocol = packet->nextProtocol;
833  }
834  else
835  {
836  selector->nextProtocol = spdEntry->selector.nextProtocol;
837  }
838 
839  //Select local port range
840  if((spdEntry->pfpFlags & IPSEC_PFP_FLAG_LOCAL_PORT) != 0)
841  {
842  selector->localPort.start = packet->localPort;
843  selector->localPort.end = packet->localPort;
844  }
845  else
846  {
847  selector->localPort.start = spdEntry->selector.localPort.start;
848  selector->localPort.end = spdEntry->selector.localPort.end;
849  }
850 
851  //Select remote port range
852  if((spdEntry->pfpFlags & IPSEC_PFP_FLAG_REMOTE_PORT) != 0)
853  {
854  selector->remotePort.start = packet->remotePort;
855  selector->remotePort.end = packet->remotePort;
856  }
857  else
858  {
859  selector->remotePort.start = spdEntry->selector.remotePort.start;
860  selector->remotePort.end = spdEntry->selector.remotePort.end;
861  }
862 
863  //Successful processing
864  return NO_ERROR;
865 }
866 
867 #endif
uint32_t spi
Definition: ah.h:143
signed int int_t
Definition: compiler_port.h:49
unsigned int uint_t
Definition: compiler_port.h:50
int bool_t
Definition: compiler_port.h:53
#define ntohl(value)
Definition: cpu_endian.h:422
#define htonl(value)
Definition: cpu_endian.h:414
Debugging facilities.
uint32_t time
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t idType
Definition: ike.h:1363
IPsec (IP security)
#define IPSEC_PORT_START_OPAQUE
Definition: ipsec.h:148
#define IpsecSadEntry
Definition: ipsec.h:36
#define IPSEC_PORT_END_ANY
Definition: ipsec.h:145
IpsecPolicyAction
Policy action.
Definition: ipsec.h:229
@ IPSEC_POLICY_ACTION_INVALID
Definition: ipsec.h:230
@ IPSEC_SA_STATE_RESERVED
Definition: ipsec.h:270
@ IPSEC_SA_STATE_CLOSED
Definition: ipsec.h:269
@ IPSEC_SA_STATE_OPEN
Definition: ipsec.h:271
IpsecProtocol
Security protocols.
Definition: ipsec.h:190
#define IPSEC_PROTOCOL_ANY
Definition: ipsec.h:141
@ IPSEC_AUTH_METHOD_IKEV2
Definition: ipsec.h:180
@ IPSEC_PFP_FLAG_LOCAL_PORT
Definition: ipsec.h:246
@ IPSEC_PFP_FLAG_REMOTE_PORT
Definition: ipsec.h:247
@ IPSEC_PFP_FLAG_LOCAL_ADDR
Definition: ipsec.h:243
@ IPSEC_PFP_FLAG_REMOTE_ADDR
Definition: ipsec.h:244
@ IPSEC_PFP_FLAG_NEXT_PROTOCOL
Definition: ipsec.h:245
#define IPSEC_PORT_END_OPAQUE
Definition: ipsec.h:149
@ IPSEC_DIR_OUTBOUND
Definition: ipsec.h:168
@ IPSEC_DIR_INBOUND
Definition: ipsec.h:167
#define IPSEC_PORT_START_ANY
Definition: ipsec.h:144
@ IPSEC_ID_TYPE_KEY_ID
Key ID.
Definition: ipsec.h:220
@ IPSEC_ID_TYPE_IPV6_ADDR
IPv6 address.
Definition: ipsec.h:218
@ IPSEC_ID_TYPE_RFC822_ADDR
RFC 822 email address.
Definition: ipsec.h:217
@ IPSEC_ID_TYPE_IPV4_ADDR
IPv4 address.
Definition: ipsec.h:215
@ IPSEC_ID_TYPE_FQDN
Fully-qualified domain name.
Definition: ipsec.h:216
@ IPSEC_ID_TYPE_DN
X.500 distinguished name.
Definition: ipsec.h:219
error_t ipsecDeriveSelector(const IpsecSpdEntry *spdEntry, const IpsecPacketInfo *packet, IpsecSelector *selector)
Derive SAD selector from SPD entry and triggering packet.
Definition: ipsec_misc.c:802
int_t ipsecAllocateSadEntry(IpsecContext *context)
Allocate a new entry in the SAD database.
Definition: ipsec_misc.c:96
IpsecPadEntry * ipsecFindPadEntry(IpsecContext *context, uint8_t idType, const uint8_t *id, size_t idLen)
Find PAD entry that matches the specified identification data.
Definition: ipsec_misc.c:243
IpsecSadEntry * ipsecFindInboundSadEntry(IpsecContext *context, IpsecProtocol protocol, uint32_t spi)
Search the SAD database for a matching inbound entry.
Definition: ipsec_misc.c:134
bool_t ipsecIntersectSelectors(const IpsecSelector *selector1, const IpsecSelector *selector2, IpsecSelector *result)
Calculate the intersection of two selectors.
Definition: ipsec_misc.c:545
const uint8_t IPSEC_INVALID_SPI[4]
Definition: ipsec_misc.c:40
IpsecSpdEntry * ipsecFindSpdEntry(IpsecContext *context, IpsecPolicyAction policyAction, const IpsecSelector *selector)
Search the SPD database for a matching entry.
Definition: ipsec_misc.c:51
bool_t ipsecIsSubsetSelector(const IpsecSelector *selector1, const IpsecSelector *selector2)
Test if a selector is a subset of another selector.
Definition: ipsec_misc.c:362
IpsecSadEntry * ipsecFindOutboundSadEntry(IpsecContext *context, const IpsecSelector *selector)
Search the SAD database for a matching outbound entry.
Definition: ipsec_misc.c:174
Helper routines for IPsec.
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:267
uint8_t protocol
Definition: ipv4.h:296
Ipv6Addr
Definition: ipv6.h:251
#define MIN(a, b)
Definition: os_port.h:63
#define osMemcmp(p1, p2, length)
Definition: os_port.h:153
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define MAX(a, b)
Definition: os_port.h:67
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t systime_t
System time.
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
uint_t numSpdEntries
Number of entries in the SPD database.
Definition: ipsec.h:438
IpsecSadEntry * sad
Security Association Database (SAD)
Definition: ipsec.h:439
IpsecPadEntry * pad
Peer Authorization Database (PAD)
Definition: ipsec.h:441
uint_t numSadEntries
Number of entries in the SAD database.
Definition: ipsec.h:440
uint_t numPadEntries
Number of entries in the PAD database.
Definition: ipsec.h:442
IpsecSpdEntry * spd
Security Policy Database (SPD)
Definition: ipsec.h:437
IP packet information.
Definition: ipsec.h:316
IpAddr remoteIpAddr
Remote IP address.
Definition: ipsec.h:318
IpAddr localIpAddr
Local IP address.
Definition: ipsec.h:317
uint16_t remotePort
Remote port.
Definition: ipsec.h:321
uint8_t nextProtocol
Next layer protocol.
Definition: ipsec.h:319
uint16_t localPort
Local port.
Definition: ipsec.h:320
Peer Authorization Database (PAD) entry.
Definition: ipsec.h:400
IpsecId id
ID.
Definition: ipsec.h:403
IpsecAuthMethod authMethod
Authentication method (IKEv1, IKEv2, KINK)
Definition: ipsec.h:401
IpsecIdType idType
ID type.
Definition: ipsec.h:402
size_t idLen
Length of the ID, in bytes.
Definition: ipsec.h:404
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
Security Policy Database (SPD) entry.
Definition: ipsec.h:344
IpsecPolicyAction policyAction
Processing choice (DISCARD, BYPASS or PROTECT)
Definition: ipsec.h:345
uint_t pfpFlags
PFP flags.
Definition: ipsec.h:346
IpsecSelector selector
Traffic selector.
Definition: ipsec.h:347
IpsecAddrRange ipAddr
IPv4 or IPv6 address range.
Definition: ipsec.h:335
uint8_t dn[IPSEC_MAX_ID_LEN]
X.500 Distinguished Name.
Definition: ipsec.h:333
char_t fqdn[IPSEC_MAX_ID_LEN+1]
Fully-qualified domain name.
Definition: ipsec.h:331
char_t email[IPSEC_MAX_ID_LEN+1]
RFC 822 email address.
Definition: ipsec.h:332
uint8_t keyId[IPSEC_MAX_ID_LEN]
Key ID.
Definition: ipsec.h:334