Goodix Protocol - owaink/libfprint GitHub Wiki
This is everything we know about Goodix implementation of fingerprint scanning, mainly from reverse engineering the Windows driver. Some of it may be outdated, incomplete, inaccurate, missing, or straight up wrong. If you have any corrections to existing documentation or new information to contribute, feel free to do so. This wiki is an effort to make our documentation more accessible, as most has been left in conversations on discord.
Goodix Devices
Goodix devices are primarily found as embedded sensors in mobile devices like laptops and smartphones. We mostly focus on laptops here, but most of this should translate to smartphones or other devices if needed. The sensors we are working on primarily communicate over USB, though some do use SPI instead. Based on this page, future devices will most likely use SPI. Goodix devices are identified by their vendor ID of 27C6. If you have a different vendor ID, this project is likely of very little use to you. The specific device is then identified by it's device ID, such as 532D found on the Dell XPS 13 2-in-1 (7390), which is the device the writer of this documentation has. You can see a full list of the tracked devices in the #readme section of the community discord.
Encrypted Traffic
Some devices encrypt their traffic, making it much more difficult to reverse engineer. All devices with encryption discovered so far use TLS with a preshared key to encrypt the fingerprint image. Once that preshared key is known, you can see the fingerprint clearly. Commands to and from the device are generally not encrypted and can be seen in plain text. There are a few ways of getting around this:
Crack the preshared key that is already present
By determining the preshared key already on the scanner, we could listen into the traffic on every device. This has obvious security implications, so we won't go into detail here to prevent our efforts from undermining the security of Windows users. It has reportedly been cracked, but we don't recommend this option. If you are looking to dual boot Windows and Linux, this is the only option that allows the scanner to work on both without constant reflashing of firmware.
Overwrite the preshared key with a known one
Goodix devices use a Trust on First Use model, meaning the preshared key is provided by the driver when it is first initialized. By changing the preshared key after it has been generated, but before it has been transmitted to the device, we can provide a known preshared key for the device to use until the next time it is initialized (like when the driver is reinstalled). This is the preferred way of working around encryption.
Disable encryption all together
The Windows driver reads a few registry keys when it is loaded, with a few debug options that can be enabled. This option hasn't been thoroughly explored and likely won't be since a working method already exists. It may be discovered incidentally through further reverse engineering of the Windows driver
Protocol
Goodix devices use a client-server model for communicating with the driver. The driver can send a request to the device, the device will usually respond with an acknowledgement packet, then it will process the request. For example:
(> indicates driver to device, < indicates device to driver)
> GET_FIRMWARE_VERSION (A command to the device)
< ACK (Acknowledgement that the device received the command)
< GF5298_GM168SEC_APP_13016 (Some sort of reply)
This communication is wrapped in the USB protocol and sent in URBs. For fingerprint images, it is also wrapped in TLS encryption as discussed above.
The list of known commands are as follows:
| Command | Hex | Description |
|---|---|---|
| GOODIX_CMD_NOP | 0x00 | This is a no-operation command, it does nothing, but is used in this context to test if the device is responding before sending more useful commands |
| GOODIX_CMD_MCU_GET_IMAGE | 0x20 | Asks the device for a scanner, the reply is sent to the driver TLS encrypted |
| GOODIX_CMD_MCU_SWITCH_TO_FDT_DOWN | 0x32 | Specifics unknown, current theory is to ask the device to start listening for a finger to be placed on the scanner |
| GOODIX_CMD_MCU_SWITCH_TO_FDT_UP | 0x34 | Specifics unknown, current theory is to ask the device to start listening for a finger to be lifted from the scanner |
| GOODIX_CMD_MCU_SWITCH_TO_FDT_MODE | 0x36 | Specifics unknown, current theory is to ask the device to start listening for a finger to be lifted or placed on the scanner |
| GOODIX_CMD_NAV_0 | 0x50 | Specifics unknown, current theory is related to swipe navigation for mobile devices, unused on most devices |
| GOODIX_CMD_MCU_SWITCH_TO_SLEEP | 0x60 | Ask the scanner to go into sleep mode to conserve power, usually woken up with GOODIX_CMD_QUERY_MCU_STATE |
| GOODIX_CMD_MCU_SWITCH_TO_IDLE_MODE | 0x70 | Ask the scanner to idle to save power, not as deep as sleep mode |
| GOODIX_CMD_WRITE_SENSOR_REGISTER | 0x80 | Specifics are unknown, but this is called before and after getting an image from the sensor with GOODIX_CMD_MCU_GET_IMAGE |
| GOODIX_CMD_READ_SENSOR_REGISTER | 0x82 | Specifics unknown, this is performed only when the scanner is initialized |
| GOODIX_CMD_UPLOAD_CONFIG_MCU | 0x90 | Upload the config for the scanner, the config is just a binary blob, not sure what we are configuring here so its just copied from the windows driver |
| GOODIX_CMD_SET_POWERDOWN_SCAN_FREQUENCY | 0x94 | Unused and Unknown |
| GOODIX_CMD_ENABLE_CHIP | 0x96 | Unused and Unknown |
| GOODIX_CMD_RESET | 0xa2 | Reset the sensor, MCU, and/or the copy(?) depending on which flags are set |
| GOODIX_CMD_READ_OTP | 0xa6 | Read calibration information for the specific, individual sensor |
| GOODIX_CMD_FIRMWARE_VERSION | 0xa8 | Gives the string of the current firmware the scanner is running |
| GOODIX_CMD_QUERY_MCU_STATE | 0xae | Get the current state of the scanner? |
| GOODIX_CMD_ACK | 0xb0 | Acknowledge the previous command was received |
| GOODIX_CMD_REQUEST_TLS_CONNECTION | 0xd0 | Setup secure communication for transmitting fingerprint image |
| GOODIX_CMD_TLS_SUCCESSFULLY_ESTABLISHED | 0xd4 | Secure communication successful |
| GOODIX_CMD_PRESET_PSK_WRITE | 0xe0 | Write a new preshared key, this appears to only work on initial setup |
| GOODIX_CMD_PRESET_PSK_READ | 0xe4 | Checks that the preshared key defined when the firmware was uploaded to the scanner matches what the driver expects, returns a true or false, doesn't actually return the PSK |
| GOODIX_CMD_WRITE_FIRMWARE | 0xf0 | Write a chunk of firmware at the given offset |
| GOODIX_CMD_CHECK_FIRMWARE | 0xf4 | Sanity check that the firmware is as expected, returns the offset, length, and checksum |