pok3r-custom / pok3rtool

Command line tool and library for keyboards using qmk-pok3r
BSD 3-Clause "New" or "Revised" License
41 stars 7 forks source link

Support for ISP bootrom's USB flash mechanism #12

Open hansemro opened 1 year ago

hansemro commented 1 year ago

ISP bootrom features programming via USB and UART using external software like HT32 Flash Programmer. Two important distinctions between ISP and IAP are that ISP bootrom is on all HT32 devices and ISP features a command to trigger mass erase (to clear flash security; to run QMK without lockups) without the need of an external SWD/JTAG debugger.

More information will be provided after analyzing USB packet captures on HT32F1654 and HT32F52352.

HT32 Flash Programmer Usage Notes

  1. Select IAP bootloader as target flash image (since it starts writing at address 0).
  2. Disable flash protection and security
  3. Tick 'All pages', 'Erase', 'Program', 'Verify'
  4. Short BOOT(1) pin to ground and plug in USB.
    • leave pin shorted since the device needs to re-enter ISP after mass erase reset
    • HT32F1654 and HT32F52352 in ISP shows up as "04d9:8010 Holtek Semiconductor, Inc."
    • read user guide on VMCR register in FMC for more information.
    • HT32F165x: BOOT0 should be shorted to 3V3 (if not already pulled up).
  5. Press 'Connect' then 'Programming'
  6. After keyboard is programmed, remove the pin short and reset the keyboard
  7. Proceed to flash application firmware with IAP mechanism as normal.

Tasks:

hansemro commented 1 year ago

Holtek HT32 Flash Commander is a command-line tool alternative to HT32 Flash Programmer described in the initial post. Unfortunately, it has bugs programming HT32F1654 where certain regions are left unprogrammed. The only difference I was able identify between Flash Commander and Flash Programmer is the frequency of status reports on the control endpoint.

As previously tested (https://gist.github.com/hansemro/acdb861d4bb9c5b52bac57d4dbf39601), IAP/ISP instructions (up-to 64) return codes are stored in a 64-byte buffer which are read over the control endpoint after sending the GET_REPORT control message (bmRequestType=0xa1, bRequest=0x01, wValue=0x0100, wLength=64). Once the status buffer is full, no entries will be saved until cleared by 4 new entries after filled or buffer read. Another thing to note is that a return code is saved after the operation is completed so the buffer may have fewer elements if read from too early.

HT32 Flash Programmer likely utilizes the buffer as a method to synchronize transactions (where 30 write requests yields 30 status entries over the span of one or more status requests). In contrast, HT32 Flash Commander does not wait for an equal number of write requests and may end up writing at a rate faster than can be consumed. More prototyping work is required to prove this theory...

If status report requests are necessary, then we may need to update rawhid to transmit/receive control messages in a way that is supported on all platforms.

Update: When buffer is full and gets 4 new instructions, the device reboots (which clears the buffer). So clearing the buffer before it gets full seems necessary for ISP flash programming.

hansemro commented 1 year ago

Updated cooler master gist python script for Holtek ISP with basic status report tests: https://gist.github.com/hansemro/76493b59cbade75309dde1fdbe1b103b

ChaoticEnigma commented 1 year ago

This is very interesting! I never thought about the ROM bootloader in the HT32, because the user manuals just didn't say anything specific about it.

The HT32 ISP User Manual doesn't say anything at all about USB functionality. But that document is pretty old, so I guess they just never published the updated document after they added USB to the HT32 ISP?

The format and commands of the protocol you've figured out look very similar to the HID-based protocol the original non-RGB POK3R used for firmware updates. So, I suspect this protocol was based on the USB version of the IAP protocol.

hansemro commented 1 year ago

Flash Commander user manual can be found in its install location and does describe connecting to ISP via USB. The command line tool features an engineering mode to do specific operations (mass erase, read/set flash security, program, crc, reset). It is just unfortunate that it cannot write properly to HT32F1654 (but works fine on HT32F52352).

hansemro commented 1 year ago

Kinda funny how I did recognize the ISP USB VID/PID (https://github.com/mateuszradomski/re-masterkeys/issues/1#issuecomment-1146783414) months ago, but was a bit too panicked to check how it was even possible for my bricked keyboard to be recognized over USB.

hansemro commented 1 year ago

Proof of concept branch with working writeFirmware operation: https://github.com/hansemro/pok3rtool/tree/holtek-isp-libusb-linux-poc

This targets Linux with new libusb-1.0 backend for now. My plan is to eventually replace rawhid backend drivers with a common libusb-1.0 driver to make development easier across platforms.

hansemro commented 1 year ago

Branch with Linux+Windows support: https://github.com/hansemro/pok3rtool/tree/holtek-isp-libusb-linux-windows-poc

Reboot delays may need to be extended if libusb fails to find/reopen devices as done with ISP protocol.

Cherry-pick this commit to build and install from msys2: https://github.com/hansemro/pok3rtool/commit/095864f9900c048db5a9876f872d7628e35cfb40

hansemro commented 1 year ago

Branch with Linux+Windows+macOS support: https://github.com/hansemro/pok3rtool/tree/holtek-isp-libusb-linux-windows-macos-poc

Demo with cooler-master-dev branch included: asciicast

hansemro commented 1 year ago

@ChaoticEnigma Possibly coming in the near future: dump firmware from flash-secured devices:

asciicast

hansemro commented 1 year ago

Not sure if the vulnerability can be assigned CVE since the vendor is not based in the US and not in the database, but I will still try to reach out the vendor so that they can fix it in future hardware revisions, notify their customers, etc.

ChaoticEnigma commented 1 year ago

Wow, that's very cool! Is the flash just not protected via the ISP read command? Or did you find a bug in it? IIRC, the flash security protection just disables flash reading altogether if a debug probe is detected, or if it is not booted from flash.

I think I have the firmware and bootloaders for all the Holtek-based keyboards I have. But good to know!

hansemro commented 1 year ago

Is the flash just not protected via the ISP read command?

Read command obeys flash security at least by reading out 0s to the endpoint buffers.

Or did you find a bug in it?

Didn't find find a bug in the read command. If I had to define it, there is a security design flaw that was overlooked for an ISP feature. The flaw is pretty inconspicuous at first glance.

IIRC, the flash security protection just disables flash reading altogether if a debug probe is detected...

Close. Flash access is only partially disabled with debugger attached: the processor will continue to fetch/decode/execute instructions but with the caveat that the processor loads 0s when loading from flash memory (this ultimately breaks firmware in flash). This is to prevent the debugger from overwriting an argument of a load instruction to read out an address from flash (https://blog.includesecurity.com/2015/11/firmware-dumping-technique-for-an-arm-cortex-m0-soc/). Also, the user manual specifies that only DCODE read access is blocked (and not ICODE).

IIRC, the flash security protection just disables flash reading altogether ... if it is not booted from flash.

I guess ROM bootloader counts as flash since it is able to access flash memory somehow.

hansemro commented 1 year ago

Found a new workaround that does not require WinUSB driver filter step or libusb.

Relevant change: https://github.com/hansemro/pok3rtool/commit/1259eb514b5dee9b679a6ed0d590cce45654295c Branch: https://github.com/hansemro/pok3rtool/tree/holtek-isp-dev

hansemro commented 1 year ago

Decided to write a standalone tool for flashing ISP devices: https://github.com/hansemro/ht32-dfu-tool