From d57d0b818935c20a7b468c0e717773ea8a3373e6 Mon Sep 17 00:00:00 2001 From: Veronika Hanulíková Date: Thu, 13 Jul 2023 17:07:00 +0200 Subject: Add option for in-place cipher testing in evp_test The command line option enables setting in-place data processing for cipher testing in `evp_test`. The `both` option argument runs both - in-place and non-in-place testing. Reviewed-by: Tim Hudson Reviewed-by: Dmitry Belyavskiy (Merged from https://github.com/openssl/openssl/pull/21546) --- test/evp_test.c | 144 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 87 insertions(+), 57 deletions(-) (limited to 'test') diff --git a/test/evp_test.c b/test/evp_test.c index 19efa95901..0a33ed3ba8 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -72,6 +72,7 @@ typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_CONFIG_FILE, + OPT_IN_PLACE, OPT_TEST_ENUM } OPTION_CHOICE; @@ -111,6 +112,18 @@ static int memory_err_compare(EVP_TEST *t, const char *err, return r; } +/* Option specific for evp test */ +static int process_mode_in_place; + +static int evp_test_process_mode(char *mode) +{ + if (strcmp(mode, "in_place") == 0) + return 1; + else if (strcmp(mode, "both") == 0) + return 0; + return -1; +} + /* * Structure used to hold a list of blocks of memory to test * calls to "update" like functions. @@ -713,8 +726,8 @@ static int cipher_test_parse(EVP_TEST *t, const char *keyword, return 0; } -static int cipher_test_enc(EVP_TEST *t, int enc, - size_t out_misalign, size_t inp_misalign, int frag) +static int cipher_test_enc(EVP_TEST *t, int enc, size_t out_misalign, + size_t inp_misalign, int frag, int in_place) { CIPHER_DATA *expected = t->data; unsigned char *in, *expected_out, *tmp = NULL; @@ -740,7 +753,7 @@ static int cipher_test_enc(EVP_TEST *t, int enc, expected_out = expected->plaintext; out_len = expected->plaintext_len; } - if (inp_misalign == (size_t)-1) { + if (in_place == 1) { /* Exercise in-place encryption */ tmp = OPENSSL_malloc(out_misalign + in_len + 2 * EVP_MAX_BLOCK_LENGTH); if (!tmp) @@ -1053,10 +1066,27 @@ static int cipher_test_enc(EVP_TEST *t, int enc, return ok; } +/* + * XTS, SIV, CCM, stitched ciphers and Wrap modes have special + * requirements about input lengths so we don't fragment for those + */ +static int cipher_test_valid_fragmentation(CIPHER_DATA *cdat) +{ + return (cdat->aead == EVP_CIPH_CCM_MODE + || cdat->aead == EVP_CIPH_CBC_MODE + || (cdat->aead == -1 + && EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_STREAM_CIPHER) + || ((EVP_CIPHER_get_flags(cdat->cipher) & EVP_CIPH_FLAG_CTS) != 0) + || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_SIV_MODE + || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_GCM_SIV_MODE + || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_XTS_MODE + || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_WRAP_MODE) ? 0 : 1; +} + static int cipher_test_run(EVP_TEST *t) { CIPHER_DATA *cdat = t->data; - int rv, frag = 0; + int rv, frag, fragmax, in_place; size_t out_misalign, inp_misalign; if (!cdat->key) { @@ -1074,63 +1104,57 @@ static int cipher_test_run(EVP_TEST *t) t->err = "NO_TAG"; return 0; } - for (out_misalign = 0; out_misalign <= 1;) { + + fragmax = (cipher_test_valid_fragmentation(cdat) == 0) ? 0 : 1; + for (in_place = 1; in_place >= 0; in_place--) { static char aux_err[64]; + t->aux_err = aux_err; - for (inp_misalign = (size_t)-1; inp_misalign != 2; inp_misalign++) { - if (inp_misalign == (size_t)-1) { - /* kludge: inp_misalign == -1 means "exercise in-place" */ - BIO_snprintf(aux_err, sizeof(aux_err), - "%s in-place, %sfragmented", - out_misalign ? "misaligned" : "aligned", - frag ? "" : "not "); - } else { - BIO_snprintf(aux_err, sizeof(aux_err), - "%s output and %s input, %sfragmented", - out_misalign ? "misaligned" : "aligned", - inp_misalign ? "misaligned" : "aligned", - frag ? "" : "not "); - } - if (cdat->enc) { - rv = cipher_test_enc(t, 1, out_misalign, inp_misalign, frag); - /* Not fatal errors: return */ - if (rv != 1) { - if (rv < 0) - return 0; - return 1; - } - } - if (cdat->enc != 1) { - rv = cipher_test_enc(t, 0, out_misalign, inp_misalign, frag); - /* Not fatal errors: return */ - if (rv != 1) { - if (rv < 0) - return 0; - return 1; + /* Test only in-place data processing */ + if (process_mode_in_place == 1 && in_place == 0) + break; + + for (frag = 0; frag <= fragmax; frag++) { + for (out_misalign = 0; out_misalign <= 1; out_misalign++) { + for (inp_misalign = 0; inp_misalign <= 1; inp_misalign++) { + /* Skip input misalign tests for in-place processing */ + if (inp_misalign == 1 && in_place == 1) + break; + if (in_place == 1) { + BIO_snprintf(aux_err, sizeof(aux_err), + "%s in-place, %sfragmented", + out_misalign ? "misaligned" : "aligned", + frag ? "" : "not "); + } else { + BIO_snprintf(aux_err, sizeof(aux_err), + "%s output and %s input, %sfragmented", + out_misalign ? "misaligned" : "aligned", + inp_misalign ? "misaligned" : "aligned", + frag ? "" : "not "); + } + if (cdat->enc) { + rv = cipher_test_enc(t, 1, out_misalign, inp_misalign, + frag, in_place); + /* Not fatal errors: return */ + if (rv != 1) { + if (rv < 0) + return 0; + return 1; + } + } + if (cdat->enc != 1) { + rv = cipher_test_enc(t, 0, out_misalign, inp_misalign, + frag, in_place); + /* Not fatal errors: return */ + if (rv != 1) { + if (rv < 0) + return 0; + return 1; + } + } } } } - - if (out_misalign == 1 && frag == 0) { - /* - * XTS, SIV, CCM, stitched ciphers and Wrap modes have special - * requirements about input lengths so we don't fragment for those - */ - if (cdat->aead == EVP_CIPH_CCM_MODE - || cdat->aead == EVP_CIPH_CBC_MODE - || (cdat->aead == -1 - && EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_STREAM_CIPHER) - || ((EVP_CIPHER_get_flags(cdat->cipher) & EVP_CIPH_FLAG_CTS) != 0) - || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_SIV_MODE - || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_GCM_SIV_MODE - || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_XTS_MODE - || EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_WRAP_MODE) - break; - out_misalign = 0; - frag++; - } else { - out_misalign++; - } } t->aux_err = NULL; @@ -4070,6 +4094,8 @@ const OPTIONS *test_get_options(void) OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("[file...]\n"), { "config", OPT_CONFIG_FILE, '<', "The configuration file to use for the libctx" }, + { "process", OPT_IN_PLACE, 's', + "Mode for data processing by cipher tests [in_place/both], both by default"}, { OPT_HELP_STR, 1, '-', "file\tFile to run tests on.\n" }, { NULL } }; @@ -4088,8 +4114,12 @@ int setup_tests(void) case OPT_CONFIG_FILE: config_file = opt_arg(); break; + case OPT_IN_PLACE: + if ((process_mode_in_place = evp_test_process_mode(opt_arg())) == -1) + return 0; + break; case OPT_TEST_CASES: - break; + break; default: case OPT_ERR: return 0; -- cgit v1.2.3