summaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
authorBenoît Ganne <bganne@cisco.com>2019-04-29 16:05:46 +0200
committerDamjan Marion <dmarion@me.com>2019-04-30 15:33:53 +0000
commitbe95444fbb31b875c2ab98cd330fdcb36027ced8 (patch)
treecdd489306a290cff918b954be950eca0fb4b61bd /src/vnet
parentd577e1f578182d7f663e0f8519dadc81f21cb7a6 (diff)
crypto: enforce per-alg crypto key length
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>
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/crypto/crypto.c36
-rw-r--r--src/vnet/crypto/crypto.h30
-rw-r--r--src/vnet/ipsec/ipsec_sa.c5
3 files changed, 55 insertions, 16 deletions
diff --git a/src/vnet/crypto/crypto.c b/src/vnet/crypto/crypto.c
index b748e47fd3d..eecbd5f49a4 100644
--- a/src/vnet/crypto/crypto.c
+++ b/src/vnet/crypto/crypto.c
@@ -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);
diff --git a/src/vnet/crypto/crypto.h b/src/vnet/crypto/crypto.h
index 95bc72b2dc0..5af0822812f 100644
--- a/src/vnet/crypto/crypto.h
+++ b/src/vnet/crypto/crypto.h
@@ -20,20 +20,22 @@
#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 _
diff --git a/src/vnet/ipsec/ipsec_sa.c b/src/vnet/ipsec/ipsec_sa.c
index 324e7a4db2f..46c3b6d3821 100644
--- a/src/vnet/ipsec/ipsec_sa.c
+++ b/src/vnet/ipsec/ipsec_sa.c
@@ -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)