9f3e1d365074d732f776b35180e25a5e0d815128
[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   if (pool_elts (im->tunnel_interfaces))
210     return clib_error_return (0,
211                               "%d tunnel-interface entries configured",
212                               pool_elts (im->tunnel_interfaces));
213
214   return (NULL);
215 }
216
217 int
218 ipsec_select_ah_backend (ipsec_main_t * im, u32 backend_idx)
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;
228   im->ah4_encrypt_node_index = b->ah4_encrypt_node_index;
229   im->ah4_decrypt_node_index = b->ah4_decrypt_node_index;
230   im->ah4_encrypt_next_index = b->ah4_encrypt_next_index;
231   im->ah4_decrypt_next_index = b->ah4_decrypt_next_index;
232   im->ah6_encrypt_node_index = b->ah6_encrypt_node_index;
233   im->ah6_decrypt_node_index = b->ah6_decrypt_node_index;
234   im->ah6_encrypt_next_index = b->ah6_encrypt_next_index;
235   im->ah6_decrypt_next_index = b->ah6_decrypt_next_index;
236
237   return 0;
238 }
239
240 int
241 ipsec_select_esp_backend (ipsec_main_t * im, u32 backend_idx)
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;
251   im->esp4_encrypt_node_index = b->esp4_encrypt_node_index;
252   im->esp4_decrypt_node_index = b->esp4_decrypt_node_index;
253   im->esp4_encrypt_next_index = b->esp4_encrypt_next_index;
254   im->esp4_decrypt_next_index = b->esp4_decrypt_next_index;
255   im->esp6_encrypt_node_index = b->esp6_encrypt_node_index;
256   im->esp6_decrypt_node_index = b->esp6_decrypt_node_index;
257   im->esp6_encrypt_next_index = b->esp6_encrypt_next_index;
258   im->esp6_decrypt_next_index = b->esp6_decrypt_next_index;
259
260   im->esp4_encrypt_tun_feature_index = b->esp4_encrypt_tun_feature_index;
261   im->esp6_encrypt_tun_feature_index = b->esp6_encrypt_tun_feature_index;
262
263   return 0;
264 }
265
266 static clib_error_t *
267 ipsec_init (vlib_main_t * vm)
268 {
269   clib_error_t *error;
270   ipsec_main_t *im = &ipsec_main;
271   ipsec_main_crypto_alg_t *a;
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",
293                                        ipsec_check_ah_support,
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",
308                                     ipsec_check_esp_support, NULL);
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
321   vec_validate (im->crypto_algs, IPSEC_CRYPTO_N_ALG - 1);
322
323   a = im->crypto_algs + IPSEC_CRYPTO_ALG_NONE;
324   a->enc_op_id = VNET_CRYPTO_OP_NONE;
325   a->dec_op_id = VNET_CRYPTO_OP_NONE;
326   a->alg = VNET_CRYPTO_ALG_NONE;
327   a->iv_size = 0;
328   a->block_size = 1;
329
330   a = im->crypto_algs + IPSEC_CRYPTO_ALG_DES_CBC;
331   a->enc_op_id = VNET_CRYPTO_OP_DES_CBC_ENC;
332   a->dec_op_id = VNET_CRYPTO_OP_DES_CBC_DEC;
333   a->alg = VNET_CRYPTO_ALG_DES_CBC;
334   a->iv_size = a->block_size = 8;
335
336   a = im->crypto_algs + IPSEC_CRYPTO_ALG_3DES_CBC;
337   a->enc_op_id = VNET_CRYPTO_OP_3DES_CBC_ENC;
338   a->dec_op_id = VNET_CRYPTO_OP_3DES_CBC_DEC;
339   a->alg = VNET_CRYPTO_ALG_3DES_CBC;
340   a->iv_size = a->block_size = 8;
341
342   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_128;
343   a->enc_op_id = VNET_CRYPTO_OP_AES_128_CBC_ENC;
344   a->dec_op_id = VNET_CRYPTO_OP_AES_128_CBC_DEC;
345   a->alg = VNET_CRYPTO_ALG_AES_128_CBC;
346   a->iv_size = a->block_size = 16;
347
348   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_192;
349   a->enc_op_id = VNET_CRYPTO_OP_AES_192_CBC_ENC;
350   a->dec_op_id = VNET_CRYPTO_OP_AES_192_CBC_DEC;
351   a->alg = VNET_CRYPTO_ALG_AES_192_CBC;
352   a->iv_size = a->block_size = 16;
353
354   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_CBC_256;
355   a->enc_op_id = VNET_CRYPTO_OP_AES_256_CBC_ENC;
356   a->dec_op_id = VNET_CRYPTO_OP_AES_256_CBC_DEC;
357   a->alg = VNET_CRYPTO_ALG_AES_256_CBC;
358   a->iv_size = a->block_size = 16;
359
360   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_128;
361   a->enc_op_id = VNET_CRYPTO_OP_AES_128_GCM_ENC;
362   a->dec_op_id = VNET_CRYPTO_OP_AES_128_GCM_DEC;
363   a->alg = VNET_CRYPTO_ALG_AES_128_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_192;
368   a->enc_op_id = VNET_CRYPTO_OP_AES_192_GCM_ENC;
369   a->dec_op_id = VNET_CRYPTO_OP_AES_192_GCM_DEC;
370   a->alg = VNET_CRYPTO_ALG_AES_192_GCM;
371   a->iv_size = a->block_size = 8;
372   a->icv_size = 16;
373
374   a = im->crypto_algs + IPSEC_CRYPTO_ALG_AES_GCM_256;
375   a->enc_op_id = VNET_CRYPTO_OP_AES_256_GCM_ENC;
376   a->dec_op_id = VNET_CRYPTO_OP_AES_256_GCM_DEC;
377   a->alg = VNET_CRYPTO_ALG_AES_256_GCM;
378   a->iv_size = a->block_size = 8;
379   a->icv_size = 16;
380
381   vec_validate (im->integ_algs, IPSEC_INTEG_N_ALG - 1);
382   ipsec_main_integ_alg_t *i;
383
384   i = &im->integ_algs[IPSEC_INTEG_ALG_MD5_96];
385   i->op_id = VNET_CRYPTO_OP_MD5_HMAC;
386   i->alg = VNET_CRYPTO_ALG_HMAC_MD5;
387   i->icv_size = 12;
388
389   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA1_96];
390   i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
391   i->alg = VNET_CRYPTO_ALG_HMAC_SHA1;
392   i->icv_size = 12;
393
394   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_96];
395   i->op_id = VNET_CRYPTO_OP_SHA1_HMAC;
396   i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
397   i->icv_size = 12;
398
399   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_256_128];
400   i->op_id = VNET_CRYPTO_OP_SHA256_HMAC;
401   i->alg = VNET_CRYPTO_ALG_HMAC_SHA256;
402   i->icv_size = 16;
403
404   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_384_192];
405   i->op_id = VNET_CRYPTO_OP_SHA384_HMAC;
406   i->alg = VNET_CRYPTO_ALG_HMAC_SHA384;
407   i->icv_size = 24;
408
409   i = &im->integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
410   i->op_id = VNET_CRYPTO_OP_SHA512_HMAC;
411   i->alg = VNET_CRYPTO_ALG_HMAC_SHA512;
412   i->icv_size = 32;
413
414   vec_validate_aligned (im->ptd, vlib_num_workers (), CLIB_CACHE_LINE_BYTES);
415
416   return 0;
417 }
418
419 VLIB_INIT_FUNCTION (ipsec_init);
420
421 /*
422  * fd.io coding-style-patch-verification: ON
423  *
424  * Local Variables:
425  * eval: (c-set-style "gnu")
426  * End:
427  */