FD.io VPP  v19.04.4-rc0-5-ge88582fac
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 IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE (64)
23 
24 #define foreach_ipsec_crypto_alg \
25  _ (0, NONE, "none") \
26  _ (1, AES_CBC_128, "aes-cbc-128") \
27  _ (2, AES_CBC_192, "aes-cbc-192") \
28  _ (3, AES_CBC_256, "aes-cbc-256") \
29  _ (4, AES_CTR_128, "aes-ctr-128") \
30  _ (5, AES_CTR_192, "aes-ctr-192") \
31  _ (6, AES_CTR_256, "aes-ctr-256") \
32  _ (7, AES_GCM_128, "aes-gcm-128") \
33  _ (8, AES_GCM_192, "aes-gcm-192") \
34  _ (9, AES_GCM_256, "aes-gcm-256") \
35  _ (10, DES_CBC, "des-cbc") \
36  _ (11, 3DES_CBC, "3des-cbc")
37 
38 typedef enum
39 {
40 #define _(v, f, s) IPSEC_CRYPTO_ALG_##f = v,
42 #undef _
45 
46 #define IPSEC_CRYPTO_ALG_IS_GCM(_alg) \
47  (((_alg == IPSEC_CRYPTO_ALG_AES_GCM_128) || \
48  (_alg == IPSEC_CRYPTO_ALG_AES_GCM_192) || \
49  (_alg == IPSEC_CRYPTO_ALG_AES_GCM_256)))
50 
51 #define foreach_ipsec_integ_alg \
52  _ (0, NONE, "none") \
53  _ (1, MD5_96, "md5-96") /* RFC2403 */ \
54  _ (2, SHA1_96, "sha1-96") /* RFC2404 */ \
55  _ (3, SHA_256_96, "sha-256-96") /* draft-ietf-ipsec-ciph-sha-256-00 */ \
56  _ (4, SHA_256_128, "sha-256-128") /* RFC4868 */ \
57  _ (5, SHA_384_192, "sha-384-192") /* RFC4868 */ \
58  _ (6, SHA_512_256, "sha-512-256") /* RFC4868 */
59 
60 typedef enum
61 {
62 #define _(v, f, s) IPSEC_INTEG_ALG_##f = v,
64 #undef _
67 
68 typedef enum
69 {
73 
74 #define IPSEC_N_PROTOCOLS (IPSEC_PROTOCOL_ESP+1)
75 
76 #define IPSEC_KEY_MAX_LEN 128
77 typedef struct ipsec_key_t_
78 {
81 } ipsec_key_t;
82 
83 /*
84  * Enable extended sequence numbers
85  * Enable Anti-replay
86  * IPsec tunnel mode if non-zero, else transport mode
87  * IPsec tunnel mode is IPv6 if non-zero,
88  * else IPv4 tunnel only valid if is_tunnel is non-zero
89  * enable UDP encapsulation for NAT traversal
90  */
91 #define foreach_ipsec_sa_flags \
92  _ (0, NONE, "none") \
93  _ (1, USE_ESN, "esn") \
94  _ (2, USE_ANTI_REPLAY, "anti-replay") \
95  _ (4, IS_TUNNEL, "tunnel") \
96  _ (8, IS_TUNNEL_V6, "tunnel-v6") \
97  _ (16, UDP_ENCAP, "udp-encap") \
98  _ (32, IS_GRE, "GRE") \
99  _ (64, IS_INBOUND, "inboud") \
100  _ (128, IS_AEAD, "aead") \
101 
102 typedef enum ipsec_sad_flags_t_
103 {
104 #define _(v, f, s) IPSEC_SA_FLAG_##f = v,
106 #undef _
107 } __clib_packed ipsec_sa_flags_t;
108 
109 STATIC_ASSERT (sizeof (ipsec_sa_flags_t) == 1, "IPSEC SA flags > 1 byte");
110 
111 typedef struct
112 {
113  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
114 
115  /* flags */
116  ipsec_sa_flags_t flags;
117 
127 
131 
133 
134  /* data accessed by dataplane code should be above this comment */
135  CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
136 
137  union
138  {
141  };
143 
144 
149 
150  ipsec_crypto_alg_t crypto_alg;
152 
153  ipsec_integ_alg_t integ_alg;
155 
156  ip46_address_t tunnel_src_addr;
157  ip46_address_t tunnel_dst_addr;
158 
161 
164 
165  /* runtime */
166 } ipsec_sa_t;
167 
169 
170 #define _(a,v,s) \
171  always_inline int \
172  ipsec_sa_is_set_##v (const ipsec_sa_t *sa) { \
173  return (sa->flags & IPSEC_SA_FLAG_##v); \
174  }
176 #undef _
177 #define _(a,v,s) \
178  always_inline int \
179  ipsec_sa_set_##v (ipsec_sa_t *sa) { \
180  return (sa->flags |= IPSEC_SA_FLAG_##v); \
181  }
183 #undef _
184 /**
185  * @brief
186  * SA packet & bytes counters
187  */
189 
190 extern void ipsec_mk_key (ipsec_key_t * key, const u8 * data, u8 len);
191 
192 extern int ipsec_sa_add (u32 id,
193  u32 spi,
194  ipsec_protocol_t proto,
195  ipsec_crypto_alg_t crypto_alg,
196  const ipsec_key_t * ck,
197  ipsec_integ_alg_t integ_alg,
198  const ipsec_key_t * ik,
199  ipsec_sa_flags_t flags,
201  u32 salt,
202  const ip46_address_t * tunnel_src_addr,
203  const ip46_address_t * tunnel_dst_addr,
204  u32 * sa_index);
205 extern u32 ipsec_sa_del (u32 id);
206 extern void ipsec_sa_set_crypto_alg (ipsec_sa_t * sa,
207  ipsec_crypto_alg_t crypto_alg);
208 extern void ipsec_sa_set_integ_alg (ipsec_sa_t * sa,
209  ipsec_integ_alg_t integ_alg);
210 
211 extern u8 ipsec_is_sa_used (u32 sa_index);
212 extern int ipsec_set_sa_key (u32 id,
213  const ipsec_key_t * ck, const ipsec_key_t * ik);
215 
216 typedef walk_rc_t (*ipsec_sa_walk_cb_t) (ipsec_sa_t * sa, void *ctx);
217 extern void ipsec_sa_walk (ipsec_sa_walk_cb_t cd, void *ctx);
218 
219 extern u8 *format_ipsec_crypto_alg (u8 * s, va_list * args);
220 extern u8 *format_ipsec_integ_alg (u8 * s, va_list * args);
221 extern u8 *format_ipsec_sa (u8 * s, va_list * args);
222 extern u8 *format_ipsec_key (u8 * s, va_list * args);
224  va_list * args);
226  va_list * args);
227 extern uword unformat_ipsec_key (unformat_input_t * input, va_list * args);
228 
229 always_inline int
231 {
232  u32 seq, diff, tl, th;
233  if ((sa->flags & IPSEC_SA_FLAG_USE_ANTI_REPLAY) == 0)
234  return 0;
235 
236  seq = clib_net_to_host_u32 (*seqp);
237 
238  if ((sa->flags & IPSEC_SA_FLAG_USE_ESN) == 0)
239  {
240 
241  if (PREDICT_TRUE (seq > sa->last_seq))
242  return 0;
243 
244  diff = sa->last_seq - seq;
245 
247  return (sa->replay_window & (1ULL << diff)) ? 1 : 0;
248  else
249  return 1;
250 
251  return 0;
252  }
253 
254  tl = sa->last_seq;
255  th = sa->last_seq_hi;
256  diff = tl - seq;
257 
259  {
260  if (seq >= (tl - IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE + 1))
261  {
262  sa->seq_hi = th;
263  if (seq <= tl)
264  return (sa->replay_window & (1ULL << diff)) ? 1 : 0;
265  else
266  return 0;
267  }
268  else
269  {
270  sa->seq_hi = th + 1;
271  return 0;
272  }
273  }
274  else
275  {
276  if (seq >= (tl - IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE + 1))
277  {
278  sa->seq_hi = th - 1;
279  return (sa->replay_window & (1ULL << diff)) ? 1 : 0;
280  }
281  else
282  {
283  sa->seq_hi = th;
284  if (seq <= tl)
285  return (sa->replay_window & (1ULL << diff)) ? 1 : 0;
286  else
287  return 0;
288  }
289  }
290 
291  return 0;
292 }
293 
294 always_inline void
296 {
297  u32 pos, seq;
298  if (PREDICT_TRUE (sa->flags & IPSEC_SA_FLAG_USE_ANTI_REPLAY) == 0)
299  return;
300 
301  seq = clib_host_to_net_u32 (*seqp);
302  if (PREDICT_TRUE (sa->flags & IPSEC_SA_FLAG_USE_ESN))
303  {
304  int wrap = sa->seq_hi - sa->last_seq_hi;
305 
306  if (wrap == 0 && seq > sa->last_seq)
307  {
308  pos = seq - sa->last_seq;
310  sa->replay_window = ((sa->replay_window) << pos) | 1;
311  else
312  sa->replay_window = 1;
313  sa->last_seq = seq;
314  }
315  else if (wrap > 0)
316  {
317  pos = ~seq + sa->last_seq + 1;
319  sa->replay_window = ((sa->replay_window) << pos) | 1;
320  else
321  sa->replay_window = 1;
322  sa->last_seq = seq;
323  sa->last_seq_hi = sa->seq_hi;
324  }
325  else if (wrap < 0)
326  {
327  pos = ~seq + sa->last_seq + 1;
328  sa->replay_window |= (1ULL << pos);
329  }
330  else
331  {
332  pos = sa->last_seq - seq;
333  sa->replay_window |= (1ULL << pos);
334  }
335  }
336  else
337  {
338  if (seq > sa->last_seq)
339  {
340  pos = seq - sa->last_seq;
342  sa->replay_window = ((sa->replay_window) << pos) | 1;
343  else
344  sa->replay_window = 1;
345  sa->last_seq = seq;
346  }
347  else
348  {
349  pos = sa->last_seq - seq;
350  sa->replay_window |= (1ULL << pos);
351  }
352  }
353 }
354 
355 #endif /* __IPSEC_SPD_SA_H__ */
356 
357 /*
358  * fd.io coding-style-patch-verification: ON
359  *
360  * Local Variables:
361  * eval: (c-set-style "gnu")
362  * End:
363  */
u32 tx_table_id
Definition: ipsec.api:284
fib_node_t node
Definition: ipsec_sa.h:145
static int ipsec_sa_anti_replay_check(ipsec_sa_t *sa, u32 *seqp)
Definition: ipsec_sa.h:230
#define CLIB_CACHE_LINE_ALIGN_MARK(mark)
Definition: cache.h:60
u32 flags
Definition: vhost_user.h:115
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:60
unsigned long u64
Definition: types.h:89
uword unformat_ipsec_integ_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:127
#define foreach_ipsec_crypto_alg
Definition: ipsec_sa.h:24
ipsec_key_t crypto_key
Definition: ipsec_sa.h:151
ipsec_integ_alg_t integ_alg
Definition: ipsec_sa.h:153
ipsec_protocol_t
Definition: ipsec_sa.h:68
#define foreach_ipsec_integ_alg
Definition: ipsec_sa.h:51
u8 * format_ipsec_integ_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:109
int ipsec_set_sa_key(u32 id, const ipsec_key_t *ck, const ipsec_key_t *ik)
Definition: ipsec_sa.c:321
vnet_crypto_op_id_t integ_op_id
Definition: ipsec_sa.h:130
static void ipsec_sa_anti_replay_advance(ipsec_sa_t *sa, u32 *seqp)
Definition: ipsec_sa.h:295
int ipsec_sa_add(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:123
unsigned char u8
Definition: types.h:56
u32 seq_hi
Definition: ipsec_sa.h:123
enum walk_rc_t_ walk_rc_t
Walk return code.
u64 replay_window
Definition: ipsec_sa.h:126
walk_rc_t(* ipsec_sa_walk_cb_t)(ipsec_sa_t *sa, void *ctx)
Definition: ipsec_sa.h:216
#define always_inline
Definition: clib.h:98
uword unformat_ipsec_key(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:241
unsigned int u32
Definition: types.h:88
#define foreach_ipsec_sa_flags
Definition: ipsec_sa.h:91
ipsec_sa_flags_t flags
Definition: ipsec_sa.h:116
u32 stat_index
Definition: ipsec_sa.h:147
u32 last_seq
Definition: ipsec_sa.h:124
u8 * format_ipsec_crypto_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:77
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
u32 tx_fib_index
Definition: ipsec_sa.h:162
u32 sa_id
Definition: ipsec.api:94
u8 ipsec_is_sa_used(u32 sa_index)
Definition: ipsec_sa.c:294
#define IPSEC_N_PROTOCOLS
Definition: ipsec_sa.h:74
long ctx[MAX_CONNS]
Definition: main.c:144
u32 salt
Definition: ipsec_sa.h:163
struct _unformat_input_t unformat_input_t
fib_node_index_t fib_entry_index
Definition: ipsec_sa.h:159
u32 last_seq_hi
Definition: ipsec_sa.h:125
u32 ipsec_sa_del(u32 id)
Definition: ipsec_sa.c:254
#define IPSEC_KEY_MAX_LEN
Definition: ipsec_sa.h:76
ipsec_sad_flags_t_
Definition: ipsec_sa.h:102
An node in the FIB graph.
Definition: fib_node.h:291
void ipsec_sa_set_crypto_alg(ipsec_sa_t *sa, ipsec_crypto_alg_t crypto_alg)
Definition: ipsec_sa.c:95
ip46_address_t tunnel_dst_addr
Definition: ipsec_sa.h:157
foreach_ipsec_sa_flags vlib_combined_counter_main_t ipsec_sa_counters
SA packet & bytes counters.
Definition: ipsec_sa.c:25
u32 ipsec_get_sa_index_by_sa_id(u32 sa_id)
Definition: ipsec_sa.c:362
udp_header_t udp_hdr
Definition: ipsec_sa.h:142
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
u8 * format_ipsec_sa(u8 *s, va_list *args)
Definition: ipsec_format.c:270
u8 data[IPSEC_KEY_MAX_LEN]
Definition: ipsec_sa.h:80
u32 spi
Definition: ipsec.api:270
ip6_header_t ip6_hdr
Definition: ipsec_sa.h:140
STATIC_ASSERT_OFFSET_OF(ipsec_sa_t, cacheline1, CLIB_CACHE_LINE_BYTES)
ipsec_protocol_t protocol
Definition: ipsec_sa.h:148
u32 sibling
Definition: ipsec_sa.h:160
void ipsec_sa_walk(ipsec_sa_walk_cb_t cd, void *ctx)
Definition: ipsec_sa.c:373
u8 * format_ipsec_key(u8 *s, va_list *args)
Definition: ipsec_format.c:233
void ipsec_sa_set_integ_alg(ipsec_sa_t *sa, ipsec_integ_alg_t integ_alg)
Definition: ipsec_sa.c:113
uword unformat_ipsec_crypto_alg(unformat_input_t *input, va_list *args)
Definition: ipsec_format.c:95
u64 uword
Definition: types.h:112
void ipsec_mk_key(ipsec_key_t *key, const u8 *data, u8 len)
Definition: ipsec_sa.c:54
#define IPSEC_SA_ANTI_REPLAY_WINDOW_SIZE
Definition: ipsec_sa.h:22
ipsec_crypto_alg_t
Definition: ipsec_sa.h:38
typedef key
Definition: ipsec.api:244
vnet_crypto_op_id_t crypto_enc_op_id
Definition: ipsec_sa.h:128
A collection of combined counters.
Definition: counter.h:188
vnet_crypto_op_id_t
Definition: crypto.h:87
ipsec_crypto_alg_t crypto_alg
Definition: ipsec_sa.h:150
ip4_header_t ip4_hdr
Definition: ipsec_sa.h:139
u8 crypto_block_size
Definition: ipsec_sa.h:119
struct ipsec_key_t_ ipsec_key_t
u8 crypto_iv_size
Definition: ipsec_sa.h:118
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
ipsec_key_t integ_key
Definition: ipsec_sa.h:154
vnet_crypto_op_id_t crypto_dec_op_id
Definition: ipsec_sa.h:129
u8 integ_icv_size
Definition: ipsec_sa.h:120
STATIC_ASSERT(sizeof(ipsec_sa_flags_t)==1, "IPSEC SA flags > 1 byte")