diff options
author | Aloys Augustin <aloaugus@cisco.com> | 2021-08-02 17:42:23 +0200 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2021-08-03 17:09:18 +0000 |
commit | 7dbc8ebe54f4ddb83e337be152e9b8405f52e577 (patch) | |
tree | 3f11b93e346f7f4a686ada3448296e69f0d35fdb | |
parent | 8f174ad5b6ab472d7ee4cba61bc5f672bd6a3fbb (diff) |
quic: do not update crypto keys from workers
The vnet_crypto_key_add should only be called from the main thread.
This patch works around this limitation by allocating one key per worker
and updating it on the fly everytime we need to do a crypto operation.
This solution is far from ideal, but quicly has a strong assumption that
it can use a key immediately after determining it, so making the key
creation asynchronous is not a possibility.
Signed-off-by: Aloys Augustin <aloaugus@cisco.com>
Change-Id: I19fc5814195156003c36a73bb616738ba9d828f7
Type: fix
-rw-r--r-- | src/plugins/quic/quic.c | 9 | ||||
-rw-r--r-- | src/plugins/quic/quic.h | 3 | ||||
-rw-r--r-- | src/plugins/quic/quic_crypto.c | 67 |
3 files changed, 59 insertions, 20 deletions
diff --git a/src/plugins/quic/quic.c b/src/plugins/quic/quic.c index 26f2216a3d8..499eb8bc776 100644 --- a/src/plugins/quic/quic.c +++ b/src/plugins/quic/quic.c @@ -2563,14 +2563,19 @@ quic_init (vlib_main_t * vm) qm->vnet_crypto_enabled = 1; if (qm->vnet_crypto_enabled == 1) { + u8 empty_key[32] = {}; quic_register_cipher_suite (CRYPTO_ENGINE_VPP, quic_crypto_cipher_suites); qm->default_crypto_engine = CRYPTO_ENGINE_VPP; + vec_validate (qm->per_thread_crypto_key_indices, num_threads); + for (i = 0; i < num_threads; i++) + { + qm->per_thread_crypto_key_indices[i] = vnet_crypto_key_add ( + vm, VNET_CRYPTO_ALG_AES_256_CTR, empty_key, 32); + } } qm->max_packets_per_key = DEFAULT_MAX_PACKETS_PER_KEY; - clib_rwlock_init (&qm->crypto_keys_quic_rw_lock); - qm->default_quic_cc = QUIC_CC_RENO; vec_free (a->name); diff --git a/src/plugins/quic/quic.h b/src/plugins/quic/quic.h index 901bdbc39b2..2c5a21c01a4 100644 --- a/src/plugins/quic/quic.h +++ b/src/plugins/quic/quic.h @@ -263,8 +263,7 @@ typedef struct quic_main_ u32 connection_timeout; u8 vnet_crypto_enabled; - - clib_rwlock_t crypto_keys_quic_rw_lock; + u32 *per_thread_crypto_key_indices; } quic_main_t; #endif /* __included_quic_h__ */ diff --git a/src/plugins/quic/quic_crypto.c b/src/plugins/quic/quic_crypto.c index 602b3f8570c..9931ab56b76 100644 --- a/src/plugins/quic/quic_crypto.c +++ b/src/plugins/quic/quic_crypto.c @@ -15,9 +15,11 @@ #include <quic/quic.h> #include <quic/quic_crypto.h> +#include <vnet/session/session.h> #include <quicly.h> #include <picotls/openssl.h> +#include <pthread.h> #define QUICLY_EPOCH_1RTT 3 @@ -25,12 +27,19 @@ extern quic_main_t quic_main; extern quic_ctx_t *quic_get_conn_ctx (quicly_conn_t * conn); vnet_crypto_main_t *cm = &crypto_main; +typedef struct crypto_key_ +{ + vnet_crypto_alg_t algo; + u8 key[32]; + u16 key_len; +} crypto_key_t; + struct cipher_context_t { ptls_cipher_context_t super; vnet_crypto_op_t op; vnet_crypto_op_id_t id; - u32 key_index; + crypto_key_t key; }; struct aead_crypto_context_t @@ -39,7 +48,8 @@ struct aead_crypto_context_t EVP_CIPHER_CTX *evp_ctx; uint8_t static_iv[PTLS_MAX_IV_SIZE]; vnet_crypto_op_t op; - u32 key_index; + crypto_key_t key; + vnet_crypto_op_id_t id; uint8_t iv[PTLS_MAX_IV_SIZE]; }; @@ -114,6 +124,29 @@ Exit: return ret; } +static u32 +quic_crypto_set_key (crypto_key_t *key) +{ + u8 thread_index = vlib_get_thread_index (); + u32 key_id = quic_main.per_thread_crypto_key_indices[thread_index]; + vnet_crypto_key_t *vnet_key = vnet_crypto_get_key (key_id); + vlib_main_t *vm = vlib_get_main (); + vnet_crypto_engine_t *engine; + + vec_foreach (engine, cm->engines) + if (engine->key_op_handler) + engine->key_op_handler (vm, VNET_CRYPTO_KEY_OP_DEL, key_id); + + vnet_key->alg = key->algo; + clib_memcpy (vnet_key->data, key->key, key->key_len); + + vec_foreach (engine, cm->engines) + if (engine->key_op_handler) + engine->key_op_handler (vm, VNET_CRYPTO_KEY_OP_ADD, key_id); + + return key_id; +} + static size_t quic_crypto_aead_decrypt (quic_ctx_t *qctx, ptls_aead_context_t *_ctx, void *_output, const void *input, size_t inlen, @@ -132,7 +165,7 @@ quic_crypto_aead_decrypt (quic_ctx_t *qctx, ptls_aead_context_t *_ctx, decrypted_pn); ctx->op.src = (u8 *) input; ctx->op.dst = _output; - ctx->op.key_index = ctx->key_index; + ctx->op.key_index = quic_crypto_set_key (&ctx->key); ctx->op.len = inlen - ctx->super.algo->tag_size; ctx->op.tag_len = ctx->super.algo->tag_size; ctx->op.tag = ctx->op.src + ctx->op.len; @@ -260,7 +293,7 @@ quic_crypto_encrypt_packet (struct st_quicly_crypto_engine_t *engine, aead_ctx->op.iv = aead_ctx->iv; ptls_aead__build_iv (aead_ctx->super.algo, aead_ctx->op.iv, aead_ctx->static_iv, packet_number); - aead_ctx->op.key_index = aead_ctx->key_index; + aead_ctx->op.key_index = quic_crypto_set_key (&aead_ctx->key); aead_ctx->op.src = (u8 *) input; aead_ctx->op.dst = output; aead_ctx->op.len = inlen; @@ -280,7 +313,8 @@ quic_crypto_encrypt_packet (struct st_quicly_crypto_engine_t *engine, vnet_crypto_op_init (&hp_ctx->op, hp_ctx->id); memset (supp.output, 0, sizeof (supp.output)); hp_ctx->op.iv = (u8 *) supp.input; - hp_ctx->op.key_index = hp_ctx->key_index; + hp_ctx->op.key_index = quic_crypto_set_key (&hp_ctx->key); + ; hp_ctx->op.src = (u8 *) supp.output; hp_ctx->op.dst = (u8 *) supp.output; hp_ctx->op.len = sizeof (supp.output); @@ -301,7 +335,6 @@ quic_crypto_cipher_setup_crypto (ptls_cipher_context_t *_ctx, int is_enc, { struct cipher_context_t *ctx = (struct cipher_context_t *) _ctx; - vlib_main_t *vm = vlib_get_main (); vnet_crypto_alg_t algo; if (!strcmp (ctx->super.algo->name, "AES128-CTR")) { @@ -326,10 +359,12 @@ quic_crypto_cipher_setup_crypto (ptls_cipher_context_t *_ctx, int is_enc, if (quic_main.vnet_crypto_enabled) { - clib_rwlock_writer_lock (&quic_main.crypto_keys_quic_rw_lock); - ctx->key_index = - vnet_crypto_key_add (vm, algo, (u8 *) key, _ctx->algo->key_size); - clib_rwlock_writer_unlock (&quic_main.crypto_keys_quic_rw_lock); + // ctx->key_index = + // quic_crypto_go_setup_key (algo, key, _ctx->algo->key_size); + ctx->key.algo = algo; + ctx->key.key_len = _ctx->algo->key_size; + assert (ctx->key.key_len <= 32); + clib_memcpy (&ctx->key.key, key, ctx->key.key_len); } return 0; @@ -354,7 +389,6 @@ quic_crypto_aead_setup_crypto (ptls_aead_context_t *_ctx, int is_enc, const void *key, const void *iv, const EVP_CIPHER *cipher) { - vlib_main_t *vm = vlib_get_main (); struct aead_crypto_context_t *ctx = (struct aead_crypto_context_t *) _ctx; vnet_crypto_alg_t algo; @@ -382,11 +416,12 @@ quic_crypto_aead_setup_crypto (ptls_aead_context_t *_ctx, int is_enc, if (quic_main.vnet_crypto_enabled) { clib_memcpy (ctx->static_iv, iv, ctx->super.algo->iv_size); - - clib_rwlock_writer_lock (&quic_main.crypto_keys_quic_rw_lock); - ctx->key_index = vnet_crypto_key_add (vm, algo, - (u8 *) key, _ctx->algo->key_size); - clib_rwlock_writer_unlock (&quic_main.crypto_keys_quic_rw_lock); + // ctx->key_index = + // quic_crypto_go_setup_key (algo, key, _ctx->algo->key_size); + ctx->key.algo = algo; + ctx->key.key_len = _ctx->algo->key_size; + assert (ctx->key.key_len <= 32); + clib_memcpy (&ctx->key.key, key, ctx->key.key_len); } return 0; |