diff options
Diffstat (limited to 'src/plugins/crypto_openssl/main.c')
-rw-r--r-- | src/plugins/crypto_openssl/main.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/src/plugins/crypto_openssl/main.c b/src/plugins/crypto_openssl/main.c new file mode 100644 index 00000000000..30c9c03f643 --- /dev/null +++ b/src/plugins/crypto_openssl/main.c @@ -0,0 +1,213 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2019 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/rand.h> + +#include <vlib/vlib.h> +#include <vnet/plugin/plugin.h> +#include <vnet/crypto/crypto.h> +#include <vpp/app/version.h> + +typedef struct +{ + CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); + EVP_CIPHER_CTX *evp_cipher_ctx; + HMAC_CTX *hmac_ctx; +#if OPENSSL_VERSION_NUMBER < 0x10100000L + HMAC_CTX _hmac_ctx; +#endif +} openssl_per_thread_data_t; + +static openssl_per_thread_data_t *per_thread_data = 0; + +#define foreach_openssl_evp_op \ + _(DES_CBC, EVP_des_cbc) \ + _(3DES_CBC, EVP_des_ede3_cbc) \ + _(AES_128_CBC, EVP_aes_128_cbc) \ + _(AES_192_CBC, EVP_aes_192_cbc) \ + _(AES_256_CBC, EVP_aes_256_cbc) + +#define foreach_openssl_hmac_op \ + _(SHA1, EVP_sha1) \ + _(SHA224, EVP_sha224) \ + _(SHA256, EVP_sha256) \ + _(SHA384, EVP_sha384) \ + _(SHA512, EVP_sha512) + +static_always_inline u32 +openssl_ops_enc_cbc (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops, + const EVP_CIPHER * cipher) +{ + openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data, + vm->thread_index); + EVP_CIPHER_CTX *ctx = ptd->evp_cipher_ctx; + u32 i; + for (i = 0; i < n_ops; i++) + { + vnet_crypto_op_t *op = ops[i]; + int out_len; + + if (op->flags & VNET_CRYPTO_OP_FLAG_INIT_IV) + RAND_bytes (op->iv, 16); + + EVP_EncryptInit_ex (ctx, cipher, NULL, op->key, op->iv); + EVP_EncryptUpdate (ctx, op->dst, &out_len, op->src, op->len); + EVP_EncryptFinal_ex (ctx, op->dst + out_len, &out_len); + op->status = VNET_CRYPTO_OP_STATUS_COMPLETED; + } + return n_ops; +} + +static_always_inline u32 +openssl_ops_dec_cbc (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops, + const EVP_CIPHER * cipher) +{ + openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data, + vm->thread_index); + EVP_CIPHER_CTX *ctx = ptd->evp_cipher_ctx; + u32 i; + for (i = 0; i < n_ops; i++) + { + vnet_crypto_op_t *op = ops[i]; + int out_len; + + EVP_DecryptInit_ex (ctx, cipher, NULL, op->key, op->iv); + EVP_DecryptUpdate (ctx, op->dst, &out_len, op->src, op->len); + EVP_DecryptFinal_ex (ctx, op->dst + out_len, &out_len); + op->status = VNET_CRYPTO_OP_STATUS_COMPLETED; + } + return n_ops; +} + +static_always_inline u32 +openssl_ops_hmac (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops, + const EVP_MD * md) +{ + openssl_per_thread_data_t *ptd = vec_elt_at_index (per_thread_data, + vm->thread_index); + HMAC_CTX *ctx = ptd->hmac_ctx; + u32 i; + for (i = 0; i < n_ops; i++) + { + vnet_crypto_op_t *op = ops[i]; + unsigned int out_len; + + HMAC_Init_ex (ctx, op->key, op->key_len, md, NULL); + HMAC_Update (ctx, op->src, op->len); + HMAC_Final (ctx, op->dst, &out_len); + op->status = VNET_CRYPTO_OP_STATUS_COMPLETED; + } + return n_ops; +} + +#define _(a, b) \ +static u32 \ +openssl_ops_enc_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops) \ +{ return openssl_ops_enc_cbc (vm, ops, n_ops, b ()); } \ +\ +u32 \ +openssl_ops_dec_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops) \ +{ return openssl_ops_dec_cbc (vm, ops, n_ops, b ()); } + +foreach_openssl_evp_op; +#undef _ + +#define _(a, b) \ +static u32 \ +openssl_ops_hmac_##a (vlib_main_t * vm, vnet_crypto_op_t * ops[], u32 n_ops) \ +{ return openssl_ops_hmac (vm, ops, n_ops, b ()); } \ + +foreach_openssl_hmac_op; +#undef _ + + +clib_error_t * +crypto_openssl_init (vlib_main_t * vm) +{ + vlib_thread_main_t *tm = vlib_get_thread_main (); + openssl_per_thread_data_t *ptd; + u8 *seed_data = 0; + time_t t; + pid_t pid; + + u32 eidx = vnet_crypto_register_engine (vm, "openssl", 50, "OpenSSL"); + clib_error_t *error; + + if ((error = vlib_call_init_function (vm, vnet_crypto_init))) + return error; + +#define _(a, b) \ + vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_ENC, \ + openssl_ops_enc_##a); \ + vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_DEC, \ + openssl_ops_dec_##a); + + foreach_openssl_evp_op; +#undef _ + +#define _(a, b) \ + vnet_crypto_register_ops_handler (vm, eidx, VNET_CRYPTO_OP_##a##_HMAC, \ + openssl_ops_hmac_##a); \ + + foreach_openssl_hmac_op; +#undef _ + + vec_validate_aligned (per_thread_data, tm->n_vlib_mains - 1, + CLIB_CACHE_LINE_BYTES); + + vec_foreach (ptd, per_thread_data) + { + ptd->evp_cipher_ctx = EVP_CIPHER_CTX_new (); +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + ptd->hmac_ctx = HMAC_CTX_new (); +#else + HMAC_CTX_init (&(ptd->_hmac_ctx)); + ptd->hmac_ctx = &ptd->_hmac_ctx; +#endif + } + + t = time (NULL); + pid = getpid (); + vec_add (seed_data, &t, sizeof (t)); + vec_add (seed_data, &pid, sizeof (pid)); + vec_add (seed_data, seed_data, sizeof (seed_data)); + + RAND_seed ((const void *) seed_data, vec_len (seed_data)); + + vec_free (seed_data); + + return 0; +} + +VLIB_INIT_FUNCTION (crypto_openssl_init); + +/* *INDENT-OFF* */ +VLIB_PLUGIN_REGISTER () = { + .version = VPP_BUILD_VER, + .description = "OpenSSL Crypto Engine Plugin", +}; +/* *INDENT-ON* */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ |