---
.../security/keys/trusted-encrypted.rst | 4 +-
arch/powerpc/include/asm/plpks.h | 10 ++-
arch/powerpc/platforms/pseries/plpks.c | 64 ++++++++++---------
include/keys/trusted_pkwm.h | 3 +
security/keys/trusted-keys/trusted_pkwm.c | 34 +++++++++-
5 files changed, 80 insertions(+), 35 deletions(-)
diff --git a/Documentation/security/keys/trusted-encrypted.rst
b/Documentation/security/keys/trusted-encrypted.rst
index ddff7c7c2582..76fda28fddb1 100644
--- a/Documentation/security/keys/trusted-encrypted.rst
+++ b/Documentation/security/keys/trusted-encrypted.rst
@@ -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
diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
index c39d1f07017e..badb07afe749 100644
--- a/arch/powerpc/include/asm/plpks.h
+++ b/arch/powerpc/include/asm/plpks.h
@@ -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);
diff --git a/arch/powerpc/platforms/pseries/plpks.c
b/arch/powerpc/platforms/pseries/plpks.c
index 3b1e6f00b4ae..5cdaabe9de06 100644
--- a/arch/powerpc/platforms/pseries/plpks.c
+++ b/arch/powerpc/platforms/pseries/plpks.c
@@ -9,9 +9,6 @@
#define pr_fmt(fmt) "plpks: " fmt
-#define PLPKS_WRAPKEY_COMPONENT "PLPKSWR"
-#define PLPKS_DEFAULT_WRAPKEY_LABEL "default-wrapping-key"
-
/*
* To 4K align the {input, output} buffers to the {UN}WRAP H_CALLs
*/
@@ -935,6 +932,7 @@ EXPORT_SYMBOL_GPL(plpks_revoke_is_supported);
/**
* plpks_gen_wrapping_key() - Generate a new random key with the 'wrapping
key'
* policy set.
+ * @var: variable representing the wrapping key to be created
*
* The H_PKS_GEN_KEY HCALL makes the hypervisor generate a new random key and
* store the key in a PLPKS object with the provided object label. With the
@@ -960,25 +958,27 @@ EXPORT_SYMBOL_GPL(plpks_revoke_is_supported);
*
* Returns: On success 0 is returned, a negative errno if not.
*/
-int plpks_gen_wrapping_key(void)
+int plpks_gen_wrapping_key(struct plpks_var *var)
{
unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = { 0 };
struct plpks_auth *auth;
struct label *label;
int rc = 0, pseries_status = 0;
- struct plpks_var var = {
- .name = PLPKS_DEFAULT_WRAPKEY_LABEL,
- .namelen = sizeof(PLPKS_DEFAULT_WRAPKEY_LABEL) - 1,
- .policy = PLPKS_WRAPPINGKEY,
- .os = PLPKS_VAR_LINUX,
- .component = PLPKS_WRAPKEY_COMPONENT
- };
+
+ if (!var)
+ return -EINVAL;
+
+ if (!var->name || !*var->name) {
+ pr_err("key label cannot be NULL/empty\n");
+ return -EINVAL;
+ }
auth = construct_auth(PLPKS_OS_OWNER);
if (IS_ERR(auth))
return PTR_ERR(auth);
- label = construct_label(var.component, var.os, var.name, var.namelen);
+ label = construct_label(var->component, var->os, var->name,
+ var->namelen);
if (IS_ERR(label)) {
rc = PTR_ERR(label);
goto out;
@@ -986,7 +986,7 @@ int plpks_gen_wrapping_key(void)
rc = plpar_hcall(H_PKS_GEN_KEY, retbuf,
virt_to_phys(auth), virt_to_phys(label),
- label->size, var.policy,
+ label->size, var->policy,
NULL, PLPKS_WRAPPING_KEY_LENGTH);
if (!rc)
@@ -995,11 +995,13 @@ int plpks_gen_wrapping_key(void)
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;
+ if (rc) {
+ if (rc == -EEXIST)
+ pr_info("wrapping key <%s> already exists\n",
+ (char *)var->name);
+ else
+ pr_err("H_PKS_GEN_KEY failed. pseries_status=%d,
rc=%d\n",
+ pseries_status, rc);
}
kfree(label);
@@ -1010,13 +1012,14 @@ int plpks_gen_wrapping_key(void)
EXPORT_SYMBOL_GPL(plpks_gen_wrapping_key);
/**
- * plpks_wrap_object() - Wrap an object using the default wrapping key stored
in
- * the PLPKS.
+ * plpks_wrap_object() - Wrap an object using the specified wrapping key stored
+ * in the PLPKS.
* @input_buf: buffer containing the data to be wrapped
* @input_len: length of the input buffer
* @wrap_flags: object wrapping flags
* @output_buf: buffer to store the wrapped data
* @output_len: length of the output buffer
+ * @var: variable representing the wrapping key to be used
*
* The H_PKS_WRAP_OBJECT HCALL wraps an object using a wrapping key stored in
* the PLPKS and returns the wrapped object to the caller. The caller
provides a
@@ -1051,7 +1054,7 @@ 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, u64 input_len, u16 wrap_flags,
- u8 **output_buf, u64 *output_len)
+ u8 **output_buf, u64 *output_len, struct plpks_var *var)
{
unsigned long retbuf[PLPAR_HCALL9_BUFSIZE] = { 0 };
struct plpks_auth *auth;
@@ -1061,18 +1064,21 @@ int plpks_wrap_object(u8 **input_buf, u64 input_len,
u16 wrap_flags,
int rc = 0, pseries_status = 0;
bool sb_audit_or_enforce_bit = wrap_flags & BIT(0);
bool sb_enforce_bit = wrap_flags & BIT(1);
- struct plpks_var var = {
- .name = PLPKS_DEFAULT_WRAPKEY_LABEL,
- .namelen = sizeof(PLPKS_DEFAULT_WRAPKEY_LABEL) - 1,
- .os = PLPKS_VAR_LINUX,
- .component = PLPKS_WRAPKEY_COMPONENT
- };
+
+ if (!var)
+ return -EINVAL;
+
+ if (!var->name || !*var->name) {
+ pr_err("key label cannot be NULL/empty\n");
+ return -EINVAL;
+ }
auth = construct_auth(PLPKS_OS_OWNER);
if (IS_ERR(auth))
return PTR_ERR(auth);
- label = construct_label(var.component, var.os, var.name, var.namelen);
+ label = construct_label(var->component, var->os, var->name,
+ var->namelen);
if (IS_ERR(label)) {
rc = PTR_ERR(label);
goto out;
@@ -1135,7 +1141,7 @@ int plpks_wrap_object(u8 **input_buf, u64 input_len, u16
wrap_flags,
EXPORT_SYMBOL_GPL(plpks_wrap_object);
/**
- * plpks_unwrap_object() - Unwrap an object using the default wrapping key
+ * plpks_unwrap_object() - Unwrap an object using its associated wrapping key
* stored in the PLPKS.
* @input_buf: buffer containing the data to be unwrapped
* @input_len: length of the input buffer
diff --git a/include/keys/trusted_pkwm.h b/include/keys/trusted_pkwm.h
index 4035b9776394..53a5f780edd2 100644
--- a/include/keys/trusted_pkwm.h
+++ b/include/keys/trusted_pkwm.h
@@ -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)
diff --git a/security/keys/trusted-keys/trusted_pkwm.c
b/security/keys/trusted-keys/trusted_pkwm.c
index 633a7674d065..7bfe98d79cd7 100644
--- a/security/keys/trusted-keys/trusted_pkwm.c
+++ b/security/keys/trusted-keys/trusted_pkwm.c
@@ -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;
}
@@ -82,6 +90,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;
+ struct plpks_var var;
u8 *input_buf, *output_buf;
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,14 +180,23 @@ 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) {
+ 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);
+ if (ret && ret != -EEXIST) {
pr_err("Failed to generate default wrapping key\n");
return ret;
}