Skip to content

Conversation

@afeight
Copy link
Contributor

@afeight afeight commented Dec 5, 2025

crypto: add TEE attestation service

Summary

Adds TEE (Trusted Execution Environment) attestation functionality to the Swift SDK, translating the JavaScript implementation from open-signer. This enables native iOS apps to verify TEE attestations and obtain the TEE's public key for secure communication.

New Components:

  • TEEAttestationService - Actor that fetches attestation via CrossmintService, verifies the TEE report, validates the public key commitment, and imports the P-256 ECDH public key
  • TEEAttestationEndpoint - Endpoint enum for /ncs/v1/attestation following SDK patterns
  • DstackVerifier - Verifier that calls Phala's API to verify Intel TDX quotes and extract report data
  • TEEQuoteVerifier protocol - Allows for different verification strategies
  • TEEAttestationError - Conforms to ServiceError for proper error handling integration

Note: The verifyTEEApplicationIntegrity step is skipped per request - this can be added in a follow-up PR.

Updates since last revision

  • Refactored TEEAttestationService to use CrossmintService instead of raw URLSession calls
  • Added TEEAttestationEndpoint enum following the SDK's endpoint pattern (e.g., HeadlessCheckoutOrderEndpoint)
  • Made TEEAttestationError conform to ServiceError protocol with fromServiceError and fromNetworkError mappings
  • Added CrossmintService and Http dependencies to the Cryptography target
  • Updated tests to use MockCrossmintService
  • DstackVerifier still calls Phala API directly for quote verification (this is intentional - only attestation fetch uses CrossmintService)

Review & Testing Checklist for Human

  • Endpoint path correctness: Verify /ncs/v1/attestation is correct. The SDK base URL is https://{env}crossmint.com/api, so the full path will be /api/ncs/v1/attestation. Confirm this matches the expected API route.
  • JSON key ordering in verifyReportAttestsPublicKey: The SHA-512 hash verification depends on exact JSON serialization matching the TypeScript implementation. Swift uses .sortedKeys which should produce alphabetical ordering (publicKey before timestamp). Verify this matches the server-side expectation.
  • P-256 public key import format: Code tries x963Representation first, then rawRepresentation. Confirm this matches the base64-encoded format returned by the attestation API.
  • ServiceError mapping: Verify that TEEAttestationError.fromNetworkError and fromServiceError produce appropriate error messages for debugging.
  • Integration test with real attestation: Unit tests use mocks. Consider testing against a real attestation endpoint to verify end-to-end flow.

Test Plan

  1. Run swift test to execute unit tests
  2. Verify the endpoint path test passes: testTEEAttestationEndpointPath checks that path is /ncs/v1/attestation
  3. For integration testing, initialize TEEAttestationService with a real CrossmintService and DstackVerifier, call initialize(), and verify getAttestedPublicKey() returns a valid P-256 key

Notes

- Add TEEAttestationService for fetching and verifying TEE attestations
- Add DstackVerifier using Phala API for TEE quote verification
- Add unit tests for both components
- Implements P-256 ECDH public key import from attestation

Co-Authored-By: [email protected] <[email protected]>
@devin-ai-integration
Copy link

Original prompt from [email protected]
SYSTEM:
=== BEGIN THREAD HISTORY (in #proj-non-custodial-signers) ===
Austin Feight (U03BS1CLKAN): from discussion today

ATTACHMENT:"https://app.devin.ai/attachments/c5bccfe6-6aaf-40ec-888c-3a3b755da785/image.png"

Tomás Martins (U09TNM5QQ1F): thanks for putting this together <@U03BS1CLKAN> :pray:

on this whole process, which takes part inside the iframe and which happens in the native part of the SDK?

Having this in mind will really help me out lay down how we can log this whole thing on the sdks

Austin Feight (U03BS1CLKAN): Right now, everything after `[SDK] --> { request }` is handled within the WebView. Still important from mobile SDK perspective because:
1. SDK is the one doing the retries and defining the timeouts for them
2. Not pictured is “is the webview successfully loaded in the first place”
3. We should consider if the webview is helping or hurting; all of these steps we can probably do with native code and then we have a more native way to handle network latency/errors/etc. IndexedDB hasn’t proven to be super reliable

Austin Feight (U03BS1CLKAN): Re: #1
Timeouts don’t really make sense. We have an exception handler in JS to catch any errors that appear during the request handling process, so we _should_ reasonably be able to assume that we’ll always get a response back eventually, whether success or error.
However, there’s always the 1% chance that something completely unexpected happens and JS stops executing entirely. So I wanted to ask: would we know from iOS (and Android) that something critical went wrong within the webview like this?

Austin Feight (U03BS1CLKAN): Am I crazy for thinking that these steps would be relatively easy to replicate with native code?

Alberto Elias (U07DZFTNUQL): which steps specifically? the reason for loading the frame is making a TEE client-side

Austin Feight (U03BS1CLKAN): all of them
• get device ID
    ◦ check in keychain (user-scoped)
    ◦ else, generate keypair &amp; store in keychain
• get master secret
   ... (2550 chars truncated...)

@devin-ai-integration
Copy link

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration bot and others added 2 commits December 5, 2025 03:26
…ssion

- Add CrossmintService and Http dependencies to Cryptography target
- Create TEEAttestationEndpoint enum for /ncs/v1/attestation endpoint
- Make TEEAttestationError conform to ServiceError protocol
- Update TEEAttestationService to accept CrossmintService instead of apiBaseURL
- Add MockCrossmintService for unit tests
- DstackVerifier still calls Phala API directly for quote verification

Co-Authored-By: [email protected] <[email protected]>
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