From c36c0f4e22fad4374c05f6e526e1fb34d0457ee2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> Date: Tue, 4 Dec 2012 20:50:00 +0100 Subject: [PATCH] Fixed ctr_crypt zero-length bug, reported by Tim Kosse. --- ChangeLog | 11 +++++++++++ ctr.c | 20 ++++++++++---------- testsuite/ctr-test.c | 7 +++++++ testsuite/testutils.c | 21 ++++++++++++++++++++- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index c1373f1e..93390291 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2012-12-04 Niels Möller <nisse@lysator.liu.se> + + * ctr.c (ctr_crypt): Fix bug reported by Tim Kosse. Don't + increment the counter when length is zero (was broken for the + in-place case). + + * testsuite/ctr-test.c (test_main): Added test with zero-length + data. + * testsuite/testutils.c (test_cipher_ctr): Check the ctr value + after encrypt and decrypt. + 2012-12-03 Niels Möller <nisse@lysator.liu.se> * sha3-permute.c (sha3_permute): Optimized, to reduce number of diff --git a/ctr.c b/ctr.c index 49cfa2a9..6b970305 100644 --- a/ctr.c +++ b/ctr.c @@ -82,16 +82,7 @@ ctr_crypt(void *ctx, nettle_crypt_func *f, } else { - if (length <= block_size) - { - TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE); - TMP_ALLOC(buffer, block_size); - - f(ctx, block_size, buffer, ctr); - INCREMENT(block_size, ctr); - memxor3(dst, src, buffer, length); - } - else + if (length > block_size) { TMP_DECL(buffer, uint8_t, NBLOCKS * NETTLE_MAX_CIPHER_BLOCK_SIZE); unsigned chunk = NBLOCKS * block_size; @@ -124,5 +115,14 @@ ctr_crypt(void *ctx, nettle_crypt_func *f, memxor3(dst, src, buffer, length); } } + else if (length > 0) + { + TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE); + TMP_ALLOC(buffer, block_size); + + f(ctx, block_size, buffer, ctr); + INCREMENT(block_size, ctr); + memxor3(dst, src, buffer, length); + } } } diff --git a/testsuite/ctr-test.c b/testsuite/ctr-test.c index b47b8aef..be312529 100644 --- a/testsuite/ctr-test.c +++ b/testsuite/ctr-test.c @@ -12,6 +12,13 @@ test_main(void) * F.5 CTR Example Vectors */ + /* Zero-length data. Exposes bug reported by Tim Kosse, where + ctr_crypt increment the ctr when it shouldn't. */ + test_cipher_ctr(&nettle_aes128, + SHEX("2b7e151628aed2a6abf7158809cf4f3c"), + SHEX(""), SHEX(""), + SHEX("f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff")); + /* F.5.1 CTR-AES128.Encrypt */ test_cipher_ctr(&nettle_aes128, SHEX("2b7e151628aed2a6abf7158809cf4f3c"), diff --git a/testsuite/testutils.c b/testsuite/testutils.c index 78cd0d45..028a4bd0 100644 --- a/testsuite/testutils.c +++ b/testsuite/testutils.c @@ -5,6 +5,7 @@ #include "cbc.h" #include "ctr.h" #include "knuth-lfib.h" +#include "macros.h" #include "nettle-internal.h" #include <ctype.h> @@ -308,13 +309,26 @@ test_cipher_ctr(const struct nettle_cipher *cipher, void *ctx = xalloc(cipher->context_size); uint8_t *data; uint8_t *ctr = xalloc(cipher->block_size); + uint8_t *octr = xalloc(cipher->block_size); unsigned length; + unsigned low, nblocks; ASSERT (cleartext->length == ciphertext->length); length = cleartext->length; ASSERT (ictr->length == cipher->block_size); - + + /* Compute expected counter value after the operation. */ + nblocks = (length + cipher->block_size - 1) / cipher->block_size; + ASSERT (nblocks < 0x100); + + memcpy (octr, ictr->data, cipher->block_size - 1); + low = ictr->data[cipher->block_size - 1] + nblocks; + octr[cipher->block_size - 1] = low; + + if (low >= 0x100) + INCREMENT (cipher->block_size - 1, octr); + data = xalloc(length); cipher->set_encrypt_key(ctx, key->length, key->data); @@ -336,6 +350,8 @@ test_cipher_ctr(const struct nettle_cipher *cipher, FAIL(); } + ASSERT (MEMEQ (cipher->block_size, ctr, octr)); + memcpy(ctr, ictr->data, cipher->block_size); ctr_crypt(ctx, cipher->encrypt, @@ -354,8 +370,11 @@ test_cipher_ctr(const struct nettle_cipher *cipher, FAIL(); } + ASSERT (MEMEQ (cipher->block_size, ctr, octr)); + free(ctx); free(data); + free(octr); free(ctr); } -- GitLab