From c0be4c68610cfa8cb60259e4e00d69e8f7d2705d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 27 Jul 2015 14:00:57 +0100 Subject: [PATCH] [test] Generalise cipher tests and use okx() Generalise the existing support for performing CBC-mode block cipher tests, and update the code to use okx() for neater reporting of test results. Signed-off-by: Michael Brown --- src/tests/{aes_cbc_test.c => aes_test.c} | 123 ++++------------------- src/tests/cbc_test.h | 57 ----------- src/tests/{cbc_test.c => cipher_test.c} | 112 +++++++++++---------- src/tests/cipher_test.h | 111 ++++++++++++++++++++ src/tests/tests.c | 2 +- 5 files changed, 192 insertions(+), 213 deletions(-) rename src/tests/{aes_cbc_test.c => aes_test.c} (54%) delete mode 100644 src/tests/cbc_test.h rename src/tests/{cbc_test.c => cipher_test.c} (57%) create mode 100644 src/tests/cipher_test.h diff --git a/src/tests/aes_cbc_test.c b/src/tests/aes_test.c similarity index 54% rename from src/tests/aes_cbc_test.c rename to src/tests/aes_test.c index 1b9f4da9..bc23cba5 100644 --- a/src/tests/aes_cbc_test.c +++ b/src/tests/aes_test.c @@ -25,7 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * - * AES-in-CBC-mode tests + * AES tests * * These test vectors are provided by NIST as part of the * Cryptographic Toolkit Examples, downloadable from: @@ -41,88 +41,10 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include -#include "cbc_test.h" +#include "cipher_test.h" -/** Define inline key */ -#define KEY(...) { __VA_ARGS__ } - -/** Define inline initialisation vector */ -#define IV(...) { __VA_ARGS__ } - -/** Define inline plaintext data */ -#define PLAINTEXT(...) { __VA_ARGS__ } - -/** Define inline ciphertext data */ -#define CIPHERTEXT(...) { __VA_ARGS__ } - -/** An AES-in-CBC-mode test */ -struct aes_cbc_test { - /** Key */ - const void *key; - /** Length of key */ - size_t key_len; - /** Initialisation vector */ - const void *iv; - /** Length of initialisation vector */ - size_t iv_len; - /** Plaintext */ - const void *plaintext; - /** Length of plaintext */ - size_t plaintext_len; - /** Ciphertext */ - const void *ciphertext; - /** Length of ciphertext */ - size_t ciphertext_len; -}; - -/** - * Define an AES-in-CBC-mode test - * - * @v name Test name - * @v key_array Key - * @v iv_array Initialisation vector - * @v plaintext_array Plaintext - * @v ciphertext_array Ciphertext - * @ret test AES-in-CBC-mode test - */ -#define AES_CBC_TEST( name, key_array, iv_array, plaintext_array, \ - ciphertext_array ) \ - static const uint8_t name ## _key [] = key_array; \ - static const uint8_t name ## _iv [] = iv_array; \ - static const uint8_t name ## _plaintext [] = plaintext_array; \ - static const uint8_t name ## _ciphertext [] = ciphertext_array; \ - static struct aes_cbc_test name = { \ - .key = name ## _key, \ - .key_len = sizeof ( name ## _key ), \ - .iv = name ## _iv, \ - .iv_len = sizeof ( name ## _iv ), \ - .plaintext = name ## _plaintext, \ - .plaintext_len = sizeof ( name ## _plaintext ), \ - .ciphertext = name ## _ciphertext, \ - .ciphertext_len = sizeof ( name ## _ciphertext ), \ - } - -/** - * Report AES-in-CBC-mode - * - * @v state HMAC_DRBG internal state - * @v test Instantiation test - */ -#define aes_cbc_ok( test ) do { \ - struct cipher_algorithm *cipher = &aes_cbc_algorithm; \ - \ - assert ( (test)->iv_len == cipher->blocksize ); \ - assert ( (test)->plaintext_len == (test)->ciphertext_len ); \ - cbc_encrypt_ok ( cipher, (test)->key, (test)->key_len, \ - (test)->iv, (test)->plaintext, \ - (test)->ciphertext, (test)->plaintext_len ); \ - cbc_decrypt_ok ( cipher, (test)->key, (test)->key_len, \ - (test)->iv, (test)->ciphertext, \ - (test)->plaintext, (test)->ciphertext_len ); \ - } while ( 0 ) - -/** CBC_AES128 */ -AES_CBC_TEST ( test_128, +/** AES-128-CBC */ +CIPHER_TEST ( aes_128_cbc, &aes_cbc_algorithm, KEY ( 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c ), IV ( 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, @@ -144,8 +66,8 @@ AES_CBC_TEST ( test_128, 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 ) ); -/** CBC_AES256 */ -AES_CBC_TEST ( test_256, +/** AES-256-CBC */ +CIPHER_TEST ( aes_256_cbc, &aes_cbc_algorithm, KEY ( 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 ), @@ -169,29 +91,28 @@ AES_CBC_TEST ( test_256, 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b ) ); /** - * Perform AES-in-CBC-mode self-test + * Perform AES self-test * */ -static void aes_cbc_test_exec ( void ) { - struct cipher_algorithm *cipher = &aes_cbc_algorithm; +static void aes_test_exec ( void ) { + struct cipher_algorithm *cbc = &aes_cbc_algorithm; + unsigned int keylen; /* Correctness tests */ - aes_cbc_ok ( &test_128 ); - aes_cbc_ok ( &test_256 ); + cipher_ok ( &aes_128_cbc ); + cipher_ok ( &aes_256_cbc ); /* Speed tests */ - DBG ( "AES128 encryption required %ld cycles per byte\n", - cbc_cost_encrypt ( cipher, test_128.key_len ) ); - DBG ( "AES128 decryption required %ld cycles per byte\n", - cbc_cost_decrypt ( cipher, test_128.key_len ) ); - DBG ( "AES256 encryption required %ld cycles per byte\n", - cbc_cost_encrypt ( cipher, test_256.key_len ) ); - DBG ( "AES256 decryption required %ld cycles per byte\n", - cbc_cost_decrypt ( cipher, test_256.key_len ) ); + for ( keylen = 128 ; keylen <= 256 ; keylen += 128 ) { + DBG ( "AES-%d-CBC encryption required %ld cycles per byte\n", + keylen, cipher_cost_encrypt ( cbc, ( keylen / 8 ) ) ); + DBG ( "AES-%d-CBC decryption required %ld cycles per byte\n", + keylen, cipher_cost_decrypt ( cbc, ( keylen / 8 ) ) ); + } } -/** AES-in-CBC-mode self-test */ -struct self_test aes_cbc_test __self_test = { - .name = "aes_cbc", - .exec = aes_cbc_test_exec, +/** AES self-test */ +struct self_test aes_test __self_test = { + .name = "aes", + .exec = aes_test_exec, }; diff --git a/src/tests/cbc_test.h b/src/tests/cbc_test.h deleted file mode 100644 index 059b090f..00000000 --- a/src/tests/cbc_test.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _CBC_TEST_H -#define _CBC_TEST_H - -FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); - -#include -#include -#include - -extern int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key, - size_t key_len, const void *iv, - const void *plaintext, - const void *expected_ciphertext, size_t len ); -extern int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key, - size_t key_len, const void *iv, - const void *ciphertext, - const void *expected_plaintext, size_t len ); -extern unsigned long cbc_cost_encrypt ( struct cipher_algorithm *cipher, - size_t key_len ); -extern unsigned long cbc_cost_decrypt ( struct cipher_algorithm *cipher, - size_t key_len ); - -/** - * Report CBC encryption test result - * - * @v cipher Cipher algorithm - * @v key Key - * @v key_len Length of key - * @v iv Initialisation vector - * @v plaintext Plaintext data - * @v expected_ciphertext Expected ciphertext data - * @v len Length of data - */ -#define cbc_encrypt_ok( cipher, key, key_len, iv, plaintext, \ - expected_ciphertext, len ) do { \ - ok ( cbc_test_encrypt ( cipher, key, key_len, iv, plaintext, \ - expected_ciphertext, len ) ); \ - } while ( 0 ) - -/** - * Report CBC decryption test result - * - * @v cipher Cipher algorithm - * @v key Key - * @v key_len Length of key - * @v iv Initialisation vector - * @v ciphertext Ciphertext data - * @v expected_plaintext Expected plaintext data - * @v len Length of data - */ -#define cbc_decrypt_ok( cipher, key, key_len, iv, ciphertext, \ - expected_plaintext, len ) do { \ - ok ( cbc_test_decrypt ( cipher, key, key_len, iv, ciphertext, \ - expected_plaintext, len ) ); \ - } while ( 0 ) - -#endif /* _CBC_TEST_H */ diff --git a/src/tests/cbc_test.c b/src/tests/cipher_test.c similarity index 57% rename from src/tests/cbc_test.c rename to src/tests/cipher_test.c index 0751ca2f..800d6c13 100644 --- a/src/tests/cbc_test.c +++ b/src/tests/cipher_test.c @@ -25,7 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); /** @file * - * CBC self-tests + * Cipher self-tests * */ @@ -38,86 +38,90 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include -#include "cbc_test.h" +#include +#include "cipher_test.h" /** Number of sample iterations for profiling */ #define PROFILE_COUNT 16 /** - * Test CBC encryption + * Report a cipher encryption test result * - * @v cipher Cipher algorithm - * @v key Key - * @v key_len Length of key - * @v iv Initialisation vector - * @v plaintext Plaintext data - * @v expected_ciphertext Expected ciphertext data - * @v len Length of data - * @ret ok Ciphertext is as expected + * @v test Cipher test + * @v file Test code file + * @v line Test code line */ -int cbc_test_encrypt ( struct cipher_algorithm *cipher, const void *key, - size_t key_len, const void *iv, const void *plaintext, - const void *expected_ciphertext, size_t len ) { +void cipher_encrypt_okx ( struct cipher_test *test, const char *file, + unsigned int line ) { + struct cipher_algorithm *cipher = test->cipher; + size_t len = test->len; uint8_t ctx[cipher->ctxsize]; uint8_t ciphertext[len]; - int rc; /* Initialise cipher */ - rc = cipher_setkey ( cipher, ctx, key, key_len ); - assert ( rc == 0 ); - cipher_setiv ( cipher, ctx, iv ); + okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0, + file, line ); + cipher_setiv ( cipher, ctx, test->iv ); /* Perform encryption */ - cipher_encrypt ( cipher, ctx, plaintext, ciphertext, len ); + cipher_encrypt ( cipher, ctx, test->plaintext, ciphertext, len ); - /* Verify result */ - return ( memcmp ( ciphertext, expected_ciphertext, len ) == 0 ); + /* Compare against expected ciphertext */ + okx ( memcmp ( ciphertext, test->ciphertext, len ) == 0, file, line ); } /** - * Test CBC decryption + * Report a cipher decryption test result * - * @v cipher Cipher algorithm - * @v key Key - * @v key_len Length of key - * @v iv Initialisation vector - * @v ciphertext Ciphertext data - * @v expected_plaintext Expected plaintext data - * @v len Length of data - * @ret ok Plaintext is as expected + * @v test Cipher test + * @v file Test code file + * @v line Test code line */ -int cbc_test_decrypt ( struct cipher_algorithm *cipher, const void *key, - size_t key_len, const void *iv, const void *ciphertext, - const void *expected_plaintext, size_t len ) { +void cipher_decrypt_okx ( struct cipher_test *test, const char *file, + unsigned int line ) { + struct cipher_algorithm *cipher = test->cipher; + size_t len = test->len; uint8_t ctx[cipher->ctxsize]; uint8_t plaintext[len]; - int rc; /* Initialise cipher */ - rc = cipher_setkey ( cipher, ctx, key, key_len ); - assert ( rc == 0 ); - cipher_setiv ( cipher, ctx, iv ); + okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0, + file, line ); + cipher_setiv ( cipher, ctx, test->iv ); /* Perform encryption */ - cipher_decrypt ( cipher, ctx, ciphertext, plaintext, len ); + cipher_decrypt ( cipher, ctx, test->ciphertext, plaintext, len ); - /* Verify result */ - return ( memcmp ( plaintext, expected_plaintext, len ) == 0 ); + /* Compare against expected plaintext */ + okx ( memcmp ( plaintext, test->plaintext, len ) == 0, file, line ); } /** - * Calculate CBC encryption or decryption cost + * Report a cipher encryption and decryption test result + * + * @v test Cipher test + * @v file Test code file + * @v line Test code line + */ +void cipher_okx ( struct cipher_test *test, const char *file, + unsigned int line ) { + + cipher_encrypt_okx ( test, file, line ); + cipher_decrypt_okx ( test, file, line ); +} + +/** + * Calculate cipher encryption or decryption cost * * @v cipher Cipher algorithm * @v key_len Length of key * @v op Encryption or decryption operation * @ret cost Cost (in cycles per byte) */ -static unsigned long cbc_cost ( struct cipher_algorithm *cipher, - size_t key_len, - void ( * op ) ( struct cipher_algorithm *cipher, - void *ctx, const void *src, - void *dst, size_t len ) ) { +static unsigned long +cipher_cost ( struct cipher_algorithm *cipher, size_t key_len, + void ( * op ) ( struct cipher_algorithm *cipher, void *ctx, + const void *src, void *dst, size_t len ) ) { static uint8_t random[8192]; /* Too large for stack */ uint8_t key[key_len]; uint8_t iv[cipher->blocksize]; @@ -157,25 +161,25 @@ static unsigned long cbc_cost ( struct cipher_algorithm *cipher, } /** - * Calculate CBC encryption cost + * Calculate cipher encryption cost * * @v cipher Cipher algorithm * @v key_len Length of key * @ret cost Cost (in cycles per byte) */ -unsigned long cbc_cost_encrypt ( struct cipher_algorithm *cipher, - size_t key_len ) { - return cbc_cost ( cipher, key_len, cipher_encrypt ); +unsigned long cipher_cost_encrypt ( struct cipher_algorithm *cipher, + size_t key_len ) { + return cipher_cost ( cipher, key_len, cipher_encrypt ); } /** - * Calculate CBC decryption cost + * Calculate cipher decryption cost * * @v cipher Cipher algorithm * @v key_len Length of key * @ret cost Cost (in cycles per byte) */ -unsigned long cbc_cost_decrypt ( struct cipher_algorithm *cipher, - size_t key_len ) { - return cbc_cost ( cipher, key_len, cipher_decrypt ); +unsigned long cipher_cost_decrypt ( struct cipher_algorithm *cipher, + size_t key_len ) { + return cipher_cost ( cipher, key_len, cipher_decrypt ); } diff --git a/src/tests/cipher_test.h b/src/tests/cipher_test.h new file mode 100644 index 00000000..d7c5aef8 --- /dev/null +++ b/src/tests/cipher_test.h @@ -0,0 +1,111 @@ +#ifndef _CIPHER_TEST_H +#define _CIPHER_TEST_H + +/** @file + * + * Cipher self-tests + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include +#include +#include + +/** A cipher test */ +struct cipher_test { + /** Cipher algorithm */ + struct cipher_algorithm *cipher; + /** Key */ + const void *key; + /** Length of key */ + size_t key_len; + /** Initialisation vector */ + const void *iv; + /** Length of initialisation vector */ + size_t iv_len; + /** Plaintext */ + const void *plaintext; + /** Ciphertext */ + const void *ciphertext; + /** Length of text */ + size_t len; +}; + +/** Define inline key */ +#define KEY(...) { __VA_ARGS__ } + +/** Define inline initialisation vector */ +#define IV(...) { __VA_ARGS__ } + +/** Define inline plaintext data */ +#define PLAINTEXT(...) { __VA_ARGS__ } + +/** Define inline ciphertext data */ +#define CIPHERTEXT(...) { __VA_ARGS__ } + +/** + * Define a cipher test + * + * @v name Test name + * @v CIPHER Cipher algorithm + * @v KEY Key + * @v IV Initialisation vector + * @v PLAINTEXT Plaintext + * @v CIPHERTEXT Ciphertext + * @ret test Cipher test + */ +#define CIPHER_TEST( name, CIPHER, KEY, IV, PLAINTEXT, CIPHERTEXT ) \ + static const uint8_t name ## _key [] = KEY; \ + static const uint8_t name ## _iv [] = IV; \ + static const uint8_t name ## _plaintext [] = PLAINTEXT; \ + static const uint8_t name ## _ciphertext \ + [ sizeof ( name ## _plaintext ) ] = CIPHERTEXT; \ + static struct cipher_test name = { \ + .cipher = CIPHER, \ + .key = name ## _key, \ + .key_len = sizeof ( name ## _key ), \ + .iv = name ## _iv, \ + .iv_len = sizeof ( name ## _iv ), \ + .plaintext = name ## _plaintext, \ + .ciphertext = name ## _ciphertext, \ + .len = sizeof ( name ## _plaintext ), \ + } + +extern void cipher_encrypt_okx ( struct cipher_test *test, const char *file, + unsigned int line ); +extern void cipher_decrypt_okx ( struct cipher_test *test, const char *file, + unsigned int line ); +extern void cipher_okx ( struct cipher_test *test, const char *file, + unsigned int line ); +extern unsigned long cipher_cost_encrypt ( struct cipher_algorithm *cipher, + size_t key_len ); +extern unsigned long cipher_cost_decrypt ( struct cipher_algorithm *cipher, + size_t key_len ); + +/** + * Report a cipher encryption test result + * + * @v test Cipher test + */ +#define cipher_encrypt_ok( test ) \ + cipher_encrypt_okx ( test, __FILE__, __LINE__ ) + +/** + * Report a cipher decryption test result + * + * @v test Cipher test + */ +#define cipher_decrypt_ok( test ) \ + cipher_decrypt_okx ( test, __FILE__, __LINE__ ) + +/** + * Report a cipher encryption and decryption test result + * + * @v test Cipher test + */ +#define cipher_ok( test ) \ + cipher_okx ( test, __FILE__, __LINE__ ) + +#endif /* _CIPHER_TEST_H */ diff --git a/src/tests/tests.c b/src/tests/tests.c index 97e510f6..0e6afee6 100644 --- a/src/tests/tests.c +++ b/src/tests/tests.c @@ -50,7 +50,7 @@ REQUIRE_OBJECT ( md5_test ); REQUIRE_OBJECT ( sha1_test ); REQUIRE_OBJECT ( sha256_test ); REQUIRE_OBJECT ( sha512_test ); -REQUIRE_OBJECT ( aes_cbc_test ); +REQUIRE_OBJECT ( aes_test ); REQUIRE_OBJECT ( hmac_drbg_test ); REQUIRE_OBJECT ( hash_df_test ); REQUIRE_OBJECT ( bigint_test );