]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Rework OCB tests.
authorNiels Möller <nisse@lysator.liu.se>
Mon, 24 Apr 2023 17:47:53 +0000 (19:47 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Mon, 24 Apr 2023 17:47:53 +0000 (19:47 +0200)
ChangeLog
testsuite/ocb-test.c
testsuite/testutils.c
testsuite/testutils.h

index 9febf4c6ad70faa889864e8ddd7a3865aac76a2f..1334eb370e35a1a5e3a1662b547b5e4038cf05fa 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2023-04-24  Niels Möller  <nisse@lysator.liu.se>
+
+       Rework tests of OCB message functions.
+       * testsuite/testutils.c (test_aead_message): New function, for
+       testing AEAD message functions.
+       * testsuite/testutils.h (nettle_encrypt_message_func)
+       (nettle_decrypt_message_func): New typedefs.
+       (struct nettle_aead_message): New struct.
+       * testsuite/ocb-test.c (nettle_encrypt_message_func)
+       (nettle_decrypt_message_func): Deleted typedefs.
+       (test_compare_results): Deleted function.
+       (test_ocb_aes128): Deleted macro.
+       (struct ocb_aes128_message_key): New struct.
+       (ocb_aes128_set_encrypt_key_wrapper)
+       (ocb_aes128_set_decrypt_key_wrapper)
+       (ocb_aes128_encrypt_message_wrapper)
+       (ocb_aes128_decrypt_message_wrapper): New wrapper functions, using
+       above ocb_aes128_message_key for both encrypt and decrypt, and a
+       fix tag length of 16 octets.
+       (ocb_aes128_message): New algorithm struct, with above wrappers.
+       (test_main): Use test_aead_message.
+
 2023-04-23  Niels Möller  <nisse@lysator.liu.se>
 
        * testsuite/siv-cmac-test.c: Renamed file, from...
index d377b3ec0c3ddfc078c2178a97eb3bdfc54b585f..3892dddaad9e8ae0b577bc9b813e7c735fbdc7f6 100644 (file)
 #include "testutils.h"
 #include "nettle-internal.h"
 
-/* FIXME: Lots of almost duplicated code with siv tests. */
-/* AEAD ciphers */
-typedef void
-nettle_encrypt_message_func(const 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_func(const void *encrypt_ctx, const void *decrypt_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);
+struct ocb_aes128_message_key
+{
+  struct ocb_aes128_encrypt_key encrypt_key;
+  struct aes128_ctx decrypt_key;
+};
 
 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)
+ocb_aes128_set_encrypt_key_wrapper (struct ocb_aes128_message_key *key,
+                                   const uint8_t *aes_key)
 {
-  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 */
-
+  ocb_aes128_set_encrypt_key (&key->encrypt_key, aes_key);
+}
 static void
-test_ocb_message(const char *name,
-                nettle_set_key_func *set_encrypt_key,
-                nettle_set_key_func *set_decrypt_key,
-                nettle_encrypt_message_func *encrypt,
-                nettle_decrypt_message_func *decrypt,
-                size_t encrypt_context_size, size_t decrypt_context_size,
-                size_t key_size, size_t digest_size,
-                const struct tstring *key,
-                const struct tstring *nonce,
-                const struct tstring *authdata,
-                const struct tstring *cleartext,
-                const struct tstring *ciphertext)
+ocb_aes128_set_decrypt_key_wrapper (struct ocb_aes128_message_key *key,
+                                   const uint8_t *aes_key)
 {
-  void *encrypt_ctx = xalloc(encrypt_context_size);
-  void *decrypt_ctx = xalloc(decrypt_context_size);
-  uint8_t *en_data;
-  uint8_t *de_data;
-  int ret;
-
-  ASSERT (key->length == key_size);
-  ASSERT (cleartext->length + digest_size == ciphertext->length);
-
-  de_data = xalloc(cleartext->length);
-  en_data = xalloc(ciphertext->length);
-
-  /* Ensure we get the same answers using the all-in-one API. */
-  memset(de_data, 0, cleartext->length);
-  memset(en_data, 0, ciphertext->length);
-
-  set_encrypt_key(encrypt_ctx, key->data);
-  encrypt(encrypt_ctx, nonce->length, nonce->data,
-         authdata->length, authdata->data, digest_size,
-         ciphertext->length, en_data, cleartext->data);
-
-  set_decrypt_key(decrypt_ctx, key->data);
-
-  ret = decrypt(encrypt_ctx, decrypt_ctx, nonce->length, nonce->data,
-               authdata->length, authdata->data, digest_size,
-               cleartext->length, de_data, ciphertext->data);
-
-  if (ret != 1)
-    {
-      fprintf(stderr, "decrypt_message failed to validate message\n");
-      FAIL();
-    }
-  test_compare_results(name, authdata,
-                      cleartext, ciphertext, de_data, en_data);
-
-  /* Ensure that we can detect corrupted message or tag data. */
-  en_data[0] ^= 1;
-  ret = decrypt(encrypt_ctx, decrypt_ctx, nonce->length, nonce->data,
-               authdata->length, authdata->data, digest_size,
-               cleartext->length, de_data, en_data);
-  if (ret != 0)
-    {
-      fprintf(stderr, "decrypt_message failed to detect corrupted message\n");
-      FAIL();
-    }
-
-  /* Ensure we can detect corrupted adata. */
-  if (authdata->length) {
-    en_data[0] ^= 1;
-    ret = decrypt(encrypt_ctx, decrypt_ctx, nonce->length, nonce->data,
-                 authdata->length-1, authdata->data, digest_size,
-                 cleartext->length, de_data, en_data);
-    if (ret != 0)
-      {
-       fprintf(stderr, "siv_decrypt_message failed to detect corrupted message\n");
-       FAIL();
-      }
-  }
-
-  free(encrypt_ctx);
-  free(decrypt_ctx);
-  free(en_data);
-  free(de_data);
+  ocb_aes128_set_decrypt_key (&key->encrypt_key, &key->decrypt_key, aes_key);
+}
+static void
+ocb_aes128_encrypt_message_wrapper (const struct ocb_aes128_message_key *key,
+                                   size_t nlength, const uint8_t *nonce,
+                                   size_t alength, const uint8_t *adata,
+                                   size_t clength, uint8_t *dst, const uint8_t *src)
+{
+  ocb_aes128_encrypt_message (&key->encrypt_key, nlength, nonce, alength, adata,
+                             OCB_DIGEST_SIZE, clength, dst, src);
+}
+static int
+ocb_aes128_decrypt_message_wrapper (const struct ocb_aes128_message_key *key,
+                                   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 ocb_aes128_decrypt_message (&key->encrypt_key, &key->decrypt_key,
+                                    nlength, nonce, alength, adata,
+                                    OCB_DIGEST_SIZE, mlength, dst, src);
 }
 
-#define test_ocb_aes128(key, nonce, authdata, cleartext, ciphertext) \
-  test_ocb_message("ocb_aes128",                                       \
-                  (nettle_set_key_func*)ocb_aes128_set_encrypt_key,    \
-                  (nettle_set_key_func*)aes128_set_decrypt_key,        \
-                  (nettle_encrypt_message_func*)ocb_aes128_encrypt_message, \
-                  (nettle_decrypt_message_func*)ocb_aes128_decrypt_message, \
-                  sizeof(struct ocb_aes128_ctx), sizeof(struct aes128_ctx), \
-                  AES128_KEY_SIZE, OCB_DIGEST_SIZE,                    \
-                  key, nonce, authdata, cleartext, ciphertext)
+static const struct nettle_aead_message
+ocb_aes128_message = {
+  "ocb_aes128",
+  sizeof(struct ocb_aes128_message_key),
+  AES128_KEY_SIZE,
+  OCB_DIGEST_SIZE,
+  1, /* Supports in-place operation. */
+  (nettle_set_key_func*) ocb_aes128_set_encrypt_key_wrapper,
+  (nettle_set_key_func*) ocb_aes128_set_decrypt_key_wrapper,
+  (nettle_encrypt_message_func*) ocb_aes128_encrypt_message_wrapper,
+  (nettle_decrypt_message_func*) ocb_aes128_decrypt_message_wrapper,
+};
 
 /* For 96-bit tag */
 static void
@@ -376,14 +284,14 @@ test_main(void)
            SHEX("8a24edb596b59425 43ec197d5369979b")); /* tag */
 
   /* Test the all-in-one message functions. */
-  test_ocb_aes128(
+  test_aead_message(&ocb_aes128_message,
            SHEX("000102030405060708090A0B0C0D0E0F"), /* key */
            SHEX("BBAA99887766554433221100"), /* nonce */
            SHEX(""), /* auth data */
            SHEX(""), /* plaintext */
            SHEX("785407BFFFC8AD9EDCC5520AC9111EE6"));
 
-  test_ocb_aes128(
+  test_aead_message(&ocb_aes128_message,
            SHEX("000102030405060708090A0B0C0D0E0F"), /* key */
            SHEX("BBAA99887766554433221101"), /* nonce */
            SHEX("0001020304050607"), /* auth data */
index 391f7b588f893a71388daef0878de023ed3b2f2e..3420ae9d20ae97131977201f8857a6f68c48b856 100644 (file)
@@ -907,6 +907,156 @@ test_aead(const struct nettle_aead *aead,
   free(buffer);
 }
 
+void
+test_aead_message (const struct nettle_aead_message *aead,
+                  const struct tstring *key,
+                  const struct tstring *nonce,
+                  const struct tstring *adata,
+                  const struct tstring *clear,
+                  const struct tstring *cipher)
+{
+  void *ctx = xalloc (aead->context_size);
+  uint8_t *buf = xalloc (cipher->length + 1);
+  uint8_t *copy = xalloc (cipher->length);
+
+  static const uint8_t nul = 0;
+  int res;
+
+  ASSERT (key->length == aead->key_size);
+  ASSERT (cipher->length > clear->length);
+  ASSERT (cipher->length - clear->length == aead->digest_size);
+
+  aead->set_encrypt_key (ctx, key->data);
+  buf[cipher->length] = 0xae;
+  aead->encrypt (ctx,
+                nonce->length, nonce->data,
+                adata->length, adata->data,
+                cipher->length, buf, clear->data);
+  if (!MEMEQ (cipher->length, cipher->data, buf))
+    {
+      fprintf(stderr, "aead->encrypt (message) failed:\n  got: ");
+      print_hex (cipher->length, buf);
+      fprintf (stderr, "  exp: ");
+      tstring_print_hex (cipher);
+      FAIL();
+    }
+  if (buf[cipher->length] != 0xae)
+    {
+      fprintf (stderr, "aead->encrypt (message) wrote too much.\n ");
+      FAIL();
+    }
+  aead->set_decrypt_key (ctx, key->data);
+
+  memset (buf, 0xae, clear->length + 1);
+
+  res = aead->decrypt (ctx,
+                      nonce->length, nonce->data,
+                      adata->length, adata->data,
+                      clear->length, buf, cipher->data);
+  if (!res)
+    {
+      fprintf (stderr, "decrypting valid ciphertext failed:\n  ");
+      tstring_print_hex (cipher);
+    }
+  if (!MEMEQ (clear->length, clear->data, buf))
+    {
+      fprintf(stderr, "aead->decrypt (message) failed:\n  got: ");
+      print_hex (clear->length, buf);
+      fprintf (stderr, "  exp: ");
+      tstring_print_hex (clear);
+      FAIL();
+    }
+
+  /* Invalid messages */
+  if (clear->length > 0
+      && aead->decrypt (ctx,
+                       nonce->length, nonce->data,
+                       adata->length, adata->data,
+                       clear->length - 1, buf, cipher->data))
+    {
+      fprintf (stderr, "Invalid message (truncated) not rejected\n");
+      FAIL();
+    }
+  memcpy (copy, cipher->data, cipher->length);
+  copy[0] ^= 4;
+  if (aead->decrypt (ctx,
+                    nonce->length, nonce->data,
+                    adata->length, adata->data,
+                    clear->length, buf, copy))
+    {
+      fprintf (stderr, "Invalid message (first byte modified) not rejected\n");
+      FAIL();
+    }
+
+  memcpy (copy, cipher->data, cipher->length);
+  copy[cipher->length - 1] ^= 4;
+  if (aead->decrypt (ctx,
+                    nonce->length, nonce->data,
+                    adata->length, adata->data,
+                    clear->length, buf, copy))
+    {
+      fprintf (stderr, "Invalid message (last byte modified) not rejected\n");
+      FAIL();
+    }
+
+  if (aead->decrypt (ctx,
+                    nonce->length, nonce->data,
+                    adata->length > 0 ? adata->length - 1 : 1,
+                    adata->length > 0 ? adata->data : &nul,
+                    clear->length, buf, cipher->data))
+    {
+      fprintf (stderr, "Invalid adata not rejected\n");
+      FAIL();
+    }
+
+  /* Test in-place operation. NOTE: Not supported for SIV-CMAC. */
+  if (aead->supports_inplace)
+    {
+      aead->set_encrypt_key (ctx, key->data);
+      buf[cipher->length] = 0xae;
+
+      memcpy (buf, clear->data, clear->length);
+      aead->encrypt (ctx,
+                    nonce->length, nonce->data,
+                    adata->length, adata->data,
+                    cipher->length, buf, buf);
+      if (!MEMEQ (cipher->length, cipher->data, buf))
+       {
+         fprintf(stderr, "aead->encrypt (in-place message) failed:\n  got: ");
+         print_hex (cipher->length, buf);
+         fprintf (stderr, "  exp: ");
+         tstring_print_hex (cipher);
+         FAIL();
+       }
+      if (buf[cipher->length] != 0xae)
+       {
+         fprintf (stderr, "aead->encrypt (in-place message) wrote too much.\n ");
+         FAIL();
+       }
+
+      res = aead->decrypt (ctx,
+                          nonce->length, nonce->data,
+                          adata->length, adata->data,
+                          clear->length, buf, buf);
+      if (!res)
+       {
+         fprintf (stderr, "in-place decrypting valid ciphertext failed:\n  ");
+         tstring_print_hex (cipher);
+       }
+      if (!MEMEQ (clear->length, clear->data, buf))
+       {
+         fprintf(stderr, "aead->decrypt (in-place message) failed:\n  got: ");
+         print_hex (clear->length, buf);
+         fprintf (stderr, "  exp: ");
+         tstring_print_hex (clear);
+         FAIL();
+       }
+    }
+  free (ctx);
+  free (buf);
+  free (copy);
+}
+
 void
 test_hash(const struct nettle_hash *hash,
          const struct tstring *msg,
index 0e35a251966c3786c1c11c12cb44061c1e3be24a..687bcd7311b446130a837bbfd1f7ea5137633b96 100644 (file)
@@ -79,6 +79,31 @@ test_main(void);
 
 extern int verbose;
 
+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);
+
+struct nettle_aead_message
+{
+  const char *name;
+  unsigned context_size;
+  unsigned key_size;
+  unsigned digest_size;
+  int supports_inplace;
+  nettle_set_key_func *set_encrypt_key;
+  nettle_set_key_func *set_decrypt_key;
+  nettle_encrypt_message_func *encrypt;
+  nettle_decrypt_message_func *decrypt;
+};
+
 void
 test_cipher(const struct nettle_cipher *cipher,
            const struct tstring *key,
@@ -129,6 +154,14 @@ test_aead(const struct nettle_aead *aead,
          const struct tstring *nonce,
          const struct tstring *digest);
 
+void
+test_aead_message(const struct nettle_aead_message *aead,
+                 const struct tstring *key,
+                 const struct tstring *adata,
+                 const struct tstring *nonce,
+                 const struct tstring *clear,
+                 const struct tstring *cipher);
+
 void
 test_hash(const struct nettle_hash *hash,
          const struct tstring *msg,