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.0
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->authCipherAlgo = params->authCipherAlgo;
235  entry->authHashAlgo = params->authHashAlgo;
236  entry->authKeyLen = params->authKeyLen;
237  entry->icvLen = params->icvLen;
238  entry->esn = params->esn;
239  entry->seqNum = params->seqNum;
240  entry->antiReplayEnabled = params->antiReplayEnabled;
241 
242  //Set integrity protection key
243  osMemcpy(entry->authKey, params->authKey, params->authKeyLen);
244 
245 #if (ESP_SUPPORT == ENABLED)
246  //Set encryption parameters
247  entry->cipherMode = params->cipherMode;
248  entry->cipherAlgo = params->cipherAlgo;
249  entry->encKeyLen = params->encKeyLen;
250  entry->saltLen = params->saltLen;
251  entry->ivLen = params->ivLen;
252 
253  //Set encryption key
254  osMemcpy(entry->encKey, params->encKey, params->encKeyLen +
255  params->saltLen);
256 
257  //Check encryption mode
258  if(params->protocol == IPSEC_PROTOCOL_ESP &&
259  params->cipherMode != CIPHER_MODE_CBC)
260  {
261  //Copy initialization vector
262  osMemcpy(entry->iv, params->iv, params->ivLen);
263  }
264 #endif
265 
266  //ESP and AH SA use secret keys that should be used only for a limited
267  //amount of time
268  entry->lifetimeStart = osGetSystemTime();
269 
270  //Update the state of the SAD entry
271  entry->state = IPSEC_SA_STATE_OPEN;
272 
273  //Sucessful processing
274  return NO_ERROR;
275 }
276 
277 
278 /**
279  * @brief Clear entry at specified index in SAD database
280  * @param[in] context Pointer to the IPsec context
281  * @param[in] index Zero-based index identifying a given entry
282  * @return Error code
283  **/
284 
286 {
287  IpsecSadEntry *entry;
288 
289  //Check parameters
290  if(context == NULL)
292 
293  //The implementation limits the number of SAD entries
294  if(index >= context->numSadEntries)
296 
297  //Point to the SAD entry
298  entry = &context->sad[index];
299 
300  //Clear SAD entry
301  entry->direction = IPSEC_DIR_INVALID;
302  entry->mode = IPSEC_MODE_INVALID;
303  entry->protocol = IPSEC_PROTOCOL_INVALID;
304  entry->spi = 0;
305  entry->authCipherAlgo = NULL;
306  entry->authHashAlgo = NULL;
307  entry->authKeyLen = 0;
308  entry->icvLen = 0;
309  entry->esn = 0;
310  entry->seqNum = 0;
311  entry->antiReplayEnabled = FALSE;
312 
313  //Clear selector
314  osMemset(&entry->selector, 0, sizeof(IpsecSelector));
315  //Clear integrity protection key
316  osMemset(entry->authKey, 0, IPSEC_MAX_AUTH_KEY_LEN);
317 
318 #if (ESP_SUPPORT == ENABLED)
319  //Clear encryption parameters
320  entry->cipherMode = CIPHER_MODE_NULL;
321  entry->cipherAlgo = NULL;
322  entry->encKeyLen = 0;
323  entry->saltLen = 0;
324  entry->ivLen = 0;
325 
326  //Clear encryption key
327  osMemset(entry->encKey, 0, IPSEC_MAX_ENC_KEY_LEN);
328 #endif
329 
330  //Mark the entry as closed
331  entry->state = IPSEC_SA_STATE_CLOSED;
332 
333  //Sucessful processing
334  return NO_ERROR;
335 }
336 
337 
338 /**
339  * @brief Set entry at specified index in PAD database
340  * @param[in] context Pointer to the IPsec context
341  * @param[in] index Zero-based index identifying a given entry
342  * @param[in] params Pointer to the structure describing the PAD entry
343  * @return Error code
344  **/
345 
347  IpsecPadEntry *params)
348 {
349  //Check parameters
350  if(context == NULL || params == NULL)
352 
353  //The implementation limits the number of PAD entries that can be loaded
354  if(index >= context->numPadEntries)
356 
357  //Update PAD entry
358  osMemcpy(&context->pad[index], params, sizeof(IpsecPadEntry));
359 
360  //Sucessful processing
361  return NO_ERROR;
362 }
363 
364 
365 /**
366  * @brief Clear entry at specified index in PAD database
367  * @param[in] context Pointer to the IPsec context
368  * @param[in] index Zero-based index identifying a given entry
369  * @return Error code
370  **/
371 
373 {
374  //Check parameters
375  if(context == NULL)
377 
378  //The implementation limits the number of PAD entries
379  if(index >= context->numPadEntries)
381 
382  //Clear PAD entry
383  osMemset(&context->pad[index], 0, sizeof(IpsecPadEntry));
384 
385  //Sucessful processing
386  return NO_ERROR;
387 }
388 
389 
390 /**
391  * @brief Release IPsec context
392  * @param[in] context Pointer to the IPsec context
393  **/
394 
395 void ipsecDeinit(IpsecContext *context)
396 {
397  NetContext *netContext;
398 
399  //Make sure the IPsec context is valid
400  if(context != NULL)
401  {
402  //Point to the TCP/IP stack context
403  netContext = context->netContext;
404 
405  //Get exclusive access
406  netLock(netContext);
407  //Detach the IPsec context
408  netContext->ipsecContext = NULL;
409  //Release exclusive access
410  netUnlock(netContext);
411 
412  //Clear IPsec context
413  osMemset(context, 0, sizeof(IpsecContext));
414  }
415 }
416 
417 #endif
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:170
uint_t numSadEntries
Number of entries in the SAD database.
Definition: ipsec.h:428
@ IPSEC_SA_STATE_CLOSED
Definition: ipsec.h:273
@ CIPHER_MODE_CBC
Definition: crypto.h:1063
IPsec selector.
Definition: ipsec.h:306
void * prngContext
Pseudo-random number generator context.
Definition: ipsec.h:424
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:372
#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:197
Peer Authorization Database (PAD) entry.
Definition: ipsec.h:404
#define FALSE
Definition: os_port.h:46
IpsecSadEntry * sadEntries
Security Association Database (SAD)
Definition: ipsec.h:427
@ 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
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:429
#define TRACE_INFO(...)
Definition: debug.h:105
void ipsecDeinit(IpsecContext *context)
Release IPsec context.
Definition: ipsec.c:395
const PrngAlgo * prngAlgo
Pseudo-random number generator to be used.
Definition: ipsec.h:423
#define IpsecSadEntry
Definition: ipsec.h:36
IPsec (IP security)
uint_t numPadEntries
Number of entries in the PAD database.
Definition: ipsec.h:430
error_t ipsecSetPadEntry(IpsecContext *context, uint_t index, IpsecPadEntry *params)
Set entry at specified index in PAD database.
Definition: ipsec.c:346
uint_t numSpdEntries
Number of entries in the SPD database.
Definition: ipsec.h:426
#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:207
void netLock(NetContext *context)
Get exclusive access to the core of the TCP/IP stack.
Definition: net.c:307
@ CIPHER_MODE_NULL
Definition: crypto.h:1060
Security Policy Database (SPD) entry.
Definition: ipsec.h:348
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
NetContext * netContext
TCP/IP stack context.
Definition: ipsec.h:422
error_t ipsecClearSadEntry(IpsecContext *context, uint_t index)
Clear entry at specified index in SAD database.
Definition: ipsec.c:285
@ IPSEC_SA_STATE_OPEN
Definition: ipsec.h:275
@ IPSEC_PROTOCOL_INVALID
Definition: ipsec.h:195
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
IpsecSpdEntry * spdEntries
Security Policy Database (SPD)
Definition: ipsec.h:425
systime_t osGetSystemTime(void)
Retrieve system time.
IPsec settings.
Definition: ipsec.h:421
error_t ipsecSetSpdEntry(IpsecContext *context, uint_t index, IpsecSpdEntry *params)
Set entry at specified index in SPD database.
Definition: ipsec.c:150