// 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 provisioned" ,
"signing-key" ,
"endorsement-key" ,
};
struct secureplatform_provisioning_data {
u8 state;
u8 version[2 ];
u8 reserved1;
u32 features;
u32 nonce;
u8 reserved2[28 ];
u8 sk_mod[MAX_KEY_MOD_SIZE];
u8 kek_mod[MAX_KEY_MOD_SIZE];
};
/**
* hp_calculate_security_buffer ( ) - determines size of security buffer
* for authentication scheme
*
* @ authentication : the authentication content
*
* Currently only supported type is Admin password
*/
size_t hp_calculate_security_buffer(const char *authentication)
{
size_t size, authlen;
if (!authentication)
return sizeof (u16) * 2 ;
authlen = strlen(authentication);
if (!authlen)
return sizeof (u16) * 2 ;
size = sizeof (u16) + authlen * sizeof (u16);
if (!strstarts(authentication, BEAM_PREFIX))
size += strlen(UTF_PREFIX) * sizeof (u16);
return size;
}
/**
* hp_populate_security_buffer ( ) - builds a security buffer for
* authentication scheme
*
* @ authbuf : the security buffer
* @ authentication : the authentication content
*
* Currently only supported type is PLAIN TEXT
*/
int hp_populate_security_buffer(u16 *authbuf, const char *authentication)
{
u16 *auth = authbuf;
char *strprefix = NULL;
int ret = 0 ;
if (strstarts(authentication, BEAM_PREFIX)) {
/*
* BEAM_PREFIX is append to authbuf when a signature
* is provided and Sure Admin is enabled in BIOS
*/
/* BEAM_PREFIX found, convert part to unicode */
auth = hp_ascii_to_utf16_unicode(auth, authentication);
if (!auth)
return -EINVAL;
} else {
/*
* UTF - 16 prefix is append to the * authbuf 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)
return -ENOMEM;
auth = hp_ascii_to_utf16_unicode(auth, strprefix);
kfree(strprefix);
if (!auth) {
ret = -EINVAL;
goto out_buffer;
}
}
out_buffer:
return ret;
}
static ssize_t update_spm_state(void )
{
struct secureplatform_provisioning_data data;
int ret;
ret = hp_wmi_perform_query(HPWMI_SECUREPLATFORM_GET_STATE,
HPWMI_SECUREPLATFORM, &data, 0 ,
sizeof (data));
if (ret < 0 )
return ret;
bioscfg_drv.spm_data.mechanism = data.state;
if (bioscfg_drv.spm_data.mechanism)
bioscfg_drv.spm_data.is_enabled = 1 ;
return 0 ;
}
static ssize_t statusbin(struct kobject *kobj,
struct kobj_attribute *attr,
struct secureplatform_provisioning_data *buf)
{
int ret = hp_wmi_perform_query(HPWMI_SECUREPLATFORM_GET_STATE,
HPWMI_SECUREPLATFORM, buf, 0 ,
sizeof (*buf));
if (ret < 0 )
return ret;
return sizeof (struct secureplatform_provisioning_data);
}
/*
* status_show - Reads SPM status
*/
static ssize_t status_show(struct kobject *kobj, struct kobj_attribute
*attr, char *buf)
{
int ret, i;
int len = 0 ;
struct secureplatform_provisioning_data data;
ret = statusbin(kobj, attr, &data);
if (ret < 0 )
return ret;
/*
* ' status ' is a read - only file that returns ASCII text in
* JSON format reporting the status information .
*
* " State " : " not provisioned | provisioned | provisioning in progress " ,
* " Version " : " Major . Minor " ,
* " Nonce " : < 16 - bit unsigned number display in base 10 > ,
* " FeaturesInUse " : < 16 - bit unsigned number display in base 10 > ,
* " EndorsementKeyMod " : " < 256 bytes in base64 > " ,
* " SigningKeyMod " : " < 256 bytes in base64 > "
*/
len += sysfs_emit_at(buf, len, "{\n" );
len += sysfs_emit_at(buf, len, "\t\" State\": \" %s\",\n" ,
spm_state_types[data.state]);
len += sysfs_emit_at(buf, len, "\t\" Version\": \" %d.%d\"" ,
data.version[0 ], data.version[1 ]);
/*
* state = = 0 means secure platform management
* feature is not configured in BIOS .
*/
if (data.state == 0 ) {
len += sysfs_emit_at(buf, len, "\n" );
goto status_exit;
} else {
len += sysfs_emit_at(buf, len, ",\n" );
}
len += sysfs_emit_at(buf, len, "\t\" Nonce\": %d,\n" , data.nonce);
len += sysfs_emit_at(buf, len, "\t\" FeaturesInUse\": %d,\n" , data.features);
len += sysfs_emit_at(buf, len, "\t\" EndorsementKeyMod\": \" ");
for (i = 255 ; i >= 0 ; i--)
len += sysfs_emit_at(buf, len, " %u" , data.kek_mod[i]);
len += sysfs_emit_at(buf, len, " \" ,\n");
len += sysfs_emit_at(buf, len, "\t\" SigningKeyMod\": \" ");
for (i = 255 ; i >= 0 ; i--)
len += sysfs_emit_at(buf, len, " %u" , data.sk_mod[i]);
/* Return buf contents */
len += sysfs_emit_at(buf, len, " \" \n");
status_exit:
len += sysfs_emit_at(buf, len, "}\n" );
return len;
}
static struct kobj_attribute password_spm_status = __ATTR_RO(status);
ATTRIBUTE_SPM_N_PROPERTY_SHOW(is_enabled, spm);
static struct kobj_attribute password_spm_is_key_enabled = __ATTR_RO(is_enabled);
static ssize_t key_mechanism_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
return sysfs_emit(buf, "%s\n" ,
spm_mechanism_types[bioscfg_drv.spm_data.mechanism]);
}
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 = kmemdup(buf, length, GFP_KERNEL);
if (!bioscfg_drv.spm_data.signing_key)
return -ENOMEM;
/* submit signing key payload */
ret = hp_wmi_perform_query(HPWMI_SECUREPLATFORM_SET_SK,
HPWMI_SECUREPLATFORM,
(void *)bioscfg_drv.spm_data.signing_key,
count, 0 );
if (!ret) {
bioscfg_drv.spm_data.mechanism = SIGNING_KEY;
hp_set_reboot_and_signal_event();
}
kfree(bioscfg_drv.spm_data.signing_key);
bioscfg_drv.spm_data.signing_key = NULL;
return ret ? ret : count;
}
static struct kobj_attribute password_spm_signing_key = __ATTR_WO(sk);
static ssize_t kek_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.endorsement_key = kmemdup(buf, length, GFP_KERNEL);
if (!bioscfg_drv.spm_data.endorsement_key) {
ret = -ENOMEM;
goto exit_kek;
}
ret = hp_wmi_perform_query(HPWMI_SECUREPLATFORM_SET_KEK,
HPWMI_SECUREPLATFORM,
(void *)bioscfg_drv.spm_data.endorsement_key,
count, 0 );
if (!ret) {
bioscfg_drv.spm_data.mechanism = ENDORSEMENT_KEY;
hp_set_reboot_and_signal_event();
}
exit_kek:
kfree(bioscfg_drv.spm_data.endorsement_key);
bioscfg_drv.spm_data.endorsement_key = NULL;
return ret ? ret : count;
}
static struct kobj_attribute password_spm_endorsement_key = __ATTR_WO(kek);
static ssize_t role_show(struct kobject *kobj, struct kobj_attribute *attr,
char *buf)
{
return sysfs_emit(buf, "%s\n" , BIOS_SPM);
}
static struct kobj_attribute password_spm_role = __ATTR_RO(role);
static ssize_t auth_token_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
int ret = 0 ;
int length;
length = count;
if (buf[length - 1 ] == '\n' )
length--;
/* allocate space and copy current auth token */
bioscfg_drv.spm_data.auth_token = kmemdup(buf, length, GFP_KERNEL);
if (!bioscfg_drv.spm_data.auth_token) {
ret = -ENOMEM;
goto exit_token;
}
return count;
exit_token:
kfree(bioscfg_drv.spm_data.auth_token);
bioscfg_drv.spm_data.auth_token = NULL;
return ret;
}
static struct kobj_attribute password_spm_auth_token = __ATTR_WO(auth_token);
static struct attribute *secure_platform_attrs[] = {
&password_spm_is_key_enabled.attr,
&password_spm_signing_key.attr,
&password_spm_endorsement_key.attr,
&password_spm_key_mechanism.attr,
&password_spm_status.attr,
&password_spm_role.attr,
&password_spm_auth_token.attr,
NULL,
};
static const struct attribute_group secure_platform_attr_group = {
.attrs = secure_platform_attrs,
};
void hp_exit_secure_platform_attributes(void )
{
/* remove secure platform sysfs entry and free key data*/
kfree(bioscfg_drv.spm_data.endorsement_key);
bioscfg_drv.spm_data.endorsement_key = NULL;
kfree(bioscfg_drv.spm_data.signing_key);
bioscfg_drv.spm_data.signing_key = NULL;
kfree(bioscfg_drv.spm_data.auth_token);
bioscfg_drv.spm_data.auth_token = NULL;
if (bioscfg_drv.spm_data.attr_name_kobj)
sysfs_remove_group(bioscfg_drv.spm_data.attr_name_kobj,
&secure_platform_attr_group);
}
int hp_populate_secure_platform_data(struct kobject *attr_name_kobj)
{
/* Populate data for Secure Platform Management */
bioscfg_drv.spm_data.attr_name_kobj = attr_name_kobj;
strscpy(bioscfg_drv.spm_data.attribute_name, SPM_STR);
bioscfg_drv.spm_data.is_enabled = 0 ;
bioscfg_drv.spm_data.mechanism = 0 ;
bioscfg_drv.pending_reboot = false ;
update_spm_state();
bioscfg_drv.spm_data.endorsement_key = NULL;
bioscfg_drv.spm_data.signing_key = NULL;
bioscfg_drv.spm_data.auth_token = NULL;
return sysfs_create_group(attr_name_kobj, &secure_platform_attr_group);
}
Messung V0.5 in Prozent C=93 H=94 G=93
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-10-11)
¤
*© Formatika GbR, Deutschland