summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/lib/vboot_api_kernel.c251
-rw-r--r--tests/vboot_api_kernel3_tests.c38
2 files changed, 101 insertions, 188 deletions
diff --git a/firmware/lib/vboot_api_kernel.c b/firmware/lib/vboot_api_kernel.c
index 5adeac41..90703a90 100644
--- a/firmware/lib/vboot_api_kernel.c
+++ b/firmware/lib/vboot_api_kernel.c
@@ -714,11 +714,11 @@ static VbError_t EcUpdateImage(int devidx, VbCommonParams *cparams,
(VbSharedDataHeader *)cparams->shared_data_blob;
int rv;
int hash_size;
+ int ec_hash_size;
const uint8_t *hash = NULL;
const uint8_t *expected = NULL;
const uint8_t *ec_hash = NULL;
int expected_size;
- uint8_t expected_hash[SHA256_DIGEST_SIZE];
int i;
int rw_request = select != VB_SELECT_FIRMWARE_READONLY;
@@ -727,202 +727,141 @@ static VbError_t EcUpdateImage(int devidx, VbCommonParams *cparams,
"Check for %s update\n", rw_request ? "RW" : "RO"));
/* Get current EC hash. */
- rv = VbExEcHashImage(devidx, select, &ec_hash, &hash_size);
-
+ rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
if (rv) {
VBDEBUG(("EcUpdateImage() - "
"VbExEcHashImage() returned %d\n", rv));
VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
- if (hash_size != SHA256_DIGEST_SIZE) {
- VBDEBUG(("EcUpdateImage() - "
- "VbExEcHashImage() says size %d, not %d\n",
- hash_size, SHA256_DIGEST_SIZE));
- VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
- return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- }
- VBDEBUG(("EC-%s hash:", rw_request ? "RW" : "RO"));
- for (i = 0; i < SHA256_DIGEST_SIZE; i++)
+ VBDEBUG(("EC-%s hash: ", rw_request ? "RW" : "RO"));
+ for (i = 0; i < ec_hash_size; i++)
VBDEBUG(("%02x",ec_hash[i]));
VBDEBUG(("\n"));
/* Get expected EC hash. */
rv = VbExEcGetExpectedImageHash(devidx, select, &hash, &hash_size);
-
- if (rv == VBERROR_EC_GET_EXPECTED_HASH_FROM_IMAGE) {
- /*
- * BIOS has verified EC image but doesn't have a precomputed
- * hash for it, so we must compute the hash ourselves.
- */
- hash = NULL;
- } else if (rv) {
+ if (rv) {
VBDEBUG(("EcUpdateImage() - "
"VbExEcGetExpectedImageHash() returned %d\n", rv));
VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_HASH);
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- } else if (hash_size != SHA256_DIGEST_SIZE) {
+ }
+ if (ec_hash_size != hash_size) {
VBDEBUG(("EcUpdateImage() - "
- "VbExEcGetExpectedImageHash() says size %d, not %d\n",
- hash_size, SHA256_DIGEST_SIZE));
- VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_HASH);
+ "EC uses %d-byte hash, but AP-RW contains %d bytes\n",
+ ec_hash_size, hash_size));
+ VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- } else {
- VBDEBUG(("Expected hash:"));
- for (i = 0; i < SHA256_DIGEST_SIZE; i++)
- VBDEBUG(("%02x", hash[i]));
- VBDEBUG(("\n"));
- *need_update = SafeMemcmp(ec_hash, hash, SHA256_DIGEST_SIZE);
}
- /*
- * Get expected EC image if we're sure we need to update (because the
- * expected hash didn't match the EC) or we still don't know (because
- * there was no expected hash and we need the image to compute one
- * ourselves).
- */
- if (*need_update || !hash) {
- /* Get expected EC image */
- rv = VbExEcGetExpectedImage(devidx, select, &expected,
- &expected_size);
- if (rv) {
- VBDEBUG(("EcUpdateImage() - "
- "VbExEcGetExpectedImage() returned %d\n", rv));
- VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_IMAGE);
- return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- }
- VBDEBUG(("EcUpdateImage() - image len = %d\n", expected_size));
-
- /* Hash expected image */
- internal_SHA256(expected, expected_size, expected_hash);
- VBDEBUG(("Computed hash of expected image:"));
- for (i = 0; i < SHA256_DIGEST_SIZE; i++)
- VBDEBUG(("%02x", expected_hash[i]));
- VBDEBUG(("\n"));
- }
+ VBDEBUG(("Expected hash: "));
+ for (i = 0; i < hash_size; i++)
+ VBDEBUG(("%02x", hash[i]));
+ VBDEBUG(("\n"));
+ *need_update = SafeMemcmp(ec_hash, hash, hash_size);
- if (!hash) {
- /*
- * BIOS didn't have expected EC hash, so check if we need
- * update by comparing EC hash to the one we just computed.
- */
- *need_update = SafeMemcmp(ec_hash, expected_hash,
- SHA256_DIGEST_SIZE);
- } else if (*need_update && SafeMemcmp(hash, expected_hash,
- SHA256_DIGEST_SIZE)) {
- /*
- * We need to update, but the expected EC image doesn't match
- * the expected EC hash we were given.
- */
+ if (!*need_update)
+ return VBERROR_SUCCESS;
+
+ /* Get expected EC image */
+ rv = VbExEcGetExpectedImage(devidx, select, &expected, &expected_size);
+ if (rv) {
VBDEBUG(("EcUpdateImage() - "
"VbExEcGetExpectedImage() returned %d\n", rv));
- VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_MISMATCH);
+ VbSetRecoveryRequest(VBNV_RECOVERY_EC_EXPECTED_IMAGE);
return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
+ VBDEBUG(("EcUpdateImage() - image len = %d\n", expected_size));
if (in_rw && rw_request) {
- if (*need_update) {
- /*
- * Check if BIOS should also load VGA Option ROM when
- * rebooting to save another reboot if possible.
- */
- if ((shared->flags & VBSD_EC_SLOW_UPDATE) &&
- (shared->flags & VBSD_OPROM_MATTERS) &&
- !(shared->flags & VBSD_OPROM_LOADED)) {
- VBDEBUG(("EcUpdateImage() - Reboot to "
- "load VGA Option ROM\n"));
- VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
- }
-
- /*
- * EC is running the wrong RW image. Reboot the EC to
- * RO so we can update it on the next boot.
- */
- VBDEBUG(("EcUpdateImage() - "
- "in RW, need to update RW, so reboot\n"));
- return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
+ /*
+ * Check if BIOS should also load VGA Option ROM when
+ * rebooting to save another reboot if possible.
+ */
+ if ((shared->flags & VBSD_EC_SLOW_UPDATE) &&
+ (shared->flags & VBSD_OPROM_MATTERS) &&
+ !(shared->flags & VBSD_OPROM_LOADED)) {
+ VBDEBUG(("EcUpdateImage() - Reboot to "
+ "load VGA Option ROM\n"));
+ VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
}
- VBDEBUG(("EcUpdateImage() in EC-RW and it matches\n"));
- return VBERROR_SUCCESS;
+ /*
+ * EC is running the wrong RW image. Reboot the EC to
+ * RO so we can update it on the next boot.
+ */
+ VBDEBUG(("EcUpdateImage() - "
+ "in RW, need to update RW, so reboot\n"));
+ return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
- /* Update EC if necessary */
-
- if (*need_update) {
- VBDEBUG(("EcUpdateImage() updating EC-%s...\n",
- rw_request ? "RW" : "RO"));
+ VBDEBUG(("EcUpdateImage() updating EC-%s...\n",
+ rw_request ? "RW" : "RO"));
- if (shared->flags & VBSD_EC_SLOW_UPDATE) {
- VBDEBUG(("EcUpdateImage() - "
- "EC is slow. Show WAIT screen.\n"));
+ if (shared->flags & VBSD_EC_SLOW_UPDATE) {
+ VBDEBUG(("EcUpdateImage() - EC is slow. Show WAIT screen.\n"));
- /* Ensure the VGA Option ROM is loaded */
- if ((shared->flags & VBSD_OPROM_MATTERS) &&
- !(shared->flags & VBSD_OPROM_LOADED)) {
- VBDEBUG(("EcUpdateImage() - Reboot to "
- "load VGA Option ROM\n"));
- VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
- return VBERROR_VGA_OPROM_MISMATCH;
- }
-
- VbDisplayScreen(cparams, VB_SCREEN_WAIT, 0, &vnc);
+ /* Ensure the VGA Option ROM is loaded */
+ if ((shared->flags & VBSD_OPROM_MATTERS) &&
+ !(shared->flags & VBSD_OPROM_LOADED)) {
+ VBDEBUG(("EcUpdateImage() - Reboot to "
+ "load VGA Option ROM\n"));
+ VbNvSet(&vnc, VBNV_OPROM_NEEDED, 1);
+ return VBERROR_VGA_OPROM_MISMATCH;
}
- rv = VbExEcUpdateImage(devidx, select, expected, expected_size);
-
- if (rv != VBERROR_SUCCESS) {
- VBDEBUG(("EcUpdateImage() - "
- "VbExEcUpdateImage() returned %d\n", rv));
+ VbDisplayScreen(cparams, VB_SCREEN_WAIT, 0, &vnc);
+ }
- /*
- * The EC may know it needs a reboot. It may need to
- * unprotect the region before updating, or may need to
- * reboot after updating. Either way, it's not an error
- * requiring recovery mode.
- *
- * If we fail for any other reason, trigger recovery
- * mode.
- */
- if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
- VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
+ rv = VbExEcUpdateImage(devidx, select, expected, expected_size);
+ if (rv != VBERROR_SUCCESS) {
+ VBDEBUG(("EcUpdateImage() - "
+ "VbExEcUpdateImage() returned %d\n", rv));
- return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- }
+ /*
+ * The EC may know it needs a reboot. It may need to
+ * unprotect the region before updating, or may need to
+ * reboot after updating. Either way, it's not an error
+ * requiring recovery mode.
+ *
+ * If we fail for any other reason, trigger recovery
+ * mode.
+ */
+ if (rv != VBERROR_EC_REBOOT_TO_RO_REQUIRED)
+ VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
+ return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
/* Verify the EC was updated properly */
- if (*need_update) {
- /* Get current EC hash. */
- rv = VbExEcHashImage(devidx, select, &ec_hash, &hash_size);
-
- if (rv) {
- VBDEBUG(("EcUpdateImage() - "
- "VbExEcHashImage() returned %d\n", rv));
- VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
- return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- }
- if (hash_size != SHA256_DIGEST_SIZE) {
- VBDEBUG(("EcUpdateImage() - "
- "VbExEcHashImage() says size %d, not %d\n",
- hash_size, SHA256_DIGEST_SIZE));
- VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
- return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- }
- VBDEBUG(("Updated EC-%s hash:", rw_request ? "RW" : "RO"));
- for (i = 0; i < SHA256_DIGEST_SIZE; i++)
- VBDEBUG(("%02x",ec_hash[i]));
- VBDEBUG(("\n"));
-
- if (SafeMemcmp(ec_hash, hash, SHA256_DIGEST_SIZE)){
- VBDEBUG(("EcUpdateImage() - "
- "Failed to update EC-%s\n", rw_request ?
- "RW" : "RO"));
- VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
- return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
- }
+ rv = VbExEcHashImage(devidx, select, &ec_hash, &ec_hash_size);
+ if (rv) {
+ VBDEBUG(("EcUpdateImage() - "
+ "VbExEcHashImage() returned %d\n", rv));
+ VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_FAILED);
+ return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
}
+ if (hash_size != ec_hash_size) {
+ VBDEBUG(("EcUpdateImage() - "
+ "VbExEcHashImage() says size %d, not %d\n",
+ ec_hash_size, hash_size));
+ VbSetRecoveryRequest(VBNV_RECOVERY_EC_HASH_SIZE);
+ return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
+ }
+ VBDEBUG(("Updated EC-%s hash: ", rw_request ? "RW" : "RO"));
+ for (i = 0; i < ec_hash_size; i++)
+ VBDEBUG(("%02x",ec_hash[i]));
+ VBDEBUG(("\n"));
+
+ if (SafeMemcmp(ec_hash, hash, hash_size)){
+ VBDEBUG(("EcUpdateImage() - "
+ "Failed to update EC-%s\n", rw_request ?
+ "RW" : "RO"));
+ VbSetRecoveryRequest(VBNV_RECOVERY_EC_UPDATE);
+ return VBERROR_EC_REBOOT_TO_RO_REQUIRED;
+ }
+
return VBERROR_SUCCESS;
}
diff --git a/tests/vboot_api_kernel3_tests.c b/tests/vboot_api_kernel3_tests.c
index d6f740b6..6ca58f21 100644
--- a/tests/vboot_api_kernel3_tests.c
+++ b/tests/vboot_api_kernel3_tests.c
@@ -47,7 +47,6 @@ static int mock_ec_rw_hash_size;
static uint8_t want_ec_hash[32];
static uint8_t update_hash;
static int want_ec_hash_size;
-static uint8_t mock_sha[32];
static uint32_t screens_displayed[8];
static uint32_t screens_count = 0;
@@ -104,9 +103,6 @@ static void ResetMocks(void)
update_hash = 42;
- Memset(mock_sha, 0, sizeof(want_ec_hash));
- mock_sha[0] = 42;
-
// TODO: ensure these are actually needed
Memset(screens_displayed, 0, sizeof(screens_displayed));
@@ -182,16 +178,7 @@ VbError_t VbExEcGetExpectedImageHash(int devidx, enum VbSelectFirmware_t select,
*hash = want_ec_hash;
*hash_size = want_ec_hash_size;
- if (want_ec_hash_size == -1)
- return VBERROR_EC_GET_EXPECTED_HASH_FROM_IMAGE;
- else
- return want_ec_hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED;
-}
-
-uint8_t *internal_SHA256(const uint8_t *data, uint64_t len, uint8_t *digest)
-{
- Memcpy(digest, mock_sha, sizeof(mock_sha));
- return digest;
+ return want_ec_hash_size ? VBERROR_SUCCESS : VBERROR_SIMULATED;
}
VbError_t VbExEcUpdateImage(int devidx, enum VbSelectFirmware_t select,
@@ -296,30 +283,17 @@ static void VbSoftwareSyncTest(void)
ResetMocks();
want_ec_hash_size = 16;
test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
- VBNV_RECOVERY_EC_EXPECTED_HASH,
- "Bad precalculated hash size");
+ VBNV_RECOVERY_EC_HASH_SIZE,
+ "Hash size mismatch");
ResetMocks();
- mock_in_rw = 1;
- want_ec_hash_size = -1;
- test_ssync(0, 0, "No precomputed hash");
-
- ResetMocks();
- want_ec_hash_size = -1;
- get_expected_retval = VBERROR_SIMULATED;
- test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
- VBNV_RECOVERY_EC_EXPECTED_IMAGE, "Can't fetch image");
+ want_ec_hash_size = 4;
+ mock_ec_rw_hash_size = 4;
+ test_ssync(0, 0, "Custom hash size");
/* Updates required */
ResetMocks();
mock_in_rw = 1;
- want_ec_hash[0]++;
- test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
- VBNV_RECOVERY_EC_HASH_MISMATCH,
- "Precalculated hash mismatch");
-
- ResetMocks();
- mock_in_rw = 1;
mock_ec_rw_hash[0]++;
test_ssync(VBERROR_EC_REBOOT_TO_RO_REQUIRED,
0, "Pending update needs reboot");