Extend PKWM to support user-created wrapping keys
Subsystems (8)
Srish Srinivasan
maintainerv4 cover Extend PKWM to support user-created wrapping keys
The PKWM trusted source currently uses a single default wrapping key per LPAR. This key is created during trusted source initialization, and all trusted keys backed by PKWM are sealed and unsealed using it.
Recent versions of PKWM allow users to create and manage their own wrapping keys through a set of lifecycle operations. This patch series brings these PKWM capabilities into the kernel, allowing users to create, manage, and select wrapping keys for sealing their trusted keys, rather than requiring all trusted keys to use the default wrapping key.
This series extends PKWM to support user-created wrapping keys. It adds the required hcalls, allows users to select a wrapping key by label when creating PKWM-backed trusted keys, and introduces a sysfs interface for managing wrapping keys from userspace.
This patchset also includes six preparatory fixes. These correct double conversion of PLPKS write, remove, and wrapping key flush errors; align wrapping length types with the underlying hcall interfaces; preserve the original error returned when default wrapping key generation fails; initialize PKWM output buffer pointers before cleanup; and clear sensitive PKWM seal and unseal buffers before freeing them.
This series depends on the following PLPKS refactoring and hardening series and must be applied on top of it:
https://lore.kernel.org/all/[email protected]/
Changelog:
v3 -> v4:
- Addressed issues reported by Sashiko
- Fixed double conversion of PLPKS object flush errors
- Initialized PKWM output buffer pointers before cleanup
- Corrected the documented H_PKS_GET_OBJECTLABELS output field order
- Prevented stale policy use and caller data modification during revocation checks
- Fixed wrapping key sysfs kobject cleanup
- Restricted wrapping key sysfs initialization to pseries
- Dropped Tested-by tags from modified patches
v2 -> v3:
- Moved most of the refactoring and hardening patches into a separate series:
https://lore.kernel.org/all/[email protected]/
- Added a fix to clear sensitive PKWM seal and unseal buffers before freeing them
- Added Nageswara's Tested-by tag
- Refined error handling and documented default wrapping key restrictions
v1 -> v2:
- Addressed parameter validation issues reported by Nageswara
- Tweaked PLPKS_WRAPKEY_SYSFS Kconfig help text
- Added two preparatory bug-fix patches
- Cc'd [email protected] where applicable
Srish Srinivasan (9):
pseries/plpks: fix double conversion of write and remove flush errors pseries/plpks: fix double conversion of wrapping key flush errors pseries/plpks: fix length types for wrapping operations keys/trusted_keys: propagate wrapping key generation errors keys/trusted_keys: fix PKWM output buffer cleanup keys/trusted_keys: clear sensitive PKWM buffers pseries/plpks: add HCALLs for PKWM wrapping key life cycle management keys/trusted_keys: enable PKWM wrapping key selection by label pseries/plpks/wrapkey: expose PKWM wrapping key management to
userspace via sysfs
.../ABI/testing/sysfs-firmware-plpks | 116 ++++ Documentation/arch/powerpc/papr_hcalls.rst | 33 ++ .../security/keys/trusted-encrypted.rst | 4 +- arch/powerpc/include/asm/hvcall.h | 5 +- arch/powerpc/include/asm/plpks.h | 40 +- arch/powerpc/platforms/pseries/Kconfig | 15 + arch/powerpc/platforms/pseries/Makefile | 1 + arch/powerpc/platforms/pseries/plpks-sysfs.c | 11 + .../platforms/pseries/plpks-wrapkey-sysfs.c | 408 ++++++++++++++ arch/powerpc/platforms/pseries/plpks.c | 526 ++++++++++++++++-- include/keys/trusted_pkwm.h | 3 + security/keys/trusted-keys/trusted_pkwm.c | 52 +- 12 files changed, 1154 insertions(+), 60 deletions(-) create mode 100644 arch/powerpc/platforms/pseries/plpks-wrapkey-sysfs.c
Signature · 1 line
2.52.0
Srish Srinivasan
maintainerPATCH v4 1/9 pseries/plpks: fix double conversion of write and remove flush errors
plpks_confirm_object_flushed() returns zero or a negative Linux errno. However, plpks_write_var() and plpks_remove_var() pass this return value through pseries_status_to_err(), which treats it as a raw hypervisor status and converts it again.
Convert only errors returned by the write and remove HCALLs, and propagate errors from plpks_confirm_object_flushed() unchanged.
--- arch/powerpc/platforms/pseries/plpks.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/powerpc/platforms/pseries/plpks.c +4 -2
@@ -750,8 +750,9 @@ int plpks_write_var(struct plpks_var var)if (!rc) rc =plpks_confirm_object_flushed (label, auth); +else + rc =pseries_status_to_err (rc); - rc =pseries_status_to_err (rc);kfree (label); out:kfree_sensitive (auth);
@@ -808,8 +809,9 @@ int plpks_remove_var(char *component, u8 varos, struct plpks_var_name vname)if (!rc) rc =plpks_confirm_object_flushed (label, auth); +else + rc =pseries_status_to_err (rc); - rc =pseries_status_to_err (rc);kfree (label); out:kfree_sensitive (auth);
Signature · 1 line
2.52.0
[email protected]
AI reviewRe: [PATCH v4 1/9] pseries/plpks: fix double conversion of write and remove flush errors
Sashiko has reviewed this patch and found no issues.
Quoted 11 lines
plpks_confirm_object_flushed()returns zero or a negative Linux errno. However,plpks_write_var()andplpks_remove_var()pass this return value throughpseries_status_to_err(), which treats it as a raw hypervisor status and converts it again.Convert only errors returned by the write and remove HCALLs, and propagate errors from
plpks_confirm_object_flushed()unchanged.Fixes 2454a7af0f2a ("powerpc/pseries: define driver for Platform KeyStore")Cc [email protected] # 6.0Signed-off-by Srish Srinivasan <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Srish Srinivasan
maintainerPATCH v4 2/9 pseries/plpks: fix double conversion of wrapping key flush errors
In reply to Srish Srinivasanplpks_confirm_object_flushed() returns zero or a negative Linux errno. However, plpks_gen_wrapping_key() passes this return value through pseries_status_to_err(), which treats it as a raw hypervisor status and converts it again.
Convert only errors returned by H_PKS_GEN_KEY, and propagate errors from plpks_confirm_object_flushed() unchanged.
--- arch/powerpc/platforms/pseries/plpks.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
arch/powerpc/platforms/pseries/plpks.c +10 -10
@@ -938,7 +938,7 @@ int plpks_gen_wrapping_key(void)unsigned long retbuf[PLPAR_HCALL_BUFSIZE ] = {0 };struct plpks_auth *auth;struct label *label; -int rc =0 , pseries_status =0 ; +int rc, pseries_status;struct plpks_var var = { .name =PLPKS_DEFAULT_WRAPKEY_LABEL , .namelen =sizeof (PLPKS_DEFAULT_WRAPKEY_LABEL ) -1 ,
@@ -962,17 +962,17 @@ int plpks_gen_wrapping_key(void) label->size, var.policy, NULL, PLPKS_WRAPPING_KEY_LENGTH); -if (!rc) +if (!rc) { rc =plpks_confirm_object_flushed (label, auth); - - 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 ; + pseries_status = rc; + rc =pseries_status_to_err (rc); + +if (rc != -EEXIST ) +pr_err ("H_PKS_GEN_KEY failed. pseries_status=%d, rc=%d" , + pseries_status, rc); +else + rc =0 ; }kfree (label);
Signature · 1 line
2.52.0
[email protected]
AI reviewRe: [PATCH v4 2/9] pseries/plpks: fix double conversion of wrapping key flush errors
Sashiko has reviewed this patch and found no issues.
Quoted 11 lines
plpks_confirm_object_flushed()returns zero or a negative Linux errno. However,plpks_gen_wrapping_key()passes this return value throughpseries_status_to_err(), which treats it as a raw hypervisor status and converts it again.Convert only errors returned by
H_PKS_GEN_KEY, and propagate errors fromplpks_confirm_object_flushed()unchanged.Fixes 133aa79e211d ("pseries/plpks: add HCALLs for PowerVM Key Wrapping Module")Cc [email protected] # 7.0Signed-off-by Srish Srinivasan <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
Srish Srinivasan
maintainerPATCH v4 3/9 pseries/plpks: fix length types for wrapping operations
In reply to Srish SrinivasanThe object wrapping and unwrapping hcalls use 64-bit length values, but plpks_wrap_object() and plpks_unwrap_object() currently use u32 for the input and output length parameters. As a result, the interfaces cannot represent the full range of values supported by the hcalls.
Use u64 for the length parameters to align them with the underlying hcall interfaces. Update the PKWM consumer accordingly.
--- arch/powerpc/include/asm/plpks.h | 8 ++++---- arch/powerpc/platforms/pseries/plpks.c | 8 ++++---- security/keys/trusted-keys/trusted_pkwm.c | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-)
arch/powerpc/include/asm/plpks.h +4 -4
@@ -118,11 +118,11 @@ bool plpks_wrapping_is_supported(void);int plpks_gen_wrapping_key (void ); -int plpks_wrap_object (u8 **input_buf,u32 input_len,u16 wrap_flags, -u8 **output_buf,u32 *output_len); +int plpks_wrap_object (u8 **input_buf,u64 input_len,u16 wrap_flags, +u8 **output_buf,u64 *output_len); -int plpks_unwrap_object (u8 **input_buf,u32 input_len, -u8 **output_buf,u32 *output_len); +int plpks_unwrap_object (u8 **input_buf,u64 input_len, +u8 **output_buf,u64 *output_len);#else // CONFIG_PSERIES_PLPKS static inline bool plpks_is_available (void ) {return false; }static inline u16 plpks_get_passwordlen (void ) {BUILD_BUG (); }
arch/powerpc/platforms/pseries/plpks.c +4 -4
@@ -1023,8 +1023,8 @@ 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,u32 input_len,u16 wrap_flags, -u8 **output_buf,u32 *output_len) +int plpks_wrap_object (u8 **input_buf,u64 input_len,u16 wrap_flags, +u8 **output_buf,u64 *output_len) {unsigned long retbuf[PLPAR_HCALL9_BUFSIZE ] = {0 };struct plpks_auth *auth;
@@ -1142,8 +1142,8 @@ EXPORT_SYMBOL_GPL(plpks_wrap_object);* * Returns: On success 0 is returned, a negative errno if not. */ -int plpks_unwrap_object (u8 **input_buf,u32 input_len,u8 **output_buf, -u32 *output_len) +int plpks_unwrap_object (u8 **input_buf,u64 input_len,u8 **output_buf, +u64 *output_len) {unsigned long retbuf[PLPAR_HCALL9_BUFSIZE ] = {0 };struct plpks_auth *auth;
security/keys/trusted-keys/trusted_pkwm.c +2 -2
@@ -83,7 +83,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 ;u8 *input_buf, *output_buf; -u32 output_len, input_len; +u64 output_len, input_len;int rc; options =trusted_options_alloc ();
@@ -130,7 +130,7 @@ static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob)static int trusted_pkwm_unseal (struct trusted_key_payload *p,char *datablob) {u8 *input_buf, *output_buf; -u32 input_len, output_len; +u64 input_len, output_len;int rc; input_len = p->blob_len;
Signature · 1 line
2.52.0
[email protected]
AI reviewRe: [PATCH v4 3/9] pseries/plpks: fix length types for wrapping operations
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] pseries/plpks: u64 output_len underflow in plpks_unwrap_object() --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] pseries/plpks: u64 output_len underflow in plpks_unwrap_object() --
commit 59911ed0b25c4af265ad691443d2271f507882e0
Author: Srish Srinivasan <[email protected]>
pseries/plpks: fix length types for wrapping operations
This commit updates the input_len and output_len parameters of plpks_wrap_object() and plpks_unwrap_object(), along with their caller in trusted_pkwm.c, from u32 to u64 to match the underlying 64-bit hypercall interfaces.
Quoted 16 lines
arch/powerpc/platforms/pseries/plpks.c +2
-2@@ -1023,8 +1023,8 @@ 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,u32 input_len,u16 wrap_flags, -u8 **output_buf,u32 *output_len) +int plpks_wrap_object (u8 **input_buf,u64 input_len,u16 wrap_flags, +u8 **output_buf,u64 *output_len) {unsigned long retbuf[PLPAR_HCALL9_BUFSIZE ] = {0 };struct plpks_auth *auth;
arch/powerpc/platforms/pseries/plpks.c EXPORT_SYMBOL_GPL(plpks_wrap_object); · line 1149
Quoted 10 lines
arch/powerpc/platforms/pseries/plpks.c +2
-2@@ -1142,8 +1142,8 @@ EXPORT_SYMBOL_GPL(plpks_wrap_object);* * Returns: On success 0 is returned, a negative errno if not. */ -int plpks_unwrap_object (u8 **input_buf,u32 input_len,u8 **output_buf, -u32 *output_len) +int plpks_unwrap_object (u8 **input_buf,u64 input_len,u8 **output_buf, +u64 *output_len) {unsigned long retbuf[PLPAR_HCALL9_BUFSIZE ] = {0 };struct plpks_auth *auth;
[Severity: High]
With input_len and *output_len changed to u64, what happens in plpks_unwrap_object() if input_len is less than or equal to PLPKS_WRAPPING_BUF_DIFF (1024)?
In arch/powerpc/platforms/pseries/plpks.c:plpks_unwrap_object():
*output_len = input_len - PLPKS_WRAPPING_BUF_DIFF; *output_buf = kzalloc(ALIGN(*output_len, PLPKS_WRAPPING_BUF_ALIGN), GFP_KERNEL);
Previously, when *output_len was u32, an underflow produced a 32-bit value such as 0xfffffc00, which promoted to u64 inside ALIGN(..., 4096) and allocated 0x100000000 bytes (failing in kzalloc()).
Now that *output_len is u64, if input_len <= 1024, *output_len underflows to [0xfffffffffffffc00ULL, 0xffffffffffffffffULL] (or 0 when input_len == 1024), and ALIGN(*output_len, 4096) wraps 64-bit arithmetic around to 0.
kzalloc(0, GFP_KERNEL) then returns ZERO_SIZE_PTR ((void *)16), which passes the !(*output_buf) check. Subsequently, virt_to_phys(*output_buf) triggers WARN_ON under CONFIG_DEBUG_VIRTUAL and passes physical address 0x10 along with the underflowed 64-bit *output_len to plpar_hcall9(H_PKS_UNWRAP_OBJECT, ...).
This can be reached from userspace via add_key("trusted", ..., "load <hex>", ...):
trusted_instantiate()
datablob_parse()
trusted_pkwm_unseal()
plpks_unwrap_object()
because datablob_parse() only enforces p->blob_len <= MAX_BLOB_SIZE (1152) and does not enforce a minimum blob length. In addition, in plpks_wrap_object(), PLPKS_WRAPPING_BUF_DIFF is the extra buffer capacity allocated for H_PKS_WRAP_OBJECT, while the actual wrapped blob size comes from retbuf[1], which is not guaranteed to exceed 1024 bytes.
Similarly, in arch/powerpc/platforms/pseries/plpks.c:plpks_wrap_object():
*output_len = input_len + PLPKS_WRAPPING_BUF_DIFF; *output_buf = kzalloc(ALIGN(*output_len, PLPKS_WRAPPING_BUF_ALIGN), GFP_KERNEL);
could input_len + PLPKS_WRAPPING_BUF_DIFF or ALIGN(*output_len, PLPKS_WRAPPING_BUF_ALIGN) overflow u64 if a caller passes a large input_len near U64_MAX?
Should plpks_unwrap_object() and plpks_wrap_object() validate input_len before computing *output_len and allocating *output_buf?
Quoted 4 lines
security/keys/trusted-keys/trusted_pkwm.c +0
-0
[ ... ]
security/keys/trusted-keys/trusted_pkwm.c static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob) · line 136
Quoted 9 lines
security/keys/trusted-keys/trusted_pkwm.c +1
-1@@ -130,7 +130,7 @@ static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob)static int trusted_pkwm_unseal (struct trusted_key_payload *p,char *datablob) {u8 *input_buf, *output_buf; -u32 input_len, output_len; +u64 input_len, output_len;int rc; input_len = p->blob_len;
In trusted_pkwm_unseal(), p->blob_len is assigned directly to input_len and passed to kmalloc(ALIGN(input_len, 4096), GFP_KERNEL) and plpks_unwrap_object() without checking that p->blob_len > PLPKS_WRAPPING_BUF_DIFF (or non-zero, since ALIGN(0, 4096) also results in kmalloc(0) returning ZERO_SIZE_PTR for input_buf).
_________________
AI review your patch. Please Reach out if you have any feedback! Sidharth Seela <[email protected]>
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
Srish Srinivasan
maintainerPATCH v4 4/9 keys/trusted_keys: propagate wrapping key generation errors
In reply to Srish Srinivasanplpks_gen_wrapping_key() returns a negative errno when default wrapping key generation fails. However, trusted_pkwm_init() returns -EINVAL for all such failures, discarding the original error.
Propagate the error returned by plpks_gen_wrapping_key() unchanged.
--- security/keys/trusted-keys/trusted_pkwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/keys/trusted-keys/trusted_pkwm.c +1 -1
@@ -170,7 +170,7 @@ static int trusted_pkwm_init(void) ret =plpks_gen_wrapping_key ();if (ret) {pr_err ("Failed to generate default wrapping key\n" ); -return -EINVAL ; +return ret; }return register_key_type (&key_type_trusted);
Signature · 1 line
2.52.0
[email protected]
AI reviewRe: [PATCH v4 4/9] keys/trusted_keys: propagate wrapping key generation errors
Sashiko has reviewed this patch and found no issues.
Quoted 9 lines
plpks_gen_wrapping_key()returns a negative errno when default wrapping key generation fails. However,trusted_pkwm_init()returns-EINVALfor all such failures, discarding the original error.Propagate the error returned by
plpks_gen_wrapping_key()unchanged.Fixes c99fcb0d735b ("keys/trusted_keys: establish PKWM as a trusted source")Cc [email protected] # 7.0Signed-off-by Srish Srinivasan <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
Srish Srinivasan
maintainerPATCH v4 5/9 keys/trusted_keys: fix PKWM output buffer cleanup
In reply to Srish SrinivasanThe PKWM seal and unseal paths unconditionally free their output buffers, but the PLPKS helpers can return without initializing those pointers.
Initialize the output buffer pointers to NULL to make cleanup safe on early failure paths.
--- security/keys/trusted-keys/trusted_pkwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
security/keys/trusted-keys/trusted_pkwm.c +2 -2
@@ -82,7 +82,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 ; -u8 *input_buf, *output_buf; +u8 *input_buf, *output_buf =NULL ;u64 output_len, input_len;int rc;
@@ -129,7 +129,7 @@ static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob)static int trusted_pkwm_unseal (struct trusted_key_payload *p,char *datablob) { -u8 *input_buf, *output_buf; +u8 *input_buf, *output_buf =NULL ;u64 input_len, output_len;int rc;
Signature · 1 line
2.52.0
[email protected]
AI reviewRe: [PATCH v4 5/9] keys/trusted_keys: fix PKWM output buffer cleanup
Sashiko has reviewed this patch and found no issues.
Quoted 9 lines
The PKWM seal and unseal paths unconditionally free their output buffers, but the PLPKS helpers can return without initializing those pointers.
Initialize the output buffer pointers to NULL to make cleanup safe on early failure paths.
Fixes c99fcb0d735b ("keys/trusted_keys: establish PKWM as a trusted source")Cc [email protected] # 7.0Signed-off-by Srish Srinivasan <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
Srish Srinivasan
maintainerPATCH v4 6/9 keys/trusted_keys: clear sensitive PKWM buffers
In reply to Srish SrinivasanThe input buffer to PKWM seal and the output buffer from PKWM unseal contain plaintext trusted-key payload data. Freeing these buffers with kfree(), without wiping the contents, can leave sensitive key material in memory.
Use kfree_sensitive() to wipe the sensitive key material when freeing these buffers.
--- security/keys/trusted-keys/trusted_pkwm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
security/keys/trusted-keys/trusted_pkwm.c +2 -2
@@ -118,7 +118,7 @@ static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob)pr_err ("Wrapping of payload key failed: %d\n" , rc); } -kfree (input_buf); +kfree_sensitive (input_buf);kfree (output_buf); out:
@@ -153,7 +153,7 @@ static int trusted_pkwm_unseal(struct trusted_key_payload *p, char *datablob) }kfree (input_buf); -kfree (output_buf); +kfree_sensitive (output_buf);return rc; }
Signature · 1 line
2.52.0
[email protected]
AI reviewRe: [PATCH v4 6/9] keys/trusted_keys: clear sensitive PKWM buffers
Sashiko has reviewed this patch and found no issues.
Quoted 11 lines
The input buffer to PKWM seal and the output buffer from PKWM unseal contain plaintext trusted-key payload data. Freeing these buffers with
kfree(), without wiping the contents, can leave sensitive key material in memory.Use
kfree_sensitive()to wipe the sensitive key material when freeing these buffers.Fixes c99fcb0d735b ("keys/trusted_keys: establish PKWM as a trusted source")Cc [email protected] # 7.0Signed-off-by Srish Srinivasan <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
Srish Srinivasan
maintainerPATCH v4 7/9 pseries/plpks: add HCALLs for PKWM wrapping key life cycle management
In reply to Srish SrinivasanThe PKWM trusted source uses a single wrapping key per LPAR, created only once during trust source initialization. All the wrap and unwrap requests are bound to this default wrapping key.
Implement H_PKS_REVOKE_OBJECT, H_PKS_UNREVOKE_OBJECT, and H_PKS_GET_OBJECTLABELS HCALLs to enable support for revoking and unrevoking PKWM wrapping keys, and for retrieving wrapping key labels. The label retrieval operation (H_PKS_GET_OBJECTLABELS) applies to all wrapping keys including the default one, while the life cycle operations (H_PKS_REVOKE_OBJECT/H_PKS_UNREVOKE_OBJECT) apply only to user-created wrapping keys.
--- Documentation/arch/powerpc/papr_hcalls.rst | 33 ++ arch/powerpc/include/asm/hvcall.h | 5 +- arch/powerpc/include/asm/plpks.h | 15 + arch/powerpc/platforms/pseries/plpks.c | 455 ++++++++++++++++++++- 4 files changed, 504 insertions(+), 4 deletions(-)
Documentation/arch/powerpc/papr_hcalls.rst +33 -0
@@ -343,6 +343,39 @@ is returned to the caller. H_PKS_UNWRAP_OBJECT is used to unwrap an object that was previously wrapped with H_PKS_WRAP_OBJECT. +**H_PKS_REVOKE_OBJECT** + +| Input: authorization, objectlabel, objectlabellen, flags +| Out: *object policy* +| Return Value: *H_Success, H_Function, H_State, H_Parameter, H_P2, H_P3, H_P4, + H_Authority, H_Not_Found, H_Busy, H_Aborted* + +H_PKS_REVOKE_OBJECT is used to revoke an object in Platform Keystore. + + +**H_PKS_UNREVOKE_OBJECT** + +| Input: authorization, objectlabel, objectlabellen, flags +| Out: *object policy* +| Return Value: *H_Success, H_Function, H_State, H_Parameter, H_P2, H_P3, H_P4, + H_Authority, H_Not_Found, H_Busy, H_Aborted* + +H_PKS_UNREVOKE_OBJECT is used to unrevoke an object that was previously revoked +with H_PKS_REVOKE_OBJECT in Platform Keystore. + + +**H_PKS_GET_OBJECTLABELS** + +| Input: authorization, continueToken, out, outlen +| Out: *number of object labels in the returned list, continue-token, object + label list* +| Return Value: *H_Success, H_Function, H_State, H_Parameter, H_P2, H_P3, H_P4, + H_Authority, H_Busy, H_Aborted, H_Continue* + +H_PKS_GET_OBJECTLABELS is used to retrieve a list of object labels owned by the +specified consumer. + + References ========== .. [1] "Power Architecture Platform Reference"
arch/powerpc/include/asm/hvcall.h +4 -1
@@ -340,6 +340,7 @@#define H_PKS_GET_CONFIG 0x41C#define H_PKS_SET_PASSWORD 0x420#define H_PKS_GEN_PASSWORD 0x424 +#define H_PKS_GET_OBJECTLABELS 0x428#define H_PKS_WRITE_OBJECT 0x42C#define H_PKS_GEN_KEY 0x430#define H_PKS_READ_OBJECT 0x434
@@ -362,7 +363,9 @@#define H_GUEST_DELETE 0x488#define H_PKS_WRAP_OBJECT 0x490#define H_PKS_UNWRAP_OBJECT 0x494 -#define MAX_HCALL_OPCODE H_PKS_UNWRAP_OBJECT +#define H_PKS_REVOKE_OBJECT 0x4AC +#define H_PKS_UNREVOKE_OBJECT 0x4B0 +#define MAX_HCALL_OPCODE H_PKS_UNREVOKE_OBJECT/* Scope args for H_SCM_UNBIND_ALL */ #define H_UNBIND_SCOPE_ALL (0x1)
arch/powerpc/include/asm/plpks.h +15 -0
@@ -25,6 +25,7 @@#define PLPKS_SIGNEDUPDATE PPC_BIT32(7) // Object can only be modified by signed updates#define PLPKS_WRAPPINGKEY PPC_BIT32(8) // Object contains a wrapping key#define PLPKS_HVPROVISIONED PPC_BIT32(28) // Hypervisor has provisioned this object +#define PLPKS_REVOKED PPC_BIT32(30) // Object is revoked// Signature algorithm flags from signed_update_algorithms #define PLPKS_ALG_RSA2048 PPC_BIT(0)
@@ -123,6 +124,20 @@ int plpks_wrap_object(u8 **input_buf, u64 input_len, u16 wrap_flags,int plpks_unwrap_object (u8 **input_buf,u64 input_len,u8 **output_buf,u64 *output_len); + +int plpks_revoke_wrapping_key (struct plpks_var *var); + +int plpks_unrevoke_wrapping_key (struct plpks_var *var); + +int plpks_del_wrapping_key (struct plpks_var *var); + +int plpks_is_wrapping_key_revoked (const struct plpks_var *var); + +int plpks_get_object_labels (u8 **output_buf,u64 *output_len, +char *comp_prefix); + +bool plpks_revoke_is_supported (void ); +#else // CONFIG_PSERIES_PLPKS static inline bool plpks_is_available (void ) {return false; }static inline u16 plpks_get_passwordlen (void ) {BUILD_BUG (); }
arch/powerpc/platforms/pseries/plpks.c +452 -3
505 lines not on this page · raw message
Signature · 1 line
2.52.0
[email protected]
AI reviewRe: [PATCH v4 7/9] pseries/plpks: add HCALLs for PKWM wrapping key life cycle management
Sashiko has reviewed this patch and found no issues.
Quoted 12 lines
The PKWM trusted source uses a single wrapping key per LPAR, created only once during trust source initialization. All the wrap and unwrap requests are bound to this default wrapping key.
Implement
H_PKS_REVOKE_OBJECT,H_PKS_UNREVOKE_OBJECT, andH_PKS_GET_OBJECTLABELSHCALLs to enable support for revoking and unrevoking PKWM wrapping keys, and for retrieving wrapping key labels. The label retrieval operation (H_PKS_GET_OBJECTLABELS) applies to all wrapping keys including the default one, while the life cycle operations (H_PKS_REVOKE_OBJECT/H_PKS_UNREVOKE_OBJECT) apply only to user-created wrapping keys.
Quoted 1 line
Signed-off-by Srish Srinivasan <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7
Srish Srinivasan
maintainerPATCH v4 8/9 keys/trusted_keys: enable PKWM wrapping key selection by label
In reply to Srish SrinivasanThe 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.
--- .../security/keys/trusted-encrypted.rst | 4 +- arch/powerpc/include/asm/plpks.h | 10 ++++- arch/powerpc/platforms/pseries/plpks.c | 44 ++++++++----------- include/keys/trusted_pkwm.h | 3 ++ security/keys/trusted-keys/trusted_pkwm.c | 38 ++++++++++++++-- 5 files changed, 66 insertions(+), 33 deletions(-)
Documentation/security/keys/trusted-encrypted.rst +3 -1
@@ -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
arch/powerpc/include/asm/plpks.h +8 -2
@@ -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);
arch/powerpc/platforms/pseries/plpks.c +18 -26
118 lines not on this page · raw message
include/keys/trusted_pkwm.h +3 -0
@@ -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)
security/keys/trusted-keys/trusted_pkwm.c +34 -4
@@ -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 ; }
@@ -83,6 +91,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 ;u8 *input_buf, *output_buf =NULL ; +struct plpks_var var = {0 };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,15 +180,26 @@ 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) { -pr_err ("Failed to generate default wrapping key\n" ); + 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); + +/* An existing default wrapping key is considered success. */ +if (ret && ret != -EEXIST ) { +pr_err ("Failed to generate default wrapping key: %d\n" , ret);return ret; }
Signature · 1 line
2.52.0
[email protected]
AI reviewRe: [PATCH v4 8/9] keys/trusted_keys: enable PKWM wrapping key selection by label
Sashiko has reviewed this patch and found no issues.
Quoted 10 lines
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 <[email protected]>
Sashiko has reviewed this patch and found no issues.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=8
Srish Srinivasan
maintainerPATCH v4 9/9 pseries/plpks/wrapkey: expose PKWM wrapping key management to userspace via sysfs
In reply to Srish SrinivasanThe PKWM trusted source currently uses a single default wrapping key created during initialization. However, PKWM also supports user-created wrapping keys for better isolation between trusted keys.
Expose wrapping key lifecycle operations through sysfs to allow users to create and manage their own wrapping keys.
Create a sysfs interface at /sys/firmware/plpks/wrapkey with the following attributes:
create - Create a new wrapping key with a user-provided label delete - Delete a revoked wrapping key by label revoke - Revoke a wrapping key by label unrevoke - Unrevoke a previously revoked wrapping key by label list_active - List labels of all active (non-revoked) wrapping keys list_revoked - List labels of all revoked wrapping keys
User-provided labels are validated to contain only alphanumeric characters.
Wrapping key lifecycle constraints:
- A wrapping key must be revoked before it can be deleted
- Revoked wrapping keys cannot be used for wrap operations until unrevoked
- The default wrapping key cannot be revoked or deleted; it always appears in list_active
The wrapping keys themselves are confidential objects stored in PLPKS. Only the user-provided labels are exposed to userspace for identification and management purposes.
These user-created wrapping keys can be used in seal operations via the wrapping_key=<label> option.
--- .../ABI/testing/sysfs-firmware-plpks | 116 +++++ arch/powerpc/include/asm/plpks.h | 9 + arch/powerpc/platforms/pseries/Kconfig | 15 + arch/powerpc/platforms/pseries/Makefile | 1 + arch/powerpc/platforms/pseries/plpks-sysfs.c | 11 + .../platforms/pseries/plpks-wrapkey-sysfs.c | 408 ++++++++++++++++++ arch/powerpc/platforms/pseries/plpks.c | 1 - 7 files changed, 560 insertions(+), 1 deletion(-) create mode 100644 arch/powerpc/platforms/pseries/plpks-wrapkey-sysfs.c
Documentation/ABI/testing/sysfs-firmware-plpks +116 -0
@@ -56,3 +56,119 @@ Description: Bitmask of the wrapping features indicating the wrapping algorithms that are supported for the H_PKS_WRAP_OBJECT requests , represented as a 8 byte hexadecimal ASCII string. Consult the hypervisor documentation for what these flags mean. + +What: /sys/firmware/plpks/wrapkey +Date: August 2026 +Contact: Srish Srinivasan <[email protected]> +Description: This directory provides the interface for creating and managing + user-created PKWM wrapping keys. + + The directory is present only when CONFIG_PLPKS_WRAPKEY_SYSFS is + enabled and the system supports the H_PKS_{UN}REVOKE_OBJECT + interfaces. + + Only alphanumeric characters are accepted in wrapping key + labels. The wrapping keys themselves are confidential PLPKS + objects and are not exposed to userspace. Only their labels are + exposed for identification and management. + + Each write is processed as an independent operation and accepts + exactly one wrapping key label. The resulting state can be + verified through list_active or list_revoked, as appropriate. + + The default wrapping key, named "default-wrapping-key", cannot + be created, revoked, unrevoked, or deleted through this + interface. + +What: /sys/firmware/plpks/wrapkey/create +Date: August 2026 +Contact: Srish Srinivasan <[email protected]> +Description: (WO) Create a wrapping key with the specified label, except + "default-wrapping-key", which is reserved for the default + wrapping key. + + On success, the label appears in list_active. + + For example, to create a wrapping key labelled "wk1": + + echo -n wk1 > /sys/firmware/plpks/wrapkey/create + + or: + + printf '%s' 'wk1' > /sys/firmware/plpks/wrapkey/create + +What: /sys/firmware/plpks/wrapkey/delete +Date: August 2026 +Contact: Srish Srinivasan <[email protected]> +Description: (WO) Delete a revoked wrapping key identified by the specified + label. A wrapping key must be revoked before it can be deleted. + The default wrapping key, named "default-wrapping-key", cannot + be deleted. + + On success, the label no longer appears in list_revoked. + + For example, to delete a revoked wrapping key labelled "wk1": + + echo -n wk1 > /sys/firmware/plpks/wrapkey/delete + + or: + + printf '%s' 'wk1' > /sys/firmware/plpks/wrapkey/delete + +What: /sys/firmware/plpks/wrapkey/revoke +Date: August 2026 +Contact: Srish Srinivasan <[email protected]> +Description: (WO) Revoke a wrapping key identified by the specified label. A + revoked wrapping key cannot be used for seal or unseal + operations until it is unrevoked. The default wrapping key, + named "default-wrapping-key", cannot be revoked. + + On success, the label appears in list_revoked and no longer + appears in list_active. + + For example, to revoke a wrapping key labelled "wk1": + + echo -n wk1 > /sys/firmware/plpks/wrapkey/revoke + + or: + + printf '%s' 'wk1' > /sys/firmware/plpks/wrapkey/revoke + +What: /sys/firmware/plpks/wrapkey/unrevoke +Date: August 2026 +Contact: Srish Srinivasan <[email protected]> +Description: (WO) Unrevoke a revoked wrapping key identified by the specified + label. The default wrapping key, named "default-wrapping-key", + cannot be unrevoked through this interface because it cannot be + revoked. + + On success, the label appears in list_active and no longer + appears in list_revoked. + + For example, to unrevoke a revoked wrapping key labelled "wk1": + + echo -n wk1 > /sys/firmware/plpks/wrapkey/unrevoke + + or: + + printf '%s' 'wk1' > /sys/firmware/plpks/wrapkey/unrevoke + +What: /sys/firmware/plpks/wrapkey/list_active +Date: August 2026 +Contact: Srish Srinivasan <[email protected]> +Description: (RO) List the labels of active, non-revoked wrapping keys. The + default wrapping key, named "default-wrapping-key", is always + included in this list. + + For example: + + cat /sys/firmware/plpks/wrapkey/list_active + +What: /sys/firmware/plpks/wrapkey/list_revoked +Date: August 2026 +Contact: Srish Srinivasan <[email protected]> +Description: (RO) List the labels of revoked wrapping keys. + + For example: + + cat /sys/firmware/plpks/wrapkey/list_revoked
arch/powerpc/include/asm/plpks.h +9 -0
@@ -56,6 +56,8 @@// Component for a PKWM wrapping key #define PLPKS_WRAPKEY_COMPONENT "PLPKSWR" +#define PLPKS_OBJLABEL_LEN_FIELD_SIZE 2 +struct plpks_var {char *component;u8 *name;
@@ -144,6 +146,9 @@ int plpks_get_object_labels(u8 **output_buf, u64 *output_len,bool plpks_revoke_is_supported (void ); +int plpks_init_child_kobj (struct kobject *kobj,const struct kobj_type *ktype, +const char *name); +#else // CONFIG_PSERIES_PLPKS static inline bool plpks_is_available (void ) {return false; }static inline u16 plpks_get_passwordlen (void ) {BUILD_BUG (); }
@@ -151,6 +156,10 @@ static inline void plpks_early_init_devtree(void) { }static inline int plpks_populate_fdt (void *fdt) {BUILD_BUG (); }static inline int plpks_config_create_softlink (struct kobject *from) {return 0 ; } +static inline int plpks_init_child_kobj (struct kobject *kobj, +const struct kobj_type *ktype, +const char *name) + {return 0 ; }#endif // CONFIG_PSERIES_PLPKS #endif // _ASM_POWERPC_PLPKS_H
arch/powerpc/platforms/pseries/Kconfig +15 -0
@@ -216,3 +216,18 @@ config PPC_SVM those guests. If unsure, say "N". + +config PLPKS_WRAPKEY_SYSFS + bool "Enable sysfs interface for managing PKWM wrapping keys" + default n + depends on PSERIES_PLPKS + depends on SYSFS + depends on TRUSTED_KEYS_PKWM + help + The PKWM trusted source supports user-created wrapping keys that are + managed by the OS. These wrapping keys can be created, revoked, + unrevoked, and deleted through sysfs. Their labels can also be viewed + through sysfs. + + Say Y if PLPKS and PKWM are enabled and you want to isolate trusted + keys using user-created wrapping keys.
arch/powerpc/platforms/pseries/Makefile +1 -0
@@ -33,6 +33,7 @@ obj-$(CONFIG_FA_DUMP) += rtas-fadump.o obj-$(CONFIG_PSERIES_PLPKS) += plpks.o plpks-sysfs.o obj-$(CONFIG_PPC_SECURE_BOOT) += plpks-secvar.o obj-$(CONFIG_PSERIES_PLPKS_SED) += plpks_sed_ops.o +obj-$(CONFIG_PLPKS_WRAPKEY_SYSFS) += plpks-wrapkey-sysfs.o obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_PPC_VAS) += vas.o vas-sysfs.o
arch/powerpc/platforms/pseries/plpks-sysfs.c +11 -0
@@ -55,6 +55,17 @@ static umode_t plpks_config_attr_is_visible(struct kobject *kobj,return attr->mode; } +int plpks_init_child_kobj (struct kobject *kobj,const struct kobj_type *ktype, +const char *name) +{ +kobject_init (kobj, ktype); + +if (!plpks_kobj) +return -ENODEV ; + +return kobject_add (kobj, plpks_kobj,"%s" , name); +} +int plpks_config_create_softlink (struct kobject *from) {if (!plpks_config_kobj)
arch/powerpc/platforms/pseries/plpks-wrapkey-sysfs.c new file +408 -0
408 lines not on this page · raw message
arch/powerpc/platforms/pseries/plpks.c +0 -1
@@ -28,7 +28,6 @@#define PLPKS_OBJLABEL_BUF_SIZE \ roundup_pow_of_two(PLPKS_OBJLABEL_BUF_BASE_SIZE) -#define PLPKS_OBJLABEL_LEN_FIELD_SIZE 2#define PLPKS_OBJLABEL_PREFIX_LEN 8#define PLPKS_WRAP_INTERFACE_BIT 3
Signature · 1 line
2.52.0
[email protected]
AI reviewRe: [PATCH v4 9/9] pseries/plpks/wrapkey: expose PKWM wrapping key management to userspace via sysfs
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Medium] powerpc/pseries/plpks: use-after-free of plpks_kobj in plpks_init_child_kobj() - [Medium]…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] powerpc/pseries/plpks: use-after-free of plpks_kobj in plpks_init_child_kobj()
- [Medium] powerpc/pseries: wrapkey_sysfs_init() does not ensure default key exists --
commit 81ec5557b710c94f51afed01c64f4716ffcf0140
Author: Srish Srinivasan <[email protected]>
pseries/plpks/wrapkey: expose PKWM wrapping key management to userspace via sysfs
This commit adds a sysfs interface under /sys/firmware/plpks/wrapkey to allow userspace to create, revoke, unrevoke, delete, and list PKWM wrapping keys by label.
Quoted 4 lines
Documentation/ABI/testing/sysfs-firmware-plpks +0
-0
[ ... ]
Quoted 10 lines
Documentation/ABI/testing/sysfs-firmware-plpks +10
-0+What: /sys/firmware/plpks/wrapkey/list_active +Date: August 2026 +Contact: Srish Srinivasan <[email protected]> +Description: (RO) List the labels of active, non-revoked wrapping keys. The + default wrapping key, named "default-wrapping-key", is always + included in this list. + + For example: + + cat /sys/firmware/plpks/wrapkey/list_active
[ ... ]
Quoted 23 lines
arch/powerpc/platforms/pseries/Kconfig +15
-0@@ -215,3 +215,18 @@ config PPC_SVM those guests. If unsure, say "N". + +config PLPKS_WRAPKEY_SYSFS + bool "Enable sysfs interface for managing PKWM wrapping keys" + default n + depends on PSERIES_PLPKS + depends on SYSFS + depends on TRUSTED_KEYS_PKWM + help + The PKWM trusted source supports user-created wrapping keys that are + managed by the OS. These wrapping keys can be created, revoked, + unrevoked, and deleted through sysfs. Their labels can also be viewed + through sysfs. + + Say Y if PLPKS and PKWM are enabled and you want to isolate trusted + keys using user-created wrapping keys.
[ ... ]
Quoted 12 lines
arch/powerpc/platforms/pseries/plpks-sysfs.c +4
-0@@ -55,6 +55,17 @@ static umode_t plpks_config_attr_is_visible(struct kobject *kobj,return attr->mode; } +int plpks_init_child_kobj (struct kobject *kobj,const struct kobj_type *ktype, +const char *name) +{ +kobject_init (kobj, ktype);
arch/powerpc/platforms/pseries/plpks-sysfs.c static umode_t plpks_config_attr_is_visible(struct kobject *kobj, · line 71
Quoted 10 lines
arch/powerpc/platforms/pseries/plpks-sysfs.c +7
-0+ +if (!plpks_kobj) +return -ENODEV ; + +return kobject_add (kobj, plpks_kobj,"%s" , name); +} +int plpks_config_create_softlink (struct kobject *from) {if (!plpks_config_kobj)
[Severity: Medium]
Can plpks_init_child_kobj() dereference a freed plpks_kobj if plpks_sysfs_init() fails after creating plpks_kobj?
In arch/powerpc/platforms/pseries/plpks-sysfs.c:plpks_sysfs_init():
plpks_config_kobj = kobject_create_and_add("config", plpks_kobj);
if (!plpks_config_kobj) {
pr_err("Failed to create plpks config kobj\n");
kobject_put(plpks_kobj);
return -ENOMEM;
}
rc = plpks_sysfs_config(plpks_config_kobj);
if (rc) {
pr_err("Failed to create attribute group for plpks config\n");
kobject_put(plpks_config_kobj);
kobject_put(plpks_kobj);
return rc;
}If either of those steps fails during machine_subsys_initcall, kobject_put() frees plpks_kobj without resetting the static pointer to NULL. When wrapkey_sysfs_init() later runs at machine_late_initcall and calls plpks_init_child_kobj(), the !plpks_kobj check passes and kobject_add() operates on the dangling plpks_kobj pointer.
Quoted 5 lines
arch/powerpc/platforms/pseries/plpks-wrapkey-sysfs.c new file +0
-0
[ ... ]
Quoted 14 lines
arch/powerpc/platforms/pseries/plpks-wrapkey-sysfs.c new file +14
-0+static __init int wrapkey_sysfs_init (void ) +{ +int rc; + +if (!plpks_revoke_is_supported ()) { +pr_err ("H_PKS_{UN}REVOKE_OBJECT interface not supported\n" ); +return -ENODEV ; + } + + wrapkey_kobj =kzalloc_obj (*wrapkey_kobj); +if (!wrapkey_kobj) +return -ENOMEM ; + + rc =plpks_init_child_kobj (wrapkey_kobj, &wrapkey_ktype,"wrapkey" );
arch/powerpc/platforms/pseries/plpks-wrapkey-sysfs.c line 408
Quoted 10 lines
arch/powerpc/platforms/pseries/plpks-wrapkey-sysfs.c new file +10
-0+ +if (rc) { +kobject_put (wrapkey_kobj); + wrapkey_kobj =NULL ; + } + +return rc; +} + +machine_late_initcall (pseries, wrapkey_sysfs_init);
[Severity: Medium]
Is "default-wrapping-key" guaranteed to exist in PLPKS when wrapkey_sysfs_init() exposes /sys/firmware/plpks/wrapkey?
Both the commit message and Documentation/ABI/testing/sysfs-firmware-plpks state that "default-wrapping-key" is always included in list_active, and create_store() rejects "default-wrapping-key" with -EEXIST.
However, "default-wrapping-key" is only generated in security/keys/trusted-keys/trusted_pkwm.c:trusted_pkwm_init():
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);
Because CONFIG_PLPKS_WRAPKEY_SYSFS is a bool while CONFIG_TRUSTED_KEYS is tristate, wrapkey_sysfs_init() runs at machine_late_initcall even when trusted.ko has not been loaded, or when init_trusted() selects another trusted key source (such as TPM) earlier in trusted_key_sources[]. On a fresh LPAR where trusted_pkwm_init() has not run, won't reading list_active omit "default-wrapping-key" while writing "default-wrapping-key" to create fails with -EEXIST?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=9