diff --git a/libfprint/drivers/validity/validity.c b/libfprint/drivers/validity/validity.c index 0082b95e..2aa12351 100644 --- a/libfprint/drivers/validity/validity.c +++ b/libfprint/drivers/validity/validity.c @@ -527,17 +527,17 @@ open_load_data (FpiSsm *ssm, /* Populate TLS state key pointers from common data store */ self->tls.password = validity_data_get_bytes (&self->common_data, - VALIDITY_DATA_TLS_PASSWORD, - &self->tls.password_len); + VALIDITY_DATA_TLS_PASSWORD, + &self->tls.password_len); self->tls.gwk_sign = validity_data_get_bytes (&self->common_data, - VALIDITY_DATA_GWK_SIGN, - &self->tls.gwk_sign_len); + VALIDITY_DATA_GWK_SIGN, + &self->tls.gwk_sign_len); self->tls.fw_pubkey_x = validity_data_get_bytes (&self->common_data, - VALIDITY_DATA_FW_PUBKEY_X, - &self->tls.fw_pubkey_x_len); + VALIDITY_DATA_FW_PUBKEY_X, + &self->tls.fw_pubkey_x_len); self->tls.fw_pubkey_y = validity_data_get_bytes (&self->common_data, - VALIDITY_DATA_FW_PUBKEY_Y, - &self->tls.fw_pubkey_y_len); + VALIDITY_DATA_FW_PUBKEY_Y, + &self->tls.fw_pubkey_y_len); fp_info ("Loaded external data files for %04x:%04x", desc->vid, desc->pid); fpi_ssm_next_state (ssm); diff --git a/libfprint/drivers/validity/validity.h b/libfprint/drivers/validity/validity.h index 617a8a48..d42f4e7e 100644 --- a/libfprint/drivers/validity/validity.h +++ b/libfprint/drivers/validity/validity.h @@ -251,8 +251,8 @@ struct _FpiDeviceValidity GCancellable *interrupt_cancellable; /* Runtime data files loaded from libfprint-validity-data package */ - ValidityDataStore device_data; - ValidityDataStore common_data; + ValidityDataStore device_data; + ValidityDataStore common_data; /* TLS session state */ ValidityTlsState tls; diff --git a/libfprint/drivers/validity/validity_data.c b/libfprint/drivers/validity/validity_data.c index b86c960d..3b37a02d 100644 --- a/libfprint/drivers/validity/validity_data.c +++ b/libfprint/drivers/validity/validity_data.c @@ -54,7 +54,8 @@ static const gchar *device_blob_filenames[] = { }; /* Common data filename mapping (indexed by tag) */ -static const struct { +static const struct +{ ValidityDataTag tag; const gchar *filename; } common_file_map[] = { @@ -79,6 +80,7 @@ verify_hmac (const guint8 *data, guint8 computed[32]; GHmac *hmac = g_hmac_new (G_CHECKSUM_SHA256, hmac_key, sizeof (hmac_key)); + g_hmac_update (hmac, data, data_len); gsize digest_len = sizeof (computed); diff --git a/libfprint/drivers/validity/validity_pair.c b/libfprint/drivers/validity/validity_pair.c index dcde0584..52510cde 100644 --- a/libfprint/drivers/validity/validity_pair.c +++ b/libfprint/drivers/validity/validity_pair.c @@ -860,9 +860,9 @@ pair_partition_flash_send (FpiSsm *ssm, const guint8 *ca_cert_data; /* Select partition signature based on PID */ - ValidityDataTag sig_tag = (ps->dev_desc->pid == 0x0090) - ? VALIDITY_DATA_PARTITION_SIG_0090 - : VALIDITY_DATA_PARTITION_SIG_STANDARD; + ValidityDataTag sig_tag = (ps->dev_desc->pid == 0x0090) ? + VALIDITY_DATA_PARTITION_SIG_0090 : + VALIDITY_DATA_PARTITION_SIG_STANDARD; partition_sig_data = validity_data_get_bytes (&self->common_data, sig_tag, &partition_sig_len); @@ -1209,8 +1209,8 @@ pair_erase_dbe_send (FpiSsm *ssm, gsize dbe_len; const guint8 *dbe_data = validity_data_get_bytes (&self->device_data, - VALIDITY_DATA_DB_WRITE_ENABLE, - &dbe_len); + VALIDITY_DATA_DB_WRITE_ENABLE, + &dbe_len); if (!dbe_data || dbe_len == 0) { fpi_ssm_mark_failed (ssm, @@ -1286,8 +1286,9 @@ pair_write_dbe_send (FpiSsm *ssm, /* db_write_enable before write_flash */ gsize dbe_len; const guint8 *dbe_data = validity_data_get_bytes (&self->device_data, - VALIDITY_DATA_DB_WRITE_ENABLE, - &dbe_len); + VALIDITY_DATA_DB_WRITE_ENABLE, + &dbe_len); + if (!dbe_data || dbe_len == 0) { fp_warn ("No db_write_enable data for pairing"); @@ -1307,8 +1308,8 @@ pair_write_flash_send (FpiSsm *ssm, /* Build TLS flash image */ gsize ca_len; const guint8 *ca_data = validity_data_get_bytes (&self->common_data, - VALIDITY_DATA_CA_PUBKEY, - &ca_len); + VALIDITY_DATA_CA_PUBKEY, + &ca_len); gsize flash_len; g_autofree guint8 *flash_data = validity_pair_build_tls_flash (ps, ca_data, ca_len, &flash_len); diff --git a/tests/libfprint.supp b/tests/libfprint.supp index 274d740e..fc11d2f8 100644 --- a/tests/libfprint.supp +++ b/tests/libfprint.supp @@ -33,3 +33,19 @@ ... fun:libusb_init_context } + +{ + + Memcheck:Value8 + fun:gchecksum_digest_to_string + fun:*sha256* + fun:g_checksum_get_digest +} + +{ + + Memcheck:Cond + fun:gchecksum_digest_to_string + fun:*sha256* + fun:g_checksum_get_digest +} diff --git a/tests/test-validity.c b/tests/test-validity.c index 7223086b..91650c16 100644 --- a/tests/test-validity.c +++ b/tests/test-validity.c @@ -1347,6 +1347,7 @@ test_fwext_db_write_enable_blob (void) /* Create a minimal FpiDeviceValidity with empty data stores. * Since no data files are loaded, the accessor should return NULL. */ FpiDeviceValidity dev = { 0 }; + validity_data_store_init (&dev.device_data); gsize len; @@ -1951,6 +1952,7 @@ static void test_db_write_enable_blob (void) { FpiDeviceValidity dev = { 0 }; + validity_data_store_init (&dev.device_data); gsize len; @@ -2738,12 +2740,30 @@ test_decrypt_invalid (void) /* ================================================================ * Test: PSK derivation runs without crashing * ================================================================ */ +static const guint8 test_password[32] = { + 0x97, 0x04, 0x4D, 0x1A, 0xF0, 0x66, 0xAD, 0x8D, + 0x18, 0x1A, 0x6E, 0xE5, 0xC1, 0x55, 0x79, 0x31, + 0x3B, 0xA5, 0x77, 0xCC, 0x59, 0xD2, 0x0B, 0x10, + 0xD0, 0x4B, 0x8E, 0xC8, 0x9D, 0xBA, 0x4C, 0x86, +}; + +static const guint8 test_gwk_sign[32] = { + 0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6, 0x07, 0x18, + 0x29, 0x3A, 0x4B, 0x5C, 0x6D, 0x7E, 0x8F, 0x90, + 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, + 0x89, 0x9A, 0xAB, 0xBC, 0xCD, 0xDE, 0xEF, 0xF0, +}; + static void test_psk_derivation (void) { ValidityTlsState tls; validity_tls_init (&tls); + tls.password = test_password; + tls.password_len = sizeof (test_password); + tls.gwk_sign = test_gwk_sign; + tls.gwk_sign_len = sizeof (test_gwk_sign); validity_tls_derive_psk (&tls); @@ -2783,6 +2803,14 @@ test_psk_deterministic (void) validity_tls_init (&tls1); validity_tls_init (&tls2); + tls1.password = test_password; + tls1.password_len = sizeof (test_password); + tls1.gwk_sign = test_gwk_sign; + tls1.gwk_sign_len = sizeof (test_gwk_sign); + tls2.password = test_password; + tls2.password_len = sizeof (test_password); + tls2.gwk_sign = test_gwk_sign; + tls2.gwk_sign_len = sizeof (test_gwk_sign); validity_tls_derive_psk (&tls1); validity_tls_derive_psk (&tls2); @@ -2955,6 +2983,12 @@ test_flash_parse_needs_psk (void) validity_tls_init (&tls_with_psk); validity_tls_init (&tls_no_psk); + /* Set up key material before PSK derivation */ + tls_with_psk.password = test_password; + tls_with_psk.password_len = sizeof (test_password); + tls_with_psk.gwk_sign = test_gwk_sign; + tls_with_psk.gwk_sign_len = sizeof (test_gwk_sign); + /* Derive PSK so we can build a valid encrypted private key block */ validity_tls_derive_psk (&tls_with_psk); @@ -3432,8 +3466,8 @@ test_make_cert_size (void) guint8 password[32]; RAND_bytes (password, sizeof (password)); g_autofree guint8 *cert = validity_pair_make_cert (pub_x, pub_y, - password, sizeof (password), - &cert_len); + password, sizeof (password), + &cert_len); g_assert_nonnull (cert); g_assert_cmpuint (cert_len, ==, VALIDITY_CLIENT_CERT_SIZE); @@ -3460,11 +3494,11 @@ test_make_cert_deterministic (void) gsize len1, len2; g_autofree guint8 *cert1 = validity_pair_make_cert (pub_x, pub_y, - password, sizeof (password), - &len1); + password, sizeof (password), + &len1); g_autofree guint8 *cert2 = validity_pair_make_cert (pub_x, pub_y, - password, sizeof (password), - &len2); + password, sizeof (password), + &len2); g_assert_nonnull (cert1); g_assert_nonnull (cert2); @@ -3618,8 +3652,8 @@ test_build_tls_flash_size (void) gsize flash_len; g_autofree guint8 *flash = validity_pair_build_tls_flash (&state, - ca_cert, sizeof (ca_cert), - &flash_len); + ca_cert, sizeof (ca_cert), + &flash_len); g_assert_nonnull (flash); g_assert_cmpuint (flash_len, ==, 0x1000); @@ -3672,8 +3706,8 @@ test_build_tls_flash_blocks (void) gsize flash_len; g_autofree guint8 *flash = validity_pair_build_tls_flash (&state, - ca_cert2, sizeof (ca_cert2), - &flash_len); + ca_cert2, sizeof (ca_cert2), + &flash_len); g_assert_nonnull (flash); /* Block 0 should be first: id=0, size=1 */ @@ -4750,6 +4784,7 @@ test_data_load_valid_hmac (void) }; GHmac *hmac = g_hmac_new (G_CHECKSUM_SHA256, hmac_key, sizeof (hmac_key)); + g_hmac_update (hmac, payload, payload_len); guint8 trailer[32]; gsize digest_len = sizeof (trailer); @@ -4771,7 +4806,7 @@ test_data_load_valid_hmac (void) GError *error = NULL; gboolean ok = validity_data_load_file (&store, VALIDITY_DATA_INIT, - tmpfile, &error); + tmpfile, &error); g_assert_no_error (error); g_assert_true (ok); @@ -4794,6 +4829,7 @@ test_data_load_corrupt_hmac (void) { guint8 payload[] = { 0xCA, 0xFE }; guint8 bad_trailer[32]; + memset (bad_trailer, 0xFF, sizeof (bad_trailer)); g_autofree gchar *tmpfile = NULL; @@ -4809,7 +4845,7 @@ test_data_load_corrupt_hmac (void) GError *error = NULL; gboolean ok = validity_data_load_file (&store, VALIDITY_DATA_INIT, - tmpfile, &error); + tmpfile, &error); g_assert_false (ok); g_assert_nonnull (error); g_error_free (error); @@ -4831,6 +4867,7 @@ test_data_load_too_small (void) { /* File with only 20 bytes — less than HMAC size (32) */ guint8 tiny[20]; + memset (tiny, 0x42, sizeof (tiny)); g_autofree gchar *tmpfile = NULL; @@ -4845,7 +4882,7 @@ test_data_load_too_small (void) GError *error = NULL; gboolean ok = validity_data_load_file (&store, VALIDITY_DATA_INIT, - tmpfile, &error); + tmpfile, &error); g_assert_false (ok); g_assert_nonnull (error); g_error_free (error); @@ -4861,12 +4898,13 @@ static void test_data_load_nonexistent (void) { ValidityDataStore store; + validity_data_store_init (&store); GError *error = NULL; gboolean ok = validity_data_load_file (&store, VALIDITY_DATA_INIT, - "/nonexistent/path/blob.bin", - &error); + "/nonexistent/path/blob.bin", + &error); g_assert_false (ok); g_assert_nonnull (error); g_error_free (error); @@ -4902,6 +4940,7 @@ write_hmac_file (const gchar *path, }; GHmac *hmac = g_hmac_new (G_CHECKSUM_SHA256, hmac_key, sizeof (hmac_key)); + g_hmac_update (hmac, payload, payload_len); guint8 trailer[32]; gsize digest_len = sizeof (trailer); @@ -4923,6 +4962,7 @@ static void test_data_load_device_missing (void) { ValidityDataStore store; + validity_data_store_init (&store); /* Temporarily override search paths to a non-existent directory */ @@ -4953,6 +4993,7 @@ test_data_load_device_missing_init (void) { /* Create temp dir with the expected subdir but no files */ g_autofree gchar *tmpdir = g_dir_make_tmp ("validity-data-XXXXXX", NULL); + g_assert_nonnull (tmpdir); g_autofree gchar *devdir = g_build_filename (tmpdir, "06cb_009a", NULL); @@ -4989,6 +5030,7 @@ static void test_data_load_device_valid (void) { g_autofree gchar *tmpdir = g_dir_make_tmp ("validity-data-XXXXXX", NULL); + g_assert_nonnull (tmpdir); g_autofree gchar *devdir = g_build_filename (tmpdir, "06cb_009a", NULL); @@ -5028,15 +5070,15 @@ test_data_load_device_valid (void) /* Verify db_write_enable was loaded */ const guint8 *dbe = validity_data_get_bytes (&store, - VALIDITY_DATA_DB_WRITE_ENABLE, - &len); + VALIDITY_DATA_DB_WRITE_ENABLE, + &len); g_assert_nonnull (dbe); g_assert_cmpuint (len, ==, sizeof (dbe_payload)); g_assert_cmpmem (dbe, len, dbe_payload, sizeof (dbe_payload)); /* Optional files not present should be NULL */ const guint8 *reset = validity_data_get_bytes (&store, - VALIDITY_DATA_RESET, &len); + VALIDITY_DATA_RESET, &len); g_assert_null (reset); g_assert_cmpuint (len, ==, 0); @@ -5057,6 +5099,7 @@ static void test_data_load_common_missing (void) { ValidityDataStore store; + validity_data_store_init (&store); const gchar *saved0 = validity_data_search_paths[0]; @@ -5085,10 +5128,12 @@ static void test_data_load_common_valid (void) { g_autofree gchar *tmpdir = g_dir_make_tmp ("validity-common-XXXXXX", NULL); + g_assert_nonnull (tmpdir); /* Write all 7 common files with test payloads */ - static const struct { + static const struct + { const gchar *filename; ValidityDataTag tag; guint8 marker; @@ -5160,11 +5205,12 @@ test_data_enroll_dbe_missing (void) { /* Create a minimal FpiDeviceValidity with empty data stores */ FpiDeviceValidity dev = { 0 }; + validity_data_store_init (&dev.device_data); validity_data_store_init (&dev.common_data); /* db_write_enable is used in enroll, verify (match), and delete flows. - * When data files are not installed, it must return NULL gracefully. */ + * When data files are not installed, it must return NULL gracefully. */ gsize len; const guint8 *dbe = validity_db_get_write_enable_blob (&dev, &len); g_assert_null (dbe); @@ -5196,6 +5242,7 @@ test_data_enroll_dbe_loaded (void) { /* Create device with loaded db_write_enable */ g_autofree gchar *tmpdir = g_dir_make_tmp ("validity-dbe-XXXXXX", NULL); + g_assert_nonnull (tmpdir); g_autofree gchar *devdir = g_build_filename (tmpdir, "06cb_009a", NULL); @@ -5221,7 +5268,7 @@ test_data_enroll_dbe_loaded (void) GError *error = NULL; gboolean ok = validity_data_load_device (&dev.device_data, - 0x06cb, 0x009a, &error); + 0x06cb, 0x009a, &error); g_assert_no_error (error); g_assert_true (ok); @@ -5257,6 +5304,7 @@ static void test_data_load_device_corrupt (void) { g_autofree gchar *tmpdir = g_dir_make_tmp ("validity-corrupt-XXXXXX", NULL); + g_assert_nonnull (tmpdir); g_autofree gchar *devdir = g_build_filename (tmpdir, "06cb_009a", NULL); @@ -5268,7 +5316,7 @@ test_data_load_device_corrupt (void) g_autofree gchar *init_path = g_build_filename (devdir, "init.bin", NULL); g_assert_true (g_file_set_contents (init_path, (const gchar *) bad_file, - sizeof (bad_file), NULL)); + sizeof (bad_file), NULL)); ValidityDataStore store; validity_data_store_init (&store);