Skip to contentSkip to conversation

RFC: s390/crypto: Add hardware acceleration for HMAC modes

PATCH Harald Freudenberger 2 participants 3 messages Aug 13, 2024 – Aug 14, 2024 2 messages not in the archive

Subsystems (3)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): [email protected]

Harald Freudenberger

author maintainer
#2 lore raw

Hello Herbert, hi linux kernel crypto list

With the next s390 machine generation there comes hmac(sha2) support in hardware. So here is a patch which exploits this hardware.
However, before pushing this into linux-next it would be nice to get some feedback and a review of someone really familiar with all the odds and ends of the in-kernel crypto implementations.

The implementation here is a shash implementation providing hmac(sha224), hmac(sha256), hmac(sha384) and hmac(sha512) support. This is file arch/s390/crypto/hmac_s390.c. It would be nice to get some feedback if we did this the correct way. The rest of the patch is s390 specific - ignore it.

Thanks for spending some time on this.
Harald Freudenberger

-------- Original Message --------
Subject: [PATCH v3 2/2] s390/crypto: Add hardware acceleration for HMAC modes
Date: 2024-08-07 18:06
From: Holger Dengler <[email protected]>
To: [email protected]
Cc: [email protected], [email protected], Heiko Carstens <[email protected]>, Vasily Gorbik <[email protected]>, Alexander Gordeev <[email protected]>

Add new shash exploiting the HMAC hardware accelerations for SHA224, SHA256, SHA384 and SHA512 introduced with message-security assist extension 11.

Reference-ID: SEC2304

---
 arch/s390/configs/debug_defconfig |   1 +
 arch/s390/configs/defconfig       |   1 +
 arch/s390/crypto/Kconfig          |  10 +
 arch/s390/crypto/Makefile         |   1 +
 arch/s390/crypto/hmac_s390.c      | 334 ++++++++++++++++++++++++++++++
 arch/s390/include/asm/cpacf.h     |  37 +++-
 6 files changed, 376 insertions(+), 8 deletions(-)
 create mode 100644 arch/s390/crypto/hmac_s390.c
arch/s390/configs/debug_defconfig +1 -0
index ea63a7342f5f..6c57f024acae 100644
@@ -794,6 +794,7 @@ CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_CHACHA_S390=m
+CONFIG_CRYPTO_HMAC_S390=m
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
 CONFIG_CRYPTO_PAES_S390=m
arch/s390/configs/defconfig +1 -0
index d8b28ff8ff45..c75e375570fa 100644
@@ -781,6 +781,7 @@ CONFIG_CRYPTO_GHASH_S390=m
 CONFIG_CRYPTO_AES_S390=m
 CONFIG_CRYPTO_DES_S390=m
 CONFIG_CRYPTO_CHACHA_S390=m
+CONFIG_CRYPTO_HMAC_S390=m
 CONFIG_ZCRYPT=m
 CONFIG_PKEY=m
 CONFIG_CRYPTO_PAES_S390=m
arch/s390/crypto/Kconfig +10 -0
index 06ee706b0d78..d3eb3a233693 100644
@@ -132,4 +132,14 @@ config CRYPTO_CHACHA_S390
 
 	  It is available as of z13.
 
+config CRYPTO_HMAC_S390
+	tristate "Keyed-hash message authentication code: HMAC"
+	depends on S390
+	select CRYPTO_HASH
+	help
+	  s390 specific HMAC hardware support for SHA224, SHA256, SHA384 and
+	  SHA512.
+
+	  Architecture: s390
+
 endmenu
arch/s390/crypto/Makefile +1 -0
index 1b1cc478fa94..a0cb96937c3d 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_CRYPTO_CHACHA_S390) += chacha_s390.o
 obj-$(CONFIG_S390_PRNG) += prng.o
 obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o
 obj-$(CONFIG_CRYPTO_CRC32_S390) += crc32-vx_s390.o
+obj-$(CONFIG_CRYPTO_HMAC_S390) += hmac_s390.o
 obj-y += arch_random.o
 
 crc32-vx_s390-y := crc32-vx.o crc32le-vx.o crc32be-vx.o
arch/s390/crypto/hmac_s390.c new file +334 -0

334 lines not on this page · raw message

arch/s390/include/asm/cpacf.h +7 -3
index b2f355751bf6..2dbe2e2088bb 100644
@@ -123,6 +123,10 @@
 #define CPACF_KMAC_DEA		0x01
 #define CPACF_KMAC_TDEA_128	0x02
 #define CPACF_KMAC_TDEA_192	0x03
+#define CPACF_KMAC_HMAC_SHA_224	0x70
+#define CPACF_KMAC_HMAC_SHA_256	0x71
+#define CPACF_KMAC_HMAC_SHA_384	0x72
+#define CPACF_KMAC_HMAC_SHA_512	0x73
 
 /*
  * Function codes for the PCKMO (PERFORM CRYPTOGRAPHIC KEY MANAGEMENT)
@@ -427,35 +431,52 @@ static inline void cpacf_klmd(unsigned long func, void *param,
 }
 
 /**
- * cpacf_kmac() - executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
- *		  instruction
- * @func: the function code passed to KM; see CPACF_KMAC_xxx defines
+ * _cpacf_kmac() - executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
+ * instruction and updates flags in gr0
+ * @gr0: pointer to gr0 (fc and flags) passed to KMAC; see CPACF_KMAC_xxx defines
  * @param: address of parameter block; see POP for details on each func
  * @src: address of source memory area
  * @src_len: length of src operand in bytes
  *
  * Returns 0 for the query func, number of processed bytes for digest 

funcs
*/
-static inline int cpacf_kmac(unsigned long func, void *param,
- const u8 *src, long src_len)
+static inline int _cpacf_kmac(unsigned long *gr0, void *param,
+ const u8 *src, long src_len)
{
union register_pair s;

s.even = (unsigned long)src;
s.odd = (unsigned long)src_len;
asm volatile(
- " lgr 0,%[fc]\n"
+ " lgr 0,%[r0]\n"
" lgr 1,%[pba]\n"
"0: .insn rre,%[opc] << 16,0,%[src]\n"
" brc 1,0b\n" /* handle partial completion */
- : [src] "+&d" (s.pair)
- : [fc] "d" (func), [pba] "d" ((unsigned long)param),
+ " lgr %[r0],0\n"
+ : [r0] "+d" (*gr0), [src] "+&d" (s.pair)
+ : [pba] "d" ((unsigned long)param),
[opc] "i" (CPACF_KMAC)
: "cc", "memory", "0", "1");

return src_len - s.odd;
}

+/**
+ * cpacf_kmac() - executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
+ * instruction
+ * @func: function code passed to KMAC; see CPACF_KMAC_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Returns 0 for the query func, number of processed bytes for digest funcs
+ */
+static inline int cpacf_kmac(unsigned long func, void *param,
+ const u8 *src, long src_len)
+{
+ return _cpacf_kmac(&func, param, src, src_len);
+}
+
/**
* cpacf_kmctr() - executes the KMCTR (CIPHER MESSAGE WITH COUNTER)
instruction
* @func: the function code passed to KMCTR; see CPACF_KMCTR_xxx
defines

maintainer
#3 lore raw
Quoted 26 lines · Harald Freudenberger
arch/s390/crypto/hmac_s390.c new file +25 -0
+static int hash(const u8 *in, unsigned int inlen,
+		u8 *digest, unsigned int digestsize)
+{
+	struct crypto_shash *htfm;
+	const char *alg_name;
+	int ret;
+
+	switch (digestsize) {
+	case SHA224_DIGEST_SIZE:
+		alg_name = "sha224";
+		break;
+	case SHA256_DIGEST_SIZE:
+		alg_name = "sha256";
+		break;
+	case SHA384_DIGEST_SIZE:
+		alg_name = "sha384";
+		break;
+	case SHA512_DIGEST_SIZE:
+		alg_name = "sha512";
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	htfm = crypto_alloc_shash(alg_name, 0, CRYPTO_ALG_NEED_FALLBACK);

arch/s390/crypto/hmac_s390.c line 132

Quoted 10 lines
arch/s390/crypto/hmac_s390.c new file +10 -0
+	if (IS_ERR(htfm))
+		return PTR_ERR(htfm);
+
+	ret = crypto_shash_tfm_digest(htfm, in, inlen, digest);
+	if (ret)
+		pr_err("shash digest error: %d\n", ret);
+
+	crypto_free_shash(htfm);
+	return ret;
+}

The setkey function can be called in softirq context. Therefore calling crypto_alloc_* from it is not allowed. You could either move the allocation to init_tfm and carry it throughout the life of the tfm, or perhaps you could call the s390 underlying sha hash function directly?

Cheers,

Signature · 3 lines
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
author maintainer
#4 lore raw
Quoted 44 lines · Herbert Xu
Quoted 26 lines · Harald Freudenberger
arch/s390/crypto/hmac_s390.c new file +25 -0
+static int hash(const u8 *in, unsigned int inlen,
+		u8 *digest, unsigned int digestsize)
+{
+	struct crypto_shash *htfm;
+	const char *alg_name;
+	int ret;
+
+	switch (digestsize) {
+	case SHA224_DIGEST_SIZE:
+		alg_name = "sha224";
+		break;
+	case SHA256_DIGEST_SIZE:
+		alg_name = "sha256";
+		break;
+	case SHA384_DIGEST_SIZE:
+		alg_name = "sha384";
+		break;
+	case SHA512_DIGEST_SIZE:
+		alg_name = "sha512";
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	htfm = crypto_alloc_shash(alg_name, 0, CRYPTO_ALG_NEED_FALLBACK);

arch/s390/crypto/hmac_s390.c line 132

Quoted 10 lines
arch/s390/crypto/hmac_s390.c new file +10 -0
+	if (IS_ERR(htfm))
+		return PTR_ERR(htfm);
+
+	ret = crypto_shash_tfm_digest(htfm, in, inlen, digest);
+	if (ret)
+		pr_err("shash digest error: %d\n", ret);
+
+	crypto_free_shash(htfm);
+	return ret;
+}

The setkey function can be called in softirq context. Therefore calling crypto_alloc_* from it is not allowed. You could either move the allocation to init_tfm and carry it throughout the life of the tfm, or perhaps you could call the s390 underlying sha hash function directly?

Quoted 1 line

Cheers,

Ok, good catch. I'll discuss this with Holger when he is back from vacation.

Thanks for your work.