XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
"""Bind two fully tested editions to one immutable, selectable USB image."""
import argparse
import importlib.util
import json
from pathlib import Path
import sys

ROOT = Path(__file__).resolve().parents[2]


def load_media():
    spec = importlib.util.spec_from_file_location('xfe_media', ROOT / 'scripts/physical-media-verify.py')
    module = importlib.util.module_from_spec(spec)
    sys.modules[spec.name] = module
    spec.loader.exec_module(module)
    return module


def resolve_bound(folder, entry, media):
    path = Path(entry['Path'])
    if not path.is_absolute():
        path = folder / path
    path = path.resolve()
    media.require(media.digest(path) == entry['Sha256'], 'Dual delivery artifact changed: ' + str(path))
    return path


def evidence_files(proof_paths, media):
    artifacts = {}
    for proof_path in proof_paths:
        for artifact in proof_path.parent.iterdir():
            if artifact.is_file() and artifact.suffix.lower() in ('.json', '.png', '.log', '.txt'):
                artifacts[str(artifact.resolve())] = {'Path': str(artifact.resolve()), 'Sha256': media.digest(artifact)}
    return [artifacts[name] for name in sorted(artifacts)]


def verify_dual(image, composite_path, media=None):
    media = media or load_media()
    require = media.require
    image, composite_path = Path(image).resolve(), Path(composite_path).resolve()
    composite, composite_hash = media.read_bound_json(composite_path)
    require(composite.get('Kind') == 'XfeIndependentDualBootProof' and composite.get('Passed') is True,
            'A dual edition acceptance receipt is required')
    require(composite.get('ImageSha256') == media.digest(image), 'The dual image differs from its acceptance')
    manifest, manifest_hash = media.read_bound_json(str(image) + '.json')
    require(manifest.get('Edition') == 'Dual' and manifest.get('BootEntries') == ['Desktop', 'Console'] and
            manifest.get('DefaultBootEntry') == 'Desktop' and manifest.get('BootMenuTimeoutSeconds') == 10,
            'Expected the explicit Desktop/Console boot menu')
    desktop_path = resolve_bound(composite_path.parent, composite['DesktopBoot'], media)
    console_path = resolve_bound(composite_path.parent, composite['ConsoleBoot'], media)
    desktop = media.read_json(desktop_path)
    console = media.read_json(console_path)
    for proof, index, label in ((desktop, 0, 'XFESystem Desktop'), (console, 1, 'XFESystem Console')):
        menu = proof.get('BootMenuSelection', {})
        require(type(proof.get('BootEntry')) is int and proof['BootEntry'] == index and
                proof.get('SourcesUnchanged') is True and
                menu.get('Input') == 'Actual QMP PS2 keyboard packets only' and
                type(menu.get('Index')) is int and menu['Index'] == index and menu.get('Entry') == label and
                type(menu.get('MenuSerialOffset')) is int and menu['MenuSerialOffset'] > 0,
                'Actual source-bound QMP menu selection is required for ' + label)
    require(desktop.get('Edition') == 'Desktop' and desktop.get('KernelImagePath') == 'System/Kernel.elf' and
            desktop.get('BootEntry') == 0, 'Actual default desktop menu boot is required')
    # Reuse every existing geometry, source, application, HTTPS, documents and
    # real terminal guard for the desktop half. No Boolean-only shortcut.
    verified = media.verify(image, desktop_path, 'IndependentCSharp128', _dual_image=True)
    require(console.get('Kind') == 'XfeIndependentKernelBootProof' and console.get('Passed') is True and
            console.get('Edition') == 'Console' and console.get('KernelImagePath') == 'System/Console.elf' and
            console.get('BootEntry') == 1 and console.get('ConsoleAcceptanceRequired') is True and
            console.get('ConsoleAcceptancePassed') is True and console.get('ManagedRuntimeAcceptancePassed') is True and
            console.get('ContainsCosmos') is False and console.get('ImageUnchanged') is True and
            type(console.get('QemuExitCode')) is int and console['QemuExitCode'] == 0 and not console.get('ForcedCleanup'),
            'Actual cleaned-up standalone console menu boot is required')
    require(console.get('ImageSha256') == verified['ImageSha256'] and
            console.get('KernelSha256') == manifest.get('ConsoleKernelSha256') and
            console.get('KernelSha256') == verified['IndependentImageInspection']['Files'].get('System/Console.elf') and
            console.get('ImageVerification', {}).get('Files') == verified['IndependentImageInspection']['Files'],
            'Console proof does not bind the exact dual image inventory')
    console_snapshot_path = Path(console['SourceSnapshotPath'])
    if not console_snapshot_path.is_absolute():
        console_snapshot_path = console_path.parent / console_snapshot_path
    console_snapshot, console_snapshot_hash = media.read_bound_json(console_snapshot_path)
    require(console_snapshot_hash == console['SourceSnapshotSha256'], 'Console source snapshot changed')
    for relative, expected in console_snapshot.items():
        source = (ROOT / relative).resolve()
        require(source.is_relative_to(ROOT) and source.is_file() and media.digest(source) == expected,
                'Console source changed: ' + relative)
    console_build = manifest.get('IndependentConsoleKernelBuild', {})
    require(console_build.get('Kind') == 'XfeIndependentKernelBuild' and console_build.get('Passed') is True and
            console_build.get('Edition') == 'Console' and console_build.get('ContainsCosmos') is False and
            console_build.get('BootstrapOnly') is False and
            console_build.get('Configuration') == manifest['IndependentKernelBuild']['Configuration'],
            'Both editions must use the same RAM-only self-developed kernel configuration')
    gate = media.verify_independent_delivery(image, console_path, console_snapshot, verified['ImageSha256'],
                                             media.digest(console_path), 'Console')
    merged_path = resolve_bound(composite_path.parent, composite['MergedSourceSnapshot'], media)
    merged = media.read_json(merged_path)
    expected_merged = media.read_json(verified['SourceSnapshotPath'])
    for name, expected in console_snapshot.items():
        require(name not in expected_merged or expected_merged[name] == expected, 'Edition source snapshots conflict: ' + name)
        expected_merged[name] = expected
    require(merged == expected_merged, 'Dual source snapshot is not the exact union of both tested editions')
    for relative in ('Tools/IndependentKernel/TestBoot.py', 'Tools/IndependentKernel/VerifyDualDelivery.py',
                     'scripts/physical-media-verify.py', 'Tools/CSharpBoot/Program.cs', 'Tools/CSharpBoot/ReadImage.py'):
        require(merged.get(relative) == media.digest(ROOT / relative), 'Missing or stale dual delivery harness: ' + relative)
    usb_paths=[]
    if manifest['IndependentKernelBuild']['Configuration'].get('UsbHidEnabled') is True:
        from IndependentConsoleEvidence import terminal_command_output
        entries=composite.get('UsbInputEvidence', [])
        require(len(entries)==2, 'Both editions require actual USB-only acceptance')
        for entry,edition,kernel_sha in zip(entries,('Desktop','Console'),(manifest['KernelSha256'],manifest['ConsoleKernelSha256'])):
            path=resolve_bound(composite_path.parent,entry,media);usb_paths.append(path)
            usb=media.read_json(path)
            require(usb.get('Kind')=='XfeIndependentUsbInputProof' and usb.get('Passed') is True and
                usb.get('Edition')==edition and usb.get('KernelSha256')==kernel_sha and usb.get('Hub') is True and
                usb.get('Ps2ControllerPresent') is False and usb.get('HardwareReportsQueued') is True and
                usb.get('ActualKeyboardUnplugReplugPassed') is True and usb.get('SourcesUnchanged') is True and
                usb.get('PhysicalCorsairVerified') is False and usb.get('GuestCudaVerified') is False and
                usb.get('QemuExitCode')==0 and not usb.get('ForcedCleanup') and usb.get('ImageUnchanged') is True,
                'Incomplete USB-only kernel, HID, cleanup or hotplug evidence: '+edition)
            for name,sha in usb['SourceHashes'].items():
                require(merged.get(name)==sha==media.digest(ROOT/name), 'USB proof source differs from dual delivery: '+name)
            require(media.digest(usb['ImagePath'])==usb['ImageSha256'], 'The separate USB test image changed')
            qtree=path.parent/'Qtree.txt';serial=path.parent/'Serial.log'
            require(media.digest(qtree)==usb['QtreeSha256'] and media.digest(serial)==usb['SerialSha256'], 'USB hardware evidence changed')
            tree=qtree.read_text(encoding='utf-8');log=serial.read_text(encoding='utf-8')
            require('dev: i8042' not in tree and 'dev: ps2-kbd' not in tree and 'dev: ps2-mouse' not in tree and
                'dev: usb-kbd' in tree and 'dev: usb-mouse' in tree and 'dev: usb-hub' in tree,
                'USB input must not fall back to a PS/2 device')
            require(all(x in log for x in ('XFE_USB_HID_READY','|Kind|1|','|Kind|2|',
                'FIRST_HARDWARE_KEY_QUEUED','FIRST_HARDWARE_POINTER_QUEUED','|HUB_CONTEXT_CONFIGURED','|DISCONNECTED')), 'Missing actual hardware USB reports')
            require(usb.get('HubContextReadbackVerified') is False and usb.get('QemuHubContextNotModeled') is True and
                '|HUB_CONTEXT_QEMU_NOT_MODELED' in log, 'QEMU does not model physical hub/TT context readback; do not claim hardware proof')
            require('usb-replug' in terminal_command_output(usb['RepluggedCommandReadback']['Value'],'echo usb-replug'),
                'The replugged keyboard must submit and render the exact echo command')
            require(usb.get('ActualUsbDesktopEditingPassed' if edition=='Desktop' else 'ActualUsbConsoleEditingPassed') is True,
                'Actual USB application editing missing')
    require(composite.get('EvidenceFiles') == evidence_files((desktop_path, console_path,*usb_paths), media),
            'Dual evidence locks must contain the exact complete evidence set for both guests')
    for artifact in composite['EvidenceFiles']:
        resolve_bound(composite_path.parent, artifact, media)
    require(composite.get('FullReleaseQualified') is False, 'Dual delivery remains experimental')
    require(media.digest(str(image) + '.json') == manifest_hash == verified['ImageManifestSha256'] and
            media.digest(composite_path) == composite_hash,
            'The dual manifest or composite receipt changed during verification')
    return {**verified, 'Profile': 'IndependentDualCSharp256', 'BootResultPath': str(composite_path),
            'BootResultSha256': composite_hash, 'SourceSnapshotPath': str(merged_path),
            'SourceSnapshotSha256': media.digest(merged_path), 'ConsoleFinalDeliveryGate': gate,
            'DualEditionAcceptancePassed': True, 'AdditionalEvidenceLocks': composite['EvidenceFiles'],
            'DualVerifierSha256': media.digest(__file__), 'BootMenuEntries': ['Desktop', 'Console']}


def prepare(image, desktop_path, console_path, output, usb_desktop=None, usb_console=None):
    media = load_media()
    image, desktop_path, console_path, output = map(lambda p: Path(p).resolve(), (image, desktop_path, console_path, output))
    media.require(not output.exists(), 'Refusing to replace an existing dual delivery receipt')
    output.parent.mkdir(parents=True, exist_ok=True)
    merged = {}
    for proof_path in (desktop_path, console_path):
        proof = media.read_json(proof_path)
        snapshot_path = Path(proof['SourceSnapshotPath'])
        if not snapshot_path.is_absolute():
            snapshot_path = proof_path.parent / snapshot_path
        for name, expected in media.read_json(snapshot_path).items():
            media.require(name not in merged or merged[name] == expected, 'Source maps conflict: ' + name)
            merged[name] = expected
    merged_path = output.parent / 'MergedSourceSnapshot.json'
    with merged_path.open('x', encoding='utf-8') as stream:
        json.dump(dict(sorted(merged.items())), stream, indent=2)
    usb_paths=[Path(p).resolve() for p in (usb_desktop,usb_console) if p is not None]
    composite = {'Kind': 'XfeIndependentDualBootProof', 'Passed': True, 'ImageSha256': media.digest(image),
                 'DesktopBoot': {'Path': str(desktop_path), 'Sha256': media.digest(desktop_path)},
                 'ConsoleBoot': {'Path': str(console_path), 'Sha256': media.digest(console_path)},
                 'MergedSourceSnapshot': {'Path': str(merged_path), 'Sha256': media.digest(merged_path)},
                 'UsbInputEvidence': [{'Path':str(p),'Sha256':media.digest(p)} for p in usb_paths],
                 'EvidenceFiles': evidence_files((desktop_path, console_path,*usb_paths), media), 'FullReleaseQualified': False}
    with output.open('x', encoding='utf-8') as stream:
        json.dump(composite, stream, indent=2)
    try:
        verified = verify_dual(image, output, media)
    except Exception:
        composite['Passed'] = False
        output.write_text(json.dumps(composite, indent=2), encoding='utf-8')
        raise
    print(json.dumps(verified, ensure_ascii=True))


if __name__ == '__main__':
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('image')
    parser.add_argument('--desktop-proof', required=True)
    parser.add_argument('--console-proof', required=True)
    parser.add_argument('--output', required=True)
    parser.add_argument('--usb-desktop-proof')
    parser.add_argument('--usb-console-proof')
    args = parser.parse_args()
    prepare(args.image, args.desktop_proof, args.console_proof, args.output,args.usb_desktop_proof,args.usb_console_proof)