From nobody Sat Feb 7 15:30:16 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (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 3A4D733B96B; Sun, 1 Feb 2026 14:00:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769954414; cv=none; b=JS4ka+oO3xNS2bTfSj1/GtKu1sIYDKoRW3TTYzl8qvXtpsBCQhg5bfNvuAXEpZJwbGc/XlNPTPn/l+YtBBPguEtlVRbbyeCuB35j5HRxkcMLem/X8Ws3d8vWnRzTKHBjvkReMR99VUsFWOqSVBBcE152lxeC5DsFOZYsi9rrDbA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769954414; c=relaxed/simple; bh=8GSCM9PTZmTDnOfw++1u4ef8KcGAb923KxDhQz2Xeec=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Q9sXEGtB0pEQLjBFftiVUHz63WCKrKqubv1aIXsQJFZdUx8ZYAJ1I61P6vKwCT/+VfGRxCzu+bPr2gjQSzxyzTZ6TE0iEc1DUvOaJhZnAcfWyCes2gQPdxm3PWwE2oKK7oW3k248mqC6GrbhWVje/As73AXK/h+Ch43yCLtUFBs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=S8uC7eMP; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="S8uC7eMP" Received: from pps.filterd (m0353725.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 611804YK008775; Sun, 1 Feb 2026 13:59:58 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=JPX9D80ShV/Vh62aB WDxM9M6aEzJOTHR1/BpdkwVEEw=; b=S8uC7eMPegxckvofTXBZpHtxZeN05NUjn 9YxzvroqJbJMchuCfdkclRbIzo7ehKPY9uvwV5r+Nab7fUDiGl7phalDEz9r70Iq bHkKDfNBUT9SlDcqcUejBZ2aioLYs1zjvSvDvg4vS5PvFmgZWQohRByjZvhtScFf PXlGFpCzbdlIXJ5+jEL1YtgMVRLd75szIEIN+e7+Y0T97jQ1g8zYvwVDAXAsfR9T Ajk6H5J/HUIodeNARhA6Cm9PSmHzKx3s3tmAktAY6rRYx4hy6+b4SgE4Ungm4pBA ku1WxrUB14ZqmyEWn1Ym/36a+Zwocey3J8/8B1P8UyxhkJxKxvuow== Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4c185gkt4s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 01 Feb 2026 13:59:58 +0000 (GMT) Received: from m0353725.ppops.net (m0353725.ppops.net [127.0.0.1]) by pps.reinject (8.18.1.12/8.18.0.8) with ESMTP id 611Dxv06000499; Sun, 1 Feb 2026 13:59:57 GMT Received: from ppma21.wdc07v.mail.ibm.com (5b.69.3da9.ip4.static.sl-reverse.com [169.61.105.91]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4c185gkt4q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 01 Feb 2026 13:59:57 +0000 (GMT) Received: from pps.filterd (ppma21.wdc07v.mail.ibm.com [127.0.0.1]) by ppma21.wdc07v.mail.ibm.com (8.18.1.2/8.18.1.2) with ESMTP id 61187s8T025696; Sun, 1 Feb 2026 13:59:57 GMT Received: from smtprelay04.fra02v.mail.ibm.com ([9.218.2.228]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4c1w2mhkq5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Sun, 01 Feb 2026 13:59:56 +0000 Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay04.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 611Dxr8d13697450 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Sun, 1 Feb 2026 13:59:53 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0F4F520043; Sun, 1 Feb 2026 13:59:53 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E837120040; Sun, 1 Feb 2026 13:59:49 +0000 (GMT) Received: from li-fc74f8cc-3279-11b2-a85c-ef5828687581.ibm.com.com (unknown [9.39.20.39]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Sun, 1 Feb 2026 13:59:49 +0000 (GMT) From: Srish Srinivasan To: 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, nayna@linux.ibm.com, rnsastry@linux.ibm.com, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, ssrish@linux.ibm.com Subject: [PATCH v6 5/6] keys/trusted_keys: establish PKWM as a trusted source Date: Sun, 1 Feb 2026 19:29:29 +0530 Message-ID: <20260201135930.898721-6-ssrish@linux.ibm.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260201135930.898721-1-ssrish@linux.ibm.com> References: <20260201135930.898721-1-ssrish@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Authority-Analysis: v=2.4 cv=UdxciaSN c=1 sm=1 tr=0 ts=697f5c5e cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=HzLeVaNsDn8A:10 a=VkNPw1HP01LnGYTKEx00:22 a=VnNF1IyMAAAA:8 a=VwQbUJbxAAAA:8 a=6hcB66QTelQ3WYe9m3UA:9 X-Proofpoint-GUID: dvlZM0pJONVTpG8C-cyyAEqLVT6K_W1x X-Proofpoint-ORIG-GUID: t2eacskfmF420wyF_lXk8jsO-JzQi3QC X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwMjAxMDEyMCBTYWx0ZWRfX0EwaMa03mfQF nR+oDv38Ly/JttSqzJwM2Xs78zgpDvr/9JcqNzuIjRMTK4LiRVAYlveX1CLO3wV2quPR1glSjOX xalQ/laBb/fSPc57Ei2bjX7w+iNgVyUqNefjmpIMmJHRZoNQhPP6cZOIOrU/8A3gsc5hHaYruIk PbAXOyzEtWwTUfMb9fVwIcN1x+9qowViDyzQWHlcpzDBvp6u9O/SzNxRklScvE1BJEpkfdvFsuH n7mAAfvw1YzW1fkO6y0QB2h0hF1XQaCktBLwWJqZOs6mJJ74qSX63XPzLRy49tRPloMd2GQZZKk JkUKBpDkwJWHmVr6vE8N8CZYkBAjsGiHJeicDZk6E4QunHYJrsBqZgcEdHxgX1WyLjtpCkVHxCz reyekBIH/8qn9R1f6ixSTdDIAGVMeV8T39osJLrEW07ukdMEoItUluDYOxRu2XXy+9nGjv7+QcD 0Abwt9EnlAgvK8fCdVA== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1121,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-02-01_05,2026-01-30_04,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 impostorscore=0 lowpriorityscore=0 suspectscore=0 clxscore=1015 bulkscore=0 spamscore=0 phishscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2601150000 definitions=main-2602010120 Content-Type: text/plain; charset="utf-8" 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 commands: 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=3D0x00" @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=3D0x01" = @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=3D0x02" = @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 required to be not set. -> Set the kernel parameter trusted.source=3Dpkwm 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 Reviewed-by: Mimi Zohar Reviewed-by: Nayna Jain Reviewed-by: Jarkko Sakkinen Tested-by: Nayna Jain --- MAINTAINERS | 9 + include/keys/trusted-type.h | 7 +- include/keys/trusted_pkwm.h | 33 ++++ 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 | 190 ++++++++++++++++++++++ 7 files changed, 253 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 0efa8cc6775b..b037648e66fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14013,6 +14013,15 @@ S: Supported F: include/keys/trusted_dcp.h F: security/keys/trusted-keys/trusted_dcp.c =20 +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_pkwm.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..03527162613f 100644 --- a/include/keys/trusted-type.h +++ b/include/keys/trusted-type.h @@ -19,7 +19,11 @@ =20 #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 =20 @@ -46,6 +50,7 @@ struct trusted_key_options { uint32_t policydigest_len; unsigned char policydigest[MAX_DIGEST_SIZE]; uint32_t policyhandle; + void *private; }; =20 struct trusted_key_ops { diff --git a/include/keys/trusted_pkwm.h b/include/keys/trusted_pkwm.h new file mode 100644 index 000000000000..4035b9776394 --- /dev/null +++ b/include/keys/trusted_pkwm.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PKWM_TRUSTED_KEY_H +#define __PKWM_TRUSTED_KEY_H + +#include +#include +#include + +extern struct trusted_key_ops pkwm_trusted_key_ops; + +struct trusted_pkwm_options { + u16 wrap_flags; +}; + +static inline void dump_options(struct trusted_key_options *o) +{ + const struct trusted_pkwm_options *pkwm; + bool sb_audit_or_enforce_bit; + bool sb_enforce_bit; + + pkwm =3D o->private; + sb_audit_or_enforce_bit =3D pkwm->wrap_flags & BIT(0); + sb_enforce_bit =3D pkwm->wrap_flags & BIT(1); + + if (sb_audit_or_enforce_bit) + pr_debug("secure boot mode required: audit or enforce"); + else if (sb_enforce_bit) + pr_debug("secure boot mode required: enforce"); + else + pr_debug("secure boot mode required: disabled"); +} + +#endif diff --git a/security/keys/trusted-keys/Kconfig b/security/keys/trusted-key= s/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. =20 +config TRUSTED_KEYS_PKWM + bool "PKWM-based trusted keys" + depends on PSERIES_PLPKS >=3D TRUSTED_KEYS + default y + select HAVE_TRUSTED_KEYS + help + Enable use of IBM PowerVM Key Wrapping Module (PKWM) as a trusted key b= ackend. + if !HAVE_TRUSTED_KEYS comment "No trust source selected!" endif diff --git a/security/keys/trusted-keys/Makefile b/security/keys/trusted-ke= ys/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) +=3D trusted_tee.o trusted-$(CONFIG_TRUSTED_KEYS_CAAM) +=3D trusted_caam.o =20 trusted-$(CONFIG_TRUSTED_KEYS_DCP) +=3D trusted_dcp.o + +trusted-$(CONFIG_TRUSTED_KEYS_PKWM) +=3D trusted_pkwm.o diff --git a/security/keys/trusted-keys/trusted_core.c b/security/keys/trus= ted-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"); =20 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 dc= p)"); +MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam, dcp = or pkwm)"); =20 static const struct trusted_key_source trusted_key_sources[] =3D { #if defined(CONFIG_TRUSTED_KEYS_TPM) @@ -46,6 +47,9 @@ static const struct trusted_key_source trusted_key_source= s[] =3D { #if defined(CONFIG_TRUSTED_KEYS_DCP) { "dcp", &dcp_trusted_key_ops }, #endif +#if defined(CONFIG_TRUSTED_KEYS_PKWM) + { "pkwm", &pkwm_trusted_key_ops }, +#endif }; =20 DEFINE_STATIC_CALL_NULL(trusted_key_seal, *trusted_key_sources[0].ops->sea= l); diff --git a/security/keys/trusted-keys/trusted_pkwm.c b/security/keys/trus= ted-keys/trusted_pkwm.c new file mode 100644 index 000000000000..4f391b77a907 --- /dev/null +++ b/security/keys/trusted-keys/trusted_pkwm.c @@ -0,0 +1,190 @@ +// 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 =3D { + {Opt_wrap_flags, "wrap_flags=3D%s"}, + {Opt_err, NULL} +}; + +static int getoptions(char *datablob, struct trusted_key_options *opt) +{ + substring_t args[MAX_OPT_ARGS]; + char *p =3D datablob; + int token; + int res; + u16 wrap_flags; + unsigned long token_mask =3D 0; + struct trusted_pkwm_options *pkwm; + + if (!datablob) + return 0; + + pkwm =3D opt->private; + + while ((p =3D strsep(&datablob, " \t"))) { + if (*p =3D=3D '\0' || *p =3D=3D ' ' || *p =3D=3D '\t') + continue; + + token =3D match_token(p, key_tokens, args); + if (test_and_set_bit(token, &token_mask)) + return -EINVAL; + + switch (token) { + case Opt_wrap_flags: + res =3D kstrtou16(args[0].from, 16, &wrap_flags); + if (res < 0 || wrap_flags > 2) + return -EINVAL; + pkwm->wrap_flags =3D wrap_flags; + break; + default: + return -EINVAL; + } + } + return 0; +} + +static struct trusted_key_options *trusted_options_alloc(void) +{ + struct trusted_key_options *options; + struct trusted_pkwm_options *pkwm; + + options =3D kzalloc(sizeof(*options), GFP_KERNEL); + + if (options) { + pkwm =3D kzalloc(sizeof(*pkwm), GFP_KERNEL); + + if (!pkwm) { + kfree_sensitive(options); + options =3D NULL; + } else { + options->private =3D pkwm; + } + } + + return options; +} + +static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob) +{ + struct trusted_key_options *options =3D NULL; + struct trusted_pkwm_options *pkwm =3D NULL; + u8 *input_buf, *output_buf; + u32 output_len, input_len; + int rc; + + options =3D trusted_options_alloc(); + + if (!options) + return -ENOMEM; + + rc =3D getoptions(datablob, options); + if (rc < 0) + goto out; + dump_options(options); + + input_len =3D p->key_len; + input_buf =3D kmalloc(ALIGN(input_len, 4096), GFP_KERNEL); + if (!input_buf) { + pr_err("Input buffer allocation failed. Returning -ENOMEM."); + rc =3D -ENOMEM; + goto out; + } + + memcpy(input_buf, p->key, p->key_len); + + pkwm =3D options->private; + + rc =3D plpks_wrap_object(&input_buf, input_len, pkwm->wrap_flags, + &output_buf, &output_len); + if (!rc) { + memcpy(p->blob, output_buf, output_len); + p->blob_len =3D output_len; + dump_payload(p); + } else { + pr_err("Wrapping of payload key failed: %d\n", rc); + } + + kfree(input_buf); + kfree(output_buf); + +out: + kfree_sensitive(options->private); + kfree_sensitive(options); + return rc; +} + +static int trusted_pkwm_unseal(struct trusted_key_payload *p, char *databl= ob) +{ + u8 *input_buf, *output_buf; + u32 input_len, output_len; + int rc; + + input_len =3D p->blob_len; + input_buf =3D kmalloc(ALIGN(input_len, 4096), GFP_KERNEL); + if (!input_buf) { + pr_err("Input buffer allocation failed. Returning -ENOMEM."); + return -ENOMEM; + } + + memcpy(input_buf, p->blob, p->blob_len); + + rc =3D plpks_unwrap_object(&input_buf, input_len, &output_buf, + &output_len); + if (!rc) { + memcpy(p->key, output_buf, output_len); + p->key_len =3D output_len; + dump_payload(p); + } else { + pr_err("Unwrapping of payload failed: %d\n", rc); + } + + 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 =3D 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 =3D { + .migratable =3D 0, /* non-migratable */ + .init =3D trusted_pkwm_init, + .seal =3D trusted_pkwm_seal, + .unseal =3D trusted_pkwm_unseal, + .exit =3D trusted_pkwm_exit, +}; --=20 2.47.3