From be4e3fffdcebd3e9fcd583ce7bf0c53409845bcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Sat, 19 Mar 2022 17:47:47 +0100 Subject: [PATCH] genesys: usbhub: Identify HP usbhub using its public-key The HP M2xfd monitors use GenesysLogic GL3523 USB Hub and provides their own firmwares. Furthermore, HP uses the same VID/PID for other USB Hubs products, with a different public-key; the HP M24fd and M27fd use different public-key. This appends the public-key to the instance-id string to make the distinction between all the HP USB Hubs, and prevents to install a firmware with the wrong public-key. --- plugins/genesys/README.md | 2 ++ plugins/genesys/fu-genesys-usbhub-device.c | 37 ++++++++++++++++++++ plugins/genesys/fu-genesys-usbhub-firmware.c | 1 + plugins/genesys/genesys.quirk | 17 ++++++++- 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/plugins/genesys/README.md b/plugins/genesys/README.md index 601d041ac..e0ca42bd6 100644 --- a/plugins/genesys/README.md +++ b/plugins/genesys/README.md @@ -25,6 +25,8 @@ This plugin supports the following protocol IDs: These devices use the standard USB DeviceInstanceId values for the USB Hub, e.g. * HP USB-C Controller: `USB\VID_03F0&PID_0610` +* HP M24fd USB-C Controller: `USB\VID_03F0&PID_0610&PUBKEY_B335BDCE-7073-5D0E-9BD3-9B69C1A6899F` +* HP M27fd USB-C Controller: `USB\VID_03F0&PID_0610&PUBKEY_847A3650-8648-586B-83C8-8B53714F37E3` These devices also use custom GUID values for the Scaler, e.g. diff --git a/plugins/genesys/fu-genesys-usbhub-device.c b/plugins/genesys/fu-genesys-usbhub-device.c index 05c3b423c..a93f49cde 100644 --- a/plugins/genesys/fu-genesys-usbhub-device.c +++ b/plugins/genesys/fu-genesys-usbhub-device.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2022 Gaël PORTAY * Copyright (C) 2021 Ricardo Cañuelo * * SPDX-License-Identifier: LGPL-2.1+ @@ -115,6 +116,7 @@ struct _FuGenesysUsbhubDevice { gboolean read_first_bank; gboolean write_recovery_bank; + guint8 public_key[0x212]; FuCfiDevice *cfi_device; }; @@ -693,6 +695,7 @@ fu_genesys_usbhub_device_setup(FuDevice *device, GError **error) g_autoptr(GError) error_local = NULL; g_autoptr(GBytes) blob = NULL; g_autofree guint8 *buf = NULL; + g_autofree gchar *guid = NULL; /* FuUsbDevice->setup */ if (!FU_DEVICE_CLASS(fu_genesys_usbhub_device_parent_class)->setup(device, error)) { @@ -926,6 +929,21 @@ fu_genesys_usbhub_device_setup(FuDevice *device, GError **error) self->write_recovery_bank = address == self->fw_bank_addr[1]; } + /* get public key */ + if (!fu_memcpy_safe(self->public_key, + sizeof(self->public_key), + 0, /* dst */ + g_bytes_get_data(blob, NULL), + g_bytes_get_size(blob), + self->fw_data_total_count, /* src */ + sizeof(self->public_key), + error)) + return FALSE; + guid = + fwupd_guid_hash_data(self->public_key, sizeof(self->public_key), FWUPD_GUID_FLAG_NONE); + fu_device_add_instance_strup(device, "PUBKEY", guid); + fu_device_build_instance_id(device, NULL, "USB", "VID", "PID", "PUBKEY", NULL); + /* have MStar scaler */ if (fu_device_has_private_flag(device, FU_GENESYS_USBHUB_FLAG_HAS_MSTAR_SCALER)) if (!fu_genesys_usbhub_device_mstar_scaler_setup(self, error)) @@ -969,12 +987,31 @@ fu_genesys_usbhub_device_prepare_firmware(FuDevice *device, FwupdInstallFlags flags, GError **error) { + FuGenesysUsbhubDevice *self = FU_GENESYS_USBHUB_DEVICE(device); g_autoptr(FuFirmware) firmware = fu_genesys_usbhub_firmware_new(); /* parse firmware */ if (!fu_firmware_parse(firmware, fw, flags, error)) return NULL; + /* has public-key */ + if (g_bytes_get_size(fw) >= fu_firmware_get_size(firmware) + sizeof(self->public_key)) { + gsize bufsz = 0; + const guint8 *buf = g_bytes_get_data(fw, &bufsz); + + if (g_getenv("FWUPD_GENESYS_USBHUB_VERBOSE") != NULL) + fu_common_dump_raw(G_LOG_DOMAIN, "Footer", buf, bufsz); + if (memcmp(buf + fu_firmware_get_size(firmware), + self->public_key, + sizeof(self->public_key)) != 0) { + g_set_error_literal(error, + FWUPD_ERROR, + FWUPD_ERROR_SIGNATURE_INVALID, + "mismatch public-key"); + return NULL; + } + } + /* check size */ if (g_bytes_get_size(fw) > fu_device_get_firmware_size_max(device)) { g_set_error(error, diff --git a/plugins/genesys/fu-genesys-usbhub-firmware.c b/plugins/genesys/fu-genesys-usbhub-firmware.c index 10072ccd2..f7b809c02 100644 --- a/plugins/genesys/fu-genesys-usbhub-firmware.c +++ b/plugins/genesys/fu-genesys-usbhub-firmware.c @@ -153,6 +153,7 @@ fu_genesys_usbhub_firmware_parse(FuFirmware *firmware, } else { code_size = 0x6000; } + fu_firmware_set_size(firmware, code_size); /* calculate checksum */ if ((flags & FWUPD_INSTALL_FLAG_IGNORE_CHECKSUM) == 0) diff --git a/plugins/genesys/genesys.quirk b/plugins/genesys/genesys.quirk index 380a2fd8b..1bb56842f 100644 --- a/plugins/genesys/genesys.quirk +++ b/plugins/genesys/genesys.quirk @@ -1,9 +1,24 @@ -# M2xfd +# HP M2xfd # usbhub [USB\VID_03F0&PID_0610] Plugin = genesys Name = HP USB-C Controller +GenesysUsbhubSwitchRequest = 0xA1 +GenesysUsbhubReadRequest = 0xA2 +GenesysUsbhubWriteRequest = 0xA3 + +[USB\VID_03F0&PID_0610&PUBKEY_AB859399-95B8-5817-B521-9AD8CC7F5BD6] +Plugin = genesys +Name = HP M24fd USB-C Controller +Flags = has-mstar-scaler +GenesysUsbhubSwitchRequest = 0xA1 +GenesysUsbhubReadRequest = 0xA2 +GenesysUsbhubWriteRequest = 0xA3 + +[USB\VID_03F0&PID_0610&PUBKEY_6BE97D77-C2BA-5AA2-B7DF-B9B318BEC2B5] +Plugin = genesys +Name = HP M27fd USB-C Controller Flags = has-mstar-scaler GenesysUsbhubSwitchRequest = 0xA1 GenesysUsbhubReadRequest = 0xA2