Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 9 Jul 2018 07:28:13 +0000 (UTC)
From:      Conrad Meyer <cem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r336125 - in head: sys/opencrypto tools/tools/crypto
Message-ID:  <201807090728.w697SDGE025242@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: cem
Date: Mon Jul  9 07:28:13 2018
New Revision: 336125
URL: https://svnweb.freebsd.org/changeset/base/336125

Log:
  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 .

Modified:
  head/sys/opencrypto/cryptodev.c
  head/sys/opencrypto/cryptodev.h
  head/sys/opencrypto/cryptosoft.c
  head/sys/opencrypto/xform_auth.h
  head/sys/opencrypto/xform_sha1.c
  head/sys/opencrypto/xform_sha2.c
  head/tools/tools/crypto/cryptocheck.c

Modified: head/sys/opencrypto/cryptodev.c
==============================================================================
--- head/sys/opencrypto/cryptodev.c	Mon Jul  9 07:26:12 2018	(r336124)
+++ head/sys/opencrypto/cryptodev.c	Mon Jul  9 07:28:13 2018	(r336125)
@@ -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;

Modified: head/sys/opencrypto/cryptodev.h
==============================================================================
--- head/sys/opencrypto/cryptodev.h	Mon Jul  9 07:26:12 2018	(r336124)
+++ head/sys/opencrypto/cryptodev.h	Mon Jul  9 07:28:13 2018	(r336125)
@@ -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)

Modified: head/sys/opencrypto/cryptosoft.c
==============================================================================
--- head/sys/opencrypto/cryptosoft.c	Mon Jul  9 07:26:12 2018	(r336124)
+++ head/sys/opencrypto/cryptosoft.c	Mon Jul  9 07:28:13 2018	(r336125)
@@ -421,6 +421,14 @@ swcr_authcompute(struct cryptodesc *crd, struct swcr_d
 		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 c
 		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 c
 			(*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 hi
 		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);

Modified: head/sys/opencrypto/xform_auth.h
==============================================================================
--- head/sys/opencrypto/xform_auth.h	Mon Jul  9 07:26:12 2018	(r336124)
+++ head/sys/opencrypto/xform_auth.h	Mon Jul  9 07:28:13 2018	(r336125)
@@ -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;

Modified: head/sys/opencrypto/xform_sha1.c
==============================================================================
--- head/sys/opencrypto/xform_sha1.c	Mon Jul  9 07:26:12 2018	(r336124)
+++ head/sys/opencrypto/xform_sha1.c	Mon Jul  9 07:28:13 2018	(r336125)
@@ -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,

Modified: head/sys/opencrypto/xform_sha2.c
==============================================================================
--- head/sys/opencrypto/xform_sha2.c	Mon Jul  9 07:26:12 2018	(r336124)
+++ head/sys/opencrypto/xform_sha2.c	Mon Jul  9 07:28:13 2018	(r336125)
@@ -61,6 +61,54 @@ static	int SHA256Update_int(void *, const u_int8_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,

Modified: head/tools/tools/crypto/cryptocheck.c
==============================================================================
--- head/tools/tools/crypto/cryptocheck.c	Mon Jul  9 07:26:12 2018	(r336124)
+++ head/tools/tools/crypto/cryptocheck.c	Mon Jul  9 07:28:13 2018	(r336125)
@@ -131,20 +131,30 @@ 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 },
 	{ .name = "blake2s", .mac = CRYPTO_BLAKE2S, .type = T_HMAC,
@@ -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 n
 }
 
 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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201807090728.w697SDGE025242>