From: Harald Freudenberger <freude@linux.ibm.com>
To: herbert@gondor.apana.org.au, davem@davemloft.net, dengler@linux.ibm.com
Cc: linux-s390@vger.kernel.org, linux-crypto@vger.kernel.org
Subject: [PATCH v10 4/5] s390/crypto: Add selftest support for phmac
Date: Wed, 15 Jan 2025 17:22:30 +0100 [thread overview]
Message-ID: <20250115162231.83516-5-freude@linux.ibm.com> (raw)
In-Reply-To: <20250115162231.83516-1-freude@linux.ibm.com>
Add key preparation code in case of selftest running to the phmac
setkey function:
As long as the CRYPTO_ALG_TESTED flag is not set, 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 the CRYPTO_ALG_TESTED flag is set (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>
---
arch/s390/crypto/phmac_s390.c | 151 +++++++++++++++++++++++++++++++++-
1 file changed, 147 insertions(+), 4 deletions(-)
diff --git a/arch/s390/crypto/phmac_s390.c b/arch/s390/crypto/phmac_s390.c
index b2b389e94a37..5123664e4d2e 100644
--- a/arch/s390/crypto/phmac_s390.c
+++ b/arch/s390/crypto/phmac_s390.c
@@ -112,6 +112,19 @@ struct s390_phmac_req_ctx {
struct s390_kmac_sha2_ctx sha2_ctx;
};
+/*
+ * 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;
+
/*
* kmac_sha2_set_imbl - sets the input message bit-length based on the blocksize
*/
@@ -132,6 +145,101 @@ static inline void kmac_sha2_set_imbl(u8 *param, unsigned int buflen,
}
}
+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, ¶m, in, inlen);
+
+ memcpy(digest, ¶m, 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;
+}
+
/*
* Convert the raw key material into a protected key via PKEY api.
* This function may sleep - don't call in non-sleeping context.
@@ -680,6 +788,12 @@ static int s390_phmac_setkey(struct crypto_ahash *tfm,
const u8 *key, unsigned int keylen)
{
struct s390_phmac_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
+ struct crypto_tfm *tfm_base = crypto_ahash_tfm(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 (tfm_ctx->keylen) {
kfree_sensitive(tfm_ctx->key);
@@ -687,9 +801,31 @@ static int s390_phmac_setkey(struct crypto_ahash *tfm,
tfm_ctx->keylen = 0;
}
+ if (!(crypto_tfm_alg_get_flags(tfm_base) & CRYPTO_ALG_TESTED)) {
+ /*
+ * 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_ATOMIC);
+ if (!tmpkey) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = make_clrkey_token(key, keylen, ds, tmpkey);
+ if (rc)
+ goto out;
+ keylen = tmpkeylen;
+ key = tmpkey;
+ }
+
+ /* key is always a key token digestable by PKEY */
tfm_ctx->key = kmemdup(key, keylen, GFP_ATOMIC);
- if (!tfm_ctx->key)
- return -ENOMEM;
+ if (!tfm_ctx->key) {
+ rc = -ENOMEM;
+ goto out;
+ }
tfm_ctx->keylen = keylen;
/* Always trigger an asynch key convert */
@@ -698,8 +834,10 @@ static int s390_phmac_setkey(struct crypto_ahash *tfm,
spin_unlock_bh(&tfm_ctx->pk_lock);
schedule_delayed_work(&tfm_ctx->work, 0);
- pr_debug("rc=0\n");
- return 0;
+out:
+ kfree(tmpkey);
+ pr_debug("rc=%d\n", rc);
+ return rc;
}
static int s390_phmac_import(struct ahash_request *req, const void *in)
@@ -816,6 +954,11 @@ static int __init phmac_s390_init(void)
struct s390_hmac_alg *hmac;
int i, rc = -ENODEV;
+ if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_256))
+ return -ENODEV;
+ if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_512))
+ return -ENODEV;
+
for (i = 0; i < ARRAY_SIZE(s390_hmac_algs); i++) {
hmac = &s390_hmac_algs[i];
if (!cpacf_query_func(CPACF_KMAC, hmac->fc))
--
2.43.0
next prev parent reply other threads:[~2025-01-15 16:22 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-15 16:22 New s390 specific protected key hmac Harald Freudenberger
2025-01-15 16:22 ` [PATCH v10 1/5] s390/crypto: Add protected key hmac subfunctions for KMAC Harald Freudenberger
2025-01-15 16:22 ` [PATCH v10 2/5] s390/crypto: New s390 specific protected key hash phmac Harald Freudenberger
2025-02-09 8:47 ` Herbert Xu
2025-02-09 16:34 ` Eric Biggers
2025-02-10 7:57 ` Herbert Xu
2025-02-10 16:32 ` Eric Biggers
2025-02-10 23:14 ` Herbert Xu
2025-02-12 11:17 ` Harald Freudenberger
2025-02-12 15:20 ` Eric Biggers
2025-02-13 4:08 ` Herbert Xu
2025-02-11 12:09 ` Harald Freudenberger
2025-02-11 15:31 ` Eric Biggers
2025-02-12 3:19 ` Herbert Xu
2025-02-12 3:23 ` Herbert Xu
2025-02-12 3:32 ` Eric Biggers
2025-02-22 8:23 ` Herbert Xu
2025-01-15 16:22 ` [PATCH v10 3/5] crypto: api - Add crypto_tfm_alg_get_flags() helper inline function Harald Freudenberger
2025-01-15 16:22 ` Harald Freudenberger [this message]
2025-01-15 16:22 ` [PATCH v10 5/5] crypto: testmgr - Enable phmac selftest Harald Freudenberger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250115162231.83516-5-freude@linux.ibm.com \
--to=freude@linux.ibm.com \
--cc=davem@davemloft.net \
--cc=dengler@linux.ibm.com \
--cc=herbert@gondor.apana.org.au \
--cc=linux-crypto@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox