ipsec_anti_replay.c
Go to the documentation of this file.
1 /**
2  * @file ipsec_anti_replay.c
3  * @brief Anti-replay mechanism
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 //Dependencies
32 #include "ipsec/ipsec.h"
34 
35 //Check IPsec library configuration
36 #if (IPSEC_SUPPORT == ENABLED)
37 
38 
39 /**
40  * @brief Initialize sliding window
41  * @param[in] sa Pointer to the security association
42  **/
43 
45 {
46 #if (IPSEC_ANTI_REPLAY_SUPPORT == ENABLED)
47  uint_t i;
48 
49  //Clear the bitmap window
50  for(i = 0; i < (IPSEC_ANTI_REPLAY_WINDOW_SIZE + 31) / 32; i++)
51  {
52  sa->antiReplayWindow[i] = 0;
53  }
54 #endif
55 }
56 
57 
58 /**
59  * @brief Perform replay detection
60  * @param[in] sa Pointer to the security association
61  * @param[in] seqNum Sequence number of the received packet
62  * @return Error code
63  **/
64 
66 {
67  error_t error;
68 
69 #if (IPSEC_ANTI_REPLAY_SUPPORT == ENABLED)
70  //All AH implementations must support the anti-replay service, though its
71  //use may be enabled or disabled by the receiver on a per-SA basis (refer
72  //to RFC 4302, section 3.4.3)
73  if(sa->antiReplayEnabled)
74  {
75  uint_t j;
76  uint_t k;
77  uint64_t n;
78  uint64_t right;
79 
80  //The right edge of the window represents the highest validated sequence
81  //number value received on this SA
82  right = sa->seqNum;
83 
84  //Check sequence number
85  if(seqNum == 0)
86  {
87  //the first packet sent using a given SA will contain a sequence
88  //number of 1
90  }
91  else if(seqNum <= right)
92  {
93  //Calculate the position relative to the right edge of the window
94  n = right - seqNum;
95 
96  //Check whether the sequence number falls within the window
98  {
99  //Records falling within the window are checked against a list of
100  //received packets within the window
101  j = (uint_t) (n / 32);
102  k = (uint_t) (n % 32);
103 
104  //Duplicate record are rejected through the use of a sliding
105  //receive window
106  if(sa->antiReplayWindow[j] & (1U << k))
107  {
108  //The received record is a duplicate
110  }
111  else
112  {
113  //If the received record falls within the window and is new,
114  //then the receiver proceeds to ICV verification
115  error = NO_ERROR;
116  }
117 
118  }
119  else
120  {
121  //Records that contain sequence numbers lower than the left edge
122  //of the window are rejected
124  }
125  }
126  else
127  {
128  //If the packet is to the right of the window, then the receiver
129  //proceeds to ICV verification
130  error = NO_ERROR;
131  }
132  }
133  else
134 #endif
135  {
136  //If the receiver does not enable anti-replay for an SA, no inbound
137  //checks are performed on the sequence number
138  error = NO_ERROR;
139  }
140 
141  //Return status code
142  return error;
143 }
144 
145 
146 /**
147  * @brief Update sliding window
148  * @param[in] sa Pointer to the security association
149  * @param[in] seqNum Sequence number of the received packet
150  **/
151 
153 {
154  uint64_t n;
155  uint64_t right;
156 
157  //The right edge of the window represents the highest validated sequence
158  //number value received on this SA
159  right = sa->seqNum;
160 
161  //Check sequence number
162  if(seqNum <= right)
163  {
164 #if (IPSEC_ANTI_REPLAY_SUPPORT == ENABLED)
165  uint_t j;
166  uint_t k;
167 
168  //Calculate the position relative to the right edge of the window
169  n = right - seqNum;
170 
171  //Check whether the sequence number falls within the window
173  {
174  j = (uint_t) (n / 32);
175  k = (uint_t) (n % 32);
176 
177  //Set the corresponding bit in the bitmap window
178  sa->antiReplayWindow[j] |= 1U << k;
179  }
180 #endif
181  }
182  else
183  {
184 #if (IPSEC_ANTI_REPLAY_SUPPORT == ENABLED)
185  uint_t i;
186  uint_t j;
187  uint_t k;
188 
189  //Calculate the position relative to the right edge of the window
190  n = seqNum - right;
191 
192  //Check resulting value
194  {
195  j = (uint_t) (n / 32);
196  k = (uint_t) (n % 32);
197 
198  //First, shift words
199  if(j > 0)
200  {
201  //Shift the most significant words of the window
202  for(i = (IPSEC_ANTI_REPLAY_WINDOW_SIZE - 1) / 32; i >= j; i--)
203  {
204  sa->antiReplayWindow[i] = sa->antiReplayWindow[i - j];
205  }
206 
207  //Fill the least significant words with zeroes
208  for(i = 0; i < j; i++)
209  {
210  sa->antiReplayWindow[i] = 0;
211  }
212  }
213 
214  //Then shift bits
215  if(k > 0)
216  {
217  //Shift the most significant words of the window
218  for(i = (IPSEC_ANTI_REPLAY_WINDOW_SIZE - 1) / 32; i >= 1; i--)
219  {
220  sa->antiReplayWindow[i] = (sa->antiReplayWindow[i] << k) |
221  (sa->antiReplayWindow[i - 1] >> (32 - k));
222  }
223 
224  //Shift the least significant word
225  sa->antiReplayWindow[0] <<= k;
226  }
227  }
228  else
229  {
230  //Clear the bitmap window
231  for(i = 0; i < (IPSEC_ANTI_REPLAY_WINDOW_SIZE + 31) / 32; i++)
232  {
233  sa->antiReplayWindow[i] = 0;
234  }
235  }
236 
237  //Set the corresponding bit in the bitmap window
238  sa->antiReplayWindow[0] |= 1;
239 #endif
240 
241  //Save the highest sequence number value received on this session
242  sa->seqNum = seqNum;
243  }
244 }
245 
246 #endif
#define IPSEC_ANTI_REPLAY_WINDOW_SIZE
Definition: ipsec.h:104
error_t ipsecCheckReplayWindow(const IpsecSadEntry *sa, uint64_t seqNum)
Perform replay detection.
error_t
Error codes.
Definition: error.h:43
uint32_t seqNum
Definition: tcp.h:341
Anti-replay mechanism.
#define IpsecSadEntry
Definition: ipsec.h:36
IPsec (IP security)
uint8_t n
unsigned int uint_t
Definition: compiler_port.h:50
void ipsecInitReplayWindow(IpsecSadEntry *sa)
Initialize sliding window.
void ipsecUpdateReplayWindow(IpsecSadEntry *sa, uint64_t seqNum)
Update sliding window.
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_INVALID_SEQUENCE_NUMBER
Definition: error.h:109