FD.io VPP  v20.01-48-g3e0dafb74
Vector Packet Processing
ipsec_sa.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #ifndef __IPSEC_SPD_SA_H__
16 #define __IPSEC_SPD_SA_H__
17 
18 #include <vlib/vlib.h>
19 #include <vnet/ip/ip.h>
20 #include <vnet/fib/fib_node.h>
21 
22 #define foreach_ipsec_crypto_alg \
23  _ (0, NONE, "none") \
24  _ (1, AES_CBC_128, "aes-cbc-128") \
25  _ (2, AES_CBC_192, "aes-cbc-192") \
26  _ (3, AES_CBC_256, "aes-cbc-256") \
27  _ (4, AES_CTR_128, "aes-ctr-128") \
28  _ (5, AES_CTR_192, "aes-ctr-192") \
29  _ (6, AES_CTR_256, "aes-ctr-256") \
30  _ (7, AES_GCM_128, "aes-gcm-128") \
31  _ (8, AES_GCM_192, "aes-gcm-192") \
32  _ (9, AES_GCM_256, "aes-gcm-256") \
33  _ (10, DES_CBC, "des-cbc") \
34  _ (11, 3DES_CBC, "3des-cbc")
35 
36 typedef enum
37 {
38 #define _(v, f, s) IPSEC_CRYPTO_ALG_##f = v,
40 #undef _
43 
44 #define IPSEC_CRYPTO_ALG_IS_GCM(_alg) \
45  (((_alg == IPSEC_CRYPTO_ALG_AES_GCM_128) || \
46  (_alg == IPSEC_CRYPTO_ALG_AES_GCM_192) || \
47  (_alg == IPSEC_CRYPTO_ALG_AES_GCM_256)))
48 
49 #define foreach_ipsec_integ_alg \
50  _ (0, NONE, "none") \
51  _ (1, MD5_96, "md5-96") /* RFC2403 */ \
52  _ (2, SHA1_96, "sha1-96") /* RFC2404 */ \
53  _ (3, SHA_256_96, "sha-256-96") /* draft-ietf-ipsec-ciph-sha-256-00 */ \
54  _ (4, SHA_256_128, "sha-256-128") /* RFC4868 */ \
55  _ (5, SHA_384_192, "sha-384-192") /* RFC4868 */ \
56  _ (6, SHA_512_256, "sha-512-256") /* RFC4868 */
57 
58 typedef enum
59 {
60 #define _(v, f, s) IPSEC_INTEG_ALG_##f = v,
62 #undef _
65 
66 typedef enum
67 {
71 
72 #define IPSEC_KEY_MAX_LEN 128
73 typedef struct ipsec_key_t_
74 {
77 } ipsec_key_t;
78 
79 /*
80  * Enable extended sequence numbers
81  * Enable Anti-replay
82  * IPsec tunnel mode if non-zero, else transport mode
83  * IPsec tunnel mode is IPv6 if non-zero,
84  * else IPv4 tunnel only valid if is_tunnel is non-zero
85  * enable UDP encapsulation for NAT traversal
86  */
87 #define foreach_ipsec_sa_flags \
88  _ (0, NONE, "none") \
89  _ (1, USE_ESN, "esn") \
90  _ (2, USE_ANTI_REPLAY, "anti-replay") \
91  _ (4, IS_TUNNEL, "tunnel") \
92  _ (8, IS_TUNNEL_V6, "tunnel-v6") \
93  _ (16, UDP_ENCAP, "udp-encap") \
94  _ (32, IS_PROTECT, "Protect") \
95  _ (64, IS_INBOUND, "inbound") \
96  _ (128, IS_AEAD, "aead") \
97 
98 typedef enum ipsec_sad_flags_t_
99 {
100 #define _(v, f, s) IPSEC_SA_FLAG_##f = v,
102 #undef _
103 } __clib_packed ipsec_sa_flags_t;
104 
105 STATIC_ASSERT (sizeof (ipsec_sa_flags_t) == 1, "IPSEC SA flags > 1 byte");
106 
107 typedef struct
108 {
109  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
110 
111  /* flags */
112  ipsec_sa_flags_t flags;
113 
126 
132 
133  /* data accessed by dataplane code should be above this comment */
134  CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
135 
136  union
137  {
140  };
142 
147 
148  ipsec_crypto_alg_t crypto_alg;
151 
152  ipsec_integ_alg_t integ_alg;
155 
156  ip46_address_t tunnel_src_addr;
157  ip46_address_t tunnel_dst_addr;
158 
161 
163 
164  /* Salt used in GCM modes - stored in network byte order */
167 } ipsec_sa_t;
168 
170 
171 #define _(a,v,s) \
172  always_inline int \
173  ipsec_sa_is_set_##v (const ipsec_sa_t *sa) { \
174  return (sa->flags & IPSEC_SA_FLAG_##v); \
175  }
177 #undef _
178 #define _(a,v,s) \
179  always_inline int \
180  ipsec_sa_set_##v (ipsec_sa_t *sa) { \
181  return (sa->flags |= IPSEC_SA_FLAG_##v); \
182  }
184 #undef _
185 #define _(a,v,s) \
186  always_inline int \
187  ipsec_sa_unset_##v (ipsec_sa_t *sa) { \
188  return (sa->flags &= ~IPSEC_SA_FLAG_##v); \
189  }
191 #undef _
192 /**
193  * @brief
194  * SA packet & bytes counters
195  */
197 
198 extern void ipsec_mk_key (ipsec_key_t * key, const u8 * data, u8 len);
199 
200 extern int ipsec_sa_add_and_lock (u32 id,
201  u32 spi,
203  ipsec_crypto_alg_t crypto_alg,
204  const ipsec_key_t * ck,
205  ipsec_integ_alg_t integ_alg,
206  const ipsec_key_t * ik,
207  ipsec_sa_flags_t flags,
209  u32 salt,
210  const ip46_address_t * tunnel_src_addr,
211  const ip46_address_t * tunnel_dst_addr,
212  u32 * sa_index);
214 extern int ipsec_sa_unlock_id (u32 id);
215 extern void ipsec_sa_unlock (index_t sai);
216 extern void ipsec_sa_lock (index_t sai);
217 extern void ipsec_sa_clear (index_t sai);
218 extern void ipsec_sa_set_crypto_alg (ipsec_sa_t * sa,
219  ipsec_crypto_alg_t crypto_alg);
220 extern void ipsec_sa_set_integ_alg (ipsec_sa_t * sa,
221  ipsec_integ_alg_t integ_alg);
222 
223 typedef walk_rc_t (*ipsec_sa_walk_cb_t) (ipsec_sa_t * sa, void *ctx);
224 extern void ipsec_sa_walk (ipsec_sa_walk_cb_t cd, void *ctx);
225 
226 extern u8 *format_ipsec_crypto_alg (u8 * s, va_list * args);
227 extern u8 *format_ipsec_integ_alg (u8 * s, va_list * args);
228 extern u8 *format_ipsec_sa (u8 * s, va_list * args);
229 extern u8 *format_ipsec_key (u8 * s, va_list * args);
231  va_list * args);
233  va_list * args);
234 extern uword unformat_ipsec_key (unformat_input_t * input, va_list * args);
235 
236 /*
237  * Anti Replay definitions
238  */
239 
240 #define IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE (64)
241 #define IPSEC_SA_ANTI_REPLAY_WINDOW_MAX_INDEX (IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE-1)
242 
243 /*
244  * sequence number less than the lower bound are outside of the window
245  * From RFC4303 Appendix A:
246  * Bl = Tl - W + 1
247  */
248 #define IPSEC_SA_ANTI_REPLAY_WINDOW_LOWER_BOUND(_tl) (_tl - IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE + 1)
249 
250 /*
251  * Anti replay check.
252  * inputs need to be in host byte order.
253  */
254 always_inline int
256 {
257  u32 diff, tl, th;
258 
259  if ((sa->flags & IPSEC_SA_FLAG_USE_ANTI_REPLAY) == 0)
260  return 0;
261 
262  if (!ipsec_sa_is_set_USE_ESN (sa))
263  {
264  if (PREDICT_TRUE (seq > sa->last_seq))
265  return 0;
266 
267  diff = sa->last_seq - seq;
268 
270  return (sa->replay_window & (1ULL << diff)) ? 1 : 0;
271  else
272  return 1;
273 
274  return 0;
275  }
276 
277  tl = sa->last_seq;
278  th = sa->last_seq_hi;
279  diff = tl - seq;
280 
282  {
283  /*
284  * the last sequence number VPP recieved is more than one
285  * window size greater than zero.
286  * Case A from RFC4303 Appendix A.
287  */
289  {
290  /*
291  * the received sequence number is lower than the lower bound
292  * of the window, this could mean either a replay packet or that
293  * the high sequence number has wrapped. if it decrypts corrently
294  * then it's the latter.
295  */
296  sa->seq_hi = th + 1;
297  return 0;
298  }
299  else
300  {
301  /*
302  * the recieved sequence number greater than the low
303  * end of the window.
304  */
305  sa->seq_hi = th;
306  if (seq <= tl)
307  /*
308  * The recieved seq number is within bounds of the window
309  * check if it's a duplicate
310  */
311  return (sa->replay_window & (1ULL << diff)) ? 1 : 0;
312  else
313  /*
314  * The received sequence number is greater than the window
315  * upper bound. this packet will move the window along, assuming
316  * it decrypts correctly.
317  */
318  return 0;
319  }
320  }
321  else
322  {
323  /*
324  * the last sequence number VPP recieved is within one window
325  * size of zero, i.e. 0 < TL < WINDOW_SIZE, the lower bound is thus a
326  * large sequence number.
327  * Note that the check below uses unsiged integer arthimetic, so the
328  * RHS will be a larger number.
329  * Case B from RFC4303 Appendix A.
330  */
332  {
333  /*
334  * the sequence number is less than the lower bound.
335  */
336  if (seq <= tl)
337  {
338  /*
339  * the packet is within the window upper bound.
340  * check for duplicates.
341  */
342  sa->seq_hi = th;
343  return (sa->replay_window & (1ULL << diff)) ? 1 : 0;
344  }
345  else
346  {
347  /*
348  * the packet is less the window lower bound or greater than
349  * the higher bound, depending on how you look at it...
350  * We're assuming, given that the last sequence number received,
351  * TL < WINDOW_SIZE, that a largeer seq num is more likely to be
352  * a packet that moves the window forward, than a packet that has
353  * wrapped the high sequence again. If it were the latter then
354  * we've lost close to 2^32 packets.
355  */
356  sa->seq_hi = th;
357  return 0;
358  }
359  }
360  else
361  {
362  /*
363  * the packet seq number is between the lower bound (a large nubmer)
364  * and MAX_SEQ_NUM. This is in the window since the window upper bound
365  * tl > 0.
366  * However, since TL is the other side of 0 to the received
367  * packet, the SA has moved on to a higher sequence number.
368  */
369  sa->seq_hi = th - 1;
370  return (sa->replay_window & (1ULL << diff)) ? 1 : 0;
371  }
372  }
373 
374  return 0;
375 }
376 
377 /*
378  * Anti replay window advance
379  * inputs need to be in host byte order.
380  */
381 always_inline void
383 {
384  u32 pos;
385  if (PREDICT_TRUE (sa->flags & IPSEC_SA_FLAG_USE_ANTI_REPLAY) == 0)
386  return;
387 
388  if (PREDICT_TRUE (sa->flags & IPSEC_SA_FLAG_USE_ESN))
389  {
390  int wrap = sa->seq_hi - sa->last_seq_hi;
391 
392  if (wrap == 0 && seq > sa->last_seq)
393  {
394  pos = seq - sa->last_seq;
396  sa->replay_window = ((sa->replay_window) << pos) | 1;
397  else
398  sa->replay_window = 1;
399  sa->last_seq = seq;
400  }
401  else if (wrap > 0)
402  {
403  pos = ~seq + sa->last_seq + 1;
405  sa->replay_window = ((sa->replay_window) << pos) | 1;
406  else
407  sa->replay_window = 1;
408  sa->last_seq = seq;
409  sa->last_seq_hi = sa->seq_hi;
410  }
411  else if (wrap < 0)
412  {
413  pos = ~seq + sa->last_seq + 1;
414  sa->replay_window |= (1ULL << pos);
415  }
416  else
417  {
418  pos = sa->last_seq - seq;
419  sa->replay_window |= (1ULL << pos);
420  }
421  }
422  else
423  {
424  if (seq > sa->last_seq)
425  {
426  pos = seq - sa->last_seq;
428  sa->replay_window = ((sa->replay_window) << pos) | 1;
429  else
430  sa->replay_window = 1;
431  sa->last_seq = seq;
432  }
433  else
434  {
435  pos = sa->last_seq - seq;
436  sa->replay_window |= (1ULL << pos);
437  }
438  }
439 }
440 
441 
442 /*
443  * Makes choice for thread_id should be assigned.
444  * if input ~0, gets random worker_id based on unix_time_now_nsec
445 */
448 {
449  return ((thread_id) ? thread_id
450  : (unix_time_now_nsec () % vlib_num_workers ()) + 1);
451 }
452 
453 #endif /* __IPSEC_SPD_SA_H__ */
454 
455 /*
456  * fd.io coding-style-patch-verification: ON
457  *
458  * Local Variables:
459  * eval: (c-set-style "gnu")
460  * End:
461  */
u32 spi
fib_node_t node
Definition: ipsec_sa.h:143
u8 proto
Definition: acl_types.api:47
#define CLIB_CACHE_LINE_ALIGN_MARK(mark)
Definition: cache.h:60
ip46_address_t tunnel_src_addr
Definition: ipsec_sa.h:156
#define PREDICT_TRUE(x)
Definition: clib.h:112
ipsec_integ_alg_t
Definition: ipsec_sa.h:58
unsigned long u64
Definition: types.h:89
uword unformat_ipsec_integ_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:128
static u32 ipsec_sa_assign_thread(u32 thread_id)
Definition: ipsec_sa.h:447
#define foreach_ipsec_crypto_alg
Definition: ipsec_sa.h:22
ipsec_key_t crypto_key
Definition: ipsec_sa.h:149
ipsec_integ_alg_t integ_alg
Definition: ipsec_sa.h:152
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
ipsec_protocol_t
Definition: ipsec_sa.h:66
u32 tx_table_id
#define foreach_ipsec_integ_alg
Definition: ipsec_sa.h:49
u8 * format_ipsec_integ_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:110
int ipsec_sa_unlock_id(u32 id)
Definition: ipsec_sa.c:356
vnet_crypto_op_id_t integ_op_id
Definition: ipsec_sa.h:131
void ipsec_sa_unlock(index_t sai)
Definition: ipsec_sa.c:309
unsigned char u8
Definition: types.h:56
u32 seq_hi
Definition: ipsec_sa.h:121
enum walk_rc_t_ walk_rc_t
Walk return code.
vnet_crypto_key_index_t crypto_key_index
Definition: ipsec_sa.h:127
u64 replay_window
Definition: ipsec_sa.h:124
walk_rc_t(* ipsec_sa_walk_cb_t)(ipsec_sa_t *sa, void *ctx)
Definition: ipsec_sa.h:223
uword unformat_ipsec_key(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:242
u32 salt
unsigned int u32
Definition: types.h:88
#define foreach_ipsec_sa_flags
Definition: ipsec_sa.h:87
ipsec_sa_flags_t flags
Definition: ipsec_sa.h:112
vnet_crypto_alg_t
Definition: crypto.h:86
u32 stat_index
Definition: ipsec_sa.h:145
u32 last_seq
Definition: ipsec_sa.h:122
u8 * format_ipsec_crypto_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:78
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
u32 encrypt_thread_index
Definition: ipsec_sa.h:117
u32 tx_fib_index
Definition: ipsec_sa.h:162
long ctx[MAX_CONNS]
Definition: main.c:144
u32 salt
Definition: ipsec_sa.h:165
int ipsec_sa_add_and_lock(u32 id, u32 spi, ipsec_protocol_t proto, ipsec_crypto_alg_t crypto_alg, const ipsec_key_t *ck, ipsec_integ_alg_t integ_alg, const ipsec_key_t *ik, ipsec_sa_flags_t flags, u32 tx_table_id, u32 salt, const ip46_address_t *tunnel_src_addr, const ip46_address_t *tunnel_dst_addr, u32 *sa_index)
Definition: ipsec_sa.c:127
struct _unformat_input_t unformat_input_t
static void ipsec_sa_anti_replay_advance(ipsec_sa_t *sa, u32 seq)
Definition: ipsec_sa.h:382
fib_node_index_t fib_entry_index
Definition: ipsec_sa.h:159
u32 last_seq_hi
Definition: ipsec_sa.h:123
#define IPSEC_KEY_MAX_LEN
Definition: ipsec_sa.h:72
#define always_inline
Definition: ipsec.h:28
ipsec_sad_flags_t_
Definition: ipsec_sa.h:98
An node in the FIB graph.
Definition: fib_node.h:295
void ipsec_sa_set_crypto_alg(ipsec_sa_t *sa, ipsec_crypto_alg_t crypto_alg)
Definition: ipsec_sa.c:97
ip46_address_t tunnel_dst_addr
Definition: ipsec_sa.h:157
u32 flags
Definition: vhost_user.h:141
void ipsec_sa_lock(index_t sai)
Definition: ipsec_sa.c:323
foreach_ipsec_sa_flags vlib_combined_counter_main_t ipsec_sa_counters
SA packet & bytes counters.
Definition: ipsec_sa.c:27
udp_header_t udp_hdr
Definition: ipsec_sa.h:141
enum ipsec_sad_flags_t_ ipsec_sa_flags_t
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
static u64 unix_time_now_nsec(void)
Definition: time.h:264
u8 * format_ipsec_sa(u8 *s, va_list *args)
Definition: ipsec_format.c:269
#define IPSEC_SA_ANTI_REPLAY_WINDOW_MAX_INDEX
Definition: ipsec_sa.h:241
u8 data[IPSEC_KEY_MAX_LEN]
Definition: ipsec_sa.h:76
ip6_header_t ip6_hdr
Definition: ipsec_sa.h:139
STATIC_ASSERT_OFFSET_OF(ipsec_sa_t, cacheline1, CLIB_CACHE_LINE_BYTES)
u32 vnet_crypto_key_index_t
Definition: crypto.h:159
static int ipsec_sa_anti_replay_check(ipsec_sa_t *sa, u32 seq)
Definition: ipsec_sa.h:255
ipsec_protocol_t protocol
Definition: ipsec_sa.h:146
u32 sibling
Definition: ipsec_sa.h:160
vnet_crypto_key_index_t integ_key_index
Definition: ipsec_sa.h:128
vnet_crypto_alg_t integ_calg
Definition: ipsec_sa.h:154
void ipsec_sa_walk(ipsec_sa_walk_cb_t cd, void *ctx)
Definition: ipsec_sa.c:378
u8 * format_ipsec_key(u8 *s, va_list *args)
Definition: ipsec_format.c:234
vnet_crypto_alg_t crypto_calg
Definition: ipsec_sa.h:150
typedef key
Definition: ipsec_types.api:83
void ipsec_sa_set_integ_alg(ipsec_sa_t *sa, ipsec_integ_alg_t integ_alg)
Definition: ipsec_sa.c:116
uword unformat_ipsec_crypto_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:96
#define IPSEC_SA_ANTI_REPLAY_WINDOW_LOWER_BOUND(_tl)
Definition: ipsec_sa.h:248
u64 uword
Definition: types.h:112
void ipsec_mk_key(ipsec_key_t *key, const u8 *data, u8 len)
Definition: ipsec_sa.c:56
#define IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE
Definition: ipsec_sa.h:240
ipsec_crypto_alg_t
Definition: ipsec_sa.h:36
u64 gcm_iv_counter
Definition: ipsec_sa.h:166
index_t ipsec_sa_find_and_lock(u32 id)
Definition: ipsec_sa.c:337
vnet_crypto_op_id_t crypto_enc_op_id
Definition: ipsec_sa.h:129
A collection of combined counters.
Definition: counter.h:188
vnet_crypto_op_id_t
Definition: crypto.h:105
dpo_id_t dpo
Definition: ipsec_sa.h:125
ipsec_crypto_alg_t crypto_alg
Definition: ipsec_sa.h:148
ip4_header_t ip4_hdr
Definition: ipsec_sa.h:138
static u32 vlib_num_workers()
Definition: threads.h:372
u8 crypto_block_size
Definition: ipsec_sa.h:115
struct ipsec_key_t_ ipsec_key_t
u8 crypto_iv_size
Definition: ipsec_sa.h:114
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
ipsec_key_t integ_key
Definition: ipsec_sa.h:153
void ipsec_sa_clear(index_t sai)
Definition: ipsec_sa.c:372
vnet_crypto_op_id_t crypto_dec_op_id
Definition: ipsec_sa.h:130
u8 integ_icv_size
Definition: ipsec_sa.h:116
u32 decrypt_thread_index
Definition: ipsec_sa.h:118
STATIC_ASSERT(sizeof(ipsec_sa_flags_t)==1, "IPSEC SA flags > 1 byte")