mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-11-26 19:25:02 +00:00
vboot: Add firmware management parameters
This adds RW firmware support for the optional firmware management
parameters TPM space.
System-level tests require CL:339262 to add cryptohome support.
BUG=chromium:601492
BRANCH=baytrail and newer platforms
TEST=make -j runtests
Or better, COV=1 make, and then make sure all new code is covered.
Change-Id: Ifaf644c80809552d5961615be6017c2a332a034b
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/339234
This commit is contained in:
committed by
chrome-bot
parent
111c59b567
commit
946abf1439
@@ -74,6 +74,9 @@
|
|||||||
#define GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP 0x00002000
|
#define GBB_FLAG_FORCE_DEV_BOOT_FASTBOOT_FULL_CAP 0x00002000
|
||||||
/* Enable serial console */
|
/* Enable serial console */
|
||||||
#define GBB_FLAG_ENABLE_SERIAL 0x00004000
|
#define GBB_FLAG_ENABLE_SERIAL 0x00004000
|
||||||
|
/* Disable using FWMP */
|
||||||
|
#define GBB_FLAG_DISABLE_FWMP 0x00008000
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -40,6 +40,8 @@
|
|||||||
#define TPM_E_WRITE_FAILURE ((uint32_t) 0x00005008) /* vboot local */
|
#define TPM_E_WRITE_FAILURE ((uint32_t) 0x00005008) /* vboot local */
|
||||||
#define TPM_E_READ_EMPTY ((uint32_t) 0x00005009) /* vboot local */
|
#define TPM_E_READ_EMPTY ((uint32_t) 0x00005009) /* vboot local */
|
||||||
#define TPM_E_READ_FAILURE ((uint32_t) 0x0000500a) /* vboot local */
|
#define TPM_E_READ_FAILURE ((uint32_t) 0x0000500a) /* vboot local */
|
||||||
|
#define TPM_E_STRUCT_SIZE ((uint32_t) 0x0000500b) /* vboot local */
|
||||||
|
#define TPM_E_STRUCT_VERSION ((uint32_t) 0x0000500c) /* vboot local */
|
||||||
|
|
||||||
#define TPM_NV_INDEX0 ((uint32_t) 0x00000000)
|
#define TPM_NV_INDEX0 ((uint32_t) 0x00000000)
|
||||||
#define TPM_NV_INDEX_LOCK ((uint32_t) 0xffffffff)
|
#define TPM_NV_INDEX_LOCK ((uint32_t) 0xffffffff)
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ enum VbErrorPredefined_t {
|
|||||||
VBERROR_SCREEN_DRAW = 0x10027,
|
VBERROR_SCREEN_DRAW = 0x10027,
|
||||||
/* failed to jump to RW image */
|
/* failed to jump to RW image */
|
||||||
VBERROR_RW_JUMP_FAILED = 0x10028,
|
VBERROR_RW_JUMP_FAILED = 0x10028,
|
||||||
|
/* Error reading FWMP from TPM (note: not present is not an error) */
|
||||||
|
VBERROR_TPM_READ_FWMP = 0x10029,
|
||||||
|
|
||||||
/* VbExEcGetExpectedRWHash() may return the following codes */
|
/* VbExEcGetExpectedRWHash() may return the following codes */
|
||||||
/* Compute expected RW hash from the EC image; BIOS doesn't have it */
|
/* Compute expected RW hash from the EC image; BIOS doesn't have it */
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
/* GPT is external */
|
/* GPT is external */
|
||||||
#define BOOT_FLAG_EXTERNAL_GPT (0x04ULL)
|
#define BOOT_FLAG_EXTERNAL_GPT (0x04ULL)
|
||||||
|
|
||||||
|
struct RollbackSpaceFwmp;
|
||||||
|
|
||||||
typedef struct LoadKernelParams {
|
typedef struct LoadKernelParams {
|
||||||
/* Inputs to LoadKernel() */
|
/* Inputs to LoadKernel() */
|
||||||
/*
|
/*
|
||||||
@@ -57,6 +59,8 @@ typedef struct LoadKernelParams {
|
|||||||
* VbNvSetup() and VbNvTeardown() on the context.
|
* VbNvSetup() and VbNvTeardown() on the context.
|
||||||
*/
|
*/
|
||||||
VbNvContext *nv_context;
|
VbNvContext *nv_context;
|
||||||
|
/* Firmware management parameters; may be NULL if not present. */
|
||||||
|
const struct RollbackSpaceFwmp *fwmp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Outputs from LoadKernel(); valid only if LoadKernel() returns
|
* Outputs from LoadKernel(); valid only if LoadKernel() returns
|
||||||
|
|||||||
@@ -18,7 +18,8 @@
|
|||||||
/* This is just an opaque space for backup purposes */
|
/* This is just an opaque space for backup purposes */
|
||||||
#define BACKUP_NV_INDEX 0x1009
|
#define BACKUP_NV_INDEX 0x1009
|
||||||
#define BACKUP_NV_SIZE 16
|
#define BACKUP_NV_SIZE 16
|
||||||
|
#define FWMP_NV_INDEX 0x100a
|
||||||
|
#define FWMP_NV_MAX_SIZE 128
|
||||||
|
|
||||||
/* Structure definitions for TPM spaces */
|
/* Structure definitions for TPM spaces */
|
||||||
|
|
||||||
@@ -70,6 +71,34 @@ typedef struct RollbackSpaceFirmware {
|
|||||||
uint8_t crc8;
|
uint8_t crc8;
|
||||||
} __attribute__((packed)) RollbackSpaceFirmware;
|
} __attribute__((packed)) RollbackSpaceFirmware;
|
||||||
|
|
||||||
|
#define FWMP_HASH_SIZE 32 /* Enough for SHA-256 */
|
||||||
|
|
||||||
|
/* Firmware management parameters */
|
||||||
|
struct RollbackSpaceFwmp {
|
||||||
|
/* CRC-8 of fields following struct_size */
|
||||||
|
uint8_t crc;
|
||||||
|
/* Structure size in bytes */
|
||||||
|
uint8_t struct_size;
|
||||||
|
/* Structure version */
|
||||||
|
uint8_t struct_version;
|
||||||
|
/* Reserved; ignored by current reader */
|
||||||
|
uint8_t reserved0;
|
||||||
|
/* Flags; see enum fwmp_flags */
|
||||||
|
uint32_t flags;
|
||||||
|
/* Hash of developer kernel key */
|
||||||
|
uint8_t dev_key_hash[FWMP_HASH_SIZE];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define ROLLBACK_SPACE_FWMP_VERSION 0x10 /* 1.0 */
|
||||||
|
|
||||||
|
enum fwmp_flags {
|
||||||
|
FWMP_DEV_DISABLE_BOOT = (1 << 0),
|
||||||
|
FWMP_DEV_DISABLE_RECOVERY = (1 << 1),
|
||||||
|
FWMP_DEV_ENABLE_USB = (1 << 2),
|
||||||
|
FWMP_DEV_ENABLE_LEGACY = (1 << 3),
|
||||||
|
FWMP_DEV_ENABLE_OFFICIAL_ONLY = (1 << 4),
|
||||||
|
FWMP_DEV_USE_KEY_HASH = (1 << 5),
|
||||||
|
};
|
||||||
|
|
||||||
/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */
|
/* All functions return TPM_SUCCESS (zero) if successful, non-zero if error */
|
||||||
|
|
||||||
@@ -134,6 +163,15 @@ uint32_t RollbackBackupWrite(uint8_t *raw);
|
|||||||
*/
|
*/
|
||||||
uint32_t RollbackKernelLock(int recovery_mode);
|
uint32_t RollbackKernelLock(int recovery_mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read and validate firmware management parameters.
|
||||||
|
*
|
||||||
|
* Absence of a FWMP is not an error; in this case, fwmp will be cleared.
|
||||||
|
*
|
||||||
|
* Returns non-zero if error.
|
||||||
|
*/
|
||||||
|
uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp);
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -481,7 +481,6 @@ uint32_t SetupTPM(int developer_mode, int disable_dev_request,
|
|||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef DISABLE_ROLLBACK_TPM
|
#ifdef DISABLE_ROLLBACK_TPM
|
||||||
/* Dummy implementations which don't support TPM rollback protection */
|
/* Dummy implementations which don't support TPM rollback protection */
|
||||||
|
|
||||||
@@ -680,3 +679,73 @@ uint32_t RollbackKernelLock(int recovery_mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* DISABLE_ROLLBACK_TPM */
|
#endif /* DISABLE_ROLLBACK_TPM */
|
||||||
|
|
||||||
|
uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp)
|
||||||
|
{
|
||||||
|
uint8_t buf[FWMP_NV_MAX_SIZE];
|
||||||
|
struct RollbackSpaceFwmp *bf = (struct RollbackSpaceFwmp *)buf;
|
||||||
|
uint32_t r;
|
||||||
|
int attempts = 3;
|
||||||
|
|
||||||
|
/* Clear destination in case error or FWMP not present */
|
||||||
|
Memset(fwmp, 0, sizeof(*fwmp));
|
||||||
|
|
||||||
|
while (attempts--) {
|
||||||
|
/* Try to read entire 1.0 struct */
|
||||||
|
r = TlclRead(FWMP_NV_INDEX, buf, sizeof(*bf));
|
||||||
|
if (r == TPM_E_BADINDEX) {
|
||||||
|
/* Missing space is not an error; use defaults */
|
||||||
|
VBDEBUG(("TPM: %s() - no FWMP space\n", __func__));
|
||||||
|
return TPM_SUCCESS;
|
||||||
|
} else if (r != TPM_SUCCESS) {
|
||||||
|
VBDEBUG(("TPM: %s() - read returned 0x%x\n",
|
||||||
|
__func__, r));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Struct must be at least big enough for 1.0, but not bigger
|
||||||
|
* than our buffer size.
|
||||||
|
*/
|
||||||
|
if (bf->struct_size < sizeof(*bf) ||
|
||||||
|
bf->struct_size > sizeof(buf))
|
||||||
|
return TPM_E_STRUCT_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If space is bigger than we expect, re-read so we properly
|
||||||
|
* compute the CRC.
|
||||||
|
*/
|
||||||
|
if (bf->struct_size > sizeof(*bf)) {
|
||||||
|
r = TlclRead(FWMP_NV_INDEX, buf, bf->struct_size);
|
||||||
|
if (r != TPM_SUCCESS)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify CRC */
|
||||||
|
if (bf->crc != Crc8(buf + 2, bf->struct_size - 2)) {
|
||||||
|
VBDEBUG(("TPM: %s() - bad CRC\n", __func__));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify major version is compatible */
|
||||||
|
if ((bf->struct_version >> 4) !=
|
||||||
|
(ROLLBACK_SPACE_FWMP_VERSION >> 4))
|
||||||
|
return TPM_E_STRUCT_VERSION;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy to destination. Note that if the space is bigger than
|
||||||
|
* we expect (due to a minor version change), we only copy the
|
||||||
|
* part of the FWMP that we know what to do with.
|
||||||
|
*
|
||||||
|
* If this were a 1.1+ reader and the source was a 1.0 struct,
|
||||||
|
* we would need to take care of initializing the extra fields
|
||||||
|
* added in 1.1+. But that's not an issue yet.
|
||||||
|
*/
|
||||||
|
Memcpy(fwmp, bf, sizeof(*fwmp));
|
||||||
|
return TPM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
VBDEBUG(("TPM: %s() - too many bad CRCs, giving up\n", __func__));
|
||||||
|
return TPM_E_CORRUPTED_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,14 +22,20 @@
|
|||||||
|
|
||||||
/* Global variables */
|
/* Global variables */
|
||||||
static VbNvContext vnc;
|
static VbNvContext vnc;
|
||||||
|
static struct RollbackSpaceFwmp fwmp;
|
||||||
|
|
||||||
#ifdef CHROMEOS_ENVIRONMENT
|
#ifdef CHROMEOS_ENVIRONMENT
|
||||||
/* Global variable accessor for unit tests */
|
/* Global variable accessors for unit tests */
|
||||||
|
|
||||||
VbNvContext *VbApiKernelGetVnc(void)
|
VbNvContext *VbApiKernelGetVnc(void)
|
||||||
{
|
{
|
||||||
return &vnc;
|
return &vnc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct RollbackSpaceFwmp *VbApiKernelGetFwmp(void)
|
||||||
|
{
|
||||||
|
return &fwmp;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -280,6 +286,11 @@ VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p)
|
|||||||
return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
|
return VbTryLoadKernel(cparams, p, VB_DISK_FLAG_FIXED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char dev_disable_msg[] =
|
||||||
|
"Developer mode is disabled on this device by system policy.\n"
|
||||||
|
"For more information, see http://dev.chromium.org/chromium-os/fwmp\n"
|
||||||
|
"\n";
|
||||||
|
|
||||||
VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p)
|
VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p)
|
||||||
{
|
{
|
||||||
GoogleBinaryBlockHeader *gbb = cparams->gbb;
|
GoogleBinaryBlockHeader *gbb = cparams->gbb;
|
||||||
@@ -288,6 +299,7 @@ VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p)
|
|||||||
|
|
||||||
uint32_t allow_usb = 0;
|
uint32_t allow_usb = 0;
|
||||||
uint32_t allow_legacy = 0;
|
uint32_t allow_legacy = 0;
|
||||||
|
uint32_t disable_dev_boot = 0;
|
||||||
uint32_t use_usb = 0;
|
uint32_t use_usb = 0;
|
||||||
uint32_t use_legacy = 0;
|
uint32_t use_legacy = 0;
|
||||||
uint32_t default_boot = 0;
|
uint32_t default_boot = 0;
|
||||||
@@ -319,6 +331,46 @@ VbError_t VbBootDeveloper(VbCommonParams *cparams, LoadKernelParams *p)
|
|||||||
use_usb = 0;
|
use_usb = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle FWMP override */
|
||||||
|
if (fwmp.flags & FWMP_DEV_ENABLE_USB)
|
||||||
|
allow_usb = 1;
|
||||||
|
if (fwmp.flags & FWMP_DEV_ENABLE_LEGACY)
|
||||||
|
allow_legacy = 1;
|
||||||
|
if (fwmp.flags & FWMP_DEV_DISABLE_BOOT) {
|
||||||
|
if (gbb->flags & GBB_FLAG_FORCE_DEV_SWITCH_ON) {
|
||||||
|
VBDEBUG(("%s() - FWMP_DEV_DISABLE_BOOT rejected by "
|
||||||
|
"FORCE_DEV_SWITCH_ON\n",
|
||||||
|
__func__));
|
||||||
|
} else {
|
||||||
|
disable_dev_boot = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If dev mode is disabled, only allow TONORM */
|
||||||
|
while (disable_dev_boot) {
|
||||||
|
VBDEBUG(("%s() - dev_disable_boot is set.\n", __func__));
|
||||||
|
VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_TO_NORM, 0, &vnc);
|
||||||
|
VbExDisplayDebugInfo(dev_disable_msg);
|
||||||
|
|
||||||
|
/* Ignore space in VbUserConfirms()... */
|
||||||
|
switch (VbUserConfirms(cparams, 0)) {
|
||||||
|
case 1:
|
||||||
|
VBDEBUG(("%s() - leaving dev-mode.\n", __func__));
|
||||||
|
VbNvSet(&vnc, VBNV_DISABLE_DEV_REQUEST, 1);
|
||||||
|
VbDisplayScreen(cparams,
|
||||||
|
VB_SCREEN_TO_NORM_CONFIRMED,
|
||||||
|
0, &vnc);
|
||||||
|
VbExSleepMs(5000);
|
||||||
|
return VBERROR_TPM_REBOOT_REQUIRED;
|
||||||
|
case -1:
|
||||||
|
VBDEBUG(("%s() - shutdown requested\n", __func__));
|
||||||
|
return VBERROR_SHUTDOWN_REQUESTED;
|
||||||
|
default:
|
||||||
|
/* Ignore user attempt to cancel */
|
||||||
|
VBDEBUG(("%s() - ignore cancel TONORM\n", __func__));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Show the dev mode warning screen */
|
/* Show the dev mode warning screen */
|
||||||
VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_WARNING, 0, &vnc);
|
VbDisplayScreen(cparams, VB_SCREEN_DEVELOPER_WARNING, 0, &vnc);
|
||||||
|
|
||||||
@@ -1162,12 +1214,29 @@ VbError_t VbSelectAndLoadKernel(VbCommonParams *cparams,
|
|||||||
}
|
}
|
||||||
shared->kernel_version_tpm_start = shared->kernel_version_tpm;
|
shared->kernel_version_tpm_start = shared->kernel_version_tpm;
|
||||||
|
|
||||||
|
/* Read FWMP. Ignore errors in recovery mode. */
|
||||||
|
if (cparams->gbb->flags & GBB_FLAG_DISABLE_FWMP) {
|
||||||
|
Memset(&fwmp, 0, sizeof(fwmp));
|
||||||
|
tpm_status = 0;
|
||||||
|
} else {
|
||||||
|
tpm_status = RollbackFwmpRead(&fwmp);
|
||||||
|
}
|
||||||
|
if (0 != tpm_status) {
|
||||||
|
VBDEBUG(("Unable to get FWMP from TPM\n"));
|
||||||
|
if (!shared->recovery_reason) {
|
||||||
|
VbSetRecoveryRequest(VBNV_RECOVERY_RW_TPM_R_ERROR);
|
||||||
|
retval = VBERROR_TPM_READ_FWMP;
|
||||||
|
goto VbSelectAndLoadKernel_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Fill in params for calls to LoadKernel() */
|
/* Fill in params for calls to LoadKernel() */
|
||||||
Memset(&p, 0, sizeof(p));
|
Memset(&p, 0, sizeof(p));
|
||||||
p.shared_data_blob = cparams->shared_data_blob;
|
p.shared_data_blob = cparams->shared_data_blob;
|
||||||
p.shared_data_size = cparams->shared_data_size;
|
p.shared_data_size = cparams->shared_data_size;
|
||||||
p.gbb_data = cparams->gbb_data;
|
p.gbb_data = cparams->gbb_data;
|
||||||
p.gbb_size = cparams->gbb_size;
|
p.gbb_size = cparams->gbb_size;
|
||||||
|
p.fwmp = &fwmp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This could be set to NULL, in which case the vboot header
|
* This could be set to NULL, in which case the vboot header
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include "gbb_header.h"
|
#include "gbb_header.h"
|
||||||
#include "gpt_misc.h"
|
#include "gpt_misc.h"
|
||||||
#include "load_kernel_fw.h"
|
#include "load_kernel_fw.h"
|
||||||
|
#include "rollback_index.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "vboot_api.h"
|
#include "vboot_api.h"
|
||||||
#include "vboot_common.h"
|
#include "vboot_common.h"
|
||||||
@@ -77,6 +78,10 @@ VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams)
|
|||||||
} else if (dev_switch) {
|
} else if (dev_switch) {
|
||||||
boot_mode = kBootDev;
|
boot_mode = kBootDev;
|
||||||
VbNvGet(vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &require_official_os);
|
VbNvGet(vnc, VBNV_DEV_BOOT_SIGNED_ONLY, &require_official_os);
|
||||||
|
|
||||||
|
if (params->fwmp &&
|
||||||
|
(params->fwmp->flags & FWMP_DEV_ENABLE_OFFICIAL_ONLY))
|
||||||
|
require_official_os = 1;
|
||||||
} else {
|
} else {
|
||||||
boot_mode = kBootNormal;
|
boot_mode = kBootNormal;
|
||||||
}
|
}
|
||||||
@@ -268,6 +273,39 @@ VbError_t LoadKernel(LoadKernelParams *params, VbCommonParams *cparams)
|
|||||||
goto bad_kernel;
|
goto bad_kernel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* If in developer mode and using key hash, check it */
|
||||||
|
if ((kBootDev == boot_mode) &&
|
||||||
|
params->fwmp &&
|
||||||
|
(params->fwmp->flags & FWMP_DEV_USE_KEY_HASH)) {
|
||||||
|
VbPublicKey *key = &key_block->data_key;
|
||||||
|
uint8_t *buf = ((uint8_t *)key) + key->key_offset;
|
||||||
|
uint64_t buflen = key->key_size;
|
||||||
|
uint8_t *digest;
|
||||||
|
|
||||||
|
VBDEBUG(("Checking developer key hash.\n"));
|
||||||
|
digest = DigestBuf(buf, buflen,
|
||||||
|
SHA256_DIGEST_ALGORITHM);
|
||||||
|
if (0 != SafeMemcmp(digest, params->fwmp->dev_key_hash,
|
||||||
|
SHA256_DIGEST_SIZE)) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
VBDEBUG(("Wrong developer key hash.\n"));
|
||||||
|
VBDEBUG(("Want: "));
|
||||||
|
for (i = 0; i < SHA256_DIGEST_SIZE; i++)
|
||||||
|
VBDEBUG(("%02x",
|
||||||
|
params->fwmp->dev_key_hash[i]));
|
||||||
|
VBDEBUG(("\nGot: "));
|
||||||
|
for (i = 0; i < SHA256_DIGEST_SIZE; i++)
|
||||||
|
VBDEBUG(("%02x", digest[i]));
|
||||||
|
VBDEBUG(("\n"));
|
||||||
|
|
||||||
|
VbExFree(digest);
|
||||||
|
goto bad_kernel;
|
||||||
|
}
|
||||||
|
VbExFree(digest);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get key for preamble/data verification from the key block. */
|
/* Get key for preamble/data verification from the key block. */
|
||||||
data_key = PublicKeyToRSA(&key_block->data_key);
|
data_key = PublicKeyToRSA(&key_block->data_key);
|
||||||
if (!data_key) {
|
if (!data_key) {
|
||||||
|
|||||||
@@ -53,8 +53,21 @@ static int noise_on[MAX_NOISE_COUNT]; /* calls to inject noise on */
|
|||||||
static TPM_PERMANENT_FLAGS mock_pflags;
|
static TPM_PERMANENT_FLAGS mock_pflags;
|
||||||
static RollbackSpaceFirmware mock_rsf;
|
static RollbackSpaceFirmware mock_rsf;
|
||||||
static RollbackSpaceKernel mock_rsk;
|
static RollbackSpaceKernel mock_rsk;
|
||||||
|
|
||||||
|
static union {
|
||||||
|
struct RollbackSpaceFwmp fwmp;
|
||||||
|
uint8_t buf[FWMP_NV_MAX_SIZE];
|
||||||
|
} mock_fwmp;
|
||||||
|
|
||||||
static uint32_t mock_permissions;
|
static uint32_t mock_permissions;
|
||||||
|
|
||||||
|
/* Recalculate CRC of FWMP data */
|
||||||
|
static void RecalcFwmpCrc(void)
|
||||||
|
{
|
||||||
|
mock_fwmp.fwmp.crc = Crc8(mock_fwmp.buf + 2,
|
||||||
|
mock_fwmp.fwmp.struct_size - 2);
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset the variables for the Tlcl mock functions. */
|
/* Reset the variables for the Tlcl mock functions. */
|
||||||
static void ResetMocks(int fail_on_call, uint32_t fail_with_err)
|
static void ResetMocks(int fail_on_call, uint32_t fail_with_err)
|
||||||
{
|
{
|
||||||
@@ -70,6 +83,15 @@ static void ResetMocks(int fail_on_call, uint32_t fail_with_err)
|
|||||||
Memset(&mock_rsf, 0, sizeof(mock_rsf));
|
Memset(&mock_rsf, 0, sizeof(mock_rsf));
|
||||||
Memset(&mock_rsk, 0, sizeof(mock_rsk));
|
Memset(&mock_rsk, 0, sizeof(mock_rsk));
|
||||||
mock_permissions = 0;
|
mock_permissions = 0;
|
||||||
|
|
||||||
|
Memset(mock_fwmp.buf, 0, sizeof(mock_fwmp.buf));
|
||||||
|
mock_fwmp.fwmp.struct_size = sizeof(mock_fwmp.fwmp);
|
||||||
|
mock_fwmp.fwmp.struct_version = ROLLBACK_SPACE_FWMP_VERSION;
|
||||||
|
mock_fwmp.fwmp.flags = 0x1234;
|
||||||
|
/* Put some data in the hash */
|
||||||
|
mock_fwmp.fwmp.dev_key_hash[0] = 0xaa;
|
||||||
|
mock_fwmp.fwmp.dev_key_hash[FWMP_HASH_SIZE - 1] = 0xbb;
|
||||||
|
RecalcFwmpCrc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
@@ -135,6 +157,12 @@ uint32_t TlclRead(uint32_t index, void* data, uint32_t length)
|
|||||||
TEST_EQ(length, sizeof(mock_rsk), "TlclRead rsk size");
|
TEST_EQ(length, sizeof(mock_rsk), "TlclRead rsk size");
|
||||||
Memcpy(data, &mock_rsk, length);
|
Memcpy(data, &mock_rsk, length);
|
||||||
MaybeInjectNoise(data, length);
|
MaybeInjectNoise(data, length);
|
||||||
|
} else if (FWMP_NV_INDEX == index) {
|
||||||
|
Memset(data, 0, length);
|
||||||
|
if (length > sizeof(mock_fwmp))
|
||||||
|
length = sizeof(mock_fwmp);
|
||||||
|
Memcpy(data, &mock_fwmp, length);
|
||||||
|
MaybeInjectNoise(data, length);
|
||||||
} else {
|
} else {
|
||||||
Memset(data, 0, length);
|
Memset(data, 0, length);
|
||||||
}
|
}
|
||||||
@@ -962,6 +990,7 @@ static void RollbackKernelTest(void)
|
|||||||
"tlcl calls");
|
"tlcl calls");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
/* Tests for RollbackS3Resume() */
|
/* Tests for RollbackS3Resume() */
|
||||||
static void RollbackS3ResumeTest(void)
|
static void RollbackS3ResumeTest(void)
|
||||||
{
|
{
|
||||||
@@ -982,6 +1011,99 @@ static void RollbackS3ResumeTest(void)
|
|||||||
"RollbackS3Resume() other error");
|
"RollbackS3Resume() other error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************/
|
||||||
|
/* Tests for RollbackFwmpRead() calls */
|
||||||
|
|
||||||
|
static void RollbackFwmpTest(void)
|
||||||
|
{
|
||||||
|
struct RollbackSpaceFwmp fwmp;
|
||||||
|
struct RollbackSpaceFwmp fwmp_zero = {0};
|
||||||
|
|
||||||
|
/* Normal read */
|
||||||
|
ResetMocks(0, 0);
|
||||||
|
TEST_EQ(RollbackFwmpRead(&fwmp), 0, "RollbackFwmpRead()");
|
||||||
|
TEST_STR_EQ(mock_calls,
|
||||||
|
"TlclRead(0x100a, 40)\n",
|
||||||
|
" tlcl calls");
|
||||||
|
TEST_EQ(0, Memcmp(&fwmp, &mock_fwmp, sizeof(fwmp)), " data");
|
||||||
|
|
||||||
|
/* Read error */
|
||||||
|
ResetMocks(1, TPM_E_IOERROR);
|
||||||
|
TEST_EQ(RollbackFwmpRead(&fwmp), TPM_E_IOERROR,
|
||||||
|
"RollbackFwmpRead() error");
|
||||||
|
TEST_STR_EQ(mock_calls,
|
||||||
|
"TlclRead(0x100a, 40)\n",
|
||||||
|
" tlcl calls");
|
||||||
|
TEST_EQ(0, Memcmp(&fwmp, &fwmp_zero, sizeof(fwmp)), " data clear");
|
||||||
|
|
||||||
|
/* Not present isn't an error; just returns empty data */
|
||||||
|
ResetMocks(1, TPM_E_BADINDEX);
|
||||||
|
TEST_EQ(RollbackFwmpRead(&fwmp), 0, "RollbackFwmpRead() not present");
|
||||||
|
TEST_STR_EQ(mock_calls,
|
||||||
|
"TlclRead(0x100a, 40)\n",
|
||||||
|
" tlcl calls");
|
||||||
|
TEST_EQ(0, Memcmp(&fwmp, &fwmp_zero, sizeof(fwmp)), " data clear");
|
||||||
|
|
||||||
|
/* Struct size too small */
|
||||||
|
ResetMocks(0, 0);
|
||||||
|
mock_fwmp.fwmp.struct_size--;
|
||||||
|
TEST_EQ(RollbackFwmpRead(&fwmp), TPM_E_STRUCT_SIZE,
|
||||||
|
"RollbackFwmpRead() too small");
|
||||||
|
|
||||||
|
/* Struct size too large with good CRC */
|
||||||
|
ResetMocks(0, 0);
|
||||||
|
mock_fwmp.fwmp.struct_size += 4;
|
||||||
|
RecalcFwmpCrc();
|
||||||
|
TEST_EQ(RollbackFwmpRead(&fwmp), 0, "RollbackFwmpRead() bigger");
|
||||||
|
TEST_STR_EQ(mock_calls,
|
||||||
|
"TlclRead(0x100a, 40)\n"
|
||||||
|
"TlclRead(0x100a, 44)\n",
|
||||||
|
" tlcl calls");
|
||||||
|
TEST_EQ(0, Memcmp(&fwmp, &mock_fwmp, sizeof(fwmp)), " data");
|
||||||
|
|
||||||
|
/* Bad CRC causes retry, then eventual failure */
|
||||||
|
ResetMocks(0, 0);
|
||||||
|
mock_fwmp.fwmp.crc++;
|
||||||
|
TEST_EQ(RollbackFwmpRead(&fwmp), TPM_E_CORRUPTED_STATE,
|
||||||
|
"RollbackFwmpRead() crc");
|
||||||
|
TEST_STR_EQ(mock_calls,
|
||||||
|
"TlclRead(0x100a, 40)\n"
|
||||||
|
"TlclRead(0x100a, 40)\n"
|
||||||
|
"TlclRead(0x100a, 40)\n",
|
||||||
|
" tlcl calls");
|
||||||
|
|
||||||
|
/* Struct size too large with bad CRC */
|
||||||
|
ResetMocks(0, 0);
|
||||||
|
mock_fwmp.fwmp.struct_size += 4;
|
||||||
|
RecalcFwmpCrc();
|
||||||
|
mock_fwmp.fwmp.crc++;
|
||||||
|
TEST_EQ(RollbackFwmpRead(&fwmp), TPM_E_CORRUPTED_STATE,
|
||||||
|
"RollbackFwmpRead() bigger crc");
|
||||||
|
TEST_STR_EQ(mock_calls,
|
||||||
|
"TlclRead(0x100a, 40)\n"
|
||||||
|
"TlclRead(0x100a, 44)\n"
|
||||||
|
"TlclRead(0x100a, 40)\n"
|
||||||
|
"TlclRead(0x100a, 44)\n"
|
||||||
|
"TlclRead(0x100a, 40)\n"
|
||||||
|
"TlclRead(0x100a, 44)\n",
|
||||||
|
" tlcl calls");
|
||||||
|
TEST_EQ(0, Memcmp(&fwmp, &fwmp_zero, sizeof(fwmp)), " data");
|
||||||
|
|
||||||
|
/* Minor version difference ok */
|
||||||
|
ResetMocks(0, 0);
|
||||||
|
mock_fwmp.fwmp.struct_version++;
|
||||||
|
RecalcFwmpCrc();
|
||||||
|
TEST_EQ(RollbackFwmpRead(&fwmp), 0, "RollbackFwmpRead() minor version");
|
||||||
|
TEST_EQ(0, Memcmp(&fwmp, &mock_fwmp, sizeof(fwmp)), " data");
|
||||||
|
|
||||||
|
/* Major version difference not ok */
|
||||||
|
ResetMocks(0, 0);
|
||||||
|
mock_fwmp.fwmp.struct_version += 0x10;
|
||||||
|
RecalcFwmpCrc();
|
||||||
|
TEST_EQ(RollbackFwmpRead(&fwmp), TPM_E_STRUCT_VERSION,
|
||||||
|
"RollbackFwmpRead() major version");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
CrcTestFirmware();
|
CrcTestFirmware();
|
||||||
@@ -992,6 +1114,7 @@ int main(int argc, char* argv[])
|
|||||||
RollbackFirmwareTest();
|
RollbackFirmwareTest();
|
||||||
RollbackKernelTest();
|
RollbackKernelTest();
|
||||||
RollbackS3ResumeTest();
|
RollbackS3ResumeTest();
|
||||||
|
RollbackFwmpTest();
|
||||||
|
|
||||||
return gTestSuccess ? 0 : 255;
|
return gTestSuccess ? 0 : 255;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ static uint32_t mock_num_disks[8];
|
|||||||
static uint32_t mock_num_disks_count;
|
static uint32_t mock_num_disks_count;
|
||||||
|
|
||||||
extern enum VbEcBootMode_t VbGetMode(void);
|
extern enum VbEcBootMode_t VbGetMode(void);
|
||||||
|
extern struct RollbackSpaceFwmp *VbApiKernelGetFwmp(void);
|
||||||
|
|
||||||
/* Reset mock data (for use before each test) */
|
/* Reset mock data (for use before each test) */
|
||||||
static void ResetMocks(void)
|
static void ResetMocks(void)
|
||||||
@@ -69,6 +70,8 @@ static void ResetMocks(void)
|
|||||||
VbNvSetup(VbApiKernelGetVnc());
|
VbNvSetup(VbApiKernelGetVnc());
|
||||||
VbNvTeardown(VbApiKernelGetVnc()); /* So CRC gets generated */
|
VbNvTeardown(VbApiKernelGetVnc()); /* So CRC gets generated */
|
||||||
|
|
||||||
|
Memset(VbApiKernelGetFwmp(), 0, sizeof(struct RollbackSpaceFwmp));
|
||||||
|
|
||||||
Memset(&shared_data, 0, sizeof(shared_data));
|
Memset(&shared_data, 0, sizeof(shared_data));
|
||||||
VbSharedDataInit(shared, sizeof(shared_data));
|
VbSharedDataInit(shared, sizeof(shared_data));
|
||||||
|
|
||||||
@@ -452,6 +455,12 @@ static void VbBootDevTest(void)
|
|||||||
TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Ctrl+L nv legacy");
|
TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Ctrl+L nv legacy");
|
||||||
TEST_EQ(vbexlegacy_called, 1, " try legacy");
|
TEST_EQ(vbexlegacy_called, 1, " try legacy");
|
||||||
|
|
||||||
|
ResetMocks();
|
||||||
|
VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_LEGACY;
|
||||||
|
mock_keypress[0] = 0x0c;
|
||||||
|
TEST_EQ(VbBootDeveloper(&cparams, &lkp), 1002, "Ctrl+L fwmp legacy");
|
||||||
|
TEST_EQ(vbexlegacy_called, 1, " fwmp legacy");
|
||||||
|
|
||||||
/* Ctrl+U boots USB only if enabled */
|
/* Ctrl+U boots USB only if enabled */
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
mock_keypress[0] = 0x15;
|
mock_keypress[0] = 0x15;
|
||||||
@@ -471,6 +480,13 @@ static void VbBootDevTest(void)
|
|||||||
vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
|
vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
|
||||||
TEST_EQ(VbBootDeveloper(&cparams, &lkp), 0, "Ctrl+U force USB");
|
TEST_EQ(VbBootDeveloper(&cparams, &lkp), 0, "Ctrl+U force USB");
|
||||||
|
|
||||||
|
/* Ctrl+U enabled via FWMP */
|
||||||
|
ResetMocks();
|
||||||
|
VbApiKernelGetFwmp()->flags |= FWMP_DEV_ENABLE_USB;
|
||||||
|
mock_keypress[0] = 0x15;
|
||||||
|
vbtlk_retval = VBERROR_SUCCESS - VB_DISK_FLAG_REMOVABLE;
|
||||||
|
TEST_EQ(VbBootDeveloper(&cparams, &lkp), 0, "Ctrl+U force USB");
|
||||||
|
|
||||||
/* If no USB, eventually times out and tries fixed disk */
|
/* If no USB, eventually times out and tries fixed disk */
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
VbNvSet(VbApiKernelGetVnc(), VBNV_DEV_BOOT_USB, 1);
|
VbNvSet(VbApiKernelGetVnc(), VBNV_DEV_BOOT_USB, 1);
|
||||||
@@ -481,6 +497,32 @@ static void VbBootDevTest(void)
|
|||||||
TEST_EQ(u, 0, " recovery reason");
|
TEST_EQ(u, 0, " recovery reason");
|
||||||
TEST_EQ(audio_looping_calls_left, 0, " used up audio");
|
TEST_EQ(audio_looping_calls_left, 0, " used up audio");
|
||||||
|
|
||||||
|
/* If dev mode is disabled, goes to TONORM screen repeatedly */
|
||||||
|
ResetMocks();
|
||||||
|
VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT;
|
||||||
|
mock_keypress[0] = '\x1b'; /* Just causes TONORM again */
|
||||||
|
mock_keypress[1] = '\r';
|
||||||
|
TEST_EQ(VbBootDeveloper(&cparams, &lkp), VBERROR_TPM_REBOOT_REQUIRED,
|
||||||
|
"FWMP dev disabled");
|
||||||
|
TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM,
|
||||||
|
" tonorm screen");
|
||||||
|
TEST_EQ(screens_displayed[1], VB_SCREEN_DEVELOPER_TO_NORM,
|
||||||
|
" tonorm screen");
|
||||||
|
TEST_EQ(screens_displayed[2], VB_SCREEN_TO_NORM_CONFIRMED,
|
||||||
|
" confirm screen");
|
||||||
|
VbNvGet(VbApiKernelGetVnc(), VBNV_DISABLE_DEV_REQUEST, &u);
|
||||||
|
TEST_EQ(u, 1, " disable dev request");
|
||||||
|
|
||||||
|
/* Shutdown requested when dev disabled */
|
||||||
|
ResetMocks();
|
||||||
|
shared->flags = VBSD_HONOR_VIRT_DEV_SWITCH | VBSD_BOOT_DEV_SWITCH_ON;
|
||||||
|
VbApiKernelGetFwmp()->flags |= FWMP_DEV_DISABLE_BOOT;
|
||||||
|
shutdown_request_calls_left = 1;
|
||||||
|
TEST_EQ(VbBootDeveloper(&cparams, &lkp), VBERROR_SHUTDOWN_REQUESTED,
|
||||||
|
"Shutdown requested when dev disabled");
|
||||||
|
TEST_EQ(screens_displayed[0], VB_SCREEN_DEVELOPER_TO_NORM,
|
||||||
|
" tonorm screen");
|
||||||
|
|
||||||
printf("...done.\n");
|
printf("...done.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ static GoogleBinaryBlockHeader gbb;
|
|||||||
static int ecsync_retval;
|
static int ecsync_retval;
|
||||||
static uint32_t rkr_version;
|
static uint32_t rkr_version;
|
||||||
static uint32_t new_version;
|
static uint32_t new_version;
|
||||||
static int rkr_retval, rkw_retval, rkl_retval;
|
static struct RollbackSpaceFwmp rfr_fwmp;
|
||||||
|
static int rkr_retval, rkw_retval, rkl_retval, rfr_retval;
|
||||||
static VbError_t vbboot_retval;
|
static VbError_t vbboot_retval;
|
||||||
|
|
||||||
/* Reset mock data (for use before each test) */
|
/* Reset mock data (for use before each test) */
|
||||||
@@ -57,6 +58,9 @@ static void ResetMocks(void)
|
|||||||
Memset(&shared_data, 0, sizeof(shared_data));
|
Memset(&shared_data, 0, sizeof(shared_data));
|
||||||
VbSharedDataInit(shared, sizeof(shared_data));
|
VbSharedDataInit(shared, sizeof(shared_data));
|
||||||
|
|
||||||
|
Memset(&rfr_fwmp, 0, sizeof(rfr_fwmp));
|
||||||
|
rfr_retval = TPM_SUCCESS;
|
||||||
|
|
||||||
ecsync_retval = VBERROR_SUCCESS;
|
ecsync_retval = VBERROR_SUCCESS;
|
||||||
rkr_version = new_version = 0x10002;
|
rkr_version = new_version = 0x10002;
|
||||||
rkr_retval = rkw_retval = rkl_retval = VBERROR_SUCCESS;
|
rkr_retval = rkw_retval = rkl_retval = VBERROR_SUCCESS;
|
||||||
@@ -100,6 +104,12 @@ uint32_t RollbackKernelLock(int recovery_mode)
|
|||||||
return rkl_retval;
|
return rkl_retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t RollbackFwmpRead(struct RollbackSpaceFwmp *fwmp)
|
||||||
|
{
|
||||||
|
Memcpy(fwmp, &rfr_fwmp, sizeof(*fwmp));
|
||||||
|
return rfr_retval;
|
||||||
|
}
|
||||||
|
|
||||||
VbError_t VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p)
|
VbError_t VbBootNormal(VbCommonParams *cparams, LoadKernelParams *p)
|
||||||
{
|
{
|
||||||
shared->kernel_version_tpm = new_version;
|
shared->kernel_version_tpm = new_version;
|
||||||
|
|||||||
@@ -13,10 +13,12 @@
|
|||||||
#include "cgptlib.h"
|
#include "cgptlib.h"
|
||||||
#include "cgptlib_internal.h"
|
#include "cgptlib_internal.h"
|
||||||
#include "crc32.h"
|
#include "crc32.h"
|
||||||
|
#include "cryptolib.h"
|
||||||
#include "gbb_header.h"
|
#include "gbb_header.h"
|
||||||
#include "gpt.h"
|
#include "gpt.h"
|
||||||
#include "host_common.h"
|
#include "host_common.h"
|
||||||
#include "load_kernel_fw.h"
|
#include "load_kernel_fw.h"
|
||||||
|
#include "rollback_index.h"
|
||||||
#include "test_common.h"
|
#include "test_common.h"
|
||||||
#include "vboot_api.h"
|
#include "vboot_api.h"
|
||||||
#include "vboot_common.h"
|
#include "vboot_common.h"
|
||||||
@@ -63,12 +65,13 @@ static LoadKernelParams lkp;
|
|||||||
static VbKeyBlockHeader kbh;
|
static VbKeyBlockHeader kbh;
|
||||||
static VbKernelPreambleHeader kph;
|
static VbKernelPreambleHeader kph;
|
||||||
static VbCommonParams cparams;
|
static VbCommonParams cparams;
|
||||||
|
static struct RollbackSpaceFwmp fwmp;
|
||||||
static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT];
|
static uint8_t mock_disk[MOCK_SECTOR_SIZE * MOCK_SECTOR_COUNT];
|
||||||
static GptHeader *mock_gpt_primary =
|
static GptHeader *mock_gpt_primary =
|
||||||
(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1];
|
(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * 1];
|
||||||
static GptHeader *mock_gpt_secondary =
|
static GptHeader *mock_gpt_secondary =
|
||||||
(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * (MOCK_SECTOR_COUNT - 1)];
|
(GptHeader*)&mock_disk[MOCK_SECTOR_SIZE * (MOCK_SECTOR_COUNT - 1)];
|
||||||
|
static uint8_t mock_digest[SHA256_DIGEST_SIZE] = {12, 34, 56, 78};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepare a valid GPT header that will pass CheckHeader() tests
|
* Prepare a valid GPT header that will pass CheckHeader() tests
|
||||||
@@ -172,6 +175,9 @@ static void ResetMocks(void)
|
|||||||
kph.bootloader_address = 0xbeadd008;
|
kph.bootloader_address = 0xbeadd008;
|
||||||
kph.bootloader_size = 0x1234;
|
kph.bootloader_size = 0x1234;
|
||||||
|
|
||||||
|
memset(&fwmp, 0, sizeof(fwmp));
|
||||||
|
memcpy(fwmp.dev_key_hash, mock_digest, sizeof(fwmp.dev_key_hash));
|
||||||
|
|
||||||
memset(mock_parts, 0, sizeof(mock_parts));
|
memset(mock_parts, 0, sizeof(mock_parts));
|
||||||
mock_parts[0].start = 100;
|
mock_parts[0].start = 100;
|
||||||
mock_parts[0].size = 150; /* 75 KB */
|
mock_parts[0].size = 150; /* 75 KB */
|
||||||
@@ -287,6 +293,13 @@ int VerifyData(const uint8_t *data, uint64_t size, const VbSignature *sig,
|
|||||||
return VBERROR_SUCCESS;
|
return VBERROR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t* DigestBuf(const uint8_t* buf, uint64_t len, int sig_algorithm)
|
||||||
|
{
|
||||||
|
uint8_t *d = VbExMalloc(sizeof(mock_digest));
|
||||||
|
|
||||||
|
memcpy(d, mock_digest, sizeof(mock_digest));
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test reading/writing GPT
|
* Test reading/writing GPT
|
||||||
@@ -640,6 +653,14 @@ static void LoadKernelTest(void)
|
|||||||
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
|
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
|
||||||
"Fail key block dev sig");
|
"Fail key block dev sig");
|
||||||
|
|
||||||
|
ResetMocks();
|
||||||
|
lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
|
||||||
|
lkp.fwmp = &fwmp;
|
||||||
|
fwmp.flags |= FWMP_DEV_ENABLE_OFFICIAL_ONLY;
|
||||||
|
key_block_verify_fail = 1;
|
||||||
|
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
|
||||||
|
"Fail key block dev sig fwmp");
|
||||||
|
|
||||||
/* Check key block flag mismatches */
|
/* Check key block flag mismatches */
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
kbh.key_block_flags =
|
kbh.key_block_flags =
|
||||||
@@ -725,6 +746,22 @@ static void LoadKernelTest(void)
|
|||||||
lkp.boot_flags |= BOOT_FLAG_RECOVERY;
|
lkp.boot_flags |= BOOT_FLAG_RECOVERY;
|
||||||
TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode");
|
TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Kernel version ignored in rec mode");
|
||||||
|
|
||||||
|
/* Check developer key hash - bad */
|
||||||
|
ResetMocks();
|
||||||
|
lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
|
||||||
|
lkp.fwmp = &fwmp;
|
||||||
|
fwmp.flags |= FWMP_DEV_USE_KEY_HASH;
|
||||||
|
fwmp.dev_key_hash[0]++;
|
||||||
|
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
|
||||||
|
"Fail key block dev fwmp hash");
|
||||||
|
|
||||||
|
/* Check developer key hash - good */
|
||||||
|
ResetMocks();
|
||||||
|
lkp.boot_flags |= BOOT_FLAG_DEVELOPER;
|
||||||
|
lkp.fwmp = &fwmp;
|
||||||
|
fwmp.flags |= FWMP_DEV_USE_KEY_HASH;
|
||||||
|
TEST_EQ(LoadKernel(&lkp, &cparams), 0, "Good key block dev fwmp hash");
|
||||||
|
|
||||||
ResetMocks();
|
ResetMocks();
|
||||||
kph.preamble_size |= 0x07;
|
kph.preamble_size |= 0x07;
|
||||||
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
|
TEST_EQ(LoadKernel(&lkp, &cparams), VBERROR_INVALID_KERNEL_FOUND,
|
||||||
|
|||||||
Reference in New Issue
Block a user