From: R Nageswara Sastry <rnsastry@linux.ibm.com>
To: Srish Srinivasan <ssrish@linux.ibm.com>,
linux-integrity@vger.kernel.org, keyrings@vger.kernel.org,
linuxppc-dev@lists.ozlabs.org
Cc: maddy@linux.ibm.com, mpe@ellerman.id.au, npiggin@gmail.com,
christophe.leroy@csgroup.eu,
James.Bottomley@HansenPartnership.com, jarkko@kernel.org,
zohar@linux.ibm.com, linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org, nayna@linux.ibm.com
Subject: Re: [PATCH v2 09/10] keys/trusted_keys: enable PKWM wrapping key selection by label
Date: Fri, 4 Sep 2026 11:47:33 +0530 [thread overview]
Message-ID: <805f4e2c-f48e-4ace-ad16-18fd99aa4270@linux.ibm.com> (raw)
In-Reply-To: <20260831111738.334857-10-ssrish@linux.ibm.com>
On 31.08.2026 4:47 PM, Srish Srinivasan wrote:
> The PKWM trusted source currently uses the default wrapping key for all
> seal and unseal operations. However, PKWM supports multiple wrapping keys,
> enabling better isolation between trusted keys.
>
> Allow users to provide an active wrapping key of their choice created
> through sysfs when sealing trusted keys through a new wrapping_key=<label>
> option. If no label is specified, the default wrapping key is used for
> sealing.
>
> Signed-off-by: Srish Srinivasan <ssrish@linux.ibm.com>
Tested-by: R Nageswara Sastry <rnsastry@linux.ibm.com>
Tested on ppc64le PowerVM LPARs on firmware with wrap/unwrap support,
with and without Secure Boot enabled.
Verified that:
- Trusted key creation without specifying wrapping_key= continues to work
(default wrapping key used).
- Trusted key creation with wrapping_key=<label> works correctly.
- A label longer than 239 characters is rejected.
- wrap_flags=0x01 and wrap_flags=0x02 behave as expected with the
wrapping_key= option under each Secure Boot mode.
> ---
> .../security/keys/trusted-encrypted.rst | 4 +-
> arch/powerpc/include/asm/plpks.h | 10 ++-
> arch/powerpc/platforms/pseries/plpks.c | 64 ++++++++++---------
> include/keys/trusted_pkwm.h | 3 +
> security/keys/trusted-keys/trusted_pkwm.c | 34 +++++++++-
> 5 files changed, 80 insertions(+), 35 deletions(-)
>
> diff --git a/Documentation/security/keys/trusted-encrypted.rst b/Documentation/security/keys/trusted-encrypted.rst
> index ddff7c7c2582..76fda28fddb1 100644
> --- a/Documentation/security/keys/trusted-encrypted.rst
> +++ b/Documentation/security/keys/trusted-encrypted.rst
> @@ -83,7 +83,7 @@ safe.
>
> (5) PKWM (PowerVM Key Wrapping Module: IBM PowerVM + Platform KeyStore)
>
> - Rooted to a unique, per-LPAR key, which is derived from a system-wide,
> + Rooted to unique, per-LPAR keys, which are derived from a system-wide,
> randomly generated LPAR root key. Both the per-LPAR keys and the LPAR
> root key are stored in hypervisor-owned secure memory at runtime,
> and the LPAR root key is additionally persisted in secure locations
> @@ -366,6 +366,8 @@ Usage::
> 0x01: require secure boot to be in either audit or
> enforced mode
> 0x02: require secure boot to be in enforced mode
> + wrapping_key= optional wrapping key label as a string. The default
> + wrapping key is used when no label is provided.
>
> "keyctl print" returns an ASCII hex copy of the sealed key, which is in format
> specific to PKWM key-blob implementation. The key length for new keys is
> diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
> index c39d1f07017e..badb07afe749 100644
> --- a/arch/powerpc/include/asm/plpks.h
> +++ b/arch/powerpc/include/asm/plpks.h
> @@ -50,6 +50,12 @@
> #define PLPKS_MAX_TIMEOUT (5 * USEC_PER_SEC)
> #define PLPKS_FLUSH_SLEEP 10000 // usec
>
> +// Label for the PKWM default wrapping key
> +#define PLPKS_DEFAULT_WRAPKEY_LABEL "default-wrapping-key"
> +
> +// Component for a PKWM wrapping key
> +#define PLPKS_WRAPKEY_COMPONENT "PLPKSWR"
> +
> struct plpks_var {
> char *component;
> u8 *name;
> @@ -117,10 +123,10 @@ int plpks_config_create_softlink(struct kobject *from);
>
> bool plpks_wrapping_is_supported(void);
>
> -int plpks_gen_wrapping_key(void);
> +int plpks_gen_wrapping_key(struct plpks_var *var);
>
> int plpks_wrap_object(u8 **input_buf, u64 input_len, u16 wrap_flags,
> - u8 **output_buf, u64 *output_len);
> + u8 **output_buf, u64 *output_len, struct plpks_var *var);
>
> int plpks_unwrap_object(u8 **input_buf, u64 input_len,
> u8 **output_buf, u64 *output_len);
> diff --git a/arch/powerpc/platforms/pseries/plpks.c b/arch/powerpc/platforms/pseries/plpks.c
> index 3b1e6f00b4ae..5cdaabe9de06 100644
> --- a/arch/powerpc/platforms/pseries/plpks.c
> +++ b/arch/powerpc/platforms/pseries/plpks.c
> @@ -9,9 +9,6 @@
>
> #define pr_fmt(fmt) "plpks: " fmt
>
> -#define PLPKS_WRAPKEY_COMPONENT "PLPKSWR"
> -#define PLPKS_DEFAULT_WRAPKEY_LABEL "default-wrapping-key"
> -
> /*
> * To 4K align the {input, output} buffers to the {UN}WRAP H_CALLs
> */
> @@ -935,6 +932,7 @@ EXPORT_SYMBOL_GPL(plpks_revoke_is_supported);
> /**
> * plpks_gen_wrapping_key() - Generate a new random key with the 'wrapping key'
> * policy set.
> + * @var: variable representing the wrapping key to be created
> *
> * The H_PKS_GEN_KEY HCALL makes the hypervisor generate a new random key and
> * store the key in a PLPKS object with the provided object label. With the
> @@ -960,25 +958,27 @@ EXPORT_SYMBOL_GPL(plpks_revoke_is_supported);
> *
> * Returns: On success 0 is returned, a negative errno if not.
> */
> -int plpks_gen_wrapping_key(void)
> +int plpks_gen_wrapping_key(struct plpks_var *var)
> {
> unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
> struct plpks_auth *auth;
> struct label *label;
> int rc = 0, pseries_status = 0;
> - struct plpks_var var = {
> - .name = PLPKS_DEFAULT_WRAPKEY_LABEL,
> - .namelen = sizeof(PLPKS_DEFAULT_WRAPKEY_LABEL) - 1,
> - .policy = PLPKS_WRAPPINGKEY,
> - .os = PLPKS_VAR_LINUX,
> - .component = PLPKS_WRAPKEY_COMPONENT
> - };
> +
> + if (!var)
> + return -EINVAL;
> +
> + if (!var->name || !*var->name) {
> + pr_err("key label cannot be NULL/empty\n");
> + return -EINVAL;
> + }
>
> auth = construct_auth(PLPKS_OS_OWNER);
> if (IS_ERR(auth))
> return PTR_ERR(auth);
>
> - label = construct_label(var.component, var.os, var.name, var.namelen);
> + label = construct_label(var->component, var->os, var->name,
> + var->namelen);
> if (IS_ERR(label)) {
> rc = PTR_ERR(label);
> goto out;
> @@ -986,7 +986,7 @@ int plpks_gen_wrapping_key(void)
>
> rc = plpar_hcall(H_PKS_GEN_KEY, retbuf,
> virt_to_phys(auth), virt_to_phys(label),
> - label->size, var.policy,
> + label->size, var->policy,
> NULL, PLPKS_WRAPPING_KEY_LENGTH);
>
> if (!rc)
> @@ -995,11 +995,13 @@ int plpks_gen_wrapping_key(void)
> pseries_status = rc;
> rc = pseries_status_to_err(rc);
>
> - if (rc && rc != -EEXIST) {
> - pr_err("H_PKS_GEN_KEY failed. pseries_status=%d, rc=%d",
> - pseries_status, rc);
> - } else {
> - rc = 0;
> + if (rc) {
> + if (rc == -EEXIST)
> + pr_info("wrapping key <%s> already exists\n",
> + (char *)var->name);
> + else
> + pr_err("H_PKS_GEN_KEY failed. pseries_status=%d, rc=%d\n",
> + pseries_status, rc);
> }
>
> kfree(label);
> @@ -1010,13 +1012,14 @@ int plpks_gen_wrapping_key(void)
> EXPORT_SYMBOL_GPL(plpks_gen_wrapping_key);
>
> /**
> - * plpks_wrap_object() - Wrap an object using the default wrapping key stored in
> - * the PLPKS.
> + * plpks_wrap_object() - Wrap an object using the specified wrapping key stored
> + * in the PLPKS.
> * @input_buf: buffer containing the data to be wrapped
> * @input_len: length of the input buffer
> * @wrap_flags: object wrapping flags
> * @output_buf: buffer to store the wrapped data
> * @output_len: length of the output buffer
> + * @var: variable representing the wrapping key to be used
> *
> * The H_PKS_WRAP_OBJECT HCALL wraps an object using a wrapping key stored in
> * the PLPKS and returns the wrapped object to the caller. The caller provides a
> @@ -1051,7 +1054,7 @@ EXPORT_SYMBOL_GPL(plpks_gen_wrapping_key);
> * Returns: On success 0 is returned, a negative errno if not.
> */
> int plpks_wrap_object(u8 **input_buf, u64 input_len, u16 wrap_flags,
> - u8 **output_buf, u64 *output_len)
> + u8 **output_buf, u64 *output_len, struct plpks_var *var)
> {
> unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
> struct plpks_auth *auth;
> @@ -1061,18 +1064,21 @@ int plpks_wrap_object(u8 **input_buf, u64 input_len, u16 wrap_flags,
> int rc = 0, pseries_status = 0;
> bool sb_audit_or_enforce_bit = wrap_flags & BIT(0);
> bool sb_enforce_bit = wrap_flags & BIT(1);
> - struct plpks_var var = {
> - .name = PLPKS_DEFAULT_WRAPKEY_LABEL,
> - .namelen = sizeof(PLPKS_DEFAULT_WRAPKEY_LABEL) - 1,
> - .os = PLPKS_VAR_LINUX,
> - .component = PLPKS_WRAPKEY_COMPONENT
> - };
> +
> + if (!var)
> + return -EINVAL;
> +
> + if (!var->name || !*var->name) {
> + pr_err("key label cannot be NULL/empty\n");
> + return -EINVAL;
> + }
>
> auth = construct_auth(PLPKS_OS_OWNER);
> if (IS_ERR(auth))
> return PTR_ERR(auth);
>
> - label = construct_label(var.component, var.os, var.name, var.namelen);
> + label = construct_label(var->component, var->os, var->name,
> + var->namelen);
> if (IS_ERR(label)) {
> rc = PTR_ERR(label);
> goto out;
> @@ -1135,7 +1141,7 @@ int plpks_wrap_object(u8 **input_buf, u64 input_len, u16 wrap_flags,
> EXPORT_SYMBOL_GPL(plpks_wrap_object);
>
> /**
> - * plpks_unwrap_object() - Unwrap an object using the default wrapping key
> + * plpks_unwrap_object() - Unwrap an object using its associated wrapping key
> * stored in the PLPKS.
> * @input_buf: buffer containing the data to be unwrapped
> * @input_len: length of the input buffer
> diff --git a/include/keys/trusted_pkwm.h b/include/keys/trusted_pkwm.h
> index 4035b9776394..53a5f780edd2 100644
> --- a/include/keys/trusted_pkwm.h
> +++ b/include/keys/trusted_pkwm.h
> @@ -6,10 +6,13 @@
> #include <linux/bitops.h>
> #include <linux/printk.h>
>
> +#define WRAPPING_KEY_LABEL_LEN_MAX 239
> +
> extern struct trusted_key_ops pkwm_trusted_key_ops;
>
> struct trusted_pkwm_options {
> u16 wrap_flags;
> + unsigned char wrapping_key_label[WRAPPING_KEY_LABEL_LEN_MAX + 1];
> };
>
> static inline void dump_options(struct trusted_key_options *o)
> diff --git a/security/keys/trusted-keys/trusted_pkwm.c b/security/keys/trusted-keys/trusted_pkwm.c
> index 633a7674d065..7bfe98d79cd7 100644
> --- a/security/keys/trusted-keys/trusted_pkwm.c
> +++ b/security/keys/trusted-keys/trusted_pkwm.c
> @@ -13,10 +13,12 @@
> enum {
> Opt_err,
> Opt_wrap_flags,
> + Opt_wrapping_key_label,
> };
>
> static const match_table_t key_tokens = {
> {Opt_wrap_flags, "wrap_flags=%s"},
> + {Opt_wrapping_key_label, "wrapping_key=%s"},
> {Opt_err, NULL}
> };
>
> @@ -50,6 +52,12 @@ static int getoptions(char *datablob, struct trusted_key_options *opt)
> return -EINVAL;
> pkwm->wrap_flags = wrap_flags;
> break;
> + case Opt_wrapping_key_label:
> + if (strlen(args[0].from) > WRAPPING_KEY_LABEL_LEN_MAX)
> + return -EINVAL;
> + strscpy(pkwm->wrapping_key_label, args[0].from,
> + sizeof(pkwm->wrapping_key_label));
> + break;
> default:
> return -EINVAL;
> }
> @@ -82,6 +90,7 @@ static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob)
> {
> struct trusted_key_options *options = NULL;
> struct trusted_pkwm_options *pkwm = NULL;
> + struct plpks_var var;
> u8 *input_buf, *output_buf;
> u64 output_len, input_len;
> int rc;
> @@ -108,8 +117,18 @@ static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob)
>
> pkwm = options->private;
>
> + if (pkwm->wrapping_key_label[0]) {
> + var.name = (u8 *)pkwm->wrapping_key_label;
> + var.namelen = strlen(pkwm->wrapping_key_label);
> + } else {
> + var.name = (u8 *)PLPKS_DEFAULT_WRAPKEY_LABEL;
> + var.namelen = strlen(PLPKS_DEFAULT_WRAPKEY_LABEL);
> + }
> + var.os = PLPKS_VAR_LINUX;
> + var.component = PLPKS_WRAPKEY_COMPONENT;
> +
> rc = plpks_wrap_object(&input_buf, input_len, pkwm->wrap_flags,
> - &output_buf, &output_len);
> + &output_buf, &output_len, &var);
> if (!rc) {
> memcpy(p->blob, output_buf, output_len);
> p->blob_len = output_len;
> @@ -161,14 +180,23 @@ static int trusted_pkwm_unseal(struct trusted_key_payload *p, char *datablob)
> static int trusted_pkwm_init(void)
> {
> int ret;
> + struct plpks_var var;
>
> if (!plpks_wrapping_is_supported()) {
> pr_err("H_PKS_WRAP_OBJECT interface not supported\n");
> return -ENODEV;
> }
>
> - ret = plpks_gen_wrapping_key();
> - if (ret) {
> + var = (struct plpks_var) {
> + .name = (u8 *)PLPKS_DEFAULT_WRAPKEY_LABEL,
> + .namelen = sizeof(PLPKS_DEFAULT_WRAPKEY_LABEL) - 1,
> + .policy = PLPKS_WRAPPINGKEY,
> + .os = PLPKS_VAR_LINUX,
> + .component = PLPKS_WRAPKEY_COMPONENT
> + };
> +
> + ret = plpks_gen_wrapping_key(&var);
> + if (ret && ret != -EEXIST) {
> pr_err("Failed to generate default wrapping key\n");
> return ret;
> }
--
Thanks and Regards
R.Nageswara Sastry
next prev parent reply other threads:[~2026-09-04 6:18 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 11:17 [PATCH v2 00/10] Extend PKWM to support user-created wrapping keys Srish Srinivasan
2026-08-31 11:17 ` [PATCH v2 01/10] pseries/plpks: update PKS documentation and maintainer entry Srish Srinivasan
2026-09-04 6:10 ` R Nageswara Sastry
2026-08-31 11:17 ` [PATCH v2 02/10] pseries/plpks: fix error handling in plpks_read_var() Srish Srinivasan
2026-09-04 6:10 ` R Nageswara Sastry
2026-08-31 11:17 ` [PATCH v2 03/10] pseries/plpks: improve type consistency and parameter validation Srish Srinivasan
2026-09-04 6:11 ` R Nageswara Sastry
2026-08-31 11:17 ` [PATCH v2 04/10] keys/trusted_keys: propagate wrapping key generation errors Srish Srinivasan
2026-09-04 6:12 ` R Nageswara Sastry
2026-08-31 11:17 ` [PATCH v2 05/10] pseries/plpks: rename the default wrapping key macro Srish Srinivasan
2026-09-04 6:13 ` R Nageswara Sastry
2026-08-31 11:17 ` [PATCH v2 06/10] pseries/plpks: fix self-reference in plpks_var initializer Srish Srinivasan
2026-09-04 6:14 ` R Nageswara Sastry
2026-08-31 11:17 ` [PATCH v2 07/10] pseries/plpks: hide wrapping_features when unsupported Srish Srinivasan
2026-09-04 6:16 ` R Nageswara Sastry
2026-08-31 11:17 ` [PATCH v2 08/10] pseries/plpks: add HCALLs for PKWM wrapping key life cycle management Srish Srinivasan
2026-09-04 6:16 ` R Nageswara Sastry
2026-08-31 11:17 ` [PATCH v2 09/10] keys/trusted_keys: enable PKWM wrapping key selection by label Srish Srinivasan
2026-09-04 6:17 ` R Nageswara Sastry [this message]
2026-08-31 11:17 ` [PATCH v2 10/10] pseries/plpks/wrapkey: expose PKWM wrapping key management to userspace via sysfs Srish Srinivasan
2026-09-04 6:19 ` R Nageswara Sastry
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=805f4e2c-f48e-4ace-ad16-18fd99aa4270@linux.ibm.com \
--to=rnsastry@linux.ibm.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=christophe.leroy@csgroup.eu \
--cc=jarkko@kernel.org \
--cc=keyrings@vger.kernel.org \
--cc=linux-integrity@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=maddy@linux.ibm.com \
--cc=mpe@ellerman.id.au \
--cc=nayna@linux.ibm.com \
--cc=npiggin@gmail.com \
--cc=ssrish@linux.ibm.com \
--cc=zohar@linux.ibm.com \
/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