139 lines
6.0 KiB
Python
139 lines
6.0 KiB
Python
#!/usr/bin/env python3
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
"""Pure, inactive Phase-1.0DC BigApp comparison-gate contract."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from datetime import datetime, timezone
|
|
import re
|
|
|
|
|
|
PHASE = "PHASE_1_0DC_INACTIVE_BIGAPP_COMPARISON_GATE"
|
|
FIRMWARE = "9.60"
|
|
TITLE_ID = "PPSA01659"
|
|
PAYLOAD_NAME = "retroarch_ps5_launch_canary.elf"
|
|
PAYLOAD_SIZE = 1845240
|
|
PAYLOAD_SHA256 = "8dadce9d9faaef21ea129a3d216c768eea9a3ca9bf8ecb8d852e376b58a9bf95"
|
|
PROTOCOL_MAGIC = "CHD10AV1"
|
|
PROTOCOL_TERMINAL = "D14"
|
|
MAX_WINDOW_SECONDS = 300
|
|
SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
|
RUN_ID = re.compile(r"^[A-Z0-9][A-Z0-9_-]{7,63}$")
|
|
|
|
|
|
class BigAppGateError(ValueError):
|
|
"""Candidate data is incomplete, ambiguous, or unsafe."""
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class BigAppGateRecord:
|
|
phase: str
|
|
active: bool
|
|
firmware: str | None
|
|
title_id: str | None
|
|
run_id: str | None
|
|
not_before: str | None
|
|
expires_at: str | None
|
|
launcher_name: str | None
|
|
launcher_size: int | None
|
|
launcher_sha256: str | None
|
|
payload_name: str | None
|
|
payload_size: int | None
|
|
payload_sha256: str | None
|
|
approval_sha256: str | None
|
|
result_magic: str | None
|
|
result_terminal: str | None
|
|
no_running_bigapp_attested: bool
|
|
kernel_ptrace_effects_accepted: bool
|
|
app_termination_authorized: bool
|
|
persistent_write_authorized: bool
|
|
system_remount_authorized: bool
|
|
installation_authorized: bool
|
|
autoload_authorized: bool
|
|
automatic_retry: bool
|
|
reconnect: bool
|
|
fallback_title: bool
|
|
bounded_parent_detach_proven: bool
|
|
bounded_child_cleanup_proven: bool
|
|
bounded_result_channel_proven: bool
|
|
|
|
|
|
def _utc(value: str | None) -> datetime:
|
|
if not isinstance(value, str) or not value.endswith("Z"):
|
|
raise BigAppGateError("timestamp must be exact UTC")
|
|
try:
|
|
result = datetime.fromisoformat(value[:-1] + "+00:00")
|
|
except ValueError as error:
|
|
raise BigAppGateError("timestamp is invalid") from error
|
|
if result.tzinfo != timezone.utc:
|
|
raise BigAppGateError("timestamp is not UTC")
|
|
return result
|
|
|
|
|
|
def validate_inactive(record: BigAppGateRecord) -> None:
|
|
"""Require the tracked record to contain no live identity or authority."""
|
|
if type(record) is not BigAppGateRecord or record.phase != PHASE or record.active:
|
|
raise BigAppGateError("tracked gate is not inert")
|
|
identities = (
|
|
record.firmware, record.title_id, record.run_id, record.not_before,
|
|
record.expires_at, record.launcher_name, record.launcher_size,
|
|
record.launcher_sha256, record.payload_name, record.payload_size,
|
|
record.payload_sha256, record.approval_sha256, record.result_magic,
|
|
record.result_terminal,
|
|
)
|
|
if any(value is not None for value in identities):
|
|
raise BigAppGateError("inactive gate contains an identity")
|
|
if any((record.no_running_bigapp_attested,
|
|
record.kernel_ptrace_effects_accepted,
|
|
record.app_termination_authorized,
|
|
record.persistent_write_authorized,
|
|
record.system_remount_authorized,
|
|
record.installation_authorized, record.autoload_authorized,
|
|
record.automatic_retry, record.reconnect, record.fallback_title,
|
|
record.bounded_parent_detach_proven,
|
|
record.bounded_child_cleanup_proven,
|
|
record.bounded_result_channel_proven)):
|
|
raise BigAppGateError("inactive gate contains authority or proof")
|
|
|
|
|
|
def validate_candidate(record: BigAppGateRecord) -> None:
|
|
"""Validate hypothetical data; this function grants no authorization."""
|
|
if type(record) is not BigAppGateRecord or record.phase != PHASE or not record.active:
|
|
raise BigAppGateError("candidate is not explicitly active")
|
|
if record.firmware != FIRMWARE or record.title_id != TITLE_ID:
|
|
raise BigAppGateError("firmware or fixed title mismatch")
|
|
if not isinstance(record.run_id, str) or not RUN_ID.fullmatch(record.run_id):
|
|
raise BigAppGateError("run identity is invalid")
|
|
start, end = _utc(record.not_before), _utc(record.expires_at)
|
|
if not 0 < (end - start).total_seconds() <= MAX_WINDOW_SECONDS:
|
|
raise BigAppGateError("activation window is invalid")
|
|
if record.launcher_name != "chimera_bigapp_canary_launcher.elf" or \
|
|
not isinstance(record.launcher_size, int) or isinstance(record.launcher_size, bool) or \
|
|
not 1 <= record.launcher_size <= 1048576 or \
|
|
not isinstance(record.launcher_sha256, str) or not SHA256.fullmatch(record.launcher_sha256):
|
|
raise BigAppGateError("launcher identity is invalid")
|
|
if (record.payload_name, record.payload_size, record.payload_sha256) != \
|
|
(PAYLOAD_NAME, PAYLOAD_SIZE, PAYLOAD_SHA256):
|
|
raise BigAppGateError("payload identity is not the unchanged CZ artifact")
|
|
if not isinstance(record.approval_sha256, str) or not SHA256.fullmatch(record.approval_sha256):
|
|
raise BigAppGateError("separate approval identity is invalid")
|
|
if (record.result_magic, record.result_terminal) != \
|
|
(PROTOCOL_MAGIC, PROTOCOL_TERMINAL):
|
|
raise BigAppGateError("result protocol is invalid")
|
|
required = (record.no_running_bigapp_attested,
|
|
record.kernel_ptrace_effects_accepted,
|
|
record.bounded_parent_detach_proven,
|
|
record.bounded_child_cleanup_proven,
|
|
record.bounded_result_channel_proven)
|
|
if any(value is not True for value in required):
|
|
raise BigAppGateError("required attestation or bounded proof is absent")
|
|
forbidden = (record.app_termination_authorized,
|
|
record.persistent_write_authorized,
|
|
record.system_remount_authorized,
|
|
record.installation_authorized, record.autoload_authorized,
|
|
record.automatic_retry, record.reconnect,
|
|
record.fallback_title)
|
|
if any(value is not False for value in forbidden):
|
|
raise BigAppGateError("candidate permits a forbidden effect")
|