Skip to content

Commit d226f55

Browse files
committed
WIP: Add OCI image signing, sealing, and signature-verified mount
Implement end-to-end support for cryptographically signing composefs OCI images using PKCS#7/fsverity detached signatures, stored as OCI referrer artifacts following the 'composefs erofs-alongside' spec. Core signing infrastructure (composefs crate): - Add fsverity algorithm constants and ComposeFsAlgorithm type - Add formatted_digest module for kernel-compatible fsverity digest construction (the 12-byte header + raw hash used by the kernel's FS_IOC_ENABLE_VERITY ioctl) - Add kernel keyring support via composefs-ioctls keyring module (inject X.509 certs into .fs-verity keyring for kernel-level signature enforcement) OCI signing library (composefs-oci crate): - signing.rs: FsVeritySigningKey (sign) and FsVeritySignatureVerifier (verify) using openssl PKCS#7 with DETACHED|BINARY|NOATTR flags, compatible with Linux kernel fsverity builtin signature verification - signature.rs: OCI artifact manifest builder/parser for the 'application/vnd.composefs.erofs-alongside.v1' artifact type, storing per-layer and merged EROFS images alongside their PKCS#7 signatures as typed layers with composefs.* annotations - image.rs: compute_per_layer_digests() and compute_merged_digest() for deterministic EROFS image generation from OCI layer stacks - oci_image.rs: seal_image() to compute and embed the composefs fsverity digest into the OCI config, export/import to OCI layout directories (migrated to ocidir crate for atomic I/O), referrer index management CLI commands (cfsctl): - 'oci seal <image>' — compute composefs EROFS, embed fsverity digest - 'oci sign <image> --cert --key' — create signature artifact - 'oci verify <image> [--cert]' — verify signatures (digest-only without --cert, full PKCS#7 with --cert) - 'oci mount <name> <mountpoint> [--require-signature --trust-cert]' — verify signatures before kernel mount - 'oci pull ... --require-signature --trust-cert' — verify after pull - 'oci push <image> <dest> [--signatures]' — export to OCI layout - 'oci export-signatures <image> <dest>' — export just artifacts - 'oci inspect' — show referrer info in JSON output - 'keyring add-cert <pem>' — inject cert into kernel keyring The mount and pull --require-signature paths share a common verify_image_signatures() helper that recomputes expected EROFS digests and verifies each PKCS#7 signature blob against the trusted certificate. The mount command now also resolves tag names (via OciImage::open_ref) instead of requiring raw config digests, consistent with seal/sign/ verify. Integration tests: - signing.rs: 17 unprivileged tests covering sign, verify, wrong cert, export, seal+sign roundtrip, artifact structure, --require-signature on pull and mount - privileged.rs: 7 tests for real fsverity enforcement, kernel keyring injection, kernel signature acceptance/rejection - podman.rs: 3 tests building real container images via podman - cli.rs: updated for richer OCI test layout (4 entries) and new oci push/roundtrip tests - test-oci-sign-verify.sh: standalone shell-based integration tests Assisted-by: OpenCode (Claude claude-opus-4-6) Signed-off-by: Colin Walters <walters@verbum.org>
1 parent cf5cb6a commit d226f55

File tree

26 files changed

+7004
-188
lines changed

26 files changed

+7004
-188
lines changed

contrib/packaging/install-test-deps.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ case "${ID}" in
1515
;;
1616
debian|ubuntu)
1717
pkg_install \
18-
openssl e2fsprogs bubblewrap openssh-server
18+
openssl e2fsprogs bubblewrap openssh-server fsverity-utils
1919

2020
# OSTree symlink targets — /root, /home, /srv, etc. are symlinks
2121
# into /var on OSTree systems, so the target directories must exist.

crates/cfsctl/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ path = "src/lib.rs"
1616
[features]
1717
default = ['pre-6.15', 'oci']
1818
http = ['composefs-http']
19-
oci = ['composefs-oci']
19+
oci = ['composefs-oci', 'oci-spec']
2020
rhel9 = ['composefs/rhel9']
2121
'pre-6.15' = ['composefs/pre-6.15']
2222

@@ -31,6 +31,7 @@ composefs-oci = { workspace = true, optional = true, features = ["boot"] }
3131
composefs-http = { workspace = true, optional = true }
3232
env_logger = { version = "0.11.0", default-features = false }
3333
hex = { version = "0.4.0", default-features = false }
34+
oci-spec = { version = "0.8.0", default-features = false, optional = true }
3435
rustix = { version = "1.0.0", default-features = false, features = ["fs", "process"] }
3536
serde = { version = "1.0", default-features = false, features = ["derive"] }
3637
serde_json = { version = "1.0", default-features = false, features = ["std"] }

0 commit comments

Comments
 (0)