ipsec.c
Go to the documentation of this file.
1 /**
2  * @file ipsec.c
3  * @brief IPsec (IP security)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2022-2025 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.5.2
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL IPSEC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "ipsec/ipsec.h"
36 #include "ipsec/ipsec_misc.h"
37 #include "debug.h"
38 
39 //Check IPsec library configuration
40 #if (IPSEC_SUPPORT == ENABLED)
41 
42 
43 /**
44  * @brief Initialize settings with default values
45  * @param[out] settings Structure that contains IPsec settings
46  **/
47 
49 {
50  //Pseudo-random number generator
51  settings->prngAlgo = NULL;
52  settings->prngContext = NULL;
53 
54  //Security Policy Database (SPD)
55  settings->spdEntries = NULL;
56  settings->numSpdEntries = 0;
57 
58  //Security Association Database (SAD)
59  settings->sadEntries = NULL;
60  settings->numSadEntries = 0;
61 
62  //Peer Authorization Database (PAD)
63  settings->padEntries = NULL;
64  settings->numPadEntries = 0;
65 }
66 
67 
68 /**
69  * @brief IPsec service initialization
70  * @param[in] context Pointer to the IPsec context
71  * @param[in] settings IPsec specific settings
72  * @return Error code
73  **/
74 
75 error_t ipsecInit(IpsecContext *context, const IpsecSettings *settings)
76 {
77  //Debug message
78  TRACE_INFO("Initializing IPsec...\r\n");
79 
80  //Ensure the parameters are valid
81  if(context == NULL || settings == NULL)
83 
84 #if (ESP_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
85  if(settings->prngAlgo == NULL || settings->prngContext == NULL)
87 #endif
88 
89  if(settings->spdEntries == NULL || settings->numSpdEntries == 0)
91 
92  if(settings->sadEntries == NULL || settings->numSadEntries == 0)
94 
95  if(settings->padEntries == NULL || settings->numPadEntries == 0)
97 
98  //Clear the IPsec context
99  osMemset(context, 0, sizeof(IpsecContext));
100 
101  //Pseudo-random number generator
102  context->prngAlgo = settings->prngAlgo;
103  context->prngContext = settings->prngContext;
104 
105  //Security Policy Database (SPD)
106  context->spd = settings->spdEntries;
107  context->numSpdEntries = settings->numSpdEntries;
108 
109  //Security Association Database (SAD)
110  context->sad = settings->sadEntries;
111  context->numSadEntries = settings->numSadEntries;
112 
113  //Peer Authorization Database (PAD)
114  context->pad = settings->padEntries;
115  context->numPadEntries = settings->numPadEntries;
116 
117  //Attach IPsec context
118  netContext.ipsecContext = context;
119 
120  //Sucessful processing
121  return NO_ERROR;
122 }
123 
124 
125 /**
126  * @brief Set entry at specified index in SPD database
127  * @param[in] context Pointer to the IPsec context
128  * @param[in] index Zero-based index identifying a given entry
129  * @param[in] params Pointer to the structure describing the SPD entry
130  * @return Error code
131  **/
132 
134  IpsecSpdEntry *params)
135 {
136  //Check parameters
137  if(context == NULL || params == NULL)
139 
140  //The implementation limits the number of SPD entries that can be loaded
141  if(index >= context->numSpdEntries)
143 
144  //Update SPD entry
145  osMemcpy(&context->spd[index], params, sizeof(IpsecSpdEntry));
146 
147  //Sucessful processing
148  return NO_ERROR;
149 }
150 
151 
152 /**
153  * @brief Clear entry at specified index in SPD database
154  * @param[in] context Pointer to the IPsec context
155  * @param[in] index Zero-based index identifying a given entry
156  * @return Error code
157  **/
158 
160 {
161  //Check parameters
162  if(context == NULL)
164 
165  //The implementation limits the number of SPD entries
166  if(index >= context->numSpdEntries)
168 
169  //Clear SPD entry
170  osMemset(&context->spd[index], 0, sizeof(IpsecSpdEntry));
171 
172  //Sucessful processing
173  return NO_ERROR;
174 }
175 
176 
177 /**
178  * @brief Set entry at specified index in SAD database
179  * @param[in] context Pointer to the IPsec context
180  * @param[in] index Zero-based index identifying a given entry
181  * @param[in] params Pointer to the structure describing the SAD entry
182  * @return Error code
183  **/
184 
186  IpsecSadEntry *params)
187 {
188  IpsecSadEntry *entry;
189 
190  //Check parameters
191  if(context == NULL || params == NULL)
193 
194  //The implementation limits the number of SAD entries that can be loaded
195  if(index >= context->numSadEntries)
197 
198  //Check the length of the integrity protection key
199  if(params->authKeyLen > IPSEC_MAX_AUTH_KEY_LEN)
201 
202 #if (ESP_SUPPORT == ENABLED)
203  //Check the length of the encryption key
204  if((params->encKeyLen + params->saltLen) > IPSEC_MAX_ENC_KEY_LEN)
206 #endif
207 
208  //Point to the SAD entry
209  entry = &context->sad[index];
210 
211  //Update SAD entry
212  entry->direction = params->direction;
213  entry->mode = params->mode;
214  entry->protocol = params->protocol;
215  entry->selector = params->selector;
216  entry->spi = params->spi;
217  entry->authCipherAlgo = params->authCipherAlgo;
218  entry->authHashAlgo = params->authHashAlgo;
219  entry->authKeyLen = params->authKeyLen;
220  entry->icvLen = params->icvLen;
221  entry->esn = params->esn;
222  entry->seqNum = params->seqNum;
223  entry->antiReplayEnabled = params->antiReplayEnabled;
224 
225  //Set integrity protection key
226  osMemcpy(entry->authKey, params->authKey, params->authKeyLen);
227 
228 #if (ESP_SUPPORT == ENABLED)
229  //Set encryption parameters
230  entry->cipherMode = params->cipherMode;
231  entry->cipherAlgo = params->cipherAlgo;
232  entry->encKeyLen = params->encKeyLen;
233  entry->saltLen = params->saltLen;
234  entry->ivLen = params->ivLen;
235 
236  //Set encryption key
237  osMemcpy(entry->encKey, params->encKey, params->encKeyLen +
238  params->saltLen);
239 
240  //Check encryption mode
241  if(params->protocol == IPSEC_PROTOCOL_ESP &&
242  params->cipherMode != CIPHER_MODE_CBC)
243  {
244  //Copy initialization vector
245  osMemcpy(entry->iv, params->iv, params->ivLen);
246  }
247 #endif
248 
249  //ESP and AH SA use secret keys that should be used only for a limited
250  //amount of time
251  entry->lifetimeStart = osGetSystemTime();
252 
253  //Update the state of the SAD entry
254  entry->state = IPSEC_SA_STATE_OPEN;
255 
256  //Sucessful processing
257  return NO_ERROR;
258 }
259 
260 
261 /**
262  * @brief Clear entry at specified index in SAD database
263  * @param[in] context Pointer to the IPsec context
264  * @param[in] index Zero-based index identifying a given entry
265  * @return Error code
266  **/
267 
269 {
270  IpsecSadEntry *entry;
271 
272  //Check parameters
273  if(context == NULL)
275 
276  //The implementation limits the number of SAD entries
277  if(index >= context->numSadEntries)
279 
280  //Point to the SAD entry
281  entry = &context->sad[index];
282 
283  //Clear SAD entry
284  entry->direction = IPSEC_DIR_INVALID;
285  entry->mode = IPSEC_MODE_INVALID;
286  entry->protocol = IPSEC_PROTOCOL_INVALID;
287  entry->spi = 0;
288  entry->authCipherAlgo = NULL;
289  entry->authHashAlgo = NULL;
290  entry->authKeyLen = 0;
291  entry->icvLen = 0;
292  entry->esn = 0;
293  entry->seqNum = 0;
294  entry->antiReplayEnabled = FALSE;
295 
296  //Clear selector
297  osMemset(&entry->selector, 0, sizeof(IpsecSelector));
298  //Clear integrity protection key
299  osMemset(entry->authKey, 0, IPSEC_MAX_AUTH_KEY_LEN);
300 
301 #if (ESP_SUPPORT == ENABLED)
302  //Clear encryption parameters
303  entry->cipherMode = CIPHER_MODE_NULL;
304  entry->cipherAlgo = NULL;
305  entry->encKeyLen = 0;
306  entry->saltLen = 0;
307  entry->ivLen = 0;
308 
309  //Clear encryption key
310  osMemset(entry->encKey, 0, IPSEC_MAX_ENC_KEY_LEN);
311 #endif
312 
313  //Mark the entry as closed
314  entry->state = IPSEC_SA_STATE_CLOSED;
315 
316  //Sucessful processing
317  return NO_ERROR;
318 }
319 
320 
321 /**
322  * @brief Set entry at specified index in PAD database
323  * @param[in] context Pointer to the IPsec context
324  * @param[in] index Zero-based index identifying a given entry
325  * @param[in] params Pointer to the structure describing the PAD entry
326  * @return Error code
327  **/
328 
330  IpsecPadEntry *params)
331 {
332  //Check parameters
333  if(context == NULL || params == NULL)
335 
336  //The implementation limits the number of PAD entries that can be loaded
337  if(index >= context->numPadEntries)
339 
340  //Update PAD entry
341  osMemcpy(&context->pad[index], params, sizeof(IpsecPadEntry));
342 
343  //Sucessful processing
344  return NO_ERROR;
345 }
346 
347 
348 /**
349  * @brief Clear entry at specified index in PAD database
350  * @param[in] context Pointer to the IPsec context
351  * @param[in] index Zero-based index identifying a given entry
352  * @return Error code
353  **/
354 
356 {
357  //Check parameters
358  if(context == NULL)
360 
361  //The implementation limits the number of PAD entries
362  if(index >= context->numPadEntries)
364 
365  //Clear PAD entry
366  osMemset(&context->pad[index], 0, sizeof(IpsecPadEntry));
367 
368  //Sucessful processing
369  return NO_ERROR;
370 }
371 
372 #endif
IpsecSadEntry * sad
Security Association Database (SAD)
Definition: ipsec.h:439
@ IPSEC_DIR_INVALID
Definition: ipsec.h:166
uint_t numSadEntries
Number of entries in the SAD database.
Definition: ipsec.h:423
@ IPSEC_SA_STATE_CLOSED
Definition: ipsec.h:269
uint_t numPadEntries
Number of entries in the PAD database.
Definition: ipsec.h:442
@ CIPHER_MODE_CBC
Definition: crypto.h:1008
IPsec selector.
Definition: ipsec.h:302
void * prngContext
Pseudo-random number generator context.
Definition: ipsec.h:419
void ipsecGetDefaultSettings(IpsecSettings *settings)
Initialize settings with default values.
Definition: ipsec.c:48
error_t ipsecClearPadEntry(IpsecContext *context, uint_t index)
Clear entry at specified index in PAD database.
Definition: ipsec.c:355
NetContext netContext
Definition: net.c:75
#define IPSEC_MAX_ENC_KEY_LEN
Definition: ipsec.h:125
uint_t numSadEntries
Number of entries in the SAD database.
Definition: ipsec.h:440
#define IPSEC_MAX_AUTH_KEY_LEN
Definition: ipsec.h:132
@ IPSEC_PROTOCOL_ESP
Definition: ipsec.h:193
Peer Authorization Database (PAD) entry.
Definition: ipsec.h:400
#define FALSE
Definition: os_port.h:46
IpsecSadEntry * sadEntries
Security Association Database (SAD)
Definition: ipsec.h:422
IpsecSpdEntry * spd
Security Policy Database (SPD)
Definition: ipsec.h:437
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
IpsecPadEntry * pad
Peer Authorization Database (PAD)
Definition: ipsec.h:441
Helper routines for IPsec.
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:107
error_t ipsecInit(IpsecContext *context, const IpsecSettings *settings)
IPsec service initialization.
Definition: ipsec.c:75
error_t ipsecSetSadEntry(IpsecContext *context, uint_t index, IpsecSadEntry *params)
Set entry at specified index in SAD database.
Definition: ipsec.c:185
IpsecPadEntry * padEntries
Peer Authorization Database (PAD)
Definition: ipsec.h:424
IPsec context.
Definition: ipsec.h:434
#define TRACE_INFO(...)
Definition: debug.h:105
void * ipsecContext
IPsec context.
Definition: net.h:339
const PrngAlgo * prngAlgo
Pseudo-random number generator to be used.
Definition: ipsec.h:418
#define IpsecSadEntry
Definition: ipsec.h:36
IPsec (IP security)
uint_t numPadEntries
Number of entries in the PAD database.
Definition: ipsec.h:425
error_t ipsecSetPadEntry(IpsecContext *context, uint_t index, IpsecPadEntry *params)
Set entry at specified index in PAD database.
Definition: ipsec.c:329
uint_t numSpdEntries
Number of entries in the SPD database.
Definition: ipsec.h:421
const PrngAlgo * prngAlgo
Pseudo-random number generator to be used.
Definition: ipsec.h:435
uint_t numSpdEntries
Number of entries in the SPD database.
Definition: ipsec.h:438
error_t ipsecClearSpdEntry(IpsecContext *context, uint_t index)
Clear entry at specified index in SPD database.
Definition: ipsec.c:159
@ IPSEC_MODE_INVALID
Definition: ipsec.h:203
@ CIPHER_MODE_NULL
Definition: crypto.h:1005
Security Policy Database (SPD) entry.
Definition: ipsec.h:344
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
void * prngContext
Pseudo-random number generator context.
Definition: ipsec.h:436
error_t ipsecClearSadEntry(IpsecContext *context, uint_t index)
Clear entry at specified index in SAD database.
Definition: ipsec.c:268
@ IPSEC_SA_STATE_OPEN
Definition: ipsec.h:271
@ IPSEC_PROTOCOL_INVALID
Definition: ipsec.h:191
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
IpsecSpdEntry * spdEntries
Security Policy Database (SPD)
Definition: ipsec.h:420
systime_t osGetSystemTime(void)
Retrieve system time.
IPsec settings.
Definition: ipsec.h:417
error_t ipsecSetSpdEntry(IpsecContext *context, uint_t index, IpsecSpdEntry *params)
Set entry at specified index in SPD database.
Definition: ipsec.c:133