]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
iov: _gnutls_iov_iter_next: return bytes instead of blocks
authorDaiki Ueno <dueno@redhat.com>
Thu, 3 Oct 2019 08:34:18 +0000 (10:34 +0200)
committerDaiki Ueno <dueno@redhat.com>
Sun, 6 Oct 2019 07:00:22 +0000 (09:00 +0200)
This eliminates the need of special handling of final block.  Also
adds more tests in exceptional cases.

Signed-off-by: Daiki Ueno <dueno@redhat.com>
lib/crypto-api.c
lib/iov.c
tests/iov.c

index 09b3d7bfc6d3627982ea3dfcfa546f38299df81e..41e759b74e7bdb69ee9b1d342a07ab9102f9215f 100644 (file)
@@ -992,9 +992,9 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
        uint8_t *dst;
        size_t dst_size, total = 0;
        uint8_t *p;
+       size_t len;
        size_t blocksize = handle->ctx_enc.e->blocksize;
        struct iov_iter_st iter;
-       size_t blocks;
 
        /* Limitation: this function provides an optimization under the internally registered
         * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
@@ -1045,15 +1045,7 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
                        return gnutls_assert_val(ret);
                if (ret == 0)
                        break;
-               blocks = ret;
-               ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
-                                         blocksize * blocks);
-               if (unlikely(ret < 0))
-                       return gnutls_assert_val(ret);
-       }
-       if (iter.block_offset > 0) {
-               ret = _gnutls_cipher_auth(&handle->ctx_enc,
-                                         iter.block, iter.block_offset);
+               ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
                if (unlikely(ret < 0))
                        return gnutls_assert_val(ret);
        }
@@ -1070,29 +1062,15 @@ gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
                        return gnutls_assert_val(ret);
                if (ret == 0)
                        break;
-               blocks = ret;
-               if (unlikely(dst_size < blocksize * blocks))
-                       return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
-               ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p,
-                                             blocksize * blocks,
-                                             dst, dst_size);
-               if (unlikely(ret < 0))
-                       return gnutls_assert_val(ret);
-               DECR_LEN(dst_size, blocksize * blocks);
-               dst += blocksize * blocks;
-               total += blocksize * blocks;
-       }
-       if (iter.block_offset > 0) {
-               if (unlikely(dst_size < iter.block_offset))
-                       return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+               len = ret;
                ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
-                                             iter.block, iter.block_offset,
+                                             p, len,
                                              dst, dst_size);
                if (unlikely(ret < 0))
                        return gnutls_assert_val(ret);
-               DECR_LEN(dst_size, iter.block_offset);
-               dst += iter.block_offset;
-               total += iter.block_offset;
+               DECR_LEN(dst_size, len);
+               dst += len;
+               total += len;
        }
 
        if (dst_size < tag_size)
@@ -1137,7 +1115,6 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
        uint8_t *p;
        ssize_t blocksize = handle->ctx_enc.e->blocksize;
        struct iov_iter_st iter;
-       size_t blocks;
        size_t _tag_size;
 
        if (tag_size == NULL || *tag_size == 0)
@@ -1220,15 +1197,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
                        return gnutls_assert_val(ret);
                if (ret == 0)
                        break;
-               blocks = ret;
-               ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
-                                         blocksize * blocks);
-               if (unlikely(ret < 0))
-                       return gnutls_assert_val(ret);
-       }
-       if (iter.block_offset > 0) {
-               ret = _gnutls_cipher_auth(&handle->ctx_enc,
-                                         iter.block, iter.block_offset);
+               ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
                if (unlikely(ret < 0))
                        return gnutls_assert_val(ret);
        }
@@ -1242,17 +1211,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
                        return gnutls_assert_val(ret);
                if (ret == 0)
                        break;
-               blocks = ret;
-               ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
-                                             p, blocksize * blocks,
-                                             p, blocksize * blocks);
-               if (unlikely(ret < 0))
-                       return gnutls_assert_val(ret);
-       }
-       if (iter.block_offset > 0) {
-               ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
-                                             iter.block, iter.block_offset,
-                                             iter.block, iter.block_offset);
+               ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, ret, p, ret);
                if (unlikely(ret < 0))
                        return gnutls_assert_val(ret);
        }
@@ -1296,7 +1255,6 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
        uint8_t *p;
        ssize_t blocksize = handle->ctx_enc.e->blocksize;
        struct iov_iter_st iter;
-       size_t blocks;
        uint8_t _tag[MAX_HASH_SIZE];
 
        if (tag_size == 0)
@@ -1370,15 +1328,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
                        return gnutls_assert_val(ret);
                if (ret == 0)
                        break;
-               blocks = ret;
-               ret = _gnutls_cipher_auth(&handle->ctx_enc, p,
-                                         blocksize * blocks);
-               if (unlikely(ret < 0))
-                       return gnutls_assert_val(ret);
-       }
-       if (iter.block_offset > 0) {
-               ret = _gnutls_cipher_auth(&handle->ctx_enc,
-                                         iter.block, iter.block_offset);
+               ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
                if (unlikely(ret < 0))
                        return gnutls_assert_val(ret);
        }
@@ -1392,17 +1342,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
                        return gnutls_assert_val(ret);
                if (ret == 0)
                        break;
-               blocks = ret;
-               ret = _gnutls_cipher_decrypt2(&handle->ctx_enc,
-                                             p, blocksize * blocks,
-                                             p, blocksize * blocks);
-               if (unlikely(ret < 0))
-                       return gnutls_assert_val(ret);
-       }
-       if (iter.block_offset > 0) {
-               ret = _gnutls_cipher_decrypt2(&handle->ctx_enc,
-                                             iter.block, iter.block_offset,
-                                             iter.block, iter.block_offset);
+               ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, ret, p, ret);
                if (unlikely(ret < 0))
                        return gnutls_assert_val(ret);
        }
index 5dc29c54bd96d6831db94271dfaa520db80de555..17272886cb3417ff5fa93b4fa5692b3bec96be80 100644 (file)
--- a/lib/iov.c
+++ b/lib/iov.c
@@ -58,8 +58,8 @@ _gnutls_iov_iter_init(struct iov_iter_st *iter,
  * @data: the return location of extracted data
  *
  * Retrieve block(s) pointed by @iter and advance it to the next
- * position.  It returns the number of consecutive blocks in @data.
- * At the end of iteration, 0 is returned.
+ * position.  It returns the number of bytes in @data.  At the end of
+ * iteration, 0 is returned.
  *
  * If the data stored in @iter is not multiple of the block size, the
  * remaining data is stored in the "block" field of @iter with the
@@ -88,25 +88,30 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data)
                        if ((len % iter->block_size) == 0) {
                                iter->iov_index++;
                                iter->iov_offset = 0;
-                       } else
-                               iter->iov_offset +=
-                                       len - (len % iter->block_size);
+                       } else {
+                               len -= (len % iter->block_size);
+                               iter->iov_offset += len;
+                       }
 
                        /* Return the blocks. */
                        *data = p;
-                       return len / iter->block_size;
+                       return len;
                }
 
                /* We can complete one full block to return. */
                block_left = iter->block_size - iter->block_offset;
                if (len >= block_left) {
                        memcpy(iter->block + iter->block_offset, p, block_left);
-                       iter->iov_offset += block_left;
+                       if (len == block_left) {
+                               iter->iov_index++;
+                               iter->iov_offset = 0;
+                       } else
+                               iter->iov_offset += block_left;
                        iter->block_offset = 0;
 
                        /* Return the filled block. */
                        *data = iter->block;
-                       return 1;
+                       return iter->block_size;
                }
 
                /* Not enough data for a full block, store in temp
@@ -116,5 +121,15 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data)
                iter->iov_index++;
                iter->iov_offset = 0;
        }
+
+       if (iter->block_offset > 0) {
+               size_t len = iter->block_offset;
+
+               /* Return the incomplete block. */
+               *data = iter->block;
+               iter->block_offset = 0;
+               return len;
+       }
+
        return 0;
 }
index eda5583a77d3761f42bb70912f2dc3527cc14564..3d116b47174f8f3a1b52915fb28f212b4c79c685 100644 (file)
@@ -32,7 +32,6 @@ struct exp_st {
        ssize_t ret;
        size_t iov_index;
        size_t iov_offset;
-       size_t block_offset;
 };
 
 struct test_st {
@@ -42,7 +41,6 @@ struct test_st {
        size_t block_size;
        const struct exp_st *exp;
        size_t expcnt;
-       size_t remaining;
 };
 
 static const giovec_t iov16[] = {
@@ -53,40 +51,41 @@ static const giovec_t iov16[] = {
 };
 
 static const struct exp_st exp16_64[] = {
-       {1, 3, 16, 0},
-       {0, 0, 0, 0}
+       {64, 4, 0},
+       {0, 0, 0}
 };
 
 static const struct exp_st exp16_32[] = {
-       {1, 1, 16, 0},
-       {1, 3, 16, 0},
-       {0, 0, 0, 0}
+       {32, 2, 0},
+       {32, 4, 0},
+       {0, 0, 0}
 };
 
 static const struct exp_st exp16_16[] = {
-       {1, 1, 0, 0},
-       {1, 2, 0, 0},
-       {1, 3, 0, 0},
-       {1, 4, 0, 0},
-       {0, 0, 0, 0}
+       {16, 1, 0},
+       {16, 2, 0},
+       {16, 3, 0},
+       {16, 4, 0},
+       {0, 0, 0}
 };
 
 static const struct exp_st exp16_4[] = {
-       {4, 1, 0, 0},
-       {4, 2, 0, 0},
-       {4, 3, 0, 0},
-       {4, 4, 0, 0},
-       {0, 0, 0, 0}
+       {16, 1, 0},
+       {16, 2, 0},
+       {16, 3, 0},
+       {16, 4, 0},
+       {0, 0, 0}
 };
 
 static const struct exp_st exp16_3[] = {
-       {5, 0, 15, 0},
-       {1, 1, 2, 0},
-       {4, 1, 14, 0},
-       {1, 2, 1, 0},
-       {5, 3, 0, 0},
-       {5, 3, 15, 0},
-       {0, 0, 0, 1}
+       {15, 0, 15},
+       {3, 1, 2},
+       {12, 1, 14},
+       {3, 2, 1},
+       {15, 3, 0},
+       {15, 3, 15},
+       {1, 4, 0},
+       {0, 0, 0}
 };
 
 static const giovec_t iov8[] = {
@@ -97,22 +96,74 @@ static const giovec_t iov8[] = {
 };
 
 static const struct exp_st exp8_64[] = {
-       {0, 0, 0, 32}
+       {32, 4, 0},
+       {0, 0, 0}
+};
+
+static const giovec_t iov_odd[] = {
+       {(void *) "0", 1},
+       {(void *) "012", 3},
+       {(void *) "01234", 5},
+       {(void *) "0123456", 7},
+       {(void *) "012345678", 9},
+       {(void *) "01234567890", 11},
+       {(void *) "0123456789012", 13},
+       {(void *) "012345678901234", 15}
+};
+
+static const struct exp_st exp_odd_16[] = {
+       {16, 4, 0},
+       {16, 5, 7},
+       {16, 6, 12},
+       {16, 8, 0},
+       {0, 0, 0}
+};
+
+static const giovec_t iov_skip[] = {
+       {(void *) "0123456789012345", 16},
+       {(void *) "01234567", 8},
+       {(void *) "", 0},
+       {(void *) "", 0},
+       {(void *) "0123456789012345", 16}
+};
+
+static const struct exp_st exp_skip_16[] = {
+       {16, 1, 0},
+       {16, 4, 8},
+       {8, 5, 0},
+       {0, 0, 0}
+};
+
+static const giovec_t iov_empty[] = {
+       {(void *) "", 0},
+       {(void *) "", 0},
+       {(void *) "", 0},
+       {(void *) "", 0}
+};
+
+static const struct exp_st exp_empty_16[] = {
+       {0, 0, 0}
 };
 
 static const struct test_st tests[] = {
        { "16/64", iov16, sizeof(iov16)/sizeof(iov16[0]), 64,
-         exp16_64, sizeof(exp16_64)/sizeof(exp16_64[0]), 0 },
+         exp16_64, sizeof(exp16_64)/sizeof(exp16_64[0]) },
        { "16/32", iov16, sizeof(iov16)/sizeof(iov16[0]), 32,
-         exp16_32, sizeof(exp16_32)/sizeof(exp16_32[0]), 0 },
+         exp16_32, sizeof(exp16_32)/sizeof(exp16_32[0]) },
        { "16/16", iov16, sizeof(iov16)/sizeof(iov16[0]), 16,
-         exp16_16, sizeof(exp16_16)/sizeof(exp16_16[0]), 0 },
+         exp16_16, sizeof(exp16_16)/sizeof(exp16_16[0]) },
        { "16/4", iov16, sizeof(iov16)/sizeof(iov16[0]), 4,
-         exp16_4, sizeof(exp16_4)/sizeof(exp16_4[0]), 0 },
+         exp16_4, sizeof(exp16_4)/sizeof(exp16_4[0]) },
        { "16/3", iov16, sizeof(iov16)/sizeof(iov16[0]), 3,
-         exp16_3, sizeof(exp16_3)/sizeof(exp16_3[0]), 1 },
+         exp16_3, sizeof(exp16_3)/sizeof(exp16_3[0]) },
        { "8/64", iov8, sizeof(iov8)/sizeof(iov8[0]), 64,
-         exp8_64, sizeof(exp8_64)/sizeof(exp8_64[0]), 32 }
+         exp8_64, sizeof(exp8_64)/sizeof(exp8_64[0]) },
+       { "odd/16", iov_odd, sizeof(iov_odd)/sizeof(iov_odd[0]), 16,
+         exp_odd_16, sizeof(exp_odd_16)/sizeof(exp_odd_16[0]) },
+       { "skip/16", iov_skip, sizeof(iov_skip)/sizeof(iov_skip[0]), 16,
+         exp_skip_16, sizeof(exp_skip_16)/sizeof(exp_skip_16[0]) },
+       { "empty/16", iov_empty, sizeof(iov_empty)/sizeof(iov_empty[0]), 16,
+         exp_empty_16, sizeof(exp_empty_16)/sizeof(exp_empty_16[0]) },
 };
 
 void
@@ -155,16 +206,13 @@ doit (void)
                                else if (debug)
                                        success("iter.iov_offset: %u == %u\n",
                                             (unsigned) iter.iov_offset, (unsigned) exp[j].iov_offset);
-                               if (iter.block_offset != exp[j].block_offset)
-                                       fail("iter.block_offset: %u != %u\n",
-                                            (unsigned) iter.block_offset, (unsigned) exp[j].block_offset);
+                               if (iter.block_offset != 0)
+                                       fail("iter.block_offset: %u != 0\n",
+                                            (unsigned) iter.block_offset);
                                else if (debug)
-                                       success("iter.block_offset: %u == %u\n",
-                                            (unsigned) iter.block_offset, (unsigned) exp[j].block_offset);
+                                       success("iter.block_offset: %u == 0\n",
+                                            (unsigned) iter.block_offset);
                        }
                }
-               if (iter.block_offset != tests[i].remaining)
-                       fail("remaining: %u != %u\n",
-                            (unsigned) iter.block_offset, (unsigned) tests[i].remaining);
        }
 }