From 7dca55a3fc899555d1591ced12ea3e0224acf0ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20PORTAY?= Date: Tue, 31 May 2022 09:45:54 +0200 Subject: [PATCH] genesys: Check for validity of public-key The scaler may return invalid version or public-key. This checks for the public-key by verifing if it starts with "N = " for both devices usbhub and scaler; however, the scaler version cannot be checked. Note: Replug the USB-C cable is fixes the issue. --- plugins/genesys/fu-genesys-common.h | 5 ++++ plugins/genesys/fu-genesys-scaler-device.c | 29 +++++++++++++++----- plugins/genesys/fu-genesys-scaler-firmware.h | 7 ++--- plugins/genesys/fu-genesys-usbhub-device.c | 18 ++++++++---- 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/plugins/genesys/fu-genesys-common.h b/plugins/genesys/fu-genesys-common.h index a59d0724e..20ab8ac39 100644 --- a/plugins/genesys/fu-genesys-common.h +++ b/plugins/genesys/fu-genesys-common.h @@ -6,6 +6,11 @@ #pragma once +typedef struct { + guint8 N[0x206]; + guint8 E[0x00c]; +} FuGenesysPublicKey; + typedef struct { guint8 reg; guint8 expected_val; diff --git a/plugins/genesys/fu-genesys-scaler-device.c b/plugins/genesys/fu-genesys-scaler-device.c index 5d6dab8b7..87b4b293f 100644 --- a/plugins/genesys/fu-genesys-scaler-device.c +++ b/plugins/genesys/fu-genesys-scaler-device.c @@ -62,7 +62,7 @@ typedef struct { struct _FuGenesysScalerDevice { FuDevice parent_instance; guint8 level; - guint8 public_key[0x212]; + FuGenesysPublicKey public_key; FuCfiDevice *cfi_device; FuGenesysVendorCommand vc; guint32 sector_size; @@ -1556,12 +1556,27 @@ fu_genesys_scaler_device_probe(FuDevice *device, GError **error) return FALSE; if (!fu_genesys_scaler_device_get_public_key(self, - self->public_key, + (guint8 *)&self->public_key, sizeof(self->public_key), error)) return FALSE; - guid = - fwupd_guid_hash_data(self->public_key, sizeof(self->public_key), FWUPD_GUID_FLAG_NONE); + if (memcmp(self->public_key.N, "N = ", 4) != 0 || + memcmp(self->public_key.E, "E = ", 4) != 0) { + if (g_getenv("FWUPD_GENESYS_SCALER_VERBOSE") != NULL) { + fu_common_dump_raw(G_LOG_DOMAIN, + "PublicKey", + (const guint8 *)&self->public_key, + sizeof(self->public_key)); + } + g_set_error_literal(error, + FWUPD_ERROR, + FWUPD_ERROR_SIGNATURE_INVALID, + "invalid public-key"); + return FALSE; + } + guid = fwupd_guid_hash_data((const guint8 *)&self->public_key, + sizeof(self->public_key), + FWUPD_GUID_FLAG_NONE); if (!fu_genesys_scaler_device_get_version(self, buf, sizeof(buf), error)) return FALSE; @@ -1747,7 +1762,7 @@ fu_genesys_scaler_device_prepare_firmware(FuDevice *device, return NULL; } if (memcmp(&self->footer.data.public_key, - self->public_key, + &self->public_key, sizeof(self->footer.data.public_key)) != 0) { g_set_error_literal(error, FWUPD_ERROR, @@ -1854,7 +1869,7 @@ fu_genesys_scaler_device_to_string(FuDevice *device, guint idt, GString *str) if (fu_memcpy_safe((guint8 *)public_key_e, sizeof(public_key_e), 0, /* dst */ - self->public_key, + (const guint8 *)&self->public_key, sizeof(self->public_key), sizeof(self->public_key) - 2 - (sizeof(public_key_e) - 1), /* src */ sizeof(public_key_e) - 1, @@ -1866,7 +1881,7 @@ fu_genesys_scaler_device_to_string(FuDevice *device, guint idt, GString *str) if (fu_memcpy_safe((guint8 *)public_key_n, sizeof(public_key_n), 0, /* dst */ - self->public_key, + (const guint8 *)&self->public_key, sizeof(self->public_key), 4, /* src */ sizeof(public_key_n) - 1, diff --git a/plugins/genesys/fu-genesys-scaler-firmware.h b/plugins/genesys/fu-genesys-scaler-firmware.h index 37bdcd676..d9829d376 100644 --- a/plugins/genesys/fu-genesys-scaler-firmware.h +++ b/plugins/genesys/fu-genesys-scaler-firmware.h @@ -8,6 +8,8 @@ #include +#include "fu-genesys-common.h" + #define FU_TYPE_GENESYS_SCALER_FIRMWARE (fu_genesys_scaler_firmware_get_type()) G_DECLARE_FINAL_TYPE(FuGenesysScalerFirmware, fu_genesys_scaler_firmware, @@ -134,10 +136,7 @@ typedef struct __attribute__((packed)) { typedef union __attribute__((packed)) { guint8 raw[0x312]; struct { - struct { - guint8 N[0x206]; - guint8 E[0x00c]; - } __attribute__((packed)) public_key; + FuGenesysPublicKey public_key; FuGenesysMtkRsaHeader header; } data; } FuGenesysMtkFooter; diff --git a/plugins/genesys/fu-genesys-usbhub-device.c b/plugins/genesys/fu-genesys-usbhub-device.c index e70bf64bb..dc3500df5 100644 --- a/plugins/genesys/fu-genesys-usbhub-device.c +++ b/plugins/genesys/fu-genesys-usbhub-device.c @@ -171,7 +171,7 @@ struct _FuGenesysUsbhubDevice { gboolean read_first_bank; gboolean write_recovery_bank; - guint8 public_key[0x212]; + FuGenesysPublicKey public_key; FuCfiDevice *cfi_device; }; @@ -1096,7 +1096,7 @@ fu_genesys_usbhub_device_setup(FuDevice *device, GError **error) /* has public key */ if (fu_device_has_private_flag(device, FU_GENESYS_USBHUB_FLAG_HAS_PUBLIC_KEY)) { g_autofree gchar *guid = NULL; - if (!fu_memcpy_safe(self->public_key, + if (!fu_memcpy_safe((guint8 *)&self->public_key, sizeof(self->public_key), 0, /* dst */ g_bytes_get_data(blob, NULL), @@ -1105,7 +1105,15 @@ fu_genesys_usbhub_device_setup(FuDevice *device, GError **error) sizeof(self->public_key), error)) return FALSE; - guid = fwupd_guid_hash_data(self->public_key, + if (memcmp(&self->public_key.N, "N = ", 4) != 0 && + memcmp(&self->public_key.E, "E = ", 4) != 0) { + g_set_error_literal(error, + FWUPD_ERROR, + FWUPD_ERROR_SIGNATURE_INVALID, + "invalid public-key"); + return FALSE; + } + guid = fwupd_guid_hash_data((const guint8 *)&self->public_key, sizeof(self->public_key), FWUPD_GUID_FLAG_NONE); fu_device_add_instance_strup(device, "PUBKEY", guid); @@ -1202,9 +1210,9 @@ fu_genesys_usbhub_device_prepare_firmware(FuDevice *device, 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); + fu_common_dump_raw(G_LOG_DOMAIN, "PublicKey", buf, bufsz); if (memcmp(buf + fu_firmware_get_size(firmware), - self->public_key, + &self->public_key, sizeof(self->public_key)) != 0) { g_set_error_literal(error, FWUPD_ERROR,