libfprint/libfprint/drivers/validity/validity_hal.c
Leonardo Francisco f35dd0322a validity: externalize proprietary blob data to runtime-loaded files
Remove ~400KB of compiled-in .inc blob files and replace with a runtime
data loader that reads HMAC-SHA256 verified .bin files from disk at
device open time.

New components:
- validity_data.h/c: Runtime data file loader with HMAC-SHA256 integrity
  verification. Searches /usr/share/libfprint/validity/ and
  /usr/local/share/libfprint/validity/ for per-device and common data
  files. Skipped entirely in emulation mode.

Changes to existing code:
- validity.c: New OPEN_LOAD_DATA SSM state loads device and common data
  files between firmware info reception and init sequence. Populates TLS
  key pointers from loaded data. Frees data stores on close.
- validity_hal.h/c: Simplified device_table to vid/pid/flash_layout only
  (all blob pointers and partition_sig removed from structs).
- validity_pair.c/h: Updated make_cert, build_partition_flash_cmd,
  build_tls_flash to take data parameters instead of using compiled-in
  arrays. Reset/DBE blob accessors use data store.
- validity_tls.c/h: Removed 4 static key arrays, added pointer fields
  to ValidityTlsState populated from loaded data.
- validity_db.c/h, validity_fwext.c/h: Updated get_write_enable_blob
  to take FpiDeviceValidity* and access data store.
- validity_enroll.c: Updated all 5 callers for new signatures.

Deleted files:
- validity_blobs_0090.inc, validity_blobs_0097.inc,
  validity_blobs_009a.inc, validity_blobs_009d.inc (~400KB)
- validity_pair_constants.inc (~6KB)

Tests (171 total, all passing):
- 15 data loader tests covering: empty store, double-free safety,
  valid/corrupt/too-small/nonexistent file loading, tag enum,
  load_device with missing dir/missing mandatory file/valid files/
  corrupt HMAC, load_common with missing/valid files, enroll
  db_write_enable accessor with empty and populated stores.
- All existing unit and integration tests updated and passing.

The data files are distributed separately via the
libfprint-validity-data package.
2026-04-22 03:06:34 +00:00

122 lines
4.3 KiB
C

/*
* Hardware Abstraction Layer for Validity/Synaptics VCSFW fingerprint sensors
*
* Per-device blob data, flash partition layouts, and pairing constants.
*
* Copyright (C) 2024 libfprint contributors
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FP_COMPONENT "validity"
#include "validity_hal.h"
#include "fpi-log.h"
/* ================================================================
* Flash partition layouts
*
* Standard layout: used by PID 0097, 009a, 009d
* Partition 4 (template DB) = 0x80000 bytes
*
* PID 0090 layout: smaller DB partition
* Partition 4 (template DB) = 0x30000 bytes
* ================================================================ */
/* Standard partition table (0097, 009a, 009d) */
static const ValidityPartition flash_partitions_standard[] = {
{ .id = 1, .type = 4, .access_lvl = 7, .offset = 0x00001000, .size = 0x00001000 }, /* cert store */
{ .id = 2, .type = 1, .access_lvl = 2, .offset = 0x00002000, .size = 0x0003e000 }, /* xpfwext */
{ .id = 5, .type = 5, .access_lvl = 3, .offset = 0x00040000, .size = 0x00008000 }, /* reserved */
{ .id = 6, .type = 6, .access_lvl = 3, .offset = 0x00048000, .size = 0x00008000 }, /* calibration */
{ .id = 4, .type = 3, .access_lvl = 5, .offset = 0x00050000, .size = 0x00080000 }, /* template DB */
};
/* PID 0090 partition table (smaller DB) */
static const ValidityPartition flash_partitions_0090[] = {
{ .id = 1, .type = 4, .access_lvl = 7, .offset = 0x00001000, .size = 0x00001000 }, /* cert store */
{ .id = 2, .type = 1, .access_lvl = 2, .offset = 0x00002000, .size = 0x0003e000 }, /* xpfwext */
{ .id = 5, .type = 5, .access_lvl = 3, .offset = 0x00040000, .size = 0x00008000 }, /* reserved */
{ .id = 6, .type = 6, .access_lvl = 3, .offset = 0x00048000, .size = 0x00008000 }, /* calibration */
{ .id = 4, .type = 3, .access_lvl = 5, .offset = 0x00050000, .size = 0x00030000 }, /* template DB */
};
/* Layout descriptors */
static const ValidityFlashLayout flash_layout_standard = {
.partitions = flash_partitions_standard,
.num_partitions = G_N_ELEMENTS (flash_partitions_standard),
};
static const ValidityFlashLayout flash_layout_0090 = {
.partitions = flash_partitions_0090,
.num_partitions = G_N_ELEMENTS (flash_partitions_0090),
};
/* ================================================================
* Per-device descriptors
*
* Blob data (init, reset, db_write_enable) has been moved to external
* .bin files loaded at runtime by validity_data.c. Only VID/PID and
* flash layout remain here.
* ================================================================ */
static const ValidityDeviceDesc device_table[] = {
[VALIDITY_HAL_DEV_90] = {
.vid = 0x138a,
.pid = 0x0090,
.flash_layout = &flash_layout_0090,
},
[VALIDITY_HAL_DEV_97] = {
.vid = 0x138a,
.pid = 0x0097,
.flash_layout = &flash_layout_standard,
},
[VALIDITY_HAL_DEV_9A] = {
.vid = 0x06cb,
.pid = 0x009a,
.flash_layout = &flash_layout_standard,
},
[VALIDITY_HAL_DEV_9D] = {
.vid = 0x138a,
.pid = 0x009d,
.flash_layout = &flash_layout_standard,
},
};
/* ================================================================
* Lookup functions
* ================================================================ */
const ValidityDeviceDesc *
validity_hal_device_lookup (guint dev_type)
{
if (dev_type >= G_N_ELEMENTS (device_table))
return NULL;
return &device_table[dev_type];
}
const ValidityDeviceDesc *
validity_hal_device_lookup_by_pid (guint16 vid, guint16 pid)
{
for (gsize i = 0; i < G_N_ELEMENTS (device_table); i++)
if (device_table[i].vid == vid && device_table[i].pid == pid)
return &device_table[i];
return NULL;
}