]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Implement aes key wrap and key unwrap (RFC 3394)
authorNicolas Mora <git@babelouest.org>
Sun, 23 May 2021 19:04:58 +0000 (21:04 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Sun, 23 May 2021 19:06:32 +0000 (21:06 +0200)
Makefile.in
nist-keywrap.c [new file with mode: 0644]
nist-keywrap.h [new file with mode: 0644]
testsuite/.gitignore
testsuite/Makefile.in
testsuite/aes-keywrap-test.c [new file with mode: 0644]

index 0ace35f754dabc3b2d62558995147b7d7ce672d1..e63c3da00f8e01c845b03f7d2c079bac5c2a4431 100644 (file)
@@ -84,6 +84,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
                 aes192-meta.c \
                 aes256-set-encrypt-key.c aes256-set-decrypt-key.c \
                 aes256-meta.c \
+                nist-keywrap.c \
                 arcfour.c arcfour-crypt.c \
                 arctwo.c arctwo-meta.c blowfish.c blowfish-bcrypt.c \
                 base16-encode.c base16-decode.c base16-meta.c \
@@ -236,7 +237,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
          pgp.h pkcs1.h pss.h pss-mgf1.h realloc.h ripemd160.h rsa.h \
          salsa20.h sexp.h \
          serpent.h sha.h sha1.h sha2.h sha3.h streebog.h twofish.h \
-         umac.h yarrow.h xts.h poly1305.h
+         umac.h yarrow.h xts.h poly1305.h nist-keywrap.h
 
 INSTALL_HEADERS = $(HEADERS) version.h @IF_MINI_GMP@ mini-gmp.h
 
diff --git a/nist-keywrap.c b/nist-keywrap.c
new file mode 100644 (file)
index 0000000..677a6bb
--- /dev/null
@@ -0,0 +1,200 @@
+/* nist-keywrap.c
+
+   AES Key Wrap function.
+   implements RFC 3394
+   https://tools.ietf.org/html/rfc3394
+
+   Copyright (C) 2021 Nicolas Mora
+                 2021 Niels Möller
+
+   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 "nist-keywrap.h"
+#include "memops.h"
+#include "macros.h"
+
+#if WORDS_BIGENDIAN
+#define bswap_if_le(x) (x)
+#elif HAVE_BUILTIN_BSWAP64
+#define bswap_if_le(x) (__builtin_bswap64 (x))
+#else
+static uint64_t
+bswap_if_le (uint64_t x)
+{
+  x = ((x >> 32) & UINT64_C (0xffffffff))
+    | ((x & UINT64_C (0xffffffff)) << 32);
+  x = ((x >> 16) & UINT64_C (0xffff0000ffff))
+    | ((x & UINT64_C (0xffff0000ffff)) << 16);
+  x = ((x >> 8) & UINT64_C (0xff00ff00ff00ff))
+    | ((x & UINT64_C (0xff00ff00ff00ff)) << 8);
+  return x;
+}
+#endif
+
+void
+nist_keywrap16 (const void *ctx, nettle_cipher_func *encrypt,
+               const uint8_t *iv, size_t ciphertext_length,
+               uint8_t *ciphertext, const uint8_t *cleartext)
+{
+  union nettle_block16 I, B;
+  union nettle_block8 A;
+  size_t i, j, n;
+  uint8_t *R = ciphertext + 8;
+
+  /* ciphertext_length must be at least 16
+   * and be divisible by 8 */
+  assert (ciphertext_length >= 16);
+  assert (!(ciphertext_length % 8));
+
+  n = (ciphertext_length - 8) / 8;
+  memcpy (R, cleartext, (ciphertext_length - 8));
+  memcpy (A.b, iv, 8);
+
+  for (j = 0; j < 6; j++)
+    {
+      for (i = 0; i < n; i++)
+       {
+         // I = A | R[1]
+         I.u64[0] = A.u64;
+         memcpy (I.b + 8, R + (i * 8), 8);
+
+         // B = AES(K, I)
+         encrypt (ctx, 16, B.b, I.b);
+
+         // A = MSB(64, B) ^ t where t = (n*j)+i
+         A.u64 = B.u64[0] ^ bswap_if_le ((n * j) + (i + 1));
+
+         // R[i] = LSB(64, B)
+         memcpy (R + (i * 8), B.b + 8, 8);
+       }
+    }
+
+  memcpy (ciphertext, A.b, 8);
+}
+
+int
+nist_keyunwrap16 (const void *ctx, nettle_cipher_func *decrypt,
+                 const uint8_t *iv, size_t cleartext_length,
+                 uint8_t *cleartext, const uint8_t *ciphertext)
+{
+  union nettle_block16 I, B;
+  union nettle_block8 A;
+  int i, j;
+  size_t n;
+  uint8_t *R = cleartext;
+
+  /* cleartext_length must be at least 8
+   * and be divisible by 8 */
+  assert (cleartext_length >= 8);
+  assert (!(cleartext_length % 8));
+
+  n = (cleartext_length / 8);
+  memcpy (A.b, ciphertext, 8);
+  memcpy (R, ciphertext + 8, cleartext_length);
+
+  for (j = 5; j >= 0; j--)
+    {
+      for (i = n - 1; i >= 0; i--)
+       {
+         // B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
+         I.u64[0] = A.u64 ^ bswap_if_le ((n * j) + (i + 1));
+         memcpy (I.b + 8, R + (i * 8), 8);
+         decrypt (ctx, 16, B.b, I.b);
+
+         // A = MSB(64, B)
+         A.u64 = B.u64[0];
+
+         // R[i] = LSB(64, B)
+         memcpy (R + (i * 8), B.b + 8, 8);
+         //R[i*8] = B.u64[1];
+       }
+    }
+
+  return memeql_sec (A.b, iv, 8);
+}
+
+void
+aes128_keywrap (struct aes128_ctx *ctx,
+               const uint8_t *iv, size_t ciphertext_length,
+               uint8_t *ciphertext, const uint8_t *cleartext)
+{
+  nist_keywrap16 (ctx, (nettle_cipher_func *) & aes128_encrypt,
+                 iv, ciphertext_length, ciphertext, cleartext);
+}
+
+void
+aes192_keywrap (struct aes192_ctx *ctx,
+               const uint8_t *iv, size_t ciphertext_length,
+               uint8_t *ciphertext, const uint8_t *cleartext)
+{
+  nist_keywrap16 (ctx, (nettle_cipher_func *) & aes192_encrypt,
+                 iv, ciphertext_length, ciphertext, cleartext);
+}
+
+void
+aes256_keywrap (struct aes256_ctx *ctx,
+               const uint8_t *iv, size_t ciphertext_length,
+               uint8_t *ciphertext, const uint8_t *cleartext)
+{
+  nist_keywrap16 (ctx, (nettle_cipher_func *) & aes256_encrypt,
+                 iv, ciphertext_length, ciphertext, cleartext);
+}
+
+int
+aes128_keyunwrap (struct aes128_ctx *ctx,
+                 const uint8_t *iv, size_t cleartext_length,
+                 uint8_t *cleartext, const uint8_t *ciphertext)
+{
+  return nist_keyunwrap16 (ctx, (nettle_cipher_func *) & aes128_decrypt,
+                          iv, cleartext_length, cleartext, ciphertext);
+}
+
+int
+aes192_keyunwrap (struct aes192_ctx *ctx,
+                 const uint8_t *iv, size_t cleartext_length,
+                 uint8_t *cleartext, const uint8_t *ciphertext)
+{
+  return nist_keyunwrap16 (ctx, (nettle_cipher_func *) & aes192_decrypt,
+                          iv, cleartext_length, cleartext, ciphertext);
+}
+
+int
+aes256_keyunwrap (struct aes256_ctx *ctx,
+                 const uint8_t *iv, size_t cleartext_length,
+                 uint8_t *cleartext, const uint8_t *ciphertext)
+{
+  return nist_keyunwrap16 (ctx, (nettle_cipher_func *) & aes256_decrypt,
+                          iv, cleartext_length, cleartext, ciphertext);
+}
diff --git a/nist-keywrap.h b/nist-keywrap.h
new file mode 100644 (file)
index 0000000..39f4eae
--- /dev/null
@@ -0,0 +1,101 @@
+/* nist-keywrap.h
+
+   AES Key Wrap function.
+   implements RFC 3394
+   https://tools.ietf.org/html/rfc3394
+
+   Copyright (C) 2021 Nicolas Mora
+                 2021 Niels Möller
+
+   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_NIST_KEYWRAP_H_INCLUDED
+#define NETTLE_NIST_KEYWRAP_H_INCLUDED
+
+#include "nettle-types.h"
+#include "aes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Name mangling */
+#define nist_keywrap16 nettle_nist_keywrap16
+#define nist_keyunwrap16 nettle_nist_keyunwrap16
+#define aes128_keywrap nettle_aes128_keywrap
+#define aes192_keywrap nettle_aes192_keywrap
+#define aes256_keywrap nettle_aes256_keywrap
+#define aes128_keyunwrap nettle_aes128_keyunwrap
+#define aes192_keyunwrap nettle_aes192_keyunwrap
+#define aes256_keyunwrap nettle_aes256_keyunwrap
+
+void
+nist_keywrap16 (const void *ctx, nettle_cipher_func *encrypt,
+               const uint8_t *iv, size_t ciphertext_length,
+               uint8_t *ciphertext, const uint8_t *cleartext);
+
+int
+nist_keyunwrap16 (const void *ctx, nettle_cipher_func *decrypt,
+        const uint8_t *iv, size_t cleartext_length,
+        uint8_t *cleartext, const uint8_t *ciphertext);
+
+void
+aes128_keywrap (struct aes128_ctx *ctx,
+               const uint8_t *iv, size_t ciphertext_length,
+               uint8_t *ciphertext, const uint8_t *cleartext);
+
+void
+aes192_keywrap (struct aes192_ctx *ctx,
+               const uint8_t *iv, size_t ciphertext_length,
+               uint8_t *ciphertext, const uint8_t *cleartext);
+
+void
+aes256_keywrap (struct aes256_ctx *ctx,
+               const uint8_t *iv, size_t ciphertext_length,
+               uint8_t *ciphertext, const uint8_t *cleartext);
+
+int
+aes128_keyunwrap (struct aes128_ctx *ctx,
+                 const uint8_t *iv, size_t cleartext_length,
+                 uint8_t *cleartext, const uint8_t *ciphertext);
+
+int
+aes192_keyunwrap (struct aes192_ctx *ctx,
+                 const uint8_t *iv, size_t cleartext_length,
+                 uint8_t *cleartext, const uint8_t *ciphertext);
+
+int
+aes256_keyunwrap (struct aes256_ctx *ctx,
+                 const uint8_t *iv, size_t cleartext_length,
+                 uint8_t *cleartext, const uint8_t *ciphertext);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif                         /* NETTLE_NIST_KEYWRAP_H_INCLUDED */
index 6a80f5e605eb22c01408e4563d6d554557ecbf9d..9d8a7681c5365a992c041d45ec0ca65e4acc9f57 100644 (file)
@@ -1,6 +1,7 @@
 /*.d
 /Makefile
 /aes-test
+/aes-keywrap-test
 /arcfour-test
 /arctwo-test
 /base16-test
index 40b01d519b595ab58ad66f4fabb527609dc9e2f7..2b554261eeffcd99074c3ec617eb7ce54ede91d5 100644 (file)
@@ -10,7 +10,7 @@ include ../config.make
 PRE_CPPFLAGS = -I.. -I$(top_srcdir)
 PRE_LDFLAGS = -L..
 
-TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
+TS_NETTLE_SOURCES = aes-test.c aes-keywrap-test.c arcfour-test.c arctwo-test.c \
                    blowfish-test.c bcrypt-test.c cast128-test.c \
                    base16-test.c base64-test.c \
                    camellia-test.c chacha-test.c \
diff --git a/testsuite/aes-keywrap-test.c b/testsuite/aes-keywrap-test.c
new file mode 100644 (file)
index 0000000..2f19c9b
--- /dev/null
@@ -0,0 +1,482 @@
+#include "testutils.h"
+#include "nist-keywrap.h"
+
+typedef void nettle_nist_keywrap_func(const void *ctx,
+                 const uint8_t * iv, size_t cleartext_length,
+                 uint8_t * cleartext, const uint8_t * ciphertext);
+
+typedef int nettle_nist_keyunwrap_func(const void *ctx,
+                 const uint8_t * iv, size_t cleartext_length,
+                 uint8_t * cleartext, const uint8_t * ciphertext);
+
+
+struct nettle_wrap
+{
+  void *ctx;
+  nettle_set_key_func *set_encrypt_key;
+  nettle_cipher_func *encrypt;
+  nettle_set_key_func *set_decrypt_key;
+  nettle_cipher_func *decrypt;
+};
+
+struct nettle_specific_wrap
+{
+  void *ctx;
+  nettle_set_key_func *set_encrypt_key;
+  nettle_nist_keywrap_func *keywrap_func;
+  nettle_set_key_func *set_decrypt_key;
+  nettle_nist_keyunwrap_func *keyunwrap_func;
+};
+
+static void
+test_wrap (struct nettle_wrap *w,
+          const struct tstring *key,
+          const struct tstring *iv,
+          const struct tstring *cleartext, const struct tstring *ciphertext)
+{
+  uint8_t data[40];
+  w->set_encrypt_key (w->ctx, key->data);
+  nist_keywrap16 (w->ctx, w->encrypt,
+                 iv->data, cleartext->length + 8, data, cleartext->data);
+  if (!MEMEQ (ciphertext->length, data, ciphertext->data))
+    {
+      fprintf (stderr, "test_wrap: Wrap failed:");
+      fprintf (stderr, "\nOutput: ");
+      print_hex (ciphertext->length, data);
+      fprintf (stderr, "\nExpected:");
+      tstring_print_hex (ciphertext);
+      fprintf (stderr, "\n");
+      FAIL ();
+    }
+}
+
+static void
+test_unwrap (struct nettle_wrap *w,
+            const struct tstring *key,
+            const struct tstring *iv,
+            const struct tstring *ciphertext,
+            const struct tstring *cleartext)
+{
+  uint8_t data[32];
+  w->set_decrypt_key (w->ctx, key->data);
+  nist_keyunwrap16 (w->ctx, w->decrypt,
+                   iv->data, cleartext->length, data, ciphertext->data);
+  if (!MEMEQ (cleartext->length, data, cleartext->data))
+    {
+      fprintf (stderr, "test_unwrap: Wrap failed:");
+      fprintf (stderr, "\nOutput: ");
+      print_hex (cleartext->length, data);
+      fprintf (stderr, "\nExpected:");
+      tstring_print_hex (cleartext);
+      fprintf (stderr, "\n");
+      FAIL ();
+    }
+}
+
+static void
+test_unwrap_fail (struct nettle_wrap *w,
+            const struct tstring *key,
+            const struct tstring *iv,
+            const struct tstring *ciphertext)
+{
+  uint8_t data[32];
+  w->set_decrypt_key (w->ctx, key->data);
+  if (nist_keyunwrap16 (w->ctx, w->decrypt,
+                   iv->data, ciphertext->length-8, data, ciphertext->data))
+    {
+      FAIL ();
+    }
+}
+
+static void
+test_specific_wrap (struct nettle_specific_wrap *w,
+                   const struct tstring *key,
+                   const struct tstring *iv,
+                   const struct tstring *cleartext,
+                   const struct tstring *ciphertext)
+{
+  uint8_t data[40];
+  w->set_encrypt_key (w->ctx, key->data);
+  w->keywrap_func (w->ctx,
+                  iv->data, cleartext->length + 8, data, cleartext->data);
+  if (!MEMEQ (ciphertext->length, data, ciphertext->data))
+    {
+      fprintf (stderr, "test_specific_wrap: Wrap failed:");
+      fprintf (stderr, "\nOutput: ");
+      print_hex (ciphertext->length, data);
+      fprintf (stderr, "\nExpected:");
+      tstring_print_hex (ciphertext);
+      fprintf (stderr, "\n");
+      FAIL ();
+    }
+}
+
+static void
+test_specific_unwrap (struct nettle_specific_wrap *w,
+                     const struct tstring *key,
+                     const struct tstring *iv,
+                     const struct tstring *ciphertext,
+                     const struct tstring *cleartext)
+{
+  uint8_t data[32];
+  w->set_decrypt_key (w->ctx, key->data);
+  w->keyunwrap_func (w->ctx,
+                    iv->data, cleartext->length, data, ciphertext->data);
+  if (!MEMEQ (cleartext->length, data, cleartext->data))
+    {
+      fprintf (stderr, "test_unwrap: Wrap failed:");
+      fprintf (stderr, "\nOutput: ");
+      print_hex (cleartext->length, data);
+      fprintf (stderr, "\nExpected:");
+      tstring_print_hex (cleartext);
+      fprintf (stderr, "\n");
+      FAIL ();
+    }
+}
+
+static void
+test_specific_unwrap_fail (struct nettle_specific_wrap *w,
+                     const struct tstring *key,
+                     const struct tstring *iv,
+                     const struct tstring *ciphertext)
+{
+  uint8_t data[32];
+  w->set_decrypt_key (w->ctx, key->data);
+  if (w->keyunwrap_func (w->ctx,
+                    iv->data, ciphertext->length-8, data, ciphertext->data))
+    {
+      FAIL ();
+    }
+}
+
+void
+test_main (void)
+{
+  struct aes128_ctx ctx_128;
+  struct aes192_ctx ctx_192;
+  struct aes256_ctx ctx_256;
+  struct nettle_wrap wrap128, wrap192, wrap256;
+  struct nettle_wrap unwrap128, unwrap192, unwrap256;
+  struct nettle_specific_wrap swrap128, swrap192, swrap256;
+  struct nettle_specific_wrap sunwrap128, sunwrap192, sunwrap256;
+
+  wrap128.ctx = &ctx_128;
+  wrap128.set_encrypt_key = (nettle_set_key_func *) & aes128_set_encrypt_key;
+  wrap128.encrypt = (nettle_cipher_func *) & aes128_encrypt;
+
+  unwrap128.ctx = &ctx_128;
+  unwrap128.set_decrypt_key =
+    (nettle_set_key_func *) & aes128_set_decrypt_key;
+  unwrap128.decrypt = (nettle_cipher_func *) & aes128_decrypt;
+
+  wrap192.ctx = &ctx_192;
+  wrap192.set_encrypt_key = (nettle_set_key_func *) & aes192_set_encrypt_key;
+  wrap192.encrypt = (nettle_cipher_func *) & aes192_encrypt;
+
+  unwrap192.ctx = &ctx_192;
+  unwrap192.set_decrypt_key =
+    (nettle_set_key_func *) & aes192_set_decrypt_key;
+  unwrap192.decrypt = (nettle_cipher_func *) & aes192_decrypt;
+
+  wrap256.ctx = &ctx_256;
+  wrap256.set_encrypt_key = (nettle_set_key_func *) & aes256_set_encrypt_key;
+  wrap256.encrypt = (nettle_cipher_func *) & aes256_encrypt;
+
+  unwrap256.ctx = &ctx_256;
+  unwrap256.set_decrypt_key =
+    (nettle_set_key_func *) & aes256_set_decrypt_key;
+  unwrap256.decrypt = (nettle_cipher_func *) & aes256_decrypt;
+
+  swrap128.ctx = &ctx_128;
+  swrap128.set_encrypt_key = (nettle_set_key_func *) & aes128_set_encrypt_key;
+  swrap128.keywrap_func = (nettle_nist_keywrap_func *) & aes128_keywrap;
+
+  swrap192.ctx = &ctx_192;
+  swrap192.set_encrypt_key = (nettle_set_key_func *) & aes192_set_encrypt_key;
+  swrap192.keywrap_func = (nettle_nist_keywrap_func *) & aes192_keywrap;
+
+  swrap256.ctx = &ctx_256;
+  swrap256.set_encrypt_key = (nettle_set_key_func *) & aes256_set_encrypt_key;
+  swrap256.keywrap_func = (nettle_nist_keywrap_func *) & aes256_keywrap;
+
+  sunwrap128.ctx = &ctx_128;
+  sunwrap128.set_decrypt_key =
+    (nettle_set_key_func *) & aes128_set_decrypt_key;
+  sunwrap128.keyunwrap_func =
+    (nettle_nist_keyunwrap_func *) & aes128_keyunwrap;
+
+  sunwrap192.ctx = &ctx_192;
+  sunwrap192.set_decrypt_key =
+    (nettle_set_key_func *) & aes192_set_decrypt_key;
+  sunwrap192.keyunwrap_func =
+    (nettle_nist_keyunwrap_func *) & aes192_keyunwrap;
+
+  sunwrap256.ctx = &ctx_256;
+  sunwrap256.set_decrypt_key =
+    (nettle_set_key_func *) & aes256_set_decrypt_key;
+  sunwrap256.keyunwrap_func =
+    (nettle_nist_keyunwrap_func *) & aes256_keyunwrap;
+
+  test_wrap (&wrap128,
+            SHEX ("0001020304050607 08090A0B0C0D0E0F"),
+            SHEX ("A6A6A6A6A6A6A6A6"),
+            SHEX ("0011223344556677 8899AABBCCDDEEFF"),
+            SHEX ("1FA68B0A8112B447 AEF34BD8FB5A7B82 9D3E862371D2CFE5"));
+
+  test_unwrap (&unwrap128,
+              SHEX ("0001020304050607 08090A0B0C0D0E0F"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX ("1FA68B0A8112B447 AEF34BD8FB5A7B82 9D3E862371D2CFE5"),
+              SHEX ("0011223344556677 8899AABBCCDDEEFF"));
+
+  test_unwrap_fail (&unwrap128,
+              SHEX ("0001020304050607 08090A0B0C0D0E0F"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX ("1EA68B0A8112B447 AEF34BD8FB5A7B82 9D3E862371D2CFE5"));
+
+  test_wrap (&wrap192,
+            SHEX ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+            SHEX ("A6A6A6A6A6A6A6A6"),
+            SHEX ("0011223344556677 8899AABBCCDDEEFF"),
+            SHEX ("96778B25AE6CA435 F92B5B97C050AED2 468AB8A17AD84E5D"));
+
+  test_unwrap (&unwrap192,
+              SHEX ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX ("96778B25AE6CA435 F92B5B97C050AED2 468AB8A17AD84E5D"),
+              SHEX ("0011223344556677 8899AABBCCDDEEFF"));
+
+  test_unwrap_fail (&unwrap192,
+              SHEX ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX ("96778B25AE6CA435 F92B5B97C050AED2 468AB8A17AD84E5E"));
+
+  test_wrap (&wrap256,
+            SHEX
+            ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+            SHEX ("A6A6A6A6A6A6A6A6"),
+            SHEX ("0011223344556677 8899AABBCCDDEEFF"),
+            SHEX ("64E8C3F9CE0F5BA2 63E9777905818A2A 93C8191E7D6E8AE7"));
+
+  test_unwrap (&unwrap256,
+              SHEX
+              ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX ("64E8C3F9CE0F5BA2 63E9777905818A2A 93C8191E7D6E8AE7"),
+              SHEX ("0011223344556677 8899AABBCCDDEEFF"));
+
+  test_unwrap_fail (&unwrap256,
+              SHEX
+              ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX ("64E8C3F9CE0F5BA2 63E9777905818A2A 93C8191E7D6E8AE6"));
+
+  test_wrap (&wrap192,
+            SHEX ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+            SHEX ("A6A6A6A6A6A6A6A6"),
+            SHEX ("0011223344556677 8899AABBCCDDEEFF 0001020304050607"),
+            SHEX
+            ("031D33264E15D332 68F24EC260743EDC E1C6C7DDEE725A93 6BA814915C6762D2"));
+
+  test_unwrap (&unwrap192,
+              SHEX ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX
+              ("031D33264E15D332 68F24EC260743EDC E1C6C7DDEE725A93 6BA814915C6762D2"),
+              SHEX ("0011223344556677 8899AABBCCDDEEFF 0001020304050607"));
+
+  test_unwrap_fail (&unwrap192,
+              SHEX ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX
+              ("031D33264E15D332 68F24EC260743EDC E1C6C7DDEE725B93 6BA814915C6762D2"));
+
+  test_wrap (&wrap256,
+            SHEX
+            ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+            SHEX ("A6A6A6A6A6A6A6A6"),
+            SHEX ("0011223344556677 8899AABBCCDDEEFF 0001020304050607"),
+            SHEX
+            ("A8F9BC1612C68B3F F6E6F4FBE30E71E4 769C8B80A32CB895 8CD5D17D6B254DA1"));
+
+  test_unwrap (&unwrap256,
+              SHEX
+              ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX
+              ("A8F9BC1612C68B3F F6E6F4FBE30E71E4 769C8B80A32CB895 8CD5D17D6B254DA1"),
+              SHEX ("0011223344556677 8899AABBCCDDEEFF 0001020304050607"));
+
+  test_unwrap_fail (&unwrap256,
+              SHEX
+              ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX
+              ("A8F9BC1612C68B3F F6E6F4FBE30E71E5 769C8B80A32CB895 8CD5D17D6B254DA1"));
+
+  test_wrap (&wrap256,
+            SHEX
+            ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+            SHEX ("A6A6A6A6A6A6A6A6"),
+            SHEX
+            ("0011223344556677 8899AABBCCDDEEFF 0001020304050607 08090A0B0C0D0E0F"),
+            SHEX
+            ("28C9F404C4B810F4 CBCCB35CFB87F826 3F5786E2D80ED326 CBC7F0E71A99F43B FB988B9B7A02DD21"));
+
+  test_unwrap (&unwrap256,
+              SHEX
+              ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX
+              ("28C9F404C4B810F4 CBCCB35CFB87F826 3F5786E2D80ED326 CBC7F0E71A99F43B FB988B9B7A02DD21"),
+              SHEX
+              ("0011223344556677 8899AABBCCDDEEFF 0001020304050607 08090A0B0C0D0E0F"));
+
+  test_unwrap_fail (&unwrap256,
+              SHEX
+              ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+              SHEX ("A6A6A6A6A6A6A6A6"),
+              SHEX
+              ("28C9F404C4B810F4 CBCCB35CFB87F816 3F5786E2D80ED326 CBC7F0E71A99F43B FB988B9B7A02DD21"));
+
+  test_specific_wrap (&swrap128,
+                     SHEX ("0001020304050607 08090A0B0C0D0E0F"),
+                     SHEX ("A6A6A6A6A6A6A6A6"),
+                     SHEX ("0011223344556677 8899AABBCCDDEEFF"),
+                     SHEX
+                     ("1FA68B0A8112B447 AEF34BD8FB5A7B82 9D3E862371D2CFE5"));
+
+  test_specific_unwrap (&sunwrap128,
+                       SHEX ("0001020304050607 08090A0B0C0D0E0F"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("1FA68B0A8112B447 AEF34BD8FB5A7B82 9D3E862371D2CFE5"),
+                       SHEX ("0011223344556677 8899AABBCCDDEEFF"));
+
+  test_specific_unwrap_fail (&sunwrap128,
+                       SHEX ("0001020304050607 08090A0B0C0D0E0F"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("1FA68B0A8112B446 AEF34BD8FB5A7B82 9D3E862371D2CFE5"));
+
+  test_specific_wrap (&swrap192,
+                     SHEX
+                     ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+                     SHEX ("A6A6A6A6A6A6A6A6"),
+                     SHEX ("0011223344556677 8899AABBCCDDEEFF"),
+                     SHEX
+                     ("96778B25AE6CA435 F92B5B97C050AED2 468AB8A17AD84E5D"));
+
+  test_specific_unwrap (&sunwrap192,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("96778B25AE6CA435 F92B5B97C050AED2 468AB8A17AD84E5D"),
+                       SHEX ("0011223344556677 8899AABBCCDDEEFF"));
+
+  test_specific_unwrap_fail (&sunwrap192,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("96778B25AE6CA435 F92B5B97C050AED2 478AB8A17AD84E5D"));
+
+  test_specific_wrap (&swrap256,
+                     SHEX
+                     ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+                     SHEX ("A6A6A6A6A6A6A6A6"),
+                     SHEX ("0011223344556677 8899AABBCCDDEEFF"),
+                     SHEX
+                     ("64E8C3F9CE0F5BA2 63E9777905818A2A 93C8191E7D6E8AE7"));
+
+  test_specific_unwrap (&sunwrap256,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("64E8C3F9CE0F5BA2 63E9777905818A2A 93C8191E7D6E8AE7"),
+                       SHEX ("0011223344556677 8899AABBCCDDEEFF"));
+
+  test_specific_unwrap_fail (&sunwrap256,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("64E8C3F9CE0F5BA2 63E9777905818A2A 93C8101E7D6E8AE7"));
+
+  test_specific_wrap (&swrap192,
+                     SHEX
+                     ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+                     SHEX ("A6A6A6A6A6A6A6A6"),
+                     SHEX
+                     ("0011223344556677 8899AABBCCDDEEFF 0001020304050607"),
+                     SHEX
+                     ("031D33264E15D332 68F24EC260743EDC E1C6C7DDEE725A93 6BA814915C6762D2"));
+
+  test_specific_unwrap (&sunwrap192,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("031D33264E15D332 68F24EC260743EDC E1C6C7DDEE725A93 6BA814915C6762D2"),
+                       SHEX
+                       ("0011223344556677 8899AABBCCDDEEFF 0001020304050607"));
+
+  test_specific_unwrap_fail (&sunwrap192,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("031D33264E15D332 68F24EC260743EDC E1C6C7DDEF725A93 6BA814915C6762D2"));
+
+  test_specific_wrap (&swrap256,
+                     SHEX
+                     ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+                     SHEX ("A6A6A6A6A6A6A6A6"),
+                     SHEX
+                     ("0011223344556677 8899AABBCCDDEEFF 0001020304050607"),
+                     SHEX
+                     ("A8F9BC1612C68B3F F6E6F4FBE30E71E4 769C8B80A32CB895 8CD5D17D6B254DA1"));
+
+  test_specific_unwrap (&sunwrap256,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("A8F9BC1612C68B3F F6E6F4FBE30E71E4 769C8B80A32CB895 8CD5D17D6B254DA1"),
+                       SHEX
+                       ("0011223344556677 8899AABBCCDDEEFF 0001020304050607"));
+
+  test_specific_unwrap_fail (&sunwrap256,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("A8F9BC1612C68C3F F6E6F4FBE30E71E4 769C8B80A32CB895 8CD5D17D6B254DA1"));
+
+  test_specific_wrap (&swrap256,
+                     SHEX
+                     ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+                     SHEX ("A6A6A6A6A6A6A6A6"),
+                     SHEX
+                     ("0011223344556677 8899AABBCCDDEEFF 0001020304050607 08090A0B0C0D0E0F"),
+                     SHEX
+                     ("28C9F404C4B810F4 CBCCB35CFB87F826 3F5786E2D80ED326 CBC7F0E71A99F43B FB988B9B7A02DD21"));
+
+  test_specific_unwrap (&sunwrap256,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("28C9F404C4B810F4 CBCCB35CFB87F826 3F5786E2D80ED326 CBC7F0E71A99F43B FB988B9B7A02DD21"),
+                       SHEX
+                       ("0011223344556677 8899AABBCCDDEEFF 0001020304050607 08090A0B0C0D0E0F"));
+
+  test_specific_unwrap_fail (&sunwrap256,
+                       SHEX
+                       ("0001020304050607 08090A0B0C0D0E0F 1011121314151617 18191A1B1C1D1E1F"),
+                       SHEX ("A6A6A6A6A6A6A6A6"),
+                       SHEX
+                       ("28C9F404C4B810F4 CBCCB35CFB87F826 3F5786E2D80ED426 CBC7F0E71A99F43B FB988B9B7A02DD21"));
+}