Skip to content

feat(ffi): external-token Ed25519 sign callback for federation-identity mint (Android YubiKey/NFC) - #115

Open
emooreatx wants to merge 1 commit into
mainfrom
feat/federation-identity-callback-signer
Open

feat(ffi): external-token Ed25519 sign callback for federation-identity mint (Android YubiKey/NFC)#115
emooreatx wants to merge 1 commit into
mainfrom
feat/federation-identity-callback-signer

Conversation

@emooreatx

Copy link
Copy Markdown
Contributor

What

Adds ciris_verify_create_federation_identity_with_callback + a CallbackHardwareSigner (impl HardwareSigner) so a YubiKey-backed federation identity can be minted when the token is reachable only by an app's native layer (e.g. YubiKit over NFC on Android), not by this library.

Why

On desktop the node opens the YubiKey locally via ykcs11. On a phone the runtime is sandboxed and can't reach an NFC/USB token — the hardware ops must run in the app (YubiKit). The existing ciris_verify_create_federation_identity builds its own signer internally (get_platform_ed25519_signer) with no way to inject an app-provided one. This adds that seam.

How

The core composes the self_key_record + the platform-sealed ML-DSA-65 half exactly as create_federation_identity does, and delegates only the one classical Ed25519 signature to a caller-supplied C callback:

int ciris_verify_create_federation_identity_with_callback(
    const char* config_json,
    const uint8_t* ed25519_pubkey, size_t pubkey_len,   // 32, pre-read from slot 9c
    const uint8_t* attestation_der, size_t attestation_len, // optional slot-9c PIV attest
    void* sign_ctx, FfiEd25519SignCallback sign_cb,     // delegate (e.g. YubiKit session)
    char** result_out);

CallbackHardwareSigner::sign() invokes sign_cb synchronously; public_key() returns the passed-in key; attestation() reports the external-token tier. The app pre-reads the pubkey + attestation, so the core never touches the token.

Testing

  • New unit tests (callback_signer::tests): delegation plumbing + callback-failure path — both green.
  • cargo build -p ciris-verify-ffi + cargo test -p ciris-verify-ffi pass; pre-commit (fmt/clippy/doc/version) green.
  • Not device-tested against a real YubiKey yet (no token/NFC in CI) — that lands with the Android client wiring in the 0.6.x cycle.

Scope / notes

🤖 Generated with Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

…ty mint

Adds `ciris_verify_create_federation_identity_with_callback` + a
`CallbackHardwareSigner` (impl `HardwareSigner`) so a YubiKey-backed federation
identity can be minted when the token is reachable only by an app's native layer
(e.g. YubiKit over NFC on Android), not by this library.

The core composes the `self_key_record` + the platform-sealed ML-DSA-65 half
exactly as `create_federation_identity` does, and delegates ONLY the one classical
Ed25519 signature to a caller-supplied C callback. The caller pre-reads the
32-byte Ed25519 public key + (optionally) the slot-9c PIV attestation DER, so the
core never touches the token. Unit-tested (delegation plumbing + failure path).

Builds on the v6.13.0 #112/#113 YubiKey provisioning fixes. Additive: a new FFI
symbol + module, no breaking changes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GG4YtiJZkpoJWeS8Y8bMdY
@emooreatx
emooreatx force-pushed the feat/federation-identity-callback-signer branch from 90daf88 to f0d3cf4 Compare July 1, 2026 13:32
@emooreatx

Copy link
Copy Markdown
Contributor Author

Rebased onto v8.3.0 main (was ~5 releases stale, cut against v6.13.0-era main).

  • The prior Test (windows-latest) failure was not a code bug — the Build step hit the crates.io HTTP/2 flake (download of cryptoki failed … [55] Failed receiving HTTP2 data). That flake is hardened on main since ci: harden crates.io fetch against the recurring HTTP/2 SSL-eof flake #148 (CARGO_NET_RETRY / CARGO_HTTP_MULTIPLEXING=false), which this branch now inherits.
  • Rebase was clean — no conflicts (the new callback_signer.rs + the lib.rs module registration slotted in around the v7/v8 additions).
  • Validated on the new base: cargo build -p ciris-verify-ffi ✓, 77 ffi tests pass (incl. callback_signer::tests::{delegates_sign_and_reports_pubkey, surfaces_callback_failure}), clippy -D warnings clean, fmt clean.

Mergeable again. Fresh CI running.

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.

1 participant