LCOV - code coverage report
Current view: top level - plugins/crypto_native - aes_cbc.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 95 117 81.2 %
Date: 2023-07-05 22:20:52 Functions: 12 15 80.0 %

          Line data    Source code
       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 <vppinfra/crypto/aes_cbc.h>
      23             : 
      24             : #if __GNUC__ > 4  && !__clang__ && CLIB_DEBUG == 0
      25             : #pragma GCC optimize ("O3")
      26             : #endif
      27             : 
      28             : #if defined(__VAES__) && defined(__AVX512F__)
      29             : #define N                 16
      30             : #define u8xN              u8x64
      31             : #define u32xN             u32x16
      32             : #define u32xN_min_scalar  u32x16_min_scalar
      33             : #define u32xN_is_all_zero u32x16_is_all_zero
      34             : #define u32xN_splat       u32x16_splat
      35             : #elif defined(__VAES__)
      36             : #define N                 8
      37             : #define u8xN              u8x32
      38             : #define u32xN             u32x8
      39             : #define u32xN_min_scalar  u32x8_min_scalar
      40             : #define u32xN_is_all_zero u32x8_is_all_zero
      41             : #define u32xN_splat       u32x8_splat
      42             : #else
      43             : #define N                 4
      44             : #define u8xN              u8x16
      45             : #define u32xN             u32x4
      46             : #define u32xN_min_scalar  u32x4_min_scalar
      47             : #define u32xN_is_all_zero u32x4_is_all_zero
      48             : #define u32xN_splat       u32x4_splat
      49             : #endif
      50             : 
      51             : static_always_inline u32
      52         917 : aes_ops_enc_aes_cbc (vlib_main_t * vm, vnet_crypto_op_t * ops[],
      53             :                      u32 n_ops, aes_key_size_t ks)
      54             : {
      55         917 :   crypto_native_main_t *cm = &crypto_native_main;
      56         917 :   int rounds = AES_KEY_ROUNDS (ks);
      57             :   u8 placeholder[8192];
      58         917 :   u32 i, j, count, n_left = n_ops;
      59         917 :   u32xN placeholder_mask = { };
      60         917 :   u32xN len = { };
      61             :   vnet_crypto_key_index_t key_index[N];
      62         917 :   u8 *src[N] = { };
      63         917 :   u8 *dst[N] = { };
      64         917 :   u8xN r[4] = {};
      65         917 :   u8xN k[15][4] = {};
      66             : 
      67        4585 :   for (i = 0; i < N; i++)
      68        3668 :     key_index[i] = ~0;
      69             : 
      70         917 : more:
      71       51305 :   for (i = 0; i < N; i++)
      72       41044 :     if (len[i] == 0)
      73             :       {
      74       41036 :         if (n_left == 0)
      75             :           {
      76             :             /* no more work to enqueue, so we are enqueueing placeholder buffer */
      77        1479 :             src[i] = dst[i] = placeholder;
      78        1479 :             len[i] = sizeof (placeholder);
      79        1479 :             placeholder_mask[i] = 0;
      80             :           }
      81             :         else
      82             :           {
      83       39557 :             u8x16 t = aes_block_load (ops[0]->iv);
      84       39557 :             ((u8x16 *) r)[i] = t;
      85             : 
      86       39557 :             src[i] = ops[0]->src;
      87       39557 :             dst[i] = ops[0]->dst;
      88       39557 :             len[i] = ops[0]->len;
      89       39557 :             placeholder_mask[i] = ~0;
      90       39557 :             if (key_index[i] != ops[0]->key_index)
      91             :               {
      92             :                 aes_cbc_key_data_t *kd;
      93        2729 :                 key_index[i] = ops[0]->key_index;
      94        2729 :                 kd = (aes_cbc_key_data_t *) cm->key_data[key_index[i]];
      95       36966 :                 for (j = 0; j < rounds + 1; j++)
      96       34237 :                   ((u8x16 *) k[j])[i] = kd->encrypt_key[j];
      97             :               }
      98       39557 :             ops[0]->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
      99       39557 :             n_left--;
     100       39557 :             ops++;
     101             :           }
     102             :       }
     103             : 
     104       10261 :   count = u32xN_min_scalar (len);
     105             : 
     106       10262 :   ASSERT (count % 16 == 0);
     107             : 
     108      125780 :   for (i = 0; i < count; i += 16)
     109             :     {
     110             : #if defined(__VAES__) && defined(__AVX512F__)
     111           0 :       r[0] = u8x64_xor3 (r[0], aes_block_load_x4 (src, i), k[0][0]);
     112           0 :       r[1] = u8x64_xor3 (r[1], aes_block_load_x4 (src + 4, i), k[0][1]);
     113           0 :       r[2] = u8x64_xor3 (r[2], aes_block_load_x4 (src + 8, i), k[0][2]);
     114           0 :       r[3] = u8x64_xor3 (r[3], aes_block_load_x4 (src + 12, i), k[0][3]);
     115             : 
     116           0 :       for (j = 1; j < rounds; j++)
     117             :         {
     118           0 :           r[0] = aes_enc_round_x4 (r[0], k[j][0]);
     119           0 :           r[1] = aes_enc_round_x4 (r[1], k[j][1]);
     120           0 :           r[2] = aes_enc_round_x4 (r[2], k[j][2]);
     121           0 :           r[3] = aes_enc_round_x4 (r[3], k[j][3]);
     122             :         }
     123           0 :       r[0] = aes_enc_last_round_x4 (r[0], k[j][0]);
     124           0 :       r[1] = aes_enc_last_round_x4 (r[1], k[j][1]);
     125           0 :       r[2] = aes_enc_last_round_x4 (r[2], k[j][2]);
     126           0 :       r[3] = aes_enc_last_round_x4 (r[3], k[j][3]);
     127             : 
     128           0 :       aes_block_store_x4 (dst, i, r[0]);
     129           0 :       aes_block_store_x4 (dst + 4, i, r[1]);
     130           0 :       aes_block_store_x4 (dst + 8, i, r[2]);
     131           0 :       aes_block_store_x4 (dst + 12, i, r[3]);
     132             : #elif defined(__VAES__)
     133             :       r[0] = u8x32_xor3 (r[0], aes_block_load_x2 (src, i), k[0][0]);
     134             :       r[1] = u8x32_xor3 (r[1], aes_block_load_x2 (src + 2, i), k[0][1]);
     135             :       r[2] = u8x32_xor3 (r[2], aes_block_load_x2 (src + 4, i), k[0][2]);
     136             :       r[3] = u8x32_xor3 (r[3], aes_block_load_x2 (src + 6, i), k[0][3]);
     137             : 
     138             :       for (j = 1; j < rounds; j++)
     139             :         {
     140             :           r[0] = aes_enc_round_x2 (r[0], k[j][0]);
     141             :           r[1] = aes_enc_round_x2 (r[1], k[j][1]);
     142             :           r[2] = aes_enc_round_x2 (r[2], k[j][2]);
     143             :           r[3] = aes_enc_round_x2 (r[3], k[j][3]);
     144             :         }
     145             :       r[0] = aes_enc_last_round_x2 (r[0], k[j][0]);
     146             :       r[1] = aes_enc_last_round_x2 (r[1], k[j][1]);
     147             :       r[2] = aes_enc_last_round_x2 (r[2], k[j][2]);
     148             :       r[3] = aes_enc_last_round_x2 (r[3], k[j][3]);
     149             : 
     150             :       aes_block_store_x2 (dst, i, r[0]);
     151             :       aes_block_store_x2 (dst + 2, i, r[1]);
     152             :       aes_block_store_x2 (dst + 4, i, r[2]);
     153             :       aes_block_store_x2 (dst + 6, i, r[3]);
     154             : #else
     155             : #if __x86_64__
     156      115519 :       r[0] = u8x16_xor3 (r[0], aes_block_load (src[0] + i), k[0][0]);
     157      115642 :       r[1] = u8x16_xor3 (r[1], aes_block_load (src[1] + i), k[0][1]);
     158      115858 :       r[2] = u8x16_xor3 (r[2], aes_block_load (src[2] + i), k[0][2]);
     159      116068 :       r[3] = u8x16_xor3 (r[3], aes_block_load (src[3] + i), k[0][3]);
     160             : 
     161     1283570 :       for (j = 1; j < rounds; j++)
     162             :         {
     163     1167880 :           r[0] = aes_enc_round (r[0], k[j][0]);
     164     1167630 :           r[1] = aes_enc_round (r[1], k[j][1]);
     165     1166650 :           r[2] = aes_enc_round (r[2], k[j][2]);
     166     1165990 :           r[3] = aes_enc_round (r[3], k[j][3]);
     167             :         }
     168             : 
     169      115699 :       r[0] = aes_enc_last_round (r[0], k[j][0]);
     170      115697 :       r[1] = aes_enc_last_round (r[1], k[j][1]);
     171      115689 :       r[2] = aes_enc_last_round (r[2], k[j][2]);
     172      115680 :       r[3] = aes_enc_last_round (r[3], k[j][3]);
     173             : 
     174      115665 :       aes_block_store (dst[0] + i, r[0]);
     175      115657 :       aes_block_store (dst[1] + i, r[1]);
     176      115467 :       aes_block_store (dst[2] + i, r[2]);
     177      115481 :       aes_block_store (dst[3] + i, r[3]);
     178             : #else
     179             :       r[0] ^= aes_block_load (src[0] + i);
     180             :       r[1] ^= aes_block_load (src[1] + i);
     181             :       r[2] ^= aes_block_load (src[2] + i);
     182             :       r[3] ^= aes_block_load (src[3] + i);
     183             :       for (j = 0; j < rounds - 1; j++)
     184             :         {
     185             :           r[0] = vaesmcq_u8 (vaeseq_u8 (r[0], k[j][0]));
     186             :           r[1] = vaesmcq_u8 (vaeseq_u8 (r[1], k[j][1]));
     187             :           r[2] = vaesmcq_u8 (vaeseq_u8 (r[2], k[j][2]));
     188             :           r[3] = vaesmcq_u8 (vaeseq_u8 (r[3], k[j][3]));
     189             :         }
     190             :       r[0] = vaeseq_u8 (r[0], k[j][0]) ^ k[rounds][0];
     191             :       r[1] = vaeseq_u8 (r[1], k[j][1]) ^ k[rounds][1];
     192             :       r[2] = vaeseq_u8 (r[2], k[j][2]) ^ k[rounds][2];
     193             :       r[3] = vaeseq_u8 (r[3], k[j][3]) ^ k[rounds][3];
     194             :       aes_block_store (dst[0] + i, r[0]);
     195             :       aes_block_store (dst[1] + i, r[1]);
     196             :       aes_block_store (dst[2] + i, r[2]);
     197             :       aes_block_store (dst[3] + i, r[3]);
     198             : #endif
     199             : #endif
     200             :     }
     201             : 
     202       10261 :   len -= u32xN_splat (count);
     203             : 
     204       51305 :   for (i = 0; i < N; i++)
     205             :     {
     206       41044 :       src[i] += count;
     207       41044 :       dst[i] += count;
     208             :     }
     209             : 
     210       10261 :   if (n_left > 0)
     211        9341 :     goto more;
     212             : 
     213         920 :   if (!u32xN_is_all_zero (len & placeholder_mask))
     214           3 :     goto more;
     215             : 
     216         917 :   return n_ops;
     217             : }
     218             : 
     219             : 
     220             : static_always_inline u32
     221         908 : aes_ops_dec_aes_cbc (vlib_main_t * vm, vnet_crypto_op_t * ops[],
     222             :                      u32 n_ops, aes_key_size_t ks)
     223             : {
     224         908 :   crypto_native_main_t *cm = &crypto_native_main;
     225         908 :   int rounds = AES_KEY_ROUNDS (ks);
     226         908 :   vnet_crypto_op_t *op = ops[0];
     227         908 :   aes_cbc_key_data_t *kd = (aes_cbc_key_data_t *) cm->key_data[op->key_index];
     228         908 :   u32 n_left = n_ops;
     229             : 
     230         908 :   ASSERT (n_ops >= 1);
     231             : 
     232         908 : decrypt:
     233             : #if defined(__VAES__) && defined(__AVX512F__)
     234           0 :   aes4_cbc_dec (kd->decrypt_key, (u8x64u *) op->src, (u8x64u *) op->dst,
     235           0 :                 (u8x16u *) op->iv, op->len, rounds);
     236             : #elif defined(__VAES__)
     237             :   aes2_cbc_dec (kd->decrypt_key, (u8x32u *) op->src, (u8x32u *) op->dst,
     238             :                 (u8x16u *) op->iv, op->len, rounds);
     239             : #else
     240       35204 :   aes_cbc_dec (kd->decrypt_key, (u8x16u *) op->src, (u8x16u *) op->dst,
     241       35204 :                (u8x16u *) op->iv, op->len, rounds);
     242             : #endif
     243       35204 :   op->status = VNET_CRYPTO_OP_STATUS_COMPLETED;
     244             : 
     245       35204 :   if (--n_left)
     246             :     {
     247       34296 :       op += 1;
     248       34296 :       kd = (aes_cbc_key_data_t *) cm->key_data[op->key_index];
     249       34296 :       goto decrypt;
     250             :     }
     251             : 
     252         908 :   return n_ops;
     253             : }
     254             : 
     255             : #define foreach_aes_cbc_handler_type _(128) _(192) _(256)
     256             : 
     257             : #define _(x) \
     258             : static u32 aes_ops_dec_aes_cbc_##x \
     259             : (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops) \
     260             : { return aes_ops_dec_aes_cbc (vm, ops, n_ops, AES_KEY_##x); } \
     261             : static u32 aes_ops_enc_aes_cbc_##x \
     262             : (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops) \
     263             : { return aes_ops_enc_aes_cbc (vm, ops, n_ops, AES_KEY_##x); } \
     264             : 
     265        1825 : foreach_aes_cbc_handler_type;
     266             : #undef _
     267             : 
     268             : static void *
     269        1460 : aes_cbc_key_exp_128 (vnet_crypto_key_t *key)
     270             : {
     271             :   aes_cbc_key_data_t *kd;
     272        1460 :   kd = clib_mem_alloc_aligned (sizeof (*kd), CLIB_CACHE_LINE_BYTES);
     273        1460 :   clib_aes128_cbc_key_expand (kd, key->data);
     274        1460 :   return kd;
     275             : }
     276             : 
     277             : static void *
     278         586 : aes_cbc_key_exp_192 (vnet_crypto_key_t *key)
     279             : {
     280             :   aes_cbc_key_data_t *kd;
     281         586 :   kd = clib_mem_alloc_aligned (sizeof (*kd), CLIB_CACHE_LINE_BYTES);
     282         586 :   clib_aes192_cbc_key_expand (kd, key->data);
     283         586 :   return kd;
     284             : }
     285             : 
     286             : static void *
     287         642 : aes_cbc_key_exp_256 (vnet_crypto_key_t *key)
     288             : {
     289             :   aes_cbc_key_data_t *kd;
     290         642 :   kd = clib_mem_alloc_aligned (sizeof (*kd), CLIB_CACHE_LINE_BYTES);
     291         642 :   clib_aes256_cbc_key_expand (kd, key->data);
     292         642 :   return kd;
     293             : }
     294             : 
     295             : #include <fcntl.h>
     296             : 
     297             : clib_error_t *
     298             : #if defined(__VAES__) && defined(__AVX512F__)
     299           0 : crypto_native_aes_cbc_init_icl (vlib_main_t *vm)
     300             : #elif defined(__VAES__)
     301             : crypto_native_aes_cbc_init_adl (vlib_main_t *vm)
     302             : #elif __AVX512F__
     303         559 : crypto_native_aes_cbc_init_skx (vlib_main_t * vm)
     304             : #elif __aarch64__
     305             : crypto_native_aes_cbc_init_neon (vlib_main_t * vm)
     306             : #elif __AVX2__
     307           0 : crypto_native_aes_cbc_init_hsw (vlib_main_t * vm)
     308             : #else
     309           0 : crypto_native_aes_cbc_init_slm (vlib_main_t * vm)
     310             : #endif
     311             : {
     312         559 :   crypto_native_main_t *cm = &crypto_native_main;
     313             : 
     314             : #define _(x) \
     315             :   vnet_crypto_register_ops_handler (vm, cm->crypto_engine_index, \
     316             :                                     VNET_CRYPTO_OP_AES_##x##_CBC_ENC, \
     317             :                                     aes_ops_enc_aes_cbc_##x); \
     318             :   vnet_crypto_register_ops_handler (vm, cm->crypto_engine_index, \
     319             :                                     VNET_CRYPTO_OP_AES_##x##_CBC_DEC, \
     320             :                                     aes_ops_dec_aes_cbc_##x); \
     321             :   cm->key_fn[VNET_CRYPTO_ALG_AES_##x##_CBC] = aes_cbc_key_exp_##x;
     322         559 :   foreach_aes_cbc_handler_type;
     323             : #undef _
     324             : 
     325         559 :   return 0;
     326             : }
     327             : 
     328             : /*
     329             :  * fd.io coding-style-patch-verification: ON
     330             :  *
     331             :  * Local Variables:
     332             :  * eval: (c-set-style "gnu")
     333             :  * End:
     334             :  */

Generated by: LCOV version 1.14