On Wed, 2019-04-17 at 11:37 +0200, Nikos Mavrogiannopoulos wrote:
> On Sun, 2019-04-14 at 09:33 +0200, Niels Möller wrote:
> > + assert(nc->context_size <= NETTLE_MAX_CIPHER16_CONTEXT_SIZE);
> > > +
> > > + /* ensure we have enough size of context plus any padding size
> > > */
> > > + CMAC128_SET_KEY(&ctx, nc->set_encrypt_key, nc->encrypt, s2vk);
> > > +
> > > + if (nlength == 0 && alength == 0) {
> > > + CMAC128_UPDATE(&ctx, nc->encrypt, 16, const_one);
> > > + CMAC128_DIGEST(&ctx, nc->encrypt, 16, v);
> > > + return;
> > > + }
> >
> > Shouldn't the plaintext, plength, pdata, still be processed in this
> > case?
>
> Right, there should be an and plength == 0 as well. I've added an two
> additional test cases to check these cases, and the case where
> everything is zero, doesn't seem to interoperate with two libs I
> tried.
>
> Hopefully it is issue of this code.
>
> https://github.com/miscreant/miscreant/issues/194
> https://github.com/dfoxfranke/libaes_siv/issues/14
Based on the discussions on these bugs, I think it makes sense to
strictly restrict the implementation to the common interoperable
conventions (AEAD). That is, always assume (aad, nonce, plaintext),
even if empty. As such I've updated the test vectors to include non
empty nonce and tested them against libaes_siv.
The attached bugs update this implementation, and an additional patch
adds a "make distcheck" check to CI. That ensures that any missing or
incorrectly added in Makefile files are caught by the CI.
regards,
Nikos
From 8dfd9653109844dc7253b45af1815a0492b25c2a Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Sat, 20 Jan 2018 10:36:05 +0100
Subject: [PATCH 3/3] Added support for AES_SIV_CMAC_256 and AES_SIV_CMAC_512
This AEAD algorithm provides a way to make nonce-reuse a not critical
issue. That is particular useful to stateless servers that cannot ensure
that the nonce will not repeat. This cipher is used by
draft-ietf-ntp-using-nts-for-ntp-17.
Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
---
Makefile.in | 4 +-
cmac-internal.h | 54 ++++++
cmac.c | 15 +-
nettle-internal.h | 2 +
nettle.texinfo | 94 +++++++++-
siv-aes128-cmac.c | 75 ++++++++
siv-aes256-cmac.c | 75 ++++++++
siv-cmac.c | 186 ++++++++++++++++++++
siv-cmac.h | 131 ++++++++++++++
testsuite/.gitignore | 2 +
testsuite/.test-rules.make | 3 +
testsuite/Makefile.in | 2 +-
testsuite/siv-test.c | 347 +++++++++++++++++++++++++++++++++++++
testsuite/testutils.h | 13 ++
14 files changed, 992 insertions(+), 11 deletions(-)
create mode 100644 cmac-internal.h
create mode 100644 siv-aes128-cmac.c
create mode 100644 siv-aes256-cmac.c
create mode 100644 siv-cmac.c
create mode 100644 siv-cmac.h
create mode 100644 testsuite/siv-test.c
diff --git a/Makefile.in b/Makefile.in
index 440de9f7..962a6b73 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -89,6 +89,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
camellia256-meta.c \
cast128.c cast128-meta.c cbc.c \
ccm.c ccm-aes128.c ccm-aes192.c ccm-aes256.c cfb.c \
+ siv-cmac.c siv-aes128-cmac.c siv-aes256-cmac.c \
cnd-memcpy.c \
chacha-crypt.c chacha-core-internal.c \
chacha-poly1305.c chacha-poly1305-meta.c \
@@ -198,7 +199,8 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
gcm.h gosthash94.h hmac.h \
knuth-lfib.h hkdf.h \
macros.h \
- cmac.h \
+ cmac.h cmac-internal.h \
+ siv-cmac.h \
md2.h md4.h \
md5.h md5-compat.h \
memops.h memxor.h \
diff --git a/cmac-internal.h b/cmac-internal.h
new file mode 100644
index 00000000..789588e6
--- /dev/null
+++ b/cmac-internal.h
@@ -0,0 +1,54 @@
+/* cmac.h
+
+ CMAC mode internal functions
+
+ Copyright (C) 2017 Red Hat, Inc.
+
+ Contributed by Nikos Mavrogiannopoulos
+
+ 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_CMAC_INTERNAL_H_INCLUDED
+#define NETTLE_CMAC_INTERNAL_H_INCLUDED
+
+#include "cmac.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define _cmac128_block_mulx _nettle_cmac128_block_mulx
+
+void _cmac128_block_mulx(union nettle_block16 *out,
+ const union nettle_block16 *in);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CMAC_INTERNAL_H_INCLUDED */
diff --git a/cmac.c b/cmac.c
index 01fee79e..8be1cca4 100644
--- a/cmac.c
+++ b/cmac.c
@@ -44,13 +44,13 @@
#include "memxor.h"
#include "nettle-internal.h"
+#include "cmac-internal.h"
#include "macros.h"
/* shift one and XOR with 0x87. */
#if WORDS_BIGENDIAN
-static void
-block_mulx(union nettle_block16 *dst,
- const union nettle_block16 *src)
+void _cmac128_block_mulx(union nettle_block16 *dst,
+ const union nettle_block16 *src)
{
uint64_t carry = src->u64[0] >> 63;
dst->u64[0] = (src->u64[0] << 1) | (src->u64[1] >> 63);
@@ -59,9 +59,8 @@ block_mulx(union nettle_block16 *dst,
#else /* !WORDS_BIGENDIAN */
#define LE_SHIFT(x) ((((x) & 0x7f7f7f7f7f7f7f7f) << 1) | \
(((x) & 0x8080808080808080) >> 15))
-static void
-block_mulx(union nettle_block16 *dst,
- const union nettle_block16 *src)
+void _cmac128_block_mulx(union nettle_block16 *dst,
+ const union nettle_block16 *src)
{
uint64_t carry = (src->u64[0] & 0x80) >> 7;
dst->u64[0] = LE_SHIFT(src->u64[0]) | ((src->u64[1] & 0x80) << 49);
@@ -83,8 +82,8 @@ cmac128_set_key(struct cmac128_ctx *ctx, const void *cipher,
/* step 1 - generate subkeys k1 and k2 */
encrypt(cipher, 16, L->b, const_zero.b);
- block_mulx(&ctx->K1, L);
- block_mulx(&ctx->K2, &ctx->K1);
+ _cmac128_block_mulx(&ctx->K1, L);
+ _cmac128_block_mulx(&ctx->K2, &ctx->K1);
}
#define MIN(x,y) ((x)<(y)?(x):(y))
diff --git a/nettle-internal.h b/nettle-internal.h
index dc379f1f..2937a710 100644
--- a/nettle-internal.h
+++ b/nettle-internal.h
@@ -78,6 +78,8 @@
#define NETTLE_MAX_HASH_CONTEXT_SIZE (sizeof(struct sha3_224_ctx))
#define NETTLE_MAX_SEXP_ASSOC 17
#define NETTLE_MAX_CIPHER_BLOCK_SIZE 32
+/* maximum context size of 128-bit block ciphers */
+#define NETTLE_MAX_CIPHER16_CONTEXT_SIZE (sizeof(struct aes256_ctx))
/* Doesn't quite fit with the other algorithms, because of the weak
* keys. Weak keys are not reported, the functions will simply crash
diff --git a/nettle.texinfo b/nettle.texinfo
index 596c7098..b83c13d0 100644
--- a/nettle.texinfo
+++ b/nettle.texinfo
@@ -97,6 +97,7 @@ Cipher modes
* CFB and CFB8::
* GCM::
* CCM::
+* SIV-CMAC::
Keyed Hash Functions
@@ -2565,6 +2566,7 @@ more adventurous alternative, in particular if performance is important.
* GCM::
* CCM::
* ChaCha-Poly1305::
+* SIV-CMAC::
* nettle_aead abstraction::
@end menu
@@ -3212,7 +3214,7 @@ These are identical to @code{ccm_encrypt_message} and @code{ccm_decrypt_message}
except that @var{cipher} and @var{f} are replaced with a context structure.
@end deftypefun
-@node ChaCha-Poly1305, nettle_aead abstraction, CCM, Authenticated encryption
+@node ChaCha-Poly1305, SIV-CMAC, CCM, Authenticated encryption
@comment node-name, next, previous, up
@subsection ChaCha-Poly1305
@@ -3295,6 +3297,96 @@ smaller than @code{CHACHA_POLY1305_DIGEST_SIZE}, only the first
@var{length} octets of the digest are written.
@end deftypefun
+@node SIV-CMAC, nettle_aead abstraction, ChaCha-Poly1305, Authenticated encryption
+@comment node-name, next, previous, up
+@subsection Counter with CBC-MAC mode
+
+@cindex SIV mode
+@cindex SIV-CMAC mode
+
+@acronym{SIV-CMAC} mode is a combination of counter mode with message
+authentication based on @acronym{CMAC}. Unlike other counter @acronym{AEAD}
+modes, it provides protection against accidental nonce misuse, making it
+a good choice for stateless-servers that cannot ensure nonce uniqueness.
+It is constructed on top of a block cipher which must have a block size of
+128 bits. Nettle's support for @acronym{SIV-CMAC} consists of
+a message encryption and authentication interface, for
+@acronym{SIV-CMAC} using AES as the underlying block cipher.
+When a nonce is re-used with this mode, message authenticity is retained
+however an attacker can determine whether the same plaintext was protected
+with the two messages sharing the nonce.
+These interfaces are defined in @file{<nettle/siv-cmac.h>}.
+
+Unlike other @acronym{AEAD} mode in @acronym{SIV-CMAC} the initialization
+vector serves as the tag. That means that in the generated ciphertext
+the tag precedes the ciphertext.
+
+Note also, that the @acronym{SIV-CMAC} algorithm introduces the notion
+of authenticated data which consist of multiple components. For example
+with @acronym{SIV-CMAC} the authentication tag of data @code{X} followed
+by @code{Y}, is different than the concatenated data @code{X || Y}. The interfaces
+described below follow the @acronym{AEAD} paradigm and do not allow access
+to this feature and also require the use of a non-zero tag.
+
+@subsubsection General interface
+
+@defvr Constant SIV_BLOCK_SIZE
+@acronym{SIV-CMAC}'s block size, 16.
+@end defvr
+
+@defvr Constant SIV_DIGEST_SIZE
+Size of the @acronym{SIV-CMAC} digest or initialization vector, 16.
+@end defvr
+
+@defvr Constant SIV_MIN_NONCE_SIZE
+The the minimumsizes for an @acronym{SIV-CMAC} nonce, 0
+@end defvr
+
+@subsubsection @acronym{SIV-CMAC}-@acronym{AES} interface
+
+The @acronym{AES} @acronym{SIV-CMAC} functions provide an API for using
+@acronym{SIV-CMAC} mode with the @acronym{AES} block ciphers. The parameters
+all have the same meaning as the general and message interfaces, except
+that the @var{cipher}, @var{f}, and @var{ctx} parameters are replaced
+with an @acronym{AES} context structure, and a set-key function must be
+called before using any of the other functions in this interface.
+
+@deftp {Context struct} {struct siv_aes128_cmac_ctx}
+Holds state corresponding to a particular message encrypted using the
+AES-128 block cipher.
+@end deftp
+
+@deftp {Context struct} {struct siv_aes256_cmac_ctx}
+Holds state corresponding to a particular message encrypted using the
+AES-256 block cipher.
+@end deftp
+
+@deftypefun void siv_aes128_cmac_set_key (struct siv_aes128_cmac_ctx *@var{ctx}, const uint8_t *@var{key})
+@deftypefunx void siv_aes256_cmac_set_key (struct siv_aes256_cmac_ctx *@var{ctx}, const uint8_t *@var{key})
+Initializes the encryption key for the AES block cipher. One of these
+functions must be called before any of the other functions in the
+@acronym{AES} @acronym{SIV-CMAC} interface.
+@end deftypefun
+
+@deftypefun void siv_aes128_cmac_encrypt_message (struct siv_aes128_cmac_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx void siv_aes256_cmac_encrypt_message (struct siv_aes256_cmac_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{clength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+Computes the message digest from the @var{adata} and @var{src}
+parameters, encrypts the plaintext from @var{src}, prepends the
+initialization vector to the ciphertext and outputs it to @var{dst}.
+The @var{clength} variable must be equal to the length of @var{src}
+plus @code{SIV_DIGEST_SIZE}.
+
+@end deftypefun
+
+@deftypefun int siv_aes128_cmac_decrypt_message (struct siv_aes128_cmac_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{mlength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+@deftypefunx int siv_aes256_cmac_decrypt_message (struct siv_aes128_cmac_ctx *@var{ctx}, size_t @var{nlength}, const uint8_t *@var{nonce}, size_t @var{alength}, const uint8_t *@var{adata}, size_t @var{mlength}, uint8_t *@var{dst}, const uint8_t *@var{src})
+Decrypts the ciphertext from @var{src}, outputs the plaintext to
+@var{dst}, recalculates the initialization vector from @var{adata} and the
+plaintext. If the values of the received and calculated initialization vector
+are equal, this will return 1 indicating a valid and authenticated
+message. Otherwise, this function will return zero.
+@end deftypefun
+
@node nettle_aead abstraction, , ChaCha-Poly1305, Authenticated encryption
@comment node-name, next, previous, up
@subsection The @code{struct nettle_aead} abstraction
diff --git a/siv-aes128-cmac.c b/siv-aes128-cmac.c
new file mode 100644
index 00000000..793279d1
--- /dev/null
+++ b/siv-aes128-cmac.c
@@ -0,0 +1,75 @@
+/* siv-aes128.c
+
+ AES-SIV, RFC5297
+
+ Copyright (C) 2017 Nikos Mavrogiannopoulos
+
+ 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 <string.h>
+
+#include "aes.h"
+#include "siv-cmac.h"
+#include "cmac.h"
+#include "ctr.h"
+#include "memxor.h"
+#include "memops.h"
+#include "cmac-internal.h"
+
+void
+siv_aes128_cmac_set_key(struct siv_aes128_cmac_ctx *ctx, const uint8_t *key)
+{
+ siv_cmac_set_key(&ctx->siv_cmac, &ctx->siv_cipher, &nettle_aes128, key);
+}
+
+void
+siv_aes128_cmac_encrypt_message(struct siv_aes128_cmac_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ siv_cmac_encrypt_message(&ctx->siv_cmac, &nettle_aes128, &ctx->siv_cipher,
+ nlength, nonce, alength, adata,
+ clength, dst, src);
+}
+
+int
+siv_aes128_cmac_decrypt_message(struct siv_aes128_cmac_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t mlength, uint8_t *dst, const uint8_t *src)
+{
+ return siv_cmac_decrypt_message(&ctx->siv_cmac, &nettle_aes128, &ctx->siv_cipher,
+ nlength, nonce, alength, adata,
+ mlength, dst, src);
+}
diff --git a/siv-aes256-cmac.c b/siv-aes256-cmac.c
new file mode 100644
index 00000000..61cd1163
--- /dev/null
+++ b/siv-aes256-cmac.c
@@ -0,0 +1,75 @@
+/* siv-aes128.c
+
+ AES-SIV, RFC5297
+
+ Copyright (C) 2017 Nikos Mavrogiannopoulos
+
+ 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 <string.h>
+
+#include "aes.h"
+#include "siv-cmac.h"
+#include "cmac.h"
+#include "ctr.h"
+#include "memxor.h"
+#include "memops.h"
+#include "cmac-internal.h"
+
+void
+siv_aes256_cmac_set_key(struct siv_aes256_cmac_ctx *ctx, const uint8_t *key)
+{
+ siv_cmac_set_key(&ctx->siv_cmac, &ctx->siv_cipher, &nettle_aes256, key);
+}
+
+void
+siv_aes256_cmac_encrypt_message(struct siv_aes256_cmac_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ siv_cmac_encrypt_message(&ctx->siv_cmac, &nettle_aes256, &ctx->siv_cipher,
+ nlength, nonce, alength, adata,
+ clength, dst, src);
+}
+
+int
+siv_aes256_cmac_decrypt_message(struct siv_aes256_cmac_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t mlength, uint8_t *dst, const uint8_t *src)
+{
+ return siv_cmac_decrypt_message(&ctx->siv_cmac, &nettle_aes256, &ctx->siv_cipher,
+ nlength, nonce, alength, adata,
+ mlength, dst, src);
+}
diff --git a/siv-cmac.c b/siv-cmac.c
new file mode 100644
index 00000000..f440769f
--- /dev/null
+++ b/siv-cmac.c
@@ -0,0 +1,186 @@
+/* siv-cmac.c
+
+ SIV-CMAC, RFC5297
+
+ Copyright (C) 2017 Nikos Mavrogiannopoulos
+
+ 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 <string.h>
+
+#include "aes.h"
+#include "siv-cmac.h"
+#include "cmac.h"
+#include "ctr.h"
+#include "memxor.h"
+#include "memops.h"
+#include "cmac-internal.h"
+#include "nettle-internal.h"
+
+/* This is only to allow the CMAC macros to expand in
+ * _siv_s2v */
+struct cmac128_syn {
+ struct cmac128_ctx ctx;
+ union {
+ uint64_t pad1[2]; /* to force a good alignment */
+ uint8_t pad[NETTLE_MAX_CIPHER16_CONTEXT_SIZE+16];
+ } cipher;
+};
+
+/* This is an implementation of S2V for the AEAD case where
+ * vectors if zero, are considered as S empty components */
+static
+void _siv_s2v(const struct nettle_cipher *nc,
+ struct cmac128_syn *ctx,
+ size_t alength, const uint8_t *adata,
+ size_t nlength, const uint8_t *nonce,
+ size_t plength, const uint8_t *pdata,
+ uint8_t *v)
+{
+ union nettle_block16 D, S, T;
+ static const union nettle_block16 const_zero = { .b = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ };
+
+ assert(nc->context_size <= NETTLE_MAX_CIPHER16_CONTEXT_SIZE);
+
+ /* the only unambiguous mode of this cipher is when a nonce
+ * is provided in AEAD mode. */
+ assert(nlength != 0);
+
+ CMAC128_UPDATE(ctx, nc->encrypt, 16, const_zero.b);
+ CMAC128_DIGEST(ctx, nc->encrypt, 16, D.b);
+
+ _cmac128_block_mulx(&D, &D);
+ CMAC128_UPDATE(ctx, nc->encrypt, alength, adata);
+ CMAC128_DIGEST(ctx, nc->encrypt, 16, S.b);
+ memxor(D.b, S.b, 16);
+
+ _cmac128_block_mulx(&D, &D);
+ CMAC128_UPDATE(ctx, nc->encrypt, nlength, nonce);
+ CMAC128_DIGEST(ctx, nc->encrypt, 16, S.b);
+ memxor(D.b, S.b, 16);
+
+ /* Sn */
+ if (plength >= 16) {
+ CMAC128_UPDATE(ctx, nc->encrypt, plength-16, pdata);
+
+ pdata += plength-16;
+
+ memxor3(T.b, pdata, D.b, 16);
+ } else {
+ union nettle_block16 pad;
+
+ _cmac128_block_mulx(&T, &D);
+ memcpy(pad.b, pdata, plength);
+ pad.b[plength] = 0x80;
+ if (plength+1 < 16)
+ memset(&pad.b[plength+1], 0, 16-plength-1);
+
+ memxor(T.b, pad.b, 16);
+ }
+
+ CMAC128_UPDATE(ctx, nc->encrypt, 16, T.b);
+ CMAC128_DIGEST(ctx, nc->encrypt, 16, v);
+}
+
+void
+siv_cmac_set_key(void *_ctx, void *cipher,
+ const struct nettle_cipher *nc,
+ const uint8_t *key)
+{
+ /* We rely on the fact that the siv_cmac member of the context
+ * is first in the context provided */
+ struct cmac128_syn *ctx = _ctx;
+
+ assert(nc->key_size <= SIV_MAX_KEY_SIZE/2);
+
+ CMAC128_SET_KEY(ctx, nc->set_encrypt_key, nc->encrypt, key);
+ nc->set_encrypt_key(cipher, key+nc->key_size);
+}
+
+void
+siv_cmac_encrypt_message(void *ctx,
+ const struct nettle_cipher *nc,
+ const void *cipher,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t clength, uint8_t *dst, const uint8_t *src)
+{
+ union nettle_block16 siv;
+ size_t slength;
+
+ assert(clength >= SIV_DIGEST_SIZE);
+ slength = clength - SIV_DIGEST_SIZE;
+
+ /* create CTR nonce */
+ _siv_s2v(nc,
+ ctx, alength, adata,
+ nlength, nonce, slength, src, siv.b);
+
+ memcpy(dst, siv.b, SIV_DIGEST_SIZE);
+ siv.b[8] &= ~0x80;
+ siv.b[12] &= ~0x80;
+
+ ctr_crypt(cipher, nc->encrypt, AES_BLOCK_SIZE, siv.b, slength, dst+SIV_DIGEST_SIZE, src);
+}
+
+int
+siv_cmac_decrypt_message(void *ctx,
+ const struct nettle_cipher *nc,
+ const void *cipher,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t mlength, uint8_t *dst, const uint8_t *src)
+{
+ union nettle_block16 siv;
+ union nettle_block16 ctr;
+
+ assert(mlength >= SIV_DIGEST_SIZE);
+
+ memcpy(ctr.b, src, SIV_DIGEST_SIZE);
+ ctr.b[8] &= ~0x80;
+ ctr.b[12] &= ~0x80;
+
+ ctr_crypt(cipher, nc->encrypt, AES_BLOCK_SIZE, ctr.b,
+ mlength-SIV_DIGEST_SIZE, dst, src+SIV_DIGEST_SIZE);
+
+ /* create CTR nonce */
+ _siv_s2v(nc,
+ ctx, alength, adata,
+ nlength, nonce, mlength-SIV_DIGEST_SIZE, dst, siv.b);
+
+ return memeql_sec(siv.b, src, SIV_DIGEST_SIZE);
+}
+
diff --git a/siv-cmac.h b/siv-cmac.h
new file mode 100644
index 00000000..ffbe4623
--- /dev/null
+++ b/siv-cmac.h
@@ -0,0 +1,131 @@
+/* siv.h
+
+ AES-SIV, RFC5297
+
+ Copyright (C) 2017 Nikos Mavrogiannopoulos
+
+ 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_SIV_H_INCLUDED
+#define NETTLE_SIV_H_INCLUDED
+
+#include "nettle-types.h"
+#include "nettle-meta.h"
+#include "cmac.h"
+#include "aes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Name mangling */
+#define siv_cmac_set_key nettle_siv_cmac_set_key
+#define siv_cmac_encrypt_message nettle_siv_cmac_encrypt_message
+#define siv_cmac_decrypt_message nettle_siv_cmac_decrypt_message
+#define siv_aes128_cmac_set_key nettle_siv_aes128_cmac_set_key
+#define siv_aes128_cmac_encrypt_message nettle_siv_aes128_cmac_encrypt_message
+#define siv_aes128_cmac_decrypt_message nettle_siv_aes128_cmac_decrypt_message
+#define siv_aes256_cmac_set_key nettle_siv_aes256_cmac_set_key
+#define siv_aes256_cmac_encrypt_message nettle_siv_aes256_cmac_encrypt_message
+#define siv_aes256_cmac_decrypt_message nettle_siv_aes256_cmac_decrypt_message
+
+/* For SIV, the block size of the block cipher shall be 128 bits. */
+#define SIV_BLOCK_SIZE 16
+#define SIV_DIGEST_SIZE 16
+#define SIV_MIN_NONCE_SIZE 0
+#define SIV_MAX_KEY_SIZE (AES_MAX_KEY_SIZE*2)
+
+void
+siv_cmac_set_key(void *ctx, void *cipher,
+ const struct nettle_cipher *nc,
+ const uint8_t *key);
+
+void
+siv_cmac_encrypt_message(void *ctx,
+ const struct nettle_cipher *nc,
+ const void *cipher,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+int
+siv_cmac_decrypt_message(void *ctx,
+ const struct nettle_cipher *nc,
+ const void *cipher,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t mlength, uint8_t *dst, const uint8_t *src);
+
+/*
+ * SIV mode requires the aad and plaintext when building the IV, which
+ * prevents streaming processing and it incompatible with the AEAD API.
+ */
+
+#define SIV_CMAC_CTX(type) { struct CMAC128_CTX(type) siv_cmac; type siv_cipher; }
+
+/* AES_SIV_CMAC_256 */
+struct siv_aes128_cmac_ctx SIV_CMAC_CTX(struct aes128_ctx);
+
+void
+siv_aes128_cmac_set_key(struct siv_aes128_cmac_ctx *ctx, const uint8_t *key);
+
+void
+siv_aes128_cmac_encrypt_message(struct siv_aes128_cmac_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+int
+siv_aes128_cmac_decrypt_message(struct siv_aes128_cmac_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t mlength, uint8_t *dst, const uint8_t *src);
+
+/* AES_SIV_CMAC_512 */
+struct siv_aes256_cmac_ctx SIV_CMAC_CTX(struct aes256_ctx);
+
+void
+siv_aes256_cmac_set_key(struct siv_aes256_cmac_ctx *ctx, const uint8_t *key);
+
+void
+siv_aes256_cmac_encrypt_message(struct siv_aes256_cmac_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+int
+siv_aes256_cmac_decrypt_message(struct siv_aes256_cmac_ctx *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t mlength, uint8_t *dst, const uint8_t *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_SIV_H_INCLUDED */
diff --git a/testsuite/.gitignore b/testsuite/.gitignore
index c3fc5c11..2a0d87ac 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -96,6 +96,8 @@
/version-test
/yarrow-test
/xts-test
+/cmac-test
+/siv-test
/test.in
/test1.out
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index 6eee6e22..f827175e 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -136,6 +136,9 @@ ccm-test$(EXEEXT): ccm-test.$(OBJEXT)
cmac-test$(EXEEXT): cmac-test.$(OBJEXT)
$(LINK) cmac-test.$(OBJEXT) $(TEST_OBJS) -o cmac-test$(EXEEXT)
+siv-test$(EXEEXT): siv-test.$(OBJEXT)
+ $(LINK) siv-test.$(OBJEXT) $(TEST_OBJS) -o siv-test$(EXEEXT)
+
poly1305-test$(EXEEXT): poly1305-test.$(OBJEXT)
$(LINK) poly1305-test.$(OBJEXT) $(TEST_OBJS) -o poly1305-test$(EXEEXT)
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index 287c4f75..1bd42ffa 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -27,7 +27,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
serpent-test.c twofish-test.c version-test.c \
knuth-lfib-test.c \
cbc-test.c cfb-test.c ctr-test.c gcm-test.c eax-test.c ccm-test.c \
- cmac-test.c \
+ cmac-test.c siv-test.c \
poly1305-test.c chacha-poly1305-test.c \
hmac-test.c umac-test.c \
meta-hash-test.c meta-cipher-test.c\
diff --git a/testsuite/siv-test.c b/testsuite/siv-test.c
new file mode 100644
index 00000000..0f77b4d5
--- /dev/null
+++ b/testsuite/siv-test.c
@@ -0,0 +1,347 @@
+/* siv-test.c
+
+ Self-test and vectors for AES-SIV mode ciphers
+
+ Copyright (C) 2018 Nikos Mavrogiannopoulos
+
+ 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/.
+*/
+
+/* The
+ * test vectors have been collected from the following standards:
+ * RFC5297
+ */
+
+#include "testutils.h"
+#include "aes.h"
+#include "nettle-types.h"
+#include "siv-cmac.h"
+#include "knuth-lfib.h"
+
+static void
+test_compare_results(const char *name,
+ const struct tstring *adata,
+ /* Expected results. */
+ const struct tstring *e_clear,
+ const struct tstring *e_cipher,
+ /* Actual results. */
+ const void *clear,
+ const void *cipher,
+ const void *digest) /* digest optional. */
+{
+ if (digest && !MEMEQ(SIV_DIGEST_SIZE, e_cipher->data, digest))
+ {
+ fprintf(stderr, "%s digest failed:\nAdata:", name);
+ tstring_print_hex(adata);
+ fprintf(stderr, "\nInput: ");
+ tstring_print_hex(e_clear);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(SIV_DIGEST_SIZE, digest);
+ fprintf(stderr, "\nExpected:");
+ print_hex(SIV_DIGEST_SIZE, e_cipher->data);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ if (!MEMEQ(e_cipher->length, e_cipher->data, cipher))
+ {
+ fprintf(stderr, "%s: encryption failed\nAdata: ", name);
+ tstring_print_hex(adata);
+ fprintf(stderr, "\nInput: ");
+ tstring_print_hex(e_clear);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(e_cipher->length, cipher);
+ fprintf(stderr, "\nExpected:");
+ tstring_print_hex(e_cipher);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+ if (!MEMEQ(e_clear->length, e_clear->data, clear))
+ {
+ fprintf(stderr, "%s decrypt failed:\nAdata:", name);
+ tstring_print_hex(adata);
+ fprintf(stderr, "\nInput: ");
+ tstring_print_hex(e_cipher);
+ fprintf(stderr, "\nOutput: ");
+ print_hex(e_clear->length, clear);
+ fprintf(stderr, "\nExpected:");
+ tstring_print_hex(e_clear);
+ fprintf(stderr, "\n");
+ FAIL();
+ }
+} /* test_compare_results */
+
+static void
+test_cipher_siv(const char *name,
+ nettle_set_key_func *siv_set_key,
+ nettle_encrypt_message_func *siv_encrypt,
+ nettle_decrypt_message_func *siv_decrypt,
+ unsigned context_size,
+ const struct nettle_cipher *cipher,
+ const struct tstring *key,
+ const struct tstring *nonce,
+ const struct tstring *authdata,
+ const struct tstring *cleartext,
+ const struct tstring *ciphertext)
+{
+ void *ctx = xalloc(context_size);
+ uint8_t *en_data;
+ uint8_t *de_data;
+ int ret;
+
+ ASSERT (key->length == cipher->key_size*2);
+ ASSERT (cleartext->length <= ciphertext->length);
+ ASSERT ((cleartext->length + SIV_BLOCK_SIZE) >= ciphertext->length);
+ ASSERT (ciphertext->length - cleartext->length == SIV_DIGEST_SIZE);
+
+ de_data = xalloc(cleartext->length+SIV_DIGEST_SIZE);
+ en_data = xalloc(ciphertext->length);
+ cipher->set_encrypt_key(ctx, key->data);
+
+ /* Ensure we get the same answers using the all-in-one API. */
+ memset(de_data, 0, cleartext->length);
+ memset(en_data, 0, ciphertext->length);
+
+ siv_set_key(ctx, key->data);
+ siv_encrypt(ctx, nonce->length, nonce->data,
+ authdata->length, authdata->data,
+ cleartext->length+SIV_DIGEST_SIZE, en_data, cleartext->data);
+
+ ret = siv_decrypt(ctx, nonce->length, nonce->data,
+ authdata->length, authdata->data,
+ ciphertext->length, de_data, ciphertext->data);
+
+ if (ret != 1) fprintf(stderr, "siv_decrypt_message failed to validate message\n");
+ test_compare_results(name, authdata,
+ cleartext, ciphertext, de_data, en_data, NULL);
+
+ test_compare_results(name, authdata,
+ cleartext, ciphertext, de_data, en_data, en_data);
+
+
+ /* Ensure that we can detect corrupted message or tag data. */
+ en_data[0] ^= 1;
+ ret = siv_decrypt(ctx, nonce->length, nonce->data,
+ authdata->length, authdata->data,
+ ciphertext->length, de_data, en_data);
+ if (ret != 0) fprintf(stderr, "siv_decrypt_message failed to detect corrupted message\n");
+
+ /* Ensure we can detect corrupted adata. */
+ if (authdata->length) {
+ en_data[0] ^= 1;
+ ret = siv_decrypt(ctx, nonce->length, nonce->data,
+ authdata->length-1, authdata->data,
+ ciphertext->length, de_data, en_data);
+ if (ret != 0) fprintf(stderr, "siv_decrypt_message failed to detect corrupted message\n");
+ }
+
+
+ free(ctx);
+ free(en_data);
+ free(de_data);
+}
+
+#define test_siv_aes128(name, ctx_size, cipher, key, nonce, authdata, cleartext, ciphertext) \
+ test_cipher_siv(name, (nettle_set_key_func*)siv_aes128_cmac_set_key, \
+ (nettle_encrypt_message_func*)siv_aes128_cmac_encrypt_message, \
+ (nettle_decrypt_message_func*)siv_aes128_cmac_decrypt_message, ctx_size, cipher, \
+ key, nonce, authdata, cleartext, ciphertext)
+
+#define test_siv_aes256(name, ctx_size, cipher, key, nonce, authdata, cleartext, ciphertext) \
+ test_cipher_siv(name, (nettle_set_key_func*)siv_aes256_cmac_set_key, \
+ (nettle_encrypt_message_func*)siv_aes256_cmac_encrypt_message, \
+ (nettle_decrypt_message_func*)siv_aes256_cmac_decrypt_message, ctx_size, cipher, \
+ key, nonce, authdata, cleartext, ciphertext)
+
+void
+test_main(void)
+{
+ /* The following tests were checked for interoperability against libaes_siv */
+
+ /*
+ * Example with small nonce, no AD and no plaintext
+ */
+ test_siv_aes128("AES_SIV_CMAC256", sizeof(struct siv_aes128_cmac_ctx),
+ &nettle_aes128,
+ SHEX("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0"
+ "f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff"),
+ SHEX("01"),
+ SHEX(""),
+ SHEX(""),
+ SHEX("c696f84f df92aba3 c31c23d5 f2087513"));
+ /*
+ * Example with small nonce, no AD and plaintext
+ */
+ test_siv_aes128("AES_SIV_CMAC256", sizeof(struct siv_aes128_cmac_ctx),
+ &nettle_aes128,
+ SHEX("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0"
+ "f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff"),
+ SHEX("02"),
+ SHEX(""),
+ SHEX("00112233 44556677 8899aabb ccddeeff"),
+ SHEX("5027b101 589747b8 865a9790 d3fd51d7"
+ "1f259d40 5bfa260b 9ba1d60a a287fd0b"));
+
+ /*
+ * Example with length < 16
+ */
+ test_siv_aes128("AES_SIV_CMAC256", sizeof(struct siv_aes128_cmac_ctx),
+ &nettle_aes128,
+ SHEX("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0"
+ "f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff"),
+ SHEX("02"),
+ SHEX("10111213 14151617 18191a1b 1c1d1e1f"
+ "20212223 24252627"),
+ SHEX("11223344 55667788 99aabbcc ddee"),
+ SHEX("7300cd9b 3f514a44 ed660db6 14157f59"
+ "f0382e23 ae0e6e62 27a03dd3 2619"));
+
+ /*
+ * Example with length > 16
+ */
+ test_siv_aes128("AES_SIV_CMAC256", sizeof(struct siv_aes128_cmac_ctx),
+ &nettle_aes128,
+ SHEX("7f7e7d7c 7b7a7978 77767574 73727170"
+ "40414243 44454647 48494a4b 4c4d4e4f"),
+ SHEX("020304"),
+ SHEX("00112233 44556677 8899aabb ccddeeff"
+ "deaddada deaddada ffeeddcc bbaa9988"
+ "77665544 33221100"),
+ SHEX("74686973 20697320 736f6d65 20706c61"
+ "696e7465 78742074 6f20656e 63727970"
+ "74207573 696e6720 5349562d 414553"),
+ SHEX("f1dba33d e5b3369e 883f67b6 fc823cee"
+ "a4ffb87f dba97c89 44a62325 f133b4e0"
+ "1ca55276 e2261c1a 1d1d4248 d1da30ba"
+ "52b9c8d7 955d65c8 d2ce6eb7 e367d0"));
+
+ /*
+ * Example with single AAD, length > 16
+ */
+ test_siv_aes128("AES_SIV_CMAC256", sizeof(struct siv_aes128_cmac_ctx),
+ &nettle_aes128,
+ SHEX("7f7e7d7c 7b7a7978 77767574 73727170"
+ "40414243 44454647 48494a4b 4c4d4e4f"),
+ SHEX("09f91102 9d74e35b d84156c5 635688c0"),
+ SHEX("00112233 44556677 8899aabb ccddeeff"
+ "deaddada deaddada ffeeddcc bbaa9988"
+ "77665544 33221100"),
+ SHEX("74686973 20697320 736f6d65 20706c61"
+ "696e7465 78742074 6f20656e 63727970"
+ "74207573 696e6720 5349562d 414553"),
+ SHEX("85825e22 e90cf2dd da2c548d c7c1b631"
+ "0dcdaca0 cebf9dc6 cb90583f 5bf1506e"
+ "02cd4883 2b00e4e5 98b2b22a 53e6199d"
+ "4df0c166 6a35a043 3b250dc1 34d776"));
+
+ /*
+ * Example with single AAD, length < 16
+ */
+ test_siv_aes128("AES_SIV_CMAC256", sizeof(struct siv_aes128_cmac_ctx),
+ &nettle_aes128,
+ SHEX("7f7e7d7c 7b7a7978 77767574 73727170"
+ "40414243 44454647 48494a4b 4c4d4e4f"),
+ SHEX("09f91102 9d74e35b d84156c5 635688c0"),
+ SHEX("00112233 44556677 8899aabb ccddeeff"
+ "deaddada deaddada ffeeddcc bbaa9988"
+ "77665544 33221100"),
+ SHEX("11223344 55667788 99aabbcc ddee"),
+ SHEX("15f83882 14bdc94e 3ec4c7c3 69863746"
+ "cd72d317 4b20a1e4 a0894fb7 cd78"));
+
+ /* AES-SIV-CMAC-512 (AES-256) from dchest/siv repo
+ */
+ test_siv_aes256("AES_SIV_CMAC512", sizeof(struct siv_aes256_cmac_ctx),
+ &nettle_aes256,
+ SHEX("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0"
+ "6f6e6d6c 6b6a6968 67666564 63626160"
+ "f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff"
+ "00010203 04050607 08090a0b 0c0d0e0f"),
+ SHEX("02"),
+ SHEX("10111213 14151617 18191a1b 1c1d1e1f"
+ "20212223 24252627"),
+ SHEX("11223344 55667788 99aabbcc ddee"),
+ SHEX("6f740b42 1e2972d8 5e76189e 99842843"
+ "ad9e6ff1 4ea97c32 ab315e67 464c"));
+
+
+ /* AES-SIV-CMAC-512 (AES-256)
+ */
+ test_siv_aes256("AES_SIV_CMAC512", sizeof(struct siv_aes256_cmac_ctx),
+ &nettle_aes256,
+ SHEX("c27df2fd aec35d4a 2a412a50 c3e8c47d"
+ "2d568e91 a38e5414 8abdc0b6 e86caf87"
+ "695c0a8a df4c5f8e b2c6c8b1 36529864"
+ "f3b84b3a e8e3676c e760c461 f3a13e83"),
+ SHEX("02"),
+ SHEX("10111213 14151617 18191a1b 1c1d1e1f"
+ "20212223 24252627"),
+ SHEX("11223344 55667788 99aabbcc ddee"),
+ SHEX("c3366ef8 92911eac 3d17f29a 37d4ebad"
+ "ddc1219e bbde06d1 ee893e55 a39f"));
+
+ /*
+ * Example with length > 16
+ */
+ test_siv_aes256("AES_SIV_CMAC512", sizeof(struct siv_aes256_cmac_ctx),
+ &nettle_aes256,
+ SHEX("c27df2fd aec35d4a 2a412a50 c3e8c47d"
+ "2d568e91 a38e5414 8abdc0b6 e86caf87"
+ "695c0a8a df4c5f8e b2c6c8b1 36529864"
+ "f3b84b3a e8e3676c e760c461 f3a13e83"),
+ SHEX("02"),
+ SHEX("00112233 44556677 8899aabb ccddeeff"
+ "deaddada deaddada ffeeddcc bbaa9988"
+ "77665544 33221100"),
+ SHEX("74686973 20697320 736f6d65 20706c61"
+ "696e7465 78742074 6f20656e 63727970"
+ "74207573 696e6720 5349562d 414553"),
+ SHEX("bbe4751a 549d2fce 410c2efd e0df4d13"
+ "1a6eac0d 030028f8 dc16b6c4 3a557d4e"
+ "3e846ad7 52c5a030 c75a85ff 8b07ff10"
+ "71b133f5 edac3c60 8bb6eb13 dd1fd9"));
+
+ /*
+ * Example with single AAD, length > 16
+ */
+ test_siv_aes256("AES_SIV_CMAC512", sizeof(struct siv_aes256_cmac_ctx),
+ &nettle_aes256,
+ SHEX("c27df2fd aec35d4a 2a412a50 c3e8c47d"
+ "2d568e91 a38e5414 8abdc0b6 e86caf87"
+ "695c0a8a df4c5f8e b2c6c8b1 36529864"
+ "f3b84b3a e8e3676c e760c461 f3a13e83"),
+ SHEX("09f91102 9d74e35b d84156c5 635688c0"),
+ SHEX("00112233 44556677 8899aabb ccddeeff"
+ "deaddada deaddada ffeeddcc bbaa9988"
+ "77665544 33221100"),
+ SHEX("74686973 20697320 736f6d65 20706c61"
+ "696e7465 78742074 6f20656e 63727970"
+ "74207573 696e6720 5349562d 414553"),
+ SHEX("5a979b0d a58fde80 51621ae6 bf96feda"
+ "50933da8 047bc306 fabaf0c3 d9fa8471"
+ "c70a7def 39a2f91d 68a2021c 99ac7e2a"
+ "24535a13 4ba23ec1 5787cebe 5c53cc"));
+}
diff --git a/testsuite/testutils.h b/testsuite/testutils.h
index ded57db6..3a1872f1 100644
--- a/testsuite/testutils.h
+++ b/testsuite/testutils.h
@@ -176,6 +176,19 @@ test_armor(const struct nettle_armor *armor,
const uint8_t *data,
const char *ascii);
+/* AEAD ciphers */
+typedef void
+nettle_encrypt_message_func(void *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t clength, uint8_t *dst, const uint8_t *src);
+
+typedef int
+nettle_decrypt_message_func(void *ctx,
+ size_t nlength, const uint8_t *nonce,
+ size_t alength, const uint8_t *adata,
+ size_t mlength, uint8_t *dst, const uint8_t *src);
+
#if WITH_HOGWEED
#if NETTLE_USE_MINI_GMP
--
2.20.1
From 1030249c1ac8be816b3d2bf1863d325bc3fe8827 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Wed, 17 Apr 2019 15:17:47 +0200
Subject: [PATCH 2/3] .gitlab-ci.yml: added make distcheck target
This checks whether the distributed tarball misses files
and result to a functioning library.
Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
---
.gitlab-ci.yml | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ecd95ad3..e7101c64 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -50,6 +50,15 @@ build/ndebug:
- shared
except:
- tags
+distcheck:
+ image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
+ script:
+ - ./.bootstrap &&
+ ./configure --disable-static --disable-assembler && make distcheck
+ tags:
+ - shared
+ except:
+ - tags
build/ubsan:
image: $CI_REGISTRY/$BUILD_IMAGES_PROJECT:$FEDORA_BUILD
script:
--
2.20.1
From a0ceb52e7bef137226ec5a1013d154e5516d2ba4 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Tue, 16 Apr 2019 20:19:17 +0200
Subject: [PATCH 1/3] cmac: use nettle_block16 for const variable
Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
---
cmac.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/cmac.c b/cmac.c
index ed3b5eb8..01fee79e 100644
--- a/cmac.c
+++ b/cmac.c
@@ -73,15 +73,15 @@ void
cmac128_set_key(struct cmac128_ctx *ctx, const void *cipher,
nettle_cipher_func *encrypt)
{
- static const uint8_t const_zero[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ static const union nettle_block16 const_zero = { .b = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
};
union nettle_block16 *L = &ctx->block;
memset(ctx, 0, sizeof(*ctx));
/* step 1 - generate subkeys k1 and k2 */
- encrypt(cipher, 16, L->b, const_zero);
+ encrypt(cipher, 16, L->b, const_zero.b);
block_mulx(&ctx->K1, L);
block_mulx(&ctx->K2, &ctx->K1);
--
2.20.1
_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs