[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <41a3a9ae-6d30-40d2-a74d-3a6a31054d50@linux.ibm.com>
Date: Wed, 17 Dec 2025 10:48:53 +0530
From: Srish Srinivasan <ssrish@...ux.ibm.com>
To: Jarkko Sakkinen <jarkko@...nel.org>
Cc: linux-integrity@...r.kernel.org, keyrings@...r.kernel.org,
linuxppc-dev@...ts.ozlabs.org, maddy@...ux.ibm.com, mpe@...erman.id.au,
npiggin@...il.com, christophe.leroy@...roup.eu,
James.Bottomley@...senpartnership.com, zohar@...ux.ibm.com,
nayna@...ux.ibm.com, rnsastry@...ux.ibm.com,
linux-kernel@...r.kernel.org, linux-security-module@...r.kernel.org
Subject: Re: [PATCH 5/6] keys/trusted_keys: establish PKWM as a trusted source
Hi Jarkko,
thank you for taking a look and providing feedback.
On 12/14/25 12:52 AM, Jarkko Sakkinen wrote:
> 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 <ssrish@...ux.ibm.com>
>> ---
>> 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 <ssrish@...ux.ibm.com>
>> +M: Nayna Jain <nayna@...ux.ibm.com>
>> +L: linux-integrity@...r.kernel.org
>> +L: keyrings@...r.kernel.org
>> +S: Supported
>> +F: include/keys/trusted_plpks.h
>> +F: security/keys/trusted-keys/trusted_pkwm.c
>> +
>> KEYS-TRUSTED-TEE
>> M: Sumit Garg <sumit.garg@...nel.org>
>> L: linux-integrity@...r.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 <keys/trusted-type.h>
>> +
>> +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'.
Sure, I will fix this.
>> +
>> +#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 <keys/trusted_caam.h>
>> #include <keys/trusted_dcp.h>
>> #include <keys/trusted_tpm.h>
>> +#include <keys/trusted_pkwm.h>
>> #include <linux/capability.h>
>> #include <linux/err.h>
>> #include <linux/init.h>
>> @@ -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 <ssrish@...ux.ibm.com>
>> + */
>> +
>> +#include <keys/trusted_pkwm.h>
>> +#include <keys/trusted-type.h>
>> +#include <linux/build_bug.h>
>> +#include <linux/key-type.h>
>> +#include <linux/parser.h>
>> +#include <asm/plpks.h>
>> +
>> +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.
Yes, the error message lacks clarity here.
It was meant to communicate that the unwrap operation failed.
I will provide a more meaningful error message with the error code
as that would be more helpful.
And thanks for pointing this out.
>
>> + }
>> +
>> + 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
>
thanks,
Srish.
Powered by blists - more mailing lists