
{"id":2159,"date":"2026-09-26T17:00:00","date_gmt":"2026-09-26T15:00:00","guid":{"rendered":"https:\/\/www.pcjv.de\/?p=2159"},"modified":"2026-09-26T17:00:00","modified_gmt":"2026-09-26T15:00:00","slug":"goodix-5120-linux-a-fingerprint-reader-behind-the-keyboard-controller","status":"publish","type":"post","link":"https:\/\/www.pcjv.de\/?p=2159","title":{"rendered":"goodix-5120-linux: a fingerprint reader behind the keyboard controller"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">My Huawei MateBook has a fingerprint reader, a Goodix <code>27c6:5120<\/code>. No Linux distribution supports it, so on Ubuntu it was just a button. Now it unlocks <code>sudo<\/code> and the login screen with a finger, through a libfprint driver I wrote for it: <a href=\"https:\/\/github.com\/cwbudde\/goodix-5120-linux\">goodix-5120-linux<\/a>. Getting there involved a dead keyboard, a key hidden in Windows, and a sensor too small for ordinary fingerprint matching.<\/p>\n\n\n\n<!--more-->\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1260\" height=\"660\" src=\"\/wordpress\/wp-content\/uploads\/goodix-stack.png\" alt=\"Diagram: PAM and fprintd sit on top of the goodix5120 driver, which talks USB with TLS-PSK to an ITE embedded controller. The controller drives both the fingerprint sensor and the internal keyboard. The driver's key comes from the Windows partition.\" class=\"wp-image-2158\" srcset=\"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/goodix-stack.png 1260w, https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/goodix-stack-300x157.png 300w, https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/goodix-stack-1024x536.png 1024w, https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/goodix-stack-768x402.png 768w\" sizes=\"auto, (max-width: 1260px) 100vw, 1260px\" \/><figcaption class=\"wp-element-caption\">The reader is not wired to the host directly. It sits behind the embedded controller, the same chip that runs the keyboard.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Four commands, no keyboard<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The sensor is not a USB device of its own. It hangs off the laptop&#8217;s ITE embedded controller (EC), which also scans the internal keyboard and looks to Linux like a USB serial port. The open-source <a href=\"https:\/\/github.com\/goodix-fp-linux-dev\/goodix-fp-dump\">goodix-fp-dump<\/a> project describes the protocol of this sensor family, so my first probe sent four harmless-looking commands from it: a no-op, the firmware version, a calibration read and a key read. All four answered with valid checksums. Then the keyboard stopped working.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Linux noticed nothing. No USB error, no kernel message; the EC had simply stopped sending keystrokes. A reboot did not help. Bisecting the probe found the culprit: the key read, sent with an empty argument where the Windows driver always sends eight bytes. That froze the EC&#8217;s firmware, keyboard included. Finding a reset took longer still. The one that works on this machine is to shut down, leave the charger plugged in and hold the power button for 40 seconds.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Everything since goes through a single send gate. It refuses any command the driver does not know and any payload whose length differs from what the Windows driver sends. The commands that write firmware or the key are not in the driver at all. The coding agents I worked with never touched the device either: they built and tested against a fake EC in software, and I ran every live test myself.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The key lives in Windows<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Beyond the first few commands, the EC only talks over TLS with a pre-shared key, 32 random bytes that the Windows driver wrote into the reader when it set it up. Windows keeps its copy sealed with DPAPI. The repository&#8217;s <code>goodix-dpapi<\/code> tool unseals it offline from the Windows partition, mounted read-only, so Windows Hello keeps working. The flip side: without the Windows installation that set up the reader, there is no key, and writing a new one would overwrite Windows&#8217;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The key was right, but the handshake still took a while. Its first attempt stalled halfway and left the EC stuck again. Once the Go prototype got through, the C driver inside libfprint did not: the EC answered it with a TLS error. What finally helped was timing. The EC does not like the host&#8217;s TLS records arriving back to back, so the driver now leaves a gap between them, as the Windows driver does.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Too small for minutiae<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">An image from the sensor is 64 \u00d7 80 pixels, a patch of skin only a few millimetres across. libfprint&#8217;s usual matcher compares minutiae, the points where ridges end or split, and needs at least ten of them per image. These images have one to five. No amount of scaling changed that; there just is not more finger in the picture.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The way out came from the community&#8217;s fork for similar small Goodix sensors: SIGFM, which matches images by their texture features instead. Enrolling takes 15 touches, each placed a little differently, so the template covers more of the finger than one image can. In tests, the enrolled finger scored from 36 up to over 250,000, other fingers never more than 9, against an acceptance threshold of 24.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using it<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">No package gets replaced. An install script copies the patched libfprint to <code>\/opt<\/code> and adds a systemd drop-in that makes Ubuntu&#8217;s own fprintd load it. From there it is the normal Linux setup:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo .\/goodix5120-fprintd.sh install psk.bin\nfprintd-enroll -f right-index-finger\nsudo pam-auth-update --enable fprintd<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Opening the reader, handshake included, takes about half a second, and the match comes about a tenth of a second after the finger lands, before it lifts. The one fix outside the driver was GNOME&#8217;s lock screen: it runs a password and a fingerprint login side by side, and with fprintd in both they fought over the reader, so the password prompt hung for ten seconds. The installer now keeps fprintd out of the password one.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Trying it<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is a driver for one laptop: the MateBook <code>HVY-WXX9<\/code> with EC firmware <code>GF_ITE_EC_20063<\/code>, which the driver checks for. Two calibration values are still those of my unit, so another one may need its own. You also need the Windows installation that set up the reader, for the key. If that describes your machine, the <a href=\"https:\/\/github.com\/cwbudde\/goodix-5120-linux\">README<\/a> has the steps; <code>just bundle<\/code> builds the library in Docker.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>My Huawei MateBook has a fingerprint reader, a Goodix 27c6:5120. No Linux distribution supports it, so on Ubuntu it was just a button. Now it unlocks sudo and the login screen with a finger, through a libfprint driver I wrote for it: goodix-5120-linux. Getting there involved a dead keyboard, a key hidden in Windows, and [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":2170,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[44],"tags":[],"class_list":["post-2159","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>goodix-5120-linux: a fingerprint reader behind the keyboard controller - Christian&#039;s private site<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.pcjv.de\/?p=2159\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"goodix-5120-linux: a fingerprint reader behind the keyboard controller\",\"datePublished\":\"2026-09-26T15:00:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159\"},\"wordCount\":790,\"image\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.pcjv.de\\\/wordpress\\\/wp-content\\\/uploads\\\/teaser-goodix.jpg\",\"articleSection\":[\"Linux\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159\",\"url\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159\",\"name\":\"goodix-5120-linux: a fingerprint reader behind the keyboard controller - Christian&#039;s private site\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.pcjv.de\\\/wordpress\\\/wp-content\\\/uploads\\\/teaser-goodix.jpg\",\"datePublished\":\"2026-09-26T15:00:00+00:00\",\"author\":{\"@id\":\"\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.pcjv.de\\\/?p=2159\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159#primaryimage\",\"url\":\"https:\\\/\\\/www.pcjv.de\\\/wordpress\\\/wp-content\\\/uploads\\\/teaser-goodix.jpg\",\"contentUrl\":\"https:\\\/\\\/www.pcjv.de\\\/wordpress\\\/wp-content\\\/uploads\\\/teaser-goodix.jpg\",\"width\":480,\"height\":360},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/?p=2159#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.pcjv.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"goodix-5120-linux: a fingerprint reader behind the keyboard controller\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.pcjv.de\\\/#website\",\"url\":\"https:\\\/\\\/www.pcjv.de\\\/\",\"name\":\"Christian&#039;s private site\",\"description\":\"Private site of Christian-W. Budde\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.pcjv.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"goodix-5120-linux: a fingerprint reader behind the keyboard controller - Christian&#039;s private site","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.pcjv.de\/?p=2159","twitter_misc":{"Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.pcjv.de\/?p=2159#article","isPartOf":{"@id":"https:\/\/www.pcjv.de\/?p=2159"},"author":{"name":"","@id":""},"headline":"goodix-5120-linux: a fingerprint reader behind the keyboard controller","datePublished":"2026-09-26T15:00:00+00:00","mainEntityOfPage":{"@id":"https:\/\/www.pcjv.de\/?p=2159"},"wordCount":790,"image":{"@id":"https:\/\/www.pcjv.de\/?p=2159#primaryimage"},"thumbnailUrl":"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/teaser-goodix.jpg","articleSection":["Linux"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.pcjv.de\/?p=2159","url":"https:\/\/www.pcjv.de\/?p=2159","name":"goodix-5120-linux: a fingerprint reader behind the keyboard controller - Christian&#039;s private site","isPartOf":{"@id":"https:\/\/www.pcjv.de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.pcjv.de\/?p=2159#primaryimage"},"image":{"@id":"https:\/\/www.pcjv.de\/?p=2159#primaryimage"},"thumbnailUrl":"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/teaser-goodix.jpg","datePublished":"2026-09-26T15:00:00+00:00","author":{"@id":""},"breadcrumb":{"@id":"https:\/\/www.pcjv.de\/?p=2159#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.pcjv.de\/?p=2159"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.pcjv.de\/?p=2159#primaryimage","url":"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/teaser-goodix.jpg","contentUrl":"https:\/\/www.pcjv.de\/wordpress\/wp-content\/uploads\/teaser-goodix.jpg","width":480,"height":360},{"@type":"BreadcrumbList","@id":"https:\/\/www.pcjv.de\/?p=2159#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.pcjv.de\/"},{"@type":"ListItem","position":2,"name":"goodix-5120-linux: a fingerprint reader behind the keyboard controller"}]},{"@type":"WebSite","@id":"https:\/\/www.pcjv.de\/#website","url":"https:\/\/www.pcjv.de\/","name":"Christian&#039;s private site","description":"Private site of Christian-W. Budde","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.pcjv.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"}]}},"_links":{"self":[{"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/posts\/2159","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2159"}],"version-history":[{"count":0,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/posts\/2159\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=\/wp\/v2\/media\/2170"}],"wp:attachment":[{"href":"https:\/\/www.pcjv.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2159"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2159"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pcjv.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2159"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}