diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2014-11-13 08:28:50 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-12-01 20:30:46 +0000 |
commit | 902a07b5c8efa59e03e57b3c45f17fc1d17e3125 (patch) | |
tree | 74d3759bcc147a49ecefbc51e566860ecc1f4ac6 | |
parent | b41a0632db0abd010331b507cba4b472dd8e2fd8 (diff) | |
download | chrome-ec-902a07b5c8efa59e03e57b3c45f17fc1d17e3125.tar.gz |
Add RW firmware signature verification for common runtime
For accessories without software-sync mechanism, add the option to do a
RSA-based signature verification of the Read-Write firmware.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BRANCH=samus
BUG=chrome-os-partner:31192
TEST=enable the configuration on Fruitpie and see the RW firmware
validated and jump to. Tried with good and bad RW images.
Change-Id: I3c886c2cbe17ca9543e19bf8599061c3f9751d4f
Reviewed-on: https://chromium-review.googlesource.com/229594
Reviewed-by: Todd Broch <tbroch@chromium.org>
Commit-Queue: Todd Broch <tbroch@chromium.org>
Tested-by: Todd Broch <tbroch@chromium.org>
-rw-r--r-- | Makefile.rules | 2 | ||||
-rw-r--r-- | common/build.mk | 1 | ||||
-rw-r--r-- | common/main.c | 9 | ||||
-rw-r--r-- | common/rwsig.c | 72 | ||||
-rw-r--r-- | include/config.h | 6 | ||||
-rw-r--r-- | include/rsa.h | 2 |
6 files changed, 92 insertions, 0 deletions
diff --git a/Makefile.rules b/Makefile.rules index bdb5ab8635..27f0d73f70 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -215,6 +215,8 @@ $(out)/ec_date.h: $(filter-out $(out)/common/version.o,$(objs)) $(out)/gen_pub_key.h: $(PEM) $(call quiet,pubkey,PUBKEY ) +$(out)/common/rwsig.o: $(out)/gen_pub_key.h + $(build-utils): $(out)/%:$(build-srcs) $(call quiet,c_to_build,BUILDCC) diff --git a/common/build.mk b/common/build.mk index 97e270f8f7..3be3131f42 100644 --- a/common/build.mk +++ b/common/build.mk @@ -66,6 +66,7 @@ common-$(CONFIG_PSTORE)+=pstore_commands.o common-$(CONFIG_PWM)+=pwm.o common-$(CONFIG_PWM_KBLIGHT)+=pwm_kblight.o common-$(CONFIG_RSA)+=rsa.o +common-$(CONFIG_RWSIG)+=rwsig.o common-$(CONFIG_SHA1)+=sha1.o common-$(CONFIG_SHA256)+=sha256.o common-$(CONFIG_SMBUS)+= smbus.o diff --git a/common/main.c b/common/main.c index 269781f9f6..00bc19df4a 100644 --- a/common/main.c +++ b/common/main.c @@ -21,6 +21,7 @@ #ifdef CONFIG_MPU #include "mpu.h" #endif +#include "rsa.h" #include "system.h" #include "task.h" #include "timer.h" @@ -141,6 +142,14 @@ test_mockable int main(void) keyboard_scan_init(); #endif +#ifdef CONFIG_RWSIG + /* + * Check the RW firmware signature + * and eventually jump to it if it is good. + */ + check_rw_signature(); +#endif + /* Initialize the hook library. This calls HOOK_INIT hooks. */ hook_init(); diff --git a/common/rwsig.c b/common/rwsig.c new file mode 100644 index 0000000000..92b8d1838c --- /dev/null +++ b/common/rwsig.c @@ -0,0 +1,72 @@ +/* Copyright (c) 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 "rsa.h" +#include "sha256.h" +#include "shared_mem.h" +#include "system.h" +#include "util.h" + +/* Console output macros */ +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) + +/* Insert the RSA public key definition */ +const struct rsa_public_key pkey __attribute__((section(".rsa_pubkey"))) = +#include "gen_pub_key.h" + +/* The RSA signature is stored at the end of the RW firmware */ +static const void *rw_sig = (void *)CONFIG_FLASH_BASE + CONFIG_FW_RW_OFF + + CONFIG_FW_RW_SIZE - RSANUMBYTES; + +/* RW firmware reset vector */ +static uint32_t * const rw_rst = + (uint32_t *)(CONFIG_FLASH_BASE+CONFIG_FW_RW_OFF+4); + +void check_rw_signature(void) +{ + struct sha256_ctx ctx; + int good, res; + uint8_t *hash; + uint32_t *rsa_workbuf; + + /* Only the Read-Only firmware needs to do the signature check */ + if (system_get_image_copy() != SYSTEM_IMAGE_RO) + return; + + /* Check if we have a RW firmware flashed */ + if (*rw_rst == 0xffffffff) + return; + + /* Large buffer for RSA computation : could be re-use afterwards... */ + res = shared_mem_acquire(3 * RSANUMBYTES, (char **)&rsa_workbuf); + if (res) { + CPRINTS("No memory for RW verification"); + return; + } + + /* SHA-256 Hash of the RW firmware */ + SHA256_init(&ctx); + SHA256_update(&ctx, (void *)CONFIG_FLASH_BASE + CONFIG_FW_RW_OFF, + CONFIG_FW_RW_SIZE - RSANUMBYTES); + hash = SHA256_final(&ctx); + good = rsa_verify(&pkey, (void *)rw_sig, (void *)hash, rsa_workbuf); + if (good) { + CPRINTS("RW image verified\n"); + /* Jump to the RW firmware */ + system_run_image_copy(SYSTEM_IMAGE_RW); + } else { + CPRINTS("RSA verify FAILED\n"); + /* RW firmware is invalid : do not jump there */ + if (system_is_locked()) + system_disable_jump(); + } + shared_mem_release(rsa_workbuf); +} diff --git a/include/config.h b/include/config.h index c4b07090c1..67963d3e4e 100644 --- a/include/config.h +++ b/include/config.h @@ -898,6 +898,12 @@ #undef CONFIG_RSA /* + * Verify the RW firmware using the RSA signature. + * (for accessories without software sync) + */ +#undef CONFIG_RWSIG + +/* * If defined, the hash module will save its last computed hash when jumping * between EC images. */ diff --git a/include/rsa.h b/include/rsa.h index dbf00fa13f..9013e308a9 100644 --- a/include/rsa.h +++ b/include/rsa.h @@ -49,6 +49,8 @@ int rsa_verify(const struct rsa_public_key *key, const uint8_t *sha, uint32_t *workbuf32); +void check_rw_signature(void); + #endif /* !__ASSEMBLER__ */ #endif /* _INCLUDE_RSA_H */ |