gnutls/SOURCES/gnutls-3.6.8-fix-aead-ciphe...

768 lines
21 KiB
Diff

From bbb312749780928cc10b45662c6d7eadcaa98f0b Mon Sep 17 00:00:00 2001
From: Daiki Ueno <dueno@redhat.com>
Date: Thu, 3 Oct 2019 10:34:18 +0200
Subject: [PATCH 1/3] 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>
---
lib/crypto-api.c | 82 +++++-------------------------
lib/iov.c | 31 +++++++++---
tests/iov.c | 126 ++++++++++++++++++++++++++++++++---------------
3 files changed, 121 insertions(+), 118 deletions(-)
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index 09b3d7bfc..41e759b74 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 5dc29c54b..17272886c 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 eda5583a7..3d116b471 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);
}
}
--
2.21.0
From c684814cc456a9792a9183ce77d32d435f29e6b7 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <dueno@redhat.com>
Date: Tue, 1 Oct 2019 18:14:48 +0200
Subject: [PATCH 2/3] iov: add _gnutls_iov_iter_sync to write back cached data
to iov
Signed-off-by: Daiki Ueno <dueno@redhat.com>
---
lib/iov.c | 59 +++++++++++++++++++++++++++++++++++++++++++++
lib/iov.h | 4 +++-
lib/libgnutls.map | 1 +
tests/iov.c | 61 +++++++++++++++++++++++++++++++++++++++++++----
4 files changed, 119 insertions(+), 6 deletions(-)
diff --git a/lib/iov.c b/lib/iov.c
index 17272886c..1cd8d46dd 100644
--- a/lib/iov.c
+++ b/lib/iov.c
@@ -133,3 +133,62 @@ _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data)
return 0;
}
+
+/**
+ * _gnutls_iov_iter_sync:
+ * @iter: the iterator
+ * @data: data returned by _gnutls_iov_iter_next
+ * @data_size: size of @data
+ *
+ * Flush the content of temp buffer (if any) to the data buffer.
+ */
+int
+_gnutls_iov_iter_sync(struct iov_iter_st *iter, const uint8_t *data,
+ size_t data_size)
+{
+ size_t iov_index;
+ size_t iov_offset;
+
+ /* We didn't return the cached block. */
+ if (data != iter->block)
+ return 0;
+
+ iov_index = iter->iov_index;
+ iov_offset = iter->iov_offset;
+
+ /* When syncing a cache block we walk backwards because we only have a
+ * pointer to were the block ends in the iovec, walking backwards is
+ * fine as we are always writing a full block, so the whole content
+ * is written in the right places:
+ * iovec: |--0--|---1---|--2--|-3-|
+ * block: |-----------------------|
+ * 1st write |---|
+ * 2nd write |-----
+ * 3rd write |-------
+ * last write |-----
+ */
+ while (data_size > 0) {
+ const giovec_t *iov;
+ uint8_t *p;
+ size_t to_write;
+
+ while (iov_offset == 0) {
+ if (unlikely(iov_index == 0))
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ iov_index--;
+ iov_offset = iter->iov[iov_index].iov_len;
+ }
+
+ iov = &iter->iov[iov_index];
+ p = iov->iov_base;
+ to_write = MIN(data_size, iov_offset);
+
+ iov_offset -= to_write;
+ data_size -= to_write;
+
+ memcpy(p + iov_offset, &iter->block[data_size], to_write);
+ }
+
+ return 0;
+}
diff --git a/lib/iov.h b/lib/iov.h
index 47fba559a..5b9903460 100644
--- a/lib/iov.h
+++ b/lib/iov.h
@@ -34,7 +34,6 @@ struct iov_iter_st {
uint8_t block[MAX_CIPHER_BLOCK_SIZE]; /* incomplete block for reading */
size_t block_size; /* actual block size of the cipher */
size_t block_offset; /* offset in block */
-
};
int _gnutls_iov_iter_init(struct iov_iter_st *iter,
@@ -43,4 +42,7 @@ int _gnutls_iov_iter_init(struct iov_iter_st *iter,
ssize_t _gnutls_iov_iter_next(struct iov_iter_st *iter, uint8_t **data);
+int _gnutls_iov_iter_sync(struct iov_iter_st *iter, const uint8_t *data,
+ size_t data_size);
+
#endif /* GNUTLS_LIB_IOV_H */
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index f83a21e9b..d6973f72e 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -1394,4 +1394,5 @@ GNUTLS_PRIVATE_3_4 {
# needed by tests/iov:
_gnutls_iov_iter_init;
_gnutls_iov_iter_next;
+ _gnutls_iov_iter_sync;
} GNUTLS_3_4;
diff --git a/tests/iov.c b/tests/iov.c
index 3d116b471..2acd2b5f5 100644
--- a/tests/iov.c
+++ b/tests/iov.c
@@ -44,10 +44,10 @@ struct test_st {
};
static const giovec_t iov16[] = {
- {(void *) "0123456789abcdef", 16},
- {(void *) "0123456789abcdef", 16},
- {(void *) "0123456789abcdef", 16},
- {(void *) "0123456789abcdef", 16}
+ {(void *) "0123456789012345", 16},
+ {(void *) "0123456789012345", 16},
+ {(void *) "0123456789012345", 16},
+ {(void *) "0123456789012345", 16}
};
static const struct exp_st exp16_64[] = {
@@ -166,20 +166,53 @@ static const struct test_st tests[] = {
exp_empty_16, sizeof(exp_empty_16)/sizeof(exp_empty_16[0]) },
};
+static void
+copy(giovec_t *dst, uint8_t *buffer, const giovec_t *src, size_t iovcnt)
+{
+ uint8_t *p = buffer;
+ size_t i;
+
+ for (i = 0; i < iovcnt; i++) {
+ dst[i].iov_base = p;
+ dst[i].iov_len = src[i].iov_len;
+ memcpy(dst[i].iov_base, src[i].iov_base, src[i].iov_len);
+ p += src[i].iov_len;
+ }
+}
+
+static void
+translate(uint8_t *data, size_t len)
+{
+ for (; len > 0; len--) {
+ uint8_t *p = &data[len - 1];
+ if (*p >= '0' && *p <= '9')
+ *p = 'A' + *p - '0';
+ else if (*p >= 'A' && *p <= 'Z')
+ *p = '0' + *p - 'A';
+ }
+}
+
+#define MAX_BUF 1024
+#define MAX_IOV 16
+
void
doit (void)
{
+ uint8_t buffer[MAX_BUF];
size_t i;
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+ giovec_t iov[MAX_IOV];
struct iov_iter_st iter;
const struct exp_st *exp = tests[i].exp;
uint8_t *data;
size_t j;
+ copy(iov, buffer, tests[i].iov, tests[i].iovcnt);
+
success("%s\n", tests[i].name);
assert(_gnutls_iov_iter_init(&iter,
- tests[i].iov, tests[i].iovcnt,
+ iov, tests[i].iovcnt,
tests[i].block_size) == 0);
for (j = 0; j < tests[i].expcnt; j++) {
ssize_t ret;
@@ -212,7 +245,25 @@ doit (void)
else if (debug)
success("iter.block_offset: %u == 0\n",
(unsigned) iter.block_offset);
+
+ translate(data, ret);
+
+ ret = _gnutls_iov_iter_sync(&iter, data, ret);
+ if (ret < 0)
+ fail("sync failed\n");
}
}
+
+ for (j = 0; j < tests[i].iovcnt; j++) {
+ translate(iov[j].iov_base, iov[j].iov_len);
+
+ if (memcmp(iov[j].iov_base, tests[i].iov[j].iov_base,
+ iov[j].iov_len) != 0)
+ fail("iov doesn't match: %*s != %*s\n",
+ (int)iov[j].iov_len,
+ (char *)iov[j].iov_base,
+ (int)tests[i].iov[j].iov_len,
+ (char *)tests[i].iov[j].iov_len);
+ }
}
}
--
2.21.0
From 6df0cf1c0ec727fc237a9b429684c8f2ef5d34b7 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <dueno@redhat.com>
Date: Tue, 1 Oct 2019 18:15:19 +0200
Subject: [PATCH 3/3] gnutls_aead_cipher_{en,de}cryptv2: write back cached data
to buffers
Previously, those functions failed to write the output to the buffers
if the buffer length is not multiple of cipher block size. This makes
sure that the cached data is always flushed.
Signed-off-by: Daiki Ueno <dueno@redhat.com>
---
lib/crypto-api.c | 18 ++++++++++++++++--
tests/aead-cipher-vec.c | 14 ++++++++------
2 files changed, 24 insertions(+), 8 deletions(-)
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index 41e759b74..7308d7e7b 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -1113,6 +1113,7 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
api_aead_cipher_hd_st *h = handle;
ssize_t ret;
uint8_t *p;
+ size_t len;
ssize_t blocksize = handle->ctx_enc.e->blocksize;
struct iov_iter_st iter;
size_t _tag_size;
@@ -1211,7 +1212,13 @@ gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
return gnutls_assert_val(ret);
if (ret == 0)
break;
- ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, ret, p, ret);
+
+ len = ret;
+ ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, len, p, len);
+ if (unlikely(ret < 0))
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_iov_iter_sync(&iter, p, len);
if (unlikely(ret < 0))
return gnutls_assert_val(ret);
}
@@ -1253,6 +1260,7 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
api_aead_cipher_hd_st *h = handle;
ssize_t ret;
uint8_t *p;
+ size_t len;
ssize_t blocksize = handle->ctx_enc.e->blocksize;
struct iov_iter_st iter;
uint8_t _tag[MAX_HASH_SIZE];
@@ -1342,7 +1350,13 @@ gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
return gnutls_assert_val(ret);
if (ret == 0)
break;
- ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, ret, p, ret);
+
+ len = ret;
+ ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, len, p, len);
+ if (unlikely(ret < 0))
+ return gnutls_assert_val(ret);
+
+ ret = _gnutls_iov_iter_sync(&iter, p, len);
if (unlikely(ret < 0))
return gnutls_assert_val(ret);
}
diff --git a/tests/aead-cipher-vec.c b/tests/aead-cipher-vec.c
index 6c2542cf1..10e3db862 100644
--- a/tests/aead-cipher-vec.c
+++ b/tests/aead-cipher-vec.c
@@ -43,9 +43,9 @@ static void start(const char *name, int algo)
uint8_t key16[64];
uint8_t iv16[32];
uint8_t auth[128];
- uint8_t data[128+64];
+ uint8_t data[64+56+36];
gnutls_datum_t key, iv;
- giovec_t iov[2];
+ giovec_t iov[3];
giovec_t auth_iov[2];
uint8_t tag[64];
size_t tag_size = 0;
@@ -60,13 +60,15 @@ static void start(const char *name, int algo)
memset(iv.data, 0xff, iv.size);
memset(key.data, 0xfe, key.size);
- memset(data, 0xfa, 128);
+ memset(data, 0xfa, sizeof(data));
memset(auth, 0xaa, sizeof(auth));
iov[0].iov_base = data;
iov[0].iov_len = 64;
iov[1].iov_base = data + 64;
- iov[1].iov_len = 64;
+ iov[1].iov_len = 56;
+ iov[2].iov_base = data + 64 + 56;
+ iov[2].iov_len = 36;
auth_iov[0].iov_base = auth;
auth_iov[0].iov_len = 64;
@@ -83,7 +85,7 @@ static void start(const char *name, int algo)
ret = gnutls_aead_cipher_encryptv2(ch,
iv.data, iv.size,
auth_iov, 2,
- iov, 2,
+ iov, 3,
tag, &tag_size);
if (ret < 0)
fail("could not encrypt data: %s\n", gnutls_strerror(ret));
@@ -91,7 +93,7 @@ static void start(const char *name, int algo)
ret = gnutls_aead_cipher_decryptv2(ch,
iv.data, iv.size,
auth_iov, 2,
- iov, 2,
+ iov, 3,
tag, tag_size);
if (ret < 0)
fail("could not decrypt data: %s\n", gnutls_strerror(ret));
--
2.21.0