{"id":46549248,"url":"https://github.com/raspberrypi/cryptsetup-passphrase-agent","last_synced_at":"2026-03-07T03:00:50.503Z","repository":{"id":342572277,"uuid":"1174379845","full_name":"raspberrypi/cryptsetup-passphrase-agent","owner":"raspberrypi","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-06T13:21:13.000Z","size":21,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-06T16:16:27.432Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/raspberrypi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-06T11:26:26.000Z","updated_at":"2026-03-06T13:45:44.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/raspberrypi/cryptsetup-passphrase-agent","commit_stats":null,"previous_names":["raspberrypi/cryptsetup-passphrase-agent"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/raspberrypi/cryptsetup-passphrase-agent","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Fcryptsetup-passphrase-agent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Fcryptsetup-passphrase-agent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Fcryptsetup-passphrase-agent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Fcryptsetup-passphrase-agent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/raspberrypi","download_url":"https://codeload.github.com/raspberrypi/cryptsetup-passphrase-agent/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/raspberrypi%2Fcryptsetup-passphrase-agent/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30206336,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T19:07:06.838Z","status":"online","status_checked_at":"2026-03-07T02:00:06.765Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-07T03:00:30.348Z","updated_at":"2026-03-07T03:00:50.489Z","avatar_url":"https://github.com/raspberrypi.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cryptsetup-passphrase-agent\n\nA non-interactive systemd password agent for encrypted disk passphrases written in Rust.\n\n## Overview\n\nThis agent watches `/run/systemd/ask-password/` for password requests from systemd and automatically responds to `cryptsetup` requests (encrypted disk passphrases) with a configured passphrase. All other password requests are ignored.\n\nThis is useful for systems with encrypted disks that need to be unlocked automatically without user interaction, such as headless servers or embedded systems.\n\n## Project Structure\n\n```\nsrc/\n├── main.rs              # Entry point and main loop\n├── parse.rs             # Parsing utilities for systemd config values\n├── password_request.rs  # PasswordRequest parsing and PasswordRequestWatcher iterator\n├── cryptsetup.rs        # CryptsetupPassphraseRequest for handling cryptsetup requests\n├── passphrase.rs        # Passphrase derivation from device ID\n└── rpifwcrypto.rs       # FFI bindings to librpifwcrypto\n\ndebian/\n├── control              # Package metadata\n├── rules                # Build rules\n├── changelog            # Package changelog\n├── copyright            # Licence information\n├── gbp.conf             # git-buildpackage configuration\n├── cargo-checksum.json  # Cargo checksum placeholder\n├── salsa-ci.yml         # Salsa CI configuration\n├── source/format        # Source package format\n├── cryptsetup-passphrase-agent.service  # systemd service unit\n├── cryptsetup-passphrase-agent.path     # systemd path unit\n└── cryptsetup-passphrase-agent.install  # Installation paths\n```\n\n## Building for Debian\n\nThis project is packaged as a native Debian package and uses Debian's `librust-*` packages for dependencies rather than downloading crates from crates.io, ensuring an isolated and reproducible build environment.\n\n### Build Instructions\n\nInstall build dependencies:\n\n```bash\nsudo mk-build-deps --install --remove\n```\n\nBuild the package:\n\n```bash\ndebuild -b -uc -us\n```\n\nThe built `.deb` package will be created in the parent directory.\n\n### Incremental Builds with Cargo\n\nCargo may be used directly in support of incremental builds by setting the following environment variables:\n\n```bash\nexport CARGO_HOME=debian/cargo_home\nexport CARGO_REGISTRY=debian/cargo_registry\n```\n\nThen use cargo as normal:\n\n```bash\ncargo build --release\ncargo test\n```\n\nThe binary will be at `target/release/cryptsetup-passphrase-agent`.\n\n## Usage\n\nThe agent must be run as root (or with appropriate privileges) to access `/run/systemd/ask-password/` and respond to password requests.\n\n```bash\nsudo ./target/release/cryptsetup-passphrase-agent\n```\n\nThe agent will:\n1. Watch `/run/systemd/ask-password/` for new password request files\n2. Parse each `ask.*` file that appears\n3. For `cryptsetup:` requests only, send the configured passphrase\n4. Ignore all other password requests\n\n## Passphrase Derivation\n\nThe passphrase for each encrypted device is derived using:\n\n1. **Device Innate ID** - A unique identifier for the block device (e.g., the CID for eMMC/SD cards)\n2. **HMAC-SHA256** - The ID is hashed using a firmware OTP key via `rpifwcrypto`\n\nThis ensures that:\n- Each device gets a unique passphrase\n- The passphrase cannot be derived without access to the firmware crypto service\n- The raw key material never leaves the firmware\n\nThe device innate ID is retrieved using the `block-device-id` crate, which reads hardware identifiers from sysfs (e.g., MMC CID from `/sys/block/mmcblk0/device/cid` or NVMe serial numbers).\n\n## systemd Integration\n\nThe package installs two systemd units:\n\n### `cryptsetup-passphrase-agent.path`\n\nA path unit that watches `/run/systemd/ask-password/` and triggers the service when the directory becomes non-empty. Configured to run before `cryptsetup.target`:\n\n```ini\n[Unit]\nDefaultDependencies=no\nBefore=paths.target cryptsetup.target\nConflicts=emergency.service shutdown.target\n\n[Path]\nDirectoryNotEmpty=/run/systemd/ask-password\nMakeDirectory=yes\n\n[Install]\nWantedBy=sysinit.target\n```\n\n### `cryptsetup-passphrase-agent.service`\n\nThe service unit that runs the agent:\n\n```ini\n[Service]\nType=simple\nExecStart=/usr/bin/cryptsetup-passphrase-agent\n```\n\n### Enabling\n\nAfter installing the Debian package:\n\n```bash\nsudo systemctl enable cryptsetup-passphrase-agent.path\n```\n\nThe path unit will automatically start the service when password requests appear.\n\n## How It Works\n\nThe agent implements the [systemd Password Agents protocol](https://systemd.io/PASSWORD_AGENTS/):\n\n1. Uses `inotify` to watch for `IN_CLOSE_WRITE` and `IN_MOVED_TO` events in `/run/systemd/ask-password/`\n2. Parses `.ini` format ask files using `rust-ini`\n3. Validates requests:\n   - Checks if the requesting process is still alive\n   - Checks if the request has expired (`NotAfter` field)\n   - Only handles `cryptsetup:` requests (based on `Id` field)\n4. Sends the passphrase prefixed with `+` to the Unix datagram socket specified in `Socket=`\n\n## Testing\n\n### Unit Tests\n\nWith the environment variables set (see above):\n\n```bash\ncargo test\n```\n\n### End-to-End Testing\n\nTo test the full passphrase derivation and disk unlock flow, you need a Raspberry Pi with an OTP key provisioned and a spare block device.\n\n#### 1. Prerequisites\n\nEnsure an OTP key is provisioned:\n\n```bash\nrpi-fw-crypto get-key-status 1\n```\n\n#### 2. Prepare a Test Block Device\n\nFormat the block device and create a single partition. In this example, we use `mmcblk0` (the SD card) whilst booting from NVMe:\n\n```bash\n# Save the device's CID for passphrase derivation\ncp /sys/block/mmcblk0/device/cid ./tmp_cid\n```\n\n#### 3. Derive the Passphrase\n\nDerive the disk encryption passphrase using the firmware HMAC:\n\n```bash\nrpi-fw-crypto hmac --in ./tmp_cid --key-id 1 --outform hex\n```\n\nThis prints the passphrase to stdout. Use this when setting up LUKS.\n\n#### 4. Set Up LUKS Encryption\n\nFormat the partition with LUKS using the derived passphrase:\n\n```bash\nsudo cryptsetup luksFormat /dev/mmcblk0p1\n```\n\nEnter the passphrase from step 3 when prompted.\n\n#### 5. Test the Password Agent\n\nThe password agent only responds to requests from systemd services, not interactive terminal sessions. In production, `/etc/crypttab` entries are processed by `systemd-cryptsetup-generator` to create unlock services. For testing, create a service manually:\n\nCreate `/etc/systemd/system/systemd-cryptsetup@test.service`:\n\n```ini\n[Unit]\nDescription=Cryptography Setup for %I\nDocumentation=man:crypttab(5) man:systemd-cryptsetup-generator(8) man:systemd-cryptsetup@.service(8)\n\nDefaultDependencies=no\nAfter=cryptsetup-pre.target systemd-udevd-kernel.socket\nBefore=blockdev@dev-mapper-%i.target\nWants=blockdev@dev-mapper-%i.target\nIgnoreOnIsolate=true\nConflicts=umount.target\nBefore=umount.target\nBefore=cryptsetup.target\nBindsTo=dev-mmcblk0p1\nAfter=dev-mmcblk0p1\n\n[Service]\nType=oneshot\nRemainAfterExit=yes\nTimeoutSec=infinity\nKeyringMode=shared\nOOMScoreAdjust=500\nExecStart=/usr/bin/systemd-cryptsetup attach 'test' '/dev/mmcblk0p1' 'none' 'luks,discard'\nExecStop=/usr/bin/systemd-cryptsetup detach 'test'\n```\n\nReload systemd to pick up the new service, then start it:\n\n```bash\nsudo systemctl daemon-reload\nsudo systemctl start systemd-cryptsetup@test.service\n```\n\n#### 6. Verify\n\nCheck the agent responded successfully:\n\n```bash\nsystemctl status cryptsetup-passphrase-agent.service\n```\n\nThe encrypted device should now be available at `/dev/mapper/test`.\n\n## Security Considerations\n\n- Passphrases are derived at runtime using hardware-bound cryptography:\n  - The device's innate ID (e.g., MMC CID) is read from sysfs\n  - HMAC-SHA256 is computed using a firmware OTP key that never leaves the hardware\n- The agent runs with root privileges to access block device information and password sockets\n- The passphrase is sent over a Unix socket with restricted permissions\n- The systemd service unit includes security hardening options\n\n## Dependencies\n\nAll Rust dependencies are satisfied by Debian's `librust-*` packages as specified in `debian/control`. This ensures the build is completely isolated from external package registries and uses only packages that have been reviewed and packaged by Debian maintainers.\n\n### Rust Crates\n- `block-device-id` - Retrieve innate unique identifiers from block devices\n- `nix` - Safe Rust bindings to Unix APIs\n- `rust-ini` - INI file parser\n\n### System Libraries\n- `librpifwcrypto` - Raspberry Pi firmware cryptography service\n\n## Licence\n\nBSD-3-Clause - See LICENSE file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraspberrypi%2Fcryptsetup-passphrase-agent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fraspberrypi%2Fcryptsetup-passphrase-agent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fraspberrypi%2Fcryptsetup-passphrase-agent/lists"}