crypto: enforce per-alg crypto key length 40/19240/2
authorBenoît Ganne <bganne@cisco.com>
Mon, 29 Apr 2019 14:05:46 +0000 (16:05 +0200)
committerDamjan Marion <dmarion@me.com>
Tue, 30 Apr 2019 15:33:53 +0000 (15:33 +0000)
Crypto algorithms have different requirements on key length. As we do
not support key stretching (eg. PBKDF2), user must provide the exact
key length used by the algorithm.
Failing that means low-level crypto functions might read garbage (eg.
aes128_key_expand() will read 16-bytes, regardless of the key provided
by the user).

Change-Id: I347a1ea7a59720a1ed07ceaad8b00a31f78458c9
Signed-off-by: Benoît Ganne <bganne@cisco.com>
src/scripts/vnet/ipsec
src/vnet/crypto/crypto.c
src/vnet/crypto/crypto.h
src/vnet/ipsec/ipsec_sa.c

index 6762a17..bf3cbbc 100644 (file)
@@ -18,12 +18,12 @@ set int state pg0 up
 set int state pg1 up
 set int state pipe0 up
 
-create ipsec tunnel local-ip 10.0.0.1 remote-ip 10.0.0.2 local-spi 100 remote-spi 101 local-crypto-key A11E51E5B1E0 remote-crypto-key A11E51E5B1E0 crypto-alg aes-cbc-128
+create ipsec tunnel local-ip 10.0.0.1 remote-ip 10.0.0.2 local-spi 100 remote-spi 101 local-crypto-key 6541686776336961656264656f6f6579 remote-crypto-key 6541686776336961656264656f6f6579 crypto-alg aes-cbc-128
 
 set int state ipsec0 up
 set int unnum ipsec0 use pg0
 
-create ipsec tunnel local-ip 10.0.0.2 remote-ip 10.0.0.1 local-spi 101 remote-spi 100 tx-table 1 local-crypto-key A11E51E5B1E0 remote-crypto-key A11E51E5B1E0 crypto-alg aes-cbc-128 
+create ipsec tunnel local-ip 10.0.0.2 remote-ip 10.0.0.1 local-spi 101 remote-spi 100 tx-table 1 local-crypto-key 6541686776336961656264656f6f6579 remote-crypto-key 6541686776336961656264656f6f6579 crypto-alg aes-cbc-128
 
 set int state ipsec1 up
 set int ip table ipsec1 1
index b748e47..eecbd5f 100644 (file)
@@ -167,6 +167,33 @@ vnet_crypto_register_key_handler (vlib_main_t * vm, u32 engine_index,
   return;
 }
 
+static int
+vnet_crypto_key_len_check (vnet_crypto_alg_t alg, u16 length)
+{
+  switch (alg)
+    {
+    case VNET_CRYPTO_N_ALGS:
+      return 0;
+    case VNET_CRYPTO_ALG_NONE:
+      return 1;
+
+#define _(n, s, l) \
+      case VNET_CRYPTO_ALG_##n: \
+        if ((l) == length) \
+          return 1;
+      foreach_crypto_cipher_alg foreach_crypto_aead_alg
+#undef _
+       /* HMAC allows any key length */
+#define _(n, s) \
+      case VNET_CRYPTO_ALG_HMAC_##n: \
+        return 1;
+        foreach_crypto_hmac_alg
+#undef _
+    }
+
+  return 0;
+}
+
 u32
 vnet_crypto_key_add (vlib_main_t * vm, vnet_crypto_alg_t alg, u8 * data,
                     u16 length)
@@ -175,6 +202,11 @@ vnet_crypto_key_add (vlib_main_t * vm, vnet_crypto_alg_t alg, u8 * data,
   vnet_crypto_main_t *cm = &crypto_main;
   vnet_crypto_engine_t *engine;
   vnet_crypto_key_t *key;
+
+  ASSERT (vnet_crypto_key_len_check (alg, length));
+  if (!vnet_crypto_key_len_check (alg, length))
+    return ~0;
+
   pool_get_zero (cm->keys, key);
   index = key - cm->keys;
   key->alg = alg;
@@ -279,13 +311,13 @@ vnet_crypto_init (vlib_main_t * vm)
   cm->alg_index_by_name = hash_create_string (0, sizeof (uword));
   vec_validate_aligned (cm->threads, tm->n_vlib_mains, CLIB_CACHE_LINE_BYTES);
   vec_validate (cm->algs, VNET_CRYPTO_N_ALGS);
-#define _(n, s) \
+#define _(n, s, l) \
   vnet_crypto_init_cipher_data (VNET_CRYPTO_ALG_##n, \
                                VNET_CRYPTO_OP_##n##_ENC, \
                                VNET_CRYPTO_OP_##n##_DEC, s, 0);
   foreach_crypto_cipher_alg;
 #undef _
-#define _(n, s) \
+#define _(n, s, l) \
   vnet_crypto_init_cipher_data (VNET_CRYPTO_ALG_##n, \
                                VNET_CRYPTO_OP_##n##_ENC, \
                                VNET_CRYPTO_OP_##n##_DEC, s, 1);
index 95bc72b..5af0822 100644 (file)
 
 #include <vlib/vlib.h>
 
+/* CRYPTO_ID, PRETTY_NAME, KEY_LENGTH_IN_BYTES */
 #define foreach_crypto_cipher_alg \
-  _(DES_CBC,     "des-cbc") \
-  _(3DES_CBC,    "3des-cbc") \
-  _(AES_128_CBC, "aes-128-cbc") \
-  _(AES_192_CBC, "aes-192-cbc") \
-  _(AES_256_CBC, "aes-256-cbc") \
-  _(AES_128_CTR, "aes-128-ctr") \
-  _(AES_192_CTR, "aes-192-ctr") \
-  _(AES_256_CTR, "aes-256-ctr")
-
+  _(DES_CBC,     "des-cbc", 7) \
+  _(3DES_CBC,    "3des-cbc", 14) \
+  _(AES_128_CBC, "aes-128-cbc", 16) \
+  _(AES_192_CBC, "aes-192-cbc", 24) \
+  _(AES_256_CBC, "aes-256-cbc", 32) \
+  _(AES_128_CTR, "aes-128-ctr", 16) \
+  _(AES_192_CTR, "aes-192-ctr", 24) \
+  _(AES_256_CTR, "aes-256-ctr", 32)
+
+/* CRYPTO_ID, PRETTY_NAME, KEY_LENGTH_IN_BYTES */
 #define foreach_crypto_aead_alg \
-  _(AES_128_GCM, "aes-128-gcm") \
-  _(AES_192_GCM, "aes-192-gcm") \
-  _(AES_256_GCM, "aes-256-gcm")
+  _(AES_128_GCM, "aes-128-gcm", 16) \
+  _(AES_192_GCM, "aes-192-gcm", 24) \
+  _(AES_256_GCM, "aes-256-gcm", 32)
 
 #define foreach_crypto_hmac_alg \
   _(MD5, "md5") \
@@ -85,7 +87,7 @@ typedef enum
 typedef enum
 {
   VNET_CRYPTO_ALG_NONE = 0,
-#define _(n, s) VNET_CRYPTO_ALG_##n,
+#define _(n, s, l) VNET_CRYPTO_ALG_##n,
   foreach_crypto_cipher_alg
   foreach_crypto_aead_alg
 #undef _
@@ -104,7 +106,7 @@ typedef struct
 typedef enum
 {
   VNET_CRYPTO_OP_NONE = 0,
-#define _(n, s) VNET_CRYPTO_OP_##n##_ENC, VNET_CRYPTO_OP_##n##_DEC,
+#define _(n, s, l) VNET_CRYPTO_OP_##n##_ENC, VNET_CRYPTO_OP_##n##_DEC,
   foreach_crypto_cipher_alg
   foreach_crypto_aead_alg
 #undef _
index 324e7a4..46c3b6d 100644 (file)
@@ -170,9 +170,14 @@ ipsec_sa_add (u32 id,
   sa->crypto_key_index = vnet_crypto_key_add (vm,
                                              im->crypto_algs[crypto_alg].alg,
                                              (u8 *) ck->data, ck->len);
+  if (~0 == sa->crypto_key_index)
+    return VNET_API_ERROR_INVALID_VALUE;
+
   sa->integ_key_index = vnet_crypto_key_add (vm,
                                             im->integ_algs[integ_alg].alg,
                                             (u8 *) ik->data, ik->len);
+  if (~0 == sa->integ_key_index)
+    return VNET_API_ERROR_INVALID_VALUE;
 
   err = ipsec_check_support_cb (im, sa);
   if (err)