summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2014-11-13 08:28:50 -0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-12-01 20:30:46 +0000
commit902a07b5c8efa59e03e57b3c45f17fc1d17e3125 (patch)
tree74d3759bcc147a49ecefbc51e566860ecc1f4ac6
parentb41a0632db0abd010331b507cba4b472dd8e2fd8 (diff)
downloadchrome-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.rules2
-rw-r--r--common/build.mk1
-rw-r--r--common/main.c9
-rw-r--r--common/rwsig.c72
-rw-r--r--include/config.h6
-rw-r--r--include/rsa.h2
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 */