FD.io VPP  v19.04.4-rc0-5-ge88582fac
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  if (sa->integ_alg == IPSEC_INTEG_ALG_NONE)
34  return clib_error_return (0, "unsupported none integ-alg");
35  return 0;
36 }
37 
38 static clib_error_t *
40 {
41  return 0;
42 }
43 
46 {
47  ipsec_ah_backend_t *ah =
49  if (ah->add_del_sa_sess_cb)
50  {
51  clib_error_t *err = ah->add_del_sa_sess_cb (sa_index, is_add);
52  if (err)
53  return err;
54  }
55  ipsec_esp_backend_t *esp =
57  if (esp->add_del_sa_sess_cb)
58  {
59  clib_error_t *err = esp->add_del_sa_sess_cb (sa_index, is_add);
60  if (err)
61  return err;
62  }
63  return 0;
64 }
65 
68 {
69  clib_error_t *error = 0;
70 
72  {
73  ipsec_ah_backend_t *ah =
76  error = ah->check_support_cb (sa);
77  }
78  else
79  {
80  ipsec_esp_backend_t *esp =
82  ASSERT (esp->check_support_cb);
83  error = esp->check_support_cb (sa);
84  }
85  return error;
86 }
87 
88 
89 static void
90 ipsec_add_node (vlib_main_t * vm, const char *node_name,
91  const char *prev_node_name, u32 * out_node_index,
92  u32 * out_next_index)
93 {
94  vlib_node_t *prev_node, *node;
95  prev_node = vlib_get_node_by_name (vm, (u8 *) prev_node_name);
96  ASSERT (prev_node);
97  node = vlib_get_node_by_name (vm, (u8 *) node_name);
98  ASSERT (node);
99  *out_node_index = node->index;
100  *out_next_index = vlib_node_add_next (vm, prev_node->index, node->index);
101 }
102 
103 static void
104 ipsec_add_feature (const char *arc_name,
105  const char *node_name, u32 * out_feature_index)
106 {
107  u8 arc;
108 
109  arc = vnet_get_feature_arc_index (arc_name);
110  *out_feature_index = vnet_get_feature_index (arc, node_name);
111 }
112 
113 u32
115  const char *name,
116  const char *ah4_encrypt_node_name,
117  const char *ah4_decrypt_node_name,
118  const char *ah6_encrypt_node_name,
119  const char *ah6_decrypt_node_name,
120  check_support_cb_t ah_check_support_cb,
121  add_del_sa_sess_cb_t ah_add_del_sa_sess_cb)
122 {
124  pool_get (im->ah_backends, b);
125  b->name = format (0, "%s%c", name, 0);
126 
127  ipsec_add_node (vm, ah4_encrypt_node_name, "ipsec4-output-feature",
129  ipsec_add_node (vm, ah4_decrypt_node_name, "ipsec4-input-feature",
131  ipsec_add_node (vm, ah6_encrypt_node_name, "ipsec6-output-feature",
133  ipsec_add_node (vm, ah6_decrypt_node_name, "ipsec6-input-feature",
135 
136  b->check_support_cb = ah_check_support_cb;
137  b->add_del_sa_sess_cb = ah_add_del_sa_sess_cb;
138  return b - im->ah_backends;
139 }
140 
141 u32
143  const char *name,
144  const char *esp4_encrypt_node_name,
145  const char *esp4_encrypt_node_tun_name,
146  const char *esp4_decrypt_node_name,
147  const char *esp6_encrypt_node_name,
148  const char *esp6_encrypt_node_tun_name,
149  const char *esp6_decrypt_node_name,
150  check_support_cb_t esp_check_support_cb,
151  add_del_sa_sess_cb_t esp_add_del_sa_sess_cb)
152 {
154 
155  pool_get (im->esp_backends, b);
156  b->name = format (0, "%s%c", name, 0);
157 
158  ipsec_add_node (vm, esp4_encrypt_node_name, "ipsec4-output-feature",
160  ipsec_add_node (vm, esp4_decrypt_node_name, "ipsec4-input-feature",
162  ipsec_add_node (vm, esp6_encrypt_node_name, "ipsec6-output-feature",
164  ipsec_add_node (vm, esp6_decrypt_node_name, "ipsec6-input-feature",
166 
167  ipsec_add_feature ("ip4-output", esp4_encrypt_node_tun_name,
169  ipsec_add_feature ("ip6-output", esp6_encrypt_node_tun_name,
171 
172  b->check_support_cb = esp_check_support_cb;
173  b->add_del_sa_sess_cb = esp_add_del_sa_sess_cb;
174  return b - im->esp_backends;
175 }
176 
177 clib_error_t *
179 {
180  /* return an error is crypto resource are in use */
181  if (pool_elts (im->sad) > 0)
182  return clib_error_return (0,
183  "%d SA entries configured",
184  pool_elts (im->sad));
185 
186  if (pool_elts (im->tunnel_interfaces))
187  return clib_error_return (0,
188  "%d tunnel-interface entries configured",
190 
191  return (NULL);
192 }
193 
194 int
196 {
197  if (ipsec_rsc_in_use (im))
198  return VNET_API_ERROR_RSRC_IN_USE;
199 
200  if (pool_is_free_index (im->ah_backends, backend_idx))
201  return VNET_API_ERROR_INVALID_VALUE;
202 
203  ipsec_ah_backend_t *b = pool_elt_at_index (im->ah_backends, backend_idx);
204  im->ah_current_backend = backend_idx;
213 
214  return 0;
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->esp_backends, backend_idx))
224  return VNET_API_ERROR_INVALID_VALUE;
225 
226  ipsec_esp_backend_t *b = pool_elt_at_index (im->esp_backends, backend_idx);
227  im->esp_current_backend = backend_idx;
236 
239 
240  return 0;
241 }
242 
243 static clib_error_t *
245 {
246  clib_error_t *error;
247  ipsec_main_t *im = &ipsec_main;
249 
250  im->vnet_main = vnet_get_main ();
251  im->vlib_main = vm;
252 
253  im->spd_index_by_spd_id = hash_create (0, sizeof (uword));
254  im->sa_index_by_sa_id = hash_create (0, sizeof (uword));
255  im->spd_index_by_sw_if_index = hash_create (0, sizeof (uword));
256 
257  vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
258  ASSERT (node);
259  im->error_drop_node_index = node->index;
260 
261  u32 idx = ipsec_register_ah_backend (vm, im, "default openssl backend",
262  "ah4-encrypt",
263  "ah4-decrypt",
264  "ah6-encrypt",
265  "ah6-decrypt",
267  NULL);
268 
269  im->ah_default_backend = idx;
270  int rv = ipsec_select_ah_backend (im, idx);
271  ASSERT (0 == rv);
272  (void) (rv); // avoid warning
273 
274  idx = ipsec_register_esp_backend (vm, im, "default openssl backend",
275  "esp4-encrypt",
276  "esp4-encrypt-tun",
277  "esp4-decrypt",
278  "esp6-encrypt",
279  "esp6-encrypt-tun",
280  "esp6-decrypt",
282  im->esp_default_backend = idx;
283 
284  rv = ipsec_select_esp_backend (im, idx);
285  ASSERT (0 == rv);
286  (void) (rv); // avoid warning
287 
288  if ((error = vlib_call_init_function (vm, ipsec_cli_init)))
289  return error;
290 
291  if ((error = vlib_call_init_function (vm, ipsec_tunnel_if_init)))
292  return error;
293 
295 
296  a = im->crypto_algs + IPSEC_CRYPTO_ALG_DES_CBC;
297  a->enc_op_id = VNET_CRYPTO_OP_DES_CBC_ENC;
298  a->dec_op_id = VNET_CRYPTO_OP_DES_CBC_DEC;
299  a->iv_size = a->block_size = 8;
300 
301  a = im->crypto_algs + IPSEC_CRYPTO_ALG_3DES_CBC;
302  a->enc_op_id = VNET_CRYPTO_OP_3DES_CBC_ENC;
303  a->dec_op_id = VNET_CRYPTO_OP_3DES_CBC_DEC;
304  a->iv_size = a->block_size = 8;
305 
306  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_128;
307  a->enc_op_id = VNET_CRYPTO_OP_AES_128_CBC_ENC;
308  a->dec_op_id = VNET_CRYPTO_OP_AES_128_CBC_DEC;
309  a->iv_size = a->block_size = 16;
310 
311  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_192;
312  a->enc_op_id = VNET_CRYPTO_OP_AES_192_CBC_ENC;
313  a->dec_op_id = VNET_CRYPTO_OP_AES_192_CBC_DEC;
314  a->iv_size = a->block_size = 16;
315 
316  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_256;
317  a->enc_op_id = VNET_CRYPTO_OP_AES_256_CBC_ENC;
318  a->dec_op_id = VNET_CRYPTO_OP_AES_256_CBC_DEC;
319  a->iv_size = a->block_size = 16;
320 
321  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_128;
322  a->enc_op_id = VNET_CRYPTO_OP_AES_128_GCM_ENC;
323  a->dec_op_id = VNET_CRYPTO_OP_AES_128_GCM_DEC;
324  a->iv_size = a->block_size = 8;
325  a->icv_size = 16;
326 
327  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_192;
328  a->enc_op_id = VNET_CRYPTO_OP_AES_192_GCM_ENC;
329  a->dec_op_id = VNET_CRYPTO_OP_AES_192_GCM_DEC;
330  a->iv_size = a->block_size = 8;
331  a->icv_size = 16;
332 
333  a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_256;
334  a->enc_op_id = VNET_CRYPTO_OP_AES_256_GCM_ENC;
335  a->dec_op_id = VNET_CRYPTO_OP_AES_256_GCM_DEC;
336  a->iv_size = a->block_size = 8;
337  a->icv_size = 16;
338 
341 
342  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA1_96];
343  i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
344  i->icv_size = 12;
345 
346  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_96];
347  i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
348  i->icv_size = 12;
349 
350  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_128];
351  i->op_id = VNET_CRYPTO_OP_SHA256_HMAC;
352  i->icv_size = 16;
353 
354  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_384_192];
355  i->op_id = VNET_CRYPTO_OP_SHA384_HMAC;
356  i->icv_size = 24;
357 
358  i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
359  i->op_id = VNET_CRYPTO_OP_SHA512_HMAC;
360  i->icv_size = 32;
361 
363 
364  return 0;
365 }
366 
368 
369 /*
370  * fd.io coding-style-patch-verification: ON
371  *
372  * Local Variables:
373  * eval: (c-set-style "gnu")
374  * End:
375  */
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
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:114
u32 esp_default_backend
Definition: ipsec.h:152
u32 esp4_encrypt_next_index
Definition: ipsec.h:59
ipsec_main_crypto_alg_t * crypto_algs
Definition: ipsec.h:155
ipsec_tunnel_if_t * tunnel_interfaces
Definition: ipsec.h:100
ipsec_per_thread_data_t * ptd
Definition: ipsec.h:161
u32 esp6_decrypt_node_index
Definition: ipsec.h:124
u8 vnet_get_feature_arc_index(const char *s)
Definition: feature.c:168
u32 ah4_decrypt_next_index
Definition: ipsec.h:131
a
Definition: bitmap.h:538
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
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:90
#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:153
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:130
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:195
u32 ah_current_backend
Definition: ipsec.h:146
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:148
#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:110
clib_error_t * ipsec_tunnel_if_init(vlib_main_t *vm)
Definition: ipsec_if.c:680
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:163
ipsec_main_t ipsec_main
Definition: ipsec.c:28
u32 ah_default_backend
Definition: ipsec.h:150
u32 esp6_encrypt_node_index
Definition: ipsec.h:123
u32 esp4_decrypt_next_index
Definition: ipsec.h:129
u32 ah6_encrypt_next_index
Definition: ipsec.h:46
int ipsec_select_esp_backend(ipsec_main_t *im, u32 backend_idx)
Definition: ipsec.c:218
#define clib_error_return(e, args...)
Definition: error.h:99
check_support_cb_t check_support_cb
Definition: ipsec.h:56
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:139
#define vlib_call_init_function(vm, x)
Definition: init.h:260
u32 esp6_decrypt_node_index
Definition: ipsec.h:62
u32 vnet_get_feature_index(u8 arc, const char *s)
Definition: feature.c:204
u32 ah4_decrypt_node_index
Definition: ipsec.h:122
u32 error_drop_node_index
Definition: ipsec.h:118
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:142
#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:119
vnet_main_t * vnet_main
Definition: ipsec.h:106
clib_error_t * ipsec_check_support_cb(ipsec_main_t *im, ipsec_sa_t *sa)
Definition: ipsec.c:67
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:178
#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:109
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:45
u32 ah6_encrypt_next_index
Definition: ipsec.h:134
vlib_main_t * vm
Definition: buffer.c:312
ipsec_ah_backend_t * ah_backends
Definition: ipsec.h:142
u32 esp6_encrypt_tun_feature_index
Definition: ipsec.h:66
clib_error_t * ipsec_cli_init(vlib_main_t *vm)
Definition: ipsec_cli.c:970
u32 esp4_encrypt_next_index
Definition: ipsec.h:128
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:111
u32 esp6_decrypt_next_index
Definition: ipsec.h:133
#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:105
static clib_error_t * ipsec_init(vlib_main_t *vm)
Definition: ipsec.c:244
u32 esp6_encrypt_next_index
Definition: ipsec.h:132
static clib_error_t * ipsec_check_esp_support(ipsec_sa_t *sa)
Definition: ipsec.c:39
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:80
#define ASSERT(truth)
u32 ah4_encrypt_node_index
Definition: ipsec.h:121
ipsec_main_integ_alg_t * integ_algs
Definition: ipsec.h:158
u8 is_add
Definition: ipsec_gre.api:36
ipsec_sa_t * sad
Definition: ipsec.h:95
u32 esp4_decrypt_node_index
Definition: ipsec.h:120
ipsec_protocol_t protocol
Definition: ipsec_sa.h:148
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:126
u32 ah6_encrypt_node_index
Definition: ipsec.h:125
u32 ah6_decrypt_next_index
Definition: ipsec.h:135
check_support_cb_t check_support_cb
Definition: ipsec.h:39
u64 uword
Definition: types.h:112
u32 esp4_decrypt_next_index
Definition: ipsec.h:60
u32 esp4_encrypt_tun_feature_index
Definition: ipsec.h:138
static u32 vlib_num_workers()
Definition: threads.h:366
add_del_sa_sess_cb_t add_del_sa_sess_cb
Definition: ipsec.h:37
ipsec_esp_backend_t * esp_backends
Definition: ipsec.h:144
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
static void ipsec_add_feature(const char *arc_name, const char *node_name, u32 *out_feature_index)
Definition: ipsec.c:104
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128