summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2020-04-22 18:35:44 -0700
committerVadim Bendebury <vbendeb@chromium.org>2020-05-14 18:38:39 +0000
commitca83aee50469799a9b70b03ef6bd3fc1e86d6c38 (patch)
tree0ad6a589a259294c0f3cd341b3b5a027810a5a97
parent69a887265d737c628a3c55a03b923917cf1b471e (diff)
downloadchrome-ec-stabilize-13099.72.B-cr50_stab.tar.gz
The code which allows to read a section of AP or EC flash and calculate the section's SHA256 sum does not allow calculating the sum over multiple non-adjacent flash areas. This patch changes the implementation to allow calculations over more than one region. Initialization, calculation and reporting of the result become three separate API entries. The loop counting the number of the read flash chunks, is being simplified, a watchdog kick added to the brief loop interruptions, as it turns out that sleeping alone is not enough to prevent watchdog expiration when calculating hash over large SPI flash ranges. Also simplified prototypes for usb_spi_board_enable() and usb_spi_board_disable(). BUG=b:153764696 TEST=created an RO descriptor for the Atlas DUT and verified that 'gsctool -O' succeeds. Cq-Depend: chrome-internal:2939596 Signed-off-by: Vadim Bendebury <vbendeb@chromium.org> Change-Id: Iec7b8634c7c80ebc7600c5b708879eb322bc7fec Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2163569 Reviewed-by: Andrey Pronin <apronin@chromium.org>
-rw-r--r--board/cr50/usb_spi.c83
-rw-r--r--chip/g/usb_spi.c5
-rw-r--r--chip/g/usb_spi.h9
3 files changed, 64 insertions, 33 deletions
diff --git a/board/cr50/usb_spi.c b/board/cr50/usb_spi.c
index 66083de4b1..9e40690c1a 100644
--- a/board/cr50/usb_spi.c
+++ b/board/cr50/usb_spi.c
@@ -5,7 +5,6 @@
#include "byteorder.h"
#include "ccd_config.h"
-#include "cryptoc/sha256.h"
#include "console.h"
#include "dcrypto.h"
#include "extension.h"
@@ -21,6 +20,7 @@
#include "tpm_registers.h"
#include "tpm_vendor_cmds.h"
#include "usb_spi.h"
+#include "watchdog.h"
#define CPRINTS(format, args...) cprints(CC_USB, format, ## args)
@@ -229,10 +229,8 @@ static void disable_spi_pinmux(void)
/*****************************************************************************/
/* USB SPI methods */
-int usb_spi_board_enable(struct usb_spi_config const *config)
+int usb_spi_board_enable(int host)
{
- int host = config->state->enabled_host;
-
/* Make sure we're allowed to enable the requested device */
if (host == USB_SPI_EC) {
if (!ccd_is_cap_enabled(CCD_CAP_EC_FLASH)) {
@@ -269,7 +267,7 @@ int usb_spi_board_enable(struct usb_spi_config const *config)
return EC_SUCCESS;
}
-void usb_spi_board_disable(struct usb_spi_config const *config)
+void usb_spi_board_disable(void)
{
CPRINTS("%s", __func__);
@@ -336,7 +334,8 @@ int usb_spi_interface(struct usb_spi_config const *config,
*
* @return EC_SUCCESS, or non-zero if any error.
*/
-int spi_read_chunk(uint8_t *buf_usr, unsigned int offset, unsigned int bytes)
+static int spi_read_chunk(uint8_t *buf_usr, unsigned int offset,
+ unsigned int bytes)
{
uint8_t cmd[4];
@@ -580,51 +579,77 @@ static enum vendor_cmd_rc spi_hash_dump(uint8_t *dest, uint32_t offset,
return VENDOR_RC_SUCCESS;
}
-static enum vendor_cmd_rc spi_hash_sha256(uint8_t *dest, uint32_t offset,
- uint32_t size)
+int usb_spi_sha256_start(HASH_CTX *ctx)
{
- HASH_CTX sha;
- uint8_t data[SPI_HASH_CHUNK_SIZE];
- int chunk_size = SPI_HASH_CHUNK_SIZE;
- int chunks = 0;
-
- /* Fail if we don't own the bus */
if (get_spi_bus_user() != SPI_BUS_USER_HASH) {
CPRINTS("%s: not enabled", __func__);
- return VENDOR_RC_NOT_ALLOWED;
+ return EC_ERROR_BUSY;
}
- /* Bump inactivity timer to turn hashing mode off */
- hook_call_deferred(&spi_hash_inactive_timeout_data,
- SPI_HASH_TIMEOUT_US);
+ DCRYPTO_SHA256_init(ctx, 0);
- if (size > MAX_SPI_HASH_SIZE)
- return VENDOR_RC_BOGUS_ARGS;
+ return EC_SUCCESS;
+}
- CPRINTS("%s: 0x%x 0x%x", __func__, offset, size);
+int usb_spi_sha256_update(HASH_CTX *ctx, uint32_t offset, uint32_t size)
+{
+ uint8_t data[SPI_HASH_CHUNK_SIZE];
- DCRYPTO_SHA256_init(&sha, 0);
+ while (size) {
+ const int this_chunk = MIN(size, SPI_HASH_CHUNK_SIZE);
- for (chunks = 0; size > 0; chunks++) {
- int this_chunk = MIN(size, chunk_size);
/* Read the data */
if (spi_read_chunk(data, offset, this_chunk) != EC_SUCCESS) {
CPRINTS("%s: read error at 0x%x", __func__, offset);
return VENDOR_RC_READ_FLASH_FAIL;
}
-
/* Update hash */
- HASH_update(&sha, data, this_chunk);
+ HASH_update(ctx, data, this_chunk);
- /* Give other things a chance to happen */
- if (!(chunks % 128))
+ /* Kick the watchdog every 128 chunks. */
+ if (((size / SPI_HASH_CHUNK_SIZE) % 128) == 127) {
msleep(1);
+ watchdog_reload();
+ }
size -= this_chunk;
offset += this_chunk;
}
+ return EC_SUCCESS;
+}
+
+void usb_spi_sha256_final(HASH_CTX *ctx, void *digest, size_t digest_size)
+{
+ size_t copy_size;
+
+ copy_size = MIN(digest_size, SHA256_DIGEST_SIZE);
+ memcpy(digest, HASH_final(ctx), copy_size);
+
+ if (copy_size < digest_size)
+ memset((uint8_t *)digest + copy_size, 0,
+ digest_size - copy_size);
+}
+
+static enum vendor_cmd_rc spi_hash_sha256(uint8_t *dest, uint32_t offset,
+ uint32_t size)
+{
+ HASH_CTX sha;
+
+ CPRINTS("%s: 0x%x 0x%x", __func__, offset, size);
+ if (size > MAX_SPI_HASH_SIZE)
+ return VENDOR_RC_BOGUS_ARGS;
+
+ /* Bump inactivity timer to turn hashing mode off */
+ hook_call_deferred(&spi_hash_inactive_timeout_data,
+ SPI_HASH_TIMEOUT_US);
+
+ if (usb_spi_sha256_start(&sha) != EC_SUCCESS)
+ return VENDOR_RC_INTERNAL_ERROR;
+
+ if (usb_spi_sha256_update(&sha, offset, size) != EC_SUCCESS)
+ return VENDOR_RC_READ_FLASH_FAIL;
- memcpy(dest, HASH_final(&sha), SHA256_DIGEST_SIZE);
+ usb_spi_sha256_final(&sha, dest, SHA256_DIGEST_SIZE);
CPRINTS("%s: done", __func__);
return VENDOR_RC_SUCCESS;
diff --git a/chip/g/usb_spi.c b/chip/g/usb_spi.c
index d7f7ff031f..e41d9eab67 100644
--- a/chip/g/usb_spi.c
+++ b/chip/g/usb_spi.c
@@ -74,9 +74,10 @@ void usb_spi_deferred(struct usb_spi_config const *config)
if (enabled ^ config->state->enabled) {
if (enabled)
- rv = usb_spi_board_enable(config);
+ rv = usb_spi_board_enable(config->state->enabled_host);
+
else
- usb_spi_board_disable(config);
+ usb_spi_board_disable();
/* Only update our state if we were successful. */
if (rv == EC_SUCCESS)
diff --git a/chip/g/usb_spi.h b/chip/g/usb_spi.h
index cedfe78485..0c2707df4f 100644
--- a/chip/g/usb_spi.h
+++ b/chip/g/usb_spi.h
@@ -8,6 +8,7 @@
/* USB SPI driver for Chrome EC */
#include "compile_time_macros.h"
+#include "cryptoc/sha256.h"
#include "hooks.h"
#include "queue.h"
#include "queue_policies.h"
@@ -239,7 +240,11 @@ int usb_spi_interface(struct usb_spi_config const *config,
* usb_spi_board_enable should return EC_SUCCESS on success or an error
* otherwise.
*/
-int usb_spi_board_enable(struct usb_spi_config const *config);
-void usb_spi_board_disable(struct usb_spi_config const *config);
+int usb_spi_board_enable(int host);
+void usb_spi_board_disable(void);
+
+int usb_spi_sha256_start(HASH_CTX *ctx);
+int usb_spi_sha256_update(HASH_CTX *ctx, uint32_t offset, uint32_t size);
+void usb_spi_sha256_final(HASH_CTX *ctx, void *digest, size_t digest_size);
#endif /* __CROS_EC_USB_SPI_H */