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 .
This commit is contained in:
Conrad Meyer 2018-07-09 07:28:13 +00:00
parent c97f39ce17
commit c4729f6e89
7 changed files with 274 additions and 10 deletions

View File

@ -489,10 +489,23 @@ cryptof_ioctl(
case CRYPTO_MD5:
thash = &auth_hash_md5;
break;
#endif
case CRYPTO_SHA1:
thash = &auth_hash_sha1;
break;
#endif
case CRYPTO_SHA2_224:
thash = &auth_hash_sha2_224;
break;
case CRYPTO_SHA2_256:
thash = &auth_hash_sha2_256;
break;
case CRYPTO_SHA2_384:
thash = &auth_hash_sha2_384;
break;
case CRYPTO_SHA2_512:
thash = &auth_hash_sha2_512;
break;
case CRYPTO_NULL_HMAC:
thash = &auth_hash_null;
break;

View File

@ -186,7 +186,12 @@
#define CRYPTO_BLAKE2S 30 /* Blake2s hash */
#define CRYPTO_CHACHA20 31 /* Chacha20 stream cipher */
#define CRYPTO_SHA2_224_HMAC 32
#define CRYPTO_ALGORITHM_MAX 32 /* Keep updated - see below */
#define CRYPTO_RIPEMD160 33
#define CRYPTO_SHA2_224 34
#define CRYPTO_SHA2_256 35
#define CRYPTO_SHA2_384 36
#define CRYPTO_SHA2_512 37
#define CRYPTO_ALGORITHM_MAX 37 /* Keep updated - see below */
#define CRYPTO_ALGO_VALID(x) ((x) >= CRYPTO_ALGORITHM_MIN && \
(x) <= CRYPTO_ALGORITHM_MAX)

View File

@ -421,6 +421,14 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf,
return err;
switch (sw->sw_alg) {
case CRYPTO_SHA1:
case CRYPTO_SHA2_224:
case CRYPTO_SHA2_256:
case CRYPTO_SHA2_384:
case CRYPTO_SHA2_512:
axf->Final(aalg, &ctx);
break;
case CRYPTO_MD5_HMAC:
case CRYPTO_SHA1_HMAC:
case CRYPTO_SHA2_224_HMAC:
@ -934,9 +942,23 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
case CRYPTO_MD5:
axf = &auth_hash_md5;
goto auth3common;
#endif
case CRYPTO_SHA1:
axf = &auth_hash_sha1;
goto auth3common;
case CRYPTO_SHA2_224:
axf = &auth_hash_sha2_224;
goto auth3common;
case CRYPTO_SHA2_256:
axf = &auth_hash_sha2_256;
goto auth3common;
case CRYPTO_SHA2_384:
axf = &auth_hash_sha2_384;
goto auth3common;
case CRYPTO_SHA2_512:
axf = &auth_hash_sha2_512;
auth3common:
(*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA,
M_NOWAIT);
@ -950,7 +972,6 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
(*swd)->sw_mlen = cri->cri_mlen;
(*swd)->sw_axf = axf;
break;
#endif
case CRYPTO_AES_128_NIST_GMAC:
axf = &auth_hash_nist_gmac_aes_128;
@ -1110,6 +1131,10 @@ swcr_freesession_locked(device_t dev, u_int64_t tid)
case CRYPTO_BLAKE2S:
case CRYPTO_MD5:
case CRYPTO_SHA1:
case CRYPTO_SHA2_224:
case CRYPTO_SHA2_256:
case CRYPTO_SHA2_384:
case CRYPTO_SHA2_512:
axf = swd->sw_axf;
if (swd->sw_ictx) {
@ -1216,6 +1241,10 @@ swcr_process(device_t dev, struct cryptop *crp, int hint)
case CRYPTO_SHA1_KPDK:
case CRYPTO_MD5:
case CRYPTO_SHA1:
case CRYPTO_SHA2_224:
case CRYPTO_SHA2_256:
case CRYPTO_SHA2_384:
case CRYPTO_SHA2_512:
case CRYPTO_BLAKE2B:
case CRYPTO_BLAKE2S:
if ((crp->crp_etype = swcr_authcompute(crd, sw,
@ -1300,6 +1329,10 @@ swcr_attach(device_t dev)
REGISTER(CRYPTO_SHA1_KPDK);
REGISTER(CRYPTO_MD5);
REGISTER(CRYPTO_SHA1);
REGISTER(CRYPTO_SHA2_224);
REGISTER(CRYPTO_SHA2_256);
REGISTER(CRYPTO_SHA2_384);
REGISTER(CRYPTO_SHA2_512);
REGISTER(CRYPTO_RIJNDAEL128_CBC);
REGISTER(CRYPTO_AES_XTS);
REGISTER(CRYPTO_AES_ICM);

View File

@ -73,6 +73,11 @@ extern struct auth_hash auth_hash_hmac_sha2_224;
extern struct auth_hash auth_hash_hmac_sha2_256;
extern struct auth_hash auth_hash_hmac_sha2_384;
extern struct auth_hash auth_hash_hmac_sha2_512;
extern struct auth_hash auth_hash_sha1;
extern struct auth_hash auth_hash_sha2_224;
extern struct auth_hash auth_hash_sha2_256;
extern struct auth_hash auth_hash_sha2_384;
extern struct auth_hash auth_hash_sha2_512;
extern struct auth_hash auth_hash_nist_gmac_aes_128;
extern struct auth_hash auth_hash_nist_gmac_aes_192;
extern struct auth_hash auth_hash_nist_gmac_aes_256;

View File

@ -57,6 +57,18 @@ static void SHA1Init_int(void *);
static int SHA1Update_int(void *, const u_int8_t *, u_int16_t);
static void SHA1Final_int(u_int8_t *, void *);
/* Plain hash */
struct auth_hash auth_hash_sha1 = {
.type = CRYPTO_SHA1,
.name = "SHA1",
.hashsize = SHA1_HASH_LEN,
.ctxsize = sizeof(SHA1_CTX),
.blocksize = SHA1_BLOCK_LEN,
.Init = SHA1Init_int,
.Update = SHA1Update_int,
.Final = SHA1Final_int,
};
/* Authentication instances */
struct auth_hash auth_hash_hmac_sha1 = {
.type = CRYPTO_SHA1_HMAC,

View File

@ -61,6 +61,54 @@ static int SHA256Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA384Update_int(void *, const u_int8_t *, u_int16_t);
static int SHA512Update_int(void *, const u_int8_t *, u_int16_t);
/* Plain hashes */
struct auth_hash auth_hash_sha2_224 = {
.type = CRYPTO_SHA2_224,
.name = "SHA2-224",
.hashsize = SHA2_224_HASH_LEN,
.ctxsize = sizeof(SHA224_CTX),
.blocksize = SHA2_224_BLOCK_LEN,
.Init = (void (*)(void *)) SHA224_Init,
.Update = SHA224Update_int,
.Final = (void (*)(u_int8_t *, void *)) SHA224_Final,
};
struct auth_hash auth_hash_sha2_256 = {
.type = CRYPTO_SHA2_256,
.name = "SHA2-256",
.keysize = SHA2_256_BLOCK_LEN,
.hashsize = SHA2_256_HASH_LEN,
.ctxsize = sizeof(SHA256_CTX),
.blocksize = SHA2_256_BLOCK_LEN,
.Init = (void (*)(void *)) SHA256_Init,
.Update = SHA256Update_int,
.Final = (void (*)(u_int8_t *, void *)) SHA256_Final,
};
struct auth_hash auth_hash_sha2_384 = {
.type = CRYPTO_SHA2_384,
.name = "SHA2-384",
.keysize = SHA2_384_BLOCK_LEN,
.hashsize = SHA2_384_HASH_LEN,
.ctxsize = sizeof(SHA384_CTX),
.blocksize = SHA2_384_BLOCK_LEN,
.Init = (void (*)(void *)) SHA384_Init,
.Update = SHA384Update_int,
.Final = (void (*)(u_int8_t *, void *)) SHA384_Final,
};
struct auth_hash auth_hash_sha2_512 = {
.type = CRYPTO_SHA2_512,
.name = "SHA2-512",
.keysize = SHA2_512_BLOCK_LEN,
.hashsize = SHA2_512_HASH_LEN,
.ctxsize = sizeof(SHA512_CTX),
.blocksize = SHA2_512_BLOCK_LEN,
.Init = (void (*)(void *)) SHA512_Init,
.Update = SHA512Update_int,
.Final = (void (*)(u_int8_t *, void *)) SHA512_Final,
};
/* Authentication instances */
struct auth_hash auth_hash_hmac_sha2_224 = {
.type = CRYPTO_SHA2_224_HMAC,

View File

@ -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 },
@ -351,6 +361,128 @@ generate_iv(size_t len, struct alg *alg)
return (iv);
}
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;
@ -1055,6 +1190,16 @@ run_test_sizes(struct alg *alg, size_t *sizes, u_int nsizes)
run_test(alg, sizes[i]);
}
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)
{
@ -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);