251e75d6255cc64e80709cda0cea987831f48027
[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
56 #define foreach_openssl_chacha20_evp_op                                       \
57   _ (chacha20_poly1305, CHACHA20_POLY1305, EVP_chacha20_poly1305, 8)
58
59 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
60 #define foreach_openssl_evp_op foreach_openssl_aes_evp_op \
61                                foreach_openssl_chacha20_evp_op
62 #else
63 #define foreach_openssl_evp_op foreach_openssl_aes_evp_op
64 #endif
65
66 #ifndef EVP_CTRL_AEAD_GET_TAG
67 #define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
68 #endif
69
70 #ifndef EVP_CTRL_AEAD_SET_TAG
71 #define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
72 #endif
73
74 #define foreach_openssl_hash_op                                               \
75   _ (SHA1, EVP_sha1)                                                          \
76   _ (SHA224, EVP_sha224)                                                      \
77   _ (SHA256, EVP_sha256)                                                      \
78   _ (SHA384, EVP_sha384)                                                      \
79   _ (SHA512, EVP_sha512)
80
81 #define foreach_openssl_hmac_op \
82   _(MD5, EVP_md5) \
83   _(SHA1, EVP_sha1) \
84   _(SHA224, EVP_sha224) \
85   _(SHA256, EVP_sha256) \
86   _(SHA384, EVP_sha384) \
87   _(SHA512, EVP_sha512)
88
89 static_always_inline u32
90 openssl_ops_enc_cbc (vlib_main_t *vm, vnet_crypto_op_t *ops[],
91                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
92                      const EVP_CIPHER *cipher, const int iv_len)
93 {
94   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
95                                                      vm->thread_index);
96   EVP_CIPHER_CTX *ctx = ptd->evp_cipher_ctx;
97   vnet_crypto_op_chunk_t *chp;
98   u32 i, j, curr_len = 0;
99   u8 out_buf[VLIB_BUFFER_DEFAULT_DATA_SIZE * 5];
100
101   for (i = 0; i < n_ops; i++)
102     {
103       vnet_crypto_op_t *op = ops[i];
104       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
105       int out_len = 0;
106
107       if (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
108         RAND_bytes (op->iv, iv_len);
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, const int iv_len)
206 {
207   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
208                                                      vm->thread_index);
209   EVP_CIPHER_CTX *ctx = ptd->evp_cipher_ctx;
210   vnet_crypto_op_chunk_t *chp;
211   u32 i, j;
212   for (i = 0; i < n_ops; i++)
213     {
214       vnet_crypto_op_t *op = ops[i];
215       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
216       int len = 0;
217
218       if (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
219         RAND_bytes (op->iv, 8);
220
221       EVP_EncryptInit_ex (ctx, cipher, 0, 0, 0);
222       if (is_gcm)
223         EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
224       EVP_EncryptInit_ex (ctx, 0, 0, key->data, op->iv);
225       if (op->aad_len)
226         EVP_EncryptUpdate (ctx, NULL, &len, op->aad, op->aad_len);
227       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
228         {
229           chp = chunks + op->chunk_index;
230           for (j = 0; j < op->n_chunks; j++)
231             {
232               EVP_EncryptUpdate (ctx, chp->dst, &len, chp->src, chp->len);
233               chp += 1;
234             }
235         }
236       else
237         EVP_EncryptUpdate (ctx, op->dst, &len, op->src, op->len);
238       EVP_EncryptFinal_ex (ctx, 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_gcm (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, iv_len);
252 }
253
254 static_always_inline __clib_unused u32
255 openssl_ops_enc_chacha20_poly1305 (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 */ 0, iv_len);
261 }
262
263 static_always_inline u32
264 openssl_ops_dec_aead (vlib_main_t *vm, vnet_crypto_op_t *ops[],
265                       vnet_crypto_op_chunk_t *chunks, u32 n_ops,
266                       const EVP_CIPHER *cipher, int is_gcm, const int iv_len)
267 {
268   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
269                                                      vm->thread_index);
270   EVP_CIPHER_CTX *ctx = ptd->evp_cipher_ctx;
271   vnet_crypto_op_chunk_t *chp;
272   u32 i, j, n_fail = 0;
273   for (i = 0; i < n_ops; i++)
274     {
275       vnet_crypto_op_t *op = ops[i];
276       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
277       int len = 0;
278
279       EVP_DecryptInit_ex (ctx, cipher, 0, 0, 0);
280       if (is_gcm)
281         EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, 0);
282       EVP_DecryptInit_ex (ctx, 0, 0, key->data, op->iv);
283       if (op->aad_len)
284         EVP_DecryptUpdate (ctx, 0, &len, op->aad, op->aad_len);
285       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
286         {
287           chp = chunks + op->chunk_index;
288           for (j = 0; j < op->n_chunks; j++)
289             {
290               EVP_DecryptUpdate (ctx, chp->dst, &len, chp->src, chp->len);
291               chp += 1;
292             }
293         }
294       else
295         EVP_DecryptUpdate (ctx, op->dst, &len, op->src, op->len);
296       EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_AEAD_SET_TAG, op->tag_len, op->tag);
297
298       if (EVP_DecryptFinal_ex (ctx, op->dst + len, &len) > 0)
299         op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
300       else
301         {
302           n_fail++;
303           op->status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
304         }
305     }
306   return n_ops - n_fail;
307 }
308
309 static_always_inline u32
310 openssl_ops_dec_gcm (vlib_main_t *vm, vnet_crypto_op_t *ops[],
311                      vnet_crypto_op_chunk_t *chunks, u32 n_ops,
312                      const EVP_CIPHER *cipher, const int iv_len)
313 {
314   return openssl_ops_dec_aead (vm, ops, chunks, n_ops, cipher,
315                                /* is_gcm */ 1, iv_len);
316 }
317
318 static_always_inline __clib_unused u32
319 openssl_ops_dec_chacha20_poly1305 (vlib_main_t *vm, vnet_crypto_op_t *ops[],
320                                    vnet_crypto_op_chunk_t *chunks, u32 n_ops,
321                                    const EVP_CIPHER *cipher, const int iv_len)
322 {
323   return openssl_ops_dec_aead (vm, ops, chunks, n_ops, cipher,
324                                /* is_gcm */ 0, iv_len);
325 }
326
327 static_always_inline u32
328 openssl_ops_hash (vlib_main_t *vm, vnet_crypto_op_t *ops[],
329                   vnet_crypto_op_chunk_t *chunks, u32 n_ops, const EVP_MD *md)
330 {
331   openssl_per_thread_data_t *ptd =
332     vec_elt_at_index (per_thread_data, vm->thread_index);
333   EVP_MD_CTX *ctx = ptd->hash_ctx;
334   vnet_crypto_op_chunk_t *chp;
335   u32 md_len, i, j, n_fail = 0;
336
337   for (i = 0; i < n_ops; i++)
338     {
339       vnet_crypto_op_t *op = ops[i];
340
341       EVP_DigestInit_ex (ctx, md, NULL);
342       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
343         {
344           chp = chunks + op->chunk_index;
345           for (j = 0; j < op->n_chunks; j++)
346             {
347               EVP_DigestUpdate (ctx, chp->src, chp->len);
348               chp += 1;
349             }
350         }
351       else
352         EVP_DigestUpdate (ctx, op->src, op->len);
353
354       EVP_DigestFinal_ex (ctx, op->digest, &md_len);
355       op->digest_len = md_len;
356       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
357     }
358   return n_ops - n_fail;
359 }
360
361 static_always_inline u32
362 openssl_ops_hmac (vlib_main_t * vm, vnet_crypto_op_t * ops[],
363                   vnet_crypto_op_chunk_t * chunks, u32 n_ops,
364                   const EVP_MD * md)
365 {
366   u8 buffer[64];
367   openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data,
368                                                      vm->thread_index);
369   HMAC_CTX *ctx = ptd->hmac_ctx;
370   vnet_crypto_op_chunk_t *chp;
371   u32 i, j, n_fail = 0;
372   for (i = 0; i < n_ops; i++)
373     {
374       vnet_crypto_op_t *op = ops[i];
375       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
376       unsigned int out_len = 0;
377       size_t sz = op->digest_len ? op->digest_len : EVP_MD_size (md);
378
379       HMAC_Init_ex (ctx, key->data, vec_len (key->data), md, NULL);
380       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
381         {
382           chp = chunks + op->chunk_index;
383           for (j = 0; j < op->n_chunks; j++)
384             {
385               HMAC_Update (ctx, chp->src, chp->len);
386               chp += 1;
387             }
388         }
389       else
390         HMAC_Update (ctx, op->src, op->len);
391       HMAC_Final (ctx, buffer, &out_len);
392
393       if (op->flags & VNET_CRYPTO_OP_FLAG_HMAC_CHECK)
394         {
395           if ((memcmp (op->digest, buffer, sz)))
396             {
397               n_fail++;
398               op->status = VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC;
399               continue;
400             }
401         }
402       else
403         clib_memcpy_fast (op->digest, buffer, sz);
404       op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
405     }
406   return n_ops - n_fail;
407 }
408
409 #define _(m, a, b, iv)                                                        \
410   static u32 openssl_ops_enc_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],   \
411                                   u32 n_ops)                                  \
412   {                                                                           \
413     return openssl_ops_enc_##m (vm, ops, 0, n_ops, b (), iv);                 \
414   }                                                                           \
415                                                                               \
416   u32 openssl_ops_dec_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],          \
417                            u32 n_ops)                                         \
418   {                                                                           \
419     return openssl_ops_dec_##m (vm, ops, 0, n_ops, b (), iv);                 \
420   }                                                                           \
421                                                                               \
422   static u32 openssl_ops_enc_chained_##a (                                    \
423     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
424     u32 n_ops)                                                                \
425   {                                                                           \
426     return openssl_ops_enc_##m (vm, ops, chunks, n_ops, b (), iv);            \
427   }                                                                           \
428                                                                               \
429   static u32 openssl_ops_dec_chained_##a (                                    \
430     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
431     u32 n_ops)                                                                \
432   {                                                                           \
433     return openssl_ops_dec_##m (vm, ops, chunks, n_ops, b (), iv);            \
434   }
435
436 foreach_openssl_evp_op;
437 #undef _
438
439 #define _(a, b)                                                               \
440   static u32 openssl_ops_hash_##a (vlib_main_t *vm, vnet_crypto_op_t *ops[],  \
441                                    u32 n_ops)                                 \
442   {                                                                           \
443     return openssl_ops_hash (vm, ops, 0, n_ops, b ());                        \
444   }                                                                           \
445   static u32 openssl_ops_hash_chained_##a (                                   \
446     vlib_main_t *vm, vnet_crypto_op_t *ops[], vnet_crypto_op_chunk_t *chunks, \
447     u32 n_ops)                                                                \
448   {                                                                           \
449     return openssl_ops_hash (vm, ops, chunks, n_ops, b ());                   \
450   }
451
452 foreach_openssl_hash_op;
453 #undef _
454
455 #define _(a, b) \
456 static u32 \
457 openssl_ops_hmac_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops) \
458 { return openssl_ops_hmac (vm, ops, 0, n_ops, b ()); } \
459 static u32 \
460 openssl_ops_hmac_chained_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], \
461     vnet_crypto_op_chunk_t *chunks, u32 n_ops) \
462 { return openssl_ops_hmac (vm, ops, chunks, n_ops, b ()); } \
463
464 foreach_openssl_hmac_op;
465 #undef _
466
467
468 clib_error_t *
469 crypto_openssl_init (vlib_main_t * vm)
470 {
471   vlib_thread_main_t *tm = vlib_get_thread_main ();
472   openssl_per_thread_data_t *ptd;
473   u8 seed[32];
474
475   if (syscall (SYS_getrandom, &seed, sizeof (seed), 0) != sizeof (seed))
476     return clib_error_return_unix (0, "getrandom() failed");
477
478   RAND_seed (seed, sizeof (seed));
479
480   u32 eidx = vnet_crypto_register_engine (vm, "openssl", 50, "OpenSSL");
481
482 #define _(m, a, b, iv)                                                        \
483   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_ENC,      \
484                                      openssl_ops_enc_##a,                     \
485                                      openssl_ops_enc_chained_##a);            \
486   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_DEC,      \
487                                      openssl_ops_dec_##a,                     \
488                                      openssl_ops_dec_chained_##a);
489
490   foreach_openssl_evp_op;
491 #undef _
492
493 #define _(a, b) \
494   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC, \
495                                     openssl_ops_hmac_##a, \
496                                     openssl_ops_hmac_chained_##a); \
497
498   foreach_openssl_hmac_op;
499 #undef _
500
501 #define _(a, b)                                                               \
502   vnet_crypto_register_ops_handlers (vm, eidx, VNET_CRYPTO_OP_##a##_HASH,     \
503                                      openssl_ops_hash_##a,                    \
504                                      openssl_ops_hash_chained_##a);
505
506   foreach_openssl_hash_op;
507 #undef _
508
509   vec_validate_aligned (per_thread_data, tm->n_vlib_mains - 1,
510                         CLIB_CACHE_LINE_BYTES);
511
512   vec_foreach (ptd, per_thread_data)
513   {
514     ptd->evp_cipher_ctx = EVP_CIPHER_CTX_new ();
515     EVP_CIPHER_CTX_set_padding (ptd->evp_cipher_ctx, 0);
516 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
517     ptd->hmac_ctx = HMAC_CTX_new ();
518     ptd->hash_ctx = EVP_MD_CTX_create ();
519 #else
520     HMAC_CTX_init (&(ptd->_hmac_ctx));
521     ptd->hmac_ctx = &ptd->_hmac_ctx;
522 #endif
523   }
524
525   return 0;
526 }
527
528 /* *INDENT-OFF* */
529 VLIB_INIT_FUNCTION (crypto_openssl_init) =
530 {
531   .runs_after = VLIB_INITS ("vnet_crypto_init"),
532 };
533 /* *INDENT-ON* */
534
535
536 /* *INDENT-OFF* */
537 VLIB_PLUGIN_REGISTER () = {
538   .version = VPP_BUILD_VER,
539   .description = "OpenSSL Crypto Engine",
540 };
541 /* *INDENT-ON* */
542
543 /*
544  * fd.io coding-style-patch-verification: ON
545  *
546  * Local Variables:
547  * eval: (c-set-style "gnu")
548  * End:
549  */