diff options
author | Benoît Ganne <bganne@cisco.com> | 2019-04-29 16:05:46 +0200 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2019-04-30 15:33:53 +0000 |
commit | be95444fbb31b875c2ab98cd330fdcb36027ced8 (patch) | |
tree | cdd489306a290cff918b954be950eca0fb4b61bd /src/vnet | |
parent | d577e1f578182d7f663e0f8519dadc81f21cb7a6 (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.c | 36 | ||||
-rw-r--r-- | src/vnet/crypto/crypto.h | 30 | ||||
-rw-r--r-- | src/vnet/ipsec/ipsec_sa.c | 5 |
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) |