e5b142e1a2a9f5de920e607cd83f86cdfde7fd1f
[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
30 typedef struct
31 {
32   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
33   EVP_CIPHER_CTX *evp_cipher_ctx;
34   HMAC_CTX *hmac_ctx;
35   EVP_MD_CTX *hash_ctx;
36 #if OPENSSL_VERSION_NUMBER < 0x10100000L
37   HMAC_CTX _hmac_ctx;
38 #endif
39 } openssl_per_thread_data_t;
40
41 static openssl_per_thread_data_t *per_thread_data = 0;
42
43 #define foreach_openssl_aes_evp_op                                            \
44   _ (cbc, DES_CBC, EVP_des_cbc, 8)                                            \
45   _ (cbc, 3DES_CBC, EVP_des_ede3_cbc, 8)                                      \
46   _ (cbc, AES_128_CBC, EVP_aes_128_cbc, 16)                                   \
47   _ (cbc, AES_192_CBC, EVP_aes_192_cbc, 16)                                   \
48   _ (cbc, AES_256_CBC, EVP_aes_256_cbc, 16)                                   \
49   _ (gcm, AES_128_GCM, EVP_aes_128_gcm, 8)                                    \
50   _ (gcm, AES_192_GCM, EVP_aes_192_gcm, 8)                                    \
51   _ (gcm, AES_256_GCM, EVP_aes_256_gcm, 8)                                    \
52   _ (cbc, AES_128_CTR, EVP_aes_128_ctr, 8)                                    \
53   _ (cbc, AES_192_CTR, EVP_aes_192_ctr, 8)                                    \
54   _ (cbc, AES_256_CTR, EVP_aes_256_ctr, 8)                                    \
55   _ (null_gmac, AES_128_NULL_GMAC, EVP_aes_128_gcm, 8)                        \
56   _ (null_gmac, AES_192_NULL_GMAC, EVP_aes_192_gcm, 8)                        \
57   _ (null_gmac, AES_256_NULL_GMAC, EVP_aes_256_gcm, 8)
58
59 #define foreach_openssl_chacha20_evp_op                                       \
60   _ (chacha20_poly1305, CHACHA20_POLY1305, EVP_chacha20_poly1305, 8)
61
62 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
63 #define foreach_openssl_evp_op foreach_openssl_aes_evp_op \
64                                foreach_openssl_chacha20_evp_op
65 #else
66 #define foreach_openssl_evp_op foreach_openssl_aes_evp_op
67 #endif
68
69 #ifndef EVP_CTRL_AEAD_GET_TAG
70 #define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
71 #endif
72
73 #ifndef EVP_CTRL_AEAD_SET_TAG
74 #define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
75 #endif
76
77 #define foreach_openssl_hash_op                                               \
78   _ (SHA1, EVP_sha1)                                                          \
79   _ (SHA224, EVP_sha224)                                                      \
80   _ (SHA256, EVP_sha256)                                                      \
81   _ (SHA384, EVP_sha384)                                                      \
82   _ (SHA512, EVP_sha512)
83
84 #define foreach_openssl_hmac_op \
85   _(MD5, EVP_md5) \
86   _(SHA1, EVP_sha1) \
87   _(SHA224, EVP_sha224) \
88   _(SHA256, EVP_sha256) \
89   _(SHA384, EVP_sha384) \
90   _(SHA512, EVP_sha512)
91
92 static_always_inline u32
93 openssl_ops_enc_cbc (vlib_main_t *vm, vnet_crypto_op_t *ops[],
94                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
95                      const EVP_CIPHER *cipher, const int iv_len)
96 {
97   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
98                                                      vm->thread_index);
99   EVP_CIPHER_CTX *ctx = ptd->evp_cipher_ctx;
100   vnet_crypto_op_chunk_t *chp;
101   u32 i, j, curr_len = 0;
102   u8 out_buf[VLIB_BUFFER_DEFAULT_DATA_SIZE * 5];
103
104   for (i = 0; i < n_ops; i++)
105     {
106       vnet_crypto_op_t *op = ops[i];
107       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
108       int out_len = 0;
109
110       EVP_EncryptInit_ex (ctx, cipher, NULL, key->data, op->iv);
111
112       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
113         {
114           chp = chunks + op->chunk_index;
115           u32 offset = 0;
116           for (j = 0; j < op->n_chunks; j++)
117             {
118               EVP_EncryptUpdate (ctx, out_buf + offset, &out_len, chp->src,
119                                  chp->len);
120               curr_len = chp->len;
121               offset += out_len;
122               chp += 1;
123             }
124           if (out_len < curr_len)
125             EVP_EncryptFinal_ex (ctx, out_buf + offset, &out_len);
126
127           offset = 0;
128           chp = chunks + op->chunk_index;
129           for (j = 0; j < op->n_chunks; j++)
130             {
131               clib_memcpy_fast (chp->dst, out_buf + offset, chp->len);
132               offset += chp->len;
133               chp += 1;
134             }
135         }
136       else
137         {
138           EVP_EncryptUpdate (ctx, op->dst, &out_len, op->src, op->len);
139           if (out_len < op->len)
140             EVP_EncryptFinal_ex (ctx, op->dst + out_len, &out_len);
141         }
142       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
143     }
144   return n_ops;
145 }
146
147 static_always_inline u32
148 openssl_ops_dec_cbc (vlib_main_t *vm, vnet_crypto_op_t *ops[],
149                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
150                      const EVP_CIPHER *cipher, const int iv_len)
151 {
152   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
153                                                      vm->thread_index);
154   EVP_CIPHER_CTX *ctx = ptd->evp_cipher_ctx;
155   vnet_crypto_op_chunk_t *chp;
156   u32 i, j, curr_len = 0;
157   u8 out_buf[VLIB_BUFFER_DEFAULT_DATA_SIZE * 5];
158
159   for (i = 0; i < n_ops; i++)
160     {
161       vnet_crypto_op_t *op = ops[i];
162       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
163       int out_len = 0;
164
165       EVP_DecryptInit_ex (ctx, cipher, NULL, key->data, op->iv);
166
167       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
168         {
169           chp = chunks + op->chunk_index;
170           u32 offset = 0;
171           for (j = 0; j < op->n_chunks; j++)
172             {
173               EVP_DecryptUpdate (ctx, out_buf + offset, &out_len, chp->src,
174                                  chp->len);
175               curr_len = chp->len;
176               offset += out_len;
177               chp += 1;
178             }
179           if (out_len < curr_len)
180             EVP_DecryptFinal_ex (ctx, out_buf + offset, &out_len);
181
182           offset = 0;
183           chp = chunks + op->chunk_index;
184           for (j = 0; j < op->n_chunks; j++)
185             {
186               clib_memcpy_fast (chp->dst, out_buf + offset, chp->len);
187               offset += chp->len;
188               chp += 1;
189             }
190         }
191       else
192         {
193           EVP_DecryptUpdate (ctx, op->dst, &out_len, op->src, op->len);
194           if (out_len < op->len)
195             EVP_DecryptFinal_ex (ctx, op->dst + out_len, &out_len);
196         }
197       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
198     }
199   return n_ops;
200 }
201
202 static_always_inline u32
203 openssl_ops_enc_aead (vlib_main_t *vm, vnet_crypto_op_t *ops[],
204                       vnet_crypto_op_chunk_t *chunks, u32 n_ops,
205                       const EVP_CIPHER *cipher, int is_gcm, int is_gmac,
206                       const int iv_len)
207 {
208   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
209                                                      vm->thread_index);
210   EVP_CIPHER_CTX *ctx = ptd->evp_cipher_ctx;
211   vnet_crypto_op_chunk_t *chp;
212   u32 i, j;
213   for (i = 0; i < n_ops; i++)
214     {
215       vnet_crypto_op_t *op = ops[i];
216       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
217       int len = 0;
218
219       EVP_EncryptInit_ex (ctx, cipher, 0, 0, 0);
220       if (is_gcm)
221         EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
222       EVP_EncryptInit_ex (ctx, 0, 0, key->data, op->iv);
223       if (op->aad_len)
224         EVP_EncryptUpdate (ctx, NULL, &len, op->aad, op->aad_len);
225       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
226         {
227           chp = chunks + op->chunk_index;
228           for (j = 0; j < op->n_chunks; j++)
229             {
230               EVP_EncryptUpdate (ctx, is_gmac ? 0 : chp->dst, &len, chp->src,
231                                  chp->len);
232               chp += 1;
233             }
234         }
235       else
236         EVP_EncryptUpdate (ctx, is_gmac ? 0 : op->dst, &len, op->src, op->len);
237       EVP_EncryptFinal_ex (ctx, is_gmac ? 0 : op->dst + len, &len);
238       EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_AEAD_GET_TAG, op->tag_len, op->tag);
239       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
240     }
241   return n_ops;
242 }
243
244 static_always_inline u32
245 openssl_ops_enc_null_gmac (vlib_main_t *vm, vnet_crypto_op_t *ops[],
246                            vnet_crypto_op_chunk_t *chunks, u32 n_ops,
247                            const EVP_CIPHER *cipher, const int iv_len)
248 {
249   return openssl_ops_enc_aead (vm, ops, chunks, n_ops, cipher,
250                                /* is_gcm */ 1, /* is_gmac */ 1, iv_len);
251 }
252
253 static_always_inline u32
254 openssl_ops_enc_gcm (vlib_main_t *vm, vnet_crypto_op_t *ops[],
255                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
256                      const EVP_CIPHER *cipher, const int iv_len)
257 {
258   return openssl_ops_enc_aead (vm, ops, chunks, n_ops, cipher,
259                                /* is_gcm */ 1, /* is_gmac */ 0, iv_len);
260 }
261
262 static_always_inline __clib_unused u32
263 openssl_ops_enc_chacha20_poly1305 (vlib_main_t *vm, vnet_crypto_op_t *ops[],
264                                    vnet_crypto_op_chunk_t *chunks, u32 n_ops,
265                                    const EVP_CIPHER *cipher, const int iv_len)
266 {
267   return openssl_ops_enc_aead (vm, ops, chunks, n_ops, cipher,
268                                /* is_gcm */ 0, /* is_gmac */ 0, iv_len);
269 }
270
271 static_always_inline u32
272 openssl_ops_dec_aead (vlib_main_t *vm, vnet_crypto_op_t *ops[],
273                       vnet_crypto_op_chunk_t *chunks, u32 n_ops,
274                       const EVP_CIPHER *cipher, int is_gcm, int is_gmac,
275                       const int iv_len)
276 {
277   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
278                                                      vm->thread_index);
279   EVP_CIPHER_CTX *ctx = ptd->evp_cipher_ctx;
280   vnet_crypto_op_chunk_t *chp;
281   u32 i, j, n_fail = 0;
282   for (i = 0; i < n_ops; i++)
283     {
284       vnet_crypto_op_t *op = ops[i];
285       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
286       int len = 0;
287
288       EVP_DecryptInit_ex (ctx, cipher, 0, 0, 0);
289       if (is_gcm)
290         EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0);
291       EVP_DecryptInit_ex (ctx, 0, 0, key->data, op->iv);
292       if (op->aad_len)
293         EVP_DecryptUpdate (ctx, 0, &len, op->aad, op->aad_len);
294       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
295         {
296           chp = chunks + op->chunk_index;
297           for (j = 0; j < op->n_chunks; j++)
298             {
299               EVP_DecryptUpdate (ctx, is_gmac ? 0 : chp->dst, &len, chp->src,
300                                  chp->len);
301               chp += 1;
302             }
303         }
304       else
305         {
306           EVP_DecryptUpdate (ctx, is_gmac ? 0 : op->dst, &len, op->src,
307                              op->len);
308         }
309       EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_AEAD_SET_TAG, op->tag_len, op->tag);
310
311       if (EVP_DecryptFinal_ex (ctx, is_gmac ? 0 : op->dst + len, &len) > 0)
312         op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
313       else
314         {
315           n_fail++;
316           op->status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
317         }
318     }
319   return n_ops - n_fail;
320 }
321
322 static_always_inline u32
323 openssl_ops_dec_null_gmac (vlib_main_t *vm, vnet_crypto_op_t *ops[],
324                            vnet_crypto_op_chunk_t *chunks, u32 n_ops,
325                            const EVP_CIPHER *cipher, const int iv_len)
326 {
327   return openssl_ops_dec_aead (vm, ops, chunks, n_ops, cipher,
328                                /* is_gcm */ 1, /* is_gmac */ 1, iv_len);
329 }
330
331 static_always_inline u32
332 openssl_ops_dec_gcm (vlib_main_t *vm, vnet_crypto_op_t *ops[],
333                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
334                      const EVP_CIPHER *cipher, const int iv_len)
335 {
336   return openssl_ops_dec_aead (vm, ops, chunks, n_ops, cipher,
337                                /* is_gcm */ 1, /* is_gmac */ 0, iv_len);
338 }
339
340 static_always_inline __clib_unused u32
341 openssl_ops_dec_chacha20_poly1305 (vlib_main_t *vm, vnet_crypto_op_t *ops[],
342                                    vnet_crypto_op_chunk_t *chunks, u32 n_ops,
343                                    const EVP_CIPHER *cipher, const int iv_len)
344 {
345   return openssl_ops_dec_aead (vm, ops, chunks, n_ops, cipher,
346                                /* is_gcm */ 0, /* is_gmac */ 0, iv_len);
347 }
348
349 static_always_inline u32
350 openssl_ops_hash (vlib_main_t *vm, vnet_crypto_op_t *ops[],
351                   vnet_crypto_op_chunk_t *chunks, u32 n_ops, const EVP_MD *md)
352 {
353   openssl_per_thread_data_t *ptd =
354     vec_elt_at_index (per_thread_data, vm->thread_index);
355   EVP_MD_CTX *ctx = ptd->hash_ctx;
356   vnet_crypto_op_chunk_t *chp;
357   u32 md_len, i, j, n_fail = 0;
358
359   for (i = 0; i < n_ops; i++)
360     {
361       vnet_crypto_op_t *op = ops[i];
362
363       EVP_DigestInit_ex (ctx, md, NULL);
364       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
365         {
366           chp = chunks + op->chunk_index;
367           for (j = 0; j < op->n_chunks; j++)
368             {
369               EVP_DigestUpdate (ctx, chp->src, chp->len);
370               chp += 1;
371             }
372         }
373       else
374         EVP_DigestUpdate (ctx, op->src, op->len);
375
376       EVP_DigestFinal_ex (ctx, op->digest, &md_len);
377       op->digest_len = md_len;
378       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
379     }
380   return n_ops - n_fail;
381 }
382
383 static_always_inline u32
384 openssl_ops_hmac (vlib_main_t * vm, vnet_crypto_op_t * ops[],
385                   vnet_crypto_op_chunk_t * chunks, u32 n_ops,
386                   const EVP_MD * md)
387 {
388   u8 buffer[64];
389   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
390                                                      vm->thread_index);
391   HMAC_CTX *ctx = ptd->hmac_ctx;
392   vnet_crypto_op_chunk_t *chp;
393   u32 i, j, n_fail = 0;
394   for (i = 0; i < n_ops; i++)
395     {
396       vnet_crypto_op_t *op = ops[i];
397       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
398       unsigned int out_len = 0;
399       size_t sz = op->digest_len ? op->digest_len : EVP_MD_size (md);
400
401       HMAC_Init_ex (ctx, key->data, vec_len (key->data), md, NULL);
402       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
403         {
404           chp = chunks + op->chunk_index;
405           for (j = 0; j < op->n_chunks; j++)
406             {
407               HMAC_Update (ctx, chp->src, chp->len);
408               chp += 1;
409             }
410         }
411       else
412         HMAC_Update (ctx, op->src, op->len);
413       HMAC_Final (ctx, buffer, &out_len);
414
415       if (op->flags & VNET_CRYPTO_OP_FLAG_HMAC_CHECK)
416         {
417           if ((memcmp (op->digest, buffer, sz)))
418             {
419               n_fail++;
420               op->status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
421               continue;
422             }
423         }
424       else
425         clib_memcpy_fast (op->digest, buffer, sz);
426       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
427     }
428   return n_ops - n_fail;
429 }
430
431 #define _(m, a, b, iv)                                                        \
432   static u32 openssl_ops_enc_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],   \
433                                   u32 n_ops)                                  \
434   {                                                                           \
435     return openssl_ops_enc_##m (vm, ops, 0, n_ops, b (), iv);                 \
436   }                                                                           \
437                                                                               \
438   u32 openssl_ops_dec_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],          \
439                            u32 n_ops)                                         \
440   {                                                                           \
441     return openssl_ops_dec_##m (vm, ops, 0, n_ops, b (), iv);                 \
442   }                                                                           \
443                                                                               \
444   static u32 openssl_ops_enc_chained_##a (                                    \
445     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
446     u32 n_ops)                                                                \
447   {                                                                           \
448     return openssl_ops_enc_##m (vm, ops, chunks, n_ops, b (), iv);            \
449   }                                                                           \
450                                                                               \
451   static u32 openssl_ops_dec_chained_##a (                                    \
452     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
453     u32 n_ops)                                                                \
454   {                                                                           \
455     return openssl_ops_dec_##m (vm, ops, chunks, n_ops, b (), iv);            \
456   }
457
458 foreach_openssl_evp_op;
459 #undef _
460
461 #define _(a, b)                                                               \
462   static u32 openssl_ops_hash_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],  \
463                                    u32 n_ops)                                 \
464   {                                                                           \
465     return openssl_ops_hash (vm, ops, 0, n_ops, b ());                        \
466   }                                                                           \
467   static u32 openssl_ops_hash_chained_##a (                                   \
468     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
469     u32 n_ops)                                                                \
470   {                                                                           \
471     return openssl_ops_hash (vm, ops, chunks, n_ops, b ());                   \
472   }
473
474 foreach_openssl_hash_op;
475 #undef _
476
477 #define _(a, b) \
478 static u32 \
479 openssl_ops_hmac_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops) \
480 { return openssl_ops_hmac (vm, ops, 0, n_ops, b ()); } \
481 static u32 \
482 openssl_ops_hmac_chained_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], \
483     vnet_crypto_op_chunk_t *chunks, u32 n_ops) \
484 { return openssl_ops_hmac (vm, ops, chunks, n_ops, b ()); } \
485
486 foreach_openssl_hmac_op;
487 #undef _
488
489
490 clib_error_t *
491 crypto_openssl_init (vlib_main_t * vm)
492 {
493   vlib_thread_main_t *tm = vlib_get_thread_main ();
494   openssl_per_thread_data_t *ptd;
495   u8 seed[32];
496
497   if (syscall (SYS_getrandom, &seed, sizeof (seed), 0) != sizeof (seed))
498     return clib_error_return_unix (0, "getrandom() failed");
499
500   RAND_seed (seed, sizeof (seed));
501
502   u32 eidx = vnet_crypto_register_engine (vm, "openssl", 50, "OpenSSL");
503
504 #define _(m, a, b, iv)                                                        \
505   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_ENC,      \
506                                      openssl_ops_enc_##a,                     \
507                                      openssl_ops_enc_chained_##a);            \
508   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_DEC,      \
509                                      openssl_ops_dec_##a,                     \
510                                      openssl_ops_dec_chained_##a);
511
512   foreach_openssl_evp_op;
513 #undef _
514
515 #define _(a, b) \
516   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC, \
517                                     openssl_ops_hmac_##a, \
518                                     openssl_ops_hmac_chained_##a); \
519
520   foreach_openssl_hmac_op;
521 #undef _
522
523 #define _(a, b)                                                               \
524   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_HASH,     \
525                                      openssl_ops_hash_##a,                    \
526                                      openssl_ops_hash_chained_##a);
527
528   foreach_openssl_hash_op;
529 #undef _
530
531   vec_validate_aligned (per_thread_data, tm->n_vlib_mains - 1,
532                         CLIB_CACHE_LINE_BYTES);
533
534   vec_foreach (ptd, per_thread_data)
535   {
536     ptd->evp_cipher_ctx = EVP_CIPHER_CTX_new ();
537     EVP_CIPHER_CTX_set_padding (ptd->evp_cipher_ctx, 0);
538 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
539     ptd->hmac_ctx = HMAC_CTX_new ();
540     ptd->hash_ctx = EVP_MD_CTX_create ();
541 #else
542     HMAC_CTX_init (&(ptd->_hmac_ctx));
543     ptd->hmac_ctx = &ptd->_hmac_ctx;
544 #endif
545   }
546
547   return 0;
548 }
549
550 /* *INDENT-OFF* */
551 VLIB_INIT_FUNCTION (crypto_openssl_init) =
552 {
553   .runs_after = VLIB_INITS ("vnet_crypto_init"),
554 };
555 /* *INDENT-ON* */
556
557
558 /* *INDENT-OFF* */
559 VLIB_PLUGIN_REGISTER () = {
560   .version = VPP_BUILD_VER,
561   .description = "OpenSSL Crypto Engine",
562 };
563 /* *INDENT-ON* */
564
565 /*
566  * fd.io coding-style-patch-verification: ON
567  *
568  * Local Variables:
569  * eval: (c-set-style "gnu")
570  * End:
571  */