tls: Fix tls_device handling of partial records
[sfrench/cifs-2.6.git] / net / tls / tls_device.c
index d753e362d2d9e625b9d9c4c476cc06cdcbc5430a..3e5e8e021a878acca89b4a5c89d52c7a257701c2 100644 (file)
@@ -247,6 +247,7 @@ static int tls_push_record(struct sock *sk,
                           int flags,
                           unsigned char record_type)
 {
+       struct tls_prot_info *prot = &ctx->prot_info;
        struct tcp_sock *tp = tcp_sk(sk);
        struct page_frag dummy_tag_frag;
        skb_frag_t *frag;
@@ -256,21 +257,21 @@ static int tls_push_record(struct sock *sk,
        frag = &record->frags[0];
        tls_fill_prepend(ctx,
                         skb_frag_address(frag),
-                        record->len - ctx->tx.prepend_size,
-                        record_type);
+                        record->len - prot->prepend_size,
+                        record_type,
+                        ctx->crypto_send.info.version);
 
        /* HW doesn't care about the data in the tag, because it fills it. */
        dummy_tag_frag.page = skb_frag_page(frag);
        dummy_tag_frag.offset = 0;
 
-       tls_append_frag(record, &dummy_tag_frag, ctx->tx.tag_size);
+       tls_append_frag(record, &dummy_tag_frag, prot->tag_size);
        record->end_seq = tp->write_seq + record->len;
        spin_lock_irq(&offload_ctx->lock);
        list_add_tail(&record->list, &offload_ctx->records_list);
        spin_unlock_irq(&offload_ctx->lock);
        offload_ctx->open_record = NULL;
-       set_bit(TLS_PENDING_CLOSED_RECORD, &ctx->flags);
-       tls_advance_record_sn(sk, &ctx->tx);
+       tls_advance_record_sn(sk, &ctx->tx, ctx->crypto_send.info.version);
 
        for (i = 0; i < record->num_frags; i++) {
                frag = &record->frags[i];
@@ -346,6 +347,7 @@ static int tls_push_data(struct sock *sk,
                         unsigned char record_type)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
+       struct tls_prot_info *prot = &tls_ctx->prot_info;
        struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx);
        int tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST;
        int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE);
@@ -365,9 +367,11 @@ static int tls_push_data(struct sock *sk,
                return -sk->sk_err;
 
        timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
-       rc = tls_complete_pending_work(sk, tls_ctx, flags, &timeo);
-       if (rc < 0)
-               return rc;
+       if (tls_is_partially_sent_record(tls_ctx)) {
+               rc = tls_push_partial_record(sk, tls_ctx, flags);
+               if (rc < 0)
+                       return rc;
+       }
 
        pfrag = sk_page_frag(sk);
 
@@ -375,10 +379,10 @@ static int tls_push_data(struct sock *sk,
         * we need to leave room for an authentication tag.
         */
        max_open_record_len = TLS_MAX_PAYLOAD_SIZE +
-                             tls_ctx->tx.prepend_size;
+                             prot->prepend_size;
        do {
                rc = tls_do_allocation(sk, ctx, pfrag,
-                                      tls_ctx->tx.prepend_size);
+                                      prot->prepend_size);
                if (rc) {
                        rc = sk_stream_wait_memory(sk, &timeo);
                        if (!rc)
@@ -396,7 +400,7 @@ handle_error:
                                size = orig_size;
                                destroy_record(record);
                                ctx->open_record = NULL;
-                       } else if (record->len > tls_ctx->tx.prepend_size) {
+                       } else if (record->len > prot->prepend_size) {
                                goto last_record;
                        }
 
@@ -657,6 +661,8 @@ int tls_device_decrypted(struct sock *sk, struct sk_buff *skb)
 int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
 {
        u16 nonce_size, tag_size, iv_size, rec_seq_size;
+       struct tls_context *tls_ctx = tls_get_ctx(sk);
+       struct tls_prot_info *prot = &tls_ctx->prot_info;
        struct tls_record_info *start_marker_record;
        struct tls_offload_context_tx *offload_ctx;
        struct tls_crypto_info *crypto_info;
@@ -702,10 +708,10 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
                goto free_offload_ctx;
        }
 
-       ctx->tx.prepend_size = TLS_HEADER_SIZE + nonce_size;
-       ctx->tx.tag_size = tag_size;
-       ctx->tx.overhead_size = ctx->tx.prepend_size + ctx->tx.tag_size;
-       ctx->tx.iv_size = iv_size;
+       prot->prepend_size = TLS_HEADER_SIZE + nonce_size;
+       prot->tag_size = tag_size;
+       prot->overhead_size = prot->prepend_size + prot->tag_size;
+       prot->iv_size = iv_size;
        ctx->tx.iv = kmalloc(iv_size + TLS_CIPHER_AES_GCM_128_SALT_SIZE,
                             GFP_KERNEL);
        if (!ctx->tx.iv) {
@@ -715,7 +721,7 @@ int tls_set_device_offload(struct sock *sk, struct tls_context *ctx)
 
        memcpy(ctx->tx.iv + TLS_CIPHER_AES_GCM_128_SALT_SIZE, iv, iv_size);
 
-       ctx->tx.rec_seq_size = rec_seq_size;
+       prot->rec_seq_size = rec_seq_size;
        ctx->tx.rec_seq = kmemdup(rec_seq, rec_seq_size, GFP_KERNEL);
        if (!ctx->tx.rec_seq) {
                rc = -ENOMEM;