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.
This commit is contained in:
Gaël PORTAY 2022-05-31 09:45:54 +02:00 committed by Gaël PORTAY
parent e6f049625e
commit 7dca55a3fc
4 changed files with 43 additions and 16 deletions

View File

@ -6,6 +6,11 @@
#pragma once
typedef struct {
guint8 N[0x206];
guint8 E[0x00c];
} FuGenesysPublicKey;
typedef struct {
guint8 reg;
guint8 expected_val;

View File

@ -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,

View File

@ -8,6 +8,8 @@
#include <fwupdplugin.h>
#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;

View File

@ -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,