aeec1ea3186d8515bc9ce5c476c5d1fe2f48dd59
[vpp.git] / src / plugins / crypto_native / aes_cbc.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 <vlib/vlib.h>
19 #include <vnet/plugin/plugin.h>
20 #include <vnet/crypto/crypto.h>
21 #include <crypto_native/crypto_native.h>
22 #include <crypto_native/aes.h>
23
24 #if __GNUC__ > 4  && !__clang__ && CLIB_DEBUG == 0
25 #pragma GCC optimize ("O3")
26 #endif
27
28 typedef struct
29 {
30   u8x16 encrypt_key[15];
31 #if __VAES__
32   __m512i decrypt_key[15];
33 #else
34   u8x16 decrypt_key[15];
35 #endif
36 } aes_cbc_key_data_t;
37
38 #include <crypto_native/aes_cbc_aesni.h>
39 #include <crypto_native/aes_cbc_neon.h>
40
41 static_always_inline void *
42 aesni_cbc_key_exp (vnet_crypto_key_t * key, aes_key_size_t ks)
43 {
44   u8x16 e[15], d[15];
45   aes_cbc_key_data_t *kd;
46   kd = clib_mem_alloc_aligned (sizeof (*kd), CLIB_CACHE_LINE_BYTES);
47   aes_key_expand (e, key->data, ks);
48   aes_key_enc_to_dec (e, d, ks);
49   for (int i = 0; i < AES_KEY_ROUNDS (ks) + 1; i++)
50     {
51 #if __VAES__
52       kd->decrypt_key[i] = _mm512_broadcast_i64x2 ((__m128i) d[i]);
53 #else
54       kd->decrypt_key[i] = d[i];
55 #endif
56       kd->encrypt_key[i] = e[i];
57     }
58   return kd;
59 }
60
61 #define foreach_aesni_cbc_handler_type _(128) _(192) _(256)
62
63 #define _(x) \
64 static u32 aesni_ops_dec_aes_cbc_##x \
65 (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops) \
66 { return aesni_ops_dec_aes_cbc (vm, ops, n_ops, AES_KEY_##x); } \
67 static u32 aesni_ops_enc_aes_cbc_##x \
68 (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops) \
69 { return aesni_ops_enc_aes_cbc (vm, ops, n_ops, AES_KEY_##x); } \
70 static void * aesni_cbc_key_exp_##x (vnet_crypto_key_t *key) \
71 { return aesni_cbc_key_exp (key, AES_KEY_##x); }
72
73 foreach_aesni_cbc_handler_type;
74 #undef _
75
76 #include <fcntl.h>
77
78 clib_error_t *
79 #ifdef __VAES__
80 crypto_native_aes_cbc_init_vaes (vlib_main_t * vm)
81 #elif __AVX512F__
82 crypto_native_aes_cbc_init_avx512 (vlib_main_t * vm)
83 #elif __aarch64__
84 crypto_native_aes_cbc_init_neon (vlib_main_t * vm)
85 #elif __AVX2__
86 crypto_native_aes_cbc_init_avx2 (vlib_main_t * vm)
87 #else
88 crypto_native_aes_cbc_init_sse42 (vlib_main_t * vm)
89 #endif
90 {
91   crypto_native_main_t *cm = &crypto_native_main;
92   crypto_native_per_thread_data_t *ptd;
93   clib_error_t *err = 0;
94   int fd;
95
96   if ((fd = open ("/dev/urandom", O_RDONLY)) < 0)
97     return clib_error_return_unix (0, "failed to open '/dev/urandom'");
98
99   /* *INDENT-OFF* */
100   vec_foreach (ptd, cm->per_thread_data)
101     {
102       for (int i = 0; i < 4; i++)
103         {
104           if (read(fd, ptd->cbc_iv, sizeof (ptd->cbc_iv)) !=
105               sizeof (ptd->cbc_iv))
106             {
107               err = clib_error_return_unix (0, "'/dev/urandom' read failure");
108               goto error;
109             }
110         }
111     }
112   /* *INDENT-ON* */
113
114 #define _(x) \
115   vnet_crypto_register_ops_handler (vm, cm->crypto_engine_index, \
116                                     VNET_CRYPTO_OP_AES_##x##_CBC_ENC, \
117                                     aesni_ops_enc_aes_cbc_##x); \
118   vnet_crypto_register_ops_handler (vm, cm->crypto_engine_index, \
119                                     VNET_CRYPTO_OP_AES_##x##_CBC_DEC, \
120                                     aesni_ops_dec_aes_cbc_##x); \
121   cm->key_fn[VNET_CRYPTO_ALG_AES_##x##_CBC] = aesni_cbc_key_exp_##x;
122   foreach_aesni_cbc_handler_type;
123 #undef _
124
125 error:
126   close (fd);
127   return err;
128 }
129
130 /*
131  * fd.io coding-style-patch-verification: ON
132  *
133  * Local Variables:
134  * eval: (c-set-style "gnu")
135  * End:
136  */