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 #pragma once
typedef struct {
guint8 N[0x206];
guint8 E[0x00c];
} FuGenesysPublicKey;
typedef struct { typedef struct {
guint8 reg; guint8 reg;
guint8 expected_val; guint8 expected_val;

View File

@ -62,7 +62,7 @@ typedef struct {
struct _FuGenesysScalerDevice { struct _FuGenesysScalerDevice {
FuDevice parent_instance; FuDevice parent_instance;
guint8 level; guint8 level;
guint8 public_key[0x212]; FuGenesysPublicKey public_key;
FuCfiDevice *cfi_device; FuCfiDevice *cfi_device;
FuGenesysVendorCommand vc; FuGenesysVendorCommand vc;
guint32 sector_size; guint32 sector_size;
@ -1556,12 +1556,27 @@ fu_genesys_scaler_device_probe(FuDevice *device, GError **error)
return FALSE; return FALSE;
if (!fu_genesys_scaler_device_get_public_key(self, if (!fu_genesys_scaler_device_get_public_key(self,
self->public_key, (guint8 *)&self->public_key,
sizeof(self->public_key), sizeof(self->public_key),
error)) error))
return FALSE; return FALSE;
guid = if (memcmp(self->public_key.N, "N = ", 4) != 0 ||
fwupd_guid_hash_data(self->public_key, sizeof(self->public_key), FWUPD_GUID_FLAG_NONE); 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)) if (!fu_genesys_scaler_device_get_version(self, buf, sizeof(buf), error))
return FALSE; return FALSE;
@ -1747,7 +1762,7 @@ fu_genesys_scaler_device_prepare_firmware(FuDevice *device,
return NULL; return NULL;
} }
if (memcmp(&self->footer.data.public_key, if (memcmp(&self->footer.data.public_key,
self->public_key, &self->public_key,
sizeof(self->footer.data.public_key)) != 0) { sizeof(self->footer.data.public_key)) != 0) {
g_set_error_literal(error, g_set_error_literal(error,
FWUPD_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, if (fu_memcpy_safe((guint8 *)public_key_e,
sizeof(public_key_e), sizeof(public_key_e),
0, /* dst */ 0, /* dst */
self->public_key, (const guint8 *)&self->public_key,
sizeof(self->public_key), sizeof(self->public_key),
sizeof(self->public_key) - 2 - (sizeof(public_key_e) - 1), /* src */ sizeof(self->public_key) - 2 - (sizeof(public_key_e) - 1), /* src */
sizeof(public_key_e) - 1, 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, if (fu_memcpy_safe((guint8 *)public_key_n,
sizeof(public_key_n), sizeof(public_key_n),
0, /* dst */ 0, /* dst */
self->public_key, (const guint8 *)&self->public_key,
sizeof(self->public_key), sizeof(self->public_key),
4, /* src */ 4, /* src */
sizeof(public_key_n) - 1, sizeof(public_key_n) - 1,

View File

@ -8,6 +8,8 @@
#include <fwupdplugin.h> #include <fwupdplugin.h>
#include "fu-genesys-common.h"
#define FU_TYPE_GENESYS_SCALER_FIRMWARE (fu_genesys_scaler_firmware_get_type()) #define FU_TYPE_GENESYS_SCALER_FIRMWARE (fu_genesys_scaler_firmware_get_type())
G_DECLARE_FINAL_TYPE(FuGenesysScalerFirmware, G_DECLARE_FINAL_TYPE(FuGenesysScalerFirmware,
fu_genesys_scaler_firmware, fu_genesys_scaler_firmware,
@ -134,10 +136,7 @@ typedef struct __attribute__((packed)) {
typedef union __attribute__((packed)) { typedef union __attribute__((packed)) {
guint8 raw[0x312]; guint8 raw[0x312];
struct { struct {
struct { FuGenesysPublicKey public_key;
guint8 N[0x206];
guint8 E[0x00c];
} __attribute__((packed)) public_key;
FuGenesysMtkRsaHeader header; FuGenesysMtkRsaHeader header;
} data; } data;
} FuGenesysMtkFooter; } FuGenesysMtkFooter;

View File

@ -171,7 +171,7 @@ struct _FuGenesysUsbhubDevice {
gboolean read_first_bank; gboolean read_first_bank;
gboolean write_recovery_bank; gboolean write_recovery_bank;
guint8 public_key[0x212]; FuGenesysPublicKey public_key;
FuCfiDevice *cfi_device; FuCfiDevice *cfi_device;
}; };
@ -1096,7 +1096,7 @@ fu_genesys_usbhub_device_setup(FuDevice *device, GError **error)
/* has public key */ /* has public key */
if (fu_device_has_private_flag(device, FU_GENESYS_USBHUB_FLAG_HAS_PUBLIC_KEY)) { if (fu_device_has_private_flag(device, FU_GENESYS_USBHUB_FLAG_HAS_PUBLIC_KEY)) {
g_autofree gchar *guid = NULL; g_autofree gchar *guid = NULL;
if (!fu_memcpy_safe(self->public_key, if (!fu_memcpy_safe((guint8 *)&self->public_key,
sizeof(self->public_key), sizeof(self->public_key),
0, /* dst */ 0, /* dst */
g_bytes_get_data(blob, NULL), g_bytes_get_data(blob, NULL),
@ -1105,7 +1105,15 @@ fu_genesys_usbhub_device_setup(FuDevice *device, GError **error)
sizeof(self->public_key), sizeof(self->public_key),
error)) error))
return FALSE; 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), sizeof(self->public_key),
FWUPD_GUID_FLAG_NONE); FWUPD_GUID_FLAG_NONE);
fu_device_add_instance_strup(device, "PUBKEY", guid); 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); const guint8 *buf = g_bytes_get_data(fw, &bufsz);
if (g_getenv("FWUPD_GENESYS_USBHUB_VERBOSE") != NULL) 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), if (memcmp(buf + fu_firmware_get_size(firmware),
self->public_key, &self->public_key,
sizeof(self->public_key)) != 0) { sizeof(self->public_key)) != 0) {
g_set_error_literal(error, g_set_error_literal(error,
FWUPD_ERROR, FWUPD_ERROR,