tls: picotls rx fixes and improvements 08/33308/12
authorFlorin Coras <fcoras@cisco.com>
Thu, 29 Jul 2021 16:06:00 +0000 (09:06 -0700)
committerFlorin Coras <florin.coras@gmail.com>
Fri, 30 Jul 2021 01:15:20 +0000 (01:15 +0000)
Type: fix

Signed-off-by: Florin Coras <fcoras@cisco.com>
Change-Id: I9ea41b8b271e9123e676acdc581ef429072fe843

src/plugins/tlspicotls/pico_vpp_crypto.c
src/plugins/tlspicotls/tls_picotls.c

index 9af0f2f..f3514d0 100644 (file)
@@ -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;
index ef02f66..a0fbab0 100644 (file)
@@ -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);