88 lines
4.2 KiB
JavaScript
88 lines
4.2 KiB
JavaScript
'use strict';
|
|
|
|
const assert = require('node:assert/strict');
|
|
const crypto = require('node:crypto');
|
|
const fs = require('node:fs');
|
|
const os = require('node:os');
|
|
const path = require('node:path');
|
|
const test = require('node:test');
|
|
const JSZip = require('jszip');
|
|
const {
|
|
inspectP15R3InstallGeometry,
|
|
qualifyP15R3HostArtifact,
|
|
} = require('../../src/services/ps5-p15-r3-host-artifact');
|
|
|
|
async function siBytes({ packageSize = 1_048_576, mountImageSize = '0x0000000000100000' } = {}) {
|
|
const zip = new JSZip();
|
|
zip.file('common/etc/pfsimage.xml', [
|
|
'<pfs-image>',
|
|
` <package-size>${packageSize}</package-size>`,
|
|
` <mount-image-size>${mountImageSize}</mount-image-size>`,
|
|
'</pfs-image>',
|
|
].join('\n'));
|
|
return zip.generateAsync({ type: 'nodebuffer' });
|
|
}
|
|
|
|
test('derives the installed app.pkg size from trusted SI geometry', async t => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-p15-r3-geometry-'));
|
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
const filename = path.join(root, 'control.pkg');
|
|
const prefix = Buffer.alloc(720_896, 0x41);
|
|
fs.writeFileSync(filename, Buffer.concat([prefix, await siBytes()]));
|
|
const geometry = await inspectP15R3InstallGeometry(filename);
|
|
assert.equal(geometry.packageSize, 1_048_576);
|
|
assert.equal(geometry.mountImageSize, 1_048_576);
|
|
assert.equal(geometry.installedAppPkgSize, 1_048_576);
|
|
assert.equal(geometry.provenance, 'signed-image:pfsimage.xml');
|
|
});
|
|
|
|
test('rejects contradictory SI geometry instead of accepting a config override', async t => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-p15-r3-geometry-bad-'));
|
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
const filename = path.join(root, 'control.pkg');
|
|
fs.writeFileSync(filename, Buffer.concat([Buffer.alloc(128), await siBytes({ mountImageSize: '0x200000' })]));
|
|
await assert.rejects(inspectP15R3InstallGeometry(filename), error => error.code === 'P15_R3_INSTALL_GEOMETRY_MISMATCH');
|
|
});
|
|
|
|
test('current host readiness revalidates bytes and keeps historical registration separate', async t => {
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'chimera-p15-r3-host-'));
|
|
t.after(() => fs.rmSync(root, { recursive: true, force: true }));
|
|
const filename = path.join(root, 'control.pkg');
|
|
const bytes = Buffer.from('exact-control');
|
|
const descriptor = {
|
|
titleId: 'PPSA99099', contentId: 'UP9000-PPSA99099_00-PROSPERO00000000',
|
|
size: bytes.length, sha256: crypto.createHash('sha256').update(bytes).digest('hex'),
|
|
};
|
|
const inspectPackage = () => ({ format: 'ps5-fih-debug-package', validation: {
|
|
structurallyValid: true, validationLevel: 'fih-cnt-structural-v3', contentId: descriptor.contentId,
|
|
imageCount: 0, imageKey: { profile: 'opaque-filled-0x800' },
|
|
} });
|
|
const inspectInstallGeometry = async () => ({ packageSize: 7, mountImageSize: 7, installedAppPkgSize: 7, provenance: 'signed-image:pfsimage.xml' });
|
|
const missing = await qualifyP15R3HostArtifact({
|
|
filePath: filename, descriptor, inspectPackage, inspectInstallGeometry,
|
|
historicalState: { status: 'ready', packageSetId: 99 },
|
|
});
|
|
assert.equal(missing.status, 'missing');
|
|
assert.equal(missing.currentArtifactVerified, false);
|
|
assert.equal(missing.historicalRegistration.status, 'ready');
|
|
|
|
fs.writeFileSync(filename, bytes);
|
|
const exact = await qualifyP15R3HostArtifact({
|
|
filePath: filename, descriptor, inspectPackage, inspectInstallGeometry,
|
|
historicalState: { status: 'ready', packageSetId: 99 },
|
|
});
|
|
assert.equal(exact.status, 'ready');
|
|
assert.equal(exact.currentArtifactVerified, true);
|
|
assert.equal(exact.geometry.installedAppPkgSize, 7);
|
|
|
|
fs.writeFileSync(filename, Buffer.from('exact-controx'));
|
|
const hashDrift = await qualifyP15R3HostArtifact({ filePath: filename, descriptor, inspectPackage, inspectInstallGeometry });
|
|
assert.equal(hashDrift.status, 'hash_mismatch');
|
|
assert.equal(hashDrift.currentArtifactVerified, false);
|
|
|
|
fs.writeFileSync(filename, Buffer.from('drift-control-longer'));
|
|
const drift = await qualifyP15R3HostArtifact({ filePath: filename, descriptor, inspectPackage, inspectInstallGeometry });
|
|
assert.equal(drift.status, 'size_mismatch');
|
|
assert.equal(drift.currentArtifactVerified, false);
|
|
});
|