Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

keys/trusted_keys: establish PKWM as a trusted source

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=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 required 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@linux.ibm.com>
Tested-by: Nayna Jain <nayna@linux.ibm.com>
Reviewed-by: Mimi Zohar <zohar@linux.ibm.com>
Reviewed-by: Nayna Jain <nayna@linux.ibm.com>
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20260127145228.48320-6-ssrish@linux.ibm.com

authored by

Srish Srinivasan and committed by
Madhavan Srinivasan
c99fcb0d 133aa79e

+253 -2
+9
MAINTAINERS
··· 14003 14003 F: include/keys/trusted_dcp.h 14004 14004 F: security/keys/trusted-keys/trusted_dcp.c 14005 14005 14006 + KEYS-TRUSTED-PLPKS 14007 + M: Srish Srinivasan <ssrish@linux.ibm.com> 14008 + M: Nayna Jain <nayna@linux.ibm.com> 14009 + L: linux-integrity@vger.kernel.org 14010 + L: keyrings@vger.kernel.org 14011 + S: Supported 14012 + F: include/keys/trusted_pkwm.h 14013 + F: security/keys/trusted-keys/trusted_pkwm.c 14014 + 14006 14015 KEYS-TRUSTED-TEE 14007 14016 M: Sumit Garg <sumit.garg@kernel.org> 14008 14017 L: linux-integrity@vger.kernel.org
+6 -1
include/keys/trusted-type.h
··· 19 19 20 20 #define MIN_KEY_SIZE 32 21 21 #define MAX_KEY_SIZE 128 22 - #define MAX_BLOB_SIZE 512 22 + #if IS_ENABLED(CONFIG_TRUSTED_KEYS_PKWM) 23 + #define MAX_BLOB_SIZE 1152 24 + #else 25 + #define MAX_BLOB_SIZE 512 26 + #endif 23 27 #define MAX_PCRINFO_SIZE 64 24 28 #define MAX_DIGEST_SIZE 64 25 29 ··· 50 46 uint32_t policydigest_len; 51 47 unsigned char policydigest[MAX_DIGEST_SIZE]; 52 48 uint32_t policyhandle; 49 + void *private; 53 50 }; 54 51 55 52 struct trusted_key_ops {
+33
include/keys/trusted_pkwm.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #ifndef __PKWM_TRUSTED_KEY_H 3 + #define __PKWM_TRUSTED_KEY_H 4 + 5 + #include <keys/trusted-type.h> 6 + #include <linux/bitops.h> 7 + #include <linux/printk.h> 8 + 9 + extern struct trusted_key_ops pkwm_trusted_key_ops; 10 + 11 + struct trusted_pkwm_options { 12 + u16 wrap_flags; 13 + }; 14 + 15 + static inline void dump_options(struct trusted_key_options *o) 16 + { 17 + const struct trusted_pkwm_options *pkwm; 18 + bool sb_audit_or_enforce_bit; 19 + bool sb_enforce_bit; 20 + 21 + pkwm = o->private; 22 + sb_audit_or_enforce_bit = pkwm->wrap_flags & BIT(0); 23 + sb_enforce_bit = pkwm->wrap_flags & BIT(1); 24 + 25 + if (sb_audit_or_enforce_bit) 26 + pr_debug("secure boot mode required: audit or enforce"); 27 + else if (sb_enforce_bit) 28 + pr_debug("secure boot mode required: enforce"); 29 + else 30 + pr_debug("secure boot mode required: disabled"); 31 + } 32 + 33 + #endif
+8
security/keys/trusted-keys/Kconfig
··· 46 46 help 47 47 Enable use of NXP's DCP (Data Co-Processor) as trusted key backend. 48 48 49 + config TRUSTED_KEYS_PKWM 50 + bool "PKWM-based trusted keys" 51 + depends on PSERIES_PLPKS >= TRUSTED_KEYS 52 + default y 53 + select HAVE_TRUSTED_KEYS 54 + help 55 + Enable use of IBM PowerVM Key Wrapping Module (PKWM) as a trusted key backend. 56 + 49 57 if !HAVE_TRUSTED_KEYS 50 58 comment "No trust source selected!" 51 59 endif
+2
security/keys/trusted-keys/Makefile
··· 16 16 trusted-$(CONFIG_TRUSTED_KEYS_CAAM) += trusted_caam.o 17 17 18 18 trusted-$(CONFIG_TRUSTED_KEYS_DCP) += trusted_dcp.o 19 + 20 + trusted-$(CONFIG_TRUSTED_KEYS_PKWM) += trusted_pkwm.o
+5 -1
security/keys/trusted-keys/trusted_core.c
··· 12 12 #include <keys/trusted_caam.h> 13 13 #include <keys/trusted_dcp.h> 14 14 #include <keys/trusted_tpm.h> 15 + #include <keys/trusted_pkwm.h> 15 16 #include <linux/capability.h> 16 17 #include <linux/err.h> 17 18 #include <linux/init.h> ··· 32 31 33 32 static char *trusted_key_source; 34 33 module_param_named(source, trusted_key_source, charp, 0); 35 - MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam or dcp)"); 34 + MODULE_PARM_DESC(source, "Select trusted keys source (tpm, tee, caam, dcp or pkwm)"); 36 35 37 36 static const struct trusted_key_source trusted_key_sources[] = { 38 37 #if defined(CONFIG_TRUSTED_KEYS_TPM) ··· 46 45 #endif 47 46 #if defined(CONFIG_TRUSTED_KEYS_DCP) 48 47 { "dcp", &dcp_trusted_key_ops }, 48 + #endif 49 + #if defined(CONFIG_TRUSTED_KEYS_PKWM) 50 + { "pkwm", &pkwm_trusted_key_ops }, 49 51 #endif 50 52 }; 51 53
+190
security/keys/trusted-keys/trusted_pkwm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2025 IBM Corporation, Srish Srinivasan <ssrish@linux.ibm.com> 4 + */ 5 + 6 + #include <keys/trusted_pkwm.h> 7 + #include <keys/trusted-type.h> 8 + #include <linux/build_bug.h> 9 + #include <linux/key-type.h> 10 + #include <linux/parser.h> 11 + #include <asm/plpks.h> 12 + 13 + enum { 14 + Opt_err, 15 + Opt_wrap_flags, 16 + }; 17 + 18 + static const match_table_t key_tokens = { 19 + {Opt_wrap_flags, "wrap_flags=%s"}, 20 + {Opt_err, NULL} 21 + }; 22 + 23 + static int getoptions(char *datablob, struct trusted_key_options *opt) 24 + { 25 + substring_t args[MAX_OPT_ARGS]; 26 + char *p = datablob; 27 + int token; 28 + int res; 29 + u16 wrap_flags; 30 + unsigned long token_mask = 0; 31 + struct trusted_pkwm_options *pkwm; 32 + 33 + if (!datablob) 34 + return 0; 35 + 36 + pkwm = opt->private; 37 + 38 + while ((p = strsep(&datablob, " \t"))) { 39 + if (*p == '\0' || *p == ' ' || *p == '\t') 40 + continue; 41 + 42 + token = match_token(p, key_tokens, args); 43 + if (test_and_set_bit(token, &token_mask)) 44 + return -EINVAL; 45 + 46 + switch (token) { 47 + case Opt_wrap_flags: 48 + res = kstrtou16(args[0].from, 16, &wrap_flags); 49 + if (res < 0 || wrap_flags > 2) 50 + return -EINVAL; 51 + pkwm->wrap_flags = wrap_flags; 52 + break; 53 + default: 54 + return -EINVAL; 55 + } 56 + } 57 + return 0; 58 + } 59 + 60 + static struct trusted_key_options *trusted_options_alloc(void) 61 + { 62 + struct trusted_key_options *options; 63 + struct trusted_pkwm_options *pkwm; 64 + 65 + options = kzalloc(sizeof(*options), GFP_KERNEL); 66 + 67 + if (options) { 68 + pkwm = kzalloc(sizeof(*pkwm), GFP_KERNEL); 69 + 70 + if (!pkwm) { 71 + kfree_sensitive(options); 72 + options = NULL; 73 + } else { 74 + options->private = pkwm; 75 + } 76 + } 77 + 78 + return options; 79 + } 80 + 81 + static int trusted_pkwm_seal(struct trusted_key_payload *p, char *datablob) 82 + { 83 + struct trusted_key_options *options = NULL; 84 + struct trusted_pkwm_options *pkwm = NULL; 85 + u8 *input_buf, *output_buf; 86 + u32 output_len, input_len; 87 + int rc; 88 + 89 + options = trusted_options_alloc(); 90 + 91 + if (!options) 92 + return -ENOMEM; 93 + 94 + rc = getoptions(datablob, options); 95 + if (rc < 0) 96 + goto out; 97 + dump_options(options); 98 + 99 + input_len = p->key_len; 100 + input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL); 101 + if (!input_buf) { 102 + pr_err("Input buffer allocation failed. Returning -ENOMEM."); 103 + rc = -ENOMEM; 104 + goto out; 105 + } 106 + 107 + memcpy(input_buf, p->key, p->key_len); 108 + 109 + pkwm = options->private; 110 + 111 + rc = plpks_wrap_object(&input_buf, input_len, pkwm->wrap_flags, 112 + &output_buf, &output_len); 113 + if (!rc) { 114 + memcpy(p->blob, output_buf, output_len); 115 + p->blob_len = output_len; 116 + dump_payload(p); 117 + } else { 118 + pr_err("Wrapping of payload key failed: %d\n", rc); 119 + } 120 + 121 + kfree(input_buf); 122 + kfree(output_buf); 123 + 124 + out: 125 + kfree_sensitive(options->private); 126 + kfree_sensitive(options); 127 + return rc; 128 + } 129 + 130 + static int trusted_pkwm_unseal(struct trusted_key_payload *p, char *datablob) 131 + { 132 + u8 *input_buf, *output_buf; 133 + u32 input_len, output_len; 134 + int rc; 135 + 136 + input_len = p->blob_len; 137 + input_buf = kmalloc(ALIGN(input_len, 4096), GFP_KERNEL); 138 + if (!input_buf) { 139 + pr_err("Input buffer allocation failed. Returning -ENOMEM."); 140 + return -ENOMEM; 141 + } 142 + 143 + memcpy(input_buf, p->blob, p->blob_len); 144 + 145 + rc = plpks_unwrap_object(&input_buf, input_len, &output_buf, 146 + &output_len); 147 + if (!rc) { 148 + memcpy(p->key, output_buf, output_len); 149 + p->key_len = output_len; 150 + dump_payload(p); 151 + } else { 152 + pr_err("Unwrapping of payload failed: %d\n", rc); 153 + } 154 + 155 + kfree(input_buf); 156 + kfree(output_buf); 157 + 158 + return rc; 159 + } 160 + 161 + static int trusted_pkwm_init(void) 162 + { 163 + int ret; 164 + 165 + if (!plpks_wrapping_is_supported()) { 166 + pr_err("H_PKS_WRAP_OBJECT interface not supported\n"); 167 + return -ENODEV; 168 + } 169 + 170 + ret = plpks_gen_wrapping_key(); 171 + if (ret) { 172 + pr_err("Failed to generate default wrapping key\n"); 173 + return -EINVAL; 174 + } 175 + 176 + return register_key_type(&key_type_trusted); 177 + } 178 + 179 + static void trusted_pkwm_exit(void) 180 + { 181 + unregister_key_type(&key_type_trusted); 182 + } 183 + 184 + struct trusted_key_ops pkwm_trusted_key_ops = { 185 + .migratable = 0, /* non-migratable */ 186 + .init = trusted_pkwm_init, 187 + .seal = trusted_pkwm_seal, 188 + .unseal = trusted_pkwm_unseal, 189 + .exit = trusted_pkwm_exit, 190 + };