Integrate a device security signal by proving where it came from before you act on it. On Android, the strongest proof is key attestation: the device generates a key in hardware-backed storage, and your server checks the certificate chain and the boot state, lock state and patch level it records. Then check that the observation is current, belongs to the right device and lifecycle, and is not a duplicate. Otukan Device Security supplies signals within an agreed model, chipset and integration scope. Managed Android, managed iOS and OEM firmware integrations each need their own scope record.
For the product context, see device integrity signals and Device Security.
Classify the source of each signal
Record which component observes the state, which transports it and which service decides what to do. A device identifier inside a message does not prove the message came from that device. An authenticated connection does not prove the observation inside it is true.
| Source | What it can show | How you verify it |
|---|---|---|
| Hardware-backed attestation | Boot state, bootloader lock, OS and patch level, app identity | Certificate chain to a trusted root, checked on your server |
| Firmware or system component | State seen below the app layer, within the integrated models | Authenticated producer, signed payload, agreed contract |
| Management (MDM) state | Enrolment, policy compliance, configuration | The management server’s own records |
| App observation | Conditions seen from inside one app | Bound to platform attestation on the server |
Keep these categories separate in your data. An app observation does not become hardware evidence because it is relabelled. iOS does not open its firmware to third parties, so managed iOS devices rely on management state and app-level evidence such as App Attest.
Verify Android device state with key attestation
Android Verified Boot builds a chain of trust from a hardware-protected root through the bootloader to the verified partitions. Key attestation lets your server read the result of that chain without trusting the operating system’s own report.
Generate an attested key
- Your server issues a random, single-use challenge.
- On the device, build a
KeyGenParameterSpecwithsetAttestationChallenge(challenge)and generate the key in the Android Keystore. Request StrongBox withsetIsStrongBoxBacked(true)where the device has it. - Read the chain with
KeyStore.getCertificateChain(alias)and send every certificate to the server.
Check the chain on the server
- Verify each certificate’s signature up to a Google hardware attestation root certificate published in the Android documentation. Keep that root list current.
- Check every certificate against Google’s attestation revocation status list.
- Parse the attestation extension (
KeyDescription) in the leaf certificate. ConfirmattestationChallengeequals the challenge you issued. - Require an
attestationSecurityLeveland a KeyMint (Keymaster) security level ofTrustedEnvironmentorStrongBox. ASoftwarelevel proves nothing about the hardware. - In the hardware-enforced list, read
RootOfTrust:verifiedBootStateisVerifiedfor a locked device running the manufacturer’s signed image.SelfSigned,UnverifiedorFailedmean a custom or broken boot chain.deviceLockedshows whether the bootloader is locked.verifiedBootKeyidentifies the key that signed the boot image; compare it with the values you expect for each model.
- Check
osVersion,osPatchLevel,vendorPatchLevelandbootPatchLevelagainst your minimum, andattestationApplicationIdagainst your app’s package and signing certificate.
The result is a hardware-rooted statement about the device at the moment of attestation. Store it with the device record and a timestamp, and repeat it when the device boots, updates or reaches a sensitive operation.
Define the interface contract
- Identify the models, chipsets, firmware builds and OS releases in the integration, and who may install or change each producer.
- Obtain the versioned contract and a redacted example. Map each value into your consumer’s internal representation.
- Specify the authenticated peer, trust roots, credential rotation and revocation. If payloads are signed, define verification and device binding separately from the transport.
- Separate read-only monitoring from services allowed to restrict a device or an operation.
- Reject malformed required data. Decide how unknown optional fields and unsupported versions are handled; never default them to healthy.
| Concern | Question the implementation must answer |
|---|---|
| Origin | Which producer, device and control generated the observation? |
| Meaning | Is the value an observation, an evaluation or an enforcement result? |
| Time and order | When was it observed, received and superseded? |
| Completeness | How are unsupported, unavailable and failed checks shown? |
| Version | Which schema and producer release define this meaning? |
| Trust | What does the receiver verify before accepting it? |
Process freshness, duplicates and errors
Test the receiver against fixtures first, then against the real producer. Fixtures prove your parser and decision logic; only a device proves detection.
- Validate the connection and any payload signature before parsing.
- Resolve the device binding and contract version. Send failures to a reviewable error state.
- Judge observation age by receipt time and attestation time, not by an unverified device clock alone.
- Deduplicate per the contract. Scope event keys to the producer and lifecycle; a reset or reassignment starts a new lifecycle.
- Never let a delayed observation overwrite newer evidence.
- Apply the agreed response only after these checks, and make repeated processing safe.
Keep a separate state for missing evidence. Lost connectivity, producer failure, revoked credentials and an unsupported control have different causes. None of them means “compromised”, and silence never means “trusted”. Set queue limits and an alert when delivery falls behind. Keep device identifiers out of broad application logs, and agree access, retention and deletion with fleet operations and privacy owners.
Test legitimate changes and adverse states
Pair each adverse scenario with a legitimate control on an authorised test device, and record the state change independently.
| Exercise | Acceptance question |
|---|---|
| Unlocked bootloader or custom image | Does attestation show deviceLocked false or a non-Verified boot state, and does the right consumer act? |
| Approved firmware or OS update | Is the new patch level accepted without an unjustified restriction? |
| Duplicate and delayed delivery | Is ordering kept without repeated action? |
| Revoked or expired producer credential | Is the evidence rejected with an actionable error? |
| Reset or reassignment | Does old evidence stop influencing the new lifecycle? |
| Connection loss and restoration | Does missing evidence stay visible, and does recovery restore a coherent state? |
Repeat installation, update, authentication and the sensitive workflow after every integration change. Test restrictions and their removal, not only the presence of a signal in a log.
- Tested model, chipset, firmware and OS are recorded.
- Expected observations and actions are agreed before the run.
- Each decision traces back to an authenticated or attested source.
- Recovery restores service without reusing stale trust.
For related reading, see hardware-backed mobile security and Android bootloader integrity.
Further reading
- Verify hardware-backed key pairs with key attestation — Android Developers
- Key and ID attestation — Android Open Source Project
- Verified Boot — Android Open Source Project
- Boot flow — Android Open Source Project