fib: midchain adjacency optimisations
[vpp.git] / src / vnet / ipsec / ipsec.c
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
28 ipsec_main_t ipsec_main;
29 esp_async_post_next_t esp_encrypt_async_next;
30 esp_async_post_next_t esp_decrypt_async_next;
31
32 static clib_error_t *
33 ipsec_check_ah_support (ipsec_sa_t * sa)
34 {
35   ipsec_main_t *im = &ipsec_main;
36
37   if (sa->integ_alg == IPSEC_INTEG_ALG_NONE)
38     return clib_error_return (0, "unsupported none integ-alg");
39
40   if (!vnet_crypto_is_set_handler (im->integ_algs[sa->integ_alg].alg))
41     return clib_error_return (0, "No crypto engine support for %U",
42                               format_ipsec_integ_alg, sa->integ_alg);
43
44   return 0;
45 }
46
47 static clib_error_t *
48 ipsec_check_esp_support (ipsec_sa_t * sa)
49 {
50   ipsec_main_t *im = &ipsec_main;
51
52   if (IPSEC_INTEG_ALG_NONE != sa->integ_alg)
53     {
54       if (!vnet_crypto_is_set_handler (im->integ_algs[sa->integ_alg].alg))
55         return clib_error_return (0, "No crypto engine support for %U",
56                                   format_ipsec_integ_alg, sa->integ_alg);
57     }
58   if (IPSEC_CRYPTO_ALG_NONE != sa->crypto_alg)
59     {
60       if (!vnet_crypto_is_set_handler (im->crypto_algs[sa->crypto_alg].alg))
61         return clib_error_return (0, "No crypto engine support for %U",
62                                   format_ipsec_crypto_alg, sa->crypto_alg);
63     }
64
65   return (0);
66 }
67
68 clib_error_t *
69 ipsec_add_del_sa_sess_cb (ipsec_main_t * im, u32 sa_index, u8 is_add)
70 {
71   ipsec_ah_backend_t *ah =
72     pool_elt_at_index (im->ah_backends, im->ah_current_backend);
73   if (ah->add_del_sa_sess_cb)
74     {
75       clib_error_t *err = ah->add_del_sa_sess_cb (sa_index, is_add);
76       if (err)
77         return err;
78     }
79   ipsec_esp_backend_t *esp =
80     pool_elt_at_index (im->esp_backends, im->esp_current_backend);
81   if (esp->add_del_sa_sess_cb)
82     {
83       clib_error_t *err = esp->add_del_sa_sess_cb (sa_index, is_add);
84       if (err)
85         return err;
86     }
87   return 0;
88 }
89
90 clib_error_t *
91 ipsec_check_support_cb (ipsec_main_t * im, ipsec_sa_t * sa)
92 {
93   clib_error_t *error = 0;
94
95   if (PREDICT_FALSE (sa->protocol == IPSEC_PROTOCOL_AH))
96     {
97       ipsec_ah_backend_t *ah =
98         pool_elt_at_index (im->ah_backends, im->ah_current_backend);
99       ASSERT (ah->check_support_cb);
100       error = ah->check_support_cb (sa);
101     }
102   else
103     {
104       ipsec_esp_backend_t *esp =
105         pool_elt_at_index (im->esp_backends, im->esp_current_backend);
106       ASSERT (esp->check_support_cb);
107       error = esp->check_support_cb (sa);
108     }
109   return error;
110 }
111
112
113 static void
114 ipsec_add_node (vlib_main_t * vm, const char *node_name,
115                 const char *prev_node_name, u32 * out_node_index,
116                 u32 * out_next_index)
117 {
118   vlib_node_t *prev_node, *node;
119   prev_node = vlib_get_node_by_name (vm, (u8 *) prev_node_name);
120   ASSERT (prev_node);
121   node = vlib_get_node_by_name (vm, (u8 *) node_name);
122   ASSERT (node);
123   *out_node_index = node->index;
124   *out_next_index = vlib_node_add_next (vm, prev_node->index, node->index);
125 }
126
127 u32
128 ipsec_register_ah_backend (vlib_main_t * vm, ipsec_main_t * im,
129                            const char *name,
130                            const char *ah4_encrypt_node_name,
131                            const char *ah4_decrypt_node_name,
132                            const char *ah6_encrypt_node_name,
133                            const char *ah6_decrypt_node_name,
134                            check_support_cb_t ah_check_support_cb,
135                            add_del_sa_sess_cb_t ah_add_del_sa_sess_cb)
136 {
137   ipsec_ah_backend_t *b;
138   pool_get (im->ah_backends, b);
139   b->name = format (0, "%s%c", name, 0);
140
141   ipsec_add_node (vm, ah4_encrypt_node_name, "ipsec4-output-feature",
142                   &b->ah4_encrypt_node_index, &b->ah4_encrypt_next_index);
143   ipsec_add_node (vm, ah4_decrypt_node_name, "ipsec4-input-feature",
144                   &b->ah4_decrypt_node_index, &b->ah4_decrypt_next_index);
145   ipsec_add_node (vm, ah6_encrypt_node_name, "ipsec6-output-feature",
146                   &b->ah6_encrypt_node_index, &b->ah6_encrypt_next_index);
147   ipsec_add_node (vm, ah6_decrypt_node_name, "ipsec6-input-feature",
148                   &b->ah6_decrypt_node_index, &b->ah6_decrypt_next_index);
149
150   b->check_support_cb = ah_check_support_cb;
151   b->add_del_sa_sess_cb = ah_add_del_sa_sess_cb;
152   return b - im->ah_backends;
153 }
154
155 u32
156 ipsec_register_esp_backend (vlib_main_t * vm, ipsec_main_t * im,
157                             const char *name,
158                             const char *esp4_encrypt_node_name,
159                             const char *esp4_encrypt_node_tun_name,
160                             const char *esp4_decrypt_node_name,
161                             const char *esp4_decrypt_tun_node_name,
162                             const char *esp6_encrypt_node_name,
163                             const char *esp6_encrypt_node_tun_name,
164                             const char *esp6_decrypt_node_name,
165                             const char *esp6_decrypt_tun_node_name,
166                             check_support_cb_t esp_check_support_cb,
167                             add_del_sa_sess_cb_t esp_add_del_sa_sess_cb,
168                             enable_disable_cb_t enable_disable_cb)
169 {
170   ipsec_esp_backend_t *b;
171
172   pool_get (im->esp_backends, b);
173   b->name = format (0, "%s%c", name, 0);
174
175   ipsec_add_node (vm, esp4_encrypt_node_name, "ipsec4-output-feature",
176                   &b->esp4_encrypt_node_index, &b->esp4_encrypt_next_index);
177   ipsec_add_node (vm, esp4_decrypt_node_name, "ipsec4-input-feature",
178                   &b->esp4_decrypt_node_index, &b->esp4_decrypt_next_index);
179   ipsec_add_node (vm, esp6_encrypt_node_name, "ipsec6-output-feature",
180                   &b->esp6_encrypt_node_index, &b->esp6_encrypt_next_index);
181   ipsec_add_node (vm, esp6_decrypt_node_name, "ipsec6-input-feature",
182                   &b->esp6_decrypt_node_index, &b->esp6_decrypt_next_index);
183   ipsec_add_node (vm, esp4_decrypt_tun_node_name, "ipsec4-tun-input",
184                   &b->esp4_decrypt_tun_node_index,
185                   &b->esp4_decrypt_tun_next_index);
186   ipsec_add_node (vm, esp6_decrypt_tun_node_name, "ipsec6-tun-input",
187                   &b->esp6_decrypt_tun_node_index,
188                   &b->esp6_decrypt_tun_next_index);
189
190   b->esp6_encrypt_tun_node_index =
191     vlib_get_node_by_name (vm, (u8 *) esp6_encrypt_node_tun_name)->index;
192   b->esp4_encrypt_tun_node_index =
193     vlib_get_node_by_name (vm, (u8 *) esp4_encrypt_node_tun_name)->index;
194
195   b->check_support_cb = esp_check_support_cb;
196   b->add_del_sa_sess_cb = esp_add_del_sa_sess_cb;
197   b->enable_disable_cb = enable_disable_cb;
198
199   return b - im->esp_backends;
200 }
201
202 clib_error_t *
203 ipsec_rsc_in_use (ipsec_main_t * im)
204 {
205   /* return an error is crypto resource are in use */
206   if (pool_elts (im->sad) > 0)
207     return clib_error_return (0,
208                               "%d SA entries configured",
209                               pool_elts (im->sad));
210
211   return (NULL);
212 }
213
214 int
215 ipsec_select_ah_backend (ipsec_main_t * im, u32 backend_idx)
216 {
217   if (ipsec_rsc_in_use (im))
218     return VNET_API_ERROR_RSRC_IN_USE;
219
220   if (pool_is_free_index (im->ah_backends, backend_idx))
221     return VNET_API_ERROR_INVALID_VALUE;
222
223   ipsec_ah_backend_t *b = pool_elt_at_index (im->ah_backends, backend_idx);
224   im->ah_current_backend = backend_idx;
225   im->ah4_encrypt_node_index = b->ah4_encrypt_node_index;
226   im->ah4_decrypt_node_index = b->ah4_decrypt_node_index;
227   im->ah4_encrypt_next_index = b->ah4_encrypt_next_index;
228   im->ah4_decrypt_next_index = b->ah4_decrypt_next_index;
229   im->ah6_encrypt_node_index = b->ah6_encrypt_node_index;
230   im->ah6_decrypt_node_index = b->ah6_decrypt_node_index;
231   im->ah6_encrypt_next_index = b->ah6_encrypt_next_index;
232   im->ah6_decrypt_next_index = b->ah6_decrypt_next_index;
233
234   return 0;
235 }
236
237 int
238 ipsec_select_esp_backend (ipsec_main_t * im, u32 backend_idx)
239 {
240   if (ipsec_rsc_in_use (im))
241     return VNET_API_ERROR_RSRC_IN_USE;
242
243   if (pool_is_free_index (im->esp_backends, backend_idx))
244     return VNET_API_ERROR_INVALID_VALUE;
245
246   /* disable current backend */
247   if (im->esp_current_backend != ~0)
248     {
249       ipsec_esp_backend_t *cb = pool_elt_at_index (im->esp_backends,
250                                                    im->esp_current_backend);
251       if (cb->enable_disable_cb)
252         {
253           if ((cb->enable_disable_cb) (0) != 0)
254             return -1;
255         }
256     }
257
258   ipsec_esp_backend_t *b = pool_elt_at_index (im->esp_backends, backend_idx);
259   im->esp_current_backend = backend_idx;
260   im->esp4_encrypt_node_index = b->esp4_encrypt_node_index;
261   im->esp4_decrypt_node_index = b->esp4_decrypt_node_index;
262   im->esp4_encrypt_next_index = b->esp4_encrypt_next_index;
263   im->esp4_decrypt_next_index = b->esp4_decrypt_next_index;
264   im->esp6_encrypt_node_index = b->esp6_encrypt_node_index;
265   im->esp6_decrypt_node_index = b->esp6_decrypt_node_index;
266   im->esp6_encrypt_next_index = b->esp6_encrypt_next_index;
267   im->esp6_decrypt_next_index = b->esp6_decrypt_next_index;
268   im->esp4_decrypt_tun_node_index = b->esp4_decrypt_tun_node_index;
269   im->esp4_decrypt_tun_next_index = b->esp4_decrypt_tun_next_index;
270   im->esp6_decrypt_tun_node_index = b->esp6_decrypt_tun_node_index;
271   im->esp6_decrypt_tun_next_index = b->esp6_decrypt_tun_next_index;
272   im->esp4_encrypt_tun_node_index = b->esp4_encrypt_tun_node_index;
273   im->esp6_encrypt_tun_node_index = b->esp6_encrypt_tun_node_index;
274
275   if (b->enable_disable_cb)
276     {
277       if ((b->enable_disable_cb) (1) != 0)
278         return -1;
279     }
280   return 0;
281 }
282
283 void
284 ipsec_set_async_mode (u32 is_enabled)
285 {
286   ipsec_main_t *im = &ipsec_main;
287   ipsec_sa_t *sa;
288
289   /* lock all SAs before change im->async_mode */
290   pool_foreach (sa, im->sad, (
291                                {
292                                fib_node_lock (&sa->node);
293                                }));
294
295   im->async_mode = is_enabled;
296
297   /* change SA crypto op data before unlock them */
298   pool_foreach (sa, im->sad, (
299                                {
300                                sa->crypto_op_data = is_enabled ?
301                                sa->async_op_data.data : sa->sync_op_data.data;
302                                fib_node_unlock (&sa->node);
303                                }));
304 }
305
306 static void
307 crypto_engine_backend_register_post_node (vlib_main_t * vm)
308 {
309   esp_async_post_next_t *eit;
310   esp_async_post_next_t *dit;
311
312   eit = &esp_encrypt_async_next;
313   eit->esp4_post_next =
314     vnet_crypto_register_post_node (vm, "esp4-encrypt-post");
315   eit->esp6_post_next =
316     vnet_crypto_register_post_node (vm, "esp6-encrypt-post");
317   eit->esp4_tun_post_next =
318     vnet_crypto_register_post_node (vm, "esp4-encrypt-tun-post");
319   eit->esp6_tun_post_next =
320     vnet_crypto_register_post_node (vm, "esp6-encrypt-tun-post");
321
322   dit = &esp_decrypt_async_next;
323   dit->esp4_post_next =
324     vnet_crypto_register_post_node (vm, "esp4-decrypt-post");
325   dit->esp6_post_next =
326     vnet_crypto_register_post_node (vm, "esp6-decrypt-post");
327   dit->esp4_tun_post_next =
328     vnet_crypto_register_post_node (vm, "esp4-decrypt-tun-post");
329   dit->esp6_tun_post_next =
330     vnet_crypto_register_post_node (vm, "esp6-decrypt-tun-post");
331 }
332
333 static clib_error_t *
334 ipsec_init (vlib_main_t * vm)
335 {
336   clib_error_t *error;
337   ipsec_main_t *im = &ipsec_main;
338   ipsec_main_crypto_alg_t *a;
339
340   /* Backend registration requires the feature arcs to be set up */
341   if ((error = vlib_call_init_function (vm, vnet_feature_init)))
342     return (error);
343
344   im->vnet_main = vnet_get_main ();
345   im->vlib_main = vm;
346
347   im->spd_index_by_spd_id = hash_create (0, sizeof (uword));
348   im->sa_index_by_sa_id = hash_create (0, sizeof (uword));
349   im->spd_index_by_sw_if_index = hash_create (0, sizeof (uword));
350
351   vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
352   ASSERT (node);
353   im->error_drop_node_index = node->index;
354
355   im->ah_current_backend = ~0;
356   im->esp_current_backend = ~0;
357
358   u32 idx = ipsec_register_ah_backend (vm, im, "crypto engine backend",
359                                        "ah4-encrypt",
360                                        "ah4-decrypt",
361                                        "ah6-encrypt",
362                                        "ah6-decrypt",
363                                        ipsec_check_ah_support,
364                                        NULL);
365
366   im->ah_default_backend = idx;
367   int rv = ipsec_select_ah_backend (im, idx);
368   ASSERT (0 == rv);
369   (void) (rv);                  // avoid warning
370
371   idx = ipsec_register_esp_backend (vm, im, "crypto engine backend",
372                                     "esp4-encrypt",
373                                     "esp4-encrypt-tun",
374                                     "esp4-decrypt",
375                                     "esp4-decrypt-tun",
376                                     "esp6-encrypt",
377                                     "esp6-encrypt-tun",
378                                     "esp6-decrypt",
379                                     "esp6-decrypt-tun",
380                                     ipsec_check_esp_support,
381                                     NULL, crypto_dispatch_enable_disable);
382   im->esp_default_backend = idx;
383
384   rv = ipsec_select_esp_backend (im, idx);
385   ASSERT (0 == rv);
386   (void) (rv);                  // avoid warning
387
388   if ((error = vlib_call_init_function (vm, ipsec_cli_init)))
389     return error;
390
391   vec_validate (im->crypto_algs, IPSEC_CRYPTO_N_ALG - 1);
392
393   a = im->crypto_algs + IPSEC_CRYPTO_ALG_NONE;
394   a->enc_op_id = VNET_CRYPTO_OP_NONE;
395   a->dec_op_id = VNET_CRYPTO_OP_NONE;
396   a->alg = VNET_CRYPTO_ALG_NONE;
397   a->iv_size = 0;
398   a->block_size = 1;
399
400   a = im->crypto_algs + IPSEC_CRYPTO_ALG_DES_CBC;
401   a->enc_op_id = VNET_CRYPTO_OP_DES_CBC_ENC;
402   a->dec_op_id = VNET_CRYPTO_OP_DES_CBC_DEC;
403   a->alg = VNET_CRYPTO_ALG_DES_CBC;
404   a->iv_size = a->block_size = 8;
405
406   a = im->crypto_algs + IPSEC_CRYPTO_ALG_3DES_CBC;
407   a->enc_op_id = VNET_CRYPTO_OP_3DES_CBC_ENC;
408   a->dec_op_id = VNET_CRYPTO_OP_3DES_CBC_DEC;
409   a->alg = VNET_CRYPTO_ALG_3DES_CBC;
410   a->iv_size = a->block_size = 8;
411
412   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_128;
413   a->enc_op_id = VNET_CRYPTO_OP_AES_128_CBC_ENC;
414   a->dec_op_id = VNET_CRYPTO_OP_AES_128_CBC_DEC;
415   a->alg = VNET_CRYPTO_ALG_AES_128_CBC;
416   a->iv_size = a->block_size = 16;
417
418   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_192;
419   a->enc_op_id = VNET_CRYPTO_OP_AES_192_CBC_ENC;
420   a->dec_op_id = VNET_CRYPTO_OP_AES_192_CBC_DEC;
421   a->alg = VNET_CRYPTO_ALG_AES_192_CBC;
422   a->iv_size = a->block_size = 16;
423
424   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_256;
425   a->enc_op_id = VNET_CRYPTO_OP_AES_256_CBC_ENC;
426   a->dec_op_id = VNET_CRYPTO_OP_AES_256_CBC_DEC;
427   a->alg = VNET_CRYPTO_ALG_AES_256_CBC;
428   a->iv_size = a->block_size = 16;
429
430   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_128;
431   a->enc_op_id = VNET_CRYPTO_OP_AES_128_GCM_ENC;
432   a->dec_op_id = VNET_CRYPTO_OP_AES_128_GCM_DEC;
433   a->alg = VNET_CRYPTO_ALG_AES_128_GCM;
434   a->iv_size = 8;
435   a->block_size = 16;
436   a->icv_size = 16;
437
438   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_192;
439   a->enc_op_id = VNET_CRYPTO_OP_AES_192_GCM_ENC;
440   a->dec_op_id = VNET_CRYPTO_OP_AES_192_GCM_DEC;
441   a->alg = VNET_CRYPTO_ALG_AES_192_GCM;
442   a->iv_size = 8;
443   a->block_size = 16;
444   a->icv_size = 16;
445
446   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_256;
447   a->enc_op_id = VNET_CRYPTO_OP_AES_256_GCM_ENC;
448   a->dec_op_id = VNET_CRYPTO_OP_AES_256_GCM_DEC;
449   a->alg = VNET_CRYPTO_ALG_AES_256_GCM;
450   a->iv_size = 8;
451   a->block_size = 16;
452   a->icv_size = 16;
453
454   vec_validate (im->integ_algs, IPSEC_INTEG_N_ALG - 1);
455   ipsec_main_integ_alg_t *i;
456
457   i = &im->integ_algs[IPSEC_INTEG_ALG_MD5_96];
458   i->op_id = VNET_CRYPTO_OP_MD5_HMAC;
459   i->alg = VNET_CRYPTO_ALG_HMAC_MD5;
460   i->icv_size = 12;
461
462   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA1_96];
463   i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
464   i->alg = VNET_CRYPTO_ALG_HMAC_SHA1;
465   i->icv_size = 12;
466
467   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_96];
468   i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
469   i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
470   i->icv_size = 12;
471
472   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_128];
473   i->op_id = VNET_CRYPTO_OP_SHA256_HMAC;
474   i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
475   i->icv_size = 16;
476
477   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_384_192];
478   i->op_id = VNET_CRYPTO_OP_SHA384_HMAC;
479   i->alg = VNET_CRYPTO_ALG_HMAC_SHA384;
480   i->icv_size = 24;
481
482   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
483   i->op_id = VNET_CRYPTO_OP_SHA512_HMAC;
484   i->alg = VNET_CRYPTO_ALG_HMAC_SHA512;
485   i->icv_size = 32;
486
487   vec_validate_aligned (im->ptd, vlib_num_workers (), CLIB_CACHE_LINE_BYTES);
488
489   im->ah4_enc_fq_index =
490     vlib_frame_queue_main_init (ah4_encrypt_node.index, 0);
491   im->ah4_dec_fq_index =
492     vlib_frame_queue_main_init (ah4_decrypt_node.index, 0);
493   im->ah6_enc_fq_index =
494     vlib_frame_queue_main_init (ah6_encrypt_node.index, 0);
495   im->ah6_dec_fq_index =
496     vlib_frame_queue_main_init (ah6_decrypt_node.index, 0);
497
498   im->esp4_enc_fq_index =
499     vlib_frame_queue_main_init (esp4_encrypt_node.index, 0);
500   im->esp4_dec_fq_index =
501     vlib_frame_queue_main_init (esp4_decrypt_node.index, 0);
502   im->esp6_enc_fq_index =
503     vlib_frame_queue_main_init (esp6_encrypt_node.index, 0);
504   im->esp6_dec_fq_index =
505     vlib_frame_queue_main_init (esp6_decrypt_node.index, 0);
506   im->esp4_enc_tun_fq_index =
507     vlib_frame_queue_main_init (esp4_encrypt_tun_node.index, 0);
508   im->esp6_enc_tun_fq_index =
509     vlib_frame_queue_main_init (esp6_encrypt_tun_node.index, 0);
510   im->esp4_dec_tun_fq_index =
511     vlib_frame_queue_main_init (esp4_decrypt_tun_node.index, 0);
512   im->esp6_dec_tun_fq_index =
513     vlib_frame_queue_main_init (esp6_decrypt_tun_node.index, 0);
514
515   im->async_mode = 0;
516   crypto_engine_backend_register_post_node (vm);
517
518   return 0;
519 }
520
521 VLIB_INIT_FUNCTION (ipsec_init);
522
523 /*
524  * fd.io coding-style-patch-verification: ON
525  *
526  * Local Variables:
527  * eval: (c-set-style "gnu")
528  * End:
529  */