From 9b2775458cee8e7930c37793187e81d0a90f7c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Rebelo?= Date: Mon, 5 Sep 2022 23:54:08 +0100 Subject: [PATCH] Huami: Improve large firmware zip file handling --- .../activities/FwAppInstallerActivity.java | 1 + .../huami/amazfitgts3/AmazfitGTS3FWHelper.java | 5 +++++ .../devices/huami/miband7/MiBand7FWHelper.java | 5 +++++ .../devices/miband/AbstractMiBandFWHelper.java | 13 ++++++++++++- .../devices/huami/Huami2021FirmwareInfo.java | 16 ++++++++++------ .../amazfitgts3/AmazfitGTS3FirmwareInfo.java | 5 +++++ .../huami/miband7/MiBand7FirmwareInfo.java | 5 +++++ 7 files changed, 43 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/FwAppInstallerActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/FwAppInstallerActivity.java index 805dfe2c54..1e0eebe449 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/FwAppInstallerActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/FwAppInstallerActivity.java @@ -246,6 +246,7 @@ public class FwAppInstallerActivity extends AbstractGBActivity implements Instal for (DeviceCoordinator coordinator : getAllCoordinatorsConnectedFirst()) { InstallHandler handler = coordinator.findInstallHandler(uri, this); if (handler != null) { + LOG.info("Found install handler {} from {}", handler.getClass(), coordinator.getClass()); return handler; } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts3/AmazfitGTS3FWHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts3/AmazfitGTS3FWHelper.java index bc56c52e70..f37b4eddd9 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts3/AmazfitGTS3FWHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/amazfitgts3/AmazfitGTS3FWHelper.java @@ -29,6 +29,11 @@ public class AmazfitGTS3FWHelper extends HuamiFWHelper { super(uri, context); } + @Override + public long getMaxExpectedFileSize() { + return 1024 * 1024 * 128; // 128.0MB + } + @Override protected void determineFirmwareInfo(final byte[] wholeFirmwareBytes) { firmwareInfo = new AmazfitGTS3FirmwareInfo(wholeFirmwareBytes); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband7/MiBand7FWHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband7/MiBand7FWHelper.java index ed9bf60da1..a3dd2ef411 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband7/MiBand7FWHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/miband7/MiBand7FWHelper.java @@ -29,6 +29,11 @@ public class MiBand7FWHelper extends HuamiFWHelper { super(uri, context); } + @Override + public long getMaxExpectedFileSize() { + return 1024 * 1024 * 32; // 32.0MB + } + @Override protected void determineFirmwareInfo(final byte[] wholeFirmwareBytes) { firmwareInfo = new MiBand7FirmwareInfo(wholeFirmwareBytes); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/AbstractMiBandFWHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/AbstractMiBandFWHelper.java index 3f02c709fd..d3e7a7a8e4 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/AbstractMiBandFWHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/AbstractMiBandFWHelper.java @@ -53,8 +53,12 @@ public abstract class AbstractMiBandFWHelper { throw new IOException("Firmware has a filename that looks like a Pebble app/firmware."); } + if (uriHelper.getFileSize() > getMaxExpectedFileSize()) { + throw new IOException("Firmware size is larger than the maximum expected file size of " + getMaxExpectedFileSize()); + } + try (InputStream in = new BufferedInputStream(uriHelper.openInputStream())) { - this.fw = FileUtils.readAll(in, 1024 * 1024 * 32); // 32.0 MB + this.fw = FileUtils.readAll(in, getMaxExpectedFileSize()); determineFirmwareInfo(fw); } catch (IOException ex) { throw ex; // pass through @@ -112,6 +116,13 @@ public abstract class AbstractMiBandFWHelper { return false; } + /** + * The maximum expected file size, in bytes. Files larger than this are assumed to be invalid. + */ + public long getMaxExpectedFileSize() { + return 1024 * 1024 * 16; // 16.0MB + } + protected abstract int[] getWhitelistedFirmwareVersions(); public abstract boolean isFirmwareGenerallyCompatibleWith(GBDevice device); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021FirmwareInfo.java index 67c16c10a1..3968b5cced 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/Huami2021FirmwareInfo.java @@ -41,16 +41,20 @@ public abstract class Huami2021FirmwareInfo extends AbstractHuamiFirmwareInfo { 0x50, 0x4B, 0x03, 0x04 }; - public static final byte[] FW_HEADER = new byte[]{ - 0x51, 0x71 - }; - public Huami2021FirmwareInfo(final byte[] bytes) { super(bytes); } + /** + * The device name, to search on firmware.bin in order to determine compatibility. + */ public abstract String deviceName(); + /** + * The expected firmware header bytes, to search on firmware.bin in order to determine compatibility. + */ + public abstract byte[] getExpectedFirmwareHeader(); + @Override protected HuamiFirmwareType determineFirmwareType(final byte[] bytes) { if (ArrayUtils.equals(bytes, UIHHContainer.UIHH_HEADER, 0)) { @@ -137,8 +141,8 @@ public abstract class Huami2021FirmwareInfo extends AbstractHuamiFirmwareInfo { return false; } - if (!ArrayUtils.equals(firmwareBin, FW_HEADER, 0)) { - LOG.warn("Unexpected firmware header: {}", GB.hexdump(Arrays.copyOfRange(firmwareBin, 0, FW_HEADER.length + 1))); + if (!ArrayUtils.equals(firmwareBin, getExpectedFirmwareHeader(), 0)) { + LOG.warn("Unexpected firmware header: {}", GB.hexdump(Arrays.copyOfRange(firmwareBin, 0, getExpectedFirmwareHeader().length + 3))); return false; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts3/AmazfitGTS3FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts3/AmazfitGTS3FirmwareInfo.java index fe9638bce5..3b4a0ff4fb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts3/AmazfitGTS3FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/amazfitgts3/AmazfitGTS3FirmwareInfo.java @@ -43,6 +43,11 @@ public class AmazfitGTS3FirmwareInfo extends Huami2021FirmwareInfo { return HuamiConst.AMAZFIT_GTS3_NAME; } + @Override + public byte[] getExpectedFirmwareHeader() { + return new byte[]{0x00, 0x00, 0x50}; // Probably bogus, only checked against 2 firmware files + } + @Override public boolean isGenerallyCompatibleWith(final GBDevice device) { return isHeaderValid() && device.getType() == DeviceType.AMAZFITGTS3; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband7/MiBand7FirmwareInfo.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband7/MiBand7FirmwareInfo.java index 46eef5aac5..1e592053fb 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband7/MiBand7FirmwareInfo.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/huami/miband7/MiBand7FirmwareInfo.java @@ -44,6 +44,11 @@ public class MiBand7FirmwareInfo extends Huami2021FirmwareInfo { return HuamiConst.XIAOMI_SMART_BAND7_NAME; } + @Override + public byte[] getExpectedFirmwareHeader() { + return new byte[]{0x51, 0x71}; + } + @Override public boolean isGenerallyCompatibleWith(final GBDevice device) { return isHeaderValid() && device.getType() == DeviceType.MIBAND7;