From 7f347c13dfb39aac1d2507068a2b6ae2baa09af4 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Thu, 29 Jul 2021 09:06:00 -0700 Subject: tls: picotls rx fixes and improvements Type: fix Signed-off-by: Florin Coras Change-Id: I9ea41b8b271e9123e676acdc581ef429072fe843 --- src/plugins/tlspicotls/pico_vpp_crypto.c | 89 +++++++-------- src/plugins/tlspicotls/tls_picotls.c | 186 ++++++++++++++----------------- 2 files changed, 126 insertions(+), 149 deletions(-) (limited to 'src/plugins/tlspicotls') diff --git a/src/plugins/tlspicotls/pico_vpp_crypto.c b/src/plugins/tlspicotls/pico_vpp_crypto.c index 9af0f2f4d92..f3514d07b23 100644 --- a/src/plugins/tlspicotls/pico_vpp_crypto.c +++ b/src/plugins/tlspicotls/pico_vpp_crypto.c @@ -31,19 +31,22 @@ struct cipher_context_t { ptls_cipher_context_t super; vnet_crypto_op_t op; + vnet_crypto_op_id_t id; u32 key_index; }; struct vpp_aead_context_t { ptls_aead_context_t super; + EVP_CIPHER_CTX *evp_ctx; + uint8_t static_iv[PTLS_MAX_IV_SIZE]; vnet_crypto_op_t op; + u32 key_index; + vnet_crypto_op_id_t id; vnet_crypto_op_chunk_t chunks[2]; vnet_crypto_alg_t alg; - u32 key_index; u32 chunk_index; uint8_t iv[PTLS_MAX_IV_SIZE]; - uint8_t static_iv[PTLS_MAX_IV_SIZE]; }; static void @@ -51,23 +54,7 @@ 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); + vnet_crypto_op_init (&ctx->op, ctx->id); ctx->op.iv = (u8 *) iv; ctx->op.key_index = ctx->key_index; } @@ -109,10 +96,14 @@ ptls_vpp_crypto_cipher_setup_crypto (ptls_cipher_context_t * _ctx, int is_enc, if (!strcmp (ctx->super.algo->name, "AES128-CTR")) { algo = VNET_CRYPTO_ALG_AES_128_CTR; + ctx->id = is_enc ? VNET_CRYPTO_OP_AES_128_CTR_ENC : + VNET_CRYPTO_OP_AES_128_CTR_DEC; } else if (!strcmp (ctx->super.algo->name, "AES256-CTR")) { algo = VNET_CRYPTO_ALG_AES_256_CTR; + ctx->id = is_enc ? VNET_CRYPTO_OP_AES_256_CTR_ENC : + VNET_CRYPTO_OP_AES_256_CTR_DEC; } else { @@ -138,20 +129,22 @@ ptls_vpp_crypto_aead_decrypt (ptls_aead_context_t *_ctx, void *_output, 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;; + vnet_crypto_op_init (&ctx->op, ctx->id); + ctx->op.aad = (u8 *) aad; + ctx->op.aad_len = aadlen; ctx->op.iv = ctx->iv; ptls_aead__build_iv (ctx->super.algo, ctx->op.iv, ctx->static_iv, seq); - ctx->op.aad = (void *) aad; - ctx->op.aad_len = aadlen; - ctx->op.tag = (void *) input + inlen - tag_size; + ctx->op.src = (u8 *) input; + ctx->op.dst = _output; + ctx->op.key_index = ctx->key_index; + ctx->op.len = inlen - tag_size; ctx->op.tag_len = tag_size; + ctx->op.tag = ctx->op.src + ctx->op.len; vnet_crypto_process_ops (vm, &(ctx->op), 1); assert (ctx->op.status == VNET_CRYPTO_OP_STATUS_COMPLETED); - return inlen - tag_size; + return ctx->op.len; } static void @@ -159,10 +152,13 @@ ptls_vpp_crypto_aead_encrypt_init (ptls_aead_context_t *_ctx, uint64_t seq, const void *aad, size_t aadlen) { struct vpp_aead_context_t *ctx = (struct vpp_aead_context_t *) _ctx; - ctx->op.iv = ctx->iv; - ptls_aead__build_iv (ctx->super.algo, ctx->op.iv, ctx->static_iv, seq); + + vnet_crypto_op_init (&ctx->op, ctx->id); ctx->op.aad = (void *) aad; ctx->op.aad_len = aadlen; + ctx->op.iv = ctx->iv; + ptls_aead__build_iv (ctx->super.algo, ctx->op.iv, ctx->static_iv, seq); + ctx->op.key_index = ctx->key_index; ctx->op.n_chunks = 2; ctx->op.chunk_index = 0; @@ -213,23 +209,15 @@ ptls_vpp_crypto_aead_setup_crypto (ptls_aead_context_t *_ctx, int is_enc, 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); + ctx->id = is_enc ? VNET_CRYPTO_OP_AES_128_GCM_ENC : + 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); + ctx->id = is_enc ? VNET_CRYPTO_OP_AES_256_GCM_ENC : + VNET_CRYPTO_OP_AES_256_GCM_DEC; } else { @@ -239,18 +227,23 @@ ptls_vpp_crypto_aead_setup_crypto (ptls_aead_context_t *_ctx, int is_enc, } ctx->alg = alg; + ctx->chunk_index = 0; + clib_memcpy (ctx->static_iv, iv, ctx->super.algo->iv_size); clib_rwlock_writer_lock (&picotls_main.crypto_keys_rw_lock); - ctx->op.key_index = - vnet_crypto_key_add (vm, ctx->alg, (void *) key, key_len); + ctx->key_index = vnet_crypto_key_add (vm, alg, (void *) key, key_len); clib_rwlock_writer_unlock (&picotls_main.crypto_keys_rw_lock); - ctx->chunk_index = 0; - clib_memcpy (ctx->static_iv, iv, ctx->super.algo->iv_size); - 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; + if (is_enc) + { + 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; + } + else + { + ctx->super.do_decrypt = ptls_vpp_crypto_aead_decrypt; + } ctx->super.dispose_crypto = ptls_vpp_crypto_aead_dispose_crypto; return 0; diff --git a/src/plugins/tlspicotls/tls_picotls.c b/src/plugins/tlspicotls/tls_picotls.c index ef02f66a552..a0fbab0495c 100644 --- a/src/plugins/tlspicotls/tls_picotls.c +++ b/src/plugins/tlspicotls/tls_picotls.c @@ -221,160 +221,145 @@ picotls_app_close (tls_ctx_t * ctx) } static inline int -picotls_do_handshake (picotls_ctx_t * ptls_ctx, session_t * tls_session, - u8 * input, int input_len) +picotls_do_handshake (picotls_ctx_t *ptls_ctx, session_t *tcp_session) { + int rv = PTLS_ERROR_IN_PROGRESS, write = 0, i = 0, read = 0, len; + svm_fifo_t *tcp_rx_fifo = tcp_session->rx_fifo; + ptls_buffer_t *buf = &ptls_ctx->read_buffer; + const int n_segs = 2, max_len = 16384; ptls_t *tls = ptls_ctx->tls; - ptls_buffer_t buf; - int rv = PTLS_ERROR_IN_PROGRESS; - int write = 0, off; + svm_fifo_seg_t fs[n_segs]; + uword deq_now; + + ptls_buffer_init (buf, "", 0); + + len = svm_fifo_segments (tcp_rx_fifo, 0, fs, n_segs, max_len); + if (len <= 0) + return 0; - do + while (read < len && i < n_segs) { - off = 0; - do + deq_now = fs[i].len; + rv = ptls_handshake (tls, buf, fs[i].data, &deq_now, NULL); + + write += picotls_try_handshake_write (ptls_ctx, tcp_session, buf); + read += deq_now; + + if (!(rv == 0 || rv == PTLS_ERROR_IN_PROGRESS)) { - ptls_buffer_init (&buf, "", 0); - size_t consumed = input_len - off; - rv = ptls_handshake (tls, &buf, input + off, &consumed, NULL); - off += consumed; - ptls_ctx->rx_offset += consumed; - if ((rv == 0 || rv == PTLS_ERROR_IN_PROGRESS) && buf.off != 0) - { - write = picotls_try_handshake_write (ptls_ctx, tls_session, - &buf); - } - ptls_buffer_dispose (&buf); + clib_error ("unexpected error %u", rv); + break; } - while (rv == PTLS_ERROR_IN_PROGRESS && input_len != off); + + if (!rv) + break; + + if (deq_now < fs[i].len) + { + fs[i].data += deq_now; + fs[i].len -= deq_now; + } + else + i++; } - while (rv == PTLS_ERROR_IN_PROGRESS); + + if (read) + svm_fifo_dequeue_drop (tcp_rx_fifo, read); + + ptls_buffer_dispose (buf); return write; } static inline int -picotls_ctx_read (tls_ctx_t * ctx, session_t * tls_session) +picotls_ctx_read (tls_ctx_t *ctx, session_t *tcp_session) { picotls_ctx_t *ptls_ctx = (picotls_ctx_t *) ctx; - int from_tls_len = 0, off, crypto_len, ret; - u32 deq_max, deq_now; - u32 enq_max; ptls_buffer_t *buf = &ptls_ctx->read_buffer; - svm_fifo_t *tls_rx_fifo, *app_rx_fifo; + int off = 0, ret, i = 0, read = 0, len; + const int n_segs = 4, max_len = 32768; + svm_fifo_t *tcp_rx_fifo, *app_rx_fifo; + svm_fifo_seg_t fs[n_segs]; session_t *app_session; + uword deq_now; - tls_rx_fifo = tls_session->rx_fifo; - - if (!picotls_handshake_is_over (ctx)) + if (PREDICT_FALSE (!ptls_handshake_is_complete (ptls_ctx->tls))) { - deq_max = svm_fifo_max_dequeue_cons (tls_rx_fifo); - if (!deq_max) - goto done_hs; - - vec_validate (ptls_ctx->rx_content, deq_max); - ptls_ctx->rx_offset = 0; - ptls_ctx->rx_len = 0; - - off = svm_fifo_dequeue (tls_rx_fifo, deq_max, TLS_RX_LEN (ptls_ctx)); - from_tls_len += off; - ptls_ctx->rx_len += off; - - picotls_do_handshake (ptls_ctx, tls_session, TLS_RX_OFFSET (ptls_ctx), - from_tls_len); + picotls_do_handshake (ptls_ctx, tcp_session); if (picotls_handshake_is_over (ctx)) ret = ptls_is_server (ptls_ctx->tls) ? tls_notify_app_accept (ctx) : tls_notify_app_connected (ctx, SESSION_E_NONE); - done_hs: - if (!TLS_RX_IS_LEFT (ptls_ctx)) + if (!svm_fifo_max_dequeue (tcp_session->rx_fifo)) return 0; } + tcp_rx_fifo = tcp_session->rx_fifo; app_session = session_get_from_handle (ctx->app_session_handle); app_rx_fifo = app_session->rx_fifo; if (TLS_READ_IS_LEFT (ptls_ctx)) - goto enq_buf; + goto do_enq; + + len = svm_fifo_segments (tcp_rx_fifo, 0, fs, n_segs, max_len); + if (len <= 0) + goto final_checks; ptls_buffer_init (buf, "", 0); ptls_ctx->read_buffer_offset = 0; - if (!TLS_RX_IS_LEFT (ptls_ctx)) + while (read < len && i < n_segs) { - deq_max = svm_fifo_max_dequeue_cons (tls_rx_fifo); - if (!deq_max) - goto app_fifo; - - deq_now = clib_min (deq_max, svm_fifo_max_read_chunk (tls_rx_fifo)); - - if (PREDICT_FALSE (deq_now < deq_max)) + deq_now = fs[i].len; + ret = ptls_receive (ptls_ctx->tls, buf, fs[i].data, &deq_now); + ASSERT (ret == 0 || ret == PTLS_ERROR_IN_PROGRESS); + read += deq_now; + if (deq_now < fs[i].len) { - off = - svm_fifo_dequeue (tls_rx_fifo, deq_max, TLS_RX_LEN (ptls_ctx)); - from_tls_len += off; - ptls_ctx->rx_len += off; + fs[i].data += deq_now; + fs[i].len -= deq_now; } else - { - ret = - ptls_receive (ptls_ctx->tls, buf, svm_fifo_head (tls_rx_fifo), - (size_t *) & deq_now); - svm_fifo_dequeue_drop (tls_rx_fifo, deq_now); - goto enq_buf; - } + i++; } -app_fifo: - - enq_max = svm_fifo_max_enqueue_prod (app_rx_fifo); - if (!enq_max) - goto final; - - crypto_len = clib_min (enq_max, TLS_RX_LEFT_LEN (ptls_ctx)); - off = 0; + if (read) + svm_fifo_dequeue_drop (tcp_rx_fifo, read); - do + if (!TLS_READ_LEFT_LEN (ptls_ctx)) { - size_t consumed = crypto_len - off; - ret = - ptls_receive (ptls_ctx->tls, buf, - TLS_RX_OFFSET (ptls_ctx), &consumed); - off += consumed; - ptls_ctx->rx_offset += off; + ptls_buffer_dispose (buf); + goto final_checks; } - while (ret == 0 && off < crypto_len); -enq_buf: +do_enq: - off = - svm_fifo_enqueue (app_rx_fifo, TLS_READ_LEFT_LEN (ptls_ctx), - TLS_READ_OFFSET (ptls_ctx)); - if (off < 0) + len = TLS_READ_LEFT_LEN (ptls_ctx); + off = svm_fifo_enqueue (app_rx_fifo, len, TLS_READ_OFFSET (ptls_ctx)); + if (off != len) { - tls_add_vpp_q_builtin_rx_evt (tls_session); - return 0; + if (off < 0) + { + off = 0; + goto final_checks; + } + ptls_ctx->read_buffer_offset += off; } - - ptls_ctx->read_buffer_offset += off; - if (!TLS_RX_IS_LEFT (ptls_ctx)) + else { - ptls_ctx->rx_len = 0; - ptls_ctx->rx_offset = 0; + ptls_buffer_dispose (buf); } -final: - ptls_buffer_dispose (buf); - if (app_session->session_state >= SESSION_STATE_READY) tls_notify_app_enqueue (ctx, app_session); - if (TLS_RX_IS_LEFT (ptls_ctx) || TLS_READ_IS_LEFT (ptls_ctx) - || svm_fifo_max_dequeue (tls_rx_fifo)) - tls_add_vpp_q_builtin_rx_evt (tls_session); +final_checks: - return from_tls_len; + if (TLS_READ_IS_LEFT (ptls_ctx) || svm_fifo_max_dequeue (tcp_rx_fifo)) + tls_add_vpp_q_builtin_rx_evt (tcp_session); + + return off; } static inline int @@ -455,7 +440,6 @@ picotls_ctx_write (tls_ctx_t * ctx, session_t * app_session, ptls_buffer_init (&ptls_ctx->write_buffer, "", 0); ptls_ctx->write_buffer_offset = 0; } - } deq_max = svm_fifo_max_dequeue_cons (app_tx_fifo); -- cgit 1.2.3-korg