Skip to content

Add 06cb:00cb (HP Pavilion x360 14-dh, sensor type 0x969) - #3

Open
ggiesen wants to merge 1 commit into
SimpleX-T:feat/sensor-type-0xd51from
ggiesen:add-06cb-00cb
Open

Add 06cb:00cb (HP Pavilion x360 14-dh, sensor type 0x969)#3
ggiesen wants to merge 1 commit into
SimpleX-T:feat/sensor-type-0xd51from
ggiesen:add-06cb-00cb

Conversation

@ggiesen

@ggiesen ggiesen commented Jul 9, 2026

Copy link
Copy Markdown

06cb:00cb is the HP Pavilion x360 14-dh1008ca fingerprint reader -- a Validity VCSFW sensor type 0x969 (identifies "57K0 FM-3439"), the same silicon as the ZBook 138a:00ab this branch already supports. So it reuses the existing 0x969 -> 0x199 profile handling and only needs its device registration, its own reset_blob, and its firmware.

What's here

  • usb.py: DEV_CB = (0x06cb, 0x00cb).
  • blobs_00cb.py: init_hardcoded, init_hardcoded_clean_slate, and db_write_enable are byte-identical to blobs_9a (imported from it); only reset_blob differs.
  • firmware_tables.py: 6_07f_hp_mis_qm.xpfwext, auto-fetched from HP SoftPaq sp138431 (URL + sha512 verified; validity-sensors-firmware extracts it via innoextract/cabextract like the other HP entries).

No sensor.py change -- the 0x969 alias and the FM-3439 suspend/resume handling on this branch already cover it (the capture() b[0]==3 fix already keys off real_device_type in (0xd51, 0x969)).

Why a device-specific reset_blob

This unit shipped paired to a previous host, and factory_reset() couldn't wipe it: the reset_blob from every existing set (blobs_90/97/9a/9d) is rejected 0404/04be on 0x00cb. So it needs its own. I recovered it by static RE of HP's Windows SGX driver (synaWudfBioUsb116SGX.dll) -- the signed blobs are stored there in a 30-entry descriptor table, without their leading 06 command byte. A passive USB capture is a dead end here (the driver's reset rides an ephemeral-ECDH bootstrap TLS session, so the key isn't recoverable from a pcap). Two ~12 KB table entries were size-plausible; I trialled both on hardware -- the 11972-byte one is accepted (0x0000, wipes the flash 5 partitions -> 0), the other rejected (0x04aa).

Validation

Confirmed on the actual 06cb:00cb hardware running this branch's exact code (real_type=0x969 at open): the sensor initializes, calibrates via the 0x969 -> 0x199 profile, and enroll, verify, and delete all work -- verify matches the enrolled finger and rejects others; it also survives a reboot (firmware restored into /run before the daemon opens). init_hardcoded / init_hardcoded_clean_slate / db_write_enable == blobs_9a is confirmed (the on-wire init_hardcoded matches and init_db succeeds). The reset_blob was confirmed on the foreign-paired unit (accepted 0x0000, wipes the flash); factory_reset sends it as a raw pre-TLS usb.cmd, so it's independent of the profile routing.

RE detail and the full story: uunicorn#263.

Same 0x969 silicon as the ZBook 138a:00ab already supported on this
branch, so it reuses the existing 0x199-profile handling and needs only
its own device registration, reset_blob, and firmware.

- usb.py: register DEV_CB = (0x06cb, 0x00cb).
- blobs_00cb.py: init_hardcoded / init_hardcoded_clean_slate /
  db_write_enable are byte-identical to blobs_9a; only reset_blob is
  06cb:00cb-specific (every existing set's reset_blob is rejected
  0404/04be on this chip, so factory_reset couldn't wipe a foreign
  pairing). Recovered by static RE of HP's Windows SGX driver
  (synaWudfBioUsb116SGX.dll) and confirmed on hardware.
- firmware_tables.py: fetch 6_07f_hp_mis_qm.xpfwext from HP SoftPaq
  sp138431 (validity-sensors-firmware auto-provisions it).

Confirmed on hardware: factory_reset wipes the foreign pairing, then
re-partition / pair / calibrate / enroll / verify all work.
@Karloss1234

Karloss1234 commented Aug 1, 2026

Copy link
Copy Markdown

I tested the factory reset behaviour on my HP ZBook with a Synaptics 06cb:00b7 0x969 sensor (not 06cb:00cb).

The reset_blob from blobs_00cb was not the one I originally had; after adding the 06cb-specific blob I was able to confirm that my sensor accepts the reset command:

response length: 2
response: 0000
reset_blob status: 0x0
Reset blob accepted. Rebooting...

However, the sensor did not perform a full flash wipe. After reboot, the existing partition layout remained and the provisioning data in partition 1 was still present.

I also confirmed:

  • fprintd-delete $USER removes the fingerprint records correctly (but doesn't compact the partition data).
  • Erasing the template/database partition removes/compacts enrolled templates (erase_flash(4)).
  • The sensor does not remove or compact any data after factory_reset. It seems to do nothing.

This suggests that accepting the reset_blob (0x0000) and performing a full reclaim/wipe may depend on the sensor's pairing state. My sensor appears to still be considered paired (my sensor is fully functional), so it does not enter the same reclaim path as the "foreign-paired" 06cb:00cb test case.

Has anyone tested whether 06cb:00b7 requires a different reset_blob, or whether the full flash wipe only occurs when the stored host pairing key is invalid?

@ggiesen

ggiesen commented Aug 2, 2026

Copy link
Copy Markdown
Author

Thanks for testing this -- useful data point, especially on 00b7.

The key thing your result shows: the reset_blob was accepted (0x0000), which means it's the correct blob for your 00b7 too. A wrong or mis-signed reset_blob gets rejected -- that's exactly what we saw while pinning 00cb's down (the 12100-byte candidate returned 0x04aa, and blobs_9a's own reset_blob returns 0404). So 00b7 doesn't appear to need a different reset_blob.

Your pairing-state hypothesis looks right, and it lines up with what we saw capturing the Windows driver on 00cb: it only reformats/reclaims when the sensor is foreign (host pairing key absent) -- that path shows a "double init" and wipes the partitions. On a validly-paired sensor the driver never reformats; get_flash_info is byte-identical before and after. So the full wipe is gated on the sensor being foreign, not on the reset_blob. On your working (paired) 00b7, the reset is accepted but is effectively a no-op against the flash, which is expected.

The practical upshot is that a functioning, paired sensor never needs factory_reset() at all -- that's the reclaim path for a foreign/unclaimable unit. You'd only observe the wipe by deliberately invalidating the stored host pairing, which isn't something you'd want to do to a working sensor. So I don't think there's anything to fix here for 00b7; the reset_blob is right, and the "does nothing" is the paired-state behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants