Re: [PATCH 1/2] powerpc/pseries: define driver for Platform KeyStore

2022-07-20 Thread Murilo Opsfelder Araújo

Hi, Nayna.

Some comments below.

On 7/12/22 21:59, Nayna Jain wrote:

PowerVM provides an isolated Platform Keystore(PKS) storage allocation
for each LPAR with individually managed access controls to store
sensitive information securely. It provides a new set of hypervisor
calls for Linux kernel to access PKS storage.


I think it would be nice to have some consistency as to spaces before
acronymous, e.g.: "Keystore(PKS)" vs. "Keystore (PKS)". The same could
be applied to "Keystore" vs. "KeyStore" vs. "Key Storage".



Define PLPKS driver using H_CALL interface to access PKS storage.

Signed-off-by: Nayna Jain 
---
  arch/powerpc/include/asm/hvcall.h |   9 +
  arch/powerpc/include/asm/plpks.h  |  90 
  arch/powerpc/platforms/pseries/Kconfig|  13 +
  arch/powerpc/platforms/pseries/Makefile   |   2 +
  arch/powerpc/platforms/pseries/plpks/Makefile |   7 +
  arch/powerpc/platforms/pseries/plpks/plpks.c  | 509 ++
  6 files changed, 630 insertions(+)
  create mode 100644 arch/powerpc/include/asm/plpks.h
  create mode 100644 arch/powerpc/platforms/pseries/plpks/Makefile
  create mode 100644 arch/powerpc/platforms/pseries/plpks/plpks.c

diff --git a/arch/powerpc/include/asm/hvcall.h 
b/arch/powerpc/include/asm/hvcall.h
index d92a20a85395..24b661b0717c 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -97,6 +97,7 @@
  #define H_OP_MODE -73
  #define H_COP_HW  -74
  #define H_STATE   -75
+#define H_IN_USE   -77
  #define H_UNSUPPORTED_FLAG_START  -256
  #define H_UNSUPPORTED_FLAG_END-511
  #define H_MULTI_THREADS_ACTIVE-9005
@@ -321,6 +322,14 @@
  #define H_SCM_UNBIND_ALL0x3FC
  #define H_SCM_HEALTH0x400
  #define H_SCM_PERFORMANCE_STATS 0x418
+#define H_PKS_GET_CONFIG   0x41C
+#define H_PKS_SET_PASSWORD 0x420
+#define H_PKS_GEN_PASSWORD 0x424
+#define H_PKS_WRITE_OBJECT 0x42C
+#define H_PKS_GEN_KEY  0x430
+#define H_PKS_READ_OBJECT  0x434
+#define H_PKS_REMOVE_OBJECT0x438
+#define H_PKS_CONFIRM_OBJECT_FLUSHED   0x43C
  #define H_RPT_INVALIDATE  0x448
  #define H_SCM_FLUSH   0x44C
  #define H_GET_ENERGY_SCALE_INFO   0x450
diff --git a/arch/powerpc/include/asm/plpks.h b/arch/powerpc/include/asm/plpks.h
new file mode 100644
index ..cf60e53e1f15
--- /dev/null
+++ b/arch/powerpc/include/asm/plpks.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2022 IBM Corporation
+ * Author: Nayna Jain 
+ *
+ * Platform keystore for pseries LPAR(PLPKS).
+ */
+
+#ifndef _PSERIES_PLPKS_H
+#define _PSERIES_PLPKS_H
+
+#include 
+#include 
+
+#define OSSECBOOTAUDIT 0x4000
+#define OSSECBOOTENFORCE 0x2000
+#define WORLDREADABLE 0x0800
+#define SIGNEDUPDATE 0x0100
+
+#define PLPKS_VAR_LINUX0x01
+#define PLPKS_VAR_COMMON   0x04
+
+struct plpks_var {
+   char *component;
+   u8 os;
+   u8 *name;
+   u16 namelen;
+   u32 policy;
+   u16 datalen;
+   u8 *data;
+};
+
+struct plpks_var_name {
+   u16 namelen;
+   u8  *name;
+};
+
+struct plpks_var_name_list {
+   u32 varcount;
+   struct plpks_var_name varlist[];
+};
+
+struct plpks_config {
+   u8 version;
+   u8 flags;
+   u32 rsvd0;
+   u16 maxpwsize;
+   u16 maxobjlabelsize;
+   u16 maxobjsize;
+   u32 totalsize;
+   u32 usedspace;
+   u32 supportedpolicies;
+   u64 rsvd1;
+} __packed;
+
+/**
+ * Successful return from this API  implies PKS is available.
+ * This is used to initialize kernel driver and user interfaces.
+ */
+struct plpks_config *plpks_get_config(void);
+
+/**
+ * Writes the specified var and its data to PKS.
+ * Any caller of PKS driver should present a valid component type for
+ * their variable.
+ */
+int plpks_write_var(struct plpks_var var);
+
+/**
+ * Removes the specified var and its data from PKS.
+ */
+int plpks_remove_var(char *component, u8 varos,
+struct plpks_var_name vname);
+
+/**
+ * Returns the data for the specified os variable.
+ */
+int plpks_read_os_var(struct plpks_var *var);
+
+/**
+ * Returns the data for the specified firmware variable.
+ */
+int plpks_read_fw_var(struct plpks_var *var);
+
+/**
+ * Returns the data for the specified bootloader variable.
+ */
+int plpks_read_bootloader_var(struct plpks_var *var);
+
+#endif
diff --git a/arch/powerpc/platforms/pseries/Kconfig 
b/arch/powerpc/platforms/pseries/Kconfig
index f7fd91d153a4..de6efe5d18c2 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -142,6 +142,19 @@ config IBMEBUS
help
  Bus device driver for GX bus based adapters.

+config PSERIES_PLPKS
+   depends on PPC_PSERIES
+   tristate "Support for the Platform Key Storage"
+   help
+ PowerVM provides an isolated Platform Keystore(PKS) storage
+ allocation for each 

Re: [PATCH 1/2] powerpc/pseries: define driver for Platform KeyStore

2022-07-19 Thread Eric Richter
On 7/12/22 7:59 PM, Nayna Jain wrote:
> PowerVM provides an isolated Platform Keystore(PKS) storage allocation
> for each LPAR with individually managed access controls to store
> sensitive information securely. It provides a new set of hypervisor
> calls for Linux kernel to access PKS storage.
> 
> Define PLPKS driver using H_CALL interface to access PKS storage.
> 
> Signed-off-by: Nayna Jain 
> ---
>  arch/powerpc/include/asm/hvcall.h |   9 +
>  arch/powerpc/include/asm/plpks.h  |  90 
>  arch/powerpc/platforms/pseries/Kconfig|  13 +
>  arch/powerpc/platforms/pseries/Makefile   |   2 +
>  arch/powerpc/platforms/pseries/plpks/Makefile |   7 +
>  arch/powerpc/platforms/pseries/plpks/plpks.c  | 509 ++
>  6 files changed, 630 insertions(+)
>  create mode 100644 arch/powerpc/include/asm/plpks.h
>  create mode 100644 arch/powerpc/platforms/pseries/plpks/Makefile
>  create mode 100644 arch/powerpc/platforms/pseries/plpks/plpks.c
> 
> diff --git a/arch/powerpc/include/asm/hvcall.h 
> b/arch/powerpc/include/asm/hvcall.h
> index d92a20a85395..24b661b0717c 100644
> --- a/arch/powerpc/include/asm/hvcall.h
> +++ b/arch/powerpc/include/asm/hvcall.h
> @@ -97,6 +97,7 @@
>  #define H_OP_MODE-73
>  #define H_COP_HW -74
>  #define H_STATE  -75
> +#define H_IN_USE -77
>  #define H_UNSUPPORTED_FLAG_START -256
>  #define H_UNSUPPORTED_FLAG_END   -511
>  #define H_MULTI_THREADS_ACTIVE   -9005
> @@ -321,6 +322,14 @@
>  #define H_SCM_UNBIND_ALL0x3FC
>  #define H_SCM_HEALTH0x400
>  #define H_SCM_PERFORMANCE_STATS 0x418
> +#define H_PKS_GET_CONFIG 0x41C
> +#define H_PKS_SET_PASSWORD   0x420
> +#define H_PKS_GEN_PASSWORD   0x424
> +#define H_PKS_WRITE_OBJECT   0x42C
> +#define H_PKS_GEN_KEY0x430
> +#define H_PKS_READ_OBJECT0x434
> +#define H_PKS_REMOVE_OBJECT  0x438
> +#define H_PKS_CONFIRM_OBJECT_FLUSHED 0x43C
>  #define H_RPT_INVALIDATE 0x448
>  #define H_SCM_FLUSH  0x44C
>  #define H_GET_ENERGY_SCALE_INFO  0x450
> diff --git a/arch/powerpc/include/asm/plpks.h 
> b/arch/powerpc/include/asm/plpks.h
> new file mode 100644
> index ..cf60e53e1f15
> --- /dev/null
> +++ b/arch/powerpc/include/asm/plpks.h
> @@ -0,0 +1,90 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2022 IBM Corporation
> + * Author: Nayna Jain 
> + *
> + * Platform keystore for pseries LPAR(PLPKS).
> + */
> +
> +#ifndef _PSERIES_PLPKS_H
> +#define _PSERIES_PLPKS_H
> +
> +#include 
> +#include 
> +
> +#define OSSECBOOTAUDIT 0x4000
> +#define OSSECBOOTENFORCE 0x2000
> +#define WORLDREADABLE 0x0800
> +#define SIGNEDUPDATE 0x0100
> +
> +#define PLPKS_VAR_LINUX  0x01
> +#define PLPKS_VAR_COMMON 0x04
> +
> +struct plpks_var {
> + char *component;
> + u8 os;
> + u8 *name;
> + u16 namelen;
> + u32 policy;
> + u16 datalen;
> + u8 *data;
> +};
> +
> +struct plpks_var_name {
> + u16 namelen;
> + u8  *name;
> +};
> +
> +struct plpks_var_name_list {
> + u32 varcount;
> + struct plpks_var_name varlist[];
> +};
> +
> +struct plpks_config {
> + u8 version;
> + u8 flags;
> + u32 rsvd0;
> + u16 maxpwsize;
> + u16 maxobjlabelsize;
> + u16 maxobjsize;
> + u32 totalsize;
> + u32 usedspace;
> + u32 supportedpolicies;
> + u64 rsvd1;
> +} __packed;
> +
> +/**
> + * Successful return from this API  implies PKS is available.
> + * This is used to initialize kernel driver and user interfaces.
> + */
> +struct plpks_config *plpks_get_config(void);
> +
> +/**
> + * Writes the specified var and its data to PKS.
> + * Any caller of PKS driver should present a valid component type for
> + * their variable.
> + */
> +int plpks_write_var(struct plpks_var var);
> +
> +/**
> + * Removes the specified var and its data from PKS.
> + */
> +int plpks_remove_var(char *component, u8 varos,
> +  struct plpks_var_name vname);
> +
> +/**
> + * Returns the data for the specified os variable.
> + */
> +int plpks_read_os_var(struct plpks_var *var);
> +
> +/**
> + * Returns the data for the specified firmware variable.
> + */
> +int plpks_read_fw_var(struct plpks_var *var);
> +
> +/**
> + * Returns the data for the specified bootloader variable.
> + */
> +int plpks_read_bootloader_var(struct plpks_var *var);
> +
> +#endif
> diff --git a/arch/powerpc/platforms/pseries/Kconfig 
> b/arch/powerpc/platforms/pseries/Kconfig
> index f7fd91d153a4..de6efe5d18c2 100644
> --- a/arch/powerpc/platforms/pseries/Kconfig
> +++ b/arch/powerpc/platforms/pseries/Kconfig
> @@ -142,6 +142,19 @@ config IBMEBUS
>   help
> Bus device driver for GX bus based adapters.
> 
> +config PSERIES_PLPKS
> + depends on PPC_PSERIES
> + tristate "Support for the Platform Key Storage"
> + help
> +   PowerVM provides an isolated Platform Keystore(PKS) storage
> +   allocation for each LPAR with individually 

Re: [PATCH 1/2] powerpc/pseries: define driver for Platform KeyStore

2022-07-18 Thread Gregory Joyce
Comments inline.
Reviewed-by: Greg Joyce 


From: Nayna Jain 
Sent: Tuesday, July 12, 2022 7:59 PM
To: linuxppc-dev@lists.ozlabs.org 
Cc: Michael Ellerman ; Benjamin Herrenschmidt 
; Paul Mackerras ; George Wilson 
; Gregory Joyce ; Nayna Jain 

Subject: [PATCH 1/2] powerpc/pseries: define driver for Platform KeyStore

PowerVM provides an isolated Platform Keystore(PKS) storage allocation
for each LPAR with individually managed access controls to store
sensitive information securely. It provides a new set of hypervisor
calls for Linux kernel to access PKS storage.

Define PLPKS driver using H_CALL interface to access PKS storage.

Signed-off-by: Nayna Jain 
---


+
+static int construct_auth(u8 consumer, struct plpks_auth **auth)
+{
+   pr_debug("max password size is %u\n", config->maxpwsize);

Are the pr_debugs in this function still needed?

+
+   if (!auth || consumer > 3)
+   return -EINVAL;
+
+   *auth = kmalloc(struct_size(*auth, password, config->maxpwsize),
+   GFP_KERNEL);
+   if (!*auth)
+   return -ENOMEM;
+
+   (*auth)->version = 1;
+   (*auth)->consumer = consumer;
+   (*auth)->rsvd0 = 0;
+   (*auth)->rsvd1 = 0;
+   if (consumer == PKS_FW_OWNER || consumer == PKS_BOOTLOADER_OWNER) {
+   pr_debug("consumer is bootloader or firmware\n");
+   (*auth)->passwordlength = 0;
+   return 0;
+   }
+
+   (*auth)->passwordlength = (__force __be16)ospasswordlength;
+
+   memcpy((*auth)->password, ospassword,
+  flex_array_size(*auth, password,
+  (__force u16)((*auth)->passwordlength)));
+   (*auth)->passwordlength = cpu_to_be16((__force 
u16)((*auth)->passwordlength));
+
+   return 0;
+}
+
+/**
+ * Label is combination of label attributes + name.
+ * Label attributes are used internally by kernel and not exposed to the user.
+ */
+static int construct_label(char *component, u8 varos, u8 *name, u16 namelen, 
u8 **label)
+{
+   int varlen;
+   int len = 0;
+   int llen = 0;
+   int i;
+   int rc = 0;
+   u8 labellength = MAX_LABEL_ATTR_SIZE;
+
+   if (!label)
+   return -EINVAL;
+
+   varlen = namelen + sizeof(struct label_attr);
+   *label = kzalloc(varlen, GFP_KERNEL);
+
+   if (!*label)
+   return -ENOMEM;
+
+   if (component) {
+   len = strlen(component);
+   memcpy(*label, component, len);
+   }
+   llen = len;
+

I guess the 8, 1, and 5 are field lengths. Could they be a define or sizeof?

+   if (component)
+   len = 8 - strlen(component);
+   else
+   len = 8;
+
+   memset(*label + llen, 0, len);
+   llen = llen + len;
+
+   ((*label)[llen]) = 0;
+   llen = llen + 1;
+
+   memcpy(*label + llen, , 1);
+   llen = llen + 1;
+
+   memcpy(*label + llen, , 1);
+   llen = llen + 1;
+
+   memset(*label + llen, 0, 5);
+   llen = llen + 5;
+
+   memcpy(*label + llen, name, namelen);
+   llen = llen + namelen;
+
+   for (i = 0; i < llen; i++)
+   pr_debug("%c", (*label)[i]);
+
+   rc = llen;
+   return rc;
+}
+
+static int _plpks_get_config(void)
+{
+   unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = {0};
+   int rc;
+   size_t size = sizeof(struct plpks_config);
+
+   config = kzalloc(size, GFP_KERNEL);
+   if (!config)
+   return -ENOMEM;
+
+   rc = plpar_hcall(H_PKS_GET_CONFIG,
+retbuf,
+virt_to_phys(config),
+size);
+
+   if (rc != H_SUCCESS)

Free config before returning the error.

+   return pseries_status_to_err(rc);
+
+   config->rsvd0 = be32_to_cpu((__force __be32)config->rsvd0);
+   config->maxpwsize = be16_to_cpu((__force __be16)config->maxpwsize);
+   config->maxobjlabelsize = be16_to_cpu((__force 
__be16)config->maxobjlabelsize);
+   config->maxobjsize = be16_to_cpu((__force __be16)config->maxobjsize);
+   config->totalsize = be32_to_cpu((__force __be32)config->totalsize);
+   config->usedspace = be32_to_cpu((__force __be32)config->usedspace);
+   config->supportedpolicies = be32_to_cpu((__force 
__be32)config->supportedpolicies);
+   config->rsvd1 = be64_to_cpu((__force __be64)config->rsvd1);
+
+   configset = true;
+
+   return 0;
+}
+
+static int plpks_confirm_object_flushed(u8 *label, u16 labellen)
+{
+   unsigned long retbuf[PLPAR_HCALL_BUFSIZE] = {0};
+   int rc;
+   u64 timeout = 0;
+   struct plpks_auth *auth;
+   u8 status;
+   int i;
+

Deleted pr_debugs? I guess this is a general question for all pr_debugs in this 
file.

+   rc = construct_auth(PKS_OS_OWNER, );
+   if (rc)
+   return rc;
+
+   for (i = 0; i < labellen; i++)
+   pr_debug("%02x ", label[i]);
+
+   do {
+   

Re: [PATCH 1/2] powerpc/pseries: define driver for Platform KeyStore

2022-07-18 Thread Gregory Joyce
Tested-by: Greg Joyce 


From: Nayna Jain 
Sent: Tuesday, July 12, 2022 7:59 PM
To: linuxppc-dev@lists.ozlabs.org 
Cc: Michael Ellerman ; Benjamin Herrenschmidt 
; Paul Mackerras ; George Wilson 
; Gregory Joyce ; Nayna Jain 

Subject: [PATCH 1/2] powerpc/pseries: define driver for Platform KeyStore

PowerVM provides an isolated Platform Keystore(PKS) storage allocation
for each LPAR with individually managed access controls to store
sensitive information securely. It provides a new set of hypervisor
calls for Linux kernel to access PKS storage.

Define PLPKS driver using H_CALL interface to access PKS storage.

Tested-by: Greg Joyce 
Signed-off-by: Nayna Jain