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