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>
This commit is contained in:
Benoît Ganne
2019-04-29 16:05:46 +02:00
committed by Damjan Marion
parent d577e1f578
commit be95444fbb
4 changed files with 56 additions and 17 deletions

View 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

View 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);

View File

@@ -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 _

View 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)