diff options
author | Niels Möller <nisse@lysator.liu.se> | 2023-04-24 19:47:53 +0200 |
---|---|---|
committer | Niels Möller <nisse@lysator.liu.se> | 2023-04-24 19:47:53 +0200 |
commit | 4e3199970ad6a73327e15ee2a076b7baa6774215 (patch) | |
tree | 7f1d3400f3789659c967f04ff00bac54cd6fc555 | |
parent | 4915b35195e970ef92f72e8b424443a51da6005a (diff) | |
download | nettle-4e3199970ad6a73327e15ee2a076b7baa6774215.tar.gz |
Rework OCB tests.
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | testsuite/ocb-test.c | 182 | ||||
-rw-r--r-- | testsuite/testutils.c | 150 | ||||
-rw-r--r-- | testsuite/testutils.h | 33 |
4 files changed, 250 insertions, 137 deletions
@@ -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); |