diff --git a/Cargo.lock b/Cargo.lock index a29558c..d1fbf72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -375,6 +375,8 @@ name = "enclaveapp-cache" version = "0.1.0" dependencies = [ "enclaveapp-core", + "fs4", + "sha2", "tempfile", ] @@ -387,9 +389,11 @@ dependencies = [ "libc", "serde", "serde_json", + "sha2", "thiserror", "toml 0.8.23", "tracing", + "windows", ] [[package]] @@ -406,6 +410,7 @@ dependencies = [ "serde", "serde_json", "sha2", + "zeroize", ] [[package]] @@ -437,6 +442,7 @@ dependencies = [ "serde", "serde_json", "sha2", + "zeroize", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4ed7f46..cb24914 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ aes-gcm = "0.10" elliptic-curve = { version = "0.13", features = ["sec1"] } # Windows -windows = { version = "0.58", features = ["Win32_Security", "Win32_Security_Cryptography", "Win32_Foundation", "Security_Credentials_UI", "Foundation"] } +windows = { version = "0.58", features = ["Win32_Security", "Win32_Security_Cryptography", "Win32_Foundation", "Win32_System_Threading", "Win32_System_SystemServices", "Security_Credentials_UI", "Foundation"] } # Linux TPM tss-esapi = "7" diff --git a/DESIGN.md b/DESIGN.md index 45788de..d553626 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -82,7 +82,7 @@ It also centralizes WSL bridge lookup, access-policy handling, and app-specific Beyond the backends, a handful of crates provide cross-consumer utilities: -- **`enclaveapp-app-adapter`** — generic secret-delivery substrate used by Type 1-3 apps. Provides `BindingStore`, `SecretStore`, the program resolver, the `execve()`-based launcher (with `mlock` + zeroize of env-override bytes), provenance tracking, state-locking, and `TempConfig::write` (with the per-platform `create_platform_config()` memfd/tempfile selection). +- **`enclaveapp-app-adapter`** — generic secret-delivery substrate used by Type 1-3 apps. Provides `BindingStore`, `SecretStore` (with typed `SecretRead { Present, Redacted, Absent }` read path that replaces the string-sentinel `""` round-trip), the program resolver, the `execve()`-based launcher (with `mlock` + zeroize of env-override bytes, optional `with_env_scrub(patterns)` to remove matching inherited env vars from both child and parent, and per-child `RLIMIT_CORE = 0`), provenance tracking, state-locking, and `TempConfig::write` (with the per-platform `create_platform_config()` memfd/tempfile selection). - **`enclaveapp-cache`** — the shared on-disk cache file format (`[magic][version][flags][length-prefixed blobs]`). Consumed by sso-jwt's token cache and awsenc's credential cache. - **`enclaveapp-tpm-bridge`** — the shared bridge server crate; delegated to by the per-app bridge binaries. - **`enclaveapp-build-support`** — factored-out helpers for Windows `build.rs` resource compilation. @@ -94,8 +94,12 @@ Beyond the backends, a handful of crates provide cross-consumer utilities: - `setrlimit(RLIMIT_CORE, 0)` on all Unix — no core dumps that could capture secret buffers. - `prctl(PR_SET_DUMPABLE, 0)` on Linux — `/proc//mem` becomes root-only, `ptrace` attach from same-UID peers is denied. - `prctl(PR_SET_NO_NEW_PRIVS, 1)` on Linux — subsequent `exec*()` can't gain setuid/file-capabilities privileges. +- `SetProcessMitigationPolicy` on Windows (safe subset): + - `ProcessStrictHandleCheckPolicy` with `RaiseExceptionOnInvalidHandleReference` + `HandleExceptionsPermanentlyEnabled` — turns handle-confusion bugs into `STATUS_INVALID_HANDLE` rather than silent misuse. + - `ProcessExtensionPointDisablePolicy` with `DisableExtensionPoints` — blocks AppInit_DLLs, shim engines, and other legacy DLL-injection extension points. + - `ProcessImageLoadPolicy` with `NoRemoteImages` + `NoLowMandatoryLabelImages` — refuses DLL loads from UNC paths and low-integrity files. -See `crates/enclaveapp-core/src/process.rs`. `mlock_buffer` / `munlock_buffer` are exposed for consumer crates that want to pin specific byte buffers in RAM. +See `crates/enclaveapp-core/src/process.rs`. `mlock_buffer` / `munlock_buffer` are exposed for consumer crates that want to pin specific byte buffers in RAM. Type 2 apps also clamp `RLIMIT_CORE = 0` on the **spawned child** via a `pre_exec` hook in `enclaveapp-app-adapter::launcher`, so a crash of the wrapped target (e.g. `npm`) cannot core-dump its secret-laden environment. ## Access policy model @@ -180,7 +184,7 @@ Signing keys are long-lived identity keys (e.g., SSH keys). At Levels 1-3, the h | Level | Backend | Who signs? | Private key exportable? | User presence | Key storage | |:-----:|---------|-----------|:----------------------:|---------------|-------------| -| **1** | macOS Secure Enclave | **The SE hardware.** `sshenc` sends data to the SE via CryptoKit; the SE performs ECDSA P-256 internally and returns the signature. The private key never exists outside the chip. Works for both signed and unsigned binaries on Apple Silicon. | **No** — impossible. Even root cannot extract it. The `dataRepresentation` on disk is an opaque SE handle (not key material); it is AES-256-GCM wrapped under a 32-byte key stored in the login Keychain (service `com.enclaveapp.`, account `