Skip to content

Commit

Permalink
Protect bootloader before flashing with the correct requirements
Browse files Browse the repository at this point in the history
  • Loading branch information
keeramis committed Jun 27, 2024
1 parent c819685 commit 09e5118
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 38 deletions.
6 changes: 3 additions & 3 deletions src/cmd/flash.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const {
createFlashSteps,
filterModulesToFlash,
parseModulesToFlash,
validateModulesForProtection,
maintainDeviceProtection,
flashFiles,
validateDFUSupport,
getFileFlashInfo
Expand Down Expand Up @@ -88,7 +88,7 @@ module.exports = class FlashCommand extends CLICommandBase {
platformId: device.platformId,
platformName
});
await validateModulesForProtection({ modules: modulesToFlash, device });
await maintainDeviceProtection({ modules: modulesToFlash, device });
const flashSteps = await createFlashSteps({
modules: modulesToFlash,
isInDfuMode: device.isInDfuMode,
Expand Down Expand Up @@ -158,7 +158,7 @@ module.exports = class FlashCommand extends CLICommandBase {
let modulesToFlash = [...fileModules, ...deviceOsModules];
modulesToFlash = filterModulesToFlash({ modules: modulesToFlash, platformId });

await validateModulesForProtection({ modules: modulesToFlash, device });
await maintainDeviceProtection({ modules: modulesToFlash, device });
const flashSteps = await createFlashSteps({
modules: modulesToFlash,
isInDfuMode: device.isInDfuMode,
Expand Down
4 changes: 2 additions & 2 deletions src/cmd/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const semver = require('semver');
const usbUtils = require('./usb-util');
const deviceOsUtils = require('../lib/device-os-version-util');
const CLICommandBase = require('./base');
const { parseModulesToFlash, filterModulesToFlash, validateModulesForProtection, createFlashSteps, flashFiles, validateDFUSupport } = require('../lib/flash-helper');
const { parseModulesToFlash, filterModulesToFlash, maintainDeviceProtection, createFlashSteps, flashFiles, validateDFUSupport } = require('../lib/flash-helper');
const createApiCache = require('../lib/api-cache');

module.exports = class UpdateCommand extends CLICommandBase {
Expand Down Expand Up @@ -41,7 +41,7 @@ module.exports = class UpdateCommand extends CLICommandBase {
});
const deviceOsModules = await parseModulesToFlash({ files: deviceOsBinaries });
const modulesToFlash = filterModulesToFlash({ modules: deviceOsModules, platformId: device.platformId, allowAll: true });
await validateModulesForProtection({ modules: modulesToFlash, device });
await maintainDeviceProtection({ modules: modulesToFlash, device });
const flashSteps = await createFlashSteps({ modules: modulesToFlash, isInDfuMode: device.isInDfuMode , platformId: device.platformId });
await flashFiles({ device, flashSteps, ui: this.ui });
this.ui.write('Update success!');
Expand Down
14 changes: 11 additions & 3 deletions src/lib/flash-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { delay } = require('./utilities');
const VError = require('verror');
const { PLATFORMS, platformForId } =require('./platform');
const { moduleTypeFromNumber, sortBinariesByDependency } = require('./dependency-walker');
const { HalModuleParser: ModuleParser, ModuleInfo } = require('binary-version-reader');
const { HalModuleParser: ModuleParser, ModuleInfo, createProtectedModule } = require('binary-version-reader');
const path = require('path');
const fs = require('fs-extra');
const os = require('os');
Expand Down Expand Up @@ -363,7 +363,7 @@ function validateDFUSupport({ device, ui }) {
}
}

async function validateModulesForProtection({ modules, device }) {
async function maintainDeviceProtection({ modules, device }) {
try {
const s = await device.getProtectionState();

Expand All @@ -389,6 +389,14 @@ async function validateModulesForProtection({ modules, device }) {
if (oldSystem || oldBootloader) {
throw new Error(`Cannot downgrade Device OS below version ${PROTECTED_MINIMUM_VERSION} on a Protected Device`);
}

// Enable Device Protection on the bootloader when flashing a Protected Device
if (moduleFunction === ModuleInfo.FunctionType.BOOTLOADER && moduleIndex === 0) {
const protectedBuffer = await createProtectedModule(module.fileBuffer);
const parser = new ModuleParser();
const protectedModule = await parser.parseBuffer({ fileBuffer: protectedBuffer });
Object.assign(module, protectedModule);
}
}
}

Expand All @@ -399,7 +407,7 @@ module.exports = {
createFlashSteps,
prepareDeviceForFlash,
validateDFUSupport,
validateModulesForProtection,
maintainDeviceProtection,
getFileFlashInfo,
_get256Hash,
_skipAsset
Expand Down
85 changes: 55 additions & 30 deletions src/lib/flash-helper.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const {
filterModulesToFlash,
prepareDeviceForFlash,
validateDFUSupport,
validateModulesForProtection,
maintainDeviceProtection,
getFileFlashInfo,
_get256Hash,
_skipAsset
Expand Down Expand Up @@ -661,44 +661,55 @@ describe('flash-helper', () => {
});
});

describe('validateModulesForProtection', () => {
describe.only('maintainDeviceProtection', () => {
let device;
const modulesOldBootloader = [{
prefixInfo: {



let modulesOldBootloader;
let modulesOldSystem;
let modulesNew;
let newBootloader;
let newSystemPart;

beforeEach(async () => {
device = {
getProtectionState: sinon.stub(),
};

const oldBootloaderBuffer = await firmwareTestHelper.createFirmwareBinary({
moduleFunction: ModuleInfo.FunctionType.BOOTLOADER,
platformId: 12,
moduleIndex: 0,
moduleVersion: 1200
}
}];
const modulesOldSystem = [{
prefixInfo: {
});
const oldBootloader = await new HalModuleParser().parseBuffer({ fileBuffer: oldBootloaderBuffer });
modulesOldBootloader = [oldBootloader];

const oldSystemBuffer = await firmwareTestHelper.createFirmwareBinary({
moduleFunction: ModuleInfo.FunctionType.SYSTEM_PART,
platformId: 12,
moduleIndex: 0,
moduleVersion: 5800
}
}];
const modulesNew = [{
prefixInfo: {
});
const oldSystem = await new HalModuleParser().parseBuffer({ fileBuffer: oldSystemBuffer });
modulesOldSystem = [oldSystem];

const newBootloaderBuffer = await firmwareTestHelper.createFirmwareBinary({
moduleFunction: ModuleInfo.FunctionType.BOOTLOADER,
platformId: 12,
moduleIndex: 0,
moduleVersion: 3000
}
}, {
prefixInfo: {
});
const newSystemPartBuffer = await firmwareTestHelper.createFirmwareBinary({
moduleFunction: ModuleInfo.FunctionType.SYSTEM_PART,
platformId: 12,
moduleIndex: 0,
moduleVersion: 6000
}
}];

beforeEach(() => {
device = {
getProtectionState: sinon.stub(),
};
});
newBootloader = await new HalModuleParser().parseBuffer({ fileBuffer: newBootloaderBuffer });
newSystemPart = await new HalModuleParser().parseBuffer({ fileBuffer: newSystemPartBuffer });
modulesNew = [newBootloader, newSystemPart];
});

describe('device is not protected', () => {
Expand All @@ -709,7 +720,7 @@ describe('flash-helper', () => {
it('does does not reject old modules', async () => {
let error;
try {
await validateModulesForProtection({ device, modules: modulesOldBootloader });
await maintainDeviceProtection({ device, modules: modulesOldBootloader });
} catch (_error) {
error = _error;
}
Expand All @@ -719,23 +730,30 @@ describe('flash-helper', () => {
it('does does not reject new modules', async () => {
let error;
try {
await validateModulesForProtection({ device, modules: modulesNew });
await maintainDeviceProtection({ device, modules: modulesNew });
} catch (_error) {
error = _error;
}
expect(error).to.be.undefined;
});

it('does not protect the bootloader', async () => {
await maintainDeviceProtection({ device, modules: modulesNew });

expect(newBootloader).not.to.have.property('security');
expect(newSystemPart).not.to.have.property('security');
});
});

describe('device is protected', () => {
describe('device is protected', () => {
beforeEach(() => {
device.getProtectionState.returns({ protected: true, overridden: false });
});

it('throws an exception if the bootloader is too old', async () => {
let error;
try {
await validateModulesForProtection({ device, modules: modulesOldBootloader });
await maintainDeviceProtection({ device, modules: modulesOldBootloader });
} catch (_error) {
error = _error;
}
Expand All @@ -745,7 +763,7 @@ describe('flash-helper', () => {
it('throws an exception if the system part is too old', async () => {
let error;
try {
await validateModulesForProtection({ device, modules: modulesOldSystem });
await maintainDeviceProtection({ device, modules: modulesOldSystem });
} catch (_error) {
error = _error;
}
Expand All @@ -755,12 +773,19 @@ describe('flash-helper', () => {
it('does does not reject new modules', async () => {
let error;
try {
await validateModulesForProtection({ device, modules: modulesNew });
await maintainDeviceProtection({ device, modules: modulesNew });
} catch (_error) {
error = _error;
}
expect(error).to.be.undefined;
});

it('protects the bootloader', async () => {
await maintainDeviceProtection({ device, modules: modulesNew });

expect(newBootloader).to.have.property('security');
expect(newSystemPart).not.to.have.property('security');
});
});

describe('device does not support protection', () => {
Expand All @@ -771,7 +796,7 @@ describe('flash-helper', () => {
it('does does not reject old modules', async () => {
let error;
try {
await validateModulesForProtection({ device, modules: modulesOldBootloader });
await maintainDeviceProtection({ device, modules: modulesOldBootloader });
} catch (_error) {
error = _error;
}
Expand All @@ -781,7 +806,7 @@ describe('flash-helper', () => {
it('does does not reject new modules', async () => {
let error;
try {
await validateModulesForProtection({ device, modules: modulesNew });
await maintainDeviceProtection({ device, modules: modulesNew });
} catch (_error) {
error = _error;
}
Expand Down

0 comments on commit 09e5118

Please sign in to comment.