Supplement device-property ids from system properties when unattested - #258
Merged
Conversation
Owner
Author
|
Hi @kukIux — the device-id fix is ready. Could you retest on the LineageOS device (Redmi Note 13 / sapphire) where Key Attestation failed with "attestation ID mismatch for device"? Debug build Please install it, run Key Attestation with the same options as before, and check whether the ID mismatch is gone — then attach the log and a screenshot. Thanks! |
|
Thank you. This CI build, fixed detect Tee in latest kknd detector, and fix view Attestation device props in my Redmi Note 13 on Key Attestation 2.0.3 app! |
brand/device/product/manufacturer/model are captured from the attested leaf, and Resolver
presented harvest.<id> raw. A device that produced no device-ID attestation — a plain
attestation, or a TEE that refuses ID attestation — leaves all five blank, so the profile
presented an empty id, and the reference TA's ID check then rejects an app that requests the
device's true value ("attestation ID mismatch for brand"). serial/imei/imei2/meid were already
supplemented from the OS; these five were not, even though they are exactly the ids the
framework fills ATTESTATION_ID_* from.
When the captured value is blank, the harvest now fills each from the android.os.Build field
the framework itself reads for ID attestation — which resolves from the ro.product.* system
properties — recorded as a SUPPLEMENT override. Resolver presents effective() for every id, so
a supplemented value reaches the TA while a real capture stays untouched, the WebUI shows the
supplement for what it is, and an explicit per-profile spoof still overrides it.
The first cut read plain android.os.Build.BRAND/DEVICE/PRODUCT/... to supplement an unattested id. That is the wrong source: keystore does not attest those. The framework's AndroidKeyStoreKeyPairGeneratorSpi fills ATTESTATION_ID_* from Build.<X>_FOR_ATTESTATION, and Build.getVendorDeviceIdProperty resolves that as ro.product.<base>_for_attestation (unless "unknown") -> else ro.product.vendor.<base> -> else ro.product.<base>, where <base> is brand/device/name(product)/manufacturer/model. On a ROM that ships attestation-specific ids these differ from the plain values: a LineageOS build reported ro.product.device_for_attestation=sapphire while ro.product.device =sapphiren, so we supplemented "sapphiren" while the app requested "sapphire" and the TA's id check still failed. devicePropId now mirrors that exact chain, so a supplemented id equals what the caller attests. It reads the properties directly (SystemProperties, no hidden Build.<X>_FOR_ATTESTATION field), returning blank only when the whole chain is unset so nothing garbage is supplemented.
JingMatrix
force-pushed
the
fix/harvest-device-props-fallback
branch
from
August 17, 2026 23:29
e3e6a8e to
c586712
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.






brand/device/product/manufacturer/model are captured from the attested leaf, and Resolver presented
harvest.<id>raw. A device that produced no device-ID attestation — a plain attestation, or a TEE that refuses ID attestation — leaves all five blank, so the profile presented an empty id, and the reference TA's ID check then rejects an app that requests the device's true value ("attestation ID mismatch for brand"). serial/imei/imei2/meid were already supplemented from the OS; these five were not, even though they are exactly the ids the framework fillsATTESTATION_ID_*from.When the captured value is blank, the harvest now fills each from the
android.os.Buildfield the framework itself reads for ID attestation — which resolves from thero.product.*system properties — recorded as a SUPPLEMENT override. Resolver presentseffective()for every id, so a supplemented value reaches the TA while a real capture stays untouched, the WebUI shows the supplement for what it is, and an explicit per-profile spoof still overrides it.