Author: jhb
Date: Mon May 25 23:04:18 2020
New Revision: 361487
URL: https://svnweb.freebsd.org/changeset/base/361487

Log:
  Expand coverage of different buffer sizes.
  
  - When -z is used, include small buffers from 1 to 32 bytes to test
    stream ciphers.  Note that while AES-XTS claims to support a block
    size of 1 in OpenSSL, it does require a minimum of 1 block of cipher
    text as it is not a stream cipher but depends on CTS to pad out the
    final partial block.
  
  - Permit multiple AAD sizes to be set via multiple -A options, or via
    -z.  When -z is set, use small buffers from 0 to 32 bytes followed
    by powers of 2 up to 256.  When multiple sizes are specified, the
    ETA and AEAD algorithms perform the full matrix of AAD sizes by
    payload sizes.
  
  - Only warn on unchanged ciphertext instead of erroring.  The
    currently generated plaintext and key for a couple of AES-CTR tests
    with a buffer size of 1 results in ciphertext that matches the
    plaintext.
  
  Reviewed by:  cem
  Sponsored by: Netflix
  Differential Revision:        https://reviews.freebsd.org/D25006

Modified:
  head/tools/tools/crypto/cryptocheck.c

Modified: head/tools/tools/crypto/cryptocheck.c
==============================================================================
--- head/tools/tools/crypto/cryptocheck.c       Mon May 25 22:31:45 2020        
(r361486)
+++ head/tools/tools/crypto/cryptocheck.c       Mon May 25 23:04:18 2020        
(r361487)
@@ -216,7 +216,8 @@ const struct alg {
 
 static bool verbose;
 static int crid;
-static size_t aad_len;
+static size_t aad_sizes[48], sizes[128];
+static u_int naad_sizes, nsizes;
 
 static void
 usage(void)
@@ -754,6 +755,20 @@ run_cipher_test(const struct alg *alg, size_t size)
                return;
        }
 
+       /*
+        * XTS requires at least one full block so that any partial
+        * block at the end has cipher text to steal.  Hardcoding the
+        * AES block size isn't ideal, but OpenSSL doesn't have a
+        * notion of a "native" block size.
+        */
+       if (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE &&
+           size < AES_BLOCK_LEN) {
+               if (verbose)
+                       printf("%s (%zu): invalid buffer size\n", alg->name,
+                           size);
+               return;
+       }
+
        key_len = EVP_CIPHER_key_length(cipher);
        iv_len = EVP_CIPHER_iv_length(cipher);
 
@@ -766,7 +781,7 @@ run_cipher_test(const struct alg *alg, size_t size)
        /* OpenSSL cipher. */
        openssl_cipher(alg, cipher, key, iv, cleartext, ciphertext, size, 1);
        if (size > 0 && memcmp(cleartext, ciphertext, size) == 0)
-               errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
+               warnx("OpenSSL %s (%zu): cipher text unchanged", alg->name,
                    size);
        openssl_cipher(alg, cipher, key, iv, ciphertext, buffer, size, 0);
        if (memcmp(cleartext, buffer, size) != 0) {
@@ -877,7 +892,7 @@ ocf_eta(const struct ocf_session *ses, const struct al
 }
 
 static void
-run_eta_test(const struct alg *alg, size_t size)
+run_eta_test(const struct alg *alg, size_t aad_len, size_t size)
 {
        struct ocf_session ses;
        const EVP_CIPHER *cipher;
@@ -892,11 +907,21 @@ run_eta_test(const struct alg *alg, size_t size)
        if (size % EVP_CIPHER_block_size(cipher) != 0) {
                if (verbose)
                        printf(
-                           "%s (%zu): invalid buffer size (block size %d)\n",
-                           alg->name, size, EVP_CIPHER_block_size(cipher));
+                   "%s (%zu, %zu): invalid buffer size (block size %d)\n",
+                           alg->name, aad_len, size,
+                           EVP_CIPHER_block_size(cipher));
                return;
        }
 
+       /* See comment in run_cipher_test. */
+       if (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE &&
+           size < AES_BLOCK_LEN) {
+               if (verbose)
+                       printf("%s (%zu): invalid buffer size\n", alg->name,
+                           size);
+               return;
+       }
+
        memset(control_digest, 0x3c, sizeof(control_digest));
        memset(test_digest, 0x3c, sizeof(test_digest));
 
@@ -920,13 +945,13 @@ run_eta_test(const struct alg *alg, size_t size)
            ciphertext + aad_len, size, 1);
        if (size > 0 && memcmp(cleartext + aad_len, ciphertext + aad_len,
            size) == 0)
-               errx(1, "OpenSSL %s (%zu): cipher text unchanged", alg->name,
-                   size);
+               warnx("OpenSSL %s (%zu, %zu): cipher text unchanged",
+                   alg->name, aad_len, size);
        digest_len = sizeof(control_digest);
        if (HMAC(md, auth_key, auth_key_len, (u_char *)ciphertext,
            aad_len + size, (u_char *)control_digest, &digest_len) == NULL)
-               errx(1, "OpenSSL %s (%zu) HMAC failed: %s", alg->name,
-                   size, ERR_error_string(ERR_get_error(), NULL));
+               errx(1, "OpenSSL %s (%zu, %zu) HMAC failed: %s", alg->name,
+                   aad_len, size, ERR_error_string(ERR_get_error(), NULL));
 
        if (!ocf_init_eta_session(alg, cipher_key, cipher_key_len, auth_key,
            auth_key_len, &ses))
@@ -937,12 +962,13 @@ run_eta_test(const struct alg *alg, size_t size)
            aad_len != 0 ? cleartext : NULL, aad_len, cleartext + aad_len,
            buffer + aad_len, size, test_digest, COP_ENCRYPT);
        if (error != 0) {
-               warnc(error, "cryptodev %s (%zu) ETA failed for device %s",
-                   alg->name, size, crfind(ses.crid));
+               warnc(error, "cryptodev %s (%zu, %zu) ETA failed for device %s",
+                   alg->name, aad_len, size, crfind(ses.crid));
                goto out;
        }
        if (memcmp(ciphertext + aad_len, buffer + aad_len, size) != 0) {
-               printf("%s (%zu) encryption mismatch:\n", alg->name, size);
+               printf("%s (%zu, %zu) encryption mismatch:\n", alg->name,
+                   aad_len, size);
                printf("control:\n");
                hexdump(ciphertext + aad_len, size, NULL, 0);
                printf("test (cryptodev device %s):\n", crfind(ses.crid));
@@ -951,11 +977,11 @@ run_eta_test(const struct alg *alg, size_t size)
        }
        if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
                if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
-                       printf("%s (%zu) enc hash mismatch in trailer:\n",
-                           alg->name, size);
+                       printf("%s (%zu, %zu) enc hash mismatch in trailer:\n",
+                           alg->name, aad_len, size);
                else
-                       printf("%s (%zu) enc hash mismatch:\n", alg->name,
-                           size);
+                       printf("%s (%zu, %zu) enc hash mismatch:\n", alg->name,
+                           aad_len, size);
                printf("control:\n");
                hexdump(control_digest, sizeof(control_digest), NULL, 0);
                printf("test (cryptodev device %s):\n", crfind(ses.crid));
@@ -968,12 +994,13 @@ run_eta_test(const struct alg *alg, size_t size)
            aad_len != 0 ? ciphertext : NULL, aad_len, ciphertext + aad_len,
            buffer + aad_len, size, test_digest, COP_DECRYPT);
        if (error != 0) {
-               warnc(error, "cryptodev %s (%zu) ETA failed for device %s",
-                   alg->name, size, crfind(ses.crid));
+               warnc(error, "cryptodev %s (%zu, %zu) ETA failed for device %s",
+                   alg->name, aad_len, size, crfind(ses.crid));
                goto out;
        }
        if (memcmp(cleartext + aad_len, buffer + aad_len, size) != 0) {
-               printf("%s (%zu) decryption mismatch:\n", alg->name, size);
+               printf("%s (%zu, %zu) decryption mismatch:\n", alg->name,
+                   aad_len, size);
                printf("control:\n");
                hexdump(cleartext, size, NULL, 0);
                printf("test (cryptodev device %s):\n", crfind(ses.crid));
@@ -989,18 +1016,18 @@ run_eta_test(const struct alg *alg, size_t size)
        if (error != EBADMSG) {
                if (error != 0)
                        warnc(error,
-                   "cryptodev %s (%zu) corrupt tag failed for device %s",
-                           alg->name, size, crfind(ses.crid));
+                   "cryptodev %s (%zu, %zu) corrupt tag failed for device %s",
+                           alg->name, aad_len, size, crfind(ses.crid));
                else
                        warnx(
-                   "cryptodev %s (%zu) corrupt tag didn't fail for device %s",
-                           alg->name, size, crfind(ses.crid));
+           "cryptodev %s (%zu, %zu) corrupt tag didn't fail for device %s",
+                           alg->name, aad_len, size, crfind(ses.crid));
                goto out;
        }
 
        if (verbose)
-               printf("%s (%zu) matched (cryptodev device %s)\n",
-                   alg->name, size, crfind(ses.crid));
+               printf("%s (%zu, %zu) matched (cryptodev device %s)\n",
+                   alg->name, aad_len, size, crfind(ses.crid));
 
 out:
        ocf_destroy_session(&ses);
@@ -1303,7 +1330,7 @@ ocf_aead(const struct ocf_session *ses, const struct a
 #define        AEAD_MAX_TAG_LEN        MAX(AES_GMAC_HASH_LEN, 
AES_CBC_MAC_HASH_LEN)
 
 static void
-run_aead_test(const struct alg *alg, size_t size)
+run_aead_test(const struct alg *alg, size_t aad_len, size_t size)
 {
        struct ocf_session ses;
        const EVP_CIPHER *cipher;
@@ -1317,8 +1344,9 @@ run_aead_test(const struct alg *alg, size_t size)
        if (size % EVP_CIPHER_block_size(cipher) != 0) {
                if (verbose)
                        printf(
-                           "%s (%zu): invalid buffer size (block size %d)\n",
-                           alg->name, size, EVP_CIPHER_block_size(cipher));
+                   "%s (%zu, %zu): invalid buffer size (block size %d)\n",
+                           alg->name, aad_len, size,
+                           EVP_CIPHER_block_size(cipher));
                return;
        }
 
@@ -1366,12 +1394,13 @@ run_aead_test(const struct alg *alg, size_t size)
        error = ocf_aead(&ses, alg, iv, iv_len, aad, aad_len, cleartext, buffer,
            size, test_tag, COP_ENCRYPT);
        if (error != 0) {
-               warnc(error, "cryptodev %s (%zu) failed for device %s",
-                   alg->name, size, crfind(ses.crid));
+               warnc(error, "cryptodev %s (%zu, %zu) failed for device %s",
+                   alg->name, aad_len, size, crfind(ses.crid));
                goto out;
        }
        if (memcmp(ciphertext, buffer, size) != 0) {
-               printf("%s (%zu) encryption mismatch:\n", alg->name, size);
+               printf("%s (%zu, %zu) encryption mismatch:\n", alg->name,
+                   aad_len, size);
                printf("control:\n");
                hexdump(ciphertext, size, NULL, 0);
                printf("test (cryptodev device %s):\n", crfind(crid));
@@ -1379,7 +1408,8 @@ run_aead_test(const struct alg *alg, size_t size)
                goto out;
        }
        if (memcmp(control_tag, test_tag, sizeof(control_tag)) != 0) {
-               printf("%s (%zu) enc tag mismatch:\n", alg->name, size);
+               printf("%s (%zu, %zu) enc tag mismatch:\n", alg->name, aad_len,
+                   size);
                printf("control:\n");
                hexdump(control_tag, sizeof(control_tag), NULL, 0);
                printf("test (cryptodev device %s):\n", crfind(crid));
@@ -1391,12 +1421,13 @@ run_aead_test(const struct alg *alg, size_t size)
        error = ocf_aead(&ses, alg, iv, iv_len, aad, aad_len, ciphertext,
            buffer, size, control_tag, COP_DECRYPT);
        if (error != 0) {
-               warnc(error, "cryptodev %s (%zu) failed for device %s",
-                   alg->name, size, crfind(ses.crid));
+               warnc(error, "cryptodev %s (%zu, %zu) failed for device %s",
+                   alg->name, aad_len, size, crfind(ses.crid));
                goto out;
        }
        if (memcmp(cleartext, buffer, size) != 0) {
-               printf("%s (%zu) decryption mismatch:\n", alg->name, size);
+               printf("%s (%zu, %zu) decryption mismatch:\n", alg->name,
+                   aad_len, size);
                printf("control:\n");
                hexdump(cleartext, size, NULL, 0);
                printf("test (cryptodev device %s):\n", crfind(crid));
@@ -1411,18 +1442,18 @@ run_aead_test(const struct alg *alg, size_t size)
        if (error != EBADMSG) {
                if (error != 0)
                        warnc(error,
-                   "cryptodev %s (%zu) corrupt tag failed for device %s",
-                           alg->name, size, crfind(ses.crid));
+                   "cryptodev %s (%zu, %zu) corrupt tag failed for device %s",
+                           alg->name, aad_len, size, crfind(ses.crid));
                else
                        warnx(
-                   "cryptodev %s (%zu) corrupt tag didn't fail for device %s",
-                           alg->name, size, crfind(ses.crid));
+           "cryptodev %s (%zu, %zu) corrupt tag didn't fail for device %s",
+                           alg->name, aad_len, size, crfind(ses.crid));
                goto out;
        }
 
        if (verbose)
-               printf("%s (%zu) matched (cryptodev device %s)\n",
-                   alg->name, size, crfind(ses.crid));
+               printf("%s (%zu, %zu) matched (cryptodev device %s)\n",
+                   alg->name, aad_len, size, crfind(ses.crid));
 
 out:
        ocf_destroy_session(&ses);
@@ -1435,7 +1466,7 @@ out:
 }
 
 static void
-run_test(const struct alg *alg, size_t size)
+run_test(const struct alg *alg, size_t aad_len, size_t size)
 {
 
        switch (alg->type) {
@@ -1452,55 +1483,65 @@ run_test(const struct alg *alg, size_t size)
                run_cipher_test(alg, size);
                break;
        case T_ETA:
-               run_eta_test(alg, size);
+               run_eta_test(alg, aad_len, size);
                break;
        case T_AEAD:
-               run_aead_test(alg, size);
+               run_aead_test(alg, aad_len, size);
                break;
        }
 }
 
 static void
-run_test_sizes(const struct alg *alg, size_t *sizes, u_int nsizes)
+run_test_sizes(const struct alg *alg)
 {
-       u_int i;
+       u_int i, j;
 
-       for (i = 0; i < nsizes; i++)
-               run_test(alg, sizes[i]);
+       switch (alg->type) {
+       default:
+               for (i = 0; i < nsizes; i++)
+                       run_test(alg, 0, sizes[i]);
+               break;
+       case T_ETA:
+       case T_AEAD:
+               for (i = 0; i < naad_sizes; i++)
+                       for (j = 0; j < nsizes; j++)
+                               run_test(alg, aad_sizes[i], sizes[j]);
+               break;
+       }
 }
 
 static void
-run_hash_tests(size_t *sizes, u_int nsizes)
+run_hash_tests(void)
 {
        u_int i;
 
        for (i = 0; i < nitems(algs); i++)
                if (algs[i].type == T_HASH)
-                       run_test_sizes(&algs[i], sizes, nsizes);
+                       run_test_sizes(&algs[i]);
 }
 
 static void
-run_mac_tests(size_t *sizes, u_int nsizes)
+run_mac_tests(void)
 {
        u_int i;
 
        for (i = 0; i < nitems(algs); i++)
                if (algs[i].type == T_HMAC || algs[i].type == T_GMAC)
-                       run_test_sizes(&algs[i], sizes, nsizes);
+                       run_test_sizes(&algs[i]);
 }
 
 static void
-run_cipher_tests(size_t *sizes, u_int nsizes)
+run_cipher_tests(void)
 {
        u_int i;
 
        for (i = 0; i < nitems(algs); i++)
                if (algs[i].type == T_CIPHER)
-                       run_test_sizes(&algs[i], sizes, nsizes);
+                       run_test_sizes(&algs[i]);
 }
 
 static void
-run_eta_tests(size_t *sizes, u_int nsizes)
+run_eta_tests(void)
 {
        const struct alg *cipher, *mac;
        struct alg *eta;
@@ -1515,20 +1556,20 @@ run_eta_tests(size_t *sizes, u_int nsizes)
                        if (mac->type != T_HMAC)
                                continue;
                        eta = build_eta(cipher, mac);
-                       run_test_sizes(eta, sizes, nsizes);
+                       run_test_sizes(eta);
                        free_eta(eta);
                }
        }
 }
 
 static void
-run_aead_tests(size_t *sizes, u_int nsizes)
+run_aead_tests(void)
 {
        u_int i;
 
        for (i = 0; i < nitems(algs); i++)
                if (algs[i].type == T_AEAD)
-                       run_test_sizes(&algs[i], sizes, nsizes);
+                       run_test_sizes(&algs[i]);
 }
 
 int
@@ -1537,8 +1578,9 @@ main(int ac, char **av)
        const char *algname;
        const struct alg *alg;
        struct alg *eta;
-       size_t sizes[128];
-       u_int i, nsizes;
+       char *cp;
+       size_t base_size;
+       u_int i;
        bool testall;
        int ch;
 
@@ -1549,7 +1591,14 @@ main(int ac, char **av)
        while ((ch = getopt(ac, av, "A:a:d:vz")) != -1)
                switch (ch) {
                case 'A':
-                       aad_len = atoi(optarg);
+                       if (naad_sizes >= nitems(aad_sizes)) {
+                               warnx("Too many AAD sizes, ignoring extras");
+                               break;
+                       }
+                       aad_sizes[naad_sizes] = strtol(optarg, &cp, 0);
+                       if (*cp != '\0')
+                               errx(1, "Bad AAD size %s", optarg);
+                       naad_sizes++;
                        break;
                case 'a':
                        algname = optarg;
@@ -1570,8 +1619,6 @@ main(int ac, char **av)
        av += optind;
        nsizes = 0;
        while (ac > 0) {
-               char *cp;
-
                if (nsizes >= nitems(sizes)) {
                        warnx("Too many sizes, ignoring extras");
                        break;
@@ -1586,48 +1633,78 @@ main(int ac, char **av)
 
        if (algname == NULL)
                errx(1, "Algorithm required");
+
+       if (naad_sizes == 0) {
+               if (testall) {
+                       for (i = 0; i <= 32; i++) {
+                               aad_sizes[naad_sizes] = i;
+                               naad_sizes++;
+                       }
+
+                       base_size = 32;
+                       while (base_size * 2 < 512) {
+                               base_size *= 2;
+                               assert(naad_sizes < nitems(aad_sizes));
+                               aad_sizes[naad_sizes] = base_size;
+                               naad_sizes++;
+                       }
+               } else {
+                       aad_sizes[0] = 0;
+                       naad_sizes = 1;
+               }
+       }
+
        if (nsizes == 0) {
-               sizes[0] = 16;
-               nsizes++;
                if (testall) {
-                       while (sizes[nsizes - 1] * 2 < 240 * 1024) {
+                       for (i = 1; i <= 32; i++) {
+                               sizes[nsizes] = i;
+                               nsizes++;
+                       }
+
+                       base_size = 32;
+                       while (base_size * 2 < 240 * 1024) {
+                               base_size *= 2;
                                assert(nsizes < nitems(sizes));
-                               sizes[nsizes] = sizes[nsizes - 1] * 2;
+                               sizes[nsizes] = base_size;
                                nsizes++;
                        }
+
                        if (sizes[nsizes - 1] < 240 * 1024) {
                                assert(nsizes < nitems(sizes));
                                sizes[nsizes] = 240 * 1024;
                                nsizes++;
                        }
+               } else {
+                       sizes[0] = 16;
+                       nsizes = 1;
                }
        }
 
        if (strcasecmp(algname, "hash") == 0)
-               run_hash_tests(sizes, nsizes);
+               run_hash_tests();
        else if (strcasecmp(algname, "mac") == 0)
-               run_mac_tests(sizes, nsizes);
+               run_mac_tests();
        else if (strcasecmp(algname, "cipher") == 0)
-               run_cipher_tests(sizes, nsizes);
+               run_cipher_tests();
        else if (strcasecmp(algname, "eta") == 0)
-               run_eta_tests(sizes, nsizes);
+               run_eta_tests();
        else if (strcasecmp(algname, "aead") == 0)
-               run_aead_tests(sizes, nsizes);
+               run_aead_tests();
        else if (strcasecmp(algname, "all") == 0) {
-               run_hash_tests(sizes, nsizes);
-               run_mac_tests(sizes, nsizes);
-               run_cipher_tests(sizes, nsizes);
-               run_eta_tests(sizes, nsizes);
-               run_aead_tests(sizes, nsizes);
+               run_hash_tests();
+               run_mac_tests();
+               run_cipher_tests();
+               run_eta_tests();
+               run_aead_tests();
        } else if (strchr(algname, '+') != NULL) {
                eta = build_eta_name(algname);
-               run_test_sizes(eta, sizes, nsizes);
+               run_test_sizes(eta);
                free_eta(eta);
        } else {
                alg = find_alg(algname);
                if (alg == NULL)
                        errx(1, "Invalid algorithm %s", algname);
-               run_test_sizes(alg, sizes, nsizes);
+               run_test_sizes(alg);
        }
 
        return (0);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to