FD.io VPP  v19.08-27-gf4dcae4
Vector Packet Processing
ipsec.c
Go to the documentation of this file.
1 /*
2  * ipsec.c : IPSEC module functions
3  *
4  * Copyright (c) 2015 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <vnet/vnet.h>
19 #include <vnet/api_errno.h>
20 #include <vnet/ip/ip.h>
21 #include <vnet/interface.h>
22 #include <vnet/udp/udp.h>
23 
24 #include <vnet/ipsec/ipsec.h>
25 #include <vnet/ipsec/esp.h>
26 #include <vnet/ipsec/ah.h>
27 
29 
30 static clib_error_t *
32 {
33  ipsec_main_t *im = &ipsec_main;
34 
35  if (sa->integ_alg == IPSEC_INTEG_ALG_NONE)
36  return clib_error_return (0, "unsupported none integ-alg");
37 
39  return clib_error_return (0, "No crypto engine support for %U",
41 
42  return 0;
43 }
44 
45 static clib_error_t *
47 {
48  ipsec_main_t *im = &ipsec_main;
49 
50  if (IPSEC_INTEG_ALG_NONE != sa->integ_alg)
51  {
53  return clib_error_return (0, "No crypto engine support for %U",
55  }
56  if (IPSEC_CRYPTO_ALG_NONE != sa->crypto_alg)
57  {
59  return clib_error_return (0, "No crypto engine support for %U",
61  }
62 
63  return (0);
64 }
65 
67 ipsec_add_del_sa_sess_cb (ipsec_main_t * im, u32 sa_index, u8 is_add)
68 {
69  ipsec_ah_backend_t *ah =
71  if (ah->add_del_sa_sess_cb)
72  {
73  clib_error_t *err = ah->add_del_sa_sess_cb (sa_index, is_add);
74  if (err)
75  return err;
76  }
77  ipsec_esp_backend_t *esp =
79  if (esp->add_del_sa_sess_cb)
80  {
81  clib_error_t *err = esp->add_del_sa_sess_cb (sa_index, is_add);
82  if (err)
83  return err;
84  }
85  return 0;
86 }
87 
90 {
91  clib_error_t *error = 0;
92 
94  {
95  ipsec_ah_backend_t *ah =
98  error = ah->check_support_cb (sa);
99  }
100  else
101  {
102  ipsec_esp_backend_t *esp =
104  ASSERT (esp->check_support_cb);
105  error = esp->check_support_cb (sa);
106  }
107  return error;
108 }
109 
110 
111 static void
112 ipsec_add_node (vlib_main_t * vm, const char *node_name,
113  const char *prev_node_name, u32 * out_node_index,
114  u32 * out_next_index)
115 {
116  vlib_node_t *prev_node, *node;
117  prev_node = vlib_get_node_by_name (vm, (u8 *) prev_node_name);
118  ASSERT (prev_node);
119  node = vlib_get_node_by_name (vm, (u8 *) node_name);
120  ASSERT (node);
121  *out_node_index = node->index;
122  *out_next_index = vlib_node_add_next (vm, prev_node->index, node->index);
123 }
124 
125 void
126 ipsec_add_feature (const char *arc_name,
127  const char *node_name, u32 * out_feature_index)
128 {
129  u8 arc;
130 
131  arc = vnet_get_feature_arc_index (arc_name);
132  ASSERT (arc != (u8) ~ 0);
133  *out_feature_index = vnet_get_feature_index (arc, node_name);
134 }
135 
136 u32
138  const char *name,
139  const char *ah4_encrypt_node_name,
140  const char *ah4_decrypt_node_name,
141  const char *ah6_encrypt_node_name,
142  const char *ah6_decrypt_node_name,
143  check_support_cb_t ah_check_support_cb,
144  add_del_sa_sess_cb_t ah_add_del_sa_sess_cb)
145 {
147  pool_get (im->ah_backends, b);
148  b->name = format (0, "%s%c", name, 0);
149 
150  ipsec_add_node (vm, ah4_encrypt_node_name, "ipsec4-output-feature",
152  ipsec_add_node (vm, ah4_decrypt_node_name, "ipsec4-input-feature",
154  ipsec_add_node (vm, ah6_encrypt_node_name, "ipsec6-output-feature",
156  ipsec_add_node (vm, ah6_decrypt_node_name, "ipsec6-input-feature",
158 
159  b->check_support_cb = ah_check_support_cb;
160  b->add_del_sa_sess_cb = ah_add_del_sa_sess_cb;
161  return b - im->ah_backends;
162 }
163 
164 u32
166  const char *name,
167  const char *esp4_encrypt_node_name,
168  const char *esp4_encrypt_node_tun_name,
169  const char *esp4_decrypt_node_name,
170  const char *esp6_encrypt_node_name,
171  const char *esp6_encrypt_node_tun_name,
172  const char *esp6_decrypt_node_name,
173  check_support_cb_t esp_check_support_cb,
174  add_del_sa_sess_cb_t esp_add_del_sa_sess_cb)
175 {
177 
178  pool_get (im->esp_backends, b);
179  b->name = format (0, "%s%c", name, 0);
180 
181  ipsec_add_node (vm, esp4_encrypt_node_name, "ipsec4-output-feature",
183  ipsec_add_node (vm, esp4_decrypt_node_name, "ipsec4-input-feature",
185  ipsec_add_node (vm, esp6_encrypt_node_name, "ipsec6-output-feature",
187  ipsec_add_node (vm, esp6_decrypt_node_name, "ipsec6-input-feature",
189 
190  ipsec_add_feature ("ip4-output", esp4_encrypt_node_tun_name,
192  ipsec_add_feature ("ip6-output", esp6_encrypt_node_tun_name,
194 
195  b->check_support_cb = esp_check_support_cb;
196  b->add_del_sa_sess_cb = esp_add_del_sa_sess_cb;
197  return b - im->esp_backends;
198 }
199 
200 clib_error_t *
202 {
203  /* return an error is crypto resource are in use */
204  if (pool_elts (im->sad) > 0)
205  return clib_error_return (0,
206  "%d SA entries configured",
207  pool_elts (im->sad));
208 
209  if (pool_elts (im->tunnel_interfaces))
210  return clib_error_return (0,
211  "%d tunnel-interface entries configured",
213 
214  return (NULL);
215 }
216 
217 int
219 {
220  if (ipsec_rsc_in_use (im))
221  return VNET_API_ERROR_RSRC_IN_USE;
222 
223  if (pool_is_free_index (im->ah_backends, backend_idx))
224  return VNET_API_ERROR_INVALID_VALUE;
225 
226  ipsec_ah_backend_t *b = pool_elt_at_index (im->ah_backends, backend_idx);
227  im->ah_current_backend = backend_idx;
236 
237  return 0;
238 }
239 
240 int
242 {
243  if (ipsec_rsc_in_use (im))
244  return VNET_API_ERROR_RSRC_IN_USE;
245 
246  if (pool_is_free_index (im->esp_backends, backend_idx))
247  return VNET_API_ERROR_INVALID_VALUE;
248 
249  ipsec_esp_backend_t *b = pool_elt_at_index (im->esp_backends, backend_idx);
250  im->esp_current_backend = backend_idx;
259 
262 
263  return 0;
264 }
265 
266 static clib_error_t *
268 {
269  clib_error_t *error;
270  ipsec_main_t *im = &ipsec_main;
272 
273  /* Backend registration requires the feature arcs to be set up */
274  if ((error = vlib_call_init_function (vm, vnet_feature_init)))
275  return (error);
276 
277  im->vnet_main = vnet_get_main ();
278  im->vlib_main = vm;
279 
280  im->spd_index_by_spd_id = hash_create (0, sizeof (uword));
281  im->sa_index_by_sa_id = hash_create (0, sizeof (uword));
282  im->spd_index_by_sw_if_index = hash_create (0, sizeof (uword));
283 
284  vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
285  ASSERT (node);
286  im->error_drop_node_index = node->index;
287 
288  u32 idx = ipsec_register_ah_backend (vm, im, "crypto engine backend",
289  "ah4-encrypt",
290  "ah4-decrypt",
291  "ah6-encrypt",
292  "ah6-decrypt",
294  NULL);
295 
296  im->ah_default_backend = idx;
297  int rv = ipsec_select_ah_backend (im, idx);
298  ASSERT (0 == rv);
299  (void) (rv); // avoid warning
300 
301  idx = ipsec_register_esp_backend (vm, im, "crypto engine backend",
302  "esp4-encrypt",
303  "esp4-encrypt-tun",
304  "esp4-decrypt",
305  "esp6-encrypt",
306  "esp6-encrypt-tun",
307  "esp6-decrypt",
309  im->esp_default_backend = idx;
310 
311  rv = ipsec_select_esp_backend (im, idx);
312  ASSERT (0 == rv);
313  (void) (rv); // avoid warning
314 
315  if ((error = vlib_call_init_function (vm, ipsec_cli_init)))
316  return error;
317 
318  if ((error = vlib_call_init_function (vm, ipsec_tunnel_if_init)))
319  return error;
320 
322 
323  a = im->crypto_algs + IPSEC_CRYPTO_ALG_DES_CBC;
324  a->enc_op_id = VNET_CRYPTO_OP_DES_CBC_ENC;
325  a->dec_op_id = VNET_CRYPTO_OP_DES_CBC_DEC;
326  a->alg = VNET_CRYPTO_ALG_DES_CBC;
327  a->iv_size = a->block_size = 8;
328 
329  a = im->crypto_algs + IPSEC_CRYPTO_ALG_3DES_CBC;
330  a->enc_op_id = VNET_CRYPTO_OP_3DES_CBC_ENC;
331  a->dec_op_id = VNET_CRYPTO_OP_3DES_CBC_DEC;
332  a->alg = VNET_CRYPTO_ALG_3DES_CBC;
333  a->iv_size = a->block_size = 8;
334 
335  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_128;
336  a->enc_op_id = VNET_CRYPTO_OP_AES_128_CBC_ENC;
337  a->dec_op_id = VNET_CRYPTO_OP_AES_128_CBC_DEC;
338  a->alg = VNET_CRYPTO_ALG_AES_128_CBC;
339  a->iv_size = a->block_size = 16;
340 
341  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_192;
342  a->enc_op_id = VNET_CRYPTO_OP_AES_192_CBC_ENC;
343  a->dec_op_id = VNET_CRYPTO_OP_AES_192_CBC_DEC;
344  a->alg = VNET_CRYPTO_ALG_AES_192_CBC;
345  a->iv_size = a->block_size = 16;
346 
347  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_256;
348  a->enc_op_id = VNET_CRYPTO_OP_AES_256_CBC_ENC;
349  a->dec_op_id = VNET_CRYPTO_OP_AES_256_CBC_DEC;
350  a->alg = VNET_CRYPTO_ALG_AES_256_CBC;
351  a->iv_size = a->block_size = 16;
352 
353  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_128;
354  a->enc_op_id = VNET_CRYPTO_OP_AES_128_GCM_ENC;
355  a->dec_op_id = VNET_CRYPTO_OP_AES_128_GCM_DEC;
356  a->alg = VNET_CRYPTO_ALG_AES_128_GCM;
357  a->iv_size = a->block_size = 8;
358  a->icv_size = 16;
359 
360  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_192;
361  a->enc_op_id = VNET_CRYPTO_OP_AES_192_GCM_ENC;
362  a->dec_op_id = VNET_CRYPTO_OP_AES_192_GCM_DEC;
363  a->alg = VNET_CRYPTO_ALG_AES_192_GCM;
364  a->iv_size = a->block_size = 8;
365  a->icv_size = 16;
366 
367  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_256;
368  a->enc_op_id = VNET_CRYPTO_OP_AES_256_GCM_ENC;
369  a->dec_op_id = VNET_CRYPTO_OP_AES_256_GCM_DEC;
370  a->alg = VNET_CRYPTO_ALG_AES_256_GCM;
371  a->iv_size = a->block_size = 8;
372  a->icv_size = 16;
373 
376 
377  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA1_96];
378  i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
379  i->alg = VNET_CRYPTO_ALG_HMAC_SHA1;
380  i->icv_size = 12;
381 
382  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_96];
383  i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
384  i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
385  i->icv_size = 12;
386 
387  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_128];
388  i->op_id = VNET_CRYPTO_OP_SHA256_HMAC;
389  i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
390  i->icv_size = 16;
391 
392  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_384_192];
393  i->op_id = VNET_CRYPTO_OP_SHA384_HMAC;
394  i->alg = VNET_CRYPTO_ALG_HMAC_SHA384;
395  i->icv_size = 24;
396 
397  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
398  i->op_id = VNET_CRYPTO_OP_SHA512_HMAC;
399  i->alg = VNET_CRYPTO_ALG_HMAC_SHA512;
400  i->icv_size = 32;
401 
403 
404  return 0;
405 }
406 
408 
409 /*
410  * fd.io coding-style-patch-verification: ON
411  *
412  * Local Variables:
413  * eval: (c-set-style "gnu")
414  * End:
415  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
u8 * format_ipsec_integ_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:110
u32 ipsec_register_ah_backend(vlib_main_t *vm, ipsec_main_t *im, const char *name, const char *ah4_encrypt_node_name, const char *ah4_decrypt_node_name, const char *ah6_encrypt_node_name, const char *ah6_decrypt_node_name, check_support_cb_t ah_check_support_cb, add_del_sa_sess_cb_t ah_add_del_sa_sess_cb)
Definition: ipsec.c:137
u32 esp_default_backend
Definition: ipsec.h:160
u32 esp4_encrypt_next_index
Definition: ipsec.h:59
ipsec_main_crypto_alg_t * crypto_algs
Definition: ipsec.h:163
ipsec_tunnel_if_t * tunnel_interfaces
Definition: ipsec.h:102
ipsec_per_thread_data_t * ptd
Definition: ipsec.h:169
u32 esp6_decrypt_node_index
Definition: ipsec.h:128
u8 vnet_get_feature_arc_index(const char *s)
Definition: feature.c:168
u32 ah4_decrypt_next_index
Definition: ipsec.h:135
a
Definition: bitmap.h:538
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
static void ipsec_add_node(vlib_main_t *vm, const char *node_name, const char *prev_node_name, u32 *out_node_index, u32 *out_next_index)
Definition: ipsec.c:112
#define NULL
Definition: clib.h:58
u32 index
Definition: node.h:279
u32 esp4_decrypt_node_index
Definition: ipsec.h:58
ipsec_integ_alg_t integ_alg
Definition: ipsec_sa.h:150
u32 ah6_decrypt_next_index
Definition: ipsec.h:47
u32 esp6_decrypt_next_index
Definition: ipsec.h:64
u32 ah4_encrypt_next_index
Definition: ipsec.h:134
u32 ah4_encrypt_node_index
Definition: ipsec.h:40
u32 esp6_encrypt_node_index
Definition: ipsec.h:61
int i
int ipsec_select_ah_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:218
u32 ah_current_backend
Definition: ipsec.h:154
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
#define vec_validate_aligned(V, I, A)
Make sure vector is long enough for given index (no header, specified alignment)
Definition: vec.h:450
u32 esp_current_backend
Definition: ipsec.h:156
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:236
u32 ah6_decrypt_node_index
Definition: ipsec.h:45
static uword vlib_node_add_next(vlib_main_t *vm, uword node, uword next_node)
Definition: node_funcs.h:1092
unsigned char u8
Definition: types.h:56
uword * spd_index_by_sw_if_index
Definition: ipsec.h:112
int vnet_crypto_is_set_handler(vnet_crypto_alg_t alg)
Definition: crypto.c:133
clib_error_t * ipsec_tunnel_if_init(vlib_main_t *vm)
Definition: ipsec_if.c:561
vnet_crypto_alg_t alg
Definition: ipsec.h:82
u32 esp6_encrypt_next_index
Definition: ipsec.h:63
static clib_error_t * ipsec_check_ah_support(ipsec_sa_t *sa)
Definition: ipsec.c:31
u32 ah6_encrypt_node_index
Definition: ipsec.h:44
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
ipsec_main_t ipsec_main
Definition: ipsec.c:28
u32 ah_default_backend
Definition: ipsec.h:158
u32 esp6_encrypt_node_index
Definition: ipsec.h:127
u32 esp4_decrypt_next_index
Definition: ipsec.h:133
u32 ah6_encrypt_next_index
Definition: ipsec.h:46
int ipsec_select_esp_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:241
#define clib_error_return(e, args...)
Definition: error.h:99
check_support_cb_t check_support_cb
Definition: ipsec.h:56
u8 * format_ipsec_crypto_alg(u8 *s, va_list *args)
Definition: ipsec_format.c:78
unsigned int u32
Definition: types.h:88
clib_error_t *(* add_del_sa_sess_cb_t)(u32 sa_index, u8 is_add)
Definition: ipsec.h:30
u32 esp6_encrypt_tun_feature_index
Definition: ipsec.h:143
#define vlib_call_init_function(vm, x)
Definition: init.h:270
u32 esp6_decrypt_node_index
Definition: ipsec.h:62
u32 vnet_get_feature_index(u8 arc, const char *s)
Definition: feature.c:204
static clib_error_t * vnet_feature_init(vlib_main_t *vm)
Definition: feature.c:22
u32 ah4_decrypt_node_index
Definition: ipsec.h:126
u32 error_drop_node_index
Definition: ipsec.h:122
u32 ipsec_register_esp_backend(vlib_main_t *vm, ipsec_main_t *im, const char *name, const char *esp4_encrypt_node_name, const char *esp4_encrypt_node_tun_name, const char *esp4_decrypt_node_name, const char *esp6_encrypt_node_name, const char *esp6_encrypt_node_tun_name, const char *esp6_decrypt_node_name, check_support_cb_t esp_check_support_cb, add_del_sa_sess_cb_t esp_add_del_sa_sess_cb)
Definition: ipsec.c:165
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:514
u32 esp4_encrypt_node_index
Definition: ipsec.h:123
vnet_main_t * vnet_main
Definition: ipsec.h:108
clib_error_t * ipsec_check_support_cb(ipsec_main_t *im, ipsec_sa_t *sa)
Definition: ipsec.c:89
vnet_crypto_op_id_t enc_op_id
Definition: ipsec.h:71
u32 ah4_decrypt_next_index
Definition: ipsec.h:43
clib_error_t * ipsec_rsc_in_use(ipsec_main_t *im)
Definition: ipsec.c:201
#define PREDICT_FALSE(x)
Definition: clib.h:111
u8 name[64]
Definition: memclnt.api:152
u32 esp4_encrypt_node_index
Definition: ipsec.h:57
uword * spd_index_by_spd_id
Definition: ipsec.h:111
u32 ah4_decrypt_node_index
Definition: ipsec.h:41
clib_error_t * ipsec_add_del_sa_sess_cb(ipsec_main_t *im, u32 sa_index, u8 is_add)
Definition: ipsec.c:67
u32 ah6_encrypt_next_index
Definition: ipsec.h:138
vlib_main_t * vm
Definition: buffer.c:312
ipsec_ah_backend_t * ah_backends
Definition: ipsec.h:150
u32 esp6_encrypt_tun_feature_index
Definition: ipsec.h:66
clib_error_t * ipsec_cli_init(vlib_main_t *vm)
Definition: ipsec_cli.c:998
u32 esp4_encrypt_next_index
Definition: ipsec.h:132
u32 esp4_encrypt_tun_feature_index
Definition: ipsec.h:65
u32 ah4_encrypt_next_index
Definition: ipsec.h:42
uword * sa_index_by_sa_id
Definition: ipsec.h:113
u32 esp6_decrypt_next_index
Definition: ipsec.h:137
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
vlib_node_t * vlib_get_node_by_name(vlib_main_t *vm, u8 *name)
Definition: node.c:45
vlib_main_t * vlib_main
Definition: ipsec.h:107
static clib_error_t * ipsec_init(vlib_main_t *vm)
Definition: ipsec.c:267
u32 esp6_encrypt_next_index
Definition: ipsec.h:136
static clib_error_t * ipsec_check_esp_support(ipsec_sa_t *sa)
Definition: ipsec.c:46
clib_error_t *(* check_support_cb_t)(ipsec_sa_t *sa)
Definition: ipsec.h:31
#define hash_create(elts, value_bytes)
Definition: hash.h:696
vnet_crypto_op_id_t op_id
Definition: ipsec.h:81
#define ASSERT(truth)
u32 ah4_encrypt_node_index
Definition: ipsec.h:125
ipsec_main_integ_alg_t * integ_algs
Definition: ipsec.h:166
ipsec_sa_t * sad
Definition: ipsec.h:97
u32 esp4_decrypt_node_index
Definition: ipsec.h:124
ipsec_protocol_t protocol
Definition: ipsec_sa.h:144
add_del_sa_sess_cb_t add_del_sa_sess_cb
Definition: ipsec.h:54
vnet_crypto_op_id_t dec_op_id
Definition: ipsec.h:72
u32 ah6_decrypt_node_index
Definition: ipsec.h:130
u32 ah6_encrypt_node_index
Definition: ipsec.h:129
u32 ah6_decrypt_next_index
Definition: ipsec.h:139
check_support_cb_t check_support_cb
Definition: ipsec.h:39
u64 uword
Definition: types.h:112
void ipsec_add_feature(const char *arc_name, const char *node_name, u32 *out_feature_index)
Definition: ipsec.c:126
u32 esp4_decrypt_next_index
Definition: ipsec.h:60
ipsec_crypto_alg_t crypto_alg
Definition: ipsec_sa.h:146
u32 esp4_encrypt_tun_feature_index
Definition: ipsec.h:142
static u32 vlib_num_workers()
Definition: threads.h:367
vnet_crypto_alg_t alg
Definition: ipsec.h:73
add_del_sa_sess_cb_t add_del_sa_sess_cb
Definition: ipsec.h:37
ipsec_esp_backend_t * esp_backends
Definition: ipsec.h:152
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128