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