Skip to content

About

libfprint driver for the Goodix 27c6:5F10 fingerprint sensor (HONOR MagicBook): FpDevice + host-side sigfm, with automatic TLS-PSK provisioning on Linux

Topics

Resources

Code of conduct

Stars

1 star

Watchers

0 watching

Forks

 
 

Repository files navigation

libfprint - Goodix 27c6:5F10 driver

A libfprint driver for the Goodix 27c6:5F10 fingerprint sensor - the patch-style reader that ships in HONOR MagicBook laptops and shows up as USB\VID_27C6&PID_5F10. This repo is a full libfprint tree with one extra driver on top, sitting on current libfprint master (1.94.100); everything outside libfprint/drivers/goodixtls/ is stock.

Status: no longer only my machine. Three other people have run it, on a MagicBook 2023 (GLO-G52), an X14 Plus (FMI-76) and a DRA-XX. More reports are still what I'm after before this goes upstream - see Testing.

The sensor

The 5F10 is a tiny 56x176 image sensor. It is too small for NBIS minutiae matching (the same wall the Goodix HTK32 hits), so the driver is not a normal FpImageDevice. Instead it:

  • talks to the chip over the goodixtls TLS-PSK transport (OpenSSL),
  • captures raw frames and matches them host-side with sigfm (FAST-9 + BRIEF-256 + RANSAC),
  • keeps a small gallery of raw frames in the FpPrint.

That "FpDevice + host-side sigfm + raw-frame gallery" shape is taken from AndyHazz's goodix53x5 driver - see Credits.

Sensor Goodix 27c6:5F10 (ST411SEC), 56x176
Firmware GF_ST411SEC_APP_12705
Laptops HONOR MagicBook family
Matcher pure-C sigfm (FAST-9 + BRIEF-256 + RANSAC), no OpenCV
Transport goodixtls, TLS 1.2 PSK (OpenSSL)

Quick start

The full detail is below; the shape of it is:

  1. Clone this repo - not the original. The original (Sbenazar/goodix-5f10-libfprint) has no Linux provisioning; the fork does:

    git clone https://github.com/mounkastel/goodix-5f10-libfprint
    cd goodix-5f10-libfprint
  2. Build and install exactly as described in Build and Install. The -Dlibdir= line in Install is the part people skip; without it fprintd never loads the driver. Stock libfprint 1.94.100 has no driver for the 5F10; build this tree.

  3. First run only - the driver provisions the sensor's PSK by itself on the first activation, then restart fprintd:

    sudo systemctl restart fprintd

    No configuration needed. To forbid the driver any write instead:

    sudo mkdir -p /etc/systemd/system/fprintd.service.d
    printf '[Service]\nEnvironment=GOODIX5F10_AUTOPROVISION=0\n' | \
      sudo tee /etc/systemd/system/fprintd.service.d/autoprovision.conf
    sudo systemctl daemon-reload
    sudo systemctl restart fprintd
  4. Enroll and verify - 24 touches, one per enroll-stage-passed line, the same finger every time, and let it run to the end:

    fprintd-enroll
    fprintd-verify

The sections below explain why each piece is there.

Per-device calibration

Every 5F10 leaves the factory with its own operating point and keeps it in OTP: an analog offset for the read path, and a code that sets the integration time. Three entries of the config table the driver uploads carry it.

Builds before this one shipped that table as it came off my laptop, so every other sensor ran at my operating point - on a DRA-XX, a baseline of 2993 counts where its own OTP asks for 2396. The driver reads the OTP during activation now and rewrites those three.

Prints from an older build should survive. I checked first, since the gallery is raw frames: enrolled at my own DAC, then verified with the config forced to two other people's values. 11 of 14 through at one, 5 of 6 at the other, 11 of 14 for the control

  • one finger and that few touches, but nothing I could pick out. New enrollments also carry a stamp of the point they were taken at, so a later surprise turns up in the log instead of as a finger that quietly stops working.

Re-enrolling is worth it anyway, just not for the reason you might think. The old print keeps working; what a fresh one gets you is a gallery recorded at the point your sensor is actually calibrated for, plus the stamp, so if recognition ever does go odd later there's something in the log to look at. How much better it is I honestly don't know - my own measurement couldn't tell the two apart.

GOODIX5F10_NO_OTP_PATCH=1 puts the sensor back on mine if you want to compare.

The catch: the per-device PSK (and how to make one)

The 5F10 only speaks TLS, and only with a 32-byte PSK. What ships in every unit is not a usable TLS key, so the host generates one itself. The TLS-PSK itself is generated by the host: the host draws 32 random bytes with the system CSPRNG, wraps them in a small blob and writes them to the MCU with a plain pre-TLS command (0xE0); it keeps a host copy for itself and reads the chip's stored hash back with command 0xE4.

So provisioning is a host-side operation, and there is nothing Windows-specific left once you know the wrap. This driver now does the whole thing on Linux:

  • Generated with the system CSPRNG.
  • Packed with the static key (goodix5f10_psk.c; Fixed constant of the sensor protocol; identical on every host. Test vectors: see tests/ for the expected output.).
  • Written with command 0xE0, then read back with 0xE4 and checked against SHA256(TLV-1 body).
  • Persisted to /var/lib/fprint/goodix-5f10/psk (raw 32 bytes, mode 0600).

The driver provisions automatically during activation whenever there is no key on disk, or the key on disk does not match the sensor. Set GOODIX5F10_AUTOPROVISION=0 to opt out and stay read-only: then a missing or mismatching key fails the open with an error instead of the sensor being overwritten.

There is also a standalone CLI that does the same over pyusb, with a dry-run default, for recovery and for machines where you cannot rebuild libfprint:

-> tools/goodix-5f10-provision — see its README.

The MCU PSK slot is rewritable (the Windows driver itself re-provisions on a mismatch), so a write is not a one-shot burn. It is still a write to a device with no publicly available recovery image. The driver writes on a missing or mismatching key unless you opt out with GOODIX5F10_AUTOPROVISION=0; the standalone CLI below, in contrast, never writes without --write.

If you would rather keep using the key Windows already generated, recover it offline and read-only with the companion tool:

-> goodix-5f10-psk

It drops 32 raw bytes at /var/lib/fprint/goodix-5f10/psk; the driver loads that file when it exists. This is now optional, not a requirement.

Build

You need meson, ninja, glib, gusb, udev and OpenSSL headers (on Ubuntu that is meson ninja-build libglib2.0-dev libgusb-dev libssl-dev systemd-dev). Tested with meson 1.10.1 and gcc 15.2.0 (Ubuntu 26.04) and MinGW-w64 gcc 16.1.0 (MSYS2); CI runs the same two commands on Ubuntu on every push.

That list is enough for the driver-only build below. A full build, which is what you want for Install, also pulls in the other drivers and needs libpixman-1-dev libcairo2-dev libgudev-1.0-dev on top - without them meson setup stops at "pixman is required for aes3500" or "udev is required for SPI support" (thanks @dimaCaptain).

Clone this fork, not the original - the original (Sbenazar/goodix-5f10-libfprint) does not have the Linux provisioning work yet:

git clone https://github.com/mounkastel/goodix-5f10-libfprint
cd goodix-5f10-libfprint
meson setup build -Ddrivers=goodixtls5f10 -Ddoc=false -Dgtk-examples=false -Dintrospection=false
ninja -C build

./build/libfprint/fprint-list-supported-devices should then list 27c6:5f10.

Install

Building is not enough. fprintd loads libfprint from the system library path, so the build has to end up there, and meson setup needs to be told where that is - the default prefix puts it in /usr/local/lib64, which is not in ld.so.conf on Fedora, and nothing ever picks it up (thanks @nexplorer-3e for that one):

# Fedora and other lib64 distros
meson setup build -Dprefix=/usr -Dlibdir=/usr/lib64 -Ddoc=false -Dgtk-examples=false
# Debian and Ubuntu
meson setup build -Dprefix=/usr -Dlibdir=/usr/lib/x86_64-linux-gnu -Ddoc=false -Dgtk-examples=false

ninja -C build && sudo ninja -C build install

If you're unsure which one you're on, ldconfig -p | grep libfprint-2.so.2 prints the path the loader actually uses, and that's the directory your build has to land in.

There's deliberately no -Ddrivers=goodixtls5f10 in that line. It's fine while you're testing out of the build tree, but a libfprint built with it contains this driver and nothing else, so installing that leaves your system unable to talk to any other fingerprint sensor.

One more trap, since I walked into it myself: do not park a backup copy next to the installed library. libfprint-2.so.2.0.0.bak carries the same SONAME as the real one, and ldconfig is free to point libfprint-2.so.2 at the backup - after which you're running the old build and wondering why your changes do nothing. Keep backups outside the library path.

First provision (Linux)

The sensor will not speak TLS until it has the PSK, and on a freshly wiped Linux install there is usually no key on disk yet. Two ways to get one:

Driver auto-provision (recommended)

No configuration needed: on the first activation the driver generates 32 random bytes, packs them with the same static key the MCU uses, writes them to the chip (command 0xE0), reads the stored hash back (0xE4) and requires it to equal SHA256(TLV-1 body) - only then does it save the raw key to /var/lib/fprint/goodix-5f10/psk (mode 0600). Every later open just checks the stored key against the sensor, and a stored key that no longer matches the chip is re-provisioned (generate, write, verify) the same way.

To forbid all writes instead, opt out:

sudo mkdir -p /etc/systemd/system/fprintd.service.d
printf '[Service]\nEnvironment=GOODIX5F10_AUTOPROVISION=0\n' | \
  sudo tee /etc/systemd/system/fprintd.service.d/autoprovision.conf
sudo systemctl daemon-reload
sudo systemctl restart fprintd

Then just enroll (below); the first successful activation logs generated and saved a new PSK to "/var/lib/fprint/goodix-5f10/psk". (A later re-provision of a mismatching sensor from an existing file logs writing the stored PSK … / re-provisioned the sensor from the stored PSK instead.)

With GOODIX5F10_AUTOPROVISION=0 nothing is ever written: a missing or mismatching key fails the open with an error instead of the sensor being overwritten.

Auto-provisioning and dual boot

Provisioning is on by default; GOODIX5F10_AUTOPROVISION=0 turns it off. It exists because the sensor key is a shared slot: the Windows driver also rewrites it on mismatch, so Linux restores its own key the same way instead of failing every boot after Windows ran.

Observed on one dual-boot machine: booting Windows to the lock screen, with no sign-in and no fingerprint use, changed the sensor key. The next Linux open rewrote the file key to the sensor and verify passed. Windows Hello kept working after that. This is one test, not a general claim.

Standalone CLI (recovery, or no rebuild)

tools/goodix-5f10-provision/goodix_5f10_provision.py runs the same bring-up, generate, write, verify and save over pyusb, and defaults to a read-only dry run:

# read-only: what the sensor has right now
sudo python3 tools/goodix-5f10-provision/goodix_5f10_provision.py

# generate, write, verify and save a new key
sudo python3 tools/goodix-5f10-provision/goodix_5f10_provision.py --write \
    --psk-file /var/lib/fprint/goodix-5f10/psk

See tools/goodix-5f10-provision.

Enroll & verify

# 1. make sure a PSK the sensor accepts is in place - see "First provision"
sudo systemctl restart fprintd
fprintd-enroll
fprintd-verify

Enrollment is 24 touches - exactly one enroll-stage-passed line per accepted touch. Use the same finger every time. The driver keeps one best frame per touch and only checks frame quality (a real ridge patch scores ~260 keypoints against the 12 required to pass), so almost any contact advances a stage and the finger is not checked for consistency. A thumb and an index finger both pass; that is expected. Do not stop early: if you interrupt the enroll, nothing is stored and fprintd-verify answers NoEnrolledPrints. The verify score gates are starting values; FAR/FRR are uncharacterised.

On Fedora/RHEL (SELinux) fprintd must be allowed to read the PSK, or activation fails with a permission error. Debian/Ubuntu use AppArmor - fprintd created the file itself, so skip this:

sudo chown root:root /var/lib/fprint/goodix-5f10/psk
sudo chcon -t fprintd_var_lib_t /var/lib/fprint/goodix-5f10/psk
sudo systemctl restart fprintd

One thing to know before you reach for examples/verify instead: it asks which finger to verify after opening the device, and it reads that answer straight from stdin inside a main loop callback. While the loop sits there, glib doesn't refresh the time it hands out to timeouts, so the next command the driver sends gets a deadline that already expired and fails on the spot with Command timed out: 0xae. It looks like the sensor went stale during the pause; it didn't, and the same pause with the loop left running is fine. fprintd never blocks its loop, so nothing you do through fprintd runs into this.

Testing

This is where you come in. I'm gathering reports before opening an upstream MR. If you have a 5F10:

  1. lsusb | grep 27c6:5f10 to confirm the sensor.
  2. Provision it - automatic on the first activation, see First provision; recovering the Windows key with goodix-5f10-psk also works.
  3. Build (above), enroll, verify.
  4. Paste your G_MESSAGES_DEBUG=all fprintd log into libfprint issue #735, or open an issue here. Good or bad, both are useful.

Credits

This stands on a stack of prior work:

  • the goodixtls TLS transport and protocol base from goodix-fp-linux-dev;
  • the pure-C sigfm port from buxel, which in turn comes from the original sigfm authors (Matthieu Charette, Natasha England-Elbro, Timur Mangliev);
  • the FpDevice host-side-matching architecture from AndyHazz/goodix53x5-libfprint.

License

LGPL-2.1-or-later, same as libfprint.

About

libfprint driver for the Goodix 27c6:5F10 fingerprint sensor (HONOR MagicBook): FpDevice + host-side sigfm, with automatic TLS-PSK provisioning on Linux

Topics

Resources

Code of conduct

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages