From 2f3451992e6fa45be492abf173272cf513fc2842 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Thu, 11 Apr 2019 08:18:34 +0000 Subject: 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 (cherry picked from commit 21ada3bd7e9bc5cca7c2c8399adcbaa044bf8103) --- src/plugins/crypto_ipsecmb/CMakeLists.txt | 6 +++ src/plugins/crypto_ipsecmb/ipsecmb.c | 65 ++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 14 deletions(-) (limited to 'src/plugins/crypto_ipsecmb') diff --git a/src/plugins/crypto_ipsecmb/CMakeLists.txt b/src/plugins/crypto_ipsecmb/CMakeLists.txt index a6bb8dc7dcd..0d08032c07e 100644 --- a/src/plugins/crypto_ipsecmb/CMakeLists.txt +++ b/src/plugins/crypto_ipsecmb/CMakeLists.txt @@ -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") diff --git a/src/plugins/crypto_ipsecmb/ipsecmb.c b/src/plugins/crypto_ipsecmb/ipsecmb.c index 309623ec5e4..8e40e3ec2e9 100644 --- a/src/plugins/crypto_ipsecmb/ipsecmb.c +++ b/src/plugins/crypto_ipsecmb/ipsecmb.c @@ -15,6 +15,8 @@ * limitations under the License. */ +#include + #include #include @@ -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); -- cgit 1.2.3-korg