linux-s390.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v12 0/6] New s390 specific protected key hmac
@ 2025-06-17 13:44 Harald Freudenberger
  2025-06-17 13:44 ` [PATCH v12 1/6] crypto: ahash - make hash walk functions from ahash.c public Harald Freudenberger
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Harald Freudenberger @ 2025-06-17 13:44 UTC (permalink / raw)
  To: herbert
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

Add support for protected key hmac ("phmac") for s390 arch.

With the latest machine generation there is now support for
protected key (that is a key wrapped by a master key stored
in firmware) hmac for sha2 (sha224, sha256, sha384 and sha512)
for the s390 specific CPACF instruction kmac.

This patch adds support via 4 new hashes registered as
phmac(sha224), phmac(sha256), phmac(sha384) and phmac(sha512).

Changelog:
v1: Initial version
v2: Increase HASH_MAX_DESCSIZE generic (not just for arch s390).
    Fix one finding to use kmemdup instead of kmalloc/memcpy from test
    robot. Remove unneeded cpacf subfunctions checks. Simplify
    clone_tfm() function. Rebased to s390/features.
v3: Feedback from Herbert: Use GFP_ATOMIC in setkey function.
    Feedback from Holger: rework tfm clone function, move convert key
    invocation from setkey to init function. Rebased to updated
    s390/features from 11/7/2024. Ready for integration if there are
    no complains on v3.
v4: Rewind back more or less to v2. Add code to check for non-sleeping
    context. Non-sleeping context during attempt to derive the
    protected key from raw key material is not accepted and
    -EOPNOTSUPP is returned (also currently all derivation pathes
    would in fact never sleep). In general the phmac implementation is
    not to be used within non-sleeping context and the code header
    mentions this. Tested with (patched) dm-integrity - works fine.
v5: As suggested by Herbert now the shashes have been marked as
    'internal' and wrapped by ahashes which use the cryptd if an
    atomic context is detected. So the visible phmac algorithms are
    now ahashes. Unfortunately the dm-integrity implementation
    currently requests and deals only with shashes and this phmac
    implementation is not fitting to the original goal any more...
v6: As suggested by Herbert now a pure async phmac implementation.
    Tested via AF_ALG interface. Untested via dm-integrity as this layer
    only supports shashes. Maybe I'll develop a patch to switch the
    dm-integrity to ahash as it is anyway the more flexible interface.
v7: Total rework of the implementation. Now uses workqueues and triggers
    asynch requests for key convert, init, update, final and digest.
    Tested with instrumented code and with a reworked version of
    dm-integrity which uses asynchronous hashes. A patch for dm-integrity
    is on the way but yet needs some last hone work.
v8: Added selftest. With the selftest comes some code which wraps the
    clear key into a "clear key token" digestible by PKEY. The
    selftest also uses import() and export(), so these are now also
    implemented. Furthermore a finup() implementation is now also
    available. Tested with AF_ALG testcases and dm-integrity, also
    tested with some instrumented code to check that the asynch
    workqueue functions do their job correctly. Coding is complete!
v9: As suggested by Herbert use ahash_request_complete() and surround it
    with local_bh_disable().
v10: Split the pkey selftest patch into 3 patches. Slight rework of the
     setkey function as suggested by Holger: When selftest is running
     as much as possible of the production code should run. So now the
     key prep with selftest is one additional if/then block instead of
     an if/then/else construct.
     Code is ready for integration and well tested.
v11: Utterly rework with the insights collected with the paes rework
     and the basic work done with the pkey rework over the last 5 month.
     Note that patch #1 effectively reverts commit 7fa481734016
     ("crypto: ahash - make hash walk functions private to ahash.c")
     from Eric Biggers.
v12: Fixed some typos, adaptions to 128 bit total counter,
     misc_register() invocation was missing in the patches series,
     added Herbert's proposal for a new function crypto_ahash_tested().

Harald Freudenberger (5):
  crypto: ahash - make hash walk functions from ahash.c  public
  s390/crypto: New s390 specific protected key hash phmac
  crypto: api - Add crypto_ahash_tested() helper function
  s390/crypto: Add selftest support for phmac
  crypto: testmgr - Enable phmac selftest

Holger Dengler (1):
  s390/crypto: Add protected key hmac subfunctions for KMAC

 arch/s390/configs/debug_defconfig |    1 +
 arch/s390/configs/defconfig       |    1 +
 arch/s390/crypto/Makefile         |    1 +
 arch/s390/crypto/phmac_s390.c     | 1048 +++++++++++++++++++++++++++++
 arch/s390/include/asm/cpacf.h     |    4 +
 crypto/ahash.c                    |   26 +-
 crypto/testmgr.c                  |   30 +
 drivers/crypto/Kconfig            |   13 +
 include/crypto/internal/hash.h    |   30 +
 9 files changed, 1133 insertions(+), 21 deletions(-)
 create mode 100644 arch/s390/crypto/phmac_s390.c


base-commit: 1029436218e50168812dbc44b16bca6d35721b0b
--
2.43.0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v12 1/6] crypto: ahash - make hash walk functions from ahash.c public
  2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
@ 2025-06-17 13:44 ` Harald Freudenberger
  2025-06-17 13:44 ` [PATCH v12 2/6] s390/crypto: Add protected key hmac subfunctions for KMAC Harald Freudenberger
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Harald Freudenberger @ 2025-06-17 13:44 UTC (permalink / raw)
  To: herbert
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

Make the hash walk functions
  crypto_hash_walk_done()
  crypto_hash_walk_first()
  crypto_hash_walk_last()
public again.
These functions had been removed from the header file
include/crypto/internal/hash.h with commit 7fa481734016
("crypto: ahash - make hash walk functions private to ahash.c")
as there was no crypto algorithm code using them.

With the upcoming crypto implementation for s390 phmac
these functions will be exploited and thus need to be
public within the kernel again.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Acked-by: Holger Dengler <dengler@linux.ibm.com>
---
 crypto/ahash.c                 | 26 +++++---------------------
 include/crypto/internal/hash.h | 23 +++++++++++++++++++++++
 2 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/crypto/ahash.c b/crypto/ahash.c
index bd9e49950201..0809ef102ef8 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -29,19 +29,6 @@
 
 #define CRYPTO_ALG_TYPE_AHASH_MASK	0x0000000e
 
-struct crypto_hash_walk {
-	const char *data;
-
-	unsigned int offset;
-	unsigned int flags;
-
-	struct page *pg;
-	unsigned int entrylen;
-
-	unsigned int total;
-	struct scatterlist *sg;
-};
-
 static int ahash_def_finup(struct ahash_request *req);
 
 static inline bool crypto_ahash_block_only(struct crypto_ahash *tfm)
@@ -112,8 +99,8 @@ static int hash_walk_new_entry(struct crypto_hash_walk *walk)
 	return hash_walk_next(walk);
 }
 
-static int crypto_hash_walk_first(struct ahash_request *req,
-				  struct crypto_hash_walk *walk)
+int crypto_hash_walk_first(struct ahash_request *req,
+			   struct crypto_hash_walk *walk)
 {
 	walk->total = req->nbytes;
 	walk->entrylen = 0;
@@ -133,8 +120,9 @@ static int crypto_hash_walk_first(struct ahash_request *req,
 
 	return hash_walk_new_entry(walk);
 }
+EXPORT_SYMBOL_GPL(crypto_hash_walk_first);
 
-static int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
+int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
 {
 	if ((walk->flags & CRYPTO_AHASH_REQ_VIRT))
 		return err;
@@ -160,11 +148,7 @@ static int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
 
 	return hash_walk_new_entry(walk);
 }
-
-static inline int crypto_hash_walk_last(struct crypto_hash_walk *walk)
-{
-	return !(walk->entrylen | walk->total);
-}
+EXPORT_SYMBOL_GPL(crypto_hash_walk_done);
 
 /*
  * For an ahash tfm that is using an shash algorithm (instead of an ahash
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index 0f85c543f80b..ef573545c85d 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -30,6 +30,20 @@
                 __##name##_req, (req))
 
 struct ahash_request;
+struct scatterlist;
+
+struct crypto_hash_walk {
+	const char *data;
+
+	unsigned int offset;
+	unsigned int flags;
+
+	struct page *pg;
+	unsigned int entrylen;
+
+	unsigned int total;
+	struct scatterlist *sg;
+};
 
 struct ahash_instance {
 	void (*free)(struct ahash_instance *inst);
@@ -61,6 +75,15 @@ struct crypto_shash_spawn {
 	struct crypto_spawn base;
 };
 
+int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err);
+int crypto_hash_walk_first(struct ahash_request *req,
+			   struct crypto_hash_walk *walk);
+
+static inline int crypto_hash_walk_last(struct crypto_hash_walk *walk)
+{
+	return !(walk->entrylen | walk->total);
+}
+
 int crypto_register_ahash(struct ahash_alg *alg);
 void crypto_unregister_ahash(struct ahash_alg *alg);
 int crypto_register_ahashes(struct ahash_alg *algs, int count);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v12 2/6] s390/crypto: Add protected key hmac subfunctions for KMAC
  2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
  2025-06-17 13:44 ` [PATCH v12 1/6] crypto: ahash - make hash walk functions from ahash.c public Harald Freudenberger
@ 2025-06-17 13:44 ` Harald Freudenberger
  2025-06-17 13:44 ` [PATCH v12 3/6] s390/crypto: New s390 specific protected key hash phmac Harald Freudenberger
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Harald Freudenberger @ 2025-06-17 13:44 UTC (permalink / raw)
  To: herbert
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

From: Holger Dengler <dengler@linux.ibm.com>

The CPACF KMAC instruction supports new subfunctions for
protected key hmac. Add defines for these 4 new subfuctions.

Signed-off-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
---
 arch/s390/include/asm/cpacf.h | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/s390/include/asm/cpacf.h b/arch/s390/include/asm/cpacf.h
index 54cb97603ec0..4bc5317fbb12 100644
--- a/arch/s390/include/asm/cpacf.h
+++ b/arch/s390/include/asm/cpacf.h
@@ -129,6 +129,10 @@
 #define CPACF_KMAC_HMAC_SHA_256	0x71
 #define CPACF_KMAC_HMAC_SHA_384	0x72
 #define CPACF_KMAC_HMAC_SHA_512	0x73
+#define CPACF_KMAC_PHMAC_SHA_224	0x78
+#define CPACF_KMAC_PHMAC_SHA_256	0x79
+#define CPACF_KMAC_PHMAC_SHA_384	0x7a
+#define CPACF_KMAC_PHMAC_SHA_512	0x7b
 
 /*
  * Function codes for the PCKMO (PERFORM CRYPTOGRAPHIC KEY MANAGEMENT)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v12 3/6] s390/crypto: New s390 specific protected key hash phmac
  2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
  2025-06-17 13:44 ` [PATCH v12 1/6] crypto: ahash - make hash walk functions from ahash.c public Harald Freudenberger
  2025-06-17 13:44 ` [PATCH v12 2/6] s390/crypto: Add protected key hmac subfunctions for KMAC Harald Freudenberger
@ 2025-06-17 13:44 ` Harald Freudenberger
  2025-06-18  9:21   ` Holger Dengler
  2025-06-18  9:29   ` Heiko Carstens
  2025-06-17 13:44 ` [PATCH v12 4/6] crypto: api - Add crypto_ahash_tested() helper function Harald Freudenberger
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 15+ messages in thread
From: Harald Freudenberger @ 2025-06-17 13:44 UTC (permalink / raw)
  To: herbert
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

Add support for protected key hmac ("phmac") for s390 arch.

With the latest machine generation there is now support for
protected key (that is a key wrapped by a master key stored
in firmware) hmac for sha2 (sha224, sha256, sha384 and sha512)
for the s390 specific CPACF instruction kmac.

This patch adds support via 4 new ahashes registered as
phmac(sha224), phmac(sha256), phmac(sha384) and phmac(sha512).

Co-developed-by: Holger Dengler <dengler@linux.ibm.com>
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
---
 arch/s390/configs/debug_defconfig |   1 +
 arch/s390/configs/defconfig       |   1 +
 arch/s390/crypto/Makefile         |   1 +
 arch/s390/crypto/phmac_s390.c     | 911 ++++++++++++++++++++++++++++++
 drivers/crypto/Kconfig            |  13 +
 5 files changed, 927 insertions(+)
 create mode 100644 arch/s390/crypto/phmac_s390.c

diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index 8ecad727497e..e91fe6c7832e 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -819,6 +819,7 @@ CONFIG_PKEY_EP11=m
 CONFIG_PKEY_PCKMO=m
 CONFIG_PKEY_UV=m
 CONFIG_CRYPTO_PAES_S390=m
+CONFIG_CRYPTO_PHMAC_S390=m
 CONFIG_CRYPTO_DEV_VIRTIO=m
 CONFIG_SYSTEM_BLACKLIST_KEYRING=y
 CONFIG_CRYPTO_KRB5=m
diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig
index c13a77765162..fae834beff57 100644
--- a/arch/s390/configs/defconfig
+++ b/arch/s390/configs/defconfig
@@ -806,6 +806,7 @@ CONFIG_PKEY_EP11=m
 CONFIG_PKEY_PCKMO=m
 CONFIG_PKEY_UV=m
 CONFIG_CRYPTO_PAES_S390=m
+CONFIG_CRYPTO_PHMAC_S390=m
 CONFIG_CRYPTO_DEV_VIRTIO=m
 CONFIG_SYSTEM_BLACKLIST_KEYRING=y
 CONFIG_CRYPTO_KRB5=m
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
index 21757d86cd49..6d1f1df46036 100644
--- a/arch/s390/crypto/Makefile
+++ b/arch/s390/crypto/Makefile
@@ -13,4 +13,5 @@ obj-$(CONFIG_CRYPTO_PAES_S390) += paes_s390.o
 obj-$(CONFIG_S390_PRNG) += prng.o
 obj-$(CONFIG_CRYPTO_GHASH_S390) += ghash_s390.o
 obj-$(CONFIG_CRYPTO_HMAC_S390) += hmac_s390.o
+obj-$(CONFIG_CRYPTO_PHMAC_S390) += phmac_s390.o
 obj-y += arch_random.o
diff --git a/arch/s390/crypto/phmac_s390.c b/arch/s390/crypto/phmac_s390.c
new file mode 100644
index 000000000000..8473af47f5b9
--- /dev/null
+++ b/arch/s390/crypto/phmac_s390.c
@@ -0,0 +1,911 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright IBM Corp. 2025
+ *
+ * s390 specific HMAC support for protected keys.
+ */
+
+#define KMSG_COMPONENT	"phmac_s390"
+#define pr_fmt(fmt)	KMSG_COMPONENT ": " fmt
+
+#include <asm/cpacf.h>
+#include <asm/pkey.h>
+#include <crypto/engine.h>
+#include <crypto/hash.h>
+#include <crypto/internal/hash.h>
+#include <crypto/sha2.h>
+#include <linux/atomic.h>
+#include <linux/cpufeature.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+static struct crypto_engine *phmac_crypto_engine;
+#define MAX_QLEN 10
+
+/*
+ * A simple hash walk helper
+ */
+
+struct hash_walk_helper {
+	struct crypto_hash_walk walk;
+	const u8 *walkaddr;
+	int walkbytes;
+};
+
+/*
+ * Prepare hash walk helper.
+ * Set up the base hash walk, fill walkaddr and walkbytes.
+ * Returns 0 on success or negative value on error.
+ */
+static inline int hwh_prepare(struct ahash_request *req,
+			      struct hash_walk_helper *hwh)
+{
+	hwh->walkbytes = crypto_hash_walk_first(req, &hwh->walk);
+	if (hwh->walkbytes < 0)
+		return hwh->walkbytes;
+	hwh->walkaddr = hwh->walk.data;
+	return 0;
+}
+
+/*
+ * Advance hash walk helper by n bytes.
+ * Progress the walkbytes and walkaddr fields by n bytes.
+ * If walkbytes is then 0, pull next hunk from hash walk
+ * and update walkbytes and walkaddr.
+ * If n is negative, unmap hash walk and return error.
+ * Returns 0 on success or negative value on error.
+ */
+static inline int hwh_advance(struct hash_walk_helper *hwh, int n)
+{
+	if (n < 0)
+		return crypto_hash_walk_done(&hwh->walk, n);
+
+	hwh->walkbytes -= n;
+	hwh->walkaddr += n;
+	if (hwh->walkbytes > 0)
+		return 0;
+
+	hwh->walkbytes = crypto_hash_walk_done(&hwh->walk, 0);
+	if (hwh->walkbytes < 0)
+		return hwh->walkbytes;
+
+	hwh->walkaddr = hwh->walk.data;
+	return 0;
+}
+
+/*
+ * KMAC param block layout for sha2 function codes:
+ * The layout of the param block for the KMAC instruction depends on the
+ * blocksize of the used hashing sha2-algorithm function codes. The param block
+ * contains the hash chaining value (cv), the input message bit-length (imbl)
+ * and the hmac-secret (key). To prevent code duplication, the sizes of all
+ * these are calculated based on the blocksize.
+ *
+ * param-block:
+ * +-------+
+ * | cv    |
+ * +-------+
+ * | imbl  |
+ * +-------+
+ * | key   |
+ * +-------+
+ *
+ * sizes:
+ * part | sh2-alg | calculation | size | type
+ * -----+---------+-------------+------+--------
+ * cv   | 224/256 | blocksize/2 |   32 |  u64[8]
+ *      | 384/512 |             |   64 | u128[8]
+ * imbl | 224/256 | blocksize/8 |    8 |     u64
+ *      | 384/512 |             |   16 |    u128
+ * key  | 224/256 | blocksize   |   96 |  u8[96]
+ *      | 384/512 |             |  160 | u8[160]
+ */
+
+#define MAX_DIGEST_SIZE		SHA512_DIGEST_SIZE
+#define MAX_IMBL_SIZE		sizeof(u128)
+#define MAX_BLOCK_SIZE		SHA512_BLOCK_SIZE
+
+#define SHA2_CV_SIZE(bs)	((bs) >> 1)
+#define SHA2_IMBL_SIZE(bs)	((bs) >> 3)
+
+#define SHA2_IMBL_OFFSET(bs)	(SHA2_CV_SIZE(bs))
+#define SHA2_KEY_OFFSET(bs)	(SHA2_CV_SIZE(bs) + SHA2_IMBL_SIZE(bs))
+
+#define PHMAC_MAX_KEYSIZE       256
+#define PHMAC_SHA256_PK_SIZE	(SHA256_BLOCK_SIZE + 32)
+#define PHMAC_SHA512_PK_SIZE	(SHA512_BLOCK_SIZE + 32)
+#define PHMAC_MAX_PK_SIZE	PHMAC_SHA512_PK_SIZE
+
+/* phmac protected key struct */
+struct phmac_protkey {
+	u32 type;
+	u32 len;
+	u8 protkey[PHMAC_MAX_PK_SIZE];
+};
+
+#define PK_STATE_NO_KEY		     0
+#define PK_STATE_CONVERT_IN_PROGRESS 1
+#define PK_STATE_VALID		     2
+
+/* phmac tfm context */
+struct phmac_tfm_ctx {
+	/* source key material used to derive a protected key from */
+	u8 keybuf[PHMAC_MAX_KEYSIZE];
+	unsigned int keylen;
+
+	/* cpacf function code to use with this protected key type */
+	long fc;
+
+	/* nr of requests enqueued via crypto engine which use this tfm ctx */
+	atomic_t via_engine_ctr;
+
+	/* spinlock to atomic read/update all the following fields */
+	spinlock_t pk_lock;
+
+	/* see PK_STATE* defines above, < 0 holds convert failure rc  */
+	int pk_state;
+	/* if state is valid, pk holds the protected key */
+	struct phmac_protkey pk;
+};
+
+union kmac_gr0 {
+	unsigned long reg;
+	struct {
+		unsigned long		: 48;
+		unsigned long ikp	:  1;
+		unsigned long iimp	:  1;
+		unsigned long ccup	:  1;
+		unsigned long		:  6;
+		unsigned long fc	:  7;
+	};
+};
+
+struct kmac_sha2_ctx {
+	u8 param[MAX_DIGEST_SIZE + MAX_IMBL_SIZE + PHMAC_MAX_PK_SIZE];
+	union kmac_gr0 gr0;
+	u8 buf[MAX_BLOCK_SIZE];
+	u64 buflen[2];
+};
+
+/* phmac request context */
+struct phmac_req_ctx {
+	struct hash_walk_helper hwh;
+	struct kmac_sha2_ctx kmac_ctx;
+	bool final;
+};
+
+/*
+ * phmac_tfm_ctx_setkey() - Set key value into tfm context, maybe construct
+ * a clear key token digestible by pkey from a clear key value.
+ */
+static inline int phmac_tfm_ctx_setkey(struct phmac_tfm_ctx *tfm_ctx,
+				       const u8 *key, unsigned int keylen)
+{
+	if (keylen > sizeof(tfm_ctx->keybuf))
+		return -EINVAL;
+
+	memcpy(tfm_ctx->keybuf, key, keylen);
+	tfm_ctx->keylen = keylen;
+
+	return 0;
+}
+
+/*
+ * Convert the raw key material into a protected key via PKEY api.
+ * This function may sleep - don't call in non-sleeping context.
+ */
+static inline int convert_key(const u8 *key, unsigned int keylen,
+			      struct phmac_protkey *pk)
+{
+	int rc, i;
+
+	pk->len = sizeof(pk->protkey);
+
+	/*
+	 * In case of a busy card retry with increasing delay
+	 * of 200, 400, 800 and 1600 ms - in total 3 s.
+	 */
+	for (rc = -EIO, i = 0; rc && i < 5; i++) {
+		if (rc == -EBUSY && msleep_interruptible((1 << i) * 100)) {
+			rc = -EINTR;
+			goto out;
+		}
+		rc = pkey_key2protkey(key, keylen,
+				      pk->protkey, &pk->len, &pk->type,
+				      PKEY_XFLAG_NOMEMALLOC);
+	}
+
+out:
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+/*
+ * (Re-)Convert the raw key material from the tfm ctx into a protected
+ * key via convert_key() function. Update the pk_state, pk_type, pk_len
+ * and the protected key in the tfm context.
+ * Please note this function may be invoked concurrently with the very
+ * same tfm context. The pk_lock spinlock in the context ensures an
+ * atomic update of the pk and the pk state but does not guarantee any
+ * order of update. So a fresh converted valid protected key may get
+ * updated with an 'old' expired key value. As the cpacf instructions
+ * detect this, refuse to operate with an invalid key and the calling
+ * code triggers a (re-)conversion this does no harm. This may lead to
+ * unnecessary additional conversion but never to invalid data on the
+ * hash operation.
+ */
+static int phmac_convert_key(struct phmac_tfm_ctx *tfm_ctx)
+{
+	struct phmac_protkey pk;
+	int rc;
+
+	spin_lock_bh(&tfm_ctx->pk_lock);
+	tfm_ctx->pk_state = PK_STATE_CONVERT_IN_PROGRESS;
+	spin_unlock_bh(&tfm_ctx->pk_lock);
+
+	rc = convert_key(tfm_ctx->keybuf, tfm_ctx->keylen, &pk);
+
+	/* update context */
+	spin_lock_bh(&tfm_ctx->pk_lock);
+	if (rc) {
+		tfm_ctx->pk_state = rc;
+	} else {
+		tfm_ctx->pk_state = PK_STATE_VALID;
+		tfm_ctx->pk = pk;
+	}
+	spin_unlock_bh(&tfm_ctx->pk_lock);
+
+	memzero_explicit(&pk, sizeof(pk));
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+/*
+ * kmac_sha2_set_imbl - sets the input message bit-length based on the blocksize
+ */
+static inline void kmac_sha2_set_imbl(u8 *param, u64 buflen_lo,
+				      u64 buflen_hi, unsigned int blocksize)
+{
+	u8 *imbl = param + SHA2_IMBL_OFFSET(blocksize);
+
+	switch (blocksize) {
+	case SHA256_BLOCK_SIZE:
+		*(u64 *)imbl = buflen_lo * BITS_PER_BYTE;
+		break;
+	case SHA512_BLOCK_SIZE:
+		*(u128 *)imbl = (((u128)buflen_hi << 64) + buflen_lo) << 3;
+		break;
+	default:
+		break;
+	}
+}
+
+static int phmac_kmac_update(struct ahash_request *req, bool maysleep)
+{
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
+	struct kmac_sha2_ctx *ctx = &req_ctx->kmac_ctx;
+	struct hash_walk_helper *hwh = &req_ctx->hwh;
+	unsigned int bs = crypto_ahash_blocksize(tfm);
+	unsigned int offset, k, n;
+	int rc = 0;
+
+	/*
+	 * The walk is always mapped when this function is called.
+	 * Note that in case of partial processing or failure the walk
+	 * is NOT unmapped here. So a follow up task may reuse the walk
+	 * or in case of unrecoverable failure needs to unmap it.
+	 */
+
+	while (hwh->walkbytes > 0) {
+		/* check sha2 context buffer */
+		offset = ctx->buflen[0] % bs;
+		if (offset + hwh->walkbytes < bs)
+			goto store;
+
+		if (offset) {
+			/* fill ctx buffer up to blocksize and process this block */
+			n = bs - offset;
+			memcpy(ctx->buf + offset, hwh->walkaddr, n);
+			ctx->gr0.iimp = 1;
+			for (;;) {
+				k = _cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, bs);
+				if (likely(k == bs))
+					break;
+				if (unlikely(k > 0)) {
+					/*
+					 * Can't deal with hunks smaller than blocksize.
+					 * And kmac should always return the nr of
+					 * processed bytes as 0 or a multiple of the
+					 * blocksize.
+					 */
+					rc = -EIO;
+					goto out;
+				}
+				/* protected key is invalid and needs re-conversion */
+				if (!maysleep) {
+					rc = -EKEYEXPIRED;
+					goto out;
+				}
+				rc = phmac_convert_key(tfm_ctx);
+				if (rc)
+					goto out;
+				spin_lock_bh(&tfm_ctx->pk_lock);
+				memcpy(ctx->param + SHA2_KEY_OFFSET(bs),
+				       tfm_ctx->pk.protkey, tfm_ctx->pk.len);
+				spin_unlock_bh(&tfm_ctx->pk_lock);
+			}
+			ctx->buflen[0] += n;
+			if (ctx->buflen[0] < n)
+				ctx->buflen[1]++;
+			rc = hwh_advance(hwh, n);
+			if (unlikely(rc))
+				goto out;
+			offset = 0;
+		}
+
+		/* process as many blocks as possible from the walk */
+		while (hwh->walkbytes >= bs) {
+			n = (hwh->walkbytes / bs) * bs;
+			ctx->gr0.iimp = 1;
+			k = _cpacf_kmac(&ctx->gr0.reg, ctx->param, hwh->walkaddr, n);
+			if (likely(k > 0)) {
+				ctx->buflen[0] += k;
+				if (ctx->buflen[0] < k)
+					ctx->buflen[1]++;
+				rc = hwh_advance(hwh, k);
+				if (unlikely(rc))
+					goto out;
+			}
+			if (unlikely(k < n)) {
+				/* protected key is invalid and needs re-conversion */
+				if (!maysleep) {
+					rc = -EKEYEXPIRED;
+					goto out;
+				}
+				rc = phmac_convert_key(tfm_ctx);
+				if (rc)
+					goto out;
+				spin_lock_bh(&tfm_ctx->pk_lock);
+				memcpy(ctx->param + SHA2_KEY_OFFSET(bs),
+				       tfm_ctx->pk.protkey, tfm_ctx->pk.len);
+				spin_unlock_bh(&tfm_ctx->pk_lock);
+			}
+		}
+
+store:
+		/* store incomplete block in context buffer */
+		if (hwh->walkbytes) {
+			memcpy(ctx->buf + offset, hwh->walkaddr, hwh->walkbytes);
+			ctx->buflen[0] += hwh->walkbytes;
+			if (ctx->buflen[0] < hwh->walkbytes)
+				ctx->buflen[1]++;
+			rc = hwh_advance(hwh, hwh->walkbytes);
+			if (unlikely(rc))
+				goto out;
+		}
+
+	} /* end of while (hwh->walkbytes > 0) */
+
+out:
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+static int phmac_kmac_final(struct ahash_request *req, bool maysleep)
+{
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
+	struct kmac_sha2_ctx *ctx = &req_ctx->kmac_ctx;
+	unsigned int ds = crypto_ahash_digestsize(tfm);
+	unsigned int bs = crypto_ahash_blocksize(tfm);
+	unsigned int k, n;
+	int rc = 0;
+
+	n = ctx->buflen[0] % bs;
+	ctx->gr0.iimp = 0;
+	kmac_sha2_set_imbl(ctx->param, ctx->buflen[0], ctx->buflen[1], bs);
+	for (;;) {
+		k = _cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, n);
+		if (likely(k == n))
+			break;
+		if (unlikely(k > 0)) {
+			/* Can't deal with hunks smaller than blocksize. */
+			rc = -EIO;
+			goto out;
+		}
+		/* protected key is invalid and needs re-conversion */
+		if (!maysleep) {
+			rc = -EKEYEXPIRED;
+			goto out;
+		}
+		rc = phmac_convert_key(tfm_ctx);
+		if (rc)
+			goto out;
+		spin_lock_bh(&tfm_ctx->pk_lock);
+		memcpy(ctx->param + SHA2_KEY_OFFSET(bs),
+		       tfm_ctx->pk.protkey, tfm_ctx->pk.len);
+		spin_unlock_bh(&tfm_ctx->pk_lock);
+	}
+
+	memcpy(req->result, ctx->param, ds);
+
+out:
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+static int phmac_init(struct ahash_request *req)
+{
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
+	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
+	unsigned int bs = crypto_ahash_blocksize(tfm);
+	int rc = 0;
+
+	/* zero request context (includes the kmac sha2 context) */
+	memset(req_ctx, 0, sizeof(*req_ctx));
+
+	/*
+	 * setkey() should have set a valid fc into the tfm context.
+	 * Copy this function code into the gr0 field of the kmac context.
+	 */
+	if (!tfm_ctx->fc) {
+		rc = -ENOKEY;
+		goto out;
+	}
+	kmac_ctx->gr0.fc = tfm_ctx->fc;
+
+	/*
+	 * Copy the pk from tfm ctx into kmac ctx. The protected key
+	 * may be outdated but update() and final() will handle this.
+	 */
+	spin_lock_bh(&tfm_ctx->pk_lock);
+	memcpy(kmac_ctx->param + SHA2_KEY_OFFSET(bs),
+	       tfm_ctx->pk.protkey, tfm_ctx->pk.len);
+	spin_unlock_bh(&tfm_ctx->pk_lock);
+
+out:
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+static int phmac_update(struct ahash_request *req)
+{
+	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
+	struct hash_walk_helper *hwh = &req_ctx->hwh;
+	int rc;
+
+	/* prep the walk in the request context */
+	rc = hwh_prepare(req, hwh);
+	if (rc)
+		goto out;
+
+	/* Try synchronous operation if no active engine usage */
+	if (!atomic_read(&tfm_ctx->via_engine_ctr)) {
+		rc = phmac_kmac_update(req, false);
+		if (rc == 0)
+			goto out;
+	}
+
+	/*
+	 * If sync operation failed or key expired or there are already
+	 * requests enqueued via engine, fallback to async. Mark tfm as
+	 * using engine to serialize requests.
+	 */
+	if (rc == 0 || rc == -EKEYEXPIRED) {
+		atomic_inc(&tfm_ctx->via_engine_ctr);
+		rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
+		if (rc != -EINPROGRESS)
+			atomic_dec(&tfm_ctx->via_engine_ctr);
+	}
+
+	if (rc != -EINPROGRESS) {
+		hwh_advance(hwh, rc);
+		memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
+	}
+
+out:
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+static int phmac_final(struct ahash_request *req)
+{
+	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
+	int rc = 0;
+
+	/* Try synchronous operation if no active engine usage */
+	if (!atomic_read(&tfm_ctx->via_engine_ctr)) {
+		rc = phmac_kmac_final(req, false);
+		if (rc == 0)
+			goto out;
+	}
+
+	/*
+	 * If sync operation failed or key expired or there are already
+	 * requests enqueued via engine, fallback to async. Mark tfm as
+	 * using engine to serialize requests.
+	 */
+	if (rc == 0 || rc == -EKEYEXPIRED) {
+		req->nbytes = 0;
+		req_ctx->final = true;
+		atomic_inc(&tfm_ctx->via_engine_ctr);
+		rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
+		if (rc != -EINPROGRESS)
+			atomic_dec(&tfm_ctx->via_engine_ctr);
+	}
+
+out:
+	if (rc != -EINPROGRESS)
+		memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+static int phmac_finup(struct ahash_request *req)
+{
+	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
+	struct hash_walk_helper *hwh = &req_ctx->hwh;
+	int rc;
+
+	/* prep the walk in the request context */
+	rc = hwh_prepare(req, hwh);
+	if (rc)
+		goto out;
+
+	/* Try synchronous operations if no active engine usage */
+	if (!atomic_read(&tfm_ctx->via_engine_ctr)) {
+		rc = phmac_kmac_update(req, false);
+		if (rc == 0)
+			req->nbytes = 0;
+	}
+	if (!rc && !req->nbytes && !atomic_read(&tfm_ctx->via_engine_ctr)) {
+		rc = phmac_kmac_final(req, false);
+		if (rc == 0)
+			goto out;
+	}
+
+	/*
+	 * If sync operation failed or key expired or there are already
+	 * requests enqueued via engine, fallback to async. Mark tfm as
+	 * using engine to serialize requests.
+	 */
+	if (rc == 0 || rc == -EKEYEXPIRED) {
+		req_ctx->final = true;
+		atomic_inc(&tfm_ctx->via_engine_ctr);
+		rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
+		if (rc != -EINPROGRESS)
+			atomic_dec(&tfm_ctx->via_engine_ctr);
+	}
+
+	if (rc != -EINPROGRESS)
+		hwh_advance(hwh, rc);
+
+out:
+	if (rc != -EINPROGRESS)
+		memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+static int phmac_digest(struct ahash_request *req)
+{
+	int rc;
+
+	rc = phmac_init(req);
+	if (rc)
+		goto out;
+
+	rc = phmac_finup(req);
+
+out:
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+static int phmac_setkey(struct crypto_ahash *tfm,
+			const u8 *key, unsigned int keylen)
+{
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+	unsigned int ds = crypto_ahash_digestsize(tfm);
+	int rc = 0;
+
+	/* copy raw key into tfm context */
+	rc = phmac_tfm_ctx_setkey(tfm_ctx, key, keylen);
+	if (rc)
+		goto out;
+
+	/* convert raw key into protected key */
+	rc = phmac_convert_key(tfm_ctx);
+	if (rc)
+		goto out;
+
+	/* set function code in tfm context, check for valid pk type */
+	switch (ds) {
+	case SHA224_DIGEST_SIZE:
+		if (tfm_ctx->pk.type != PKEY_KEYTYPE_HMAC_512)
+			rc = -EINVAL;
+		else
+			tfm_ctx->fc = CPACF_KMAC_PHMAC_SHA_224;
+		break;
+	case SHA256_DIGEST_SIZE:
+		if (tfm_ctx->pk.type != PKEY_KEYTYPE_HMAC_512)
+			rc = -EINVAL;
+		else
+			tfm_ctx->fc = CPACF_KMAC_PHMAC_SHA_256;
+		break;
+	case SHA384_DIGEST_SIZE:
+		if (tfm_ctx->pk.type != PKEY_KEYTYPE_HMAC_1024)
+			rc = -EINVAL;
+		else
+			tfm_ctx->fc = CPACF_KMAC_PHMAC_SHA_384;
+		break;
+	case SHA512_DIGEST_SIZE:
+		if (tfm_ctx->pk.type != PKEY_KEYTYPE_HMAC_1024)
+			rc = -EINVAL;
+		else
+			tfm_ctx->fc = CPACF_KMAC_PHMAC_SHA_512;
+		break;
+	default:
+		tfm_ctx->fc = 0;
+		rc = -EINVAL;
+	}
+
+out:
+	pr_debug("rc=%d\n", rc);
+	return rc;
+}
+
+static int phmac_export(struct ahash_request *req, void *out)
+{
+	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
+	struct kmac_sha2_ctx *ctx = &req_ctx->kmac_ctx;
+
+	memcpy(out, ctx, sizeof(*ctx));
+
+	return 0;
+}
+
+static int phmac_import(struct ahash_request *req, const void *in)
+{
+	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
+	struct kmac_sha2_ctx *ctx = &req_ctx->kmac_ctx;
+
+	memset(req_ctx, 0, sizeof(*req_ctx));
+	memcpy(ctx, in, sizeof(*ctx));
+
+	return 0;
+}
+
+static int phmac_init_tfm(struct crypto_ahash *tfm)
+{
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+
+	memset(tfm_ctx, 0, sizeof(*tfm_ctx));
+	spin_lock_init(&tfm_ctx->pk_lock);
+
+	crypto_ahash_set_reqsize(tfm, sizeof(struct phmac_req_ctx));
+
+	return 0;
+}
+
+static void phmac_exit_tfm(struct crypto_ahash *tfm)
+{
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+
+	memzero_explicit(tfm_ctx->keybuf, sizeof(tfm_ctx->keybuf));
+	memzero_explicit(&tfm_ctx->pk, sizeof(tfm_ctx->pk));
+}
+
+static int phmac_do_one_request(struct crypto_engine *engine, void *areq)
+{
+	struct ahash_request *req = ahash_request_cast(areq);
+	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
+	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+	struct phmac_req_ctx *req_ctx = ahash_request_ctx(req);
+	struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
+	struct hash_walk_helper *hwh = &req_ctx->hwh;
+	int rc = -EINVAL;
+
+	/*
+	 * Three kinds of requests come in here:
+	 * update when req->nbytes > 0 and req_ctx->final is false
+	 * final when req->nbytes = 0 and req_ctx->final is true
+	 * finup when req->nbytes > 0 and req_ctx->final is true
+	 * For update and finup the hwh walk needs to be prepared and
+	 * up to date but the actual nr of bytes in req->nbytes may be
+	 * any non zero number. For final there is no hwh walk needed.
+	 */
+
+	if (req->nbytes) {
+		rc = phmac_kmac_update(req, true);
+		if (rc == -EKEYEXPIRED) {
+			/*
+			 * Protected key expired, conversion is in process.
+			 * Trigger a re-schedule of this request by returning
+			 * -ENOSPC ("hardware queue full") to the crypto engine.
+			 * To avoid immediately re-invocation of this callback,
+			 * tell scheduler to voluntarily give up the CPU here.
+			 */
+			pr_debug("rescheduling request\n");
+			cond_resched();
+			return -ENOSPC;
+		} else if (rc) {
+			hwh_advance(hwh, rc);
+			goto out;
+		}
+		req->nbytes = 0;
+	}
+
+	if (req_ctx->final) {
+		rc = phmac_kmac_final(req, true);
+		if (rc == -EKEYEXPIRED) {
+			/*
+			 * Protected key expired, conversion is in process.
+			 * Trigger a re-schedule of this request by returning
+			 * -ENOSPC ("hardware queue full") to the crypto engine.
+			 * To avoid immediately re-invocation of this callback,
+			 * tell scheduler to voluntarily give up the CPU here.
+			 */
+			pr_debug("rescheduling request\n");
+			cond_resched();
+			return -ENOSPC;
+		}
+	}
+
+out:
+	if (rc || req_ctx->final)
+		memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
+	pr_debug("request complete with rc=%d\n", rc);
+	local_bh_disable();
+	atomic_dec(&tfm_ctx->via_engine_ctr);
+	crypto_finalize_hash_request(engine, req, rc);
+	local_bh_enable();
+	return rc;
+}
+
+#define S390_ASYNC_PHMAC_ALG(x)						\
+{									\
+	.base = {							\
+		.init	  = phmac_init,					\
+		.update	  = phmac_update,				\
+		.final	  = phmac_final,				\
+		.finup	  = phmac_finup,				\
+		.digest	  = phmac_digest,				\
+		.setkey	  = phmac_setkey,				\
+		.import	  = phmac_import,				\
+		.export	  = phmac_export,				\
+		.init_tfm = phmac_init_tfm,				\
+		.exit_tfm = phmac_exit_tfm,				\
+		.halg = {						\
+			.digestsize = SHA##x##_DIGEST_SIZE,		\
+			.statesize  = sizeof(struct kmac_sha2_ctx),	\
+			.base = {					\
+				.cra_name = "phmac(sha" #x ")",		\
+				.cra_driver_name = "phmac_s390_sha" #x,	\
+				.cra_blocksize = SHA##x##_BLOCK_SIZE,	\
+				.cra_priority = 400,			\
+				.cra_flags = CRYPTO_ALG_ASYNC |		\
+					     CRYPTO_ALG_NO_FALLBACK,	\
+				.cra_ctxsize = sizeof(struct phmac_tfm_ctx), \
+				.cra_module = THIS_MODULE,		\
+			},						\
+		},							\
+	},								\
+	.op = {								\
+		.do_one_request = phmac_do_one_request,			\
+	},								\
+}
+
+static struct phmac_alg {
+	unsigned int fc;
+	struct ahash_engine_alg alg;
+	bool registered;
+} phmac_algs[] = {
+	{
+		.fc = CPACF_KMAC_PHMAC_SHA_224,
+		.alg = S390_ASYNC_PHMAC_ALG(224),
+	}, {
+		.fc = CPACF_KMAC_PHMAC_SHA_256,
+		.alg = S390_ASYNC_PHMAC_ALG(256),
+	}, {
+		.fc = CPACF_KMAC_PHMAC_SHA_384,
+		.alg = S390_ASYNC_PHMAC_ALG(384),
+	}, {
+		.fc = CPACF_KMAC_PHMAC_SHA_512,
+		.alg = S390_ASYNC_PHMAC_ALG(512),
+	}
+};
+
+static struct miscdevice phmac_dev = {
+	.name	= "phmac",
+	.minor	= MISC_DYNAMIC_MINOR,
+};
+
+static void s390_phmac_exit(void)
+{
+	struct phmac_alg *phmac;
+	int i;
+
+	if (phmac_crypto_engine) {
+		crypto_engine_stop(phmac_crypto_engine);
+		crypto_engine_exit(phmac_crypto_engine);
+	}
+
+	for (i = ARRAY_SIZE(phmac_algs) - 1; i >= 0; i--) {
+		phmac = &phmac_algs[i];
+		if (phmac->registered)
+			crypto_engine_unregister_ahash(&phmac->alg);
+	}
+
+	misc_deregister(&phmac_dev);
+}
+
+static int __init s390_phmac_init(void)
+{
+	struct phmac_alg *phmac;
+	int i, rc;
+
+	/* register a simple phmac pseudo misc device */
+	rc = misc_register(&phmac_dev);
+	if (rc)
+		return rc;
+
+	/* with this pseudo device alloc and start a crypto engine */
+	phmac_crypto_engine =
+		crypto_engine_alloc_init_and_set(phmac_dev.this_device,
+						 true, NULL, false, MAX_QLEN);
+	if (!phmac_crypto_engine) {
+		rc = -ENOMEM;
+		goto out_err;
+	}
+	rc = crypto_engine_start(phmac_crypto_engine);
+	if (rc) {
+		crypto_engine_exit(phmac_crypto_engine);
+		phmac_crypto_engine = NULL;
+		goto out_err;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(phmac_algs); i++) {
+		phmac = &phmac_algs[i];
+		if (!cpacf_query_func(CPACF_KMAC, phmac->fc))
+			continue;
+		rc = crypto_engine_register_ahash(&phmac->alg);
+		if (rc)
+			goto out_err;
+		phmac->registered = true;
+		pr_debug("%s registered\n", phmac->alg.base.halg.base.cra_name);
+	}
+
+	return 0;
+
+out_err:
+	s390_phmac_exit();
+	return rc;
+}
+
+module_init(s390_phmac_init);
+module_exit(s390_phmac_exit);
+
+MODULE_ALIAS_CRYPTO("phmac(sha224)");
+MODULE_ALIAS_CRYPTO("phmac(sha256)");
+MODULE_ALIAS_CRYPTO("phmac(sha384)");
+MODULE_ALIAS_CRYPTO("phmac(sha512)");
+
+MODULE_DESCRIPTION("S390 HMAC driver for protected keys");
+MODULE_LICENSE("GPL");
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 9f8a3a5bed7e..04b4c43b6bae 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -188,6 +188,19 @@ config CRYPTO_PAES_S390
 	  Select this option if you want to use the paes cipher
 	  for example to use protected key encrypted devices.
 
+config CRYPTO_PHMAC_S390
+	tristate "PHMAC cipher algorithms"
+	depends on S390
+	depends on PKEY
+	select CRYPTO_HASH
+	select CRYPTO_ENGINE
+	help
+	  This is the s390 hardware accelerated implementation of the
+	  protected key HMAC support for SHA224, SHA256, SHA384 and SHA512.
+
+	  Select this option if you want to use the phmac digests
+	  for example to use dm-integrity with secure/protected keys.
+
 config S390_PRNG
 	tristate "Pseudo random number generator device driver"
 	depends on S390
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v12 4/6] crypto: api - Add crypto_ahash_tested() helper function
  2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
                   ` (2 preceding siblings ...)
  2025-06-17 13:44 ` [PATCH v12 3/6] s390/crypto: New s390 specific protected key hash phmac Harald Freudenberger
@ 2025-06-17 13:44 ` Harald Freudenberger
  2025-06-18  9:23   ` Holger Dengler
  2025-06-17 13:44 ` [PATCH v12 5/6] s390/crypto: Add selftest support for phmac Harald Freudenberger
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Harald Freudenberger @ 2025-06-17 13:44 UTC (permalink / raw)
  To: herbert
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

Add a little inline helper function
    crypto_ahash_tested()
to the internal/hash.h header file to retrieve the tested
status (that is the CRYPTO_ALG_TESTED bit in the cra_flags).

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Suggested-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 include/crypto/internal/hash.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index ef573545c85d..8126254c9255 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -190,6 +190,13 @@ static inline void crypto_ahash_set_reqsize(struct crypto_ahash *tfm,
 	tfm->reqsize = reqsize;
 }
 
+static inline bool crypto_ahash_tested(struct crypto_ahash *tfm)
+{
+	struct crypto_tfm *tfm_base = crypto_ahash_tfm(tfm);
+
+	return tfm_base->__crt_alg->cra_flags & CRYPTO_ALG_TESTED;
+}
+
 static inline void crypto_ahash_set_reqsize_dma(struct crypto_ahash *ahash,
 						unsigned int reqsize)
 {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v12 5/6] s390/crypto: Add selftest support for phmac
  2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
                   ` (3 preceding siblings ...)
  2025-06-17 13:44 ` [PATCH v12 4/6] crypto: api - Add crypto_ahash_tested() helper function Harald Freudenberger
@ 2025-06-17 13:44 ` Harald Freudenberger
  2025-06-17 13:44 ` [PATCH v12 6/6] crypto: testmgr - Enable phmac selftest Harald Freudenberger
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Harald Freudenberger @ 2025-06-17 13:44 UTC (permalink / raw)
  To: herbert
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

Add key preparation code in case of selftest running to the phmac
setkey function:

As long as crypto_ahash_tested() returns with false, all setkey()
invocations are assumed to carry sheer hmac clear key values and thus
need some preparation to work with the phmac implementation. Thus it
is possible to use the already available hmac test vectors implemented
in the testmanager to test the phmac code.

When crypto_ahash_tested() returns true (that is after larval state)
the phmac code assumes the key material is a blob digestible by the
pkey kernel module which converts the blob into a working key for the
phmac code.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
---
 arch/s390/crypto/phmac_s390.c | 137 ++++++++++++++++++++++++++++++++++
 1 file changed, 137 insertions(+)

diff --git a/arch/s390/crypto/phmac_s390.c b/arch/s390/crypto/phmac_s390.c
index 8473af47f5b9..90602f72108f 100644
--- a/arch/s390/crypto/phmac_s390.c
+++ b/arch/s390/crypto/phmac_s390.c
@@ -176,6 +176,114 @@ struct phmac_req_ctx {
 	bool final;
 };
 
+/*
+ * Pkey 'token' struct used to derive a protected key value from a clear key.
+ */
+struct hmac_clrkey_token {
+	u8  type;
+	u8  res0[3];
+	u8  version;
+	u8  res1[3];
+	u32 keytype;
+	u32 len;
+	u8 key[];
+} __packed;
+
+static int hash_key(const u8 *in, unsigned int inlen,
+		    u8 *digest, unsigned int digestsize)
+{
+	unsigned long func;
+	union {
+		struct sha256_paramblock {
+			u32 h[8];
+			u64 mbl;
+		} sha256;
+		struct sha512_paramblock {
+			u64 h[8];
+			u128 mbl;
+		} sha512;
+	} __packed param;
+
+#define PARAM_INIT(x, y, z)		   \
+	param.sha##x.h[0] = SHA##y ## _H0; \
+	param.sha##x.h[1] = SHA##y ## _H1; \
+	param.sha##x.h[2] = SHA##y ## _H2; \
+	param.sha##x.h[3] = SHA##y ## _H3; \
+	param.sha##x.h[4] = SHA##y ## _H4; \
+	param.sha##x.h[5] = SHA##y ## _H5; \
+	param.sha##x.h[6] = SHA##y ## _H6; \
+	param.sha##x.h[7] = SHA##y ## _H7; \
+	param.sha##x.mbl = (z)
+
+	switch (digestsize) {
+	case SHA224_DIGEST_SIZE:
+		func = CPACF_KLMD_SHA_256;
+		PARAM_INIT(256, 224, inlen * 8);
+		break;
+	case SHA256_DIGEST_SIZE:
+		func = CPACF_KLMD_SHA_256;
+		PARAM_INIT(256, 256, inlen * 8);
+		break;
+	case SHA384_DIGEST_SIZE:
+		func = CPACF_KLMD_SHA_512;
+		PARAM_INIT(512, 384, inlen * 8);
+		break;
+	case SHA512_DIGEST_SIZE:
+		func = CPACF_KLMD_SHA_512;
+		PARAM_INIT(512, 512, inlen * 8);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+#undef PARAM_INIT
+
+	cpacf_klmd(func, &param, in, inlen);
+
+	memcpy(digest, &param, digestsize);
+
+	return 0;
+}
+
+/*
+ * make_clrkey_token() - wrap the clear key into a pkey clearkey token.
+ */
+static inline int make_clrkey_token(const u8 *clrkey, size_t clrkeylen,
+				    unsigned int digestsize, u8 *dest)
+{
+	struct hmac_clrkey_token *token = (struct hmac_clrkey_token *)dest;
+	unsigned int blocksize;
+	int rc;
+
+	token->type = 0x00;
+	token->version = 0x02;
+	switch (digestsize) {
+	case SHA224_DIGEST_SIZE:
+	case SHA256_DIGEST_SIZE:
+		token->keytype = PKEY_KEYTYPE_HMAC_512;
+		blocksize = 64;
+		break;
+	case SHA384_DIGEST_SIZE:
+	case SHA512_DIGEST_SIZE:
+		token->keytype = PKEY_KEYTYPE_HMAC_1024;
+		blocksize = 128;
+		break;
+	default:
+		return -EINVAL;
+	}
+	token->len = blocksize;
+
+	if (clrkeylen > blocksize) {
+		rc = hash_key(clrkey, clrkeylen, token->key, digestsize);
+		if (rc)
+			return rc;
+	} else {
+		memcpy(token->key, clrkey, clrkeylen);
+	}
+
+	return 0;
+}
+
 /*
  * phmac_tfm_ctx_setkey() - Set key value into tfm context, maybe construct
  * a clear key token digestible by pkey from a clear key value.
@@ -623,8 +731,30 @@ static int phmac_setkey(struct crypto_ahash *tfm,
 {
 	struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
 	unsigned int ds = crypto_ahash_digestsize(tfm);
+	unsigned int bs = crypto_ahash_blocksize(tfm);
+	unsigned int tmpkeylen;
+	u8 *tmpkey = NULL;
 	int rc = 0;
 
+	if (!crypto_ahash_tested(tfm)) {
+		/*
+		 * selftest running: key is a raw hmac clear key and needs
+		 * to get embedded into a 'clear key token' in order to have
+		 * it correctly processed by the pkey module.
+		 */
+		tmpkeylen = sizeof(struct hmac_clrkey_token) + bs;
+		tmpkey = kzalloc(tmpkeylen, GFP_KERNEL);
+		if (!tmpkey) {
+			rc = -ENOMEM;
+			goto out;
+		}
+		rc = make_clrkey_token(key, keylen, ds, tmpkey);
+		if (rc)
+			goto out;
+		keylen = tmpkeylen;
+		key = tmpkey;
+	}
+
 	/* copy raw key into tfm context */
 	rc = phmac_tfm_ctx_setkey(tfm_ctx, key, keylen);
 	if (rc)
@@ -667,6 +797,7 @@ static int phmac_setkey(struct crypto_ahash *tfm,
 	}
 
 out:
+	kfree(tmpkey);
 	pr_debug("rc=%d\n", rc);
 	return rc;
 }
@@ -861,6 +992,12 @@ static int __init s390_phmac_init(void)
 	struct phmac_alg *phmac;
 	int i, rc;
 
+	/* for selftest cpacf klmd subfunction is needed */
+	if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_256))
+		return -ENODEV;
+	if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_512))
+		return -ENODEV;
+
 	/* register a simple phmac pseudo misc device */
 	rc = misc_register(&phmac_dev);
 	if (rc)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v12 6/6] crypto: testmgr - Enable phmac selftest
  2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
                   ` (4 preceding siblings ...)
  2025-06-17 13:44 ` [PATCH v12 5/6] s390/crypto: Add selftest support for phmac Harald Freudenberger
@ 2025-06-17 13:44 ` Harald Freudenberger
  2025-06-18  8:58 ` [PATCH v12 0/6] New s390 specific protected key hmac Herbert Xu
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Harald Freudenberger @ 2025-06-17 13:44 UTC (permalink / raw)
  To: herbert
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

Add phmac selftest invocation to the crypto testmanager.

Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Acked-by: Holger Dengler <dengler@linux.ibm.com>
---
 crypto/testmgr.c | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index a4ad939e03c9..b42112a208ff 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5306,6 +5306,36 @@ static const struct alg_test_desc alg_test_descs[] = {
 			.cipher = __VECS(fcrypt_pcbc_tv_template)
 		}
 	}, {
+#if IS_ENABLED(CONFIG_CRYPTO_PHMAC_S390)
+		.alg = "phmac(sha224)",
+		.test = alg_test_hash,
+		.fips_allowed = 1,
+		.suite = {
+			.hash = __VECS(hmac_sha224_tv_template)
+		}
+	}, {
+		.alg = "phmac(sha256)",
+		.test = alg_test_hash,
+		.fips_allowed = 1,
+		.suite = {
+			.hash = __VECS(hmac_sha256_tv_template)
+		}
+	}, {
+		.alg = "phmac(sha384)",
+		.test = alg_test_hash,
+		.fips_allowed = 1,
+		.suite = {
+			.hash = __VECS(hmac_sha384_tv_template)
+		}
+	}, {
+		.alg = "phmac(sha512)",
+		.test = alg_test_hash,
+		.fips_allowed = 1,
+		.suite = {
+			.hash = __VECS(hmac_sha512_tv_template)
+		}
+	}, {
+#endif
 		.alg = "pkcs1(rsa,none)",
 		.test = alg_test_sig,
 		.suite = {
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v12 0/6] New s390 specific protected key hmac
  2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
                   ` (5 preceding siblings ...)
  2025-06-17 13:44 ` [PATCH v12 6/6] crypto: testmgr - Enable phmac selftest Harald Freudenberger
@ 2025-06-18  8:58 ` Herbert Xu
  2025-06-24 11:34 ` Harald Freudenberger
  2025-06-26 10:54 ` Herbert Xu
  8 siblings, 0 replies; 15+ messages in thread
From: Herbert Xu @ 2025-06-18  8:58 UTC (permalink / raw)
  To: Harald Freudenberger
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

On Tue, Jun 17, 2025 at 03:44:34PM +0200, Harald Freudenberger wrote:
> Add support for protected key hmac ("phmac") for s390 arch.
> 
> With the latest machine generation there is now support for
> protected key (that is a key wrapped by a master key stored
> in firmware) hmac for sha2 (sha224, sha256, sha384 and sha512)
> for the s390 specific CPACF instruction kmac.
> 
> This patch adds support via 4 new hashes registered as
> phmac(sha224), phmac(sha256), phmac(sha384) and phmac(sha512).
> 
> Changelog:
> v1: Initial version
> v2: Increase HASH_MAX_DESCSIZE generic (not just for arch s390).
>     Fix one finding to use kmemdup instead of kmalloc/memcpy from test
>     robot. Remove unneeded cpacf subfunctions checks. Simplify
>     clone_tfm() function. Rebased to s390/features.
> v3: Feedback from Herbert: Use GFP_ATOMIC in setkey function.
>     Feedback from Holger: rework tfm clone function, move convert key
>     invocation from setkey to init function. Rebased to updated
>     s390/features from 11/7/2024. Ready for integration if there are
>     no complains on v3.
> v4: Rewind back more or less to v2. Add code to check for non-sleeping
>     context. Non-sleeping context during attempt to derive the
>     protected key from raw key material is not accepted and
>     -EOPNOTSUPP is returned (also currently all derivation pathes
>     would in fact never sleep). In general the phmac implementation is
>     not to be used within non-sleeping context and the code header
>     mentions this. Tested with (patched) dm-integrity - works fine.
> v5: As suggested by Herbert now the shashes have been marked as
>     'internal' and wrapped by ahashes which use the cryptd if an
>     atomic context is detected. So the visible phmac algorithms are
>     now ahashes. Unfortunately the dm-integrity implementation
>     currently requests and deals only with shashes and this phmac
>     implementation is not fitting to the original goal any more...
> v6: As suggested by Herbert now a pure async phmac implementation.
>     Tested via AF_ALG interface. Untested via dm-integrity as this layer
>     only supports shashes. Maybe I'll develop a patch to switch the
>     dm-integrity to ahash as it is anyway the more flexible interface.
> v7: Total rework of the implementation. Now uses workqueues and triggers
>     asynch requests for key convert, init, update, final and digest.
>     Tested with instrumented code and with a reworked version of
>     dm-integrity which uses asynchronous hashes. A patch for dm-integrity
>     is on the way but yet needs some last hone work.
> v8: Added selftest. With the selftest comes some code which wraps the
>     clear key into a "clear key token" digestible by PKEY. The
>     selftest also uses import() and export(), so these are now also
>     implemented. Furthermore a finup() implementation is now also
>     available. Tested with AF_ALG testcases and dm-integrity, also
>     tested with some instrumented code to check that the asynch
>     workqueue functions do their job correctly. Coding is complete!
> v9: As suggested by Herbert use ahash_request_complete() and surround it
>     with local_bh_disable().
> v10: Split the pkey selftest patch into 3 patches. Slight rework of the
>      setkey function as suggested by Holger: When selftest is running
>      as much as possible of the production code should run. So now the
>      key prep with selftest is one additional if/then block instead of
>      an if/then/else construct.
>      Code is ready for integration and well tested.
> v11: Utterly rework with the insights collected with the paes rework
>      and the basic work done with the pkey rework over the last 5 month.
>      Note that patch #1 effectively reverts commit 7fa481734016
>      ("crypto: ahash - make hash walk functions private to ahash.c")
>      from Eric Biggers.
> v12: Fixed some typos, adaptions to 128 bit total counter,
>      misc_register() invocation was missing in the patches series,
>      added Herbert's proposal for a new function crypto_ahash_tested().
> 
> Harald Freudenberger (5):
>   crypto: ahash - make hash walk functions from ahash.c  public
>   s390/crypto: New s390 specific protected key hash phmac
>   crypto: api - Add crypto_ahash_tested() helper function
>   s390/crypto: Add selftest support for phmac
>   crypto: testmgr - Enable phmac selftest
> 
> Holger Dengler (1):
>   s390/crypto: Add protected key hmac subfunctions for KMAC
> 
>  arch/s390/configs/debug_defconfig |    1 +
>  arch/s390/configs/defconfig       |    1 +
>  arch/s390/crypto/Makefile         |    1 +
>  arch/s390/crypto/phmac_s390.c     | 1048 +++++++++++++++++++++++++++++
>  arch/s390/include/asm/cpacf.h     |    4 +
>  crypto/ahash.c                    |   26 +-
>  crypto/testmgr.c                  |   30 +
>  drivers/crypto/Kconfig            |   13 +
>  include/crypto/internal/hash.h    |   30 +
>  9 files changed, 1133 insertions(+), 21 deletions(-)
>  create mode 100644 arch/s390/crypto/phmac_s390.c
> 
> 
> base-commit: 1029436218e50168812dbc44b16bca6d35721b0b
> --
> 2.43.0

Acked-by: Herbert Xu <herbert@gondor.apana.org.au>

Thanks,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v12 3/6] s390/crypto: New s390 specific protected key hash phmac
  2025-06-17 13:44 ` [PATCH v12 3/6] s390/crypto: New s390 specific protected key hash phmac Harald Freudenberger
@ 2025-06-18  9:21   ` Holger Dengler
  2025-06-18  9:29   ` Heiko Carstens
  1 sibling, 0 replies; 15+ messages in thread
From: Holger Dengler @ 2025-06-18  9:21 UTC (permalink / raw)
  To: Harald Freudenberger, herbert
  Cc: linux-crypto, linux-s390, ifranzki, fcallies, hca, gor, agordeev

On 17/06/2025 15:44, Harald Freudenberger wrote:
> Add support for protected key hmac ("phmac") for s390 arch.
> 
> With the latest machine generation there is now support for
> protected key (that is a key wrapped by a master key stored
> in firmware) hmac for sha2 (sha224, sha256, sha384 and sha512)
> for the s390 specific CPACF instruction kmac.
> 
> This patch adds support via 4 new ahashes registered as
> phmac(sha224), phmac(sha256), phmac(sha384) and phmac(sha512).
> 
> Co-developed-by: Holger Dengler <dengler@linux.ibm.com>

According to `Documentation/process/maintainer-tip.rst` (line 313 ff.), please add my
Signed-off-by: Holger Dengler <dengler@linux.ibm.com>

> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
> Reviewed-by: Holger Dengler <dengler@linux.ibm.com>

-- 
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v12 4/6] crypto: api - Add crypto_ahash_tested() helper function
  2025-06-17 13:44 ` [PATCH v12 4/6] crypto: api - Add crypto_ahash_tested() helper function Harald Freudenberger
@ 2025-06-18  9:23   ` Holger Dengler
  0 siblings, 0 replies; 15+ messages in thread
From: Holger Dengler @ 2025-06-18  9:23 UTC (permalink / raw)
  To: Harald Freudenberger, herbert
  Cc: linux-crypto, linux-s390, ifranzki, fcallies, hca, gor, agordeev

On 17/06/2025 15:44, Harald Freudenberger wrote:
> Add a little inline helper function
>     crypto_ahash_tested()
> to the internal/hash.h header file to retrieve the tested
> status (that is the CRYPTO_ALG_TESTED bit in the cra_flags).
> 
> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
> Suggested-by: Herbert Xu <herbert@gondor.apana.org.au>

Please change the ordering. Suggested-by: first, Signed-off-by: second.

Reviewed-by: Holger Dengler <dengler@linux.ibm.com>

-- 
Mit freundlichen Grüßen / Kind regards
Holger Dengler
--
IBM Systems, Linux on IBM Z Development
dengler@linux.ibm.com


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v12 3/6] s390/crypto: New s390 specific protected key hash phmac
  2025-06-17 13:44 ` [PATCH v12 3/6] s390/crypto: New s390 specific protected key hash phmac Harald Freudenberger
  2025-06-18  9:21   ` Holger Dengler
@ 2025-06-18  9:29   ` Heiko Carstens
  1 sibling, 0 replies; 15+ messages in thread
From: Heiko Carstens @ 2025-06-18  9:29 UTC (permalink / raw)
  To: Harald Freudenberger
  Cc: herbert, linux-crypto, linux-s390, dengler, ifranzki, fcallies,
	gor, agordeev

On Tue, Jun 17, 2025 at 03:44:37PM +0200, Harald Freudenberger wrote:
> Add support for protected key hmac ("phmac") for s390 arch.
> 
> With the latest machine generation there is now support for
> protected key (that is a key wrapped by a master key stored
> in firmware) hmac for sha2 (sha224, sha256, sha384 and sha512)
> for the s390 specific CPACF instruction kmac.
> 
> This patch adds support via 4 new ahashes registered as
> phmac(sha224), phmac(sha256), phmac(sha384) and phmac(sha512).
> 
> Co-developed-by: Holger Dengler <dengler@linux.ibm.com>
> Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
> Reviewed-by: Holger Dengler <dengler@linux.ibm.com>
> ---

Co-developed-by must come together with a Signed-off-by tag.
See Documentation/process/submitting-patches.rst.

Holger, can you provide your Sign-off, please?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v12 0/6] New s390 specific protected key hmac
  2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
                   ` (6 preceding siblings ...)
  2025-06-18  8:58 ` [PATCH v12 0/6] New s390 specific protected key hmac Herbert Xu
@ 2025-06-24 11:34 ` Harald Freudenberger
  2025-06-24 11:37   ` Herbert Xu
  2025-06-26 10:54 ` Herbert Xu
  8 siblings, 1 reply; 15+ messages in thread
From: Harald Freudenberger @ 2025-06-24 11:34 UTC (permalink / raw)
  To: herbert
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

On 2025-06-17 15:44, Harald Freudenberger wrote:
> Add support for protected key hmac ("phmac") for s390 arch.
> 
> With the latest machine generation there is now support for
> protected key (that is a key wrapped by a master key stored
> in firmware) hmac for sha2 (sha224, sha256, sha384 and sha512)
> for the s390 specific CPACF instruction kmac.
> 
> This patch adds support via 4 new hashes registered as
> phmac(sha224), phmac(sha256), phmac(sha384) and phmac(sha512).
> 
> Changelog:
> v1: Initial version
> v2: Increase HASH_MAX_DESCSIZE generic (not just for arch s390).
>     Fix one finding to use kmemdup instead of kmalloc/memcpy from test
>     robot. Remove unneeded cpacf subfunctions checks. Simplify
>     clone_tfm() function. Rebased to s390/features.
> v3: Feedback from Herbert: Use GFP_ATOMIC in setkey function.
>     Feedback from Holger: rework tfm clone function, move convert key
>     invocation from setkey to init function. Rebased to updated
>     s390/features from 11/7/2024. Ready for integration if there are
>     no complains on v3.
> v4: Rewind back more or less to v2. Add code to check for non-sleeping
>     context. Non-sleeping context during attempt to derive the
>     protected key from raw key material is not accepted and
>     -EOPNOTSUPP is returned (also currently all derivation pathes
>     would in fact never sleep). In general the phmac implementation is
>     not to be used within non-sleeping context and the code header
>     mentions this. Tested with (patched) dm-integrity - works fine.
> v5: As suggested by Herbert now the shashes have been marked as
>     'internal' and wrapped by ahashes which use the cryptd if an
>     atomic context is detected. So the visible phmac algorithms are
>     now ahashes. Unfortunately the dm-integrity implementation
>     currently requests and deals only with shashes and this phmac
>     implementation is not fitting to the original goal any more...
> v6: As suggested by Herbert now a pure async phmac implementation.
>     Tested via AF_ALG interface. Untested via dm-integrity as this 
> layer
>     only supports shashes. Maybe I'll develop a patch to switch the
>     dm-integrity to ahash as it is anyway the more flexible interface.
> v7: Total rework of the implementation. Now uses workqueues and 
> triggers
>     asynch requests for key convert, init, update, final and digest.
>     Tested with instrumented code and with a reworked version of
>     dm-integrity which uses asynchronous hashes. A patch for 
> dm-integrity
>     is on the way but yet needs some last hone work.
> v8: Added selftest. With the selftest comes some code which wraps the
>     clear key into a "clear key token" digestible by PKEY. The
>     selftest also uses import() and export(), so these are now also
>     implemented. Furthermore a finup() implementation is now also
>     available. Tested with AF_ALG testcases and dm-integrity, also
>     tested with some instrumented code to check that the asynch
>     workqueue functions do their job correctly. Coding is complete!
> v9: As suggested by Herbert use ahash_request_complete() and surround 
> it
>     with local_bh_disable().
> v10: Split the pkey selftest patch into 3 patches. Slight rework of the
>      setkey function as suggested by Holger: When selftest is running
>      as much as possible of the production code should run. So now the
>      key prep with selftest is one additional if/then block instead of
>      an if/then/else construct.
>      Code is ready for integration and well tested.
> v11: Utterly rework with the insights collected with the paes rework
>      and the basic work done with the pkey rework over the last 5 
> month.
>      Note that patch #1 effectively reverts commit 7fa481734016
>      ("crypto: ahash - make hash walk functions private to ahash.c")
>      from Eric Biggers.
> v12: Fixed some typos, adaptions to 128 bit total counter,
>      misc_register() invocation was missing in the patches series,
>      added Herbert's proposal for a new function crypto_ahash_tested().
> 
> Harald Freudenberger (5):
>   crypto: ahash - make hash walk functions from ahash.c  public
>   s390/crypto: New s390 specific protected key hash phmac
>   crypto: api - Add crypto_ahash_tested() helper function
>   s390/crypto: Add selftest support for phmac
>   crypto: testmgr - Enable phmac selftest
> 
> Holger Dengler (1):
>   s390/crypto: Add protected key hmac subfunctions for KMAC
> 
>  arch/s390/configs/debug_defconfig |    1 +
>  arch/s390/configs/defconfig       |    1 +
>  arch/s390/crypto/Makefile         |    1 +
>  arch/s390/crypto/phmac_s390.c     | 1048 +++++++++++++++++++++++++++++
>  arch/s390/include/asm/cpacf.h     |    4 +
>  crypto/ahash.c                    |   26 +-
>  crypto/testmgr.c                  |   30 +
>  drivers/crypto/Kconfig            |   13 +
>  include/crypto/internal/hash.h    |   30 +
>  9 files changed, 1133 insertions(+), 21 deletions(-)
>  create mode 100644 arch/s390/crypto/phmac_s390.c
> 
> 
> base-commit: 1029436218e50168812dbc44b16bca6d35721b0b
> --
> 2.43.0

Hi Herbert,

as the phmac implementation uses the newly introduced 
CRYPTO_ALG_NO_FALLBACK
flag, we can't deliver this patch series via s390. I talked with Heiko
about that and there are two options:
1) We (s390) pick your patch 4ccd065a69df ("crypto: ahash - Add support 
for
    drivers with no fallback") together with my patch series for the next
    kernel's merge window.
2) You (crypto) pick my patch series into your cryptodev-2.6 for next
    kernel's merge window.
I would prefer option 2 as most of the patches anyway deal with crypto
and Heiko and I do not expect unsolvable merge conflicts with the next
kernel's merge.
So what is your opinion?

Thanks,
Harald Freudenberger

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v12 0/6] New s390 specific protected key hmac
  2025-06-24 11:34 ` Harald Freudenberger
@ 2025-06-24 11:37   ` Herbert Xu
  0 siblings, 0 replies; 15+ messages in thread
From: Herbert Xu @ 2025-06-24 11:37 UTC (permalink / raw)
  To: Harald Freudenberger
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

On Tue, Jun 24, 2025 at 01:34:41PM +0200, Harald Freudenberger wrote:
>
> as the phmac implementation uses the newly introduced CRYPTO_ALG_NO_FALLBACK
> flag, we can't deliver this patch series via s390. I talked with Heiko
> about that and there are two options:
> 1) We (s390) pick your patch 4ccd065a69df ("crypto: ahash - Add support for
>    drivers with no fallback") together with my patch series for the next
>    kernel's merge window.
> 2) You (crypto) pick my patch series into your cryptodev-2.6 for next
>    kernel's merge window.
> I would prefer option 2 as most of the patches anyway deal with crypto
> and Heiko and I do not expect unsolvable merge conflicts with the next
> kernel's merge.
> So what is your opinion?

Sure I can do that if you wish.  Is it just that series or are
there other dependencies that I need first?

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v12 0/6] New s390 specific protected key hmac
@ 2025-06-25  9:04 Harald Freudenberger
  0 siblings, 0 replies; 15+ messages in thread
From: Harald Freudenberger @ 2025-06-25  9:04 UTC (permalink / raw)
  To: Herbert Xu
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

On 2025-06-24 13:37, Herbert Xu wrote:
> On Tue, Jun 24, 2025 at 01:34:41PM +0200, Harald Freudenberger wrote:
>> 
>> as the phmac implementation uses the newly introduced 
>> CRYPTO_ALG_NO_FALLBACK
>> flag, we can't deliver this patch series via s390. I talked with Heiko
>> about that and there are two options:
>> 1) We (s390) pick your patch 4ccd065a69df ("crypto: ahash - Add 
>> support for
>>    drivers with no fallback") together with my patch series for the 
>> next
>>    kernel's merge window.
>> 2) You (crypto) pick my patch series into your cryptodev-2.6 for next
>>    kernel's merge window.
>> I would prefer option 2 as most of the patches anyway deal with crypto
>> and Heiko and I do not expect unsolvable merge conflicts with the next
>> kernel's merge.
>> So what is your opinion?
> 
> Sure I can do that if you wish.  Is it just that series or are
> there other dependencies that I need first?
> 
> Cheers,

Thanks this would be great.
No there are no other dependencies, all required code has been merged
into 6.16 already. So for the 6.17 merge window the phmac patch series
v12 has all tags correct and should apply without any problems.



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v12 0/6] New s390 specific protected key hmac
  2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
                   ` (7 preceding siblings ...)
  2025-06-24 11:34 ` Harald Freudenberger
@ 2025-06-26 10:54 ` Herbert Xu
  8 siblings, 0 replies; 15+ messages in thread
From: Herbert Xu @ 2025-06-26 10:54 UTC (permalink / raw)
  To: Harald Freudenberger
  Cc: linux-crypto, linux-s390, dengler, ifranzki, fcallies, hca, gor,
	agordeev

On Tue, Jun 17, 2025 at 03:44:34PM +0200, Harald Freudenberger wrote:
> Add support for protected key hmac ("phmac") for s390 arch.
> 
> With the latest machine generation there is now support for
> protected key (that is a key wrapped by a master key stored
> in firmware) hmac for sha2 (sha224, sha256, sha384 and sha512)
> for the s390 specific CPACF instruction kmac.
> 
> This patch adds support via 4 new hashes registered as
> phmac(sha224), phmac(sha256), phmac(sha384) and phmac(sha512).
> 
> Changelog:
> v1: Initial version
> v2: Increase HASH_MAX_DESCSIZE generic (not just for arch s390).
>     Fix one finding to use kmemdup instead of kmalloc/memcpy from test
>     robot. Remove unneeded cpacf subfunctions checks. Simplify
>     clone_tfm() function. Rebased to s390/features.
> v3: Feedback from Herbert: Use GFP_ATOMIC in setkey function.
>     Feedback from Holger: rework tfm clone function, move convert key
>     invocation from setkey to init function. Rebased to updated
>     s390/features from 11/7/2024. Ready for integration if there are
>     no complains on v3.
> v4: Rewind back more or less to v2. Add code to check for non-sleeping
>     context. Non-sleeping context during attempt to derive the
>     protected key from raw key material is not accepted and
>     -EOPNOTSUPP is returned (also currently all derivation pathes
>     would in fact never sleep). In general the phmac implementation is
>     not to be used within non-sleeping context and the code header
>     mentions this. Tested with (patched) dm-integrity - works fine.
> v5: As suggested by Herbert now the shashes have been marked as
>     'internal' and wrapped by ahashes which use the cryptd if an
>     atomic context is detected. So the visible phmac algorithms are
>     now ahashes. Unfortunately the dm-integrity implementation
>     currently requests and deals only with shashes and this phmac
>     implementation is not fitting to the original goal any more...
> v6: As suggested by Herbert now a pure async phmac implementation.
>     Tested via AF_ALG interface. Untested via dm-integrity as this layer
>     only supports shashes. Maybe I'll develop a patch to switch the
>     dm-integrity to ahash as it is anyway the more flexible interface.
> v7: Total rework of the implementation. Now uses workqueues and triggers
>     asynch requests for key convert, init, update, final and digest.
>     Tested with instrumented code and with a reworked version of
>     dm-integrity which uses asynchronous hashes. A patch for dm-integrity
>     is on the way but yet needs some last hone work.
> v8: Added selftest. With the selftest comes some code which wraps the
>     clear key into a "clear key token" digestible by PKEY. The
>     selftest also uses import() and export(), so these are now also
>     implemented. Furthermore a finup() implementation is now also
>     available. Tested with AF_ALG testcases and dm-integrity, also
>     tested with some instrumented code to check that the asynch
>     workqueue functions do their job correctly. Coding is complete!
> v9: As suggested by Herbert use ahash_request_complete() and surround it
>     with local_bh_disable().
> v10: Split the pkey selftest patch into 3 patches. Slight rework of the
>      setkey function as suggested by Holger: When selftest is running
>      as much as possible of the production code should run. So now the
>      key prep with selftest is one additional if/then block instead of
>      an if/then/else construct.
>      Code is ready for integration and well tested.
> v11: Utterly rework with the insights collected with the paes rework
>      and the basic work done with the pkey rework over the last 5 month.
>      Note that patch #1 effectively reverts commit 7fa481734016
>      ("crypto: ahash - make hash walk functions private to ahash.c")
>      from Eric Biggers.
> v12: Fixed some typos, adaptions to 128 bit total counter,
>      misc_register() invocation was missing in the patches series,
>      added Herbert's proposal for a new function crypto_ahash_tested().
> 
> Harald Freudenberger (5):
>   crypto: ahash - make hash walk functions from ahash.c  public
>   s390/crypto: New s390 specific protected key hash phmac
>   crypto: api - Add crypto_ahash_tested() helper function
>   s390/crypto: Add selftest support for phmac
>   crypto: testmgr - Enable phmac selftest
> 
> Holger Dengler (1):
>   s390/crypto: Add protected key hmac subfunctions for KMAC
> 
>  arch/s390/configs/debug_defconfig |    1 +
>  arch/s390/configs/defconfig       |    1 +
>  arch/s390/crypto/Makefile         |    1 +
>  arch/s390/crypto/phmac_s390.c     | 1048 +++++++++++++++++++++++++++++
>  arch/s390/include/asm/cpacf.h     |    4 +
>  crypto/ahash.c                    |   26 +-
>  crypto/testmgr.c                  |   30 +
>  drivers/crypto/Kconfig            |   13 +
>  include/crypto/internal/hash.h    |   30 +
>  9 files changed, 1133 insertions(+), 21 deletions(-)
>  create mode 100644 arch/s390/crypto/phmac_s390.c
> 
> 
> base-commit: 1029436218e50168812dbc44b16bca6d35721b0b
> --
> 2.43.0

All applied.  Thanks.
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2025-06-26 10:54 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-17 13:44 [PATCH v12 0/6] New s390 specific protected key hmac Harald Freudenberger
2025-06-17 13:44 ` [PATCH v12 1/6] crypto: ahash - make hash walk functions from ahash.c public Harald Freudenberger
2025-06-17 13:44 ` [PATCH v12 2/6] s390/crypto: Add protected key hmac subfunctions for KMAC Harald Freudenberger
2025-06-17 13:44 ` [PATCH v12 3/6] s390/crypto: New s390 specific protected key hash phmac Harald Freudenberger
2025-06-18  9:21   ` Holger Dengler
2025-06-18  9:29   ` Heiko Carstens
2025-06-17 13:44 ` [PATCH v12 4/6] crypto: api - Add crypto_ahash_tested() helper function Harald Freudenberger
2025-06-18  9:23   ` Holger Dengler
2025-06-17 13:44 ` [PATCH v12 5/6] s390/crypto: Add selftest support for phmac Harald Freudenberger
2025-06-17 13:44 ` [PATCH v12 6/6] crypto: testmgr - Enable phmac selftest Harald Freudenberger
2025-06-18  8:58 ` [PATCH v12 0/6] New s390 specific protected key hmac Herbert Xu
2025-06-24 11:34 ` Harald Freudenberger
2025-06-24 11:37   ` Herbert Xu
2025-06-26 10:54 ` Herbert Xu
  -- strict thread matches above, loose matches on Subject: below --
2025-06-25  9:04 Harald Freudenberger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).