crypto: remove VNET_CRYPTO_OP_FLAG_INIT_IV flag 66/34966/9
authorBenoît Ganne <bganne@cisco.com>
Wed, 19 Jan 2022 09:09:42 +0000 (10:09 +0100)
committerDamjan Marion <dmarion@0xa5.net>
Mon, 6 Mar 2023 17:15:24 +0000 (17:15 +0000)
IV requirements vary wildly with the selected mode of operation. For
example, for AES-CBC the IV must be unpredictable whereas for AES
counter mode (CTR or GCM), it can be predictable but reusing an IV with
the same key material is catastrophic.
Because of that, it is hard to generate IV in a generic way, and it is
better left to the crypto user (eg. IPsec).

Type: improvement

Change-Id: I32689c591d8c6572b8d37c4d24f175ea6132d3ec
Signed-off-by: Benoît Ganne <bganne@cisco.com>
src/plugins/crypto_ipsecmb/ipsecmb.c
src/plugins/crypto_native/aes_cbc.c
src/plugins/crypto_native/crypto_native.h
src/plugins/crypto_native/main.c
src/plugins/crypto_openssl/main.c
src/plugins/crypto_sw_scheduler/main.c
src/plugins/unittest/crypto_test.c
src/vnet/crypto/crypto.h

index 02e1345..4ad4fb2 100644 (file)
@@ -31,7 +31,6 @@
 typedef struct
 {
   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
-  __m128i cbc_iv;
   MB_MGR *mgr;
 #if IMB_VERSION_NUM >= IMB_VERSION(1, 3, 0)
   JOB_AES_HMAC burst_jobs[IMB_MAX_BURST_SIZE];
@@ -306,14 +305,6 @@ ipsecmb_ops_aes_cipher_inline (vlib_main_t *vm, vnet_crypto_op_t *ops[],
 
          job->hash_alg = NULL_HASH;
 
-         if ((direction == ENCRYPT) &&
-             (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV))
-           {
-             const __m128i iv = ptd->cbc_iv;
-             _mm_storeu_si128 ((__m128i *) op->iv, iv);
-             ptd->cbc_iv = _mm_aesenc_si128 (iv, iv);
-           }
-
          job->aes_enc_key_expanded = kd->enc_key_exp;
          job->aes_dec_key_expanded = kd->dec_key_exp;
          job->iv = op->iv;
@@ -353,7 +344,6 @@ ipsecmb_ops_aes_cipher_inline (vlib_main_t *vm, vnet_crypto_op_t *ops[],
       ipsecmb_aes_key_data_t *kd;
       vnet_crypto_op_t *op = ops[i];
       kd = (ipsecmb_aes_key_data_t *) imbm->key_data[op->key_index];
-      __m128i iv;
 
       job = IMB_GET_NEXT_JOB (ptd->mgr);
 
@@ -367,13 +357,6 @@ ipsecmb_ops_aes_cipher_inline (vlib_main_t *vm, vnet_crypto_op_t *ops[],
       job->cipher_direction = direction;
       job->chain_order = (direction == ENCRYPT ? CIPHER_HASH : HASH_CIPHER);
 
-      if ((direction == ENCRYPT) && (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV))
-       {
-         iv = ptd->cbc_iv;
-         _mm_storeu_si128 ((__m128i *) op->iv, iv);
-         ptd->cbc_iv = _mm_aesenc_si128 (iv, iv);
-       }
-
       job->aes_key_len_in_bytes = key_len / 8;
       job->aes_enc_key_expanded = kd->enc_key_exp;
       job->aes_dec_key_expanded = kd->dec_key_exp;
@@ -591,13 +574,11 @@ ipsecmb_ops_chacha_poly (vlib_main_t *vm, vnet_crypto_op_t *ops[], u32 n_ops,
   MB_MGR *m = ptd->mgr;
   u32 i, n_fail = 0, last_key_index = ~0;
   u8 scratch[VLIB_FRAME_SIZE][16];
-  u8 iv_data[16];
   u8 *key = 0;
 
   for (i = 0; i < n_ops; i++)
     {
       vnet_crypto_op_t *op = ops[i];
-      __m128i iv;
 
       job = IMB_GET_NEXT_JOB (m);
       if (last_key_index != op->key_index)
@@ -620,15 +601,6 @@ ipsecmb_ops_chacha_poly (vlib_main_t *vm, vnet_crypto_op_t *ops[], u32 n_ops,
       job->src = op->src;
       job->dst = op->dst;
 
-      if ((dir == IMB_DIR_ENCRYPT) &&
-         (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV))
-       {
-         iv = ptd->cbc_iv;
-         _mm_storeu_si128 ((__m128i *) iv_data, iv);
-         clib_memcpy_fast (op->iv, iv_data, 12);
-         ptd->cbc_iv = _mm_aesenc_si128 (iv, iv);
-       }
-
       job->iv = op->iv;
       job->iv_len_in_bytes = 12;
       job->msg_len_to_cipher_in_bytes = job->msg_len_to_hash_in_bytes =
@@ -678,7 +650,6 @@ ipsecmb_ops_chacha_poly_chained (vlib_main_t *vm, vnet_crypto_op_t *ops[],
     vec_elt_at_index (imbm->per_thread_data, vm->thread_index);
   MB_MGR *m = ptd->mgr;
   u32 i, n_fail = 0, last_key_index = ~0;
-  u8 iv_data[16];
   u8 *key = 0;
 
   if (dir == IMB_DIR_ENCRYPT)
@@ -688,7 +659,6 @@ ipsecmb_ops_chacha_poly_chained (vlib_main_t *vm, vnet_crypto_op_t *ops[],
          vnet_crypto_op_t *op = ops[i];
          struct chacha20_poly1305_context_data ctx;
          vnet_crypto_op_chunk_t *chp;
-         __m128i iv;
          u32 j;
 
          ASSERT (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS);
@@ -701,14 +671,6 @@ ipsecmb_ops_chacha_poly_chained (vlib_main_t *vm, vnet_crypto_op_t *ops[],
              last_key_index = op->key_index;
            }
 
-         if (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
-           {
-             iv = ptd->cbc_iv;
-             _mm_storeu_si128 ((__m128i *) iv_data, iv);
-             clib_memcpy_fast (op->iv, iv_data, 12);
-             ptd->cbc_iv = _mm_aesenc_si128 (iv, iv);
-           }
-
          IMB_CHACHA20_POLY1305_INIT (m, key, &ctx, op->iv, op->aad,
                                      op->aad_len);
 
@@ -790,30 +752,6 @@ ipsec_mb_ops_chacha_poly_dec_chained (vlib_main_t *vm, vnet_crypto_op_t *ops[],
 }
 #endif
 
-clib_error_t *
-crypto_ipsecmb_iv_init (ipsecmb_main_t * imbm)
-{
-  ipsecmb_per_thread_data_t *ptd;
-  clib_error_t *err = 0;
-  int fd;
-
-  if ((fd = open ("/dev/urandom", O_RDONLY)) < 0)
-    return clib_error_return_unix (0, "failed to open '/dev/urandom'");
-
-  vec_foreach (ptd, imbm->per_thread_data)
-  {
-    if (read (fd, &ptd->cbc_iv, sizeof (ptd->cbc_iv)) != sizeof (ptd->cbc_iv))
-      {
-       err = clib_error_return_unix (0, "'/dev/urandom' read failure");
-       close (fd);
-       return (err);
-      }
-  }
-
-  close (fd);
-  return (NULL);
-}
-
 static void
 crypto_ipsecmb_key_handler (vlib_main_t * vm, vnet_crypto_key_op_t kop,
                            vnet_crypto_key_index_t idx)
@@ -900,7 +838,6 @@ crypto_ipsecmb_init (vlib_main_t * vm)
   ipsecmb_alg_data_t *ad;
   ipsecmb_per_thread_data_t *ptd;
   vlib_thread_main_t *tm = vlib_get_thread_main ();
-  clib_error_t *error;
   MB_MGR *m = 0;
   u32 eidx;
   u8 *name;
@@ -938,9 +875,6 @@ crypto_ipsecmb_init (vlib_main_t * vm)
     }
   /* *INDENT-ON* */
 
-  if (clib_cpu_supports_x86_aes () && (error = crypto_ipsecmb_iv_init (imbm)))
-    return (error);
-
 #define _(a, b, c, d, e, f)                                              \
   vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC, \
                                     ipsecmb_ops_hmac_##a);               \
index 20b6fd6..7896c88 100644 (file)
@@ -234,8 +234,6 @@ aes_ops_enc_aes_cbc (vlib_main_t * vm, vnet_crypto_op_t * ops[],
                     u32 n_ops, aes_key_size_t ks)
 {
   crypto_native_main_t *cm = &crypto_native_main;
-  crypto_native_per_thread_data_t *ptd =
-    vec_elt_at_index (cm->per_thread_data, vm->thread_index);
   int rounds = AES_KEY_ROUNDS (ks);
   u8 placeholder[8192];
   u32 i, j, count, n_left = n_ops;
@@ -269,15 +267,7 @@ more:
          }
        else
          {
-           u8x16 t;
-           if (ops[0]->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
-             {
-               t = ptd->cbc_iv[i];
-               *(u8x16u *) ops[0]->iv = t;
-               ptd->cbc_iv[i] = aes_enc_round (t, t);
-             }
-           else
-             t = aes_block_load (ops[0]->iv);
+           u8x16 t = aes_block_load (ops[0]->iv);
 #if __VAES__
            rq[i] = t;
 #else
@@ -486,27 +476,6 @@ crypto_native_aes_cbc_init_slm (vlib_main_t * vm)
 #endif
 {
   crypto_native_main_t *cm = &crypto_native_main;
-  crypto_native_per_thread_data_t *ptd;
-  clib_error_t *err = 0;
-  int fd;
-
-  if ((fd = open ("/dev/urandom", O_RDONLY)) < 0)
-    return clib_error_return_unix (0, "failed to open '/dev/urandom'");
-
-  /* *INDENT-OFF* */
-  vec_foreach (ptd, cm->per_thread_data)
-    {
-      for (int i = 0; i < 4; i++)
-       {
-         if (read(fd, ptd->cbc_iv, sizeof (ptd->cbc_iv)) !=
-             sizeof (ptd->cbc_iv))
-           {
-             err = clib_error_return_unix (0, "'/dev/urandom' read failure");
-             goto error;
-           }
-       }
-    }
-  /* *INDENT-ON* */
 
 #define _(x) \
   vnet_crypto_register_ops_handler (vm, cm->crypto_engine_index, \
@@ -519,9 +488,7 @@ crypto_native_aes_cbc_init_slm (vlib_main_t * vm)
   foreach_aes_cbc_handler_type;
 #undef _
 
-error:
-  close (fd);
-  return err;
+  return 0;
 }
 
 /*
index d5c33da..3bad14e 100644 (file)
 
 typedef void *(crypto_native_key_fn_t) (vnet_crypto_key_t * key);
 
-typedef struct
-{
-  CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
-  u8x16 cbc_iv[16];
-} crypto_native_per_thread_data_t;
-
 typedef struct
 {
   u32 crypto_engine_index;
-  crypto_native_per_thread_data_t *per_thread_data;
   crypto_native_key_fn_t *key_fn[VNET_CRYPTO_N_ALGS];
   void **key_data;
 } crypto_native_main_t;
index 32bbbb1..712c333 100644 (file)
@@ -63,16 +63,12 @@ clib_error_t *
 crypto_native_init (vlib_main_t * vm)
 {
   crypto_native_main_t *cm = &crypto_native_main;
-  vlib_thread_main_t *tm = vlib_get_thread_main ();
   clib_error_t *error = 0;
 
   if (clib_cpu_supports_x86_aes () == 0 &&
       clib_cpu_supports_aarch64_aes () == 0)
     return 0;
 
-  vec_validate_aligned (cm->per_thread_data, tm->n_vlib_mains - 1,
-                       CLIB_CACHE_LINE_BYTES);
-
   cm->crypto_engine_index =
     vnet_crypto_register_engine (vm, "native", 100,
                                 "Native ISA Optimized Crypto");
@@ -96,7 +92,7 @@ crypto_native_init (vlib_main_t * vm)
     error = clib_error_return (0, "No AES CBC implemenation available");
 
   if (error)
-    goto error;
+    return error;
 
 #if __x86_64__
   if (clib_cpu_supports_pclmulqdq ())
@@ -113,7 +109,7 @@ crypto_native_init (vlib_main_t * vm)
        error = clib_error_return (0, "No AES GCM implemenation available");
 
       if (error)
-       goto error;
+       return error;
     }
 #endif
 #if __aarch64__
@@ -123,18 +119,12 @@ crypto_native_init (vlib_main_t * vm)
     error = clib_error_return (0, "No AES GCM implemenation available");
 
   if (error)
-    goto error;
+    return error;
 #endif
 
   vnet_crypto_register_key_handler (vm, cm->crypto_engine_index,
                                    crypto_native_key_handler);
-
-
-error:
-  if (error)
-    vec_free (cm->per_thread_data);
-
-  return error;
+  return 0;
 }
 
 /* *INDENT-OFF* */
index 251e75d..50b40c4 100644 (file)
@@ -104,9 +104,6 @@ openssl_ops_enc_cbc (vlib_main_t *vm, vnet_crypto_op_t *ops[],
       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
       int out_len = 0;
 
-      if (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
-       RAND_bytes (op->iv, iv_len);
-
       EVP_EncryptInit_ex (ctx, cipher, NULL, key->data, op->iv);
 
       if (op->flags & VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS)
@@ -215,9 +212,6 @@ openssl_ops_enc_aead (vlib_main_t *vm, vnet_crypto_op_t *ops[],
       vnet_crypto_key_t *key = vnet_crypto_get_key (op->key_index);
       int len = 0;
 
-      if (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV)
-       RAND_bytes (op->iv, 8);
-
       EVP_EncryptInit_ex (ctx, cipher, 0, 0, 0);
       if (is_gcm)
        EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, 12, NULL);
index 991ef6a..563e359 100644 (file)
@@ -244,7 +244,7 @@ crypto_sw_scheduler_convert_link_crypto (vlib_main_t * vm,
   integ_op->digest = fe->digest;
   integ_op->digest_len = digest_len;
   integ_op->key_index = key->index_integ;
-  integ_op->flags = fe->flags & ~VNET_CRYPTO_OP_FLAG_INIT_IV;
+  integ_op->flags = fe->flags;
   crypto_op->user_data = integ_op->user_data = index;
 }
 
index e0da2d7..fc3b91b 100644 (file)
@@ -925,7 +925,6 @@ test_crypto_perf (vlib_main_t * vm, crypto_test_main_t * tm)
                               ad->op_by_type[VNET_CRYPTO_OP_TYPE_ENCRYPT]);
          vnet_crypto_op_init (op2,
                               ad->op_by_type[VNET_CRYPTO_OP_TYPE_DECRYPT]);
-         op1->flags = VNET_CRYPTO_OP_FLAG_INIT_IV;
          op1->src = op2->src = op1->dst = op2->dst = b->data;
          op1->key_index = op2->key_index = key_index;
          op1->iv = op2->iv = b->data - 64;
index 8f12a72..0bb5e36 100644 (file)
@@ -260,9 +260,8 @@ typedef struct
   vnet_crypto_op_id_t op:16;
   vnet_crypto_op_status_t status:8;
   u8 flags;
-#define VNET_CRYPTO_OP_FLAG_INIT_IV (1 << 0)
-#define VNET_CRYPTO_OP_FLAG_HMAC_CHECK (1 << 1)
-#define VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS (1 << 2)
+#define VNET_CRYPTO_OP_FLAG_HMAC_CHECK     (1 << 0)
+#define VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS (1 << 1)
 
   union
   {