summaryrefslogtreecommitdiff
path: root/common/rwsig.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/rwsig.c')
-rw-r--r--common/rwsig.c336
1 files changed, 0 insertions, 336 deletions
diff --git a/common/rwsig.c b/common/rwsig.c
deleted file mode 100644
index 418a69c1a1..0000000000
--- a/common/rwsig.c
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Copyright 2014 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/*
- * Implementation of the RW firmware signature verification and jump.
- */
-
-#include "console.h"
-#include "cros_version.h"
-#include "ec_commands.h"
-#include "flash.h"
-#include "host_command.h"
-#include "rollback.h"
-#include "rsa.h"
-#include "rwsig.h"
-#include "sha256.h"
-#include "shared_mem.h"
-#include "system.h"
-#include "task.h"
-#include "usb_pd.h"
-#include "util.h"
-#include "vb21_struct.h"
-#include "vboot.h"
-
-/* Console output macros */
-#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
-
-#if !defined(CONFIG_MAPPED_STORAGE)
-#error rwsig implementation assumes mem-mapped storage.
-#endif
-
-/* RW firmware reset vector */
-static uint32_t * const rw_rst =
- (uint32_t *)(CONFIG_PROGRAM_MEMORY_BASE + CONFIG_RW_MEM_OFF + 4);
-
-
-void rwsig_jump_now(void)
-{
- /* Protect all flash before jumping to RW. */
-
- /* This may do nothing if WP is not enabled, RO is not protected. */
- crec_flash_set_protect(EC_FLASH_PROTECT_ALL_NOW, -1);
-
- /*
- * For chips that does not support EC_FLASH_PROTECT_ALL_NOW, use
- * EC_FLASH_PROTECT_ALL_AT_BOOT.
- */
- if (system_is_locked() &&
- !(crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)) {
- crec_flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, -1);
-
- if (!(crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW) &&
- crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_AT_BOOT) {
- /*
- * If flash protection is still not enabled (some chips
- * may be able to enable it immediately), reboot.
- */
- cflush();
- system_reset(SYSTEM_RESET_HARD |
- SYSTEM_RESET_PRESERVE_FLAGS);
- }
- }
-
- /* When system is locked, only boot to RW if all flash is protected. */
- if (!system_is_locked() ||
- crec_flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
- system_run_image_copy(EC_IMAGE_RW);
-}
-
-/*
- * Check that memory between rwdata[start] and rwdata[len-1] is filled
- * with ones. data, start and len must be aligned on 4-byte boundary.
- */
-static int check_padding(const uint8_t *data,
- unsigned int start, unsigned int len)
-{
- unsigned int i;
- const uint32_t *data32 = (const uint32_t *)data;
-
- if ((start % 4) != 0 || (len % 4) != 0)
- return 0;
-
- for (i = start/4; i < len/4; i++) {
- if (data32[i] != 0xffffffff)
- return 0;
- }
-
- return 1;
-}
-
-int rwsig_check_signature(void)
-{
- struct sha256_ctx ctx;
- int res;
- const struct rsa_public_key *key;
- const uint8_t *sig;
- uint8_t *hash;
- uint32_t *rsa_workbuf = NULL;
- const uint8_t *rwdata = (uint8_t *)CONFIG_PROGRAM_MEMORY_BASE
- + CONFIG_RW_MEM_OFF;
- int good = 0;
-
- unsigned int rwlen;
-#ifdef CONFIG_RWSIG_TYPE_RWSIG
- const struct vb21_packed_key *vb21_key;
- const struct vb21_signature *vb21_sig;
-#endif
-#ifdef CONFIG_ROLLBACK
- int32_t rw_rollback_version;
- int32_t min_rollback_version;
-#endif
-
- /* Check if we have a RW firmware flashed */
- if (*rw_rst == 0xffffffff)
- goto out;
-
- CPRINTS("Verifying RW image...");
-
-#ifdef CONFIG_ROLLBACK
- rw_rollback_version = system_get_rollback_version(EC_IMAGE_RW);
- min_rollback_version = rollback_get_minimum_version();
-
- if (rw_rollback_version < 0 || min_rollback_version < 0 ||
- rw_rollback_version < min_rollback_version) {
- CPRINTS("Rollback error (%d < %d)",
- rw_rollback_version, min_rollback_version);
- goto out;
- }
-#endif
-
- /* Large buffer for RSA computation : could be re-use afterwards... */
- res = SHARED_MEM_ACQUIRE_CHECK(3 * RSANUMBYTES, (char **)&rsa_workbuf);
- if (res) {
- CPRINTS("No memory for RW verification");
- goto out;
- }
-
-#ifdef CONFIG_RWSIG_TYPE_USBPD1
- key = (const struct rsa_public_key *)CONFIG_RO_PUBKEY_ADDR;
- sig = (const uint8_t *)CONFIG_RW_SIG_ADDR;
- rwlen = CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE;
-#elif defined(CONFIG_RWSIG_TYPE_RWSIG)
- vb21_key = vb21_get_packed_key();
- vb21_sig = (const struct vb21_signature *)CONFIG_RW_SIG_ADDR;
-
- if (vb21_key->c.magic != VB21_MAGIC_PACKED_KEY ||
- vb21_key->key_size != sizeof(struct rsa_public_key)) {
- CPRINTS("Invalid key.");
- goto out;
- }
-
- key = (const struct rsa_public_key *)
- ((const uint8_t *)vb21_key + vb21_key->key_offset);
-
- /*
- * TODO(crbug.com/690773): We could verify other parameters such
- * as sig_alg/hash_alg actually matches what we build for.
- */
- if (vb21_sig->c.magic != VB21_MAGIC_SIGNATURE ||
- vb21_sig->sig_size != RSANUMBYTES ||
- vb21_key->sig_alg != vb21_sig->sig_alg ||
- vb21_key->hash_alg != vb21_sig->hash_alg ||
- /* Validity check signature offset and data size. */
- vb21_sig->sig_offset < sizeof(vb21_sig) ||
- (vb21_sig->sig_offset + RSANUMBYTES) > CONFIG_RW_SIG_SIZE ||
- vb21_sig->data_size > (CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE)) {
- CPRINTS("Invalid signature.");
- goto out;
- }
-
- sig = (const uint8_t *)vb21_sig + vb21_sig->sig_offset;
- rwlen = vb21_sig->data_size;
-#endif
-
- /*
- * Check that unverified RW region is actually filled with ones.
- */
- good = check_padding(rwdata, rwlen,
- CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE);
- if (!good) {
- CPRINTS("Invalid padding.");
- goto out;
- }
-
- /* SHA-256 Hash of the RW firmware */
- SHA256_init(&ctx);
- SHA256_update(&ctx, rwdata, rwlen);
- hash = SHA256_final(&ctx);
-
- good = rsa_verify(key, sig, hash, rsa_workbuf);
- if (!good)
- goto out;
-
-#ifdef CONFIG_ROLLBACK
- /*
- * Signature verified: we know that rw_rollback_version is valid, check
- * if rollback information should be updated.
- *
- * If the RW region can be protected independently
- * (CONFIG_FLASH_PROTECT_RW is defined), and system is locked, we only
- * increment the rollback if RW is currently protected.
- *
- * Otherwise, we immediately increment the rollback version.
- */
- if (rw_rollback_version != min_rollback_version
-#ifdef CONFIG_FLASH_PROTECT_RW
- && ((!system_is_locked() ||
- crec_flash_get_protect() &
- EC_FLASH_PROTECT_RW_NOW))
-#endif
- ) {
- /*
- * This will fail if the rollback block is protected (RW image
- * will unprotect that block later on).
- */
- int ret = rollback_update_version(rw_rollback_version);
-
- if (ret == 0) {
- CPRINTS("Rollback updated to %d",
- rw_rollback_version);
- } else if (ret != EC_ERROR_ACCESS_DENIED) {
- CPRINTS("Rollback update error %d", ret);
- good = 0;
- }
- }
-#endif
-out:
- CPRINTS("RW verify %s", good ? "OK" : "FAILED");
-
- if (!good) {
- pd_log_event(PD_EVENT_ACC_RW_FAIL, 0, 0, NULL);
- /* RW firmware is invalid : do not jump there */
- if (system_is_locked())
- system_disable_jump();
- }
- if (rsa_workbuf)
- shared_mem_release(rsa_workbuf);
-
- return good;
-}
-
-#ifdef HAS_TASK_RWSIG
-#define TASK_EVENT_ABORT TASK_EVENT_CUSTOM_BIT(0)
-#define TASK_EVENT_CONTINUE TASK_EVENT_CUSTOM_BIT(1)
-
-static enum rwsig_status rwsig_status;
-
-enum rwsig_status rwsig_get_status(void)
-{
- return rwsig_status;
-}
-
-void rwsig_abort(void)
-{
- task_set_event(TASK_ID_RWSIG, TASK_EVENT_ABORT);
-}
-
-void rwsig_continue(void)
-{
- task_set_event(TASK_ID_RWSIG, TASK_EVENT_CONTINUE);
-}
-
-void rwsig_task(void *u)
-{
- uint32_t evt;
-
- if (system_get_image_copy() != EC_IMAGE_RO)
- goto exit;
-
- /* Stay in RO if we were asked to when reset. */
- if (system_get_reset_flags() & EC_RESET_FLAG_STAY_IN_RO) {
- rwsig_status = RWSIG_ABORTED;
- goto exit;
- }
-
- rwsig_status = RWSIG_IN_PROGRESS;
- if (!rwsig_check_signature()) {
- rwsig_status = RWSIG_INVALID;
- goto exit;
- }
- rwsig_status = RWSIG_VALID;
-
- /* Jump to RW after a timeout */
- evt = task_wait_event(CONFIG_RWSIG_JUMP_TIMEOUT);
-
- /* Jump now if we timed out, or were told to continue. */
- if (evt == TASK_EVENT_TIMER || evt == TASK_EVENT_CONTINUE)
- rwsig_jump_now();
- else
- rwsig_status = RWSIG_ABORTED;
-
-exit:
- /* We're done, yield forever. */
- while (1)
- task_wait_event(-1);
-}
-
-enum ec_status rwsig_cmd_action(struct host_cmd_handler_args *args)
-{
- const struct ec_params_rwsig_action *p = args->params;
-
- switch (p->action) {
- case RWSIG_ACTION_ABORT:
- rwsig_abort();
- break;
- case RWSIG_ACTION_CONTINUE:
- rwsig_continue();
- break;
- default:
- return EC_RES_INVALID_PARAM;
- }
- args->response_size = 0;
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_RWSIG_ACTION,
- rwsig_cmd_action,
- EC_VER_MASK(0));
-
-#else /* !HAS_TASK_RWSIG */
-enum ec_status rwsig_cmd_check_status(struct host_cmd_handler_args *args)
-{
- struct ec_response_rwsig_check_status *r = args->response;
-
- memset(r, 0, sizeof(*r));
- r->status = rwsig_check_signature();
- args->response_size = sizeof(*r);
-
- return EC_RES_SUCCESS;
-}
-DECLARE_HOST_COMMAND(EC_CMD_RWSIG_CHECK_STATUS,
- rwsig_cmd_check_status,
- EC_VER_MASK(0));
-#endif