diff options
author | Daiki Ueno <dueno@redhat.com> | 2019-10-03 10:34:18 +0200 |
---|---|---|
committer | Daiki Ueno <dueno@redhat.com> | 2019-10-06 09:00:22 +0200 |
commit | bbb312749780928cc10b45662c6d7eadcaa98f0b (patch) | |
tree | 0f80002bb950a5e6ca9977fb27c14a9717927743 | |
parent | 26dc061ff647a22ca42b8596e24df03e57c541d1 (diff) | |
download | gnutls-bbb312749780928cc10b45662c6d7eadcaa98f0b.tar.gz |
iov: _gnutls_iov_iter_next: return bytes instead of blocks
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>
-rw-r--r-- | lib/crypto-api.c | 82 | ||||
-rw-r--r-- | lib/iov.c | 31 | ||||
-rw-r--r-- | tests/iov.c | 126 |
3 files changed, 121 insertions, 118 deletions
diff --git a/lib/crypto-api.c b/lib/crypto-api.c index 09b3d7bfc6..41e759b74e 100644 --- a/lib/crypto-api.c +++ b/lib/crypto-api.c @@ -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); } @@ -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; } diff --git a/tests/iov.c b/tests/iov.c index eda5583a77..3d116b4717 100644 --- a/tests/iov.c +++ b/tests/iov.c @@ -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); } } |