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-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 //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 ID type 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 ID type 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 ID type 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 #endif
240 
241  //ESP and AH SA use secret keys that should be used only for a limited
242  //amount of time
243  entry->lifetimeStart = osGetSystemTime();
244 
245  //Update the state of the SAD entry
246  entry->state = IPSEC_SA_STATE_OPEN;
247 
248  //Sucessful processing
249  return NO_ERROR;
250 }
251 
252 
253 /**
254  * @brief Clear entry at specified index in SAD database
255  * @param[in] context Pointer to the IPsec context
256  * @param[in] index ID type Zero-based index identifying a given entry
257  * @return Error code
258  **/
259 
261 {
262  IpsecSadEntry *entry;
263 
264  //Check parameters
265  if(context == NULL)
267 
268  //The implementation limits the number of SAD entries
269  if(index >= context->numSadEntries)
271 
272  //Point to the SAD entry
273  entry = &context->sad[index];
274 
275  //Clear SAD entry
276  entry->direction = IPSEC_DIR_INVALID;
277  entry->mode = IPSEC_MODE_INVALID;
278  entry->protocol = IPSEC_PROTOCOL_INVALID;
279  entry->spi = 0;
280  entry->authCipherAlgo = NULL;
281  entry->authHashAlgo = NULL;
282  entry->authKeyLen = 0;
283  entry->icvLen = 0;
284  entry->esn = 0;
285  entry->seqNum = 0;
286  entry->antiReplayEnabled = FALSE;
287 
288  //Clear selector
289  osMemset(&entry->selector, 0, sizeof(IpsecSelector));
290  //Clear integrity protection key
291  osMemset(entry->authKey, 0, IPSEC_MAX_AUTH_KEY_LEN);
292 
293 #if (ESP_SUPPORT == ENABLED)
294  //Clear encryption parameters
295  entry->cipherMode = CIPHER_MODE_NULL;
296  entry->cipherAlgo = NULL;
297  entry->encKeyLen = 0;
298  entry->saltLen = 0;
299  entry->ivLen = 0;
300 
301  //Clear encryption key
302  osMemset(entry->encKey, 0, IPSEC_MAX_ENC_KEY_LEN);
303 #endif
304 
305  //Mark the entry as closed
306  entry->state = IPSEC_SA_STATE_CLOSED;
307 
308  //Sucessful processing
309  return NO_ERROR;
310 }
311 
312 
313 /**
314  * @brief Set entry at specified index in PAD database
315  * @param[in] context Pointer to the IPsec context
316  * @param[in] index ID type Zero-based index identifying a given entry
317  * @param[in] params Pointer to the structure describing the PAD entry
318  * @return Error code
319  **/
320 
322  IpsecPadEntry *params)
323 {
324  //Check parameters
325  if(context == NULL || params == NULL)
327 
328  //The implementation limits the number of PAD entries that can be loaded
329  if(index >= context->numPadEntries)
331 
332  //Update PAD entry
333  osMemcpy(&context->pad[index], params, sizeof(IpsecPadEntry));
334 
335  //Sucessful processing
336  return NO_ERROR;
337 }
338 
339 
340 /**
341  * @brief Clear entry at specified index in PAD database
342  * @param[in] context Pointer to the IPsec context
343  * @param[in] index ID type Zero-based index identifying a given entry
344  * @return Error code
345  **/
346 
348 {
349  //Check parameters
350  if(context == NULL)
352 
353  //The implementation limits the number of PAD entries
354  if(index >= context->numPadEntries)
356 
357  //Clear PAD entry
358  osMemset(&context->pad[index], 0, sizeof(IpsecPadEntry));
359 
360  //Sucessful processing
361  return NO_ERROR;
362 }
363 
364 #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
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:347
NetContext netContext
Definition: net.c:74
#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
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:141
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:95
void * ipsecContext
IPsec context.
Definition: net.h:333
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:321
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:963
Security Policy Database (SPD) entry.
Definition: ipsec.h:344
unsigned int uint_t
Definition: compiler_port.h:50
#define osMemset(p, value, length)
Definition: os_port.h:135
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:260
@ 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