IPSEC-MB: Use random & non-repeating IV (VPP-1642)
hard code IV and key lengths based on cipher. Init IV from random data, use AES instruction to rotate. Change-Id: I13a6507d12267b823c528660a903787baeba47a0 Signed-off-by: Neale Ranns <nranns@cisco.com>
This commit is contained in:

committed by
Damjan Marion

parent
5e282e93ad
commit
21ada3bd7e
@ -12,6 +12,10 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
if(NOT CMAKE_SYSTEM_PROCESSOR MATCHES "amd64.*|x86_64.*|AMD64.*")
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_path(IPSECMB_INCLUDE_DIR NAMES intel-ipsec-mb.h HINTS ${IPSECMB_INCLUDE_DIR_HINT})
|
||||
find_library(IPSECMB_LIB NAMES libIPSec_MB.a HINTS ${IPSECMB_LIB_DIR_HINT})
|
||||
|
||||
@ -33,3 +37,5 @@ if(IPSECMB_INCLUDE_DIR AND IPSECMB_LIB)
|
||||
else()
|
||||
message(STATUS "Intel IPSecMB not found")
|
||||
endif()
|
||||
|
||||
target_compile_options(crypto_ipsecmb_plugin PRIVATE "-march=silvermont")
|
||||
|
@ -15,6 +15,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <intel-ipsec-mb.h>
|
||||
|
||||
#include <vnet/vnet.h>
|
||||
@ -26,6 +28,7 @@
|
||||
typedef struct
|
||||
{
|
||||
MB_MGR *mgr;
|
||||
__m128i cbc_iv;
|
||||
} ipsecmb_per_thread_data_t;
|
||||
|
||||
typedef struct ipsecmb_main_t_
|
||||
@ -42,9 +45,9 @@ static ipsecmb_main_t ipsecmb_main;
|
||||
_(SHA512, SHA_512, sha512)
|
||||
|
||||
#define foreach_ipsecmb_cipher_op \
|
||||
_(AES_128_CBC, 128) \
|
||||
_(AES_192_CBC, 192) \
|
||||
_(AES_256_CBC, 256)
|
||||
_(AES_128_CBC, 128, 16, 16) \
|
||||
_(AES_192_CBC, 192, 24, 16) \
|
||||
_(AES_256_CBC, 256, 32, 16)
|
||||
|
||||
always_inline void
|
||||
hash_expand_keys (const MB_MGR * mgr,
|
||||
@ -200,9 +203,9 @@ ipsecmb_retire_cipher_job (JOB_AES_HMAC * job, u32 * n_fail)
|
||||
|
||||
static_always_inline u32
|
||||
ipsecmb_ops_cipher_inline (vlib_main_t * vm,
|
||||
const ipsecmb_per_thread_data_t * ptd,
|
||||
ipsecmb_per_thread_data_t * ptd,
|
||||
vnet_crypto_op_t * ops[],
|
||||
u32 n_ops,
|
||||
u32 n_ops, u32 key_len, u32 iv_len,
|
||||
keyexp_t fn, JOB_CIPHER_DIRECTION direction)
|
||||
{
|
||||
JOB_AES_HMAC *job;
|
||||
@ -216,6 +219,7 @@ ipsecmb_ops_cipher_inline (vlib_main_t * vm,
|
||||
u8 aes_enc_key_expanded[EXPANDED_KEY_N_BYTES];
|
||||
u8 aes_dec_key_expanded[EXPANDED_KEY_N_BYTES];
|
||||
vnet_crypto_op_t *op = ops[i];
|
||||
__m128i iv;
|
||||
|
||||
fn (op->key, aes_enc_key_expanded, aes_dec_key_expanded);
|
||||
|
||||
@ -231,11 +235,18 @@ ipsecmb_ops_cipher_inline (vlib_main_t * vm,
|
||||
job->cipher_direction = direction;
|
||||
job->chain_order = (direction == ENCRYPT ? CIPHER_HASH : HASH_CIPHER);
|
||||
|
||||
job->aes_key_len_in_bytes = op->key_len;
|
||||
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;
|
||||
job->aes_enc_key_expanded = aes_enc_key_expanded;
|
||||
job->aes_dec_key_expanded = aes_dec_key_expanded;
|
||||
job->iv = op->iv;
|
||||
job->iv_len_in_bytes = op->iv_len;
|
||||
job->iv_len_in_bytes = iv_len;
|
||||
|
||||
job->user_data = op;
|
||||
|
||||
@ -257,7 +268,7 @@ ipsecmb_ops_cipher_inline (vlib_main_t * vm,
|
||||
return n_ops - n_fail;
|
||||
}
|
||||
|
||||
#define _(a, b) \
|
||||
#define _(a, b, c, d) \
|
||||
static_always_inline u32 \
|
||||
ipsecmb_ops_cipher_enc_##a (vlib_main_t * vm, \
|
||||
vnet_crypto_op_t * ops[], \
|
||||
@ -269,14 +280,14 @@ ipsecmb_ops_cipher_enc_##a (vlib_main_t * vm, \
|
||||
imbm = &ipsecmb_main; \
|
||||
ptd = vec_elt_at_index (imbm->per_thread_data, vm->thread_index); \
|
||||
\
|
||||
return ipsecmb_ops_cipher_inline (vm, ptd, ops, n_ops, \
|
||||
return ipsecmb_ops_cipher_inline (vm, ptd, ops, n_ops, c, d, \
|
||||
ptd->mgr->keyexp_##b, \
|
||||
ENCRYPT); \
|
||||
}
|
||||
foreach_ipsecmb_cipher_op;
|
||||
#undef _
|
||||
|
||||
#define _(a, b) \
|
||||
#define _(a, b, c, d) \
|
||||
static_always_inline u32 \
|
||||
ipsecmb_ops_cipher_dec_##a (vlib_main_t * vm, \
|
||||
vnet_crypto_op_t * ops[], \
|
||||
@ -288,13 +299,35 @@ ipsecmb_ops_cipher_dec_##a (vlib_main_t * vm, \
|
||||
imbm = &ipsecmb_main; \
|
||||
ptd = vec_elt_at_index (imbm->per_thread_data, vm->thread_index); \
|
||||
\
|
||||
return ipsecmb_ops_cipher_inline (vm, ptd, ops, n_ops, \
|
||||
return ipsecmb_ops_cipher_inline (vm, ptd, ops, n_ops, c, d, \
|
||||
ptd->mgr->keyexp_##b, \
|
||||
DECRYPT); \
|
||||
}
|
||||
foreach_ipsecmb_cipher_op;
|
||||
#undef _
|
||||
|
||||
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");
|
||||
return (err);
|
||||
}
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
crypto_ipsecmb_init (vlib_main_t * vm)
|
||||
{
|
||||
@ -340,26 +373,30 @@ crypto_ipsecmb_init (vlib_main_t * vm)
|
||||
}
|
||||
}
|
||||
|
||||
if (clib_cpu_supports_x86_aes () && (error = crypto_ipsecmb_iv_init (imbm)))
|
||||
return (error);
|
||||
|
||||
|
||||
#define _(a, b, c) \
|
||||
vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC, \
|
||||
ipsecmb_ops_hmac_##a); \
|
||||
|
||||
foreach_ipsecmb_hmac_op;
|
||||
#undef _
|
||||
#define _(a, b) \
|
||||
#define _(a, b, c, d) \
|
||||
vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_ENC, \
|
||||
ipsecmb_ops_cipher_enc_##a); \
|
||||
|
||||
foreach_ipsecmb_cipher_op;
|
||||
#undef _
|
||||
#define _(a, b) \
|
||||
#define _(a, b, c, d) \
|
||||
vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_DEC, \
|
||||
ipsecmb_ops_cipher_dec_##a); \
|
||||
|
||||
foreach_ipsecmb_cipher_op;
|
||||
#undef _
|
||||
|
||||
return 0;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
VLIB_INIT_FUNCTION (crypto_ipsecmb_init);
|
||||
|
@ -119,9 +119,12 @@ vnet_crypto_set_handler (char *alg_name, char *engine)
|
||||
if (id == 0)
|
||||
continue;
|
||||
od = vec_elt_at_index (cm->opt_data, id);
|
||||
if (ce->ops_handlers[id])
|
||||
{
|
||||
od->active_engine_index = p[0];
|
||||
cm->ops_handlers[id] = ce->ops_handlers[id];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -232,9 +232,7 @@ esp_decrypt_inline (vlib_main_t * vm,
|
||||
vec_add2_aligned (ptd->crypto_ops, op, 1, CLIB_CACHE_LINE_BYTES);
|
||||
vnet_crypto_op_init (op, sa0->crypto_dec_op_id);
|
||||
op->key = sa0->crypto_key.data;
|
||||
op->key_len = sa0->crypto_key.len;
|
||||
op->iv = payload;
|
||||
op->iv_len = cpd.iv_sz;
|
||||
op->src = op->dst = payload += cpd.iv_sz;
|
||||
op->len = len;
|
||||
op->user_data = b - bufs;
|
||||
@ -287,7 +285,7 @@ esp_decrypt_inline (vlib_main_t * vm,
|
||||
bi = op->user_data;
|
||||
|
||||
if (op->status == VNET_CRYPTO_OP_STATUS_FAIL_BAD_HMAC)
|
||||
err = ESP_DECRYPT_ERROR_INTEG_ERROR;
|
||||
err = ESP_DECRYPT_ERROR_DECRYPTION_FAILED;
|
||||
else
|
||||
err = ESP_DECRYPT_ERROR_CRYPTO_ENGINE_ERROR;
|
||||
|
||||
|
@ -431,10 +431,8 @@ esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
|
||||
vec_add2_aligned (ptd->crypto_ops, op, 1, CLIB_CACHE_LINE_BYTES);
|
||||
vnet_crypto_op_init (op, sa0->crypto_enc_op_id);
|
||||
op->iv = payload - iv_sz;
|
||||
op->iv_len = iv_sz;
|
||||
op->src = op->dst = payload;
|
||||
op->key = sa0->crypto_key.data;
|
||||
op->key_len = sa0->crypto_key.len;
|
||||
op->len = payload_len - icv_sz;
|
||||
op->flags = VNET_CRYPTO_OP_FLAG_INIT_IV;
|
||||
op->user_data = b - bufs;
|
||||
|
@ -337,7 +337,7 @@ class TestIpsecAhAll(ConfigIpsecAH,
|
||||
# loop through the VPP engines
|
||||
#
|
||||
for engine in engines:
|
||||
self.vapi.cli("set crypto engine all %s" % engine)
|
||||
self.vapi.cli("set crypto handler all %s" % engine)
|
||||
#
|
||||
# loop through each of the algorithms
|
||||
#
|
||||
|
@ -381,7 +381,7 @@ class TestIpsecEspAll(ConfigIpsecESP,
|
||||
# loop through the VPP engines
|
||||
#
|
||||
for engine in engines:
|
||||
self.vapi.cli("set crypto engine all %s" % engine)
|
||||
self.vapi.cli("set crypto handler all %s" % engine)
|
||||
|
||||
#
|
||||
# loop through each of the algorithms
|
||||
|
Reference in New Issue
Block a user