# Interface ShieldEngine

public 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 `ShieldSignal` results -- 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 Type
  Method
  Description
  `ShieldSignal[]`
  `collectSignals()`
  The runtime self-protection observations this engine wants reported.
  `ShieldToken`
  `fetchToken(String bindingData)`
  Obtains a token, blocking until it has one or fails.
  `ShieldToken`
  `getCachedToken()`
  The cached token, without contacting the service.
  `String`
  `getName()`
  A stable name for diagnostics, for example `unprotected`, `simulator` or the enterprise engine's own identifier.
  `PinSet`
  `getPinSet()`
  The pin set currently in force, never null.
  `void`
  `initialize(EngineContext ctx, ShieldConfig config)`
  Called once from `AppShield.init(ShieldConfig)`.
  `void`
  `invalidate()`
  Discards any cached token, forcing the next fetch to go to the service.
  `boolean`
  `isAvailable()`
  True when this engine can actually attest.
  `void`
  `shutdown()`
  Releases resources.
  `boolean`
  `verifyPins(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 example `unprotected`, `simulator` or the enterprise engine's own identifier.

  - ### isAvailable

    boolean isAvailable()
    True when this engine can actually attest. False for the inert default, which is how `AppShield.isProtected()` is answered.

  - ### initialize

    void initialize(EngineContext ctx, ShieldConfig config)
    Called once from `AppShield.init(ShieldConfig)`. Must not block on the network; do warm-up work on a background thread.

  - ### fetchToken

    ShieldToken fetchToken(String bindingData) throws ShieldException
    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 the `ShieldStatus` that 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

    boolean verifyPins(String host, String[] spkiDigests, String[] certDigests)

    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 info
      `certDigests` - whole-certificate digests, for engines that pin those instead

  - ### getPinSet

    PinSet getPinSet()
    The pin set currently in force, never null. May be `PinSet.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.