#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-or-later """Verify an artifact manifest and, when supplied, its local artifact.""" from __future__ import annotations import argparse import hashlib import json import re from pathlib import Path def hash_file(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as stream: for chunk in iter(lambda: stream.read(1024 * 1024), b""): digest.update(chunk) return digest.hexdigest() def fail(message: str) -> None: raise ValueError(message) def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--manifest", type=Path, required=True) parser.add_argument("--artifact", type=Path) args = parser.parse_args() document = json.loads(args.manifest.read_text(encoding="utf-8")) if document.get("schema_version") != 1: fail("unsupported artifact-manifest schema") artifact_record = document["artifact"] if not re.fullmatch(r"[0-9a-f]{64}", artifact_record["sha256"]): fail("invalid artifact SHA-256") if not re.fullmatch(r"[0-9a-f]{40}", document["source"]["commit"]): fail("invalid source commit") if document["source"].get("dirty") is not False: fail("artifact source must be clean") if not isinstance(document["execution"].get("execution_eligible"), bool): fail("artifact execution eligibility must be an explicit boolean") if any(document["execution"].get(key) is not False for key in ("authorized", "transferred", "executed")): fail("artifact manifest claims execution authority or activity") if document["safety"].get("direct_gnm_imports") != 0: fail("artifact manifest claims direct GNM imports") gate = document["firmware_gate"] if gate["embedded_identifier"] == "NONE" and gate["allowlisted"] is not False: fail("NONE firmware gate cannot be allowlisted") if args.artifact is not None: artifact = args.artifact.resolve(strict=True) if artifact.name != artifact_record["filename"]: fail("artifact filename mismatch") if artifact.stat().st_size != artifact_record["size"]: fail("artifact size mismatch") if hash_file(artifact) != artifact_record["sha256"]: fail("artifact digest mismatch") print(f"verified artifact manifest: {artifact_record['id']}") return 0 if __name__ == "__main__": try: raise SystemExit(main()) except (KeyError, TypeError, ValueError, json.JSONDecodeError) as error: print(f"artifact verification failed: {error}") raise SystemExit(1) from error