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
> In this function, you treat empty associated data or nonce as those
> elements missing in the input vector to S2V. E.g., if both adata and
> nonce are empty, the input vector is { plaintext }, one single
> element.
> But it could also be { "", "", plaintext }, with three elements, the
> first two being empty strings.
While the low level function could handle it, it is not exposed to be
called directly (mainly intentionally as this cipher introduces a very
new paradigm which I do not quite see much of practical uses).
This patch only adds the higher level AEAD API only, so this case
cannot happen as we don't have the notion of empty string
in nettle. We can introduce it of course, though we may be opening a
can of worms as not only empty strings are undefined in terms of AEAD
API [0], but what would these mean in the other implementations?
[0]. https://tools.ietf.org/html/rfc5116#section-2
> To me, this sounds like a likely source of interop problems. Since
> RFC
> 5297 is general and allows the application to decide on the number of
> elements and meaning of the input vector, it doesn't give much
> guidance on this, as far as I see. The crucial case is when an
> application specifies that SIV is used with associated data and/or a
> nonce, but allows an empty string for either of those.
I agree on that. That's one of the reasons I stuck on the higher level
AEAD API (expressed by the message APIs in nettle). I added two
sentences in the documentation about it.
> >> I think this function should do the underlying key setup also for
> the
> >> cipher instance used for s2v, not just store the key for later. So
> >> then the function would be
> >>
> >> void
> >> siv_cmac_set_key(void *cmac_cipher, void *ctr_cipher,
> The idea of the set_key function is to do all preparations that don't
> depend on the actual message, so they don't have to be repeated. And
> I
> think it's a bit odd to handle the keying of the two involved cipher
> contexts so differently.
Done. It needed some reorganization, and cmac128_syn is still needed in
an ugly simulation of the CMAC structure setup to use the macros. I
have kept the union
The attached version should address the comments so far and also
changes cmac128_set_key to use nettle_block16 as well.
regards,
Nikos
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/2] 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
From c85011ce5fd60cd4c941319b78cd567d14b2ec85 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Sat, 20 Jan 2018 10:36:05 +0100
Subject: [PATCH 2/2] 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 | 196 +++++++++++++++++++++
siv-cmac.h | 131 ++++++++++++++
testsuite/.gitignore | 2 +
testsuite/.test-rules.make | 3 +
testsuite/Makefile.in | 2 +-
testsuite/siv-test.c | 350 +++++++++++++++++++++++++++++++++++++
testsuite/testutils.h | 13 ++
14 files changed, 1005 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..90ee61d7 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 siv-cmac-internal.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..f853f3e2 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.
+
+@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..94f65b0f
--- /dev/null
+++ b/siv-cmac.c
@@ -0,0 +1,196 @@
+/* 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;
+};
+
+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_one = { .b = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }
+ };
+ 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);
+
+ if (nlength == 0 && alength == 0 && plength == 0) {
+ CMAC128_UPDATE(ctx, nc->encrypt, 16, const_one.b);
+ CMAC128_DIGEST(ctx, nc->encrypt, 16, v);
+ return;
+ }
+
+ CMAC128_UPDATE(ctx, nc->encrypt, 16, const_zero.b);
+ CMAC128_DIGEST(ctx, nc->encrypt, 16, D.b);
+
+ if (alength > 0) {
+ _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);
+ }
+
+ if (nlength > 0) {
+ _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..39e87514
--- /dev/null
+++ b/testsuite/siv-test.c
@@ -0,0 +1,350 @@
+/* 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)
+{
+ /*
+ * Example with no nonce, no AD and no plaintext; taken from
+ * https://github.com/miscreant/miscreant/blob/master/vectors/aes_siv.tjson
+ * however we don't interoperate.
+ */
+ test_siv_aes128("AES_SIV_CMAC256", sizeof(struct siv_aes128_cmac_ctx),
+ &nettle_aes128,
+ SHEX("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0"
+ "f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff"),
+ SHEX(""),
+ SHEX(""),
+ SHEX(""),
+ SHEX("949f99cb cc3eb5da6 d3c45d0 f59aa9c7"));
+
+ /*
+ * Example with no nonce, no AD and plaintext; taken from
+ * https://github.com/miscreant/miscreant/blob/master/vectors/aes_siv.tjson
+ */
+ test_siv_aes128("AES_SIV_CMAC256", sizeof(struct siv_aes128_cmac_ctx),
+ &nettle_aes128,
+ SHEX("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0"
+ "f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff"),
+ SHEX(""),
+ SHEX(""),
+ SHEX("00112233 44556677 8899aabb ccddeeff"),
+ SHEX("f304f912 863e303d 5b540e50 57c7010c"
+ "942ffaf4 5b0e5ca5 fb9a56a5 263bb065"));
+
+ /*
+ * Example without nonce length < 16 (RFC5297)
+ */
+ test_siv_aes128("AES_SIV_CMAC256", sizeof(struct siv_aes128_cmac_ctx),
+ &nettle_aes128,
+ SHEX("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0"
+ "f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff"),
+ SHEX(""),
+ SHEX("10111213 14151617 18191a1b 1c1d1e1f"
+ "20212223 24252627"),
+ SHEX("11223344 55667788 99aabbcc ddee"),
+ SHEX("85632d07 c6e8f37f 950acd32 0a2ecc93"
+ "40c02b96 90c4dc04 daef7f6a fe5c"));
+
+ /*
+ * Example without nonce 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(""),
+ 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("c12ccaa7 54e1b3fa 4f416c18 415625ca"
+ "472fbee de5bc03f 34934819 a9abb20b5"
+ "8cd019c 470ac832 f6eb9ddf 0656c5dce"
+ "ffe611a 5a5ca3e1 c3c12da5 6e4bb87"));
+
+ /*
+ * 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(""),
+ SHEX("10111213 14151617 18191a1b 1c1d1e1f"
+ "20212223 24252627"),
+ SHEX("11223344 55667788 99aabbcc ddee"),
+ SHEX("f125274c 598065cf c26b0e71 57502908"
+ "8b035217 e380cac8 919ee800 c126"));
+
+
+ /* 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(""),
+ SHEX("10111213 14151617 18191a1b 1c1d1e1f"
+ "20212223 24252627"),
+ SHEX("11223344 55667788 99aabbcc ddee"),
+ SHEX("ae2b1bd1 ba7fcd6a 4f9f7eb2 4b40f766"
+ "86053ffd c384cb19 76031f46 3013"));
+
+ /*
+ * Example without nonce 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(""),
+ 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("79476aaa 388374fe 97d0db51 596cb5ee"
+ "a933e001 412026c7 956c82dd b753b1af"
+ "3d7d49ac 474a800a c14b4bab a4542067"
+ "83647ef9 51315dab b7a2c05b 288ba8"));
+
+ /*
+ * 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
_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs