ipsec: remove dedicated IPSec tunnels
[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
30 static clib_error_t *
31 ipsec_check_ah_support (ipsec_sa_t * sa)
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
38   if (!vnet_crypto_is_set_handler (im->integ_algs[sa->integ_alg].alg))
39     return clib_error_return (0, "No crypto engine support for %U",
40                               format_ipsec_integ_alg, sa->integ_alg);
41
42   return 0;
43 }
44
45 static clib_error_t *
46 ipsec_check_esp_support (ipsec_sa_t * sa)
47 {
48   ipsec_main_t *im = &ipsec_main;
49
50   if (IPSEC_INTEG_ALG_NONE != sa->integ_alg)
51     {
52       if (!vnet_crypto_is_set_handler (im->integ_algs[sa->integ_alg].alg))
53         return clib_error_return (0, "No crypto engine support for %U",
54                                   format_ipsec_integ_alg, sa->integ_alg);
55     }
56   if (IPSEC_CRYPTO_ALG_NONE != sa->crypto_alg)
57     {
58       if (!vnet_crypto_is_set_handler (im->crypto_algs[sa->crypto_alg].alg))
59         return clib_error_return (0, "No crypto engine support for %U",
60                                   format_ipsec_crypto_alg, sa->crypto_alg);
61     }
62
63   return (0);
64 }
65
66 clib_error_t *
67 ipsec_add_del_sa_sess_cb (ipsec_main_t * im, u32 sa_index, u8 is_add)
68 {
69   ipsec_ah_backend_t *ah =
70     pool_elt_at_index (im->ah_backends, im->ah_current_backend);
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 =
78     pool_elt_at_index (im->esp_backends, im->esp_current_backend);
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
88 clib_error_t *
89 ipsec_check_support_cb (ipsec_main_t * im, ipsec_sa_t * sa)
90 {
91   clib_error_t *error = 0;
92
93   if (PREDICT_FALSE (sa->protocol == IPSEC_PROTOCOL_AH))
94     {
95       ipsec_ah_backend_t *ah =
96         pool_elt_at_index (im->ah_backends, im->ah_current_backend);
97       ASSERT (ah->check_support_cb);
98       error = ah->check_support_cb (sa);
99     }
100   else
101     {
102       ipsec_esp_backend_t *esp =
103         pool_elt_at_index (im->esp_backends, im->esp_current_backend);
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
137 ipsec_register_ah_backend (vlib_main_t * vm, ipsec_main_t * im,
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 {
146   ipsec_ah_backend_t *b;
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",
151                   &b->ah4_encrypt_node_index, &b->ah4_encrypt_next_index);
152   ipsec_add_node (vm, ah4_decrypt_node_name, "ipsec4-input-feature",
153                   &b->ah4_decrypt_node_index, &b->ah4_decrypt_next_index);
154   ipsec_add_node (vm, ah6_encrypt_node_name, "ipsec6-output-feature",
155                   &b->ah6_encrypt_node_index, &b->ah6_encrypt_next_index);
156   ipsec_add_node (vm, ah6_decrypt_node_name, "ipsec6-input-feature",
157                   &b->ah6_decrypt_node_index, &b->ah6_decrypt_next_index);
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
165 ipsec_register_esp_backend (vlib_main_t * vm, ipsec_main_t * im,
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 {
176   ipsec_esp_backend_t *b;
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",
182                   &b->esp4_encrypt_node_index, &b->esp4_encrypt_next_index);
183   ipsec_add_node (vm, esp4_decrypt_node_name, "ipsec4-input-feature",
184                   &b->esp4_decrypt_node_index, &b->esp4_decrypt_next_index);
185   ipsec_add_node (vm, esp6_encrypt_node_name, "ipsec6-output-feature",
186                   &b->esp6_encrypt_node_index, &b->esp6_encrypt_next_index);
187   ipsec_add_node (vm, esp6_decrypt_node_name, "ipsec6-input-feature",
188                   &b->esp6_decrypt_node_index, &b->esp6_decrypt_next_index);
189
190   ipsec_add_feature ("ip4-output", esp4_encrypt_node_tun_name,
191                      &b->esp4_encrypt_tun_feature_index);
192   ipsec_add_feature ("ip6-output", esp6_encrypt_node_tun_name,
193                      &b->esp6_encrypt_tun_feature_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   return b - im->esp_backends;
198 }
199
200 clib_error_t *
201 ipsec_rsc_in_use (ipsec_main_t * im)
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   return (NULL);
210 }
211
212 int
213 ipsec_select_ah_backend (ipsec_main_t * im, u32 backend_idx)
214 {
215   if (ipsec_rsc_in_use (im))
216     return VNET_API_ERROR_RSRC_IN_USE;
217
218   if (pool_is_free_index (im->ah_backends, backend_idx))
219     return VNET_API_ERROR_INVALID_VALUE;
220
221   ipsec_ah_backend_t *b = pool_elt_at_index (im->ah_backends, backend_idx);
222   im->ah_current_backend = backend_idx;
223   im->ah4_encrypt_node_index = b->ah4_encrypt_node_index;
224   im->ah4_decrypt_node_index = b->ah4_decrypt_node_index;
225   im->ah4_encrypt_next_index = b->ah4_encrypt_next_index;
226   im->ah4_decrypt_next_index = b->ah4_decrypt_next_index;
227   im->ah6_encrypt_node_index = b->ah6_encrypt_node_index;
228   im->ah6_decrypt_node_index = b->ah6_decrypt_node_index;
229   im->ah6_encrypt_next_index = b->ah6_encrypt_next_index;
230   im->ah6_decrypt_next_index = b->ah6_decrypt_next_index;
231
232   return 0;
233 }
234
235 int
236 ipsec_select_esp_backend (ipsec_main_t * im, u32 backend_idx)
237 {
238   if (ipsec_rsc_in_use (im))
239     return VNET_API_ERROR_RSRC_IN_USE;
240
241   if (pool_is_free_index (im->esp_backends, backend_idx))
242     return VNET_API_ERROR_INVALID_VALUE;
243
244   ipsec_esp_backend_t *b = pool_elt_at_index (im->esp_backends, backend_idx);
245   im->esp_current_backend = backend_idx;
246   im->esp4_encrypt_node_index = b->esp4_encrypt_node_index;
247   im->esp4_decrypt_node_index = b->esp4_decrypt_node_index;
248   im->esp4_encrypt_next_index = b->esp4_encrypt_next_index;
249   im->esp4_decrypt_next_index = b->esp4_decrypt_next_index;
250   im->esp6_encrypt_node_index = b->esp6_encrypt_node_index;
251   im->esp6_decrypt_node_index = b->esp6_decrypt_node_index;
252   im->esp6_encrypt_next_index = b->esp6_encrypt_next_index;
253   im->esp6_decrypt_next_index = b->esp6_decrypt_next_index;
254
255   im->esp4_encrypt_tun_feature_index = b->esp4_encrypt_tun_feature_index;
256   im->esp6_encrypt_tun_feature_index = b->esp6_encrypt_tun_feature_index;
257
258   return 0;
259 }
260
261 static clib_error_t *
262 ipsec_init (vlib_main_t * vm)
263 {
264   clib_error_t *error;
265   ipsec_main_t *im = &ipsec_main;
266   ipsec_main_crypto_alg_t *a;
267
268   /* Backend registration requires the feature arcs to be set up */
269   if ((error = vlib_call_init_function (vm, vnet_feature_init)))
270     return (error);
271
272   im->vnet_main = vnet_get_main ();
273   im->vlib_main = vm;
274
275   im->spd_index_by_spd_id = hash_create (0, sizeof (uword));
276   im->sa_index_by_sa_id = hash_create (0, sizeof (uword));
277   im->spd_index_by_sw_if_index = hash_create (0, sizeof (uword));
278
279   vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
280   ASSERT (node);
281   im->error_drop_node_index = node->index;
282
283   u32 idx = ipsec_register_ah_backend (vm, im, "crypto engine backend",
284                                        "ah4-encrypt",
285                                        "ah4-decrypt",
286                                        "ah6-encrypt",
287                                        "ah6-decrypt",
288                                        ipsec_check_ah_support,
289                                        NULL);
290
291   im->ah_default_backend = idx;
292   int rv = ipsec_select_ah_backend (im, idx);
293   ASSERT (0 == rv);
294   (void) (rv);                  // avoid warning
295
296   idx = ipsec_register_esp_backend (vm, im, "crypto engine backend",
297                                     "esp4-encrypt",
298                                     "esp4-encrypt-tun",
299                                     "esp4-decrypt",
300                                     "esp6-encrypt",
301                                     "esp6-encrypt-tun",
302                                     "esp6-decrypt",
303                                     ipsec_check_esp_support, NULL);
304   im->esp_default_backend = idx;
305
306   rv = ipsec_select_esp_backend (im, idx);
307   ASSERT (0 == rv);
308   (void) (rv);                  // avoid warning
309
310   if ((error = vlib_call_init_function (vm, ipsec_cli_init)))
311     return error;
312
313   vec_validate (im->crypto_algs, IPSEC_CRYPTO_N_ALG - 1);
314
315   a = im->crypto_algs + IPSEC_CRYPTO_ALG_NONE;
316   a->enc_op_id = VNET_CRYPTO_OP_NONE;
317   a->dec_op_id = VNET_CRYPTO_OP_NONE;
318   a->alg = VNET_CRYPTO_ALG_NONE;
319   a->iv_size = 0;
320   a->block_size = 1;
321
322   a = im->crypto_algs + IPSEC_CRYPTO_ALG_DES_CBC;
323   a->enc_op_id = VNET_CRYPTO_OP_DES_CBC_ENC;
324   a->dec_op_id = VNET_CRYPTO_OP_DES_CBC_DEC;
325   a->alg = VNET_CRYPTO_ALG_DES_CBC;
326   a->iv_size = a->block_size = 8;
327
328   a = im->crypto_algs + IPSEC_CRYPTO_ALG_3DES_CBC;
329   a->enc_op_id = VNET_CRYPTO_OP_3DES_CBC_ENC;
330   a->dec_op_id = VNET_CRYPTO_OP_3DES_CBC_DEC;
331   a->alg = VNET_CRYPTO_ALG_3DES_CBC;
332   a->iv_size = a->block_size = 8;
333
334   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_128;
335   a->enc_op_id = VNET_CRYPTO_OP_AES_128_CBC_ENC;
336   a->dec_op_id = VNET_CRYPTO_OP_AES_128_CBC_DEC;
337   a->alg = VNET_CRYPTO_ALG_AES_128_CBC;
338   a->iv_size = a->block_size = 16;
339
340   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_192;
341   a->enc_op_id = VNET_CRYPTO_OP_AES_192_CBC_ENC;
342   a->dec_op_id = VNET_CRYPTO_OP_AES_192_CBC_DEC;
343   a->alg = VNET_CRYPTO_ALG_AES_192_CBC;
344   a->iv_size = a->block_size = 16;
345
346   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_256;
347   a->enc_op_id = VNET_CRYPTO_OP_AES_256_CBC_ENC;
348   a->dec_op_id = VNET_CRYPTO_OP_AES_256_CBC_DEC;
349   a->alg = VNET_CRYPTO_ALG_AES_256_CBC;
350   a->iv_size = a->block_size = 16;
351
352   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_128;
353   a->enc_op_id = VNET_CRYPTO_OP_AES_128_GCM_ENC;
354   a->dec_op_id = VNET_CRYPTO_OP_AES_128_GCM_DEC;
355   a->alg = VNET_CRYPTO_ALG_AES_128_GCM;
356   a->iv_size = a->block_size = 8;
357   a->icv_size = 16;
358
359   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_192;
360   a->enc_op_id = VNET_CRYPTO_OP_AES_192_GCM_ENC;
361   a->dec_op_id = VNET_CRYPTO_OP_AES_192_GCM_DEC;
362   a->alg = VNET_CRYPTO_ALG_AES_192_GCM;
363   a->iv_size = a->block_size = 8;
364   a->icv_size = 16;
365
366   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_256;
367   a->enc_op_id = VNET_CRYPTO_OP_AES_256_GCM_ENC;
368   a->dec_op_id = VNET_CRYPTO_OP_AES_256_GCM_DEC;
369   a->alg = VNET_CRYPTO_ALG_AES_256_GCM;
370   a->iv_size = a->block_size = 8;
371   a->icv_size = 16;
372
373   vec_validate (im->integ_algs, IPSEC_INTEG_N_ALG - 1);
374   ipsec_main_integ_alg_t *i;
375
376   i = &im->integ_algs[IPSEC_INTEG_ALG_MD5_96];
377   i->op_id = VNET_CRYPTO_OP_MD5_HMAC;
378   i->alg = VNET_CRYPTO_ALG_HMAC_MD5;
379   i->icv_size = 12;
380
381   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA1_96];
382   i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
383   i->alg = VNET_CRYPTO_ALG_HMAC_SHA1;
384   i->icv_size = 12;
385
386   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_96];
387   i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
388   i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
389   i->icv_size = 12;
390
391   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_128];
392   i->op_id = VNET_CRYPTO_OP_SHA256_HMAC;
393   i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
394   i->icv_size = 16;
395
396   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_384_192];
397   i->op_id = VNET_CRYPTO_OP_SHA384_HMAC;
398   i->alg = VNET_CRYPTO_ALG_HMAC_SHA384;
399   i->icv_size = 24;
400
401   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
402   i->op_id = VNET_CRYPTO_OP_SHA512_HMAC;
403   i->alg = VNET_CRYPTO_ALG_HMAC_SHA512;
404   i->icv_size = 32;
405
406   vec_validate_aligned (im->ptd, vlib_num_workers (), CLIB_CACHE_LINE_BYTES);
407
408   return 0;
409 }
410
411 VLIB_INIT_FUNCTION (ipsec_init);
412
413 /*
414  * fd.io coding-style-patch-verification: ON
415  *
416  * Local Variables:
417  * eval: (c-set-style "gnu")
418  * End:
419  */