On Sat, 2018-01-27 at 09:57 +0100, Nikos Mavrogiannopoulos wrote:

> > 
> 
> But then when would generate the actual IV? When data are added
> gradually, one would have to require order in the calling of
> functions,
> to ensure that one would generate the IV to be used by the encryption
> functions. For  example require
> 
> siv_aes128_cmac_set_key
> siv_aes128_cmac_extra_adata
> siv_aes128_cmac_extra_adata
> siv_aes_128_cmac_set_nonce (must be last and must be called even if
> there is no nonce, and will generate and save the IV)
> siv_aes128_cmac_decrypt (which will use the saved in ctx IV)
> 
> or
> 
> siv_aes128_cmac_set_key
> siv_aes128_cmac_extra_adata
> siv_aes128_cmac_extra
> _adata
> siv_aes_128_cmac_set_nonce
> siv_aes_128_cmac_get_iv
> siv_aes128_cmac_
> decrypt (which will use the provided in param IV)
> 
> I'm also not sure how to check the tag? Make
> siv_aes128_cmac_decrypt()
> check it and return an int, or provide a digest function which will
> return the generated IV and let the caller do something with it?
> 
> Shouldn't the siv_aes128_cmac_extra_adata be named
> siv_aes128_cmac_update? (though its semantics would be different from
> other AEAD ciphers as updating with "ab" is different than two calls
> with "a" and "b").
> 
> Overall, the more I look how a low level API for SIV would look like,
> the more I think of having only a high level one.

I've gave up on my attempts for a low-level mode as they were resulting
to a very complex to use interface when following nettle conventions,
or a very unique interface when trying to capture SIV-CMAC intentions.

Thus, I'm sending an RFC for a high level SIV-CMAC interface with an
abstraction function set, which abstract on the cipher. The cipher is
then used for both CTR encryption and CMAC.
(Initially I tried abstracting over cipher and MAC, which caused a very
complex interface, such as functions with 13+ parameters).

That abstraction seems to have a cost on safety as in _siv_s2v()
function I simulated the cipher context using an array. Is there a
better way to capture that on nettle?

This patch works on top of the proposed CMAC interface.

regards,
Nikos
From 4798372c92332c3637048523a12052abea85b831 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <[email protected]>
Date: Sat, 20 Jan 2018 10:36:05 +0100
Subject: [PATCH] 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. It is used by draft-ietf-ntp-using-nts-for-ntp-10.

Only a high level interface is provided.

Signed-off-by: Nikos Mavrogiannopoulos <[email protected]>
---
 Makefile.in                |   4 +-
 cmac-internal.h            |  54 ++++++++
 cmac.c                     |   9 +-
 nettle-internal.h          |   2 +
 nettle-types.h             |  15 ++
 nettle.texinfo             |  82 ++++++++++-
 siv-aes128-cmac.c          |  79 +++++++++++
 siv-aes256-cmac.c          |  79 +++++++++++
 siv-cmac.c                 | 190 ++++++++++++++++++++++++++
 siv-cmac.h                 | 139 +++++++++++++++++++
 testsuite/.test-rules.make |   3 +
 testsuite/Makefile.in      |   2 +-
 testsuite/siv-test.c       | 332 +++++++++++++++++++++++++++++++++++++++++++++
 13 files changed, 983 insertions(+), 7 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 de12bb3f..b4101de2 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 \
 		 chacha-crypt.c chacha-core-internal.c \
 		 chacha-poly1305.c chacha-poly1305-meta.c \
 		 chacha-set-key.c chacha-set-nonce.c \
@@ -193,7 +194,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 95d45de4..4d124e7e 100644
--- a/cmac.c
+++ b/cmac.c
@@ -44,6 +44,7 @@
 
 #include "memxor.h"
 #include "nettle-internal.h"
+#include "cmac-internal.h"
 #include "macros.h"
 
 static const uint8_t const_zero[] = {
@@ -52,8 +53,8 @@ static const uint8_t const_zero[] = {
 };
 
 /* shift one and XOR with 0x87. */
-static inline 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 b1 = READ_UINT64(src->b);
 	uint64_t b2 = READ_UINT64(src->b+8);
@@ -77,8 +78,8 @@ void cmac128_set_key(struct cmac128 *ctx, void *cipher,
 	/* step 1 - generate subkeys k1 and k2 */
 	encrypt(cipher, 16, L->b, const_zero);
 
-	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 0b0d25c9..bc8e1df7 100644
--- a/nettle-internal.h
+++ b/nettle-internal.h
@@ -57,6 +57,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-types.h b/nettle-types.h
index f04655d6..1828ca43 100644
--- a/nettle-types.h
+++ b/nettle-types.h
@@ -64,6 +64,21 @@ typedef void *nettle_realloc_func(void *ctx, void *p, size_t length);
 /* Ciphers */
 typedef void nettle_set_key_func(void *ctx, const uint8_t *key);
 
+/* AEAD ciphers */
+typedef void
+nettle_encrypt_message(void *ctx,
+		       size_t nlength, const uint8_t *nonce,
+		       size_t alength, const uint8_t *adata,
+		       size_t tlength,
+		       size_t clength, uint8_t *dst, const uint8_t *src);
+
+typedef int
+nettle_decrypt_message(void *ctx,
+		       size_t nlength, const uint8_t *nonce,
+		       size_t alength, const uint8_t *adata,
+		       size_t tlength,
+		       size_t mlength, uint8_t *dst, const uint8_t *src);
+
 /* For block ciphers, const context. */
 typedef void nettle_cipher_func(const void *ctx,
 				size_t length, uint8_t *dst,
diff --git a/nettle.texinfo b/nettle.texinfo
index bfc97b5e..13de5cde 100644
--- a/nettle.texinfo
+++ b/nettle.texinfo
@@ -96,6 +96,7 @@ Cipher modes
 * CFB and CFB8::
 * GCM::                         
 * CCM::                         
+* SIV-CMAC::
 
 Keyed Hash Functions
 
@@ -2329,6 +2330,7 @@ more adventurous alternative, in particular if performance is important.
 * GCM::                         
 * CCM::                         
 * ChaCha-Poly1305::
+* SIV-CMAC::
 * nettle_aead abstraction::
 @end menu
 
@@ -2976,7 +2978,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
 
@@ -3059,6 +3061,84 @@ 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. 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.
+
+@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{tlength}, 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{tlength}, 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}.
+@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{tlength}, 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{tlength}, 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, and compares it to the final @var{tlength} bytes of
+@var{src}. 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..2acfc9a5
--- /dev/null
+++ b/siv-aes128-cmac.c
@@ -0,0 +1,79 @@
+/* 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->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 tlength,
+				size_t slength, uint8_t *dst, const uint8_t *src)
+{
+  assert(tlength == SIV_DIGEST_SIZE);
+  siv_cmac_encrypt_message(&ctx->siv_cmac, &nettle_aes128, &ctx->cipher,
+			   nlength, nonce, alength, adata,
+			   slength, 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 tlength,
+			 size_t mlength, uint8_t *dst, const uint8_t *src)
+{
+  assert(tlength == SIV_DIGEST_SIZE);
+  return siv_cmac_decrypt_message(&ctx->siv_cmac, &nettle_aes128, &ctx->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..c85feebe
--- /dev/null
+++ b/siv-aes256-cmac.c
@@ -0,0 +1,79 @@
+/* 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->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 tlength,
+				size_t slength, uint8_t *dst, const uint8_t *src)
+{
+  assert(tlength == SIV_DIGEST_SIZE);
+  siv_cmac_encrypt_message(&ctx->siv_cmac, &nettle_aes256, &ctx->cipher,
+			   nlength, nonce, alength, adata,
+			   slength, 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 tlength,
+			 size_t mlength, uint8_t *dst, const uint8_t *src)
+{
+  assert(tlength == SIV_DIGEST_SIZE);
+  return siv_cmac_decrypt_message(&ctx->siv_cmac, &nettle_aes256, &ctx->cipher,
+				  nlength, nonce, alength, adata,
+				  mlength, dst, src);
+}
diff --git a/siv-cmac.c b/siv-cmac.c
new file mode 100644
index 00000000..46fcd8ab
--- /dev/null
+++ b/siv-cmac.c
@@ -0,0 +1,190 @@
+/* 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"
+
+struct cmac128_syn {
+  struct cmac128 data;
+  struct {
+    uint8_t pad[NETTLE_MAX_CIPHER16_CONTEXT_SIZE];
+  } cipher;
+};
+
+static
+void _siv_s2v(const struct nettle_cipher *nc,
+	      const uint8_t *s2vk, size_t alength, const uint8_t *adata,
+              size_t nlength, const uint8_t *nonce,
+              size_t plength, const uint8_t *pdata,
+              uint8_t *v)
+{
+  struct cmac128_syn ctx;
+  union nettle_block16 D, S, T;
+  const uint8_t const_one[16] = {
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x01
+  };
+  const uint8_t const_zero[16] = {
+	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);
+
+  /* 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;
+  }
+
+  CMAC128_UPDATE(&ctx, nc->encrypt, 16, const_zero);
+  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(struct siv_cmac_ctx *ctx, void *cipher,
+		 const struct nettle_cipher *nc,
+		 const uint8_t *key)
+{
+	unsigned skey_size = nc->key_size;
+
+	assert(skey_size <= SIV_MAX_KEY_SIZE/2);
+	memcpy(ctx->s2vk, key, skey_size);
+
+	nc->set_encrypt_key(cipher, key+skey_size);
+}
+
+void
+siv_cmac_encrypt_message(struct siv_cmac_ctx *ctx,
+			 const struct nettle_cipher *nc,
+			 void *cipher,
+			 size_t nlength, const uint8_t *nonce,
+			 size_t alength, const uint8_t *adata,
+			 size_t slength, uint8_t *dst, const uint8_t *src)
+{
+	union nettle_block16 siv;
+
+	/* create CTR nonce */
+	_siv_s2v(nc,
+		 ctx->s2vk, 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(struct siv_cmac_ctx *ctx,
+			 const struct nettle_cipher *nc,
+			 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->s2vk, 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..26371b8a
--- /dev/null
+++ b/siv-cmac.h
@@ -0,0 +1,139 @@
+/* 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 "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)
+
+struct siv_cmac_ctx {
+    uint8_t s2vk[SIV_MAX_KEY_SIZE/2];
+};
+
+void
+siv_cmac_set_key(struct siv_cmac_ctx *ctx, void *cipher,
+		 const struct nettle_cipher *nc,
+		 const uint8_t *key);
+
+void
+siv_cmac_encrypt_message(struct siv_cmac_ctx *ctx,
+			 const struct nettle_cipher *nc,
+			 void *cipher, 
+			 size_t nlength, const uint8_t *nonce,
+			 size_t alength, const uint8_t *adata,
+			 size_t slength, uint8_t *dst, const uint8_t *src);
+
+int
+siv_cmac_decrypt_message(struct siv_cmac_ctx *ctx,
+			 const struct nettle_cipher *nc,
+			 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 siv_cmac_ctx siv_cmac; type 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 tlength,
+				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 tlength,
+				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 tlength,
+				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 tlength,
+				size_t mlength, uint8_t *dst, const uint8_t *src);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NETTLE_SIV_H_INCLUDED */
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index c7e04cb4..98936b87 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 dd1ecf41..d08b1754 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -26,7 +26,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..dd58e679
--- /dev/null
+++ b/testsuite/siv-test.c
@@ -0,0 +1,332 @@
+/* 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. */
+{
+  int tlength = (e_cipher->length - e_clear->length);
+  if (digest && tlength && !MEMEQ(tlength, 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(tlength, digest);
+      fprintf(stderr, "\nExpected:");
+      print_hex(tlength, 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 *siv_encrypt,
+		nettle_decrypt_message *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;
+  size_t tlength;
+  int ret;
+
+  ASSERT (key->length == cipher->key_size*2);
+  ASSERT (cleartext->length <= ciphertext->length);
+  ASSERT ((cleartext->length + SIV_BLOCK_SIZE) >= ciphertext->length);
+  tlength = ciphertext->length - cleartext->length;
+
+  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, tlength,
+				  cleartext->length, en_data, cleartext->data);
+
+  ret = siv_decrypt(ctx, nonce->length, nonce->data,
+				        authdata->length, authdata->data, tlength,
+				        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. */
+  if (tlength) {
+    en_data[0] ^= 1;
+    ret = siv_decrypt(ctx, nonce->length, nonce->data,
+				          authdata->length, authdata->data, tlength,
+				          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 (tlength && authdata->length) {
+    en_data[0] ^= 1;
+    ret = siv_decrypt(ctx, nonce->length, nonce->data,
+				         authdata->length-1, authdata->data, tlength,
+				         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*)siv_aes128_cmac_encrypt_message, \
+			(nettle_decrypt_message*)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*)siv_aes256_cmac_encrypt_message, \
+			(nettle_decrypt_message*)siv_aes256_cmac_decrypt_message, ctx_size, cipher, \
+			key, nonce, authdata, cleartext, ciphertext)
+
+void
+test_main(void)
+{
+  /* Create a pattern of 00010203 04050607 08090a00b 0c0d0e0f ... */
+  struct tstring *adata;
+  unsigned int i;
+  adata = tstring_alloc(256);
+  for (i=0; i<adata->length; i++) adata->data[i] = (i & 0xff);
+
+  /*
+   * 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"));
+}
-- 
2.14.3

_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs

Reply via email to