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-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 //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  //TCP/IP stack context
51  settings->netContext = NULL;
52 
53  //Pseudo-random number generator
54  settings->prngAlgo = NULL;
55  settings->prngContext = NULL;
56 
57  //Security Policy Database (SPD)
58  settings->spdEntries = NULL;
59  settings->numSpdEntries = 0;
60 
61  //Security Association Database (SAD)
62  settings->sadEntries = NULL;
63  settings->numSadEntries = 0;
64 
65  //Peer Authorization Database (PAD)
66  settings->padEntries = NULL;
67  settings->numPadEntries = 0;
68 }
69 
70 
71 /**
72  * @brief IPsec service initialization
73  * @param[in] context Pointer to the IPsec context
74  * @param[in] settings IPsec specific settings
75  * @return Error code
76  **/
77 
78 error_t ipsecInit(IpsecContext *context, const IpsecSettings *settings)
79 {
80  //Debug message
81  TRACE_INFO("Initializing IPsec...\r\n");
82 
83  //Ensure the parameters are valid
84  if(context == NULL || settings == NULL)
86 
87 #if (ESP_SUPPORT == ENABLED && ESP_CBC_SUPPORT == ENABLED)
88  if(settings->prngAlgo == NULL || settings->prngContext == NULL)
90 #endif
91 
92  if(settings->spdEntries == NULL || settings->numSpdEntries == 0)
94 
95  if(settings->sadEntries == NULL || settings->numSadEntries == 0)
97 
98  if(settings->padEntries == NULL || settings->numPadEntries == 0)
100 
101  //Clear the IPsec context
102  osMemset(context, 0, sizeof(IpsecContext));
103 
104  //Attach TCP/IP stack context
105  if(settings->netContext != NULL)
106  {
107  context->netContext = settings->netContext;
108  }
109  else
110  {
111  context->netContext = netGetDefaultContext();
112  }
113 
114  //Pseudo-random number generator
115  context->prngAlgo = settings->prngAlgo;
116  context->prngContext = settings->prngContext;
117 
118  //Security Policy Database (SPD)
119  context->spd = settings->spdEntries;
120  context->numSpdEntries = settings->numSpdEntries;
121 
122  //Security Association Database (SAD)
123  context->sad = settings->sadEntries;
124  context->numSadEntries = settings->numSadEntries;
125 
126  //Peer Authorization Database (PAD)
127  context->pad = settings->padEntries;
128  context->numPadEntries = settings->numPadEntries;
129 
130  //Get exclusive access
131  netLock(context->netContext);
132  //Attach IPsec context
133  context->netContext->ipsecContext = context;
134  //Release exclusive access
135  netUnlock(context->netContext);
136 
137  //Sucessful processing
138  return NO_ERROR;
139 }
140 
141 
142 /**
143  * @brief Set entry at specified index in SPD database
144  * @param[in] context Pointer to the IPsec context
145  * @param[in] index Zero-based index identifying a given entry
146  * @param[in] params Pointer to the structure describing the SPD entry
147  * @return Error code
148  **/
149 
151  IpsecSpdEntry *params)
152 {
153  //Check parameters
154  if(context == NULL || params == NULL)
156 
157  //The implementation limits the number of SPD entries that can be loaded
158  if(index >= context->numSpdEntries)
160 
161  //Update SPD entry
162  osMemcpy(&context->spd[index], params, sizeof(IpsecSpdEntry));
163 
164  //Sucessful processing
165  return NO_ERROR;
166 }
167 
168 
169 /**
170  * @brief Clear entry at specified index in SPD database
171  * @param[in] context Pointer to the IPsec context
172  * @param[in] index Zero-based index identifying a given entry
173  * @return Error code
174  **/
175 
177 {
178  //Check parameters
179  if(context == NULL)
181 
182  //The implementation limits the number of SPD entries
183  if(index >= context->numSpdEntries)
185 
186  //Clear SPD entry
187  osMemset(&context->spd[index], 0, sizeof(IpsecSpdEntry));
188 
189  //Sucessful processing
190  return NO_ERROR;
191 }
192 
193 
194 /**
195  * @brief Set entry at specified index in SAD database
196  * @param[in] context Pointer to the IPsec context
197  * @param[in] index Zero-based index identifying a given entry
198  * @param[in] params Pointer to the structure describing the SAD entry
199  * @return Error code
200  **/
201 
203  IpsecSadEntry *params)
204 {
205  IpsecSadEntry *entry;
206 
207  //Check parameters
208  if(context == NULL || params == NULL)
210 
211  //The implementation limits the number of SAD entries that can be loaded
212  if(index >= context->numSadEntries)
214 
215  //Check the length of the integrity protection key
216  if(params->authKeyLen > IPSEC_MAX_AUTH_KEY_LEN)
218 
219 #if (ESP_SUPPORT == ENABLED)
220  //Check the length of the encryption key
221  if((params->encKeyLen + params->saltLen) > IPSEC_MAX_ENC_KEY_LEN)
223 #endif
224 
225  //Point to the SAD entry
226  entry = &context->sad[index];
227 
228  //Update SAD entry
229  entry->direction = params->direction;
230  entry->mode = params->mode;
231  entry->protocol = params->protocol;
232  entry->selector = params->selector;
233  entry->spi = params->spi;
234  entry->authMacAlgo = params->authMacAlgo;
235  entry->authCipherAlgo = params->authCipherAlgo;
236  entry->authHashAlgo = params->authHashAlgo;
237  entry->authKeyLen = params->authKeyLen;
238  entry->icvLen = params->icvLen;
239  entry->esn = params->esn;
240  entry->seqNum = params->seqNum;
241  entry->antiReplayEnabled = params->antiReplayEnabled;
242 
243  //Set integrity protection key
244  osMemcpy(entry->authKey, params->authKey, params->authKeyLen);
245 
246 #if (ESP_SUPPORT == ENABLED)
247  //Set encryption parameters
248  entry->cipherMode = params->cipherMode;
249  entry->cipherAlgo = params->cipherAlgo;
250  entry->encKeyLen = params->encKeyLen;
251  entry->saltLen = params->saltLen;
252  entry->ivLen = params->ivLen;
253 
254  //Set encryption key
255  osMemcpy(entry->encKey, params->encKey, params->encKeyLen +
256  params->saltLen);
257 
258  //Check encryption mode
259  if(params->protocol == IPSEC_PROTOCOL_ESP &&
260  params->cipherMode != CIPHER_MODE_CBC)
261  {
262  //Copy initialization vector
263  osMemcpy(entry->iv, params->iv, params->ivLen);
264  }
265 #endif
266 
267 #if (ESP_SUPPORT == ENABLED && ESP_UDP_ENCAPS_SUPPORT == ENABLED)
268  //UDP encapsulation of IPsec ESP packets
269  entry->udpEncapsulation = params->udpEncapsulation;
270 #endif
271 
272  //ESP and AH SA use secret keys that should be used only for a limited
273  //amount of time
274  entry->lifetimeStart = osGetSystemTime();
275 
276  //Update the state of the SAD entry
277  entry->state = IPSEC_SA_STATE_OPEN;
278 
279  //Sucessful processing
280  return NO_ERROR;
281 }
282 
283 
284 /**
285  * @brief Clear entry at specified index in SAD database
286  * @param[in] context Pointer to the IPsec context
287  * @param[in] index Zero-based index identifying a given entry
288  * @return Error code
289  **/
290 
292 {
293  IpsecSadEntry *entry;
294 
295  //Check parameters
296  if(context == NULL)
298 
299  //The implementation limits the number of SAD entries
300  if(index >= context->numSadEntries)
302 
303  //Point to the SAD entry
304  entry = &context->sad[index];
305 
306  //Clear SAD entry
307  entry->direction = IPSEC_DIR_INVALID;
308  entry->mode = IPSEC_MODE_INVALID;
309  entry->protocol = IPSEC_PROTOCOL_INVALID;
310  entry->spi = 0;
311  entry->authCipherAlgo = NULL;
312  entry->authHashAlgo = NULL;
313  entry->authKeyLen = 0;
314  entry->icvLen = 0;
315  entry->esn = 0;
316  entry->seqNum = 0;
317  entry->antiReplayEnabled = FALSE;
318 
319  //Clear selector
320  osMemset(&entry->selector, 0, sizeof(IpsecSelector));
321  //Clear integrity protection key
322  osMemset(entry->authKey, 0, IPSEC_MAX_AUTH_KEY_LEN);
323 
324 #if (ESP_SUPPORT == ENABLED)
325  //Clear encryption parameters
326  entry->cipherMode = CIPHER_MODE_NULL;
327  entry->cipherAlgo = NULL;
328  entry->encKeyLen = 0;
329  entry->saltLen = 0;
330  entry->ivLen = 0;
331 
332  //Clear encryption key
333  osMemset(entry->encKey, 0, IPSEC_MAX_ENC_KEY_LEN);
334 #endif
335 
336  //Mark the entry as closed
337  entry->state = IPSEC_SA_STATE_CLOSED;
338 
339  //Sucessful processing
340  return NO_ERROR;
341 }
342 
343 
344 /**
345  * @brief Set entry at specified index in PAD database
346  * @param[in] context Pointer to the IPsec context
347  * @param[in] index Zero-based index identifying a given entry
348  * @param[in] params Pointer to the structure describing the PAD entry
349  * @return Error code
350  **/
351 
353  IpsecPadEntry *params)
354 {
355  //Check parameters
356  if(context == NULL || params == NULL)
358 
359  //The implementation limits the number of PAD entries that can be loaded
360  if(index >= context->numPadEntries)
362 
363  //Update PAD entry
364  osMemcpy(&context->pad[index], params, sizeof(IpsecPadEntry));
365 
366  //Sucessful processing
367  return NO_ERROR;
368 }
369 
370 
371 /**
372  * @brief Clear entry at specified index in PAD database
373  * @param[in] context Pointer to the IPsec context
374  * @param[in] index Zero-based index identifying a given entry
375  * @return Error code
376  **/
377 
379 {
380  //Check parameters
381  if(context == NULL)
383 
384  //The implementation limits the number of PAD entries
385  if(index >= context->numPadEntries)
387 
388  //Clear PAD entry
389  osMemset(&context->pad[index], 0, sizeof(IpsecPadEntry));
390 
391  //Sucessful processing
392  return NO_ERROR;
393 }
394 
395 
396 /**
397  * @brief Release IPsec context
398  * @param[in] context Pointer to the IPsec context
399  **/
400 
401 void ipsecDeinit(IpsecContext *context)
402 {
403  NetContext *netContext;
404 
405  //Make sure the IPsec context is valid
406  if(context != NULL)
407  {
408  //Point to the TCP/IP stack context
409  netContext = context->netContext;
410 
411  //Get exclusive access
412  netLock(netContext);
413  //Detach the IPsec context
414  netContext->ipsecContext = NULL;
415  //Release exclusive access
416  netUnlock(netContext);
417 
418  //Clear IPsec context
419  osMemset(context, 0, sizeof(IpsecContext));
420  }
421 }
422 
423 #endif
@ CIPHER_MODE_CBC
Definition: cipher_modes.h:82
void netUnlock(NetContext *context)
Release exclusive access to the core of the TCP/IP stack.
Definition: net.c:319
#define NetContext
Definition: net.h:36
@ IPSEC_DIR_INVALID
Definition: ipsec.h:173
uint_t numSadEntries
Number of entries in the SAD database.
Definition: ipsec.h:436
@ IPSEC_SA_STATE_CLOSED
Definition: ipsec.h:276
IPsec selector.
Definition: ipsec.h:309
void * prngContext
Pseudo-random number generator context.
Definition: ipsec.h:432
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:378
@ CIPHER_MODE_NULL
Definition: cipher_modes.h:79
#define IPSEC_MAX_ENC_KEY_LEN
Definition: ipsec.h:129
#define IPSEC_MAX_AUTH_KEY_LEN
Definition: ipsec.h:136
@ IPSEC_PROTOCOL_ESP
Definition: ipsec.h:200
Peer Authorization Database (PAD) entry.
Definition: ipsec.h:412
#define FALSE
Definition: os_port.h:46
IpsecSadEntry * sadEntries
Security Association Database (SAD)
Definition: ipsec.h:435
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
error_t
Error codes.
Definition: error.h:43
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:78
NetContext * netGetDefaultContext(void)
Get default TCP/IP stack context.
Definition: net.c:527
error_t ipsecSetSadEntry(IpsecContext *context, uint_t index, IpsecSadEntry *params)
Set entry at specified index in SAD database.
Definition: ipsec.c:202
IpsecPadEntry * padEntries
Peer Authorization Database (PAD)
Definition: ipsec.h:437
#define TRACE_INFO(...)
Definition: debug.h:105
void ipsecDeinit(IpsecContext *context)
Release IPsec context.
Definition: ipsec.c:401
const PrngAlgo * prngAlgo
Pseudo-random number generator to be used.
Definition: ipsec.h:431
#define IpsecSadEntry
Definition: ipsec.h:36
IPsec (IP security)
uint_t numPadEntries
Number of entries in the PAD database.
Definition: ipsec.h:438
error_t ipsecSetPadEntry(IpsecContext *context, uint_t index, IpsecPadEntry *params)
Set entry at specified index in PAD database.
Definition: ipsec.c:352
uint_t numSpdEntries
Number of entries in the SPD database.
Definition: ipsec.h:434
#define IpsecContext
Definition: ipsec.h:40
error_t ipsecClearSpdEntry(IpsecContext *context, uint_t index)
Clear entry at specified index in SPD database.
Definition: ipsec.c:176
@ IPSEC_MODE_INVALID
Definition: ipsec.h:210
void netLock(NetContext *context)
Get exclusive access to the core of the TCP/IP stack.
Definition: net.c:307
Security Policy Database (SPD) entry.
Definition: ipsec.h:351
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:141
NetContext * netContext
TCP/IP stack context.
Definition: ipsec.h:430
error_t ipsecClearSadEntry(IpsecContext *context, uint_t index)
Clear entry at specified index in SAD database.
Definition: ipsec.c:291
@ IPSEC_SA_STATE_OPEN
Definition: ipsec.h:278
@ IPSEC_PROTOCOL_INVALID
Definition: ipsec.h:198
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
IpsecSpdEntry * spdEntries
Security Policy Database (SPD)
Definition: ipsec.h:433
systime_t osGetSystemTime(void)
Retrieve system time.
IPsec settings.
Definition: ipsec.h:429
error_t ipsecSetSpdEntry(IpsecContext *context, uint_t index, IpsecSpdEntry *params)
Set entry at specified index in SPD database.
Definition: ipsec.c:150