From 3b8518164a51ae984b899c444f54637b490dc2e5 Mon Sep 17 00:00:00 2001 From: Simon Zhang Date: Mon, 9 Dec 2019 19:58:39 +0800 Subject: [PATCH] tls: Picotls engine symmetric crypto enhancement by vpp crypto framework Type: feature Signed-off-by: Simon Zhang Change-Id: I1d4fe75e5faf3fa2086d11020828345b173ebd03 --- src/plugins/tlspicotls/CMakeLists.txt | 1 + src/plugins/tlspicotls/pico_vpp_crypto.c | 339 +++++++++++++++++++++++++++++++ src/plugins/tlspicotls/pico_vpp_crypto.h | 31 +++ src/plugins/tlspicotls/tls_picotls.c | 3 +- 4 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 src/plugins/tlspicotls/pico_vpp_crypto.c create mode 100644 src/plugins/tlspicotls/pico_vpp_crypto.h diff --git a/src/plugins/tlspicotls/CMakeLists.txt b/src/plugins/tlspicotls/CMakeLists.txt index ba01278acad..74eff8c9845 100644 --- a/src/plugins/tlspicotls/CMakeLists.txt +++ b/src/plugins/tlspicotls/CMakeLists.txt @@ -17,6 +17,7 @@ if (PICOTLS_INCLUDE_DIR AND PICOTLS_LINK_LIBRARIES) add_vpp_plugin(tlspicotls SOURCES tls_picotls.c + pico_vpp_crypto.c certs.c LINK_LIBRARIES ${PICOTLS_LINK_LIBRARIES} diff --git a/src/plugins/tlspicotls/pico_vpp_crypto.c b/src/plugins/tlspicotls/pico_vpp_crypto.c new file mode 100644 index 00000000000..e497e5e8af7 --- /dev/null +++ b/src/plugins/tlspicotls/pico_vpp_crypto.c @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2020 Intel 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 +#include +#include +#include + +#include "pico_vpp_crypto.h" + +typedef void (*ptls_vpp_do_transform_fn) (ptls_cipher_context_t *, void *, + const void *, size_t); + +vnet_crypto_main_t *cm = &crypto_main; + +struct cipher_context_t +{ + ptls_cipher_context_t super; + vnet_crypto_op_t op; + u32 key_index; +}; + +struct vpp_aead_context_t +{ + ptls_aead_context_t super; + vnet_crypto_op_t op; + vnet_crypto_op_chunk_t chunks[2]; + vnet_crypto_alg_t alg; + u32 key_index; + u32 chunk_index; +}; + +static void +ptls_vpp_crypto_cipher_do_init (ptls_cipher_context_t * _ctx, const void *iv) +{ + struct cipher_context_t *ctx = (struct cipher_context_t *) _ctx; + + vnet_crypto_op_id_t id; + if (!strcmp (ctx->super.algo->name, "AES128-CTR")) + { + id = VNET_CRYPTO_OP_AES_128_CTR_ENC; + } + else if (!strcmp (ctx->super.algo->name, "AES256-CTR")) + { + id = VNET_CRYPTO_OP_AES_256_CTR_ENC; + } + else + { + TLS_DBG (1, "%s, Invalid crypto cipher : ", __FUNCTION__, + _ctx->algo->name); + assert (0); + } + + vnet_crypto_op_init (&ctx->op, id); + ctx->op.iv = (u8 *) iv; + ctx->op.key_index = ctx->key_index; +} + +static void +ptls_vpp_crypto_cipher_dispose (ptls_cipher_context_t * _ctx) +{ + /* Do nothing */ +} + +static void +ptls_vpp_crypto_cipher_encrypt (ptls_cipher_context_t * _ctx, void *output, + const void *input, size_t _len) +{ + vlib_main_t *vm = vlib_get_main (); + struct cipher_context_t *ctx = (struct cipher_context_t *) _ctx; + + ctx->op.src = (u8 *) input; + ctx->op.dst = output; + ctx->op.len = _len; + + vnet_crypto_process_ops (vm, &ctx->op, 1); +} + +static int +ptls_vpp_crypto_cipher_setup_crypto (ptls_cipher_context_t * _ctx, int is_enc, + const void *key, + const EVP_CIPHER * cipher, + ptls_vpp_do_transform_fn do_transform) +{ + struct cipher_context_t *ctx = (struct cipher_context_t *) _ctx; + + ctx->super.do_dispose = ptls_vpp_crypto_cipher_dispose; + ctx->super.do_init = ptls_vpp_crypto_cipher_do_init; + ctx->super.do_transform = do_transform; + + vlib_main_t *vm = vlib_get_main (); + vnet_crypto_alg_t algo; + if (!strcmp (ctx->super.algo->name, "AES128-CTR")) + { + algo = VNET_CRYPTO_ALG_AES_128_CTR; + } + else if (!strcmp (ctx->super.algo->name, "AES256-CTR")) + { + algo = VNET_CRYPTO_ALG_AES_256_CTR; + } + else + { + TLS_DBG (1, "%s, Invalid crypto cipher : ", __FUNCTION__, + _ctx->algo->name); + assert (0); + } + + ctx->key_index = vnet_crypto_key_add (vm, algo, + (u8 *) key, _ctx->algo->key_size); + + return 0; +} + +size_t +ptls_vpp_crypto_aead_decrypt (ptls_aead_context_t * _ctx, void *_output, + const void *input, size_t inlen, const void *iv, + const void *aad, size_t aadlen) +{ + vlib_main_t *vm = vlib_get_main (); + struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx; + int tag_size = ctx->super.algo->tag_size; + + ctx->op.dst = _output; + ctx->op.src = (void *) input; + ctx->op.len = inlen - tag_size;; + ctx->op.iv = (void *) iv; + ctx->op.aad = (void *) aad; + ctx->op.aad_len = aadlen; + ctx->op.tag = (void *) input + inlen - tag_size; + ctx->op.tag_len = tag_size; + + vnet_crypto_process_ops (vm, &(ctx->op), 1); + assert (ctx->op.status == VNET_CRYPTO_OP_STATUS_COMPLETED); + + return inlen - tag_size; +} + +static void +ptls_vpp_crypto_aead_encrypt_init (ptls_aead_context_t * _ctx, const void *iv, + const void *aad, size_t aadlen) +{ + struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx; + ctx->op.iv = (void *) iv; + ctx->op.aad = (void *) aad; + ctx->op.aad_len = aadlen; + ctx->op.n_chunks = 2; + ctx->op.chunk_index = 0; + + ctx->op.flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS; +} + +static size_t +ptls_vpp_crypto_aead_encrypt_update (ptls_aead_context_t * _ctx, void *output, + const void *input, size_t inlen) +{ + struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx; + ctx->chunks[ctx->chunk_index].dst = output; + ctx->chunks[ctx->chunk_index].src = (void *) input; + ctx->chunks[ctx->chunk_index].len = inlen; + + ctx->chunk_index = ctx->chunk_index == 0 ? 1 : 0; + + return inlen; +} + +static size_t +ptls_vpp_crypto_aead_encrypt_final (ptls_aead_context_t * _ctx, void *_output) +{ + struct vlib_main_t *vm = vlib_get_main (); + struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx; + + ctx->op.tag = _output; + ctx->op.tag_len = ctx->super.algo->tag_size; + + vnet_crypto_process_chained_ops (vm, &(ctx->op), ctx->chunks, 1); + assert (ctx->op.status == VNET_CRYPTO_OP_STATUS_COMPLETED); + + return ctx->super.algo->tag_size; +} + +static void +ptls_vpp_crypto_aead_dispose_crypto (ptls_aead_context_t * _ctx) +{ + /* Do nothing */ +} + + +static int +ptls_vpp_crypto_aead_setup_crypto (ptls_aead_context_t * _ctx, int is_enc, + const void *key, vnet_crypto_alg_t alg) +{ + struct vlib_main_t *vm = vlib_get_main (); + struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx; + u16 key_len = ctx->super.algo->key_size; + + memset (&(ctx->op), 0, sizeof (vnet_crypto_op_t)); + + if (alg == VNET_CRYPTO_ALG_AES_128_GCM) + { + if (is_enc) + vnet_crypto_op_init (&(ctx->op), VNET_CRYPTO_OP_AES_128_GCM_ENC); + else + vnet_crypto_op_init (&(ctx->op), VNET_CRYPTO_OP_AES_128_GCM_DEC); + } + else if (alg == VNET_CRYPTO_ALG_AES_256_GCM) + { + if (is_enc) + { + vnet_crypto_op_init (&(ctx->op), VNET_CRYPTO_OP_AES_256_GCM_ENC); + } + else + vnet_crypto_op_init (&(ctx->op), VNET_CRYPTO_OP_AES_256_GCM_DEC); + } + else + { + TLS_DBG (1, "%s, invalied aead cipher %s", __FUNCTION__, + _ctx->algo->name); + return -1; + } + + ctx->alg = alg; + + ctx->op.key_index = + vnet_crypto_key_add (vm, ctx->alg, (void *) key, key_len); + ctx->chunk_index = 0; + + ctx->super.do_decrypt = ptls_vpp_crypto_aead_decrypt; + ctx->super.do_encrypt_init = ptls_vpp_crypto_aead_encrypt_init; + ctx->super.do_encrypt_update = ptls_vpp_crypto_aead_encrypt_update; + ctx->super.do_encrypt_final = ptls_vpp_crypto_aead_encrypt_final; + ctx->super.dispose_crypto = ptls_vpp_crypto_aead_dispose_crypto; + + return 0; +} + +static int +ptls_vpp_crypto_aes128ctr_setup_crypto (ptls_cipher_context_t * ctx, + int is_enc, const void *key) +{ + return ptls_vpp_crypto_cipher_setup_crypto (ctx, 1, key, EVP_aes_128_ctr (), + ptls_vpp_crypto_cipher_encrypt); +} + +static int +ptls_vpp_crypto_aes256ctr_setup_crypto (ptls_cipher_context_t * ctx, + int is_enc, const void *key) +{ + return ptls_vpp_crypto_cipher_setup_crypto (ctx, 1, key, EVP_aes_256_ctr (), + ptls_vpp_crypto_cipher_encrypt); +} + +static int +ptls_vpp_crypto_aead_aes128gcm_setup_crypto (ptls_aead_context_t * ctx, + int is_enc, const void *key) +{ + return ptls_vpp_crypto_aead_setup_crypto (ctx, is_enc, key, + VNET_CRYPTO_ALG_AES_128_GCM); +} + +static int +ptls_vpp_crypto_aead_aes256gcm_setup_crypto (ptls_aead_context_t * ctx, + int is_enc, const void *key) +{ + return ptls_vpp_crypto_aead_setup_crypto (ctx, is_enc, key, + VNET_CRYPTO_ALG_AES_256_GCM); +} + +ptls_cipher_algorithm_t ptls_vpp_crypto_aes128ctr = { "AES128-CTR", + PTLS_AES128_KEY_SIZE, + 1, PTLS_AES_IV_SIZE, + sizeof (struct vpp_aead_context_t), + ptls_vpp_crypto_aes128ctr_setup_crypto +}; + +ptls_cipher_algorithm_t ptls_vpp_crypto_aes256ctr = { "AES256-CTR", + PTLS_AES256_KEY_SIZE, + 1 /* block size */ , + PTLS_AES_IV_SIZE, + sizeof (struct vpp_aead_context_t), + ptls_vpp_crypto_aes256ctr_setup_crypto +}; + +ptls_aead_algorithm_t ptls_vpp_crypto_aes128gcm = { "AES128-GCM", + &ptls_vpp_crypto_aes128ctr, + NULL, + PTLS_AES128_KEY_SIZE, + PTLS_AESGCM_IV_SIZE, + PTLS_AESGCM_TAG_SIZE, + sizeof (struct vpp_aead_context_t), + ptls_vpp_crypto_aead_aes128gcm_setup_crypto +}; + +ptls_aead_algorithm_t ptls_vpp_crypto_aes256gcm = { "AES256-GCM", + &ptls_vpp_crypto_aes256ctr, + NULL, + PTLS_AES256_KEY_SIZE, + PTLS_AESGCM_IV_SIZE, + PTLS_AESGCM_TAG_SIZE, + sizeof (struct vpp_aead_context_t), + ptls_vpp_crypto_aead_aes256gcm_setup_crypto +}; + +ptls_cipher_suite_t ptls_vpp_crypto_aes128gcmsha256 = + { PTLS_CIPHER_SUITE_AES_128_GCM_SHA256, + &ptls_vpp_crypto_aes128gcm, + &ptls_openssl_sha256 +}; + +ptls_cipher_suite_t ptls_vpp_crypto_aes256gcmsha384 = + { PTLS_CIPHER_SUITE_AES_256_GCM_SHA384, + &ptls_vpp_crypto_aes256gcm, + &ptls_openssl_sha384 +}; + +ptls_cipher_suite_t *ptls_vpp_crypto_cipher_suites[] = + { &ptls_vpp_crypto_aes256gcmsha384, + &ptls_vpp_crypto_aes128gcmsha256, + NULL +}; + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/tlspicotls/pico_vpp_crypto.h b/src/plugins/tlspicotls/pico_vpp_crypto.h new file mode 100644 index 00000000000..0ea3b339f49 --- /dev/null +++ b/src/plugins/tlspicotls/pico_vpp_crypto.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2020 Intel 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. + */ + +#ifndef __included_pico_vpp_crypto_h__ +#define __included_pico_vpp_crypto_h__ + +#include + +extern ptls_cipher_suite_t *ptls_vpp_crypto_cipher_suites[]; + +#endif /* __included_pico_vpp_crypto_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/plugins/tlspicotls/tls_picotls.c b/src/plugins/tlspicotls/tls_picotls.c index 054f01a721d..09927630291 100644 --- a/src/plugins/tlspicotls/tls_picotls.c +++ b/src/plugins/tlspicotls/tls_picotls.c @@ -2,6 +2,7 @@ #include "certs.h" #include "tls_picotls.h" +#include "pico_vpp_crypto.h" picotls_main_t picotls_main; @@ -151,7 +152,7 @@ picotls_start_listen (tls_ctx_t * lctx) /* setup protocol related functions */ ptls_ctx->key_exchanges = key_exchange; ptls_ctx->random_bytes = ptls_openssl_random_bytes; - ptls_ctx->cipher_suites = ptls_openssl_cipher_suites; + ptls_ctx->cipher_suites = ptls_vpp_crypto_cipher_suites; ptls_ctx->get_time = &ptls_get_time; lctx->tls_ssl_ctx = ptls_lctx_idx; -- 2.16.6