Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
626 changes: 618 additions & 8 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions kms/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@ tempfile.workspace = true
serde-duration.workspace = true
dstack-verifier = { workspace = true, default-features = false }
dstack-mr.workspace = true
base64.workspace = true

# BLS12-381 for MPC key derivation
blstrs = "0.7"
elliptic-curve = "0.13"
hkdf = "0.12.4"
bs58 = "0.5"
rand_core = { version = "0.6", features = ["getrandom"] }

# NEAR integration
near-api = "0.8"
near-crypto = "0.26" # Still needed for InMemorySigner in onboard_service.rs

[features]
default = []
65 changes: 62 additions & 3 deletions kms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ CVMs running in dstack support three boot modes:
## KMS Implementation

### Components

#### Ethereum/Base/Phala KMS

1. **dstack-kms**
- Main RPC service for app key requests
- Quote verification and boot info validation
Expand All @@ -56,11 +59,49 @@ CVMs running in dstack support three boot modes:
- Controls permissions for individual apps
- Maintains the allowed compose hashes for each app

#### NEAR KMS

1. **dstack-kms** (same as above)
- Can be configured to use NEAR auth API instead of Ethereum

2. **dstack-kms-auth-near**
- NEAR Protocol chain interface for permission checks
- Two-step validation (same as auth-eth):
1. KMS control contract check
2. App control contract check
- Handles hex → NEAR AccountId conversion
- See [auth-near README](auth-near/README.md) for details

3. **NEAR Authorization Contracts**
- `near-dstack-kms` (Rust contract)
- Maintains a registry for all Applications
- Maintains the allowed KMS Instance MRs
- Maintains the allowed OS Images
- Supports MPC-based root key derivation from NEAR MPC network
- Factory method `register_app()` for deploying app contracts
- `near-dstack-app` (Rust contract)
- Deployed as subaccounts: `{app_id}.{kms_contract_id}`
- Controls permissions for individual apps
- Maintains the allowed compose hashes and device IDs per app

4. **MPC Key Derivation** (NEAR-specific)
- KMS can derive deterministic root keys from NEAR MPC network
- Uses BLS12-381 cryptography for secure key derivation
- All KMS instances derive the same keys when using the same MPC domain
- Falls back to local key generation if MPC config is incomplete

### Deployment
The first two components are deployed as an dstack app on dstack in Local-Key-Provider mode.

The KMS components are deployed as a dstack app on dstack in Local-Key-Provider mode.
The docker compose file would look like [this](dstack-app/docker-compose.yaml).

The solidity contracts are deployed on an ethereum compatible chain.
**Authorization Contracts:**
- **Ethereum/Base/Phala**: Solidity contracts deployed on an Ethereum-compatible chain
- **NEAR**: Rust contracts deployed on NEAR Protocol (see [near-kms README](../near-kms/README.md))

**App Contract Deployment:**
- **Ethereum**: Use Hardhat tasks (`app:deploy`, `app:add-hash`) or factory method `deployAndRegisterApp()`
- **NEAR**: Use CLI commands (`bun run app:deploy`, `bun run app:add-hash`) or KMS contract's `register_app()` method


## Trustness
Expand Down Expand Up @@ -89,12 +130,25 @@ On startup, the KMS node will either:
- Onboard: Obtain root keys from an existing KMS instance

#### Bootstrapping

**Ethereum/Base/Phala KMS:**
During bootstrapping, the KMS node generates two root keys:
1. CA root key: Used to issue x509 certificates for Apps, enabling HTTPS traffic
2. K256 root key: Used to derive Ethereum-compatible keys for Apps

After generating the root keys, their public portions can be obtained along with the corresponding TDX quote and registered in the DstackKms contract.

**NEAR KMS with MPC:**
When configured with NEAR MPC, the KMS node derives deterministic root keys from the NEAR MPC network:
1. Generates ephemeral BLS12-381 G1 keypair
2. Calls MPC contract's `request_app_private_key()` with derivation path "kms-root-key"
3. Receives encrypted response and decrypts using ephemeral private key
4. Verifies MPC signature using BLS pairing
5. Derives 32-byte root key using HKDF
6. Converts root key to CA, tmp CA, RPC, and K256 keys using deterministic key derivation

All KMS instances using the same MPC domain will derive identical root keys, enabling seamless replication without key transfer. If MPC configuration is incomplete, the system automatically falls back to local key generation (same as Ethereum).

#### KMS Self Replication
When deploying a new KMS instance (`B`) using an existing instance (`A`), the process follows these steps:

Expand All @@ -117,9 +171,14 @@ Once onboarded, the KMS node begins listening for app key provisioning requests.

When a KMS node receives a key provisioning request, it:
1. Validates the TDX quote of the requesting App
2. Queries the DstackKms contract for provisioning allowance
2. Queries the authorization contract (DstackKms or near-dstack-kms) for provisioning allowance
3. If allowed, generates and sends the keys to the App

**NEAR-specific notes:**
- App contracts are deployed as subaccounts: `{app_id}.{kms_contract_id}`
- Compose hashes are stored as hex strings (without `0x` prefix)
- Use `auth-near` CLI commands for app deployment and compose hash management (see [auth-near README](auth-near/README.md#cli-commands))

### Attestation

#### Vanilla TDX Quote attestation
Expand Down
32 changes: 32 additions & 0 deletions kms/auth-near/COMPATIBILITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# NEAR Integration Compatibility Notes

## Gateway Compatibility

The gateway handles app IDs as hex-encoded strings internally. For NEAR:
- App IDs in attestations are still bytes (as per dstack spec)
- auth-near converts hex app_id to NEAR AccountId format when calling contracts
- Gateway routing uses app_id from SNI parsing - works with any string format
- **Status**: ✅ Compatible - no changes needed

## Guest Agent Compatibility

The guest-agent uses app_id as `Vec<u8>` internally:
- App IDs come from attestation (bytes)
- Encoded/decoded as hex strings when needed
- auth-near handles the conversion to NEAR AccountId format
- **Status**: ✅ Compatible - no changes needed

## App ID Format Considerations

- **Attestation**: App IDs are always bytes (hex-encoded)
- **NEAR Contracts**: Expect AccountId (string format like "app.near")
- **Conversion**: auth-near converts hex → AccountId when calling NEAR contracts
- **Storage**: Gateway/guest-agent store app_id as hex strings internally

## Potential Future Enhancements

1. **App ID Mapping**: Consider a mapping layer if hex addresses need to map to NEAR AccountIds
2. **SNI Parsing**: Gateway SNI parsing works with any string format, but ensure AccountId format is URL-safe
3. **Validation**: Add validation to ensure AccountId format is valid NEAR account ID


Loading
Loading