- Rust 100%
| .github | ||
| src | ||
| tests | ||
| .editorconfig | ||
| .gitignore | ||
| ARCHITECTURE.md | ||
| Cargo.toml | ||
| CODE_OF_CONDUCT.md | ||
| CONTRIBUTING.md | ||
| LICENSE | ||
| README.md | ||
| ROADMAP.md | ||
| rustfmt.toml | ||
| SECURITY.md | ||
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()returnsOk, then all documented invariants hold.
- If
- 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 defaultkey_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.imgfile from storage. - Trusted input: embedded public key in bootloader.
- Goal: prevent execution of unauthorized or modified images.
Verification flow (mandatory):
- Parse structure (this crate).
- Validate all invariants.
- Compute image hash.
- Verify signature with trusted public key.
- Validate all section hashes.
- 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.
Related documentation
../../docs/bootimg/format-v1.md— normative format specification../../docs/bootimg/verification.md— verification requirementsARCHITECTURE.md— component architecture and invariantsCONTRIBUTING.md— contribution guidelinesSECURITY.md— security policy
License
See LICENSE file.
For questions or contributions, see CONTRIBUTING.md.