svn commit: r361487 - head/tools/tools/crypto
John Baldwin
jhb at FreeBSD.org
Mon May 25 23:04:18 UTC 2020
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);
More information about the svn-src-all
mailing list