diff --git a/Cargo.lock b/Cargo.lock index 6a9e9a3..728efc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1634,6 +1634,14 @@ dependencies = [ "zeroize", ] +[[package]] +name = "passless-tee" +version = "0.7.6" +dependencies = [ + "libc", + "log", +] + [[package]] name = "pem-rfc7468" version = "0.7.0" diff --git a/Cargo.toml b/Cargo.toml index f641a16..7b8214d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["cmd/passless", "passless-config-doc", "passless-core"] +members = ["cmd/passless", "passless-config-doc", "passless-core", "passless-tee"] resolver = "2" [workspace.package] @@ -13,6 +13,7 @@ repository = "https://github.com/pando85/passless" # Workspace crates passless-core = { path = "./passless-core", version = "0.7.6" } passless-config-doc = { path = "./passless-config-doc", version = "0.7.6" } +passless-tee = { path = "./passless-tee", version = "0.7.6" } soft-fido2 = "0.10.1" soft-fido2-ctap = "0.10.1" diff --git a/Makefile b/Makefile index d3abefd..f5c54e8 100644 --- a/Makefile +++ b/Makefile @@ -180,3 +180,37 @@ uninstall: uninstall-systemd uninstall-udev uninstall-sysusers uninstall-binary @echo " Note: The 'fido' group still exists. To remove it:" @echo " sudo groupdel fido" @echo "" + +# Gramine/SGX targets +.PHONY: gramine-build +gramine-build: ## build Passless with Gramine/SGX support + @echo "Building Passless with Gramine/SGX..." + cd gramine && ./build.sh + +.PHONY: gramine-clean +gramine-clean: ## clean Gramine build artifacts + @echo "Cleaning Gramine artifacts..." + cd gramine && ./build.sh clean + +.PHONY: gramine-run +gramine-run: ## run Passless in SGX enclave (standard storage) + @echo "Running Passless in SGX enclave..." + cd gramine && ./run.sh + +.PHONY: gramine-run-sealed +gramine-run-sealed: ## run Passless in SGX enclave (sealed storage) + @echo "Running Passless in SGX enclave with sealed storage..." + cd gramine && ./run.sh --sealed + +.PHONY: gramine-keygen +gramine-keygen: ## generate Gramine enclave signing key + cd gramine && ./build.sh keygen + +.PHONY: docker-sgx +docker-sgx: ## build Docker image with Gramine/SGX support + @echo "Building Docker image with SGX support..." + docker build -f gramine/Dockerfile -t passless-sgx . + +.PHONY: test-tee-detection +test-tee-detection: ## test TEE hardware detection + cargo test -p passless-tee --all-features diff --git a/README.md b/README.md index aa83b5f..a345338 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ Users should choose the solution that best fits their own security and practical - [pass](https://www.passwordstore.org/) (encrypted, git-synced) - TPM 2.0 (Experimental) - Local filesystem (testing only) +- **Intel SGX support via Gramine** (hardware memory isolation) - Security hardening (memory locking, core dump prevention) - Credential management via CTAP commands @@ -99,12 +100,24 @@ make install yay -S passless ``` -or the binary from AUR: +### Gramine/Intel SGX +For enhanced security with hardware memory isolation, Passless can run in an Intel SGX enclave using Gramine. + +**Requirements:** +- Intel SGX-capable CPU (6th gen or newer) +- SGX enabled in BIOS +- Linux kernel 5.11+ + +**Quick start:** ```bash -yay -S passless-bin +# Build and run with SGX +make gramine-build +make gramine-run ``` +See [Gramine Integration Guide](docs/GRAMINE_INTEGRATION.md) for detailed setup instructions. + ## Acknowledgements A big thank you to the [PassKeeZ](https://github.com/Zig-Sec/PassKeeZ) project for being such a diff --git a/contrib/scripts/install-gramine.sh b/contrib/scripts/install-gramine.sh new file mode 100755 index 0000000..88620ce --- /dev/null +++ b/contrib/scripts/install-gramine.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# Install Gramine support for Passless + +set -e + +GRAMINE_DIR="/opt/passless/gramine" +BIN_DIR="/usr/local/bin" +SERVICE_DIR="/etc/systemd/system" + +echo "Installing Gramine support for Passless..." + +# Create directories +echo "Creating directories..." +sudo mkdir -p "$GRAMINE_DIR" +sudo mkdir -p /var/lib/passless + +# Copy Gramine files +echo "Copying Gramine files..." +sudo cp -r gramine/* "$GRAMINE_DIR/" + +# Make scripts executable +sudo chmod +x "$GRAMINE_DIR/build.sh" +sudo chmod +x "$GRAMINE_DIR/run.sh" + +# Copy systemd wrapper +sudo install -m 755 contrib/scripts/passless-sgx-wrapper "$BIN_DIR/passless-sgx" + +# Build manifest if not exists +if [ ! -f "$GRAMINE_DIR/passless-sealed.manifest.sgx" ]; then + echo "Building Gramine manifest..." + cd "$GRAMINE_DIR" + ./build.sh +fi + +# Install systemd service +if command -v systemctl &> /dev/null; then + echo "Installing systemd service..." + sudo cp contrib/systemd/passless-sgx.service "$SERVICE_DIR/" + sudo systemctl daemon-reload + echo "" + echo "To enable the service:" + echo " sudo systemctl enable passless-sgx" + echo " sudo systemctl start passless-sgx" +fi + +echo "" +echo "Installation complete!" +echo "" +echo "Run with:" +echo " passless-sgx" +echo "" +echo "Or with systemd:" +echo " sudo systemctl start passless-sgx" \ No newline at end of file diff --git a/contrib/scripts/uninstall-gramine.sh b/contrib/scripts/uninstall-gramine.sh new file mode 100755 index 0000000..30372cb --- /dev/null +++ b/contrib/scripts/uninstall-gramine.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# Uninstall Gramine support for Passless + +set -e + +GRAMINE_DIR="/opt/passless/gramine" +BIN_DIR="/usr/local/bin" +SERVICE_DIR="/etc/systemd/system" + +echo "Uninstalling Gramine support for Passless..." + +# Stop and disable service +if [ -f "$SERVICE_DIR/passless-sgx.service" ]; then + echo "Stopping systemd service..." + sudo systemctl stop passless-sgx 2>/dev/null || true + sudo systemctl disable passless-sgx 2>/dev/null || true + sudo rm -f "$SERVICE_DIR/passless-sgx.service" + sudo systemctl daemon-reload +fi + +# Remove binary wrapper +echo "Removing binary wrapper..." +sudo rm -f "$BIN_DIR/passless-sgx" + +# Remove Gramine directory +echo "Removing Gramine files..." +sudo rm -rf "$GRAMINE_DIR" + +echo "" +echo "Uninstallation complete!" +echo "" +echo "Note: Credential data in /var/lib/passless is preserved." \ No newline at end of file diff --git a/contrib/systemd/passless-sgx-wrapper.sh b/contrib/systemd/passless-sgx-wrapper.sh new file mode 100755 index 0000000..a088a8e --- /dev/null +++ b/contrib/systemd/passless-sgx-wrapper.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Systemd wrapper for running Passless with Gramine/SGX +# Install to /usr/local/bin/passless-sgx + +set -e + +GRAMINE_DIR="/opt/passless/gramine" + +# Check SGX device +if [ ! -e /dev/sgx_enclave ] && [ ! -e /dev/sgx/enclave ]; then + echo "ERROR: Intel SGX device not found" >&2 + exit 1 +fi + +# Check UHID device +if [ ! -e /dev/uhid ]; then + echo "ERROR: UHID device not found" >&2 + exit 1 +fi + +# Check manifest +if [ ! -f "$GRAMINE_DIR/passless-sealed.manifest.sgx" ]; then + echo "ERROR: Gramine manifest not found" >&2 + exit 1 +fi + +# Run in SGX enclave with sealed storage +cd "$GRAMINE_DIR" +exec gramine-sgx passless-sealed "$@" \ No newline at end of file diff --git a/contrib/systemd/passless-sgx.service b/contrib/systemd/passless-sgx.service new file mode 100755 index 0000000..2b50ebe --- /dev/null +++ b/contrib/systemd/passless-sgx.service @@ -0,0 +1,31 @@ +[Unit] +Description=Passless FIDO2 Authenticator (Gramine/SGX) +Documentation=https://github.com/pando85/passless +After=network.target +ConditionPathExists=/dev/sgx_enclave +ConditionPathExists=/dev/uhid + +[Service] +Type=simple +ExecStart=/usr/local/bin/passless-sgx +Restart=on-failure +RestartSec=5 + +# Security hardening +NoNewPrivileges=true +ProtectSystem=strict +ProtectHome=true +PrivateTmp=true +ReadWritePaths=/var/lib/passless + +# SGX device access +DeviceAllow=/dev/sgx_enclave rw +DeviceAllow=/dev/sgx/provision rw +DeviceAllow=/dev/uhid rw + +# Resource limits +LimitNOFILE=1024 +TasksMax=10 + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/docs/GRAMINE_INTEGRATION.md b/docs/GRAMINE_INTEGRATION.md new file mode 100644 index 0000000..25a6010 --- /dev/null +++ b/docs/GRAMINE_INTEGRATION.md @@ -0,0 +1,499 @@ +# Gramine Integration for Passless + +This document provides comprehensive instructions for running Passless in an Intel SGX enclave using Gramine. + +## Overview + +Gramine (formerly Graphene) is a Library OS that enables running unmodified applications in Intel SGX enclaves. This provides hardware-based memory encryption and isolation for Passless, protecting credentials and cryptographic keys even from a compromised operating system. + +### Security Benefits + +- **Memory Encryption**: All enclave memory is encrypted by the CPU +- **Hardware Isolation**: Enclave code and data are isolated from the host OS +- **Sealed Storage**: Optional hardware-bound credential storage +- **Attestation**: Capability for remote attestation (future enhancement) + +### Architecture + +``` +┌────────────────────────────────────────────────────────┐ +│ Untrusted Host │ +│ ┌──────────────────────────────────────────────────┐ │ +│ │ Gramine Runtime │ │ +│ │ ┌────────────────────────────────────────────┐ │ │ +│ │ │ Intel SGX Enclave │ │ │ +│ │ │ ┌────────────────────────────────────────┐│ │ │ +│ │ │ │ Passless Process ││ │ │ +│ │ │ │ ┌──────────────┐ ┌────────────────┐ ││ │ │ +│ │ │ │ │ CTAP Handler │ │ Credential │ ││ │ │ +│ │ │ │ │ (soft-fido2) │ │ Storage │ ││ │ │ +│ │ │ │ └──────────────┘ └────────────────┘ ││ │ │ +│ │ │ │ Sealed Storage (Optional) ││ │ │ +│ │ │ └────────────────────────────────────────┘│ │ │ +│ │ └────────────────────────────────────────────┘ │ │ +│ └──────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌──────────────────────┐ │ +│ │ UHID Device │ │ +│ └──────────────────────┘ │ +└────────────────────────────────────────────────────────┘ +``` + +## Hardware Requirements + +### Intel SGX Capable CPU + +| Generation | Support Level | +|------------|---------------| +| Intel 6th Gen (Skylake) | SGX1 (basic) | +| Intel 7th Gen (Kaby Lake) | SGX1 | +| Intel 8th Gen (Coffee Lake) | SGX2 (recommended) | +| Intel 10th Gen+ (Ice Lake, etc.) | SGX2 with larger EPC | +| AMD CPUs | Not supported | +| ARM CPUs | Not supported | + +### BIOS Configuration + +1. Enter BIOS/UEFI settings +2. Navigate to Security or CPU Configuration +3. Enable "Intel SGX" or "Software Guard Extensions" +4. Set SGX ownership to "Enabled" (not "Software Controlled") + +### Linux Kernel Requirements + +- **Kernel 5.11+**: Native SGX driver (recommended) +- **Kernel 5.4-5.10**: May require DCAP driver + +Check SGX support: +```bash +# Check for SGX device +ls -la /dev/sgx_enclave /dev/sgx/enclave + +# Check CPU flags +grep -E 'sgx|sgxlc' /proc/cpuinfo +``` + +## Installation + +### 1. Install Gramine + +**Ubuntu 22.04+:** +```bash +sudo apt-get update +sudo apt-get install -y gramine +``` + +**Ubuntu 20.04:** +```bash +sudo apt-get install -y wget gnupg +wget -O - https://packages.gramineproject.io/gramine-keyring.gpg | \ + sudo gpg --dearmor -o /usr/share/keyrings/gramine-keyring.gpg +echo "deb [arch=amd64 signed-by=/usr/share/keyrings/gramine-keyring.gpg] \ + https://packages.gramineproject.io/$(lsb_release -sc) $(lsb_release -sc) main" | \ + sudo tee /etc/apt/sources.list.d/gramine.list +sudo apt-get update +sudo apt-get install -y gramine +``` + +**From Source:** +```bash +git clone https://github.com/gramineproject/gramine.git +cd gramine +meson setup build/ --prefix=/usr +ninja -C build +sudo ninja -C build install +``` + +### 2. Install Intel SGX Driver (if needed) + +**Kernel 5.11+:** Driver is built-in. + +**Older kernels:** +```bash +# Install DCAP driver +git clone https://github.com/intel/SGXDataCenterAttestationPrimitives.git +cd SGXDataCenterAttestationPrimitives/driver/linux +sudo make install +sudo modprobe intel_sgx +``` + +### 3. Install Passless + +```bash +# Build from source +git clone https://github.com/pando85/passless.git +cd passless +cargo build --release +sudo install -m 755 target/release/passless /usr/bin/passless +``` + +## Building Gramine-Enabled Passless + +### Standard Build + +```bash +cd passless/gramine +./build.sh +``` + +This will: +1. Build the Passless binary +2. Generate Gramine manifest files +3. Create an enclave signing key +4. Sign the manifests for SGX + +### Build Artifacts + +| File | Description | +|------|-------------| +| `passless.manifest` | Generated manifest for standard storage | +| `passless.manifest.sgx` | Signed manifest for SGX execution | +| `passless-sealed.manifest` | Manifest with SGX sealed storage | +| `passless-sealed.manifest.sgx` | Signed sealed storage manifest | +| `enclave-key.pem` | RSA key for enclave signing | + +### Custom Build Options + +**Specify library path:** +```bash +./build.sh +# The build script auto-detects library paths +# For custom paths, edit the manifest template +``` + +**Use custom signing key:** +```bash +# Generate your own key +openssl genrsa -3 -out my-key.pem 3072 + +# Sign manually +gramine-sgx-sign --key my-key.pem \ + --manifest passless.manifest \ + --output passless.manifest.sgx +``` + +## Running Passless with SGX + +### Quick Start + +```bash +# Run with standard storage +./gramine/run.sh + +# Run with SGX sealed storage (hardware-bound) +./gramine/run.sh --sealed + +# Run with verbose output +./gramine/run.sh --verbose + +# Pass arguments to passless +./gramine/run.sh -- --backend-type local --local-path /var/lib/passless +``` + +### Using gramine-sgx Directly + +```bash +cd gramine + +# Standard storage +gramine-sgx passless + +# Sealed storage +gramine-sgx passless-sealed + +# With arguments +gramine-sgx passless -- --verbose + +# Debug mode +gramine-sgx -v passless +``` + +### Storage Modes + +#### Standard Storage (`passless.manifest`) + +- Credentials stored in regular files +- Protected by Gramine filesystem isolation +- Suitable for development and testing +- Files can be backed up and migrated + +#### SGX Sealed Storage (`passless-sealed.manifest`) + +- Credentials encrypted with SGX seal key +- Hardware-bound to the specific enclave +- Cannot be accessed on different hardware +- Provides maximum security + +**Note:** Sealed storage files are stored in `/var/lib/passless-sgx/` on the host. + +### UHID Device Setup + +```bash +# Load UHID kernel module +sudo modprobe uhid + +# Create fido group and add user +sudo groupadd fido 2>/dev/null || true +sudo usermod -a -G fido $USER + +# Configure udev rules +echo 'KERNEL=="uhid", GROUP="fido", MODE="0660"' | \ + sudo tee /etc/udev/rules.d/90-uinput.rules +sudo udevadm control --reload-rules +sudo udevadm trigger + +# Log out and back in for group changes +``` + +## Docker/GSC Deployment + +### Building GSC Container + +```bash +# Install GSC +pip3 install gsc + +# Build container +cd passless +gsc build -c gramine/gsc.toml gramine/Dockerfile passless-sgx + +# Sign container +gsc sign -c gramine/gsc.toml enclave-key.pem passless-sgx +``` + +### Running Container + +```bash +# Run container with SGX +docker run --device /dev/sgx_enclave \ + -v /dev/uhid:/dev/uhid \ + -v passless-data:/var/lib/passless \ + passless-sgx +``` + +### Docker Compose + +```yaml +version: '3.8' +services: + passless: + image: passless-sgx + devices: + - /dev/sgx_enclave:/dev/sgx_enclave + - /dev/uhid:/dev/uhid + volumes: + - passless-data:/var/lib/passless + restart: unless-stopped + +volumes: + passless-data: +``` + +## Manifest Configuration + +### Standard Manifest Options + +Edit `gramine/passless.manifest.template`: + +```toml +# Enclave size (adjust based on needs) +sgx.enclave_size = "256M" # 128M, 256M, 512M, 1G + +# Number of threads +sgx.thread_num = 4 + +# Enable/disable EDMM +sgx.enable_edmm = true + +# Debug mode (disable in production) +sgx.debug = false +``` + +### Storage Paths + +```toml +# Standard file storage +fs.mount.data.type = "chroot" +fs.mount.data.path = "/var/lib/passless" +fs.mount.data.uri = "file:/var/lib/passless" + +# SGX sealed storage +fs.mount.data.type = "encrypted" +fs.mount.data.path = "/var/lib/passless" +fs.mount.data.uri = "file:/var/lib/passless-sgx" +fs.mount.data.key_name = "passless_sgx_key" +``` + +### Environment Variables + +```toml +# Passless configuration +loader.env.PASSLESS_BACKEND_TYPE = "local" +loader.env.PASSLESS_LOCAL_PATH = "/var/lib/passless" +loader.env.PASSLESS_LOG_LEVEL = "info" + +# Additional env vars +loader.env.RUST_LOG = "passless=info" +``` + +## Security Considerations + +### Threat Model + +| Threat | Mitigation | +|--------|------------| +| Memory dumping | SGX memory encryption | +| Root access | Enclave isolation | +| Kernel compromise | Hardware isolation | +| Cold boot attacks | Memory encryption | +| Physical attacks | CPU-bound encryption | + +### Best Practices + +1. **Use sealed storage** for production +2. **Disable SGX debug mode** in production +3. **Verify attestation** for remote deployments +4. **Backup signing key** securely +5. **Keep system updated** for security patches +6. **Use secure boot** for full chain of trust + +### Limitations + +- **Hardware requirement**: Requires Intel SGX CPU +- **Side channels**: SGX has known side-channel vulnerabilities +- **Performance**: ~10-30% overhead +- **Memory limit**: EPC size limits (typically 128-256MB) + +## Troubleshooting + +### SGX Device Not Found + +```bash +# Check kernel module +lsmod | grep intel_sgx + +# Load module if missing +sudo modprobe intel_sgx + +# Check device nodes +ls -la /dev/sgx* + +# Check BIOS settings +# Ensure SGX is enabled in firmware +``` + +### Manifest Errors + +```bash +# Regenerate manifest +cd gramine +gramine-manifest -Darch_libdir=/lib/x86_64-linux-gnu \ + passless.manifest.template passless.manifest + +# Re-sign manifest +gramine-sgx-sign --key enclave-key.pem \ + --manifest passless.manifest \ + --output passless.manifest.sgx +``` + +### Permission Denied + +```bash +# Check UHID permissions +ls -la /dev/uhid +groups # Should include 'fido' + +# Add user to fido group +sudo usermod -a -G fido $USER +# Log out and back in + +# Or run with sudo for testing +sudo gramine-sgx passless +``` + +### Memory Allocation Errors + +```bash +# Increase enclave size in manifest +sgx.enclave_size = "512M" + +# Check available EPC +cat /proc/cpuinfo | grep -i sgx +dmesg | grep -i sgx +``` + +### Performance Issues + +```bash +# Enable EDMM for better memory management +sgx.enable_edmm = true + +# Reduce thread count if needed +sgx.thread_num = 2 + +# Use smaller enclave size +sgx.enclave_size = "128M" +``` + +## Development + +### Building for Development + +```bash +# Enable debug output +sed -i 's/sgx.debug = false/sgx.debug = true/' gramine/*.manifest.template +./gramine/build.sh + +# Run with verbose logging +gramine-sgx -v passless +``` + +### Testing + +```bash +# Run E2E tests with Gramine +PASSLESS_GRAMINE=1 make test-e2e + +# Manual testing +./gramine/run.sh & +cargo test --test e2e_webauthn +``` + +### Custom Manifest Generation + +```bash +# Use custom template +cp gramine/passless.manifest.template gramine/custom.manifest.template + +# Edit custom.manifest.template +# ... + +# Generate and sign +gramine-manifest -Darch_libdir=/lib/x86_64-linux-gnu \ + custom.manifest.template custom.manifest +gramine-sgx-sign --key enclave-key.pem \ + --manifest custom.manifest \ + --output custom.manifest.sgx + +# Run +gramine-sgx custom +``` + +## Additional Resources + +- [Gramine Documentation](https://gramine.readthedocs.io/) +- [Intel SGX Developer Guide](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/overview.html) +- [Passless Documentation](../README.md) +- [TEE Analysis](../docs/TEE_ANALYSIS.md) + +## Contributing + +Contributions to improve Gramine integration are welcome: + +1. Performance optimizations +2. Additional manifest templates +3. Cloud deployment guides +4. Remote attestation support +5. AMD SEV support + +See [CONTRIBUTING.md](../CONTRIBUTING.md) for guidelines. \ No newline at end of file diff --git a/docs/TEE_ANALYSIS.md b/docs/TEE_ANALYSIS.md new file mode 100644 index 0000000..d3a60c4 --- /dev/null +++ b/docs/TEE_ANALYSIS.md @@ -0,0 +1,446 @@ +# TEE (Trusted Execution Environment) Analysis for Passless + +**Issue:** #168 +**Date:** 2026-03-06 +**Status:** Analysis Complete + +## Executive Summary + +This document analyzes Trusted Execution Environment (TEE) solutions for securing the Passless FIDO2 authenticator. The goal is to improve security while maintaining the same user experience. + +### Recommendation + +**Primary Recommendation: Gramine with Intel SGX** + +Gramine is the most suitable TEE solution for Passless due to: +- Production-ready with active development (latest release: June 2025) +- Runs unmodified Linux binaries (no code changes required) +- Minimal user experience impact +- Strong industry backing (Intel, Golem, Invisible Things Lab) +- Part of Confidential Computing Consortium + +**Secondary Recommendation: Keep TPM 2.0 Backend** + +The existing TPM backend should remain as it provides hardware binding without requiring TEE-capable hardware. TEE support should be an optional enhancement for users with Intel SGX-capable hardware. + +--- + +## 1. TEE Solutions Overview + +### 1.1 Enarx + +| Aspect | Details | +|--------|---------| +| **Status** | Active development, but no releases since January 2023 | +| **Last Commit** | September 2025 | +| **Technology** | WebAssembly-based runtime for TEEs | +| **Supported Hardware** | Intel SGX, AMD SEV | +| **Architecture** | Requires compilation to WebAssembly | + +**Pros:** +- Hardware-agnostic approach +- Part of Confidential Computing Consortium +- Supports both Intel SGX and AMD SEV + +**Cons:** +- No stable release in 3+ years +- Requires WebAssembly compilation +- WebAssembly limitations for system calls (UHID access) +- Uncertain project trajectory + +**Feasibility for Passless: LOW** + +The WebAssembly approach presents significant challenges: +- UHID device access requires Linux system calls not typically available in WASM +- Would require significant architecture changes +- Project appears to be in maintenance mode + +--- + +### 1.2 Gramine (formerly Graphene) + +| Aspect | Details | +|--------|---------| +| **Status** | Active development, stable releases | +| **Last Release** | June 2025 | +| **Technology** | Library OS for unmodified applications | +| **Supported Hardware** | Intel SGX | +| **Architecture** | Runs native Linux binaries in SGX enclaves | + +**Pros:** +- Runs unmodified applications (no code changes) +- Docker container support (Gramine Shielded Containers) +- Production-ready with commercial deployments +- Active community and documentation +- Supports Rust applications natively + +**Cons:** +- Intel SGX only (no AMD SEV support) +- Requires SGX-capable hardware +- Manifest file configuration required +- Performance overhead (~10-30%) + +**Feasibility for Passless: HIGH** + +Gramine can run Passless with minimal modifications: +1. Create a manifest file for Passless +2. Package with Gramine Shielded Containers +3. No source code changes required + +**Implementation Path:** +```bash +# Example manifest structure +gramine-manifest -Darch_libdir=/lib/x86_64-linux-gnu passless.manifest.template passless.manifest +gramine-sgx-sign --key enclave-key.pem --manifest passless.manifest --output passless.manifest.sgx +gramine-sgx passless +``` + +--- + +### 1.3 Occlum + +| Aspect | Details | +|--------|---------| +| **Status** | Active development | +| **Last Release** | 2024 (regular releases) | +| **Technology** | LibOS for Intel SGX | +| **Supported Hardware** | Intel SGX | +| **Architecture** | Memory-safe LibOS written in Rust | + +**Pros:** +- Written in Rust (memory-safe LibOS) +- Supports multi-process applications +- Good documentation +- Designed for production use + +**Cons:** +- Intel SGX only +- Requires application linking against Occlum +- Less mature than Gramine +- Docker integration less straightforward + +**Feasibility for Passless: MEDIUM** + +Occlum is viable but requires more integration work than Gramine: +- Application needs to be linked with Occlum toolchain +- May require modifications for UHID access patterns + +--- + +### 1.4 Confidential Containers (CNCF) + +| Aspect | Details | +|--------|---------| +| **Status** | CNCF Sandbox project, active | +| **Releases** | Every 8 weeks | +| **Technology** | Kubernetes/container-focused | +| **Supported Hardware** | Intel SGX, AMD SEV, IBM SE | + +**Pros:** +- Kubernetes-native +- Multi-platform TEE support +- Strong CNCF community +- Regular releases + +**Cons:** +- Kubernetes/container orchestration required +- Overkill for single-node authenticator +- Designed for cloud deployments + +**Feasibility for Passless: LOW** + +Confidential Containers is designed for cloud Kubernetes deployments, not single-node authenticator use cases. It would add significant complexity without proportional security benefit. + +--- + +### 1.5 Intel SGX SDK (Direct Integration) + +| Aspect | Details | +|--------|---------| +| **Status** | Mature, production-ready | +| **Technology** | Native SGX enclave development | +| **Architecture** | Requires code partitioning | + +**Pros:** +- Maximum control and performance +- Native integration +- Industry standard + +**Cons:** +- Significant code refactoring required +- Enclave/untrusted boundary complexity +- Development overhead +- Security-critical code review needed + +**Feasibility for Passless: LOW** + +Direct SGX integration would require: +- Partitioning code into enclave and untrusted components +- Rewriting all I/O operations (UHID, notifications, storage) +- Ongoing security maintenance + +--- + +## 2. Passless Architecture Analysis + +### 2.1 Current Security Model + +``` +┌─────────────────────────────────────────────────────────────┐ +│ User Space (Untrusted) │ +│ ┌─────────────────────────────────────────────────────────┐│ +│ │ Passless Process ││ +│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ ││ +│ │ │ CTAP Handler│ │Credential │ │ Notification │ ││ +│ │ │ │ │Storage │ │ (D-Bus) │ ││ +│ │ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘ ││ +│ │ │ │ │ ││ +│ │ ┌──────┴──────┐ ┌──────┴──────┐ │ ││ +│ │ │ soft-fido2 │ │ TPM/GPG │ │ ││ +│ │ │ (Crypto) │ │ (Storage) │ │ ││ +│ │ └─────────────┘ └─────────────┘ │ ││ +│ └─────────────────────────────────────────────┼──────────┘│ +│ │ │ │ +└───────────────────────────┼────────────────────┼───────────┘ + │ │ +┌───────────────────────────┼────────────────────┼───────────┐ +│ Kernel Space │ │ +│ ┌──────────────────┐ │ ┌─────────┴─────────┐ │ +│ │ UHID Device │◄───┘ │ D-Bus System │ │ +│ └──────────────────┘ └───────────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +### 2.2 Security Hardening (Current) + +The current implementation includes: +- `mlockall()` - Memory locking to prevent swapping +- Core dump prevention +- Zeroize for sensitive data +- TPM/GPG encryption for credentials at rest + +### 2.3 Attack Surface Analysis + +| Attack Vector | Current Protection | TEE Improvement | +|--------------|-------------------|-----------------| +| Memory dumping | mlockall (partial) | Full memory encryption | +| Root process inspection | Limited | Complete isolation | +| Kernel compromise | None | Hardware isolation | +| Cold boot attacks | Limited | SGX sealed storage | +| Credential exfiltration | TPM/GPG encryption | Hardware-bound keys | + +--- + +## 3. Proposed Architecture with TEE + +### 3.1 Gramine Integration Architecture + +``` +┌────────────────────────────────────────────────────────────────┐ +│ Untrusted Host │ +│ ┌──────────────────────────────────────────────────────────┐ │ +│ │ Gramine Runtime │ │ +│ │ ┌──────────────────────────────────────────────────────┐│ │ +│ │ │ Intel SGX Enclave ││ │ +│ │ │ ┌────────────────────────────────────────────────┐ ││ │ +│ │ │ │ Passless Process │ ││ │ +│ │ │ │ ┌────────────┐ ┌─────────────┐ │ ││ │ +│ │ │ │ │CTAP Handler│ │Credential │ │ ││ │ +│ │ │ │ │(soft-fido2)│ │Storage │ │ ││ │ +│ │ │ │ └────────────┘ └─────────────┘ │ ││ │ +│ │ │ │ │ │ ││ │ +│ │ │ │ Sealed Storage (SGX Protected) │ ││ │ +│ │ │ └────────────────────────────────────────────────┘ ││ │ +│ │ └──────────────────────────────────────────────────────┘│ │ +│ └──────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ┌──────────────────┐ │ ┌───────────────────────┐ │ +│ │ UHID Device │◄─────┘ │ Notification Proxy │ │ +│ └──────────────────┘ └───────────────────────┘ │ +└────────────────────────────────────────────────────────────────┘ +``` + +### 3.2 User Experience Impact + +| Aspect | Current | With Gramine | Impact | +|--------|---------|--------------|--------| +| Installation | Package/cargo | Package + manifest | Minimal | +| Performance | Native | ~10-20% overhead | Acceptable | +| Hardware | Any Linux | Intel SGX required | Significant | +| Notifications | Direct | Via proxy | Minor change | +| Storage | TPM/pass/local | Sealed files | Transparent | + +--- + +## 4. Implementation Recommendations + +### 4.1 Phase 1: Gramine Support (Recommended) + +**Objective:** Add optional Gramine/SGX support for users with compatible hardware. + +**Steps:** +1. Create Gramine manifest template for Passless +2. Add GSC (Gramine Shielded Containers) support +3. Implement sealed storage backend for SGX +4. Create notification proxy for enclave communication +5. Document hardware requirements and setup + +**Estimated Effort:** 2-4 weeks + +**Manifest Template Example:** +```toml +# passless.manifest.template +loader.entrypoint = "file:/usr/bin/passless" +loader.env.LD_LIBRARY_PATH = "/lib/x86_64-linux-gnu" + +# UHID device access +fs.mount.lib.type = "chroot" +fs.mount.lib.path = "/lib" +fs.mount.lib.uri = "file:/lib" + +# SGX configuration +sgx.enclave_size = "256M" +sgx.thread_num = 4 +sgx.remote_attestation = "none" + +# Encrypted storage +fs.mount.data.type = "encrypted" +fs.mount.data.path = "/var/lib/passless" +fs.mount.data.uri = "file:/var/lib/passless" +``` + +### 4.2 Phase 2: Hardware Detection + +Add runtime detection for TEE capabilities: + +```rust +pub enum TeeBackend { + None, + IntelSgx, + AmdSev, +} + +pub fn detect_tee() -> TeeBackend { + // Check for SGX + if Path::new("/dev/sgx_enclave").exists() { + return TeeBackend::IntelSgx; + } + // Check for SEV + if let Ok(content) = fs::read_to_string("/sys/module/kvm_amd/parameters/sev") { + if content.trim() == "Y" { + return TeeBackend::AmdSev; + } + } + TeeBackend::None +} +``` + +### 4.3 Phase 3: Sealed Storage Backend + +Implement SGX-sealed storage as a new backend: + +```rust +pub struct SgxSealedStorage { + sealed_dir: PathBuf, +} + +impl CredentialStorage for SgxSealedStorage { + // Credentials sealed with SGX seal key + // Only accessible within the same enclave +} +``` + +--- + +## 5. Hardware Requirements + +### 5.1 Intel SGX Requirements + +| Requirement | Details | +|-------------|---------| +| CPU | Intel 6th gen+ (Skylake) or newer | +| Feature | SGX2 (EDMM) preferred | +| Memory | EPC (Enclave Page Cache) - typically 128MB-256MB | +| BIOS | SGX enabled in firmware | +| Driver | Linux SGX driver (in-kernel 5.11+) | + +### 5.2 Availability + +- **Consumer Hardware:** Intel Core i5/i7/i9 6th gen+, Xeon E3/E5/E7 v5+ +- **Cloud Instances:** + - Azure: DC-series, EC-series + - Google Cloud: Not widely available + - AWS: Not widely available (AMD SEV preferred) + +--- + +## 6. Alternative: AMD SEV Consideration + +AMD SEV (Secure Encrypted Virtualization) encrypts VM memory, providing different guarantees: + +| Aspect | Intel SGX | AMD SEV | +|--------|-----------|---------| +| Isolation Unit | Application (enclave) | Entire VM | +| Code Changes | Minimal (with Gramine) | None required | +| Memory Encryption | Enclave-only | Entire VM | +| Attestation | Local/Remote | Remote (SEV-SNP) | +| Availability | Limited cloud support | Broad cloud support | + +**Recommendation:** AMD SEV is better suited for cloud deployments. For desktop use, Intel SGX with Gramine is the preferred path. + +--- + +## 7. Risk Assessment + +### 7.1 Implementation Risks + +| Risk | Likelihood | Impact | Mitigation | +|------|------------|--------|------------| +| SGX hardware availability | Medium | High | Keep TPM backend as primary | +| Performance degradation | Low | Medium | Benchmark and optimize | +| Notification proxy complexity | Low | Low | Use simple D-Bus bridge | +| Gramine compatibility issues | Low | Medium | Test thoroughly | + +### 7.2 Security Considerations + +- SGX has had side-channel vulnerabilities (Spectre, Meltdown, etc.) +- Mitigations exist but require up-to-date microcode +- SGX attestation provides additional assurance +- Sealed storage provides hardware binding + +--- + +## 8. Conclusion + +### Summary of Recommendations + +1. **Implement Gramine support** as an optional enhancement for users with Intel SGX hardware +2. **Keep TPM backend** as the recommended option for most users +3. **Document hardware requirements** clearly for users interested in TEE protection +4. **Consider cloud deployment** scenarios with AMD SEV in the future + +### Priority Order + +1. **Low:** Create Gramine manifest and documentation +2. **Low:** Add SGX-sealed storage backend +3. **Future:** Evaluate AMD SEV for cloud deployments +4. **Future:** Consider Confidential Containers for Kubernetes deployments + +### Expected Outcome + +Users with Intel SGX hardware will have an additional security layer that protects: +- Cryptographic keys in memory +- Credential processing +- Attestation capabilities + +The same user experience is preserved through Gramine's transparent execution model. + +--- + +## References + +- [Gramine Documentation](https://gramine.readthedocs.io/) +- [Intel SGX Developer Reference](https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/overview.html) +- [Enarx Project](https://enarx.dev/) +- [Confidential Containers (CNCF)](https://confidentialcontainers.org/) +- [Occlum Project](https://github.com/occlum/occlum) diff --git a/gramine/Dockerfile b/gramine/Dockerfile new file mode 100644 index 0000000..12e5ed6 --- /dev/null +++ b/gramine/Dockerfile @@ -0,0 +1,69 @@ +# Gramine Shielded Container (GSC) for Passless +# This Dockerfile creates a containerized SGX-enabled Passless + +# Stage 1: Build Passless +FROM rust:1.75 AS builder + +WORKDIR /build + +# Copy workspace files +COPY Cargo.toml Cargo.lock ./ +COPY passless-core ./passless-core +COPY passless-config-doc ./passless-config-doc +COPY cmd/passless ./cmd/passless + +# Build release binary +RUN cargo build --release + +# Stage 2: Create minimal runtime image +FROM ubuntu:22.04 + +# Install Gramine and dependencies +RUN apt-get update && apt-get install -y \ + gramine \ + libsgx-enclave-common \ + libsgx-urts \ + libsgx-launch \ + && rm -rf /var/lib/apt/lists/* + +# Create passless user and directories +RUN useradd -r -s /bin/false passless && \ + mkdir -p /var/lib/passless && \ + chown passless:passless /var/lib/passless + +# Copy binary from builder +COPY --from=builder /build/target/release/passless /usr/bin/passless + +# Copy Gramine manifest +COPY gramine/passless.manifest.template /etc/passless/passless.manifest.template + +# Create entrypoint script +RUN echo '#!/bin/bash\n\ +set -e\n\ +\n\ +# Generate manifest if needed\n\ +if [ ! -f /etc/passless/passless.manifest ]; then\n\ + gramine-manifest -Darch_libdir=/lib/x86_64-linux-gnu \\\n\ + /etc/passless/passless.manifest.template \\\n\ + /etc/passless/passless.manifest\n\ +fi\n\ +\n\ +# Sign manifest if needed\n\ +if [ ! -f /etc/passless/passless.manifest.sgx ]; then\n\ + gramine-sgx-sign --key /etc/passless/enclave-key.pem \\\n\ + --manifest /etc/passless/passless.manifest \\\n\ + --output /etc/passless/passless.manifest.sgx\n\ +fi\n\ +\n\ +# Run passless in SGX enclave\n\ +exec gramine-sgx /etc/passless/passless\n\ +' > /entrypoint.sh && chmod +x /entrypoint.sh + +# Expose UHID device +VOLUME ["/dev/uhid", "/var/lib/passless"] + +# Set entrypoint +ENTRYPOINT ["/entrypoint.sh"] + +# Default command +CMD ["--backend-type", "local", "--local-path", "/var/lib/passless"] \ No newline at end of file diff --git a/gramine/QUICK_START.md b/gramine/QUICK_START.md new file mode 100644 index 0000000..75f3ba3 --- /dev/null +++ b/gramine/QUICK_START.md @@ -0,0 +1,97 @@ +# Gramine Quick Start Guide + +This guide gets you running Passless with Intel SGX in under 10 minutes. + +## Prerequisites Check + +```bash +# 1. Check for Intel SGX CPU +grep -q 'sgx' /proc/cpuinfo && echo "✓ SGX CPU found" || echo "✗ No SGX CPU" + +# 2. Check for SGX device +ls /dev/sgx_enclave /dev/sgx/enclave 2>/dev/null && echo "✓ SGX driver loaded" || echo "✗ SGX driver missing" + +# 3. Check for Gramine +command -v gramine-sgx &>/dev/null && echo "✓ Gramine installed" || echo "✗ Gramine not installed" +``` + +## Quick Install + +### Ubuntu 22.04+ + +```bash +# Install dependencies +sudo apt-get update +sudo apt-get install -y gramine cargo + +# Setup UHID +sudo modprobe uhid +sudo groupadd fido 2>/dev/null || true +sudo usermod -a -G fido $USER +echo 'KERNEL=="uhid", GROUP="fido", MODE="0660"' | sudo tee /etc/udev/rules.d/90-uinput.rules +sudo udevadm control --reload-rules && sudo udevadm trigger +``` + +### Ubuntu 20.04 + +```bash +# Add Gramine repository +wget -O - https://packages.gramineproject.io/gramine-keyring.gpg | \ + sudo gpg --dearmor -o /usr/share/keyrings/gramine-keyring.gpg +echo "deb [arch=amd64 signed-by=/usr/share/keyrings/gramine-keyring.gpg] \ + https://packages.gramineproject.io/$(lsb_release -sc) $(lsb_release -sc) main" | \ + sudo tee /etc/apt/sources.list.d/gramine.list + +sudo apt-get update +sudo apt-get install -y gramine cargo + +# Setup UHID (same as above) +``` + +## Build and Run + +```bash +# Clone and build +git clone https://github.com/pando85/passless.git +cd passless + +# Build Passless +cargo build --release +sudo install -m 755 target/release/passless /usr/bin/passless + +# Build Gramine manifest +cd gramine +./build.sh + +# Run Passless in SGX enclave +./run.sh +``` + +## Verify It Works + +```bash +# In another terminal, test WebAuthn registration +# Use any WebAuthn demo site like https://webauthn.io/ +# The authenticator should appear and register successfully +``` + +## Common Issues + +### "SGX device not found" +- Ensure your CPU supports Intel SGX (6th gen or newer) +- Enable SGX in BIOS settings +- Load kernel driver: `sudo modprobe intel_sgx` + +### "Permission denied on /dev/uhid" +- Add user to fido group: `sudo usermod -a -G fido $USER` +- Log out and back in +- Or run with sudo for testing + +### "No such file: *.manifest.sgx" +- Run `./gramine/build.sh` to generate manifests + +## Next Steps + +- Read the full [Gramine Guide](GRAMINE_GUIDE.md) for detailed configuration +- Learn about [SGX Sealed Storage](GRAMINE_GUIDE.md#storage-modes) +- Configure [Docker deployment](GRAMINE_GUIDE.md#dockergsc-deployment) \ No newline at end of file diff --git a/gramine/README.md b/gramine/README.md new file mode 100644 index 0000000..cf7e024 --- /dev/null +++ b/gramine/README.md @@ -0,0 +1,39 @@ +# Gramine Support for Passless + +This directory contains files for running Passless in an Intel SGX enclave using Gramine. + +## Files + +| File | Description | +|------|-------------| +| `passless.manifest.template` | Gramine manifest template (standard storage) | +| `passless-sealed.manifest.template` | Gramine manifest template (SGX sealed storage) | +| `build.sh` | Build script for generating and signing manifests | +| `run.sh` | Convenience script for running Passless in SGX | +| `Dockerfile` | Dockerfile for Gramine Shielded Containers | +| `gsc.toml` | GSC configuration file | +| `QUICK_START.md` | Quick start guide for Gramine setup | + +## Quick Start + +```bash +# Build Gramine manifest +./build.sh + +# Run Passless in SGX enclave +./run.sh + +# Run with SGX sealed storage (hardware-bound) +./run.sh --sealed +``` + +## Requirements + +- Intel SGX-capable CPU (6th gen or newer) +- SGX enabled in BIOS +- Linux kernel 5.11+ or DCAP driver +- Gramine installed + +## Documentation + +See [GRAMINE_INTEGRATION.md](../docs/GRAMINE_INTEGRATION.md) for comprehensive documentation. \ No newline at end of file diff --git a/gramine/build.sh b/gramine/build.sh new file mode 100755 index 0000000..d2d3ada --- /dev/null +++ b/gramine/build.sh @@ -0,0 +1,166 @@ +#!/usr/bin/env bash +# Build script for Gramine-enabled Passless +# This script builds Passless with Gramine/SGX support + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +GRAMINE_DIR="$PROJECT_ROOT/gramine" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +log_info() { + echo -e "${GREEN}[INFO]${NC} $1" +} + +log_warn() { + echo -e "${YELLOW}[WARN]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check for required tools +check_dependencies() { + log_info "Checking dependencies..." + + local missing=() + + # Check for Gramine tools + if ! command -v gramine-sgx &> /dev/null; then + missing+=("gramine-sgx") + fi + + if ! command -v gramine-manifest &> /dev/null; then + missing+=("gramine-manifest") + fi + + if ! command -v gramine-sgx-sign &> /dev/null; then + missing+=("gramine-sgx-sign") + fi + + # Check for Rust + if ! command -v cargo &> /dev/null; then + missing+=("cargo") + fi + + if [ ${#missing[@]} -ne 0 ]; then + log_error "Missing required tools: ${missing[*]}" + log_info "Install Gramine: https://gramine.readthedocs.io/en/latest/installation.html" + exit 1 + fi + + log_info "All dependencies found" +} + +# Build Passless binary +build_passless() { + log_info "Building Passless binary..." + cd "$PROJECT_ROOT" + cargo build --release + log_info "Passless binary built successfully" +} + +# Generate enclave key if it doesn't exist +generate_enclave_key() { + local key_file="$GRAMINE_DIR/enclave-key.pem" + + if [ -f "$key_file" ]; then + log_info "Enclave key already exists: $key_file" + return + fi + + log_info "Generating new enclave key..." + openssl genrsa -3 -out "$key_file" 3072 + log_info "Enclave key generated: $key_file" +} + +# Generate manifest files +generate_manifests() { + local arch_libdir="/lib/x86_64-linux-gnu" + + log_info "Generating Gramine manifests..." + + cd "$GRAMINE_DIR" + + # Generate standard manifest + if [ -f "passless.manifest.template" ]; then + gramine-manifest -Darch_libdir="$arch_libdir" \ + passless.manifest.template passless.manifest + log_info "Generated passless.manifest" + fi + + # Generate sealed storage manifest + if [ -f "passless-sealed.manifest.template" ]; then + gramine-manifest -Darch_libdir="$arch_libdir" \ + passless-sealed.manifest.template passless-sealed.manifest + log_info "Generated passless-sealed.manifest" + fi +} + +# Sign manifests for SGX +sign_manifests() { + local key_file="$GRAMINE_DIR/enclave-key.pem" + + log_info "Signing Gramine manifests..." + + cd "$GRAMINE_DIR" + + # Sign standard manifest + if [ -f "passless.manifest" ]; then + gramine-sgx-sign --key "$key_file" \ + --manifest passless.manifest \ + --output passless.manifest.sgx + log_info "Signed passless.manifest.sgx" + fi + + # Sign sealed storage manifest + if [ -f "passless-sealed.manifest" ]; then + gramine-sgx-sign --key "$key_file" \ + --manifest passless-sealed.manifest \ + --output passless-sealed.manifest.sgx + log_info "Signed passless-sealed.manifest.sgx" + fi +} + +# Main build process +main() { + log_info "Starting Gramine build process..." + + check_dependencies + build_passless + generate_enclave_key + generate_manifests + sign_manifests + + log_info "Gramine build complete!" + log_info "Run with: gramine-sgx passless" + log_info "Or with sealed storage: gramine-sgx passless-sealed" +} + +# Handle command line arguments +case "${1:-build}" in + build) + main + ;; + clean) + log_info "Cleaning Gramine build artifacts..." + rm -f "$GRAMINE_DIR"/*.manifest.sgx + rm -f "$GRAMINE_DIR"/passless.manifest + rm -f "$GRAMINE_DIR"/passless-sealed.manifest + log_info "Clean complete" + ;; + keygen) + generate_enclave_key + ;; + *) + echo "Usage: $0 {build|clean|keygen}" + exit 1 + ;; +esac \ No newline at end of file diff --git a/gramine/gsc.toml b/gramine/gsc.toml new file mode 100644 index 0000000..3dc1cb8 --- /dev/null +++ b/gramine/gsc.toml @@ -0,0 +1,67 @@ +# GSC Configuration for Passless +# This file configures Gramine Shielded Container settings + +[gsc] +# Image name +image_name = "passless-sgx" + +# Base image for the container +base_image = "ubuntu:22.04" + +# Gramine version +gramine_version = "1.7" + +# Build arguments +[gsc.build] +# Use multi-stage build for smaller image +multi_stage = true + +# Enable debug symbols in development +debug = false + +# Enclave configuration +[gsc.enclave] +# Enclave size (256MB) +size = "256M" + +# Number of threads +threads = 4 + +# Enable EDMM for dynamic memory management +enable_edmm = true + +# Enable remote attestation (set to "dcap" for production) +attestation = "none" + +# Filesystem configuration +[gsc.filesystem] +# Use encrypted mount for credential storage +encrypted_mount = true + +# Mount points +[gsc.filesystem.mounts] +# Credential storage directory +data = "/var/lib/passless" + +# UHID device +[gsc.devices] +uhid = "/dev/uhid" + +# Security configuration +[gsc.security] +# Disable debugging in production +debug = false + +# Memory protection +mlock = true + +# Allowed syscalls (minimal set for FIDO2 operations) +[gsc.syscalls] +# Required for UHID operations +allowed = [ + "read", "write", "open", "close", "ioctl", + "mmap", "munmap", "mprotect", + "socket", "connect", "bind", "listen", "accept", + "getrandom", "clock_gettime", "nanosleep", + "exit", "exit_group" +] \ No newline at end of file diff --git a/gramine/passless-sealed.manifest.template b/gramine/passless-sealed.manifest.template new file mode 100644 index 0000000..fe4bc99 --- /dev/null +++ b/gramine/passless-sealed.manifest.template @@ -0,0 +1,77 @@ +# Passless Gramine Manifest Template with SGX Sealed Storage +# This manifest uses encrypted mount for hardware-bound credential storage + +# Entry point - the passless binary +loader.entrypoint = "file:/usr/bin/passless" + +# Library path for dynamically linked libraries +loader.env.LD_LIBRARY_PATH = "/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu" + +# Disable ASLR for deterministic behavior (optional) +loader.insecure__use_cmdline_argv = true + +# Mount host filesystem directories +# Lib directory - required for dynamic libraries +fs.mount.lib.type = "chroot" +fs.mount.lib.path = "/lib" +fs.mount.lib.uri = "file:/lib" + +# Usr lib directory - additional libraries +fs.mount.usr_lib.type = "chroot" +fs.mount.usr_lib.path = "/usr/lib" +fs.mount.usr_lib.uri = "file:/usr/lib" + +# Encrypted data directory - SGX sealed storage +# This provides hardware-bound encryption for credentials +# The key is derived from the SGX seal key, making it hardware-specific +fs.mount.data.type = "encrypted" +fs.mount.data.path = "/var/lib/passless" +fs.mount.data.uri = "file:/var/lib/passless-sgx" +fs.mount.data.key_name = "passless_sgx_key" + +# Configuration directory +fs.mount.etc.type = "chroot" +fs.mount.etc.path = "/etc" +fs.mount.etc.uri = "file:/etc" + +# Runtime directory for sockets +fs.mount.run.type = "chroot" +fs.mount.run.path = "/run" +fs.mount.run.uri = "file:/run" + +# Home directory for user config +fs.mount.home.type = "chroot" +fs.mount.home.path = "/home" +fs.mount.home.uri = "file:/home" + +# Device access +# UHID device for FIDO2 communication +sgx.allowed_files.dev_uhid = "file:/dev/uhid" + +# SGX configuration +# Enclave size - 256MB should be sufficient for Passless +sgx.enclave_size = "256M" + +# Number of threads - 4 is a good default for FIDO2 operations +sgx.thread_num = 4 + +# Enable EDMM (Enclave Dynamic Memory Management) if available +sgx.enable_edmm = true + +# Trusted files - the passless binary and its dependencies +sgx.trusted_files.passless = "file:/usr/bin/passless" + +# Debugging options (disable in production) +sgx.debug = false + +# Attestation type - none for local use +sgx.remote_attestation = "none" + +# Allowed environment variables +loader.env.PASSLESS_BACKEND_TYPE = "local" +loader.env.PASSLESS_LOCAL_PATH = "/var/lib/passless" +loader.env.PASSLESS_LOG_LEVEL = "info" +loader.env.RUST_LOG = "info" + +# Enable non-PIE binaries (Passless is compiled as PIE by default) +loader.insecure__disable_aslr = false \ No newline at end of file diff --git a/gramine/passless.manifest.template b/gramine/passless.manifest.template new file mode 100644 index 0000000..3140b60 --- /dev/null +++ b/gramine/passless.manifest.template @@ -0,0 +1,79 @@ +# Passless Gramine Manifest Template +# This manifest configures Passless to run in an Intel SGX enclave + +# Entry point - the passless binary +loader.entrypoint = "file:/usr/bin/passless" + +# Library path for dynamically linked libraries +loader.env.LD_LIBRARY_PATH = "/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu" + +# Disable ASLR for deterministic behavior (optional) +loader.insecure__use_cmdline_argv = true + +# Mount host filesystem directories +# Lib directory - required for dynamic libraries +fs.mount.lib.type = "chroot" +fs.mount.lib.path = "/lib" +fs.mount.lib.uri = "file:/lib" + +# Usr lib directory - additional libraries +fs.mount.usr_lib.type = "chroot" +fs.mount.usr_lib.path = "/usr/lib" +fs.mount.usr_lib.uri = "file:/usr/lib" + +# Passless data directory - for credential storage +# This can be changed to encrypted mount for SGX sealing +fs.mount.data.type = "chroot" +fs.mount.data.path = "/var/lib/passless" +fs.mount.data.uri = "file:/var/lib/passless" + +# Configuration directory +fs.mount.etc.type = "chroot" +fs.mount.etc.path = "/etc" +fs.mount.etc.uri = "file:/etc" + +# Runtime directory for sockets +fs.mount.run.type = "chroot" +fs.mount.run.path = "/run" +fs.mount.run.uri = "file:/run" + +# Home directory for user config +fs.mount.home.type = "chroot" +fs.mount.home.path = "/home" +fs.mount.home.uri = "file:/home" + +# Device access +# UHID device for FIDO2 communication +sgx.allowed_files.dev_uhid = "file:/dev/uhid" + +# SGX configuration +# Enclave size - 256MB should be sufficient for Passless +sgx.enclave_size = "256M" + +# Number of threads - 4 is a good default for FIDO2 operations +sgx.thread_num = 4 + +# Enable EDMM (Enclave Dynamic Memory Management) if available +# This allows the enclave to dynamically add/remove memory pages +sgx.enable_edmm = true + +# Trusted files - the passless binary and its dependencies +sgx.trusted_files.passless = "file:/usr/bin/passless" + +# Debugging options (disable in production) +sgx.debug = false + +# Attestation type - none for local use +# For remote attestation, change to "dcap" or "epid" +sgx.remote_attestation = "none" + +# Allowed environment variables +# These will be passed through to the enclave +loader.env.PASSLESS_CONFIG = "pass" +loader.env.PASSLESS_BACKEND_TYPE = "pass" +loader.env.PASSLESS_LOCAL_PATH = "/var/lib/passless" +loader.env.PASSLESS_LOG_LEVEL = "info" +loader.env.RUST_LOG = "info" + +# Enable non-PIE binaries (Passless is compiled as PIE by default) +loader.insecure__disable_aslr = false \ No newline at end of file diff --git a/gramine/run.sh b/gramine/run.sh new file mode 100755 index 0000000..e87c47c --- /dev/null +++ b/gramine/run.sh @@ -0,0 +1,141 @@ +#!/usr/bin/env bash +# Run Passless with Gramine SGX +# This script simplifies running Passless in an SGX enclave + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +GRAMINE_DIR="$SCRIPT_DIR" + +# Default configuration +MANIFEST="${GRAMINE_DIR}/passless.manifest.sgx" +SGX_MANIFEST="${GRAMINE_DIR}/passless-sealed.manifest.sgx" +USE_SEALED=false +VERBOSE=false + +usage() { + echo "Usage: $0 [OPTIONS] [-- PASSLESS_ARGS]" + echo "" + echo "Run Passless FIDO2 authenticator in an Intel SGX enclave using Gramine" + echo "" + echo "Options:" + echo " -s, --sealed Use SGX sealed storage for credentials" + echo " -v, --verbose Enable verbose Gramine output" + echo " -h, --help Show this help message" + echo "" + echo "Passless Args:" + echo " Any arguments after -- are passed to passless" + echo "" + echo "Examples:" + echo " $0 # Run with standard storage" + echo " $0 --sealed # Run with SGX sealed storage" + echo " $0 -- --backend-type pass # Use password-store backend" + echo " $0 -v -- --verbose # Enable verbose logging" + echo "" + echo "Hardware Requirements:" + echo " - Intel SGX capable CPU (6th gen or newer)" + echo " - SGX enabled in BIOS" + echo " - Linux SGX driver (kernel 5.11+)" + echo "" + echo "Setup:" + echo " sudo modprobe uhid" + echo " sudo groupadd fido 2>/dev/null || true" + echo " sudo usermod -a -G fido \$USER" + echo " echo 'KERNEL==\"uhid\", GROUP=\"fido\", MODE=\"0660\"' | sudo tee /etc/udev/rules.d/90-uinput.rules" + echo " sudo udevadm control --reload-rules && sudo udevadm trigger" + exit 0 +} + +# Parse arguments +PASSLESS_ARGS=() +while [[ $# -gt 0 ]]; do + case $1 in + -s|--sealed) + USE_SEALED=true + shift + ;; + -v|--verbose) + VERBOSE=true + shift + ;; + -h|--help) + usage + ;; + --) + shift + PASSLESS_ARGS=("$@") + break + ;; + *) + echo "Unknown option: $1" + usage + ;; + esac +done + +# Check for SGX support +check_sgx() { + if [ ! -e /dev/sgx_enclave ] && [ ! -e /dev/sgx/enclave ]; then + echo "ERROR: Intel SGX device not found" + echo "" + echo "Please ensure:" + echo " 1. Your CPU supports Intel SGX" + echo " 2. SGX is enabled in BIOS" + echo " 3. SGX driver is loaded (kernel 5.11+ or DCAP driver)" + exit 1 + fi +} + +# Check for manifest +check_manifest() { + if $USE_SEALED; then + if [ ! -f "$SGX_MANIFEST" ]; then + echo "ERROR: Signed sealed manifest not found: $SGX_MANIFEST" + echo "" + echo "Run: $GRAMINE_DIR/build.sh" + exit 1 + fi + MANIFEST="$SGX_MANIFEST" + else + if [ ! -f "$MANIFEST" ]; then + echo "ERROR: Signed manifest not found: $MANIFEST" + echo "" + echo "Run: $GRAMINE_DIR/build.sh" + exit 1 + fi + fi +} + +# Run Passless in SGX +run_gramine() { + local manifest_name + manifest_name=$(basename "$MANIFEST" .manifest.sgx) + + echo "Starting Passless in Intel SGX enclave..." + echo "Manifest: $manifest_name" + echo "Storage: $([ "$USE_SEALED" = true ] && echo "SGX Sealed" || echo "Standard")" + echo "" + + cd "$GRAMINE_DIR" + + # Build gramine-sgx command + local cmd="gramine-sgx" + + if $VERBOSE; then + cmd="$cmd -v" + fi + + cmd="$cmd $manifest_name" + + # Add passless args if provided + if [ ${#PASSLESS_ARGS[@]} -gt 0 ]; then + cmd="$cmd ${PASSLESS_ARGS[*]}" + fi + + exec $cmd +} + +# Main +check_sgx +check_manifest +run_gramine \ No newline at end of file diff --git a/passless-tee/Cargo.toml b/passless-tee/Cargo.toml new file mode 100644 index 0000000..ff84ead --- /dev/null +++ b/passless-tee/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "passless-tee" +version.workspace = true +edition.workspace = true +license-file.workspace = true +authors.workspace = true + +[dependencies] +log.workspace = true + +[target.'cfg(target_os = "linux")'.dependencies] +libc.workspace = true \ No newline at end of file diff --git a/passless-tee/src/detection.rs b/passless-tee/src/detection.rs new file mode 100644 index 0000000..44186bc --- /dev/null +++ b/passless-tee/src/detection.rs @@ -0,0 +1,226 @@ +//! TEE detection implementation for Linux + +use log::{debug, info, warn}; +use std::fs; +use std::path::Path; + +/// Supported TEE backends +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TeeBackend { + /// No TEE support detected + None, + /// Intel SGX (Software Guard Extensions) + IntelSgx, + /// AMD SEV (Secure Encrypted Virtualization) + AmdSev, +} + +/// TEE capabilities and features +#[derive(Debug, Clone)] +pub struct TeeCapabilities { + /// The detected TEE backend + pub backend: TeeBackend, + /// SGX: Enclave Page Cache size (bytes) + pub sgx_epc_size: Option, + /// SGX: Supports EDMM (Enclave Dynamic Memory Management) + pub sgx_edmm: bool, + /// SEV: SEV version (1, 2 for SEV-ES, 3 for SEV-SNP) + pub sev_version: Option, +} + +impl Default for TeeCapabilities { + fn default() -> Self { + Self { + backend: TeeBackend::None, + sgx_epc_size: None, + sgx_edmm: false, + sev_version: None, + } + } +} + +impl TeeCapabilities { + /// Check if TEE is available + pub fn is_available(&self) -> bool { + self.backend != TeeBackend::None + } + + /// Check if SGX is available + pub fn is_sgx_available(&self) -> bool { + self.backend == TeeBackend::IntelSgx + } + + /// Check if SEV is available + pub fn is_sev_available(&self) -> bool { + self.backend == TeeBackend::AmdSev + } +} + +/// Detect TEE capabilities on the current system +pub fn detect_tee() -> TeeCapabilities { + let mut caps = TeeCapabilities::default(); + + if detect_sgx(&mut caps) { + info!("Intel SGX detected"); + return caps; + } + + if detect_sev(&mut caps) { + info!("AMD SEV detected"); + return caps; + } + + debug!("No TEE support detected"); + caps +} + +/// Detect Intel SGX support +fn detect_sgx(caps: &mut TeeCapabilities) -> bool { + let sgx_dev = Path::new("/dev/sgx_enclave"); + let sgx_dev_dcap = Path::new("/dev/sgx/enclave"); + + if !sgx_dev.exists() && !sgx_dev_dcap.exists() { + debug!("No SGX device found"); + return false; + } + + debug!("SGX device found"); + + if !check_cpu_flag("sgx") { + warn!("SGX device exists but CPU flag 'sgx' not found"); + return false; + } + + caps.sgx_epc_size = detect_epc_size(); + caps.sgx_edmm = check_cpu_flag("sgxlc"); + caps.backend = TeeBackend::IntelSgx; + true +} + +/// Detect AMD SEV support +fn detect_sev(caps: &mut TeeCapabilities) -> bool { + let sev_param = Path::new("/sys/module/kvm_amd/parameters/sev"); + let snp_param = Path::new("/sys/module/kvm_amd/parameters/sev_snp"); + + if !sev_param.exists() { + debug!("SEV kernel module parameter not found"); + return false; + } + + let Ok(content) = fs::read_to_string(sev_param) else { + return false; + }; + + if content.trim() != "Y" { + debug!("SEV not enabled in kernel"); + return false; + } + + caps.sev_version = Some(1); + + if let Ok(content) = fs::read_to_string("/sys/module/kvm_amd/parameters/sev_es") + && content.trim() == "Y" + { + caps.sev_version = Some(2); + } + + if snp_param.exists() + && let Ok(content) = fs::read_to_string(snp_param) + && content.trim() == "Y" + { + caps.sev_version = Some(3); + } + + caps.backend = TeeBackend::AmdSev; + true +} + +/// Check if a CPU flag is present +#[allow(clippy::collapsible_if)] +fn check_cpu_flag(flag: &str) -> bool { + let Ok(cpuinfo) = fs::read_to_string("/proc/cpuinfo") else { + warn!("Failed to read /proc/cpuinfo"); + return false; + }; + + for line in cpuinfo.lines() { + if line.starts_with("flags") { + if let Some(flags) = line.split(':').nth(1) { + return flags.split_whitespace().any(|f| f == flag); + } + } + } + + false +} + +/// Detect SGX EPC (Enclave Page Cache) size +#[allow(clippy::collapsible_if)] +fn detect_epc_size() -> Option { + let Ok(cpuinfo) = fs::read_to_string("/proc/cpuinfo") else { + return None; + }; + + for line in cpuinfo.lines() { + if line.starts_with("sgx_epc_sections") { + if let Some(size_str) = line.split(':').nth(1) { + if let Ok(size) = size_str.trim().parse::() { + return Some(size); + } + } + } + } + + debug!("Could not determine EPC size, using default estimate"); + Some(128 * 1024 * 1024) +} + +/// Check if running inside a Gramine SGX enclave +#[allow(dead_code)] +pub fn is_gramine_sgx() -> bool { + std::env::var("GRAMINE").is_ok() || std::env::var("SGX").is_ok() +} + +/// Check if SGX attestation is available +#[allow(dead_code)] +pub fn is_attestation_available() -> bool { + Path::new("/dev/sgx/attestation").exists() + || Path::new("/dev/sgx_attestation").exists() + || Path::new("/dev/sgx_isv").exists() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_tee_backend_equality() { + assert_eq!(TeeBackend::None, TeeBackend::None); + assert_eq!(TeeBackend::IntelSgx, TeeBackend::IntelSgx); + assert_ne!(TeeBackend::IntelSgx, TeeBackend::AmdSev); + } + + #[test] + fn test_tee_capabilities_default() { + let caps = TeeCapabilities::default(); + assert_eq!(caps.backend, TeeBackend::None); + assert!(!caps.is_available()); + } + + #[test] + fn test_tee_capabilities_sgx() { + let mut caps = TeeCapabilities::default(); + caps.backend = TeeBackend::IntelSgx; + assert!(caps.is_available()); + assert!(caps.is_sgx_available()); + assert!(!caps.is_sev_available()); + } + + #[test] + fn test_detect_tee() { + let caps = detect_tee(); + match caps.backend { + TeeBackend::None | TeeBackend::IntelSgx | TeeBackend::AmdSev => {} + } + } +} diff --git a/passless-tee/src/lib.rs b/passless-tee/src/lib.rs new file mode 100644 index 0000000..3d4e77f --- /dev/null +++ b/passless-tee/src/lib.rs @@ -0,0 +1,8 @@ +//! TEE (Trusted Execution Environment) detection and utilities +//! +//! This crate provides hardware detection for TEE capabilities +//! including Intel SGX and AMD SEV. + +mod detection; + +pub use detection::{TeeBackend, TeeCapabilities, detect_tee};