From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3077B26299; Sat, 13 Dec 2025 19:22:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765653742; cv=none; b=nVNhPO/9ALwcXn5J6jMIZcaMu93Z//nK3QeRf54QYzjyeZlYNS9tv2ZN4KjmBq0CQniyRX6dNc9pgPG8U96MWFZOJeB+nKJD7ca3PJp7IF9l1P8K9Ss2SWu2u2eaIhFntHutNoPAsu5/s0BVLG3fsu5FUUPL8FXeLi+JhlLDQTo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1765653742; c=relaxed/simple; bh=kUe0CMSCJN6oyiBHyw6ZT05IRDGvAOetmVrBHZn6ic4=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=hzK3Q4Q+YCxuCaESmsAlx4DCUI5iRs1E/cyoy1X+D0b6BSSa3bTJY1yBpwX8CylEf52cHh73rl9RvlpN38PwMbqY3NSUQ04kMd2joWrhjsuqkqnsXFny1TglezzE0LIKo+CirayV6hsaxTMaGew3c05apkHq908iIcCpXPW4Ssk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=g38MrFDo; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="g38MrFDo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2BDAAC4CEF7; Sat, 13 Dec 2025 19:22:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1765653741; bh=kUe0CMSCJN6oyiBHyw6ZT05IRDGvAOetmVrBHZn6ic4=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=g38MrFDoV40H1bn9d10sKQKdzTAjINIeWbFuOQ7Jd8RMmk9phxR5OXfui5TstWWMd M1NKWZOCR0yxJ/FkpYhKTubfBsvu8rbbIO50Kpx7kifhu6ZvzYnyh3pbdHHmpSXlCT SaVCdiAJmOSvBTEQNvJuMJ1PxGzSB0YOY7rbVxdHFQ6vaZLWOCyqBzT4D89ZUiaAnY qpcjH661ClwmbDohQcBwtNjQvk9d1r+c8O37y8bnceRSvp4R+t+ZI37gtt/fOyS8mB 3LX6KUoYa9yWcrOJSIyx5V2KvytD8eiysrwP0+2ZGZInZKGjeZnc6S556abBSLCyMk ShJr1rQgqXz0w== Date: Sat, 13 Dec 2025 21:22:17 +0200 From: Jarkko Sakkinen To: Srish Srinivasan Cc: linux-integrity@vger.kernel.org, keyrings@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, maddy@linux.ibm.com, mpe@ellerman.id.au, npiggin@gmail.com, christophe.leroy@csgroup.eu, James.Bottomley@hansenpartnership.com, zohar@linux.ibm.com, nayna@linux.ibm.com, rnsastry@linux.ibm.com, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org Subject: Re: [PATCH 5/6] keys/trusted_keys: establish PKWM as a trusted source Message-ID: References: <20251213052618.190691-1-ssrish@linux.ibm.com> <20251213052618.190691-6-ssrish@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-integrity@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20251213052618.190691-6-ssrish@linux.ibm.com> On Sat, Dec 13, 2025 at 10:56:17AM +0530, Srish Srinivasan wrote: > The wrapping key does not exist by default and is generated by the > hypervisor as a part of PKWM initialization. This key is then persisted by > the hypervisor and is used to wrap trusted keys. These are variable length > symmetric keys, which in the case of PowerVM Key Wrapping Module (PKWM) are > generated using the kernel RNG. PKWM can be used as a trust source through > the following example keyctl command > > keyctl add trusted my_trusted_key "new 32" @u > > Use the wrap_flags command option to set the secure boot requirement for > the wrapping request through the following keyctl commands > > case1: no secure boot requirement. (default) > keyctl usage: keyctl add trusted my_trusted_key "new 32" @u > OR > keyctl add trusted my_trusted_key "new 32 wrap_flags=0x00" @u > > case2: secure boot required to in either audit or enforce mode. set bit 0 > keyctl usage: keyctl add trusted my_trusted_key "new 32 wrap_flags=0x01" @u > > case3: secure boot required to be in enforce mode. set bit 1 > keyctl usage: keyctl add trusted my_trusted_key "new 32 wrap_flags=0x02" @u > > NOTE: > -> Setting the secure boot requirement is NOT a must. > -> Only either of the secure boot requirement options should be set. Not > both. > -> All the other bits are requied to be not set. > -> Set the kernel parameter trusted.source=pkwm to choose PKWM as the > backend for trusted keys implementation. > -> CONFIG_PSERIES_PLPKS must be enabled to build PKWM. > > Add PKWM, which is a combination of IBM PowerVM and Power LPAR Platform > KeyStore, as a new trust source for trusted keys. > > Signed-off-by: Srish Srinivasan > --- > MAINTAINERS | 9 ++ > include/keys/trusted-type.h | 7 +- > include/keys/trusted_pkwm.h | 30 ++++ > security/keys/trusted-keys/Kconfig | 8 ++ > security/keys/trusted-keys/Makefile | 2 + > security/keys/trusted-keys/trusted_core.c | 6 +- > security/keys/trusted-keys/trusted_pkwm.c | 168 ++++++++++++++++++++++ > 7 files changed, 228 insertions(+), 2 deletions(-) > create mode 100644 include/keys/trusted_pkwm.h > create mode 100644 security/keys/trusted-keys/trusted_pkwm.c > > diff --git a/MAINTAINERS b/MAINTAINERS > index aff3e162180d..bf78ab78a309 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -13993,6 +13993,15 @@ S: Supported > F: include/keys/trusted_dcp.h > F: security/keys/trusted-keys/trusted_dcp.c > > +KEYS-TRUSTED-PLPKS > +M: Srish Srinivasan > +M: Nayna Jain > +L: linux-integrity@vger.kernel.org > +L: keyrings@vger.kernel.org > +S: Supported > +F: include/keys/trusted_plpks.h > +F: security/keys/trusted-keys/trusted_pkwm.c > + > KEYS-TRUSTED-TEE > M: Sumit Garg > L: linux-integrity@vger.kernel.org > diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h > index 4eb64548a74f..45c6c538df22 100644 > --- a/include/keys/trusted-type.h > +++ b/include/keys/trusted-type.h > @@ -19,7 +19,11 @@ > > #define MIN_KEY_SIZE 32 > #define MAX_KEY_SIZE 128 > -#define MAX_BLOB_SIZE 512 > +#if IS_ENABLED(CONFIG_TRUSTED_KEYS_PKWM) > +#define MAX_BLOB_SIZE 1152 > +#else > +#define MAX_BLOB_SIZE 512 > +#endif > #define MAX_PCRINFO_SIZE 64 > #define MAX_DIGEST_SIZE 64 > > @@ -46,6 +50,7 @@ struct trusted_key_options { > uint32_t policydigest_len; > unsigned char policydigest[MAX_DIGEST_SIZE]; > uint32_t policyhandle; > + uint16_t wrap_flags; > }; > > struct trusted_key_ops { > diff --git a/include/keys/trusted_pkwm.h b/include/keys/trusted_pkwm.h > new file mode 100644 > index 000000000000..736edfc1e1dd > --- /dev/null > +++ b/include/keys/trusted_pkwm.h > @@ -0,0 +1,30 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#ifndef __PKWM_TRUSTED_KEY_H > +#define __PKWM_TRUSTED_KEY_H > + > +#include > + > +extern struct trusted_key_ops pkwm_trusted_key_ops; > + > +#define PKWM_DEBUG 0 > + > +#if PKWM_DEBUG > +static inline void dump_options(struct trusted_key_options *o) > +{ > + bool sb_audit_or_enforce_bit = o->policyhandle & BIT(0); > + bool sb_enforce_bit = o->policyhandle & BIT(1); > + > + if (sb_audit_or_enforce_bit) > + pr_info("secure boot mode: audit or enforce"); > + else if (sb_enforce_bit) > + pr_info("secure boot mode: enforce"); > + else > + pr_info("secure boot mode: disabled"); > +} > +#else > +static inline void dump_options(struct trusted_key_options *o) > +{ > +} > +#endif Please use pr_debug() instead of emulating this with 'PKWM_DEBUG'. > + > +#endif > diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-keys/Kconfig > index 204a68c1429d..9e00482d886a 100644 > --- a/security/keys/trusted-keys/Kconfig > +++ b/security/keys/trusted-keys/Kconfig > @@ -46,6 +46,14 @@ config TRUSTED_KEYS_DCP > help > Enable use of NXP's DCP (Data Co-Processor) as trusted key backend. > > +config TRUSTED_KEYS_PKWM > + bool "PKWM-based trusted keys" > + depends on PSERIES_PLPKS >= TRUSTED_KEYS > + default y > + select HAVE_TRUSTED_KEYS > + help > + Enable use of IBM PowerVM Key Wrapping Module (PKWM) as a trusted key backend. > + > if !HAVE_TRUSTED_KEYS > comment "No trust source selected!" > endif > diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-keys/Makefile > index f0f3b27f688b..5fc053a21dad 100644 > --- a/security/keys/trusted-keys/Makefile > +++ b/security/keys/trusted-keys/Makefile > @@ -16,3 +16,5 @@ trusted-$(CONFIG_TRUSTED_KEYS_TEE) += trusted_tee.o > trusted-$(CONFIG_TRUSTED_KEYS_CAAM) += trusted_caam.o > > trusted-$(CONFIG_TRUSTED_KEYS_DCP) += trusted_dcp.o > + > +trusted-$(CONFIG_TRUSTED_KEYS_PKWM) += trusted_pkwm.o > diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trusted-keys/trusted_core.c > index b1680ee53f86..2d328de170e8 100644 > --- a/security/keys/trusted-keys/trusted_core.c > +++ b/security/keys/trusted-keys/trusted_core.c > @@ -12,6 +12,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -31,7 +32,7 @@ MODULE_PARM_DESC(rng, "Select trusted key RNG"); > > static char *trusted_key_source; > module_param_named(source, trusted_key_source, charp, 0); > -MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam or dcp)"); > +MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam, dcp or pkwm)"); > > static const struct trusted_key_source trusted_key_sources[] = { > #if defined(CONFIG_TRUSTED_KEYS_TPM) > @@ -46,6 +47,9 @@ static const struct trusted_key_source trusted_key_sources[] = { > #if defined(CONFIG_TRUSTED_KEYS_DCP) > { "dcp", &dcp_trusted_key_ops }, > #endif > +#if defined(CONFIG_TRUSTED_KEYS_PKWM) > + { "pkwm", &pkwm_trusted_key_ops }, > +#endif > }; > > DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->seal); > diff --git a/security/keys/trusted-keys/trusted_pkwm.c b/security/keys/trusted-keys/trusted_pkwm.c > new file mode 100644 > index 000000000000..7968601dcf42 > --- /dev/null > +++ b/security/keys/trusted-keys/trusted_pkwm.c > @@ -0,0 +1,168 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (C) 2025 IBM Corporation, Srish Srinivasan > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +enum { > + Opt_err, > + Opt_wrap_flags, > +}; > + > +static const match_table_t key_tokens = { > + {Opt_wrap_flags, "wrap_flags=%s"}, > + {Opt_err, NULL} > +}; > + > +static int getoptions(char *datablob, struct trusted_key_options **opt) > +{ > + substring_t args[MAX_OPT_ARGS]; > + char *p = datablob; > + int token; > + int res; > + unsigned long wrap_flags; > + unsigned long token_mask = 0; > + > + if (!datablob) > + return 0; > + > + while ((p = strsep(&datablob, " \t"))) { > + if (*p == '\0' || *p == ' ' || *p == '\t') > + continue; > + > + token = match_token(p, key_tokens, args); > + if (test_and_set_bit(token, &token_mask)) > + return -EINVAL; > + > + switch (token) { > + case Opt_wrap_flags: > + res = kstrtoul(args[0].from, 16, &wrap_flags); > + if (res < 0 || wrap_flags > 2) > + return -EINVAL; > + (*opt)->wrap_flags = wrap_flags; > + break; > + default: > + return -EINVAL; > + } > + } > + return 0; > +} > + > +static struct trusted_key_options *trusted_options_alloc(void) > +{ > + struct trusted_key_options *options; > + > + options = kzalloc(sizeof(*options), GFP_KERNEL); > + return options; > +} > + > +static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob) > +{ > + struct trusted_key_options *options = NULL; > + u8 *input_buf, *output_buf; > + u32 output_len, input_len; > + int rc; > + > + options = trusted_options_alloc(); > + if (!options) > + return -ENOMEM; > + > + rc = getoptions(datablob, &options); > + if (rc < 0) > + goto out; > + dump_options(options); > + > + input_len = p->key_len; > + input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL); > + if (!input_buf) { > + pr_err("Input buffer allocation failed. Returning -ENOMEM."); > + return -ENOMEM; > + } > + > + memcpy(input_buf, p->key, p->key_len); > + > + rc = plpks_wrap_object(&input_buf, input_len, options->wrap_flags, > + &output_buf, &output_len); > + if (!rc) { > + memcpy(p->blob, output_buf, output_len); > + p->blob_len = output_len; > + dump_payload(p); > + } else { > + pr_err("Invalid argument"); > + } > + > + kfree(input_buf); > + kfree(output_buf); > + > +out: > + kfree_sensitive(options); > + return rc; > +} > + > +static int trusted_pkwm_unseal(struct trusted_key_payload *p, char *datablob) > +{ > + u8 *input_buf, *output_buf; > + u32 input_len, output_len; > + int rc; > + > + input_len = p->blob_len; > + input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL); > + if (!input_buf) > + return -ENOMEM; > + > + memcpy(input_buf, p->blob, p->blob_len); > + > + rc = plpks_unwrap_object(&input_buf, input_len, &output_buf, > + &output_len); > + if (!rc) { > + memcpy(p->key, output_buf, output_len); > + p->key_len = output_len; > + dump_payload(p); > + } else { > + pr_err("Invalid argument"); I don't get this error message. What does this mean? pr_err() is used when you have actual malfunction. > + } > + > + kfree(input_buf); > + kfree(output_buf); > + > + return rc; > +} > + > +static int trusted_pkwm_init(void) > +{ > + int ret; > + > + if (!plpks_wrapping_is_supported()) { > + pr_err("H_PKS_WRAP_OBJECT interface not supported\n"); > + > + return -ENODEV; > + } > + > + ret = plpks_gen_wrapping_key(); > + if (ret) { > + pr_err("Failed to generate default wrapping key\n"); > + > + return -EINVAL; > + } > + > + return register_key_type(&key_type_trusted); > +} > + > +static void trusted_pkwm_exit(void) > +{ > + unregister_key_type(&key_type_trusted); > +} > + > +struct trusted_key_ops pkwm_trusted_key_ops = { > + .migratable = 0, /* non-migratable */ > + .init = trusted_pkwm_init, > + .seal = trusted_pkwm_seal, > + .unseal = trusted_pkwm_unseal, > + .exit = trusted_pkwm_exit, > +}; > -- > 2.47.3 > BR, Jarkko