Fixes for buliding for 32bit targets:
[vpp.git] / src / plugins / ipsecmb / ipsecmb.c
1 /*
2  * init.c : ipsecmb common code
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 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
20 #include <vnet/plugin/plugin.h>
21 #include <vpp/app/version.h>
22 #include <ipsecmb/ipsecmb.h>
23 ipsecmb_main_t ipsecmb_main;
24
25 int
26 sa_expand_keys (u32 sa_index)
27 {
28   ipsecmb_main_t *imbm = &ipsecmb_main;
29   ipsec_sa_t *sa = pool_elt_at_index (ipsec_main.sad, sa_index);
30   ipsecmb_sa_t *samb = pool_elt_at_index (imbm->sad, sa_index);
31   if (sa->crypto_key_len > 0)
32     {
33       const keyexp_t keyexp_fn = imbm->crypto_algs[sa->crypto_alg].keyexp_fn;
34       keyexp_fn (sa->crypto_key, samb->aes_enc_key_expanded,
35                  samb->aes_dec_key_expanded);
36     }
37   if (sa->integ_key_len > 0)
38     {
39       const u8 block_size = imbm->integ_algs[sa->integ_alg].block_size;
40       const hash_one_block_t hash_one_block_fn =
41         imbm->integ_algs[sa->integ_alg].hash_one_block_fn;
42       u8 buf[block_size];
43       int i = 0;
44       if (sa->integ_key_len > block_size)
45         {
46           return VNET_API_ERROR_SYSCALL_ERROR_1;        // FIXME use correct value
47         }
48       memset (buf, 0x36, sizeof (buf));
49       for (i = 0; i < sa->integ_key_len; i++)
50         {
51           buf[i] ^= sa->integ_key[i];
52         }
53       hash_one_block_fn (buf, samb->ipad_hash);
54
55       memset (buf, 0x5c, sizeof (buf));
56       for (i = 0; i < sa->integ_key_len; i++)
57         {
58           buf[i] ^= sa->integ_key[i];
59         }
60       hash_one_block_fn (buf, samb->opad_hash);
61     }
62   return 0;
63 }
64
65 static clib_error_t *
66 ipsecmb_add_del_sa_session (u32 sa_index, u8 is_add)
67 {
68   ipsecmb_main_t *imbm = &ipsecmb_main;
69   if (is_add)
70     {
71       ipsecmb_sa_t *samb = NULL;
72       pool_get (imbm->sad, samb);
73       ASSERT (samb == pool_elt_at_index (imbm->sad, sa_index));
74       sa_expand_keys (sa_index);
75     }
76   else
77     {
78       pool_put_index (imbm->sad, sa_index);
79     }
80   return 0;
81 }
82
83 clib_error_t *
84 ipsecmb_check_esp_support (ipsec_sa_t * sa)
85 {
86   switch (sa->crypto_alg)
87     {
88     case IPSEC_CRYPTO_ALG_NONE:
89       break;
90     case IPSEC_CRYPTO_ALG_DES_CBC:
91     case IPSEC_CRYPTO_ALG_3DES_CBC:
92       return clib_error_return (0, "unsupported (3)des crypto-alg");
93     case IPSEC_CRYPTO_ALG_AES_CBC_128:
94     case IPSEC_CRYPTO_ALG_AES_CBC_192:
95     case IPSEC_CRYPTO_ALG_AES_CBC_256:
96       break;
97     case IPSEC_CRYPTO_ALG_AES_CTR_128:
98     case IPSEC_CRYPTO_ALG_AES_CTR_192:
99     case IPSEC_CRYPTO_ALG_AES_CTR_256:
100       return clib_error_return (0, "unsupported aes-ctr crypto-alg");
101     case IPSEC_CRYPTO_ALG_AES_GCM_128:
102     case IPSEC_CRYPTO_ALG_AES_GCM_192:
103     case IPSEC_CRYPTO_ALG_AES_GCM_256:
104       return clib_error_return (0, "unsupported aes-gcm crypto-alg");
105     case IPSEC_CRYPTO_N_ALG:
106       return clib_error_return (0, "invalid crypto-alg");
107     }
108
109   switch (sa->integ_alg)
110     {
111     case IPSEC_INTEG_ALG_NONE:
112       return clib_error_return (0, "unsupported none integ-alg");
113     case IPSEC_INTEG_ALG_MD5_96:
114       return clib_error_return (0, "unsupported md5 integ-alg");
115     case IPSEC_INTEG_ALG_SHA1_96:
116     case IPSEC_INTEG_ALG_SHA_256_96:
117     case IPSEC_INTEG_ALG_SHA_256_128:
118     case IPSEC_INTEG_ALG_SHA_384_192:
119     case IPSEC_INTEG_ALG_SHA_512_256:
120       break;
121     case IPSEC_INTEG_N_ALG:
122       return clib_error_return (0, "invalid integ-alg");
123     }
124   return 0;
125 }
126
127 clib_error_t *
128 ipsecmb_check_ah_support (ipsec_sa_t * sa)
129 {
130   switch (sa->integ_alg)
131     {
132     case IPSEC_INTEG_ALG_NONE:
133       return clib_error_return (0, "unsupported none integ-alg");
134     case IPSEC_INTEG_ALG_MD5_96:
135       return clib_error_return (0, "unsupported md5 integ-alg");
136     case IPSEC_INTEG_ALG_SHA1_96:
137     case IPSEC_INTEG_ALG_SHA_256_96:
138     case IPSEC_INTEG_ALG_SHA_256_128:
139     case IPSEC_INTEG_ALG_SHA_384_192:
140     case IPSEC_INTEG_ALG_SHA_512_256:
141       break;
142     case IPSEC_INTEG_N_ALG:
143       return clib_error_return (0, "invalid integ-alg");
144     }
145   return 0;
146 }
147
148 static clib_error_t *
149 ipsecmb_init (vlib_main_t * vm)
150 {
151   ipsecmb_main_t *imbm = &ipsecmb_main;
152   imbm->dev_urandom_fd = open ("/dev/urandom", O_RDONLY);
153   if (!imbm->dev_urandom_fd)
154     {
155       return clib_error_return_unix_fatal (0,
156                                            "Can't open /dev/urandom for read");
157     }
158
159   vlib_thread_main_t *tm = vlib_get_thread_main ();
160
161   imbm->crypto_algs = NULL;
162   imbm->integ_algs = NULL;
163
164   vec_validate (imbm->crypto_algs, IPSEC_CRYPTO_N_ALG - 1);
165   vec_validate (imbm->integ_algs, IPSEC_INTEG_N_ALG - 1);
166   imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_128].block_size = 16;
167   imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_192].block_size = 16;
168   imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_256].block_size = 16;
169   imbm->crypto_algs[IPSEC_CRYPTO_ALG_DES_CBC].block_size = 8;
170   imbm->crypto_algs[IPSEC_CRYPTO_ALG_3DES_CBC].block_size = 8;
171   imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_128].iv_size = 16;
172   imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_192].iv_size = 16;
173   imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_256].iv_size = 16;
174   imbm->crypto_algs[IPSEC_CRYPTO_ALG_DES_CBC].iv_size = 8;
175   imbm->crypto_algs[IPSEC_CRYPTO_ALG_3DES_CBC].iv_size = 8;
176   imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_128].cipher_mode = CBC;
177   imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_192].cipher_mode = CBC;
178   imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_256].cipher_mode = CBC;
179
180   ipsecmb_integ_alg_t *i;
181   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA1_96];
182   i->hash_alg = SHA1;
183   i->block_size = SHA1_BLOCK_SIZE;
184
185   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA_256_96];
186   i->hash_alg = SHA_256;
187   i->block_size = SHA_256_BLOCK_SIZE;
188
189   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA_256_128];
190   i->hash_alg = SHA_256;
191   i->block_size = SHA_256_BLOCK_SIZE;
192
193   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA_384_192];
194   i->hash_alg = SHA_384;
195   i->block_size = SHA_384_BLOCK_SIZE;
196
197   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
198   i->hash_alg = SHA_512;
199   i->block_size = SHA_512_BLOCK_SIZE;
200
201   vec_validate (imbm->mb_mgr, tm->n_vlib_mains - 1);
202   MB_MGR **mgr;
203 #define __set_funcs(arch)                                               \
204   do                                                                    \
205     {                                                                   \
206       imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_128].keyexp_fn =       \
207           aes_keyexp_128_##arch;                                        \
208       imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_192].keyexp_fn =       \
209           aes_keyexp_192_##arch;                                        \
210       imbm->crypto_algs[IPSEC_CRYPTO_ALG_AES_CBC_256].keyexp_fn =       \
211           aes_keyexp_256_##arch;                                        \
212       imbm->integ_algs[IPSEC_INTEG_ALG_SHA1_96].hash_one_block_fn =     \
213           sha1_one_block_##arch;                                        \
214       imbm->integ_algs[IPSEC_INTEG_ALG_SHA_256_96].hash_one_block_fn =  \
215           sha256_one_block_##arch;                                      \
216       imbm->integ_algs[IPSEC_INTEG_ALG_SHA_256_128].hash_one_block_fn = \
217           sha256_one_block_##arch;                                      \
218       imbm->integ_algs[IPSEC_INTEG_ALG_SHA_384_192].hash_one_block_fn = \
219           sha384_one_block_##arch;                                      \
220       imbm->integ_algs[IPSEC_INTEG_ALG_SHA_512_256].hash_one_block_fn = \
221           sha512_one_block_##arch;                                      \
222     }                                                                   \
223   while (0);
224
225   if (clib_cpu_supports_avx512f ())
226     {
227       __set_funcs (avx512);
228       vec_foreach (mgr, imbm->mb_mgr)
229       {
230         *mgr = alloc_mb_mgr (0);
231         init_mb_mgr_avx512 (*mgr);
232       }
233     }
234   else if (clib_cpu_supports_avx2 ())
235     {
236       __set_funcs (avx2);
237       vec_foreach (mgr, imbm->mb_mgr)
238       {
239         *mgr = alloc_mb_mgr (0);
240         init_mb_mgr_avx2 (*mgr);
241       }
242     }
243   else
244     {
245       __set_funcs (sse);
246       vec_foreach (mgr, imbm->mb_mgr)
247       {
248         *mgr = alloc_mb_mgr (0);
249         init_mb_mgr_sse (*mgr);
250       }
251     }
252 #undef __set_funcs
253
254
255   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA1_96];
256   i->hash_output_length = 12;
257
258   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA_256_96];
259   i->hash_output_length = 12;
260
261   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA_256_128];
262   i->hash_output_length = 16;
263
264   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA_384_192];
265   i->hash_output_length = 24;
266
267   i = &imbm->integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
268   i->hash_output_length = 32;
269
270   vec_validate (imbm->per_thread_data, tm->n_vlib_mains - 1);
271
272   return 0;
273 }
274
275 VLIB_INIT_FUNCTION (ipsecmb_init);
276
277 static uword
278 ipsecmb_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
279 {
280   ipsec_main_t *im = &ipsec_main;
281   ipsec_register_ah_backend (vm, im, "ipsecmb backend",
282                              "ah4-encrypt-ipsecmb",
283                              "ah4-decrypt-ipsecmb",
284                              "ah6-encrypt-ipsecmb",
285                              "ah6-decrypt-ipsecmb",
286                              ipsecmb_check_ah_support,
287                              ipsecmb_add_del_sa_session);
288
289   ipsec_register_esp_backend (vm, im, "ipsecmb backend",
290                               "esp4-encrypt-ipsecmb",
291                               "esp4-decrypt-ipsecmb",
292                               "esp6-encrypt-ipsecmb",
293                               "esp6-decrypt-ipsecmb",
294                               ipsecmb_check_esp_support,
295                               ipsecmb_add_del_sa_session);
296
297   return 0;
298 }
299
300 /* *INDENT-OFF* */
301 VLIB_REGISTER_NODE (ipsecmb_process_node, static) = {
302     .function = ipsecmb_process,
303     .type = VLIB_NODE_TYPE_PROCESS,
304     .name = "ipsecmb-process",
305     .process_log2_n_stack_bytes = 17,
306 };
307
308 /* *INDENT-OFF* */
309 VLIB_PLUGIN_REGISTER () = {
310     .version = VPP_BUILD_VER,
311     .description = "IPsecMB plugin",
312     .default_disabled = 1,
313 };
314 /* *INDENT-ON* */
315
316 /*
317  * fd.io coding-style-patch-verification: ON
318  *
319  * Local Variables:
320  * eval: (c-set-style "gnu")
321  * End:
322  */