Gunnar

nordisk/heimdall

guests/verify-bundle/src/limits.rs

// SPDX-License-Identifier: AGPL-3.0-only
//! Schema identifiers, member paths and hostile-input limits — the values of
//! Holger's `update-bundle/src/schema.rs`, copied verbatim so the guest refuses
//! exactly what Holger refuses (the differential tests hold the two together).

pub const BUNDLE_SCHEMA: &str = "holger.update-bundle/v1";
pub const POLICY_SCHEMA: &str = "holger.bundle-trust-policy/v1";

pub const MANIFEST_JSON: &str = "manifest.json";
pub const CORE_JSON: &str = "core.json";
pub const RELEASE_MANIFEST_JSON: &str = "signatures/release-manifest.json";
pub const RELEASE_SIG: &str = "signatures/release.sig";
pub const RELEASE_CRT: &str = "signatures/release.crt";
pub const APPROVALS_PREFIX: &str = "approvals/";
pub const SIGNATURES_PREFIX: &str = "signatures/";
pub const PAYLOAD_PREFIX: &str = "payload/";
pub const EVIDENCE_PREFIX: &str = "evidence/";

/// Maximum number of members in a bundle archive.
pub const MAX_MEMBERS: usize = 100_000;
/// Maximum uncompressed size of a single member.
pub const MAX_MEMBER_BYTES: u64 = 8 * 1024 * 1024 * 1024;
/// Maximum aggregate uncompressed size across all members.
pub const MAX_TOTAL_BYTES: u64 = 32 * 1024 * 1024 * 1024;
/// Maximum size of one JSON control document.
pub const MAX_CONTROL_BYTES: u64 = 16 * 1024 * 1024;
/// Maximum number of approval statements considered.
pub const MAX_APPROVALS: usize = 64;
/// Maximum size of the bundle file (the guest's whole input).
pub const MAX_BUNDLE_FILE_BYTES: u64 = 4 * 1024 * 1024 * 1024;
/// Maximum combined size of the control members, read before anything is
/// authenticated.
pub const MAX_CONTROL_TOTAL_BYTES: u64 = 64 * 1024 * 1024;
/// Maximum ratio of declared extracted bytes to the archive size.
pub const MAX_EXPANSION_RATIO: u64 = 100;
/// The floor below which the ratio is not enforced.
pub const EXPANSION_RATIO_FLOOR_BYTES: u64 = 64 * 1024 * 1024;

// ---- the guest's own bounds on the znippy index (Holger has none: it trusts
// znippy's reader; the guest IS the reader) ----

/// Maximum number of sub-index entries in the archive manifest.
pub const MAX_INDEX_SECTIONS: usize = 1024;
/// Maximum number of chunk rows across the whole index.
pub const MAX_INDEX_ROWS: usize = 4 * MAX_MEMBERS;
/// Maximum length of one member path, in bytes.
pub const MAX_PATH_BYTES: usize = 4096;
/// Highest znippy on-disk format version this reader understands.
pub const ZNIPPY_FORMAT_VERSION: u32 = 3;

/// True if `path` is a control member (read before the release signature).
pub fn is_control_member(path: &str) -> bool {
    path == CORE_JSON
        || path == MANIFEST_JSON
        || path.starts_with(SIGNATURES_PREFIX)
        || path.starts_with(APPROVALS_PREFIX)
}

/// The members the release manifest cannot cover: itself, its signature and
/// its certificate.
pub fn is_self_referential(path: &str) -> bool {
    path == RELEASE_MANIFEST_JSON || path == RELEASE_SIG || path == RELEASE_CRT
}