summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2023-04-24 19:47:53 +0200
committerNiels Möller <nisse@lysator.liu.se>2023-04-24 19:47:53 +0200
commit4e3199970ad6a73327e15ee2a076b7baa6774215 (patch)
tree7f1d3400f3789659c967f04ff00bac54cd6fc555
parent4915b35195e970ef92f72e8b424443a51da6005a (diff)
downloadnettle-4e3199970ad6a73327e15ee2a076b7baa6774215.tar.gz
Rework OCB tests.
-rw-r--r--ChangeLog22
-rw-r--r--testsuite/ocb-test.c182
-rw-r--r--testsuite/testutils.c150
-rw-r--r--testsuite/testutils.h33
4 files changed, 250 insertions, 137 deletions
diff --git a/ChangeLog b/ChangeLog
index 9febf4c6..1334eb37 100644
--- 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...
diff --git a/testsuite/ocb-test.c b/testsuite/ocb-test.c
index d377b3ec..3892ddda 100644
--- a/testsuite/ocb-test.c
+++ b/testsuite/ocb-test.c
@@ -1,148 +1,56 @@
#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 */
diff --git a/testsuite/testutils.c b/testsuite/testutils.c
index 391f7b58..3420ae9d 100644
--- a/testsuite/testutils.c
+++ b/testsuite/testutils.c
@@ -908,6 +908,156 @@ test_aead(const struct nettle_aead *aead,
}
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,
const struct tstring *digest)
diff --git a/testsuite/testutils.h b/testsuite/testutils.h
index 0e35a251..687bcd73 100644
--- a/testsuite/testutils.h
+++ b/testsuite/testutils.h
@@ -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,
@@ -130,6 +155,14 @@ test_aead(const struct nettle_aead *aead,
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,
const struct tstring *digest);