Skip to content

WIP: Rough draft for updated generic OCI sealing#226

Draft
cgwalters wants to merge 4 commits into
composefs:mainfrom
cgwalters:sealing-impl
Draft

WIP: Rough draft for updated generic OCI sealing#226
cgwalters wants to merge 4 commits into
composefs:mainfrom
cgwalters:sealing-impl

Conversation

@cgwalters
Copy link
Copy Markdown
Collaborator

This is just some rough draft raw material that builds on:

@cgwalters cgwalters force-pushed the sealing-impl branch 2 times, most recently from 1ce192a to 063ff54 Compare February 12, 2026 16:49
Comment thread crates/cfsctl/src/main.rs Outdated
composefs_oci::signing::FsVeritySigningKey::from_pem(&cert_pem, &key_pem)?;

// Build subject descriptor from the source image's manifest
let manifest_json = img.manifest().to_string()?;
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm we actually need to operate on the raw original representation, can't rely on to_string() always giving us the same thing.

Comment thread crates/cfsctl/src/main.rs Outdated
/// Image reference (tag name)
image: String,
/// Path to the OCI layout directory (must already exist)
oci_layout_path: PathBuf,
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use clap(value_parser) into an ocidir directly or so

Comment thread crates/composefs-oci/src/lib.rs Outdated
/// the container to be mounted with integrity protection.
///
/// Returns a tuple of (sha256 content hash, fs-verity hash value) for the updated configuration.
pub fn seal<ObjectID: FsVerityHashValue>(
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be cleaner if we do a prep commit that removes the old sealing as we know we're not going to do it anymore.

/// # Returns
///
/// The number of referrer artifacts exported.
pub fn export_referrers_to_oci_layout<ObjectID: FsVerityHashValue>(
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something like this could land as a prep commit

Comment thread crates/composefs-oci/src/oci_image.rs Outdated
use std::fs;
use std::io::Write;

let blobs_dir = oci_layout_path.join("blobs").join("sha256");
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ocidir

format!("{seed:02x}").repeat(32)
}

fn sample_subject() -> Descriptor {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's unify this stuff with shared infra to generate an ocidir with known content

Comment thread crates/composefs/src/fsverity/ioctl.rs Outdated
Comment thread crates/composefs/src/fsverity/ioctl.rs Outdated
Comment thread crates/composefs/src/fsverity/keyring.rs Outdated
Comment thread crates/composefs/src/fsverity/keyring.rs Outdated
@cgwalters cgwalters force-pushed the sealing-impl branch 3 times, most recently from 361eeb7 to 2f93e4a Compare March 6, 2026 12:24
@cgwalters
Copy link
Copy Markdown
Collaborator Author

This one will need to logically depend on #225 because that one has a lot of hardening for the EROFS parser

@cgwalters cgwalters force-pushed the sealing-impl branch 2 times, most recently from 6b676dd to d226f55 Compare March 14, 2026 21:30
@cgwalters cgwalters force-pushed the sealing-impl branch 2 times, most recently from 83ea13e to 13f1957 Compare April 4, 2026 12:53
@cgwalters cgwalters force-pushed the sealing-impl branch 3 times, most recently from 0f06a47 to e0c049a Compare May 23, 2026 12:41
cgwalters added 4 commits June 4, 2026 07:47
Add a `keyring` feature that exposes `inject_fsverity_cert` and
`KeyringError`, backed by `keyutils 0.4` (which provides
`Keyring::new` and `keytypes::Asymmetric` needed to add X.509
certificates to the kernel's .fs-verity keyring).

The implementation uses `keyutils::Keyring::new` to locate the
`.fs-verity` special keyring and `add_key` to inject PEM-decoded
DER certificates.

Assisted-by: OpenCode (claude-sonnet-4-6)
…est, ioctl)

Add `algorithm.rs` (ComposeFsAlgorithm enum for EROFS/signature types),
`formatted_digest.rs` (hex-encoded digest with known format), and extend
`ioctl.rs` with `fs_ioc_enable_verity_with_sig` to pass a PKCS#7
signature blob when enabling verity.

The `fsverity::mod` re-exports `inject_fsverity_cert` from
composefs-ioctls under the `keyring` feature, and exposes
`enable_verity_raw_with_sig` for callers that have pre-computed the
fs-verity descriptor and signature.

Assisted-by: OpenCode (claude-sonnet-4-6)
Add three new modules:
- `signing.rs`: PKCS#7/openssl-backed `FsVeritySigningKey` for
  signing fs-verity digests, with PEM cert/key parsing.
- `signature.rs`: `SignatureArtifactBuilder` that constructs an OCI
  artifact manifest containing EROFS layers, PKCS#7 signature blobs,
  and a config descriptor — implementing the composefs signing spec.
  Also exposes `parse_signature_artifact` for the verify path.
- `referrers.rs`: `get_referrers` to fetch OCI referrer manifests
  either locally (from repo) or via `oci-client` (remote registry),
  used by the verify and seal commands.

Update `image.rs` / `oci_image.rs` / `boot.rs` / `lib.rs` to adapt
to upstream API changes (2-arg `commit_images`, `FormatConfig`,
`generate_boot_image` tag param, `OciRefNotFound` on ENOENT,
`containers_image_proxy::oci_spec` import paths, tracing vs log).

Add `openssl` as a non-optional dep (signing.rs uses it at top level)
and optional `oci-client` feature for remote referrer fetching.

Assisted-by: OpenCode (claude-sonnet-4-6)
Add OCI sealing and signing workflows to cfsctl:
- `oci seal`: Commits EROFS images for all layers and the merged
  rootfs into the repository.
- `oci sign`: Creates a composefs PKCS#7 signature OCI artifact and
  pushes it as a referrer.
- `oci verify`: Fetches referrer artifacts and validates EROFS layer
  digests against embedded signatures.
- `oci run` / `oci stop`: Runs a container from a pulled OCI image
  by generating an OCI runtime spec, mounting a composefs overlay,
  and invoking crun/runc. `stop` unmounts and cleans up.
- `keyring add-cert`: Injects an X.509 PEM certificate into the
  kernel's .fs-verity keyring (requires CAP_SYS_ADMIN).
- `oci export`: Exports an image to an OCI layout directory.

Adapt to upstream API changes:
- `FormatSet` → `FormatConfig` throughout.
- `ComposefsCmdline` → `make_cmdline_composefs` (composefs-boot).
- `write_boot_simple` gains `insecure: bool` parameter.
- `commit_images` drops the `formats` argument (repo provides it).
- `ValidatedFileSystem::new` takes `&mut self`.
- OCI spec types via `composefs_oci` re-exports (matching
  containers_image_proxy oci-spec 0.9).
- Add missing `pub mod` declarations, `run_if_socket_activated`,
  `open_repo_at`, `Varlink`/`Mkcomposefs`/`ComposefsInfo` Command
  variants carried from upstream.
- Fsck JSON now uses `varlink::{Fsck,OciFsck}Reply` (snake_case
  fields) so integration tests pass.

Assisted-by: OpenCode (claude-sonnet-4-6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant