]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add option for in-place cipher testing in evp_test
authorVeronika Hanulíková <vhanulik@redhat.com>
Thu, 13 Jul 2023 15:07:00 +0000 (17:07 +0200)
committerDmitry Belyavskiy <beldmit@gmail.com>
Wed, 30 Aug 2023 19:53:08 +0000 (21:53 +0200)
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 <tjh@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/21546)

test/evp_test.c

index 19efa9590169d7d4637d9f5849a98e17a663390c..0a33ed3ba860e4abcb0b0e6d59e6980345f6c845 100644 (file)
@@ -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;