lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ