summaryrefslogtreecommitdiffstats
path: root/g10/cipher-aead.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2018-01-24 13:45:05 +0100
committerWerner Koch <wk@gnupg.org>2018-01-24 13:45:05 +0100
commitff1bdc23d9f1693c1add7c1fe8d218b7bf743e31 (patch)
treeb4d831af02681bd7cbf7531d9a1d3eb9cd39e8e0 /g10/cipher-aead.c
parentgpg: Rename a variable in decrypt-data for clarity. (diff)
downloadgnupg2-ff1bdc23d9f1693c1add7c1fe8d218b7bf743e31.tar.xz
gnupg2-ff1bdc23d9f1693c1add7c1fe8d218b7bf743e31.zip
gpg: Fix AEAD encryption for chunk sizes other than 64 KiB.
* g10/cipher-aead.c (do_flush): Init ERR. Fix remaining chunklen computation. (do_free): Add dummy encryption. Close the cipher handle. * g10/decrypt-data.c (aead_underflow): Rewrite. -- Until we have integrated test into the test suite extensive tests can also be done with a script like this: --8<---------------cut here---------------start------------->8--- #!/bin/sh set -e GPG="../g10/gpg --rfc4880bis --pinentry-mode=loopback" GPG="$GPG --passphrase abc --batch" MKTDATA="$HOME/b/gnupg-2.0/tools/mk-tdata" for chunksize in 6 7 12 13 14 30; do for count in $(seq 1 200) $(seq 8100 8200) \ $(seq 16350 16400) $(seq 20000 20100); do if [ ! -f "testfile-$count" ]; then $MKTDATA $count >"testfile-$count" fi echo "testing chunk size 2^$chunksize with $count bytes" $GPG --force-aead --aead-algo ocb --s2k-mode 0 --cipher AES -v -z 0 \ -c --chunk-size $chunksize \ <"testfile-$count" >"testfile-$count.gpg" 2>/dev/null $GPG -vd <"testfile-$count.gpg" >"testfile-$count.out" 2>/dev/null if ! cmp "testfile-$count" "testfile-$count.out"; then echo "FAILED comparing count $count" >&2 exit 1 fi done done echo All good --8<---------------cut here---------------end--------------->8--- Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'g10/cipher-aead.c')
-rw-r--r--g10/cipher-aead.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/g10/cipher-aead.c b/g10/cipher-aead.c
index 9cb57bdc6..573bb43fb 100644
--- a/g10/cipher-aead.c
+++ b/g10/cipher-aead.c
@@ -271,7 +271,7 @@ write_final_chunk (cipher_filter_context_t *cfx, iobuf_t a)
static gpg_error_t
do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
{
- gpg_error_t err;
+ gpg_error_t err = 0;
int newchunk = 0;
size_t n;
@@ -285,9 +285,9 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
else
n = cfx->bufsize - cfx->buflen;
- if (cfx->chunklen + n >= cfx->chunksize)
+ if (cfx->chunklen + cfx->buflen + n >= cfx->chunksize)
{
- size_t n1 = cfx->chunksize - cfx->chunklen;
+ size_t n1 = cfx->chunksize - (cfx->chunklen + cfx->buflen);
newchunk = 1;
if (DBG_FILTER)
log_debug ("chunksize %ju reached;"
@@ -305,8 +305,8 @@ do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
if (cfx->buflen == cfx->bufsize || newchunk)
{
if (DBG_FILTER)
- log_debug ("encrypting: buflen=%zu %s %p\n",
- cfx->buflen, newchunk?"(newchunk)":"", cfx->cipher_hd);
+ log_debug ("encrypting: buflen=%zu %s n=%zu\n",
+ cfx->buflen, newchunk?"(newchunk)":"", n);
if (newchunk)
gcry_cipher_final (cfx->cipher_hd);
if (!DBG_FILTER)
@@ -372,6 +372,9 @@ do_free (cipher_filter_context_t *cfx, iobuf_t a)
{
gpg_error_t err = 0;
+ if (DBG_FILTER)
+ log_debug ("do_free: buflen=%zu\n", cfx->buflen);
+
/* FIXME: Check what happens if we just wrote the last chunk and no
* more bytes were to encrypt. We should then not call finalize and
* write the auth tag again, right? May this at all happen? */
@@ -394,6 +397,8 @@ do_free (cipher_filter_context_t *cfx, iobuf_t a)
cfx->chunklen += cfx->buflen;
cfx->total += cfx->buflen;
}
+ else /* Dummy encryption. */
+ gcry_cipher_encrypt (cfx->cipher_hd, cfx->buffer, 0, NULL, 0);
/* Get and write the authentication tag. */
if (DBG_FILTER)
@@ -411,8 +416,8 @@ do_free (cipher_filter_context_t *cfx, iobuf_t a)
leave:
xfree (cfx->buffer);
cfx->buffer = NULL;
- /* gcry_cipher_close (cfx->cipher_hd); */
- /* cfx->cipher_hd = NULL; */
+ gcry_cipher_close (cfx->cipher_hd);
+ cfx->cipher_hd = NULL;
return err;
}