diff options
author | Daisuke Nojiri <dnojiri@chromium.org> | 2017-07-07 09:49:36 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-07-13 19:45:57 -0700 |
commit | 4ec4975d90713b58557beca7ed2a94745d7476e3 (patch) | |
tree | b6f5cf7601f271944de4793cfd2392b5954659e5 /common | |
parent | 7630636a0fe8ceb2dbba2b175564a17900d175cf (diff) | |
download | chrome-ec-4ec4975d90713b58557beca7ed2a94745d7476e3.tar.gz |
vboot: Move common code under common/vboot
This patch moves the code which can be shared with other data
verification schemes (e.g. RWSIG) under common/vboot. It also
adds unit tests for it.
BUG=b:38462249
BRANCH=none
TEST=make run-vboot. Verify verification succeeds on Fizz.
Change-Id: Icab4d96dd2c154a12b01c41ebe9b46286b4b590e
Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/563463
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'common')
-rw-r--r-- | common/build.mk | 5 | ||||
-rw-r--r-- | common/vboot/common.c | 60 | ||||
-rw-r--r-- | common/vboot/vb21_lib.c | 44 | ||||
-rw-r--r-- | common/vboot/vboot.c (renamed from common/vboot.c) | 105 |
4 files changed, 119 insertions, 95 deletions
diff --git a/common/build.mk b/common/build.mk index 7907a87e30..9ceef96bc1 100644 --- a/common/build.mk +++ b/common/build.mk @@ -87,7 +87,8 @@ common-$(CONFIG_PWM_KBLIGHT)+=pwm_kblight.o common-$(CONFIG_RMA_AUTH)+=rma_auth.o common-$(CONFIG_RSA)+=rsa.o common-$(CONFIG_ROLLBACK)+=rollback.o -common-$(CONFIG_RWSIG)+=rwsig.o +common-$(CONFIG_RWSIG)+=rwsig.o vboot/common.o +common-$(CONFIG_RWSIG_TYPE_RWSIG)+=vboot/vb21_lib.o common-$(CONFIG_MATH_UTIL)+=math_util.o common-$(CONFIG_SHA1)+= sha1.o common-$(CONFIG_SHA256)+=sha256.o @@ -112,7 +113,7 @@ common-$(CONFIG_USB_POWER_DELIVERY)+=usb_pd_protocol.o usb_pd_policy.o common-$(CONFIG_USB_PD_LOGGING)+=pd_log.o common-$(CONFIG_USB_PD_TCPC)+=usb_pd_tcpc.o common-$(CONFIG_USB_UPDATE)+=usb_update.o update_fw.o -common-$(CONFIG_VBOOT_EC)+=vboot.o +common-$(CONFIG_VBOOT_EC)+=vboot/vboot.o common-$(CONFIG_VBOOT_HASH)+=sha256.o vboot_hash.o common-$(CONFIG_VSTORE)+=vstore.o common-$(CONFIG_WIRELESS)+=wireless.o diff --git a/common/vboot/common.c b/common/vboot/common.c new file mode 100644 index 0000000000..3a75a297e6 --- /dev/null +++ b/common/vboot/common.c @@ -0,0 +1,60 @@ +/* Copyright 2017 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. + */ + +#include "common.h" +#include "console.h" +#include "rsa.h" +#include "sha256.h" +#include "shared_mem.h" +#include "vboot.h" + +#define CPRINTS(format, args...) cprints(CC_VBOOT, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_VBOOT, format, ## args) + +int vboot_is_padding_valid(const uint8_t *data, uint32_t start, uint32_t end) +{ + const uint32_t *data32 = (const uint32_t *)data; + int i; + + if (start > end) + return EC_ERROR_INVAL; + + if (start % 4 || end % 4) + return EC_ERROR_INVAL; + + for (i = start / 4; i < end / 4; i++) { + if (data32[i] != 0xffffffff) + return EC_ERROR_INVAL; + } + + return EC_SUCCESS; +} + +int vboot_verify(const uint8_t *data, int len, + const struct rsa_public_key *key, const uint8_t *sig) +{ + struct sha256_ctx ctx; + uint8_t *hash; + uint32_t *workbuf; + int err = EC_SUCCESS; + + if (shared_mem_acquire(3 * RSANUMBYTES, (char **)&workbuf)) { + CPRINTS("Failed to allocate memory"); + return EC_ERROR_UNKNOWN; + } + + /* Compute hash of the RW firmware */ + SHA256_init(&ctx); + SHA256_update(&ctx, data, len); + hash = SHA256_final(&ctx); + + /* Verify the data */ + if (rsa_verify(key, sig, hash, workbuf) != 1) + err = EC_ERROR_INVAL; + + shared_mem_release(workbuf); + + return err; +} diff --git a/common/vboot/vb21_lib.c b/common/vboot/vb21_lib.c new file mode 100644 index 0000000000..11242a3038 --- /dev/null +++ b/common/vboot/vb21_lib.c @@ -0,0 +1,44 @@ +/* Copyright 2017 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. + */ + +/* + * Common utility APIs for vboot 2.1 + */ + +#include "common.h" +#include "rsa.h" +#include "rwsig.h" +#include "vb21_struct.h" +#include "vboot.h" + +int vb21_is_packed_key_valid(const struct vb21_packed_key *key) +{ + if (key->c.magic != VB21_MAGIC_PACKED_KEY) + return EC_ERROR_INVAL; + if (key->key_size != sizeof(struct rsa_public_key)) + return EC_ERROR_INVAL; + return EC_SUCCESS; +} + +int vb21_is_signature_valid(const struct vb21_signature *sig, + const struct vb21_packed_key *key) +{ + if (sig->c.magic != VB21_MAGIC_SIGNATURE) + return EC_ERROR_INVAL; + if (sig->sig_size != RSANUMBYTES) + return EC_ERROR_INVAL; + if (key->sig_alg != sig->sig_alg) + return EC_ERROR_INVAL; + if (key->hash_alg != sig->hash_alg) + return EC_ERROR_INVAL; + /* Sanity check signature offset and data size. */ + if (sig->sig_offset < sizeof(*sig)) + return EC_ERROR_INVAL; + if (sig->sig_offset + RSANUMBYTES > CONFIG_RW_SIG_SIZE) + return EC_ERROR_INVAL; + if (sig->data_size > CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) + return EC_ERROR_INVAL; + return EC_SUCCESS; +} diff --git a/common/vboot.c b/common/vboot/vboot.c index 1e92572c5b..27c57b27c2 100644 --- a/common/vboot.c +++ b/common/vboot/vboot.c @@ -22,6 +22,7 @@ #include "vb21_struct.h" #define CPRINTS(format, args...) cprints(CC_VBOOT, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_VBOOT, format, ## args) enum vboot_ec_slot { VBOOT_EC_SLOT_A, @@ -47,93 +48,14 @@ static int is_low_power_ap_boot_supported(void) return 0; } -static int is_vb21_packed_key_valid(const struct vb21_packed_key *key) -{ - if (key->c.magic != VB21_MAGIC_PACKED_KEY) - return EC_ERROR_INVAL; - if (key->key_size != sizeof(struct rsa_public_key)) - return EC_ERROR_INVAL; - return EC_SUCCESS; -} - -static int is_vb21_signature_valid(const struct vb21_signature *sig, - const struct vb21_packed_key *key) -{ - if (sig->c.magic != VB21_MAGIC_SIGNATURE) - return EC_ERROR_INVAL; - if (sig->sig_size != RSANUMBYTES) - return EC_ERROR_INVAL; - if (key->sig_alg != sig->sig_alg) - return EC_ERROR_INVAL; - if (key->hash_alg != sig->hash_alg) - return EC_ERROR_INVAL; - /* Sanity check signature offset and data size. */ - if (sig->sig_offset < sizeof(*sig)) - return EC_ERROR_INVAL; - if (sig->sig_offset + RSANUMBYTES > CONFIG_RW_SIG_SIZE) - return EC_ERROR_INVAL; - if (sig->data_size > CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE) - return EC_ERROR_INVAL; - return EC_SUCCESS; -} - -static int is_padding_valid(const uint8_t *data, unsigned int start, int len) -{ - const uint32_t *data32 = (const uint32_t *)data; - int i; - - if (len < 0) - return EC_ERROR_INVAL; - - if ((start % 4) != 0 || (len % 4) != 0) - return EC_ERROR_INVAL; - - for (i = start/4; i < len/4; i++) { - if (data32[i] != 0xffffffff) - return EC_ERROR_INVAL; - } - - return EC_SUCCESS; -} - -static int vboot_verify(const uint8_t *data, int len, - const struct rsa_public_key *key, const uint8_t *sig) -{ - struct sha256_ctx ctx; - uint8_t *hash; - uint32_t *workbuf; - int err = EC_SUCCESS; - - if (shared_mem_acquire(3 * RSANUMBYTES, (char **)&workbuf)) { - CPRINTS("Failed to allocate memory"); - return EC_ERROR_UNKNOWN; - } - - /* Compute hash of the RW firmware */ - SHA256_init(&ctx); - SHA256_update(&ctx, data, len); - hash = SHA256_final(&ctx); - - /* Verify the data */ - if (rsa_verify(key, sig, hash, workbuf) != 1) { - CPRINTS("Invalid data"); - err = EC_ERROR_INVAL; - } - - shared_mem_release(workbuf); - - return err; -} - static int verify_slot(int slot) { - const uint8_t *data; const struct vb21_packed_key *vb21_key; const struct vb21_signature *vb21_sig; const struct rsa_public_key *key; const uint8_t *sig; + const uint8_t *data; int len; - int rv = EC_ERROR_INVAL; CPRINTS("Verifying RW_%c", slot == VBOOT_EC_SLOT_A ? 'A' : 'B'); @@ -141,9 +63,9 @@ static int verify_slot(int slot) CONFIG_MAPPED_STORAGE_BASE + CONFIG_EC_PROTECTED_STORAGE_OFF + CONFIG_RO_PUBKEY_STORAGE_OFF); - if (is_vb21_packed_key_valid(vb21_key)) { + if (vb21_is_packed_key_valid(vb21_key)) { CPRINTS("Invalid key"); - goto exit; + return EC_ERROR_INVAL; } key = (const struct rsa_public_key *) ((const uint8_t *)vb21_key + vb21_key->key_offset); @@ -166,28 +88,25 @@ static int verify_slot(int slot) CONFIG_RW_B_SIGN_STORAGE_OFF); } - if (is_vb21_signature_valid(vb21_sig, vb21_key)) { + if (vb21_is_signature_valid(vb21_sig, vb21_key)) { CPRINTS("Invalid signature"); - goto exit; + return EC_ERROR_INVAL; } sig = (const uint8_t *)vb21_sig + vb21_sig->sig_offset; len = vb21_sig->data_size; - if (is_padding_valid(data, len, - CONFIG_RW_SIZE - len - CONFIG_RW_SIG_SIZE)) { + if (vboot_is_padding_valid(data, len, + CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE)) { CPRINTS("Invalid padding"); - goto exit; + return EC_ERROR_INVAL; } if (vboot_verify(data, len, key, sig)) { CPRINTS("Invalid data"); - goto exit; + return EC_ERROR_INVAL; } - rv = EC_SUCCESS; - -exit: - return rv; + return EC_SUCCESS; } static int verify_and_jump(void) @@ -238,7 +157,7 @@ static int is_manual_recovery(void) return host_get_events() & EC_HOST_EVENT_KEYBOARD_RECOVERY; } -void vboot_ec(void) +void vboot_main(void) { int port = charge_manager_get_active_charge_port(); |