mirror of
https://gitlab.freedesktop.org/libfprint/libfprint.git
synced 2026-05-14 08:48:07 +02:00
Add HAL (validity_hal.h/c) with per-device lookup table for 4 PIDs (0090, 0097, 009a, 009d). Each entry holds init_hardcoded, clean_slate, reset_blob, db_write_enable blobs and a flash layout with partition table + RSA signature. Add device pairing SSM (validity_pair.h/c) — a 30-state machine that runs as a child of the open SSM when the sensor has no TLS partitions. Phases: raw USB keygen + partition flash, TLS handshake, erase 5 partitions, write 4096-byte TLS flash image, reboot. Integration: - OPEN_PAIR state in open SSM (between FWEXT and TLS_READ_FLASH) - Skipped in emulation, no-fwext, or already-paired cases - Post-reboot returns FP_DEVICE_ERROR_REMOVED for fprintd retry Migration: - validity_db.c and validity_fwext.c now use HAL lookups - Removed hardcoded validity_blob_dbe_009a.inc Tests: 24 new test cases (10 HAL + 14 pairing), 0 regressions. Result: 40 OK, 0 Fail, 2 Skipped.
251 lines
8.7 KiB
C
251 lines
8.7 KiB
C
/*
|
|
* Unit tests for validity HAL (device descriptor lookup and flash layout)
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <glib.h>
|
|
#include <string.h>
|
|
|
|
#include "drivers/validity/validity.h"
|
|
#include "drivers/validity/validity_hal.h"
|
|
|
|
/* ================================================================
|
|
* T7.1: HAL lookup by device type — all valid types return non-NULL
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_lookup_all_types (void)
|
|
{
|
|
const guint types[] = { VALIDITY_DEV_90, VALIDITY_DEV_97,
|
|
VALIDITY_DEV_9A, VALIDITY_DEV_9D };
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (types); i++)
|
|
{
|
|
const ValidityDeviceDesc *desc = validity_hal_device_lookup (types[i]);
|
|
g_assert_nonnull (desc);
|
|
g_assert_cmpuint (desc->vid, >, 0);
|
|
g_assert_cmpuint (desc->pid, >, 0);
|
|
}
|
|
}
|
|
|
|
/* ================================================================
|
|
* T7.2: HAL lookup by PID — all supported VID/PID combos
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_lookup_by_pid (void)
|
|
{
|
|
/* All 4 supported devices */
|
|
struct { guint16 vid; guint16 pid; } devices[] = {
|
|
{ 0x138a, 0x0090 },
|
|
{ 0x138a, 0x0097 },
|
|
{ 0x06cb, 0x009a },
|
|
{ 0x138a, 0x009d },
|
|
};
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (devices); i++)
|
|
{
|
|
const ValidityDeviceDesc *desc =
|
|
validity_hal_device_lookup_by_pid (devices[i].vid, devices[i].pid);
|
|
g_assert_nonnull (desc);
|
|
g_assert_cmpuint (desc->vid, ==, devices[i].vid);
|
|
g_assert_cmpuint (desc->pid, ==, devices[i].pid);
|
|
}
|
|
}
|
|
|
|
/* ================================================================
|
|
* T7.3: HAL lookup — invalid type returns NULL
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_lookup_invalid (void)
|
|
{
|
|
const ValidityDeviceDesc *desc = validity_hal_device_lookup (99);
|
|
g_assert_null (desc);
|
|
}
|
|
|
|
/* ================================================================
|
|
* T7.4: HAL lookup by PID — unknown PID returns NULL
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_lookup_by_pid_invalid (void)
|
|
{
|
|
const ValidityDeviceDesc *desc =
|
|
validity_hal_device_lookup_by_pid (0x1234, 0x5678);
|
|
g_assert_null (desc);
|
|
}
|
|
|
|
/* ================================================================
|
|
* T7.5: All devices have non-empty blobs
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_blobs_present (void)
|
|
{
|
|
const guint types[] = { VALIDITY_DEV_90, VALIDITY_DEV_97,
|
|
VALIDITY_DEV_9A, VALIDITY_DEV_9D };
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (types); i++)
|
|
{
|
|
const ValidityDeviceDesc *desc = validity_hal_device_lookup (types[i]);
|
|
g_assert_nonnull (desc);
|
|
|
|
/* init_hardcoded must be present for all */
|
|
g_assert_nonnull (desc->init_hardcoded);
|
|
g_assert_cmpuint (desc->init_hardcoded_len, >, 0);
|
|
|
|
/* reset_blob must be present for all */
|
|
g_assert_nonnull (desc->reset_blob);
|
|
g_assert_cmpuint (desc->reset_blob_len, >, 0);
|
|
|
|
/* db_write_enable must be present for all */
|
|
g_assert_nonnull (desc->db_write_enable);
|
|
g_assert_cmpuint (desc->db_write_enable_len, >, 0);
|
|
}
|
|
}
|
|
|
|
/* ================================================================
|
|
* T7.6: PID 0090 has smaller db partition and no clean_slate blob
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_pid_0090_specifics (void)
|
|
{
|
|
const ValidityDeviceDesc *desc = validity_hal_device_lookup (VALIDITY_DEV_90);
|
|
g_assert_nonnull (desc);
|
|
|
|
/* 0090 has no init_hardcoded_clean_slate */
|
|
g_assert_null (desc->init_clean_slate);
|
|
g_assert_cmpuint (desc->init_clean_slate_len, ==, 0);
|
|
|
|
/* Flash layout should exist */
|
|
g_assert_nonnull (desc->flash_layout);
|
|
g_assert_cmpuint (desc->flash_layout->num_partitions, ==,
|
|
VALIDITY_FLASH_NUM_PARTITIONS);
|
|
}
|
|
|
|
/* ================================================================
|
|
* T7.7: Non-0090 devices have init_hardcoded_clean_slate
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_clean_slate_present (void)
|
|
{
|
|
const guint types[] = { VALIDITY_DEV_97, VALIDITY_DEV_9A, VALIDITY_DEV_9D };
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (types); i++)
|
|
{
|
|
const ValidityDeviceDesc *desc = validity_hal_device_lookup (types[i]);
|
|
g_assert_nonnull (desc);
|
|
g_assert_nonnull (desc->init_clean_slate);
|
|
g_assert_cmpuint (desc->init_clean_slate_len, >, 0);
|
|
}
|
|
}
|
|
|
|
/* ================================================================
|
|
* T7.8: Flash layout has valid partition table
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_flash_layout (void)
|
|
{
|
|
const guint types[] = { VALIDITY_DEV_90, VALIDITY_DEV_97,
|
|
VALIDITY_DEV_9A, VALIDITY_DEV_9D };
|
|
|
|
for (guint i = 0; i < G_N_ELEMENTS (types); i++)
|
|
{
|
|
const ValidityDeviceDesc *desc = validity_hal_device_lookup (types[i]);
|
|
g_assert_nonnull (desc);
|
|
g_assert_nonnull (desc->flash_layout);
|
|
|
|
const ValidityFlashLayout *layout = desc->flash_layout;
|
|
g_assert_cmpuint (layout->num_partitions, ==,
|
|
VALIDITY_FLASH_NUM_PARTITIONS);
|
|
|
|
/* Signature must be 256 bytes */
|
|
g_assert_nonnull (layout->partition_sig);
|
|
g_assert_cmpuint (layout->partition_sig_len, ==,
|
|
VALIDITY_PARTITION_SIG_SIZE);
|
|
|
|
/* Verify partitions are ordered and non-overlapping */
|
|
for (guint p = 0; p < layout->num_partitions; p++)
|
|
{
|
|
const ValidityPartition *part = &layout->partitions[p];
|
|
g_assert_cmpuint (part->size, >, 0);
|
|
|
|
if (p > 0)
|
|
{
|
|
const ValidityPartition *prev = &layout->partitions[p - 1];
|
|
g_assert_cmpuint (part->offset, >=,
|
|
prev->offset + prev->size);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ================================================================
|
|
* T7.9: Blob sizes match expected values from python-validity
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_blob_sizes (void)
|
|
{
|
|
const ValidityDeviceDesc *desc_9a =
|
|
validity_hal_device_lookup (VALIDITY_DEV_9A);
|
|
g_assert_nonnull (desc_9a);
|
|
|
|
/* 009a blobs: init=581, clean_slate=741, reset=12037, dbe=3621 */
|
|
g_assert_cmpuint (desc_9a->init_hardcoded_len, ==, 581);
|
|
g_assert_cmpuint (desc_9a->init_clean_slate_len, ==, 741);
|
|
g_assert_cmpuint (desc_9a->reset_blob_len, ==, 12037);
|
|
g_assert_cmpuint (desc_9a->db_write_enable_len, ==, 3621);
|
|
|
|
const ValidityDeviceDesc *desc_90 =
|
|
validity_hal_device_lookup (VALIDITY_DEV_90);
|
|
g_assert_nonnull (desc_90);
|
|
|
|
/* 0090 blobs: init=485, no clean_slate, reset=11493, dbe=1765 */
|
|
g_assert_cmpuint (desc_90->init_hardcoded_len, ==, 485);
|
|
g_assert_cmpuint (desc_90->reset_blob_len, ==, 11493);
|
|
g_assert_cmpuint (desc_90->db_write_enable_len, ==, 1765);
|
|
}
|
|
|
|
/* ================================================================
|
|
* T7.10: Lookup consistency — by-type and by-PID return same pointer
|
|
* ================================================================ */
|
|
static void
|
|
test_hal_lookup_consistency (void)
|
|
{
|
|
const ValidityDeviceDesc *by_type =
|
|
validity_hal_device_lookup (VALIDITY_DEV_9A);
|
|
const ValidityDeviceDesc *by_pid =
|
|
validity_hal_device_lookup_by_pid (0x06cb, 0x009a);
|
|
g_assert_true (by_type == by_pid);
|
|
}
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
g_test_init (&argc, &argv, NULL);
|
|
|
|
g_test_add_func ("/validity/hal/lookup-all-types",
|
|
test_hal_lookup_all_types);
|
|
g_test_add_func ("/validity/hal/lookup-by-pid",
|
|
test_hal_lookup_by_pid);
|
|
g_test_add_func ("/validity/hal/lookup-invalid",
|
|
test_hal_lookup_invalid);
|
|
g_test_add_func ("/validity/hal/lookup-by-pid-invalid",
|
|
test_hal_lookup_by_pid_invalid);
|
|
g_test_add_func ("/validity/hal/blobs-present",
|
|
test_hal_blobs_present);
|
|
g_test_add_func ("/validity/hal/pid-0090-specifics",
|
|
test_hal_pid_0090_specifics);
|
|
g_test_add_func ("/validity/hal/clean-slate-present",
|
|
test_hal_clean_slate_present);
|
|
g_test_add_func ("/validity/hal/flash-layout",
|
|
test_hal_flash_layout);
|
|
g_test_add_func ("/validity/hal/blob-sizes",
|
|
test_hal_blob_sizes);
|
|
g_test_add_func ("/validity/hal/lookup-consistency",
|
|
test_hal_lookup_consistency);
|
|
|
|
return g_test_run ();
|
|
}
|