summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2018-02-01 20:27:33 +0100
committerNiels Möller <nisse@lysator.liu.se>2018-02-01 20:45:51 +0100
commit3919ca296ed152801514ac18663b0aff27a3a9db (patch)
treec154c2b78292159831c5636ea1452de4e8e36866
parent1af2ce835bad82f0f5df4bcde2b83abbf6f16352 (diff)
downloadnettle-3919ca296ed152801514ac18663b0aff27a3a9db.tar.gz
Generalize _ctr_crypt16, so it can be used also for gcm.
-rw-r--r--ChangeLog18
-rw-r--r--Makefile.in3
-rw-r--r--ctr-internal.h56
-rw-r--r--ctr.c77
-rw-r--r--ctr16.c106
5 files changed, 197 insertions, 63 deletions
diff --git a/ChangeLog b/ChangeLog
index 547fb590..4697be51 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2018-02-01 Niels Möller <nisse@lysator.liu.se>
+
+ Based on a patch contributed by Nikos Mavrogiannopoulos.
+ * ctr16.c (_ctr_crypt16): New file, renamed and generalized
+ function. New function pointer argument, used to fill a block with
+ counter values. Use nettle_block16 * as the type for the buffer to
+ be filled. Always process any final and partial block, and return
+ no value.
+ * ctr.c (ctr_crypt): ... previous, replaced, function.
+ (ctr_fill16): Updated to new argument type.
+ (ctr_crypt): Return immediately after using _ctr_crypt16.
+
+ * ctr-internal.h: New file, declaring _ctr_crypt16.
+ (nettle_fill16_func): New function typedef.
+
+ * Makefile.in (nettle_SOURCES): Added ctr16.c.
+ (DISTFILES): Added ctr-internal.h.
+
2018-01-30 Niels Möller <nisse@lysator.liu.se>
* Makefile.in (clean-here): Don't delete desdata.stamp.
diff --git a/Makefile.in b/Makefile.in
index 08d2208e..4444e8bd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -92,7 +92,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
chacha-crypt.c chacha-core-internal.c \
chacha-poly1305.c chacha-poly1305-meta.c \
chacha-set-key.c chacha-set-nonce.c \
- ctr.c des.c des3.c des-compat.c \
+ ctr.c ctr16.c des.c des3.c des-compat.c \
eax.c eax-aes128.c eax-aes128-meta.c \
gcm.c gcm-aes.c \
gcm-aes128.c gcm-aes128-meta.c \
@@ -225,6 +225,7 @@ DISTFILES = $(SOURCES) $(HEADERS) getopt.h getopt_int.h \
aes-internal.h camellia-internal.h serpent-internal.h \
cast128_sboxes.h desinfo.h desCode.h \
memxor-internal.h nettle-internal.h nettle-write.h \
+ ctr-internal.h \
gmp-glue.h ecc-internal.h fat-setup.h \
mini-gmp.h asm.m4 \
nettle.texinfo nettle.info nettle.html nettle.pdf sha-example.c
diff --git a/ctr-internal.h b/ctr-internal.h
new file mode 100644
index 00000000..d8bc1365
--- /dev/null
+++ b/ctr-internal.h
@@ -0,0 +1,56 @@
+/* ctr-internal.h
+
+ Copyright (C) 2018 Niels Möller
+
+ This file is part of GNU Nettle.
+
+ GNU Nettle is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+
+ GNU Nettle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see http://www.gnu.org/licenses/.
+*/
+
+#ifndef NETTLE_CTR_INTERNAL_H_INCLUDED
+#define NETTLE_CTR_INTERNAL_H_INCLUDED
+
+#include "nettle-types.h"
+
+/* Name mangling */
+#define _ctr_crypt16 _nettle_ctr_crypt16
+
+/* Size limit for temporary stack buffers. */
+#define CTR_BUFFER_LIMIT 512
+
+/* Fill BUFFER (n blocks) with incrementing CTR values. It would be
+ nice if CTR was always 64-bit aligned, but it isn't when called
+ from ctr_crypt. */
+typedef void
+nettle_fill16_func(uint8_t *ctr, size_t n, union nettle_block16 *buffer);
+
+void
+_ctr_crypt16(const void *ctx, nettle_cipher_func *f,
+ nettle_fill16_func *fill, uint8_t *ctr,
+ size_t length, uint8_t *dst,
+ const uint8_t *src);
+
+
+#endif /* NETTLE_CTR_INTERNAL_H_INCLUDED */
diff --git a/ctr.c b/ctr.c
index ee5b2888..c6601547 100644
--- a/ctr.c
+++ b/ctr.c
@@ -41,13 +41,11 @@
#include "ctr.h"
+#include "ctr-internal.h"
#include "macros.h"
#include "memxor.h"
#include "nettle-internal.h"
-/* Don't allocate any more space than this on the stack */
-#define CTR_BUFFER_LIMIT 512
-
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
static size_t
@@ -64,17 +62,19 @@ ctr_fill (size_t block_size, uint8_t *ctr, size_t length, uint8_t *buffer)
#if WORDS_BIGENDIAN
# define USE_CTR_CRYPT16 1
+static nettle_fill16_func ctr_fill16;
static void
-ctr_fill16(uint8_t *ctr, size_t blocks, uint64_t *buffer)
+ctr_fill16(uint8_t *ctr, size_t blocks, union nettle_block16 *buffer)
{
uint64_t hi, lo;
+ size_t i;
hi = READ_UINT64(ctr);
lo = READ_UINT64(ctr + 8);
- while (blocks-- > 0)
+ for (i = 0; i < blocks; i++)
{
- *buffer++ = hi;
- *buffer++ = lo;
+ buffer[i].u64[0] = hi;
+ buffer[i].u64[1] = lo;
hi += !(++lo);
}
WRITE_UINT64(ctr, hi);
@@ -83,18 +83,20 @@ ctr_fill16(uint8_t *ctr, size_t blocks, uint64_t *buffer)
#else /* !WORDS_BIGENDIAN */
# if HAVE_BUILTIN_BSWAP64
# define USE_CTR_CRYPT16 1
+static nettle_fill16_func ctr_fill16;
static void
-ctr_fill16(uint8_t *ctr, size_t blocks, uint64_t *buffer)
+ctr_fill16(uint8_t *ctr, size_t blocks, union nettle_block16 *buffer)
{
uint64_t hi, lo;
+ size_t i;
/* Read hi in native endianness */
hi = LE_READ_UINT64(ctr);
lo = READ_UINT64(ctr + 8);
- while (blocks-- > 0)
+ for (i = 0; i < blocks; i++)
{
- *buffer++ = hi;
- *buffer++ = __builtin_bswap64(lo);
+ buffer[i].u64[0] = hi;
+ buffer[i].u64[1] = __builtin_bswap64(lo);
if (!++lo)
hi = __builtin_bswap64(__builtin_bswap64(hi) + 1);
}
@@ -106,53 +108,6 @@ ctr_fill16(uint8_t *ctr, size_t blocks, uint64_t *buffer)
# endif
#endif /* !WORDS_BIGENDIAN */
-#if USE_CTR_CRYPT16
-static size_t
-ctr_crypt16(const void *ctx, nettle_cipher_func *f,
- uint8_t *ctr,
- size_t length, uint8_t *dst,
- const uint8_t *src)
-{
- if (dst != src && !((uintptr_t) dst % sizeof(uint64_t)))
- {
- size_t blocks = length / 16u;
- ctr_fill16 (ctr, blocks, (uint64_t *) dst);
- f(ctx, blocks * 16, dst, dst);
- memxor (dst, src, blocks * 16);
- return blocks * 16;
- }
- else
- {
- /* Construct an aligned buffer of consecutive counter values, of
- size at most CTR_BUFFER_LIMIT. */
- TMP_DECL(buffer, union nettle_block16, CTR_BUFFER_LIMIT / 16);
- size_t blocks = (length + 15) / 16u;
- size_t i;
- TMP_ALLOC(buffer, MIN(blocks, CTR_BUFFER_LIMIT / 16));
-
- for (i = 0; blocks >= CTR_BUFFER_LIMIT / 16;
- i += CTR_BUFFER_LIMIT, blocks -= CTR_BUFFER_LIMIT / 16)
- {
- ctr_fill16 (ctr, CTR_BUFFER_LIMIT / 16, buffer->u64);
- f(ctx, CTR_BUFFER_LIMIT, buffer->b, buffer->b);
- if (length - i < CTR_BUFFER_LIMIT)
- goto done;
- memxor3 (dst, src, buffer->b, CTR_BUFFER_LIMIT);
- }
-
- if (blocks > 0)
- {
- assert (length - i < CTR_BUFFER_LIMIT);
- ctr_fill16 (ctr, blocks, buffer->u64);
- f(ctx, blocks * 16, buffer->b, buffer->b);
- done:
- memxor3 (dst + i, src + i, buffer->b, length - i);
- }
- return length;
- }
-}
-#endif /* USE_CTR_CRYPT16 */
-
void
ctr_crypt(const void *ctx, nettle_cipher_func *f,
size_t block_size, uint8_t *ctr,
@@ -162,10 +117,8 @@ ctr_crypt(const void *ctx, nettle_cipher_func *f,
#if USE_CTR_CRYPT16
if (block_size == 16)
{
- size_t done = ctr_crypt16(ctx, f, ctr, length, dst, src);
- length -= done;
- src += done;
- dst += done;
+ _ctr_crypt16(ctx, f, ctr_fill16, ctr, length, dst, src);
+ return;
}
#endif
diff --git a/ctr16.c b/ctr16.c
new file mode 100644
index 00000000..60418e8b
--- /dev/null
+++ b/ctr16.c
@@ -0,0 +1,106 @@
+/* ctr16.c
+
+ Cipher counter mode, optimized for 16-byte blocks.
+
+ Copyright (C) 2005-2018 Niels Möller
+ Copyright (C) 2018 Red Hat, Inc.
+
+ This file is part of GNU Nettle.
+
+ GNU Nettle is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+
+ GNU Nettle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <assert.h>
+
+#include "ctr.h"
+
+#include "ctr-internal.h"
+#include "memxor.h"
+#include "nettle-internal.h"
+
+#define MIN(a,b) (((a) < (b)) ? (a) : (b))
+
+void
+_ctr_crypt16(const void *ctx, nettle_cipher_func *f,
+ nettle_fill16_func *fill, uint8_t *ctr,
+ size_t length, uint8_t *dst,
+ const uint8_t *src)
+{
+ if (dst != src && !((uintptr_t) dst % sizeof(uint64_t)))
+ {
+ size_t blocks = length / 16u;
+ size_t done;
+ fill (ctr, blocks, (union nettle_block16 *) dst);
+
+ done = blocks * 16;
+ f(ctx, done, dst, dst);
+ memxor (dst, src, done);
+
+ length -= done;
+ if (length > 0)
+ { /* Left-over partial block */
+ union nettle_block16 block;
+ dst += done;
+ src += done;
+ assert (length < 16);
+ /* Use fill, to update ctr value in the same way in all cases. */
+ fill (ctr, 1, &block);
+ f (ctx, 16, block.b, block.b);
+ memxor3 (dst, src, block.b, length);
+ }
+ }
+ else
+ {
+ /* Construct an aligned buffer of consecutive counter values, of
+ size at most CTR_BUFFER_LIMIT. */
+ TMP_DECL(buffer, union nettle_block16, CTR_BUFFER_LIMIT / 16);
+ size_t blocks = (length + 15) / 16u;
+ size_t i;
+ TMP_ALLOC(buffer, MIN(blocks, CTR_BUFFER_LIMIT / 16));
+
+ for (i = 0; blocks >= CTR_BUFFER_LIMIT / 16;
+ i += CTR_BUFFER_LIMIT, blocks -= CTR_BUFFER_LIMIT / 16)
+ {
+ fill (ctr, CTR_BUFFER_LIMIT / 16, buffer);
+ f(ctx, CTR_BUFFER_LIMIT, buffer->b, buffer->b);
+ if (length - i < CTR_BUFFER_LIMIT)
+ goto done;
+ memxor3 (dst, src, buffer->b, CTR_BUFFER_LIMIT);
+ }
+
+ if (blocks > 0)
+ {
+ assert (length - i < CTR_BUFFER_LIMIT);
+ fill (ctr, blocks, buffer);
+ f(ctx, blocks * 16, buffer->b, buffer->b);
+ done:
+ memxor3 (dst + i, src + i, buffer->b, length - i);
+ }
+ }
+}