aboutsummaryrefslogtreecommitdiff
path: root/tools/tools/crypto
diff options
context:
space:
mode:
authorConrad Meyer <cem@FreeBSD.org>2018-07-09 07:28:13 +0000
committerConrad Meyer <cem@FreeBSD.org>2018-07-09 07:28:13 +0000
commitc4729f6e89f09aead4b86294998659ac55187fe5 (patch)
treeca8881c5d703c1c2a3b9f18328dcdca5b22cf44c /tools/tools/crypto
parentc97f39ce17114100b5c463a7544912698193576a (diff)
downloadsrc-c4729f6e89f09aead4b86294998659ac55187fe5.tar.gz
src-c4729f6e89f09aead4b86294998659ac55187fe5.zip
OCF: Add plain hash modes
In part, to support OpenSSL's use of cryptodev, which puts the HMAC pieces in software and only offloads the raw hash primitive. The following cryptodev identifiers are added: * CRYPTO_RIPEMD160 (not hooked up) * CRYPTO_SHA2_224 * CRYPTO_SHA2_256 * CRYPTO_SHA2_384 * CRYPTO_SHA2_512 The plain SHA1 and 2 hashes are plumbed through cryptodev (feels like there is a lot of redundancy here...) and cryptosoft. This adds new auth_hash implementations for the plain hashes, as well as SHA1 (which had a cryptodev.h identifier, but no implementation). Add plain SHA 1 and 2 hash tests to the cryptocheck tool. Motivation stems from John Baldwin's earlier OCF email, https://lists.freebsd.org/pipermail/freebsd-arch/2018-January/018835.html .
Notes
Notes: svn path=/head/; revision=336125
Diffstat (limited to 'tools/tools/crypto')
-rw-r--r--tools/tools/crypto/cryptocheck.c162
1 files changed, 155 insertions, 7 deletions
diff --git a/tools/tools/crypto/cryptocheck.c b/tools/tools/crypto/cryptocheck.c
index 8e7629856af0..fa3459734c65 100644
--- a/tools/tools/crypto/cryptocheck.c
+++ b/tools/tools/crypto/cryptocheck.c
@@ -131,19 +131,29 @@ struct alg {
const char *name;
int cipher;
int mac;
- enum { T_HMAC, T_BLKCIPHER, T_AUTHENC, T_GCM } type;
+ enum { T_HASH, T_HMAC, T_BLKCIPHER, T_AUTHENC, T_GCM } type;
const EVP_CIPHER *(*evp_cipher)(void);
const EVP_MD *(*evp_md)(void);
} algs[] = {
- { .name = "sha1", .mac = CRYPTO_SHA1_HMAC, .type = T_HMAC,
+ { .name = "sha1", .mac = CRYPTO_SHA1, .type = T_HASH,
.evp_md = EVP_sha1 },
- { .name = "sha224", .mac = CRYPTO_SHA2_224_HMAC, .type = T_HMAC,
+ { .name = "sha224", .mac = CRYPTO_SHA2_224, .type = T_HASH,
.evp_md = EVP_sha224 },
- { .name = "sha256", .mac = CRYPTO_SHA2_256_HMAC, .type = T_HMAC,
+ { .name = "sha256", .mac = CRYPTO_SHA2_256, .type = T_HASH,
.evp_md = EVP_sha256 },
- { .name = "sha384", .mac = CRYPTO_SHA2_384_HMAC, .type = T_HMAC,
+ { .name = "sha384", .mac = CRYPTO_SHA2_384, .type = T_HASH,
.evp_md = EVP_sha384 },
- { .name = "sha512", .mac = CRYPTO_SHA2_512_HMAC, .type = T_HMAC,
+ { .name = "sha512", .mac = CRYPTO_SHA2_512, .type = T_HASH,
+ .evp_md = EVP_sha512 },
+ { .name = "sha1hmac", .mac = CRYPTO_SHA1_HMAC, .type = T_HMAC,
+ .evp_md = EVP_sha1 },
+ { .name = "sha224hmac", .mac = CRYPTO_SHA2_224_HMAC, .type = T_HMAC,
+ .evp_md = EVP_sha224 },
+ { .name = "sha256hmac", .mac = CRYPTO_SHA2_256_HMAC, .type = T_HMAC,
+ .evp_md = EVP_sha256 },
+ { .name = "sha384hmac", .mac = CRYPTO_SHA2_384_HMAC, .type = T_HMAC,
+ .evp_md = EVP_sha384 },
+ { .name = "sha512hmac", .mac = CRYPTO_SHA2_512_HMAC, .type = T_HMAC,
.evp_md = EVP_sha512 },
{ .name = "blake2b", .mac = CRYPTO_BLAKE2B, .type = T_HMAC,
.evp_md = EVP_blake2b512 },
@@ -352,6 +362,128 @@ generate_iv(size_t len, struct alg *alg)
}
static bool
+ocf_hash(struct alg *alg, const char *buffer, size_t size, char *digest,
+ int *cridp)
+{
+ struct session2_op sop;
+ struct crypt_op cop;
+ int fd;
+
+ memset(&sop, 0, sizeof(sop));
+ memset(&cop, 0, sizeof(cop));
+ sop.crid = crid;
+ sop.mac = alg->mac;
+ fd = crget();
+ if (ioctl(fd, CIOCGSESSION2, &sop) < 0) {
+ warn("cryptodev %s HASH not supported for device %s",
+ alg->name, crfind(crid));
+ close(fd);
+ return (false);
+ }
+
+ cop.ses = sop.ses;
+ cop.op = 0;
+ cop.len = size;
+ cop.src = (char *)buffer;
+ cop.dst = NULL;
+ cop.mac = digest;
+ cop.iv = NULL;
+
+ if (ioctl(fd, CIOCCRYPT, &cop) < 0) {
+ warn("cryptodev %s (%zu) HASH failed for device %s", alg->name,
+ size, crfind(crid));
+ close(fd);
+ return (false);
+ }
+
+ if (ioctl(fd, CIOCFSESSION, &sop.ses) < 0)
+ warn("ioctl(CIOCFSESSION)");
+
+ close(fd);
+ *cridp = sop.crid;
+ return (true);
+}
+
+static void
+openssl_hash(struct alg *alg, const EVP_MD *md, const void *buffer,
+ size_t size, void *digest_out, unsigned *digest_sz_out)
+{
+ EVP_MD_CTX *mdctx;
+ const char *errs;
+ int rc;
+
+ errs = "";
+
+ mdctx = EVP_MD_CTX_create();
+ if (mdctx == NULL)
+ goto err_out;
+
+ rc = EVP_DigestInit_ex(mdctx, md, NULL);
+ if (rc != 1)
+ goto err_out;
+
+ rc = EVP_DigestUpdate(mdctx, buffer, size);
+ if (rc != 1)
+ goto err_out;
+
+ rc = EVP_DigestFinal_ex(mdctx, digest_out, digest_sz_out);
+ if (rc != 1)
+ goto err_out;
+
+ EVP_MD_CTX_destroy(mdctx);
+ return;
+
+err_out:
+ errx(1, "OpenSSL %s HASH failed%s: %s", alg->name, errs,
+ ERR_error_string(ERR_get_error(), NULL));
+}
+
+static void
+run_hash_test(struct alg *alg, size_t size)
+{
+ const EVP_MD *md;
+ char *buffer;
+ u_int digest_len;
+ int crid;
+ char control_digest[EVP_MAX_MD_SIZE], test_digest[EVP_MAX_MD_SIZE];
+
+ memset(control_digest, 0x3c, sizeof(control_digest));
+ memset(test_digest, 0x3c, sizeof(test_digest));
+
+ md = alg->evp_md();
+ assert(EVP_MD_size(md) <= sizeof(control_digest));
+
+ buffer = alloc_buffer(size);
+
+ /* OpenSSL HASH. */
+ digest_len = sizeof(control_digest);
+ openssl_hash(alg, md, buffer, size, control_digest, &digest_len);
+
+ /* cryptodev HASH. */
+ if (!ocf_hash(alg, buffer, size, test_digest, &crid))
+ goto out;
+ if (memcmp(control_digest, test_digest, sizeof(control_digest)) != 0) {
+ if (memcmp(control_digest, test_digest, EVP_MD_size(md)) == 0)
+ printf("%s (%zu) mismatch in trailer:\n",
+ alg->name, size);
+ else
+ printf("%s (%zu) mismatch:\n", alg->name, size);
+ printf("control:\n");
+ hexdump(control_digest, sizeof(control_digest), NULL, 0);
+ printf("test (cryptodev device %s):\n", crfind(crid));
+ hexdump(test_digest, sizeof(test_digest), NULL, 0);
+ goto out;
+ }
+
+ if (verbose)
+ printf("%s (%zu) matched (cryptodev device %s)\n",
+ alg->name, size, crfind(crid));
+
+out:
+ free(buffer);
+}
+
+static bool
ocf_hmac(struct alg *alg, const char *buffer, size_t size, const char *key,
size_t key_len, char *digest, int *cridp)
{
@@ -1031,6 +1163,9 @@ run_test(struct alg *alg, size_t size)
{
switch (alg->type) {
+ case T_HASH:
+ run_hash_test(alg, size);
+ break;
case T_HMAC:
run_hmac_test(alg, size);
break;
@@ -1056,6 +1191,16 @@ run_test_sizes(struct alg *alg, size_t *sizes, u_int nsizes)
}
static void
+run_hash_tests(size_t *sizes, u_int nsizes)
+{
+ u_int i;
+
+ for (i = 0; i < nitems(algs); i++)
+ if (algs[i].type == T_HASH)
+ run_test_sizes(&algs[i], sizes, nsizes);
+}
+
+static void
run_hmac_tests(size_t *sizes, u_int nsizes)
{
u_int i;
@@ -1177,7 +1322,9 @@ main(int ac, char **av)
}
}
- if (strcasecmp(algname, "hmac") == 0)
+ if (strcasecmp(algname, "hash") == 0)
+ run_hash_tests(sizes, nsizes);
+ else if (strcasecmp(algname, "hmac") == 0)
run_hmac_tests(sizes, nsizes);
else if (strcasecmp(algname, "blkcipher") == 0)
run_blkcipher_tests(sizes, nsizes);
@@ -1186,6 +1333,7 @@ main(int ac, char **av)
else if (strcasecmp(algname, "aead") == 0)
run_aead_tests(sizes, nsizes);
else if (strcasecmp(algname, "all") == 0) {
+ run_hash_tests(sizes, nsizes);
run_hmac_tests(sizes, nsizes);
run_blkcipher_tests(sizes, nsizes);
run_authenc_tests(sizes, nsizes);