Interface ShieldEngine
The service-provider seam between the public shield API and the attestation engine that implements it.
Codename One ships an inert default that reports itself unavailable, so an app written against
AppShield compiles and runs everywhere. A build entitled to the
enterprise engine has a real implementation registered by the build server before
Display.init, via ShieldEngineRegistry.setEngine(ShieldEngine).
What must never move into the framework
The split is only worth anything if the engine keeps the parts an attacker would want to reach. An implementation must own, and must never delegate to open framework code:
- challenge and nonce generation -- predictable nonces make replay possible;
- any key material, and any code that touches it;
- the pin comparison and the decision to fail a request. The framework may hold a
PinSet; patching the framework's copy must not be enough to disable pinning; - the detection heuristics themselves. Published heuristics are bypassed heuristics, so the
framework only ever sees finished
ShieldSignalresults -- and only the ones the engine chooses to publish; - interpretation of the raw platform attestation. Those responses go to the verifying service, which the attacker does not control, rather than being judged on the device.
The security property this preserves is not "the app refuses to make the call" -- an attacker who controls the device can always strip a header. It is that the customer's backend refuses to serve a request without a valid, unexpired, service-signed token, which a substituted engine cannot mint.
-
Method Summary
Modifier and TypeMethodDescriptionThe runtime self-protection observations this engine wants reported.fetchToken(String bindingData) Obtains a token, blocking until it has one or fails.The cached token, without contacting the service.getName()A stable name for diagnostics, for exampleunprotected,simulatoror the enterprise engine's own identifier.The pin set currently in force, never null.voidinitialize(EngineContext ctx, ShieldConfig config) Called once fromAppShield.init(ShieldConfig).voidDiscards any cached token, forcing the next fetch to go to the service.booleanTrue when this engine can actually attest.voidshutdown()Releases resources.booleanverifyPins(String host, String[] spkiDigests, String[] certDigests) Decides whether a certificate chain is acceptable for a host.
-
Method Details
-
getName
String getName()A stable name for diagnostics, for exampleunprotected,simulatoror the enterprise engine's own identifier. -
isAvailable
boolean isAvailable()True when this engine can actually attest. False for the inert default, which is howAppShield.isProtected()is answered. -
initialize
Called once fromAppShield.init(ShieldConfig). Must not block on the network; do warm-up work on a background thread. -
fetchToken
Obtains a token, blocking until it has one or fails. Called on a network thread, never the EDT.- Parameters:
bindingData- request data to bind the token to, or null for a plain time-limited token. A bound token is only valid for the request whose data was supplied.- Throws:
ShieldException- carrying theShieldStatusthat explains whether the failure was about reaching the service or about this device
-
getCachedToken
ShieldToken getCachedToken()The cached token, without contacting the service. Returns null when nothing is cached.
Must never block: callers are typically on the EDT, deciding whether they can decorate a request right now.
-
verifyPins
Decides whether a certificate chain is acceptable for a host.
Must be purely local and non-blocking: on iOS this is invoked synchronously from the TLS delegate thread while the handshake is held open, so any network call or blocking wait here deadlocks the connection.
Returns true when the host is not pinned -- "no opinion" must never read as a mismatch.
- Parameters:
spkiDigests- base64 SHA-256 digests of each chain certificate's public key infocertDigests- whole-certificate digests, for engines that pin those instead
-
getPinSet
PinSet getPinSet()The pin set currently in force, never null. May bePinSet.EMPTY. -
collectSignals
ShieldSignal[] collectSignals()The runtime self-protection observations this engine wants reported. May legitimately be a subset of what it detected. -
invalidate
void invalidate()Discards any cached token, forcing the next fetch to go to the service. Called when a backend rejects a token, which usually means the device's attestation state is stale. -
shutdown
void shutdown()Releases resources. Called when the app is shutting down.
-