Skip to content

Warn when RKP-only attestation exposes real device state - #304

Closed
kalanihelekunihi wants to merge 1 commit into
JingMatrix:devfrom
kalanihelekunihi:diagnose-rkp-only-foreign-attest-key
Closed

kalanihelekunihi wants to merge 1 commit into
JingMatrix:devfrom
kalanihelekunihi:diagnose-rkp-only-foreign-attest-key

Conversation

@kalanihelekunihi

@kalanihelekunihi kalanihelekunihi commented Oct 4, 2026 •

Copy link
Copy Markdown

Summary

  • emit an explicit warning when an RKP-only security level supplies a foreign attest key
  • explain that patch mode and harvested.json cannot rewrite that leaf or its appended RKP chain
  • document why public donor certificates are insufficient without the secure-hardware private key

Why

The existing logs correctly identify a foreign attest key and say that its leaf keeps the real root of trust. On an RKP-only security level, however, this can be a fresh key injected by keystore2 rather than a stale app-created attest key. The RKP gate must allow registration because denying it would fail key generation instead of causing an unattested fallback.

This distinction matters operationally: purging app-created keys or substituting a previously locked harvested.json cannot affect the foreign key's leaf or Google-signed provisioning chain. The new warning tells rooted users when those controls do not apply, avoiding destructive key and data experiments that cannot change the result.

Device evidence

Tested on a rooted Google Pixel 11 Pro Fold (yogi) running Android 17 build DP11.260918.005 (16443917), fingerprint:

google/yogi_beta/yogi:17/DP11.260918.005/16443917:user/release-keys

With remote_provisioning.tee.rkp_only=true, a targeted challenge-bound request logged a fresh allowed-rkp-only-level verdict and a foreign attest key. The returned Google-rooted public chain contained the device's genuine unlocked RootOfTrust. Repeating the request after substituting a harvest captured while the same device was locked produced the same unlocked leaf and the same Google-signed RKP metadata.

The new warning is limited to that correlated, non-stale combination so ordinary foreign-key logs remain unchanged.

Related fallback test

PR #270 describes deleting the RKP-only property so keystore2 can fall back to the configured keybox. A reversible live test confirmed that route works at the Android Keystore boundary: TEESimulator denied RKP registration, generated a fresh challenge-bound RSA key, emitted a four-certificate simulated chain, and signed the server challenge.

Google's Protected Download service still returned PERMISSION_DENIED on this build. That result means RKP fallback is useful where a configured keybox is accepted, but it is not sufficient by itself for this protected AICore model service. The property and original TEESimulator configuration were restored after the test.

Validation

  • git diff --check
  • all repository submodules initialized successfully
  • ./gradlew zipDebug completed successfully with OpenJDK 21 and Android SDK/NDK
  • output: TEESimulator-v4.0-72-342f1a2-Debug.zip
  • SHA-256: 152f12ed0ea590d9439986163b6f350130972013859c37e44b6742c0a7337f7a
  • live test reproduced the precise fresh RKP-only foreign-key branch that emits the warning

The macOS build used the same local Bash 3.2 empty-array compatibility adjustment already exercised while building PR #270; that unrelated build-script adjustment is not part of this PR.

@JingMatrix

Copy link
Copy Markdown
Owner

Did you see pr #270 ?

@kalanihelekunihi

Copy link
Copy Markdown
Author

Yes—thanks for pointing me to #270. I reviewed its current delete-intent implementation and tested the core mechanism on the Android 17 Pixel from this PR's device evidence.

Deleting remote_provisioning.tee.rkp_only changed the PCS request exactly as #270 predicts:

  • TEESimulator denied getRegistration instead of allowing the RKP-only path.
  • PCS generated a fresh challenge-bound RSA key through the configured TEESimulator generation profile.
  • The TEESimulator TA emitted a four-certificate simulated chain and signed the fresh server challenge.
  • PCS logged the new simulated public-key hash.

For this particular Google Protected Download request, the server still returned PERMISSION_DENIED: The caller does not have permission. Restoring the property returned the phone to its prior state.

So #270 does solve the RKP-only routing problem and avoids the foreign attest-key case that #304 warns about. It also shows that Protected Download has at least one additional eligibility check beyond the genuine unlocked RootOfTrust/RKP chain on this device (or rejects this keybox/profile).

I can rebase or narrow #304 so it is explicitly complementary to #270—for example, retaining the warning only when an RKP-only property remains active and a foreign key is actually observed—or close it if you consider #270's UI/logging sufficient.

@JingMatrix JingMatrix closed this Oct 19, 2026
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