summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2019-07-02 14:28:04 +0200
committerNiels Möller <nisse@lysator.liu.se>2019-07-02 14:28:04 +0200
commit98bc919114f2272a8b2537467213de4a0fb776e4 (patch)
tree7ba0d138ad75a2604717cf6e2c4c861c2b3479c8
parentee5d62898cf070f08beedc410a8d7c418588bd95 (diff)
parent83296eb6a45f7dba125372a2ce3c8f4d6c8b9934 (diff)
downloadnettle-98bc919114f2272a8b2537467213de4a0fb776e4.tar.gz
Merge branch 'siv-mode' into master-updates
-rw-r--r--ChangeLog58
-rw-r--r--Makefile.in5
-rw-r--r--cmac-internal.h54
-rw-r--r--cmac.c17
-rw-r--r--nettle.texinfo99
-rw-r--r--siv-cmac-aes128.c77
-rw-r--r--siv-cmac-aes256.c77
-rw-r--r--siv-cmac.c165
-rw-r--r--siv-cmac.h134
-rw-r--r--testsuite/.gitignore2
-rw-r--r--testsuite/.test-rules.make3
-rw-r--r--testsuite/Makefile.in2
-rw-r--r--testsuite/siv-test.c382
13 files changed, 1063 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 59014632..1bc2549a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,61 @@
+2019-06-06 Niels Möller <nisse@lysator.liu.se>
+
+ Update for cmac changes, enabling const for the _message functions.
+ * siv-cmac.c (_siv_s2v): Take a const struct cmac128_key as argument,
+ and use a local struct cmac128_ctx for message-specific state.
+ (siv_cmac_set_key): Take a struct cmac128_key as argument. Updated
+ callers.
+ (siv_cmac_encrypt_message, siv_cmac_decrypt_message): Take a const
+ struct cmac128_key as argument. Updated callers.
+
+ * siv-cmac.h (SIV_CMAC_CTX): Changed to use struct cmac128_key
+ rather than struct cmac128_ctx.
+
+ * siv-cmac-aes256.c (siv_cmac_aes256_encrypt_message)
+ (siv_cmac_aes256_decrypt_message): Likewise.
+ * siv-cmac-aes128.c (siv_cmac_aes128_encrypt_message)
+ (siv_cmac_aes128_decrypt_message): The ctx argument made const.
+
+2019-05-15 Niels Möller <nisse@lysator.liu.se>
+
+ * siv-cmac.h (SIV_CMAC_AES128_KEY_SIZE, SIV_CMAC_AES256_KEY_SIZE):
+ New constants.
+ * testsuite/siv-test.c: Simplify tests a little.
+
+ * siv-cmac.h (SIV_MIN_NONCE_SIZE): New constant, 1.
+ * siv-cmac.c (_siv_s2v): Require non-empty nonce.
+ * nettle.texinfo (SIV-CMAC): Update documentation.
+
+2019-05-06 Niels Möller <nisse@lysator.liu.se>
+
+ SIV-CMAC mode, based on patch by Nikos Mavrogiannopoulos:
+ * siv-cmac.h (SIV_BLOCK_SIZE, SIV_DIGEST_SIZE): New constants.
+ (SIV_CMAC_CTX): New macro.
+ (struct siv_cmac_aes128_ctx, struct siv_cmac_aes256_ctx): New
+ context structs.
+ * siv-cmac.c (_siv_s2v, siv_cmac_set_key)
+ (siv_cmac_encrypt_message)
+ (siv_cmac_decrypt_message): New file, new functions.
+ * siv-cmac-aes128.c (siv_cmac_aes128_set_key)
+ (siv_cmac_aes128_encrypt_message)
+ (siv_cmac_aes128_decrypt_message): New file, new functions.
+ * siv-cmac-aes256.c (siv_cmac_aes256_set_key)
+ (siv_cmac_aes256_encrypt_message)
+ (siv_cmac_aes256_decrypt_message): New file, new functions.
+ * Makefile.in (nettle_SOURCES): Add siv-cmac source files.
+ (HEADERS): Add siv-cmac.h.
+ * testsuite/siv-test.c: New file.
+ * testsuite/Makefile.in (TS_NETTLE_SOURCES): Added siv-test.c
+ * nettle.texinfo (SIV-CMAC): Documentation.
+
+2019-04-30 Niels Möller <nisse@lysator.liu.se>
+
+ Based on a patch contributed by Nikos Mavrogiannopoulos.
+ * cmac.c (_cmac128_block_mulx): Renamed function...
+ (block_mulx): ... from old name.
+ * cmac-internal.h (_cmac128_block_mulx): New file, declare function.
+ * Makefile.in (DISTFILES): Added cmac-internal.h.
+
2019-06-26 Niels Möller <nisse@lysator.liu.se>
* Released nettle-3.5.1.
diff --git a/Makefile.in b/Makefile.in
index 537e97d1..b54e64b0 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-cmac-aes128.c siv-cmac-aes256.c \
cnd-memcpy.c \
chacha-crypt.c chacha-core-internal.c \
chacha-poly1305.c chacha-poly1305-meta.c \
@@ -198,7 +199,7 @@ 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 siv-cmac.h \
md2.h md4.h \
md5.h md5-compat.h \
memops.h memxor.h \
@@ -229,7 +230,7 @@ DISTFILES = $(SOURCES) $(HEADERS) getopt.h getopt_int.h \
INSTALL NEWS ChangeLog \
nettle.pc.in hogweed.pc.in \
$(des_headers) descore.README desdata.stamp \
- aes-internal.h camellia-internal.h serpent-internal.h \
+ aes-internal.h camellia-internal.h cmac-internal.h serpent-internal.h \
cast128_sboxes.h desinfo.h desCode.h \
ripemd160-internal.h sha2-internal.h \
memxor-internal.h nettle-internal.h nettle-write.h \
diff --git a/cmac-internal.h b/cmac-internal.h
new file mode 100644
index 00000000..80db7fcc
--- /dev/null
+++ b/cmac-internal.h
@@ -0,0 +1,54 @@
+/* cmac-internal.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 c5a59b18..70ce8132 100644
--- a/cmac.c
+++ b/cmac.c
@@ -44,13 +44,14 @@
#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 +60,9 @@ 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);
@@ -79,8 +80,8 @@ cmac128_set_key(struct cmac128_key *key, const void *cipher,
/* step 1 - generate subkeys k1 and k2 */
encrypt(cipher, 16, L.b, zero_block.b);
- block_mulx(&key->K1, &L);
- block_mulx(&key->K2, &key->K1);
+ _cmac128_block_mulx(&key->K1, &L);
+ _cmac128_block_mulx(&key->K2, &key->K1);
}
void
diff --git a/nettle.texinfo b/nettle.texinfo
index b8579a6e..9cdec480 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,101 @@ 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 Synthetic Initialization Vector AEAD
+
+@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, as specified in
+@cite{RFC 5297}, 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-empty nonce. In the
+terminology of the RFC, the input to the S2V function is always a vector
+of three elements, where S1 is the authenticated data, S2 is the nonce,
+and S3 is the plaintext.
+
+
+@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 minimum size for an @acronym{SIV-CMAC} nonce, 1.
+@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_cmac_aes128_ctx}
+Holds state corresponding to a particular message encrypted using the
+AES-128 block cipher.
+@end deftp
+
+@deftp {Context struct} {struct siv_cmac_aes256_ctx}
+Holds state corresponding to a particular message encrypted using the
+AES-256 block cipher.
+@end deftp
+
+@deftypefun void siv_cmac_aes128_set_key (struct siv_cmac_aes128_ctx *@var{ctx}, const uint8_t *@var{key})
+@deftypefunx void siv_cmac_aes256_set_key (struct siv_cmac_aes256_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_cmac_aes128_encrypt_message (struct siv_cmac_aes128_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_cmac_aes256_encrypt_message (struct siv_cmac_aes256_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_cmac_aes128_decrypt_message (struct siv_cmac_aes128_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_cmac_aes256_decrypt_message (struct siv_cmac_aes128_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-cmac-aes128.c b/siv-cmac-aes128.c
new file mode 100644
index 00000000..82ac16e9
--- /dev/null
+++ b/siv-cmac-aes128.c
@@ -0,0 +1,77 @@
+/* siv-cmac-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_cmac_aes128_set_key(struct siv_cmac_aes128_ctx *ctx, const uint8_t *key)
+{
+ siv_cmac_set_key(&ctx->cmac_key, &ctx->cmac_cipher, &ctx->ctr_cipher, &nettle_aes128, key);
+}
+
+void
+siv_cmac_aes128_encrypt_message(const struct siv_cmac_aes128_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->cmac_key, &ctx->cmac_cipher,
+ &nettle_aes128, &ctx->ctr_cipher,
+ nlength, nonce, alength, adata,
+ clength, dst, src);
+}
+
+int
+siv_cmac_aes128_decrypt_message(const struct siv_cmac_aes128_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->cmac_key, &ctx->cmac_cipher,
+ &nettle_aes128, &ctx->ctr_cipher,
+ nlength, nonce, alength, adata,
+ mlength, dst, src);
+}
diff --git a/siv-cmac-aes256.c b/siv-cmac-aes256.c
new file mode 100644
index 00000000..9401bbf1
--- /dev/null
+++ b/siv-cmac-aes256.c
@@ -0,0 +1,77 @@
+/* siv-cmac-aes256.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_cmac_aes256_set_key(struct siv_cmac_aes256_ctx *ctx, const uint8_t *key)
+{
+ siv_cmac_set_key(&ctx->cmac_key, &ctx->cmac_cipher, &ctx->ctr_cipher, &nettle_aes256, key);
+}
+
+void
+siv_cmac_aes256_encrypt_message(const struct siv_cmac_aes256_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->cmac_key, &ctx->cmac_cipher,
+ &nettle_aes256, &ctx->ctr_cipher,
+ nlength, nonce, alength, adata,
+ clength, dst, src);
+}
+
+int
+siv_cmac_aes256_decrypt_message(const struct siv_cmac_aes256_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->cmac_key, &ctx->cmac_cipher,
+ &nettle_aes256, &ctx->ctr_cipher,
+ nlength, nonce, alength, adata,
+ mlength, dst, src);
+}
diff --git a/siv-cmac.c b/siv-cmac.c
new file mode 100644
index 00000000..f498cb86
--- /dev/null
+++ b/siv-cmac.c
@@ -0,0 +1,165 @@
+/* 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 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,
+ const struct cmac128_key *cmac_key,
+ const void *cmac_cipher,
+ 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 = 0 };
+ struct cmac128_ctx cmac_ctx;
+ assert (nlength >= SIV_MIN_NONCE_SIZE);
+
+ cmac128_init(&cmac_ctx);
+ cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, 16, const_zero.b);
+ cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, D.b);
+
+ _cmac128_block_mulx (&D, &D);
+ cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, alength, adata);
+ cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, S.b);
+ memxor (D.b, S.b, 16);
+
+ _cmac128_block_mulx (&D, &D);
+ cmac128_update (&cmac_ctx, cmac_cipher, nc->encrypt, nlength, nonce);
+ cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, S.b);
+ memxor (D.b, S.b, 16);
+
+ /* Sn */
+ if (plength >= 16)
+ {
+ cmac128_update (&cmac_ctx, cmac_cipher, 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 (&cmac_ctx, cmac_cipher, nc->encrypt, 16, T.b);
+ cmac128_digest (&cmac_ctx, cmac_key, cmac_cipher, nc->encrypt, 16, v);
+}
+
+void
+siv_cmac_set_key (struct cmac128_key *cmac_key, void *cmac_cipher, void *siv_cipher,
+ const struct nettle_cipher *nc, const uint8_t * key)
+{
+ nc->set_encrypt_key (cmac_cipher, key);
+ cmac128_set_key (cmac_key, cmac_cipher, nc->encrypt);
+ nc->set_encrypt_key (siv_cipher, key + nc->key_size);
+}
+
+void
+siv_cmac_encrypt_message (const struct cmac128_key *cmac_key,
+ const void *cmac_cipher,
+ const struct nettle_cipher *nc,
+ const void *ctr_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, cmac_key, cmac_cipher, 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 (ctr_cipher, nc->encrypt, AES_BLOCK_SIZE, siv.b, slength,
+ dst + SIV_DIGEST_SIZE, src);
+}
+
+int
+siv_cmac_decrypt_message (const struct cmac128_key *cmac_key,
+ const void *cmac_cipher,
+ const struct nettle_cipher *nc,
+ const void *ctr_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;
+
+ memcpy (ctr.b, src, SIV_DIGEST_SIZE);
+ ctr.b[8] &= ~0x80;
+ ctr.b[12] &= ~0x80;
+
+ ctr_crypt (ctr_cipher, nc->encrypt, AES_BLOCK_SIZE, ctr.b,
+ mlength, dst, src + SIV_DIGEST_SIZE);
+
+ /* create CTR nonce */
+ _siv_s2v (nc,
+ cmac_key, cmac_cipher, alength, adata,
+ nlength, nonce, mlength, 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..c631a41e
--- /dev/null
+++ b/siv-cmac.h
@@ -0,0 +1,134 @@
+/* siv-cmac.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_cmac_aes128_set_key nettle_siv_cmac_aes128_set_key
+#define siv_cmac_aes128_encrypt_message nettle_siv_cmac_aes128_encrypt_message
+#define siv_cmac_aes128_decrypt_message nettle_siv_cmac_aes128_decrypt_message
+#define siv_cmac_aes256_set_key nettle_siv_cmac_aes256_set_key
+#define siv_cmac_aes256_encrypt_message nettle_siv_cmac_aes256_encrypt_message
+#define siv_cmac_aes256_decrypt_message nettle_siv_cmac_aes256_decrypt_message
+
+/* For SIV, the block size of the underlying cipher shall be 128 bits. */
+#define SIV_BLOCK_SIZE 16
+#define SIV_DIGEST_SIZE 16
+#define SIV_MIN_NONCE_SIZE 1
+
+void
+siv_cmac_set_key(struct cmac128_key *cmac_key, void *cmac_cipher, void *ctr_cipher,
+ const struct nettle_cipher *nc,
+ const uint8_t *key);
+
+void
+siv_cmac_encrypt_message(const struct cmac128_key *cmac_key, const void *cmac_cipher_ctx,
+ const struct nettle_cipher *nc,
+ const void *ctr_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_cmac_decrypt_message(const struct cmac128_key *cmac_key, const void *cmac_cipher,
+ const struct nettle_cipher *nc,
+ const void *ctr_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_key cmac_key; type cmac_cipher; type ctr_cipher; }
+
+/* SIV_CMAC_AES128 */
+#define SIV_CMAC_AES128_KEY_SIZE 32
+
+struct siv_cmac_aes128_ctx SIV_CMAC_CTX(struct aes128_ctx);
+
+void
+siv_cmac_aes128_set_key(struct siv_cmac_aes128_ctx *ctx, const uint8_t *key);
+
+void
+siv_cmac_aes128_encrypt_message(const struct siv_cmac_aes128_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_cmac_aes128_decrypt_message(const struct siv_cmac_aes128_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);
+
+/* SIV_CMAC_AES256 */
+#define SIV_CMAC_AES256_KEY_SIZE 64
+
+struct siv_cmac_aes256_ctx SIV_CMAC_CTX(struct aes256_ctx);
+
+void
+siv_cmac_aes256_set_key(struct siv_cmac_aes256_ctx *ctx, const uint8_t *key);
+
+void
+siv_cmac_aes256_encrypt_message(const struct siv_cmac_aes256_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_cmac_aes256_decrypt_message(const struct siv_cmac_aes256_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 4d680cd1..066bcee2 100644
--- a/testsuite/.gitignore
+++ b/testsuite/.gitignore
@@ -95,6 +95,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 ab22da23..efb7df3c 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -133,6 +133,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 9a1fe209..f8f85701 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..627e3844
--- /dev/null
+++ b/testsuite/siv-test.c
@@ -0,0 +1,382 @@
+/* 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"
+
+/* 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);
+
+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,
+ size_t context_size, size_t key_size,
+ 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 == key_size);
+ ASSERT (cleartext->length + SIV_DIGEST_SIZE == ciphertext->length);
+
+ de_data = xalloc(cleartext->length+SIV_DIGEST_SIZE);
+ en_data = xalloc(ciphertext->length);
+
+ /* 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,
+ cleartext->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, key, nonce, authdata, cleartext, ciphertext) \
+ test_cipher_siv(name, (nettle_set_key_func*)siv_cmac_aes128_set_key, \
+ (nettle_encrypt_message_func*)siv_cmac_aes128_encrypt_message, \
+ (nettle_decrypt_message_func*)siv_cmac_aes128_decrypt_message, \
+ sizeof(struct siv_cmac_aes128_ctx), SIV_CMAC_AES128_KEY_SIZE, \
+ key, nonce, authdata, cleartext, ciphertext)
+
+#define test_siv_aes256(name, key, nonce, authdata, cleartext, ciphertext) \
+ test_cipher_siv(name, (nettle_set_key_func*)siv_cmac_aes256_set_key, \
+ (nettle_encrypt_message_func*)siv_cmac_aes256_encrypt_message, \
+ (nettle_decrypt_message_func*)siv_cmac_aes256_decrypt_message, \
+ sizeof(struct siv_cmac_aes256_ctx), SIV_CMAC_AES256_KEY_SIZE, \
+ 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("SIV_CMAC_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("SIV_CMAC_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("SIV_CMAC_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("SIV_CMAC_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("SIV_CMAC_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("SIV_CMAC_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("SIV_CMAC_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("SIV_CMAC_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("SIV_CMAC_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("SIV_CMAC_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"));
+
+ /* The following tests were checked for interoperability against miscreant.js */
+
+ /*
+ * Example from miscreant.js with no AD
+ * https://github.com/miscreant/miscreant.js/blob/master/vectors/aes_siv_aead.tjson
+ */
+ test_siv_aes128("SIV_CMAC_AES128",
+ SHEX("fffefdfc fbfaf9f8 f7f6f5f4 f3f2f1f0"
+ "f0f1f2f3 f4f5f6f7 f8f9fafb fcfdfeff"),
+ SHEX("10111213 1415161718191a1b1 c1d1e1f2"
+ "02122232 4252627"),
+ SHEX(""),
+ SHEX("11223344 55667788 99aabbcc ddee"),
+ SHEX("4b3d0f15 ae9ffa9e 65b94942 1582ef70"
+ "e410910d 6446c775 9ebff9b5 385a"));
+
+ /*
+ * Example from miscreant.js with AD
+ */
+ test_siv_aes128("SIV_CMAC_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"));
+}