docs: Use newer Ubuntu LTS in tutorial
[vpp.git] / src / plugins / crypto_openssl / main.c
1 /*
2  *------------------------------------------------------------------
3  * Copyright (c) 2019 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *------------------------------------------------------------------
16  */
17
18 #include <sys/syscall.h>
19
20 #include <openssl/evp.h>
21 #include <openssl/hmac.h>
22 #include <openssl/rand.h>
23 #include <openssl/sha.h>
24
25 #include <vlib/vlib.h>
26 #include <vnet/plugin/plugin.h>
27 #include <vnet/crypto/crypto.h>
28 #include <vpp/app/version.h>
29 #include <crypto_openssl/crypto_openssl.h>
30
31 typedef struct
32 {
33   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
34   EVP_CIPHER_CTX **evp_cipher_enc_ctx;
35   EVP_CIPHER_CTX **evp_cipher_dec_ctx;
36   HMAC_CTX **hmac_ctx;
37   EVP_MD_CTX *hash_ctx;
38 #if OPENSSL_VERSION_NUMBER < 0x10100000L
39   HMAC_CTX _hmac_ctx;
40 #endif
41 } openssl_per_thread_data_t;
42
43 static openssl_per_thread_data_t *per_thread_data = 0;
44
45 #define foreach_openssl_aes_evp_op                                            \
46   _ (cbc, DES_CBC, EVP_des_cbc, 8)                                            \
47   _ (cbc, 3DES_CBC, EVP_des_ede3_cbc, 8)                                      \
48   _ (cbc, AES_128_CBC, EVP_aes_128_cbc, 16)                                   \
49   _ (cbc, AES_192_CBC, EVP_aes_192_cbc, 16)                                   \
50   _ (cbc, AES_256_CBC, EVP_aes_256_cbc, 16)                                   \
51   _ (gcm, AES_128_GCM, EVP_aes_128_gcm, 8)                                    \
52   _ (gcm, AES_192_GCM, EVP_aes_192_gcm, 8)                                    \
53   _ (gcm, AES_256_GCM, EVP_aes_256_gcm, 8)                                    \
54   _ (cbc, AES_128_CTR, EVP_aes_128_ctr, 8)                                    \
55   _ (cbc, AES_192_CTR, EVP_aes_192_ctr, 8)                                    \
56   _ (cbc, AES_256_CTR, EVP_aes_256_ctr, 8)                                    \
57   _ (null_gmac, AES_128_NULL_GMAC, EVP_aes_128_gcm, 8)                        \
58   _ (null_gmac, AES_192_NULL_GMAC, EVP_aes_192_gcm, 8)                        \
59   _ (null_gmac, AES_256_NULL_GMAC, EVP_aes_256_gcm, 8)
60
61 #define foreach_openssl_chacha20_evp_op                                       \
62   _ (chacha20_poly1305, CHACHA20_POLY1305, EVP_chacha20_poly1305, 8)
63
64 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
65 #define foreach_openssl_evp_op foreach_openssl_aes_evp_op \
66                                foreach_openssl_chacha20_evp_op
67 #else
68 #define foreach_openssl_evp_op foreach_openssl_aes_evp_op
69 #endif
70
71 #ifndef EVP_CTRL_AEAD_GET_TAG
72 #define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
73 #endif
74
75 #ifndef EVP_CTRL_AEAD_SET_TAG
76 #define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
77 #endif
78
79 #define foreach_openssl_hash_op                                               \
80   _ (SHA1, EVP_sha1)                                                          \
81   _ (SHA224, EVP_sha224)                                                      \
82   _ (SHA256, EVP_sha256)                                                      \
83   _ (SHA384, EVP_sha384)                                                      \
84   _ (SHA512, EVP_sha512)
85
86 #define foreach_openssl_hmac_op \
87   _(MD5, EVP_md5) \
88   _(SHA1, EVP_sha1) \
89   _(SHA224, EVP_sha224) \
90   _(SHA256, EVP_sha256) \
91   _(SHA384, EVP_sha384) \
92   _(SHA512, EVP_sha512)
93
94 crypto_openssl_main_t crypto_openssl_main;
95
96 static_always_inline u32
97 openssl_ops_enc_cbc (vlib_main_t *vm, vnet_crypto_op_t *ops[],
98                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
99                      const EVP_CIPHER *cipher, const int iv_len)
100 {
101   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
102                                                      vm->thread_index);
103   EVP_CIPHER_CTX *ctx;
104   vnet_crypto_op_chunk_t *chp;
105   u32 i, j, curr_len = 0;
106   u8 out_buf[VLIB_BUFFER_DEFAULT_DATA_SIZE * 5];
107
108   for (i = 0; i < n_ops; i++)
109     {
110       vnet_crypto_op_t *op = ops[i];
111       int out_len = 0;
112
113       ctx = ptd->evp_cipher_enc_ctx[op->key_index];
114       EVP_EncryptInit_ex (ctx, NULL, NULL, NULL, op->iv);
115
116       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
117         {
118           chp = chunks + op->chunk_index;
119           u32 offset = 0;
120           for (j = 0; j < op->n_chunks; j++)
121             {
122               EVP_EncryptUpdate (ctx, out_buf + offset, &out_len, chp->src,
123                                  chp->len);
124               curr_len = chp->len;
125               offset += out_len;
126               chp += 1;
127             }
128           if (out_len < curr_len)
129             EVP_EncryptFinal_ex (ctx, out_buf + offset, &out_len);
130
131           offset = 0;
132           chp = chunks + op->chunk_index;
133           for (j = 0; j < op->n_chunks; j++)
134             {
135               clib_memcpy_fast (chp->dst, out_buf + offset, chp->len);
136               offset += chp->len;
137               chp += 1;
138             }
139         }
140       else
141         {
142           EVP_EncryptUpdate (ctx, op->dst, &out_len, op->src, op->len);
143           if (out_len < op->len)
144             EVP_EncryptFinal_ex (ctx, op->dst + out_len, &out_len);
145         }
146       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
147     }
148   return n_ops;
149 }
150
151 static_always_inline u32
152 openssl_ops_dec_cbc (vlib_main_t *vm, vnet_crypto_op_t *ops[],
153                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
154                      const EVP_CIPHER *cipher, const int iv_len)
155 {
156   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
157                                                      vm->thread_index);
158   EVP_CIPHER_CTX *ctx;
159   vnet_crypto_op_chunk_t *chp;
160   u32 i, j, curr_len = 0;
161   u8 out_buf[VLIB_BUFFER_DEFAULT_DATA_SIZE * 5];
162
163   for (i = 0; i < n_ops; i++)
164     {
165       vnet_crypto_op_t *op = ops[i];
166       int out_len = 0;
167
168       ctx = ptd->evp_cipher_dec_ctx[op->key_index];
169       EVP_DecryptInit_ex (ctx, NULL, NULL, NULL, op->iv);
170
171       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
172         {
173           chp = chunks + op->chunk_index;
174           u32 offset = 0;
175           for (j = 0; j < op->n_chunks; j++)
176             {
177               EVP_DecryptUpdate (ctx, out_buf + offset, &out_len, chp->src,
178                                  chp->len);
179               curr_len = chp->len;
180               offset += out_len;
181               chp += 1;
182             }
183           if (out_len < curr_len)
184             EVP_DecryptFinal_ex (ctx, out_buf + offset, &out_len);
185
186           offset = 0;
187           chp = chunks + op->chunk_index;
188           for (j = 0; j < op->n_chunks; j++)
189             {
190               clib_memcpy_fast (chp->dst, out_buf + offset, chp->len);
191               offset += chp->len;
192               chp += 1;
193             }
194         }
195       else
196         {
197           EVP_DecryptUpdate (ctx, op->dst, &out_len, op->src, op->len);
198           if (out_len < op->len)
199             EVP_DecryptFinal_ex (ctx, op->dst + out_len, &out_len);
200         }
201       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
202     }
203   return n_ops;
204 }
205
206 static_always_inline u32
207 openssl_ops_enc_aead (vlib_main_t *vm, vnet_crypto_op_t *ops[],
208                       vnet_crypto_op_chunk_t *chunks, u32 n_ops,
209                       const EVP_CIPHER *cipher, int is_gcm, int is_gmac,
210                       const int iv_len)
211 {
212   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
213                                                      vm->thread_index);
214   EVP_CIPHER_CTX *ctx;
215   vnet_crypto_op_chunk_t *chp;
216   u32 i, j;
217   for (i = 0; i < n_ops; i++)
218     {
219       vnet_crypto_op_t *op = ops[i];
220       int len = 0;
221
222       ctx = ptd->evp_cipher_enc_ctx[op->key_index];
223       EVP_EncryptInit_ex (ctx, 0, 0, NULL, op->iv);
224       if (op->aad_len)
225         EVP_EncryptUpdate (ctx, NULL, &len, op->aad, op->aad_len);
226       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
227         {
228           chp = chunks + op->chunk_index;
229           for (j = 0; j < op->n_chunks; j++)
230             {
231               EVP_EncryptUpdate (ctx, is_gmac ? 0 : chp->dst, &len, chp->src,
232                                  chp->len);
233               chp += 1;
234             }
235         }
236       else
237         EVP_EncryptUpdate (ctx, is_gmac ? 0 : op->dst, &len, op->src, op->len);
238       EVP_EncryptFinal_ex (ctx, is_gmac ? 0 : op->dst + len, &len);
239       EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_AEAD_GET_TAG, op->tag_len, op->tag);
240       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
241     }
242   return n_ops;
243 }
244
245 static_always_inline u32
246 openssl_ops_enc_null_gmac (vlib_main_t *vm, vnet_crypto_op_t *ops[],
247                            vnet_crypto_op_chunk_t *chunks, u32 n_ops,
248                            const EVP_CIPHER *cipher, const int iv_len)
249 {
250   return openssl_ops_enc_aead (vm, ops, chunks, n_ops, cipher,
251                                /* is_gcm */ 1, /* is_gmac */ 1, iv_len);
252 }
253
254 static_always_inline u32
255 openssl_ops_enc_gcm (vlib_main_t *vm, vnet_crypto_op_t *ops[],
256                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
257                      const EVP_CIPHER *cipher, const int iv_len)
258 {
259   return openssl_ops_enc_aead (vm, ops, chunks, n_ops, cipher,
260                                /* is_gcm */ 1, /* is_gmac */ 0, iv_len);
261 }
262
263 static_always_inline __clib_unused u32
264 openssl_ops_enc_chacha20_poly1305 (vlib_main_t *vm, vnet_crypto_op_t *ops[],
265                                    vnet_crypto_op_chunk_t *chunks, u32 n_ops,
266                                    const EVP_CIPHER *cipher, const int iv_len)
267 {
268   return openssl_ops_enc_aead (vm, ops, chunks, n_ops, cipher,
269                                /* is_gcm */ 0, /* is_gmac */ 0, iv_len);
270 }
271
272 static_always_inline u32
273 openssl_ops_dec_aead (vlib_main_t *vm, vnet_crypto_op_t *ops[],
274                       vnet_crypto_op_chunk_t *chunks, u32 n_ops,
275                       const EVP_CIPHER *cipher, int is_gcm, int is_gmac,
276                       const int iv_len)
277 {
278   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
279                                                      vm->thread_index);
280   EVP_CIPHER_CTX *ctx;
281   vnet_crypto_op_chunk_t *chp;
282   u32 i, j, n_fail = 0;
283   for (i = 0; i < n_ops; i++)
284     {
285       vnet_crypto_op_t *op = ops[i];
286       int len = 0;
287
288       ctx = ptd->evp_cipher_dec_ctx[op->key_index];
289       EVP_DecryptInit_ex (ctx, 0, 0, NULL, op->iv);
290       if (op->aad_len)
291         EVP_DecryptUpdate (ctx, 0, &len, op->aad, op->aad_len);
292       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
293         {
294           chp = chunks + op->chunk_index;
295           for (j = 0; j < op->n_chunks; j++)
296             {
297               EVP_DecryptUpdate (ctx, is_gmac ? 0 : chp->dst, &len, chp->src,
298                                  chp->len);
299               chp += 1;
300             }
301         }
302       else
303         {
304           EVP_DecryptUpdate (ctx, is_gmac ? 0 : op->dst, &len, op->src,
305                              op->len);
306         }
307       EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_AEAD_SET_TAG, op->tag_len, op->tag);
308
309       if (EVP_DecryptFinal_ex (ctx, is_gmac ? 0 : op->dst + len, &len) > 0)
310         op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
311       else
312         {
313           n_fail++;
314           op->status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
315         }
316     }
317   return n_ops - n_fail;
318 }
319
320 static_always_inline u32
321 openssl_ops_dec_null_gmac (vlib_main_t *vm, vnet_crypto_op_t *ops[],
322                            vnet_crypto_op_chunk_t *chunks, u32 n_ops,
323                            const EVP_CIPHER *cipher, const int iv_len)
324 {
325   return openssl_ops_dec_aead (vm, ops, chunks, n_ops, cipher,
326                                /* is_gcm */ 1, /* is_gmac */ 1, iv_len);
327 }
328
329 static_always_inline u32
330 openssl_ops_dec_gcm (vlib_main_t *vm, vnet_crypto_op_t *ops[],
331                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
332                      const EVP_CIPHER *cipher, const int iv_len)
333 {
334   return openssl_ops_dec_aead (vm, ops, chunks, n_ops, cipher,
335                                /* is_gcm */ 1, /* is_gmac */ 0, iv_len);
336 }
337
338 static_always_inline __clib_unused u32
339 openssl_ops_dec_chacha20_poly1305 (vlib_main_t *vm, vnet_crypto_op_t *ops[],
340                                    vnet_crypto_op_chunk_t *chunks, u32 n_ops,
341                                    const EVP_CIPHER *cipher, const int iv_len)
342 {
343   return openssl_ops_dec_aead (vm, ops, chunks, n_ops, cipher,
344                                /* is_gcm */ 0, /* is_gmac */ 0, iv_len);
345 }
346
347 static_always_inline u32
348 openssl_ops_hash (vlib_main_t *vm, vnet_crypto_op_t *ops[],
349                   vnet_crypto_op_chunk_t *chunks, u32 n_ops, const EVP_MD *md)
350 {
351   openssl_per_thread_data_t *ptd =
352     vec_elt_at_index (per_thread_data, vm->thread_index);
353   EVP_MD_CTX *ctx = ptd->hash_ctx;
354   vnet_crypto_op_chunk_t *chp;
355   u32 md_len, i, j, n_fail = 0;
356
357   for (i = 0; i < n_ops; i++)
358     {
359       vnet_crypto_op_t *op = ops[i];
360
361       EVP_DigestInit_ex (ctx, md, NULL);
362       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
363         {
364           chp = chunks + op->chunk_index;
365           for (j = 0; j < op->n_chunks; j++)
366             {
367               EVP_DigestUpdate (ctx, chp->src, chp->len);
368               chp += 1;
369             }
370         }
371       else
372         EVP_DigestUpdate (ctx, op->src, op->len);
373
374       EVP_DigestFinal_ex (ctx, op->digest, &md_len);
375       op->digest_len = md_len;
376       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
377     }
378   return n_ops - n_fail;
379 }
380
381 static_always_inline u32
382 openssl_ops_hmac (vlib_main_t * vm, vnet_crypto_op_t * ops[],
383                   vnet_crypto_op_chunk_t * chunks, u32 n_ops,
384                   const EVP_MD * md)
385 {
386   u8 buffer[64];
387   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
388                                                      vm->thread_index);
389   HMAC_CTX *ctx;
390   vnet_crypto_op_chunk_t *chp;
391   u32 i, j, n_fail = 0;
392   for (i = 0; i < n_ops; i++)
393     {
394       vnet_crypto_op_t *op = ops[i];
395       unsigned int out_len = 0;
396       size_t sz = op->digest_len ? op->digest_len : EVP_MD_size (md);
397
398       ctx = ptd->hmac_ctx[op->key_index];
399       HMAC_Init_ex (ctx, NULL, 0, NULL, NULL);
400       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
401         {
402           chp = chunks + op->chunk_index;
403           for (j = 0; j < op->n_chunks; j++)
404             {
405               HMAC_Update (ctx, chp->src, chp->len);
406               chp += 1;
407             }
408         }
409       else
410         HMAC_Update (ctx, op->src, op->len);
411       HMAC_Final (ctx, buffer, &out_len);
412
413       if (op->flags & VNET_CRYPTO_OP_FLAG_HMAC_CHECK)
414         {
415           if ((memcmp (op->digest, buffer, sz)))
416             {
417               n_fail++;
418               op->status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
419               continue;
420             }
421         }
422       else
423         clib_memcpy_fast (op->digest, buffer, sz);
424       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
425     }
426   return n_ops - n_fail;
427 }
428
429 static_always_inline void *
430 openssl_ctx_cipher (vnet_crypto_key_t *key, vnet_crypto_key_op_t kop,
431                     vnet_crypto_key_index_t idx, const EVP_CIPHER *cipher,
432                     int is_gcm)
433 {
434   EVP_CIPHER_CTX *ctx;
435   openssl_per_thread_data_t *ptd;
436
437   if (VNET_CRYPTO_KEY_OP_ADD == kop)
438     {
439       vec_foreach (ptd, per_thread_data)
440         {
441           vec_validate_aligned (ptd->evp_cipher_enc_ctx, idx,
442                                 CLIB_CACHE_LINE_BYTES);
443           vec_validate_aligned (ptd->evp_cipher_dec_ctx, idx,
444                                 CLIB_CACHE_LINE_BYTES);
445
446           ctx = EVP_CIPHER_CTX_new ();
447           EVP_CIPHER_CTX_set_padding (ctx, 0);
448           EVP_EncryptInit_ex (ctx, cipher, NULL, NULL, NULL);
449           if (is_gcm)
450             EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
451           EVP_EncryptInit_ex (ctx, 0, 0, key->data, 0);
452           ptd->evp_cipher_enc_ctx[idx] = ctx;
453
454           ctx = EVP_CIPHER_CTX_new ();
455           EVP_CIPHER_CTX_set_padding (ctx, 0);
456           EVP_DecryptInit_ex (ctx, cipher, 0, 0, 0);
457           if (is_gcm)
458             EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0);
459           EVP_DecryptInit_ex (ctx, 0, 0, key->data, 0);
460           ptd->evp_cipher_dec_ctx[idx] = ctx;
461         }
462     }
463   else if (VNET_CRYPTO_KEY_OP_MODIFY == kop)
464     {
465       vec_foreach (ptd, per_thread_data)
466         {
467           ctx = ptd->evp_cipher_enc_ctx[idx];
468           EVP_EncryptInit_ex (ctx, cipher, NULL, NULL, NULL);
469           if (is_gcm)
470             EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
471           EVP_EncryptInit_ex (ctx, 0, 0, key->data, 0);
472
473           ctx = ptd->evp_cipher_dec_ctx[idx];
474           EVP_DecryptInit_ex (ctx, cipher, 0, 0, 0);
475           if (is_gcm)
476             EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0);
477           EVP_DecryptInit_ex (ctx, 0, 0, key->data, 0);
478         }
479     }
480   else if (VNET_CRYPTO_KEY_OP_DEL == kop)
481     {
482       vec_foreach (ptd, per_thread_data)
483         {
484           ctx = ptd->evp_cipher_enc_ctx[idx];
485           EVP_CIPHER_CTX_free (ctx);
486           ptd->evp_cipher_enc_ctx[idx] = NULL;
487
488           ctx = ptd->evp_cipher_dec_ctx[idx];
489           EVP_CIPHER_CTX_free (ctx);
490           ptd->evp_cipher_dec_ctx[idx] = NULL;
491         }
492     }
493   return NULL;
494 }
495
496 static_always_inline void *
497 openssl_ctx_hmac (vnet_crypto_key_t *key, vnet_crypto_key_op_t kop,
498                   vnet_crypto_key_index_t idx, const EVP_MD *md)
499 {
500   HMAC_CTX *ctx;
501   openssl_per_thread_data_t *ptd;
502   if (VNET_CRYPTO_KEY_OP_ADD == kop)
503     {
504       vec_foreach (ptd, per_thread_data)
505         {
506           vec_validate_aligned (ptd->hmac_ctx, idx, CLIB_CACHE_LINE_BYTES);
507 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
508           ctx = HMAC_CTX_new ();
509           HMAC_Init_ex (ctx, key->data, vec_len (key->data), md, NULL);
510           ptd->hmac_ctx[idx] = ctx;
511 #else
512           HMAC_CTX_init (&(ptd->_hmac_ctx));
513           ptd->hmac_ctx[idx] = &ptd->_hmac_ctx;
514 #endif
515         }
516     }
517   else if (VNET_CRYPTO_KEY_OP_MODIFY == kop)
518     {
519       vec_foreach (ptd, per_thread_data)
520         {
521           ctx = ptd->hmac_ctx[idx];
522           HMAC_Init_ex (ctx, key->data, vec_len (key->data), md, NULL);
523         }
524     }
525   else if (VNET_CRYPTO_KEY_OP_DEL == kop)
526     {
527       vec_foreach (ptd, per_thread_data)
528         {
529           ctx = ptd->hmac_ctx[idx];
530           HMAC_CTX_free (ctx);
531           ptd->hmac_ctx[idx] = NULL;
532         }
533     }
534   return NULL;
535 }
536
537 static void
538 crypto_openssl_key_handler (vlib_main_t *vm, vnet_crypto_key_op_t kop,
539                             vnet_crypto_key_index_t idx)
540 {
541   vnet_crypto_key_t *key = vnet_crypto_get_key (idx);
542   crypto_openssl_main_t *cm = &crypto_openssl_main;
543
544   /** TODO: add linked alg support **/
545   if (key->type == VNET_CRYPTO_KEY_TYPE_LINK)
546     return;
547
548   if (cm->ctx_fn[key->alg] == 0)
549     return;
550
551   cm->ctx_fn[key->alg](key, kop, idx);
552 }
553
554 #define _(m, a, b, iv)                                                        \
555   static u32 openssl_ops_enc_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],   \
556                                   u32 n_ops)                                  \
557   {                                                                           \
558     return openssl_ops_enc_##m (vm, ops, 0, n_ops, b (), iv);                 \
559   }                                                                           \
560                                                                               \
561   u32 openssl_ops_dec_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],          \
562                            u32 n_ops)                                         \
563   {                                                                           \
564     return openssl_ops_dec_##m (vm, ops, 0, n_ops, b (), iv);                 \
565   }                                                                           \
566                                                                               \
567   static u32 openssl_ops_enc_chained_##a (                                    \
568     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
569     u32 n_ops)                                                                \
570   {                                                                           \
571     return openssl_ops_enc_##m (vm, ops, chunks, n_ops, b (), iv);            \
572   }                                                                           \
573                                                                               \
574   static u32 openssl_ops_dec_chained_##a (                                    \
575     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
576     u32 n_ops)                                                                \
577   {                                                                           \
578     return openssl_ops_dec_##m (vm, ops, chunks, n_ops, b (), iv);            \
579   }                                                                           \
580   static void *openssl_ctx_##a (vnet_crypto_key_t *key,                       \
581                                 vnet_crypto_key_op_t kop,                     \
582                                 vnet_crypto_key_index_t idx)                  \
583   {                                                                           \
584     int is_gcm = ((VNET_CRYPTO_ALG_AES_128_GCM <= key->alg) &&                \
585                   (VNET_CRYPTO_ALG_AES_256_NULL_GMAC >= key->alg)) ?          \
586                          1 :                                                        \
587                          0;                                                         \
588     return openssl_ctx_cipher (key, kop, idx, b (), is_gcm);                  \
589   }
590
591 foreach_openssl_evp_op;
592 #undef _
593
594 #define _(a, b)                                                               \
595   static u32 openssl_ops_hash_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],  \
596                                    u32 n_ops)                                 \
597   {                                                                           \
598     return openssl_ops_hash (vm, ops, 0, n_ops, b ());                        \
599   }                                                                           \
600   static u32 openssl_ops_hash_chained_##a (                                   \
601     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
602     u32 n_ops)                                                                \
603   {                                                                           \
604     return openssl_ops_hash (vm, ops, chunks, n_ops, b ());                   \
605   }
606
607 foreach_openssl_hash_op;
608 #undef _
609
610 #define _(a, b)                                                               \
611   static u32 openssl_ops_hmac_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],  \
612                                    u32 n_ops)                                 \
613   {                                                                           \
614     return openssl_ops_hmac (vm, ops, 0, n_ops, b ());                        \
615   }                                                                           \
616   static u32 openssl_ops_hmac_chained_##a (                                   \
617     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
618     u32 n_ops)                                                                \
619   {                                                                           \
620     return openssl_ops_hmac (vm, ops, chunks, n_ops, b ());                   \
621   }                                                                           \
622   static void *openssl_ctx_hmac_##a (vnet_crypto_key_t *key,                  \
623                                      vnet_crypto_key_op_t kop,                \
624                                      vnet_crypto_key_index_t idx)             \
625   {                                                                           \
626     return openssl_ctx_hmac (key, kop, idx, b ());                            \
627   }
628
629 foreach_openssl_hmac_op;
630 #undef _
631
632 clib_error_t *
633 crypto_openssl_init (vlib_main_t * vm)
634 {
635   crypto_openssl_main_t *cm = &crypto_openssl_main;
636   vlib_thread_main_t *tm = vlib_get_thread_main ();
637   openssl_per_thread_data_t *ptd;
638   u8 seed[32];
639
640   if (syscall (SYS_getrandom, &seed, sizeof (seed), 0) != sizeof (seed))
641     return clib_error_return_unix (0, "getrandom() failed");
642
643   RAND_seed (seed, sizeof (seed));
644
645   u32 eidx = vnet_crypto_register_engine (vm, "openssl", 50, "OpenSSL");
646   cm->crypto_engine_index = eidx;
647
648 #define _(m, a, b, iv)                                                        \
649   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_ENC,      \
650                                      openssl_ops_enc_##a,                     \
651                                      openssl_ops_enc_chained_##a);            \
652   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_DEC,      \
653                                      openssl_ops_dec_##a,                     \
654                                      openssl_ops_dec_chained_##a);            \
655   cm->ctx_fn[VNET_CRYPTO_ALG_##a] = openssl_ctx_##a;
656
657   foreach_openssl_evp_op;
658 #undef _
659
660 #define _(a, b)                                                               \
661   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC,     \
662                                      openssl_ops_hmac_##a,                    \
663                                      openssl_ops_hmac_chained_##a);           \
664   cm->ctx_fn[VNET_CRYPTO_ALG_HMAC_##a] = openssl_ctx_hmac_##a;
665
666   foreach_openssl_hmac_op;
667 #undef _
668
669 #define _(a, b)                                                               \
670   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_HASH,     \
671                                      openssl_ops_hash_##a,                    \
672                                      openssl_ops_hash_chained_##a);
673
674   foreach_openssl_hash_op;
675 #undef _
676
677   vec_validate_aligned (per_thread_data, tm->n_vlib_mains - 1,
678                         CLIB_CACHE_LINE_BYTES);
679
680   vec_foreach (ptd, per_thread_data)
681   {
682 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
683     ptd->hash_ctx = EVP_MD_CTX_create ();
684 #endif
685   }
686   vnet_crypto_register_key_handler (vm, cm->crypto_engine_index,
687                                     crypto_openssl_key_handler);
688   return 0;
689 }
690
691 VLIB_INIT_FUNCTION (crypto_openssl_init) =
692 {
693   .runs_after = VLIB_INITS ("vnet_crypto_init"),
694 };
695
696
697 VLIB_PLUGIN_REGISTER () = {
698   .version = VPP_BUILD_VER,
699   .description = "OpenSSL Crypto Engine",
700 };
701
702 /*
703  * fd.io coding-style-patch-verification: ON
704  *
705  * Local Variables:
706  * eval: (c-set-style "gnu")
707  * End:
708  */