A small, validation-first boot.img parser and verifier for the EriX project, written in Rust.
Find a file
Erik Inkinen 33b18d6d75
All checks were successful
CI / test (push) Successful in 5s
CI / security (push) Successful in 1m27s
CI / minimal-versions (push) Successful in 11s
lib-bootimg: drop unstable rustfmt options for stable toolchains
2026-03-23 10:19:53 +02:00
.github Refactor milestone terminology to "Component Milestone Tracking" across templates and documentation for consistency 2026-03-05 11:54:01 +02:00
src lib-bootimg: split boot image types by section family 2026-03-23 09:37:41 +02:00
tests Enforce default key policy in BootImage verification and update tests for key ID checks 2026-02-26 17:50:17 +02:00
.editorconfig Initial commit 2026-02-26 10:11:07 +01:00
.gitignore Initial commit 2026-02-26 10:11:07 +01:00
ARCHITECTURE.md Refine documentation to clarify the dual-path architecture and purpose of the lib-bootimg crate 2026-02-26 14:12:05 +02:00
Cargo.toml Add constant-time library dependency and implement image hash verification in BootImage 2026-02-26 17:41:08 +02:00
CODE_OF_CONDUCT.md Initial commit 2026-02-26 10:11:07 +01:00
CONTRIBUTING.md Refactor milestone terminology to "Component Milestone Tracking" across templates and documentation for consistency 2026-03-05 11:54:01 +02:00
LICENSE Initial commit 2026-02-26 10:11:07 +01:00
README.md Refactor milestone terminology to "Component Milestone Tracking" across templates and documentation for consistency 2026-03-05 11:54:01 +02:00
ROADMAP.md Update README and ROADMAP to reflect current implementation status and structure 2026-02-28 04:54:02 +02:00
rustfmt.toml lib-bootimg: drop unstable rustfmt options for stable toolchains 2026-03-23 10:19:53 +02:00
SECURITY.md docs: align security policy phase numbering 2026-03-11 05:28:12 +02:00

lib-bootimg

A small, validation-first boot.img format crate for the EriX project, written in Rust.

This crate is intentionally not a general-purpose boot image toolkit. It exists to support secure boot verification and early-boot parsing with a tight, auditable surface area and strong invariants.


Architecture model

lib-bootimg uses a dual architecture with strict boundaries:

  • Read path (runtime/TCB):
    • Parse and validate boot.img structure
    • Verify hashes/signatures
    • Provide safe borrowed section access
  • Build path (tooling/build-time):
    • Deterministic layout generation
    • Header/section table/manifest assembly
    • Hash/signature coverage generation helpers

Policy remains outside this crate:

  • what sections are required for a given boot profile
  • key provisioning and trust policy
  • dev vs release acceptance policy

Goals

  • Parse boot.img v1 as defined in the normative specification.
  • Provide a borrowed view over the input (&[u8]) with zero-copy access to sections.
  • Focus on what a bootloader needs:
    • Header parsing
    • Section table access
    • Manifest extraction
    • Signature verification
    • Section data retrieval
  • Be validation-first: parse() succeeds only if the image is structurally sound and secure.
  • Support cryptographic verification (SHA-256 hashing, Ed25519 signature validation).
  • Provide deterministic boot.img construction primitives for internal tools (boot-tool).

Non-goals (for now)

  • Support for boot.img versions other than v1
  • Compression handling
  • Incremental updates
  • "Best-effort" parsing of malformed or untrusted inputs
  • Runtime boot policy decisions (owned by bootloader/kernel/tooling policy layers)

If we need any of these later, they should be added deliberately and with clear invariants.


Supported format

  • Version: boot.img v1
  • Endianness: little-endian (fixed)
  • Alignment: 4 KiB for section data, 16-byte for metadata
  • Magic: ERIXBOOT
  • Signature: Ed25519
  • Hash: SHA-256

See: ../../docs/bootimg/format-v1.md for the normative specification.


API design principles

  • Parse returns a validated representation.
    • If BootImage::parse() returns Ok, then all documented invariants hold.
  • Verification is mandatory for boot.
    • The parser validates structure; the verifier checks cryptographic integrity.
  • Builder logic is deterministic and format-only.
    • The build path defines how bytes are laid out, not what higher-level policy requires.
  • No hidden allocations required.
    • Parsed structures borrow from the input slice where possible.
  • Errors are explicit and stable.
    • Failures return structured error variants (not strings).

Core invariants (success means…)

When BootImage::parse(bytes) returns Ok(img):

  • The input begins with valid magic ERIXBOOT.
  • Header fields are structurally valid (version=1, correct sizes).
  • All offsets (section table, manifest, signature) are in-bounds.
  • Section table is well-formed:
    • All section entries are fully in-bounds.
    • Section data ranges are in-bounds and 4 KiB aligned.
    • No overlapping sections.
  • Manifest is structurally valid and can be parsed.
  • Signature block is present and in-bounds.
  • Arithmetic checks do not overflow.
  • File size matches declared total_size.
  • File size is a multiple of 4 KiB.

When verify() (or verify_with_key_id()) succeeds:

  • Image hash over the canonicalized covered region matches manifest. Canonicalization: bytes [manifest_offset+56 .. manifest_offset+88) are treated as zero.
  • Ed25519 signature is valid for the provided public key.
  • All section hashes match their respective blobs.
  • Key policy is satisfied (verify() enforces default key_id == 0; verify_with_key_id() enforces caller-provided key ID).

Example (intended usage)

Note: exact names may evolve while the API is being finalized.

use bootimg::{BootImage, PublicKey};

fn verify_and_load(bytes: &[u8], pubkey: &PublicKey) -> Result<(), bootimg::Error> {
    // Parse and validate structure
    let img = BootImage::parse(bytes)?;
    
    println!("boot.img version: {}", img.version());
    println!("sections: {}", img.section_count());

    // Verify cryptographic integrity
    img.verify(pubkey)?;
    // Optional key policy:
    // img.verify_with_key_id(pubkey, expected_key_id)?;

    // Access sections
    for section in img.sections() {
        println!(
            "section '{}': offset=0x{:x} size=0x{:x}",
            section.name(),
            section.offset(),
            section.size(),
        );
        
        // Borrowed bytes for this section
        let data = section.data(bytes)?;
        println!("  data: {} bytes", data.len());
    }

    // Extract kernel section
    if let Some(kernel) = img.section_by_name("kernel")? {
        let kernel_bytes = kernel.data(bytes)?;
        println!("kernel ready: {} bytes", kernel_bytes.len());
    }

    Ok(())
}

Security model

The read path of this crate is part of the Trusted Computing Base (TCB) for EriX. The build path is a tooling surface and not itself a runtime execution boundary.

Threat model:

  • Attacker-controlled input: any boot.img file from storage.
  • Trusted input: embedded public key in bootloader.
  • Goal: prevent execution of unauthorized or modified images.

Verification flow (mandatory):

  1. Parse structure (this crate).
  2. Validate all invariants.
  3. Compute image hash.
  4. Verify signature with trusted public key.
  5. Validate all section hashes.
  6. Only then allow loading.

See: ../../docs/bootimg/verification.md for the normative verification model.

Testing strategy

This repo prefers deterministic, authored tests:

  • Hand-authored fixtures (valid boot.img samples, built as part of testing).
  • Negative tests for each validation rule:
    • Bad magic
    • Invalid version
    • Misaligned sections
    • Out-of-bounds offsets
    • Overflow cases
    • Signature mismatches
    • Hash mismatches
  • Optional internal mutation harnesses (randomized corruption) as smoke tests.

Repository layout

lib-bootimg/
├── src/
│   ├── lib.rs          # Public API
│   ├── parse.rs        # Read path: structure parsing
│   ├── verify.rs       # Read path: cryptographic verification
│   ├── build.rs        # Build path: deterministic image construction
│   ├── error.rs        # Error types
│   └── ...
├── tests/
│   ├── valid_images/   # Known-good test fixtures
│   └── invalid_images/ # Negative test cases
├── ARCHITECTURE.md     # Component architecture
├── README.md           # This file
└── ...

Dependencies

This crate uses sibling EriX crypto crates:

  • lib-sha2 (SHA-256)
  • lib-ed25519 (Ed25519 verification)
  • lib-constant-time (timing-safe comparisons)

See: ../../docs/policies/no-external-code.md

Current status

Implemented baseline.

Read/verify/build paths are implemented and exercised by tests. Current work is focused on hardening coverage and broader cross-repo integration fixtures.

See: ROADMAP.md for planned milestones.

  • ../../docs/bootimg/format-v1.md — normative format specification
  • ../../docs/bootimg/verification.md — verification requirements
  • ARCHITECTURE.md — component architecture and invariants
  • CONTRIBUTING.md — contribution guidelines
  • SECURITY.md — security policy

License

See LICENSE file.


For questions or contributions, see CONTRIBUTING.md.