Re: [PATCH v11 11/14] HP BIOSCFG driver - spmobj-attributes

From: Jorge Lopez
Date: Wed May 03 2023 - 15:35:20 EST


On Sun, Apr 23, 2023 at 4:24 AM <thomas@xxxxxxxx> wrote:
>
> On 2023-04-20 11:54:51-0500, Jorge Lopez wrote:
> > .../x86/hp/hp-bioscfg/spmobj-attributes.c | 405 ++++++++++++++++++
> > 1 file changed, 405 insertions(+)
> > create mode 100644 drivers/platform/x86/hp/hp-bioscfg/spmobj-attributes.c
> >
> > diff --git a/drivers/platform/x86/hp/hp-bioscfg/spmobj-attributes.c b/drivers/platform/x86/hp/hp-bioscfg/spmobj-attributes.c
> > new file mode 100644
> > index 000000000000..78228f44c39b
> > --- /dev/null
> > +++ b/drivers/platform/x86/hp/hp-bioscfg/spmobj-attributes.c
> > @@ -0,0 +1,405 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Functions corresponding to secure platform management object type
> > + * attributes under BIOS PASSWORD for use with hp-bioscfg driver
> > + *
> > + * Copyright (c) 2022 HP Development Company, L.P.
> > + */
> > +
> > +#include "bioscfg.h"
> > +
> > +
> > +static const char * const spm_state_types[] = {
> > + "not provisioned",
> > + "provisioned",
> > + "provisioning in progress"
> > +};
> > +
> > +static const char * const spm_mechanism_types[] = {
> > + "not provision",
>
> "not provisioned" as above?

Good catch. Done!
>
> > + "signing-key",
> > + "endorsement-key"
>
> Trailing commas please.
>
Done!
> > +};
> > +
> > +
> > +int check_spm_is_enabled(void)
> > +{
> > + /* do we need to check the admin password is also configured */
> > + return bioscfg_drv.spm_data.is_enabled;
> > +}
> > +
> > +/*
> > + * calculate_security_buffer() - determines size of security buffer
> > + * for authentication scheme
> > + *
> > + * @authentication: the authentication content
> > + *
> > + * Currently only supported type is Admin password
> > + */
> > +size_t calculate_security_buffer(const char *authentication)
> > +{
> > + int size;
> > +
> > + if (authentication != NULL && strlen(authentication) > 0) {
> > +
> > + size = (sizeof(u16) + (strlen(authentication) * sizeof(u16)));
> > + if (strncmp(authentication, BEAM_PREFIX, strlen(BEAM_PREFIX)) != 0)
>
> strstarts()

Done!
>
> > + size += (strlen(UTF_PREFIX) * sizeof(u16));
>
> No need for braces.

Done!
>
> > +
> > + return size;
> > + }
> > +
> > + size = sizeof(u16) * 2;
> > + return size;
> > +}
> > +
> > +/*
> > + * populate_security_buffer() - builds a security buffer for
> > + * authentication scheme
> > + *
> > + * @buffer: the buffer to populate
> > + * @authentication: the authentication content
> > + *
> > + * Currently only supported type is PLAIN TEXT
> > + */
> > +void populate_security_buffer(u16 *buffer, const char *authentication)
> > +{
> > + u16 *auth = buffer;
> > + char *strprefix = NULL;
> > +
> > + if (strncmp(authentication, BEAM_PREFIX, strlen(BEAM_PREFIX)) == 0) {
>
> strstarts()

Done!
>
> > + /*
> > + * BEAM_PREFIX is append to buffer when a signature
> > + * is provided and Sure Admin is enabled in BIOS
> > + */
> > + // BEAM_PREFIX found, convert part to unicode
> > + auth = ascii_to_utf16_unicode(auth, authentication);
> > + } else {
> > + /*
> > + * UTF-16 prefix is append to the * buffer when a BIOS
> > + * admin password is configured in BIOS
> > + */
> > +
> > + // append UTF_PREFIX to part and then convert it to unicode
> > + strprefix = kasprintf(GFP_KERNEL, "%s%s", UTF_PREFIX,
> > + authentication);
> > + if (!strprefix)
> > + goto out_buffer;
> > +
> > + auth = ascii_to_utf16_unicode(auth, strprefix);
> > + }
> > +out_buffer:
> > +
> > + kfree(strprefix);
> > +}
> > +
> > +ssize_t update_spm_state(void)
> > +{
> > + int ret;
> > + struct secureplatform_provisioning_data *data = NULL;
>
> This can be allocated on the stack.

Done!
>
> > +
> > + data = kmalloc(sizeof(struct secureplatform_provisioning_data),
> > + GFP_KERNEL);
> > + if (!data) {
> > + ret = -ENOMEM;
> > + goto state_exit;
> > + }
> > +
> > + ret = hp_wmi_perform_query(HPWMI_SECUREPLATFORM_GET_STATE,
> > + HPWMI_SECUREPLATFORM, data, 0,
> > + sizeof(*data));
> > + if (ret < 0)
> > + goto state_exit;
> > +
> > + bioscfg_drv.spm_data.mechanism = data->state;
> > + if (bioscfg_drv.spm_data.mechanism)
> > + bioscfg_drv.spm_data.is_enabled = 1;
> > +
> > +state_exit:
> > + kfree(data);
> > +
> > + return ret;
> > +}
> > +
> > +ssize_t statusbin(struct kobject *kobj,
> > + struct kobj_attribute *attr, char *buf)
>
> This can be static.

Done!
>
> If it is known that a struct secureplatform_provisioning_data is to be
> passed, then the type can reflect that.

Done!
>
> > +{
> > + int ret = hp_wmi_perform_query(HPWMI_SECUREPLATFORM_GET_STATE,
> > + HPWMI_SECUREPLATFORM, buf, 0,
> > + sizeof(struct secureplatform_provisioning_data));
> > +
> > + return ret ? -ENODEV : sizeof(struct secureplatform_provisioning_data);
>
> Why not return "ret" on error?

Good point. Done!
>
> > +}
> > +
> > +/*
> > + * status_show - Reads SPM status
> > + */
> > +ssize_t status_show(struct kobject *kobj, struct kobj_attribute
> > + *attr, char *buf)
> > +{
> > + int ret, i;
> > + struct secureplatform_provisioning_data *data = NULL;
>
> Can also be on-stack.

Done!
>
<snip>
> > +static struct kobj_attribute password_spm_key_mechanism = __ATTR_RO(key_mechanism);
> > +
> > +static ssize_t sk_store(struct kobject *kobj,
> > + struct kobj_attribute *attr,
> > + const char *buf, size_t count)
> > +{
> > + int ret;
> > + int length;
> > +
> > + length = count;
> > + if (buf[length-1] == '\n')
> > + length--;
> > +
> > + /* allocate space and copy current signing key */
> > + bioscfg_drv.spm_data.signing_key = kmalloc(length, GFP_KERNEL);
> > + if (!bioscfg_drv.spm_data.signing_key) {
> > + ret = -ENOMEM;
> > + goto exit_sk;
> > + }
> > +
> > + memcpy(bioscfg_drv.spm_data.signing_key, buf, length);
> > + bioscfg_drv.spm_data.signing_key[length] = '\0';
>
> Is this supposed to handle zero-bytes in the input?
> If yes: Did you test this with zero bytes, I don't think the normal
> attribute APIs handle this.
> If no: Why not use strscpy?
>

Done!

<snip>