summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2019-10-03 10:34:18 +0200
committerDaiki Ueno <dueno@redhat.com>2019-10-06 09:00:22 +0200
commitbbb312749780928cc10b45662c6d7eadcaa98f0b (patch)
tree0f80002bb950a5e6ca9977fb27c14a9717927743
parent26dc061ff647a22ca42b8596e24df03e57c541d1 (diff)
downloadgnutls-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.c82
-rw-r--r--lib/iov.c31
-rw-r--r--tests/iov.c126
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);
}
diff --git a/lib/iov.c b/lib/iov.c
index 5dc29c54bd..17272886cb 100644
--- 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;
}
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);
}
}