[PATCH 1/2] powerpc/pseries: define driver for Platform KeyStore
Gregory Joyce
gjoyce at ibm.com
Tue Jul 19 08:30:13 AEST 2022
Comments inline.
Reviewed-by: Greg Joyce <gjoyce at linux.vnet.ibm.com>
________________________________
From: Nayna Jain <nayna at linux.ibm.com>
Sent: Tuesday, July 12, 2022 7:59 PM
To: linuxppc-dev at lists.ozlabs.org <linuxppc-dev at lists.ozlabs.org>
Cc: Michael Ellerman <mpe at ellerman.id.au>; Benjamin Herrenschmidt <benh at kernel.crashing.org>; Paul Mackerras <paulus at samba.org>; George Wilson <gcwilson at linux.ibm.com>; Gregory Joyce <gjoyce at ibm.com>; Nayna Jain <nayna at linux.ibm.com>
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 <nayna at linux.ibm.com>
---
+
+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, &varos, 1);
+ llen = llen + 1;
+
+ memcpy(*label + llen, &labellength, 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, &auth);
+ if (rc)
+ return rc;
+
+ for (i = 0; i < labellen; i++)
+ pr_debug("%02x ", label[i]);
+
+ do {
+ rc = plpar_hcall(H_PKS_CONFIRM_OBJECT_FLUSHED,
+ retbuf,
+ virt_to_phys(auth),
+ virt_to_phys(label),
+ labellen);
+
+ status = retbuf[0];
+ if (rc) {
+ pr_info("rc is %d, status is %d\n", rc, status);
+ if (rc == H_NOT_FOUND && status == 1)
+ rc = 0;
+ break;
+ }
+
+ pr_debug("rc is %d, status is %d\n", rc, status);
+
+ if (!rc && status == 1)
+ break;
+
+ usleep_range(PKS_FLUSH_SLEEP, PKS_FLUSH_SLEEP + PKS_FLUSH_SLEEP_RANGE);
+ timeout = timeout + PKS_FLUSH_SLEEP;
+ pr_debug("timeout is %llu\n", timeout);
+
+ } while (timeout < PKS_FLUSH_MAX_TIMEOUT);
+
+ rc = pseries_status_to_err(rc);
+
+ kfree(auth);
+
+ return rc;
+}
+
+EXPORT_SYMBOL(plpks_remove_var);
XPORT_SYMBOL(plpks_get_config);
+
+static __init int pseries_plpks_init(void)
+{
+ int rc = 0;
+
+ rc = _plpks_get_config();
+
+ if (rc) {
I think this pr_err would be better if provided more info like the pr_info below.
+ pr_err("Error initializing plpks\n");
+ return rc;
+ }
+
+ rc = plpks_gen_password();
+ if (rc) {
+ if (rc == H_IN_USE) {
+ rc = 0;
+ } else {
I think this pr_err would be better if provided more info like the pr_info below.
+ pr_err("Failed setting password %d\n", rc);
+ rc = pseries_status_to_err(rc);
+ return rc;
+ }
+ }
+
+ pr_info("POWER LPAR Platform Keystore initialized successfully\n");
+
+ return rc;
+}
+arch_initcall(pseries_plpks_init);
--
2.27.0
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/linuxppc-dev/attachments/20220718/d5f5aaf8/attachment-0001.htm>
More information about the Linuxppc-dev
mailing list