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 v9 3/3] s390/crypto: Enable phmac selftest invocation
Date: Thu, 2 Jan 2025 10:46:15 +0100 [thread overview]
Message-ID: <20250102094615.99181-4-freude@linux.ibm.com> (raw)
In-Reply-To: <20250102094615.99181-1-freude@linux.ibm.com>
- Add a little helper inline function
crypto_tfm_alg_get_flags()
to crypto.h to retrieve the alg flags.
- Add key preparation code in case of selftest running
to the phmac setkey function.
- Add phmac selftest invocation to the crypto testmanager.
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
---
arch/s390/crypto/phmac_s390.c | 144 ++++++++++++++++++++++++++++++++--
crypto/testmgr.c | 30 +++++++
include/linux/crypto.h | 5 ++
3 files changed, 174 insertions(+), 5 deletions(-)
diff --git a/arch/s390/crypto/phmac_s390.c b/arch/s390/crypto/phmac_s390.c
index b2b389e94a37..3d80168775ab 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,10 @@ 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);
+ int rc = 0;
if (tfm_ctx->keylen) {
kfree_sensitive(tfm_ctx->key);
@@ -687,10 +799,26 @@ static int s390_phmac_setkey(struct crypto_ahash *tfm,
tfm_ctx->keylen = 0;
}
- tfm_ctx->key = kmemdup(key, keylen, GFP_ATOMIC);
- if (!tfm_ctx->key)
- return -ENOMEM;
- tfm_ctx->keylen = keylen;
+ if (crypto_tfm_alg_get_flags(tfm_base) & CRYPTO_ALG_TESTED) {
+ /* no selftest: key is always a key token digestable by PKEY */
+ tfm_ctx->key = kmemdup(key, keylen, GFP_ATOMIC);
+ if (!tfm_ctx->key) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ tfm_ctx->keylen = keylen;
+ } else {
+ /* selftest running: key is a raw hmac clear key */
+ tfm_ctx->keylen = sizeof(struct hmac_clrkey_token) + bs;
+ tfm_ctx->key = kzalloc(tfm_ctx->keylen, GFP_ATOMIC);
+ if (!tfm_ctx->key) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ rc = make_clrkey_token(key, keylen, ds, tfm_ctx->key);
+ if (rc)
+ goto out;
+ }
/* Always trigger an asynch key convert */
spin_lock_bh(&tfm_ctx->pk_lock);
@@ -698,8 +826,9 @@ static int s390_phmac_setkey(struct crypto_ahash *tfm,
spin_unlock_bh(&tfm_ctx->pk_lock);
schedule_delayed_work(&tfm_ctx->work, 0);
+out:
pr_debug("rc=0\n");
- return 0;
+ return rc;
}
static int s390_phmac_import(struct ahash_request *req, const void *in)
@@ -816,6 +945,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))
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 1f5f48ab18c7..e753a68be861 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -5539,6 +5539,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 = {
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index b164da5e129e..8b37d381cd97 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -472,6 +472,11 @@ static inline unsigned int crypto_tfm_alg_alignmask(struct crypto_tfm *tfm)
return tfm->__crt_alg->cra_alignmask;
}
+static inline u32 crypto_tfm_alg_get_flags(struct crypto_tfm *tfm)
+{
+ return tfm->__crt_alg->cra_flags;
+}
+
static inline u32 crypto_tfm_get_flags(struct crypto_tfm *tfm)
{
return tfm->crt_flags;
--
2.43.0
next prev parent reply other threads:[~2025-01-02 9:46 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-02 9:46 [PATCH v9 0/3] New s390 specific protected key hmac Harald Freudenberger
2025-01-02 9:46 ` [PATCH v9 1/3] s390/crypto: Add protected key hmac subfunctions for KMAC Harald Freudenberger
2025-01-02 9:46 ` [PATCH v9 2/3] s390/crypto: New s390 specific protected key hash phmac Harald Freudenberger
2025-01-03 9:22 ` Holger Dengler
2025-01-02 9:46 ` Harald Freudenberger [this message]
2025-01-13 7:45 ` [PATCH v9 3/3] s390/crypto: Enable phmac selftest invocation Holger Dengler
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=20250102094615.99181-4-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.