summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamyoon Woo <namyoon@chromium.org>2020-02-28 09:44:46 -0800
committerCommit Bot <commit-bot@chromium.org>2020-03-09 21:48:18 +0000
commit5ccb5c7cc9c448b66c6f8e0abbb2dd785da0efb7 (patch)
tree84f6021a658d5b8b11c7612dafac86ede442b27a
parent97c73303cf9d5f6c8b6e871ddebd01a8e4ce4206 (diff)
downloadchrome-ec-5ccb5c7cc9c448b66c6f8e0abbb2dd785da0efb7.tar.gz
remove cr50 related files
BUG=b:149350081 BRANCH=none TEST=build all, and emerged ec related packages for host and octopus. $ make buildall -j $ cros_workon --host list chromeos-base/chromeos-cr50-dev chromeos-base/chromeos-ec chromeos-base/chromeos-ec-headers chromeos-base/ec-devutils chromeos-base/ec-utils chromeos-base/ec-utils-test dev-util/hdctools $ sudo emerge chromeos-cr50-dev -j $ sudo emerge chromeos-ec -j $ sudo emerge chromeos-ec-headers -j $ sudo emerge ec-devutils -j $ sudo emerge ec-utils -j $ sudo emerge ec-utils-test -j $ sudo emerge hdctools -j $ cros_workon-octopus list chromeos-base/chromeos-ec chromeos-base/chromeos-ec-headers chromeos-base/ec-devutils chromeos-base/ec-utils chromeos-base/ec-utils-test dev-util/hdctools $ sudo emerge-octopus chromeos-ec -j $ sudo emerge-octopus chromeos-ec-headers -j $ sudo emerge-octopus ec-devutils -j $ sudo emerge-octopus ec-utils -j $ sudo emerge-octopus ec-utils-test -j $ sudo emerge-octopus hdctools -j Signed-off-by: Namyoon Woo <namyoon@chromium.org> Change-Id: If751b26b0635b0021c077338e96eaa8e8dcf17a5 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2080631 Reviewed-by: Edward Hill <ecgh@chromium.org> Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r--Makefile.rules3
-rw-r--r--board/host/dcrypto.h78
-rw-r--r--chip/host/build.mk12
-rw-r--r--chip/host/dcrypto/README.md13
-rw-r--r--chip/host/dcrypto/aes.c37
-rw-r--r--chip/host/dcrypto/app_cipher.c48
-rw-r--r--chip/host/dcrypto/app_key.c31
-rw-r--r--chip/host/dcrypto/sha256.c18
-rw-r--r--common/build.mk12
-rw-r--r--common/ccd_config.c1553
-rw-r--r--common/extension.c85
-rw-r--r--common/factory_mode.c87
-rw-r--r--common/flash_log.c589
-rw-r--r--common/flash_log_vc.c74
-rw-r--r--common/hooks.c3
-rw-r--r--common/i2cs_tpm.c261
-rw-r--r--common/new_nvmem.c3217
-rw-r--r--common/nvmem.c508
-rw-r--r--common/nvmem_vars.c171
-rw-r--r--common/physical_presence.c326
-rw-r--r--common/pinweaver.c1543
-rw-r--r--common/tpm_registers.c1096
-rw-r--r--common/u2f.c445
-rw-r--r--common/update_fw.c8
-rw-r--r--common/usb_update.c1
-rw-r--r--core/cortex-m/ec.lds.S6
-rw-r--r--extra/usb_updater/Makefile28
-rw-r--r--extra/usb_updater/gsctool.c3027
-rw-r--r--extra/usb_updater/gsctool.h122
-rw-r--r--extra/usb_updater/verify_ro.c362
-rw-r--r--extra/usb_updater/verify_ro.h24
-rw-r--r--fuzz/fuzz_config.h70
-rw-r--r--include/ccd_config.h359
-rw-r--r--include/config.h127
-rw-r--r--include/console_channel.inc15
-rw-r--r--include/extension.h102
-rw-r--r--include/hooks.h9
-rw-r--r--include/link_defs.h4
-rw-r--r--include/new_nvmem.h155
-rw-r--r--include/nvmem.h219
-rw-r--r--include/nvmem_vars.h128
-rw-r--r--include/pinweaver.h188
-rw-r--r--include/pinweaver_tpm_imports.h39
-rw-r--r--include/pinweaver_types.h420
-rw-r--r--include/tpm_manufacture.h36
-rw-r--r--include/tpm_nvmem.h13
-rw-r--r--include/tpm_registers.h126
-rw-r--r--include/tpm_vendor_cmds.h252
-rw-r--r--include/u2f.h126
-rw-r--r--include/u2f_impl.h132
-rw-r--r--include/usb_api.h7
-rw-r--r--test/build.mk4
-rw-r--r--test/flash_log.c276
-rw-r--r--test/flash_log.tasklist9
-rw-r--r--test/nvmem_test.h32
-rw-r--r--test/pinweaver.c2681
-rw-r--r--test/pinweaver.tasklist9
-rw-r--r--test/rma_auth.tasklist9
-rw-r--r--test/test_config.h37
-rwxr-xr-xutil/g_regs77
-rwxr-xr-xutil/signer/bs342
-rw-r--r--util/signer/cr50_RW-prod.pem.pub9
-rw-r--r--util/signer/cr50_rom0-dev-blsign.pem.pub9
-rwxr-xr-xutil/signer/create_released_image.sh232
-rw-r--r--util/signer/ec_RW-manifest-dev.json48
-rw-r--r--util/signer/ec_RW-manifest-prod.json52
-rw-r--r--util/signer/fuses.xml2034
-rw-r--r--util/signer/loader-testkey-A.pem27
-rw-r--r--util/signer/rom-testkey-A.pem39
69 files changed, 4 insertions, 22237 deletions
diff --git a/Makefile.rules b/Makefile.rules
index c6851611c2..cf4d80c495 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -141,8 +141,7 @@ cmd_cp_script = cp "$<" "$@" && chmod +x "$@"
cmd_libcryptoc_make = $(MAKE) --no-print-directory -C $(CRYPTOCLIB) \
obj=$(realpath $(out))/cryptoc \
- SUPPORT_UNALIGNED=1 \
- CONFIG_UPTO_SHA512=$(CONFIG_UPTO_SHA512)
+ SUPPORT_UNALIGNED=1
cmd_libcryptoc = $(cmd_libcryptoc_make) -q || $(cmd_libcryptoc_make)
# commands for RSA signature: rwsig does not need to sign the whole image
diff --git a/board/host/dcrypto.h b/board/host/dcrypto.h
deleted file mode 100644
index 31f04e51aa..0000000000
--- a/board/host/dcrypto.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/* Provides the minimal declarations needed by pinweaver to build on
- * CHIP_HOST. While it might be preferable to simply use the original dcrypto.h,
- * That would require incorporating additional headers / dependencies such as
- * cryptoc.
- */
-
-#ifndef __CROS_EC_DCRYPTO_HOST_H
-#define __CROS_EC_DCRYPTO_HOST_H
-#include <stdint.h>
-#include <string.h>
-
-/* Allow tests to return a faked result for the purpose of testing. If
- * this is not set, a combination of cryptoc and openssl are used for the
- * dcrypto implementation.
- */
-#ifndef CONFIG_DCRYPTO_MOCK
-
-/* If not using the mock struct definitions, use the ones from Cr50. */
-#include "chip/g/dcrypto/dcrypto.h"
-
-#else /* defined(CONFIG_DCRYPTO_MOCK) */
-
-#include <sha256.h>
-
-#define HASH_CTX sha256_ctx
-
-/* Used as a replacement for declarations in cryptoc that are used by Cr50, but
- * add unnecessary complexity to the test code.
- */
-struct dcrypto_mock_ctx_t {
- struct HASH_CTX hash;
-};
-#define LITE_HMAC_CTX struct dcrypto_mock_ctx_t
-#define LITE_SHA256_CTX struct HASH_CTX
-
-void HASH_update(struct HASH_CTX *ctx, const void *data, size_t len);
-uint8_t *HASH_final(struct HASH_CTX *ctx);
-
-#define AES256_BLOCK_CIPHER_KEY_SIZE 32
-#define SHA256_DIGEST_SIZE 32
-
-enum dcrypto_appid {
- RESERVED = 0,
- NVMEM = 1,
- U2F_ATTEST = 2,
- U2F_ORIGIN = 3,
- U2F_WRAP = 4,
- PERSO_AUTH = 5,
- PINWEAVER = 6,
- /* This enum value should not exceed 7. */
-};
-
-void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required);
-
-void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
- unsigned int len);
-const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx);
-
-int DCRYPTO_aes_ctr(uint8_t *out, const uint8_t *key, uint32_t key_bits,
- const uint8_t *iv, const uint8_t *in, size_t in_len);
-
-struct APPKEY_CTX {};
-
-int DCRYPTO_appkey_init(enum dcrypto_appid appid, struct APPKEY_CTX *ctx);
-
-void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx);
-
-int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8],
- uint32_t output[8]);
-
-#endif /* CONFIG_DCRYPTO_MOCK */
-
-#endif /* __CROS_EC_HOST_DCRYPTO_H */
diff --git a/chip/host/build.mk b/chip/host/build.mk
index 9d77937776..8d2d69f3c3 100644
--- a/chip/host/build.mk
+++ b/chip/host/build.mk
@@ -16,18 +16,6 @@ chip-$(HAS_TASK_KEYSCAN)+=keyboard_raw.o
endif
chip-$(CONFIG_USB_PD_TCPC)+=usb_pd_phy.o
-ifeq ($(CONFIG_DCRYPTO),y)
-CPPFLAGS += -I$(abspath ./chip/g)
-dirs-y += chip/g/dcrypto
-endif
dirs-y += chip/host/dcrypto
chip-$(CONFIG_I2C)+= i2c.o
-
-chip-$(CONFIG_DCRYPTO)+= dcrypto/aes.o
-chip-$(CONFIG_DCRYPTO)+= dcrypto/app_cipher.o
-chip-$(CONFIG_DCRYPTO)+= dcrypto/app_key.o
-chip-$(CONFIG_DCRYPTO)+= dcrypto/sha256.o
-
-# Object files that can be shared with the Cr50 dcrypto implementation
-chip-$(CONFIG_DCRYPTO)+= ../g/dcrypto/hmac.o
diff --git a/chip/host/dcrypto/README.md b/chip/host/dcrypto/README.md
deleted file mode 100644
index 6812dde311..0000000000
--- a/chip/host/dcrypto/README.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Rough Dcrypto Implementation on Host for Fuzzing Targets.
-
-This implementation of the dcrypto API is not complete, but provides the needed
-function definitions to fuzz Cr50 code.
-The the following should be noted:
-* A complete implementation of dcrypto does not add any extra coverage since the
- dcrypto code here doesn't match the Cr50 implementation that depends on
- a specific hardware accelerator.
-* The input data comes from a fuzzer so storage encryption isn't necessary—no
- user data is handled.
-* For fuzzing fully implementing the crypto functionality isn't useful for the
- purpose of finding bugs--it makes the fuzzer take longer to execute without
- providing any benefit for the extra cycles.
diff --git a/chip/host/dcrypto/aes.c b/chip/host/dcrypto/aes.c
deleted file mode 100644
index cc57168cbb..0000000000
--- a/chip/host/dcrypto/aes.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/* Copyright 2018 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 <openssl/evp.h>
-
-#define HIDE_EC_STDLIB
-
-#include "dcrypto.h"
-#include "registers.h"
-
-int DCRYPTO_aes_ctr(uint8_t *out, const uint8_t *key, uint32_t key_bits,
- const uint8_t *iv, const uint8_t *in, size_t in_len)
-{
- EVP_CIPHER_CTX *ctx;
- int ret = 0;
- int out_len = 0;
-
- ctx = EVP_CIPHER_CTX_new();
- if (!ctx)
- return 0;
-
- if (EVP_EncryptInit_ex(ctx, EVP_aes_256_ctr(), NULL, key, iv) != 1)
- goto cleanup;
-
- if (EVP_EncryptUpdate(ctx, out, &out_len, in, in_len) != 1)
- goto cleanup;
-
- if (EVP_EncryptFinal(ctx, out + out_len, &out_len) != 1)
- goto cleanup;
- ret = 1;
-
-cleanup:
- EVP_CIPHER_CTX_free(ctx);
- return ret;
-}
diff --git a/chip/host/dcrypto/app_cipher.c b/chip/host/dcrypto/app_cipher.c
deleted file mode 100644
index ab52484753..0000000000
--- a/chip/host/dcrypto/app_cipher.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* Copyright 2018 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 "dcrypto.h"
-#include "util.h"
-
-void app_compute_hash(uint8_t *p_buf, size_t num_bytes,
- uint8_t *p_hash, size_t hash_len)
-{
- uint8_t digest[SHA256_DIGEST_SIZE];
-
- /*
- * Use the built in dcrypto engine to generate the sha1 hash of the
- * buffer.
- */
- DCRYPTO_SHA256_hash((uint8_t *)p_buf, num_bytes, digest);
-
- memcpy(p_hash, digest, MIN(hash_len, sizeof(digest)));
-
- if (hash_len > sizeof(digest))
- memset(p_hash + sizeof(digest), 0,
- hash_len - sizeof(digest));
-}
-
-int app_cipher(const void *salt_p, void *out_p, const void *in_p, size_t size)
-{
- /* See README.md for why this is not a real encryption.. */
- size_t i;
- const uint8_t *src;
- const uint8_t *salt;
- uint8_t *dst;
-
- src = in_p;
- salt = salt_p;
- dst = out_p;
-
- for (i = 0; i < size; i++)
- dst[i] = src[i] ^ salt[i & 7];
-
- return 1;
-}
-
-int crypto_enabled(void)
-{
- return 1;
-}
diff --git a/chip/host/dcrypto/app_key.c b/chip/host/dcrypto/app_key.c
deleted file mode 100644
index 58066c84ba..0000000000
--- a/chip/host/dcrypto/app_key.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/* Copyright 2018 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 "dcrypto.h"
-
-static int dcrypto_appkey_init_flag_ = -1;
-
-int DCRYPTO_appkey_init(enum dcrypto_appid appid, struct APPKEY_CTX *ctx)
-{
- if (dcrypto_appkey_init_flag_ != -1)
- return 0;
-
- dcrypto_appkey_init_flag_ = appid;
- return 1;
-}
-
-void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx)
-{
- memset(ctx, 0, sizeof(struct APPKEY_CTX));
- dcrypto_appkey_init_flag_ = -1;
-}
-
-int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8],
- uint32_t output[8])
-{
- /* See README.md for while this is a passthrough. */
- memcpy(output, input, SHA256_DIGEST_SIZE);
- return 1;
-}
diff --git a/chip/host/dcrypto/sha256.c b/chip/host/dcrypto/sha256.c
deleted file mode 100644
index 429588c8ac..0000000000
--- a/chip/host/dcrypto/sha256.c
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Copyright 2018 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 "dcrypto.h"
-
-void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required)
-{
- SHA256_init(ctx);
-}
-
-const uint8_t *DCRYPTO_SHA256_hash(const void *data, uint32_t n,
- uint8_t *digest)
-{
- SHA256_hash(data, n, digest);
- return digest;
-}
diff --git a/common/build.mk b/common/build.mk
index a931b10890..5948e08d51 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -41,7 +41,6 @@ common-$(CONFIG_BATTERY_FUEL_GAUGE)+=battery_fuel_gauge.o
common-$(CONFIG_BLUETOOTH_LE)+=bluetooth_le.o
common-$(CONFIG_BLUETOOTH_LE_STACK)+=btle_hci_controller.o btle_ll.o
common-$(CONFIG_CAPSENSE)+=capsense.o
-common-$(CONFIG_CASE_CLOSED_DEBUG_V1)+=ccd_config.o
common-$(CONFIG_CEC)+=cec.o
common-$(CONFIG_CROS_BOARD_INFO)+=cbi.o
common-$(CONFIG_CHARGE_MANAGER)+=charge_manager.o
@@ -68,15 +67,9 @@ common-$(CONFIG_DPTF)+=dptf.o
common-$(CONFIG_EC_EC_COMM_MASTER)+=ec_ec_comm_master.o
common-$(CONFIG_EC_EC_COMM_SLAVE)+=ec_ec_comm_slave.o
common-$(CONFIG_HOSTCMD_ESPI)+=espi.o
-common-$(CONFIG_EXTENSION_COMMAND)+=extension.o
common-$(CONFIG_EXTPOWER_GPIO)+=extpower_gpio.o
common-$(CONFIG_FANS)+=fan.o pwm.o
-common-$(CONFIG_FACTORY_MODE)+=factory_mode.o
common-$(CONFIG_FLASH)+=flash.o
-common-$(CONFIG_FLASH_LOG)+=flash_log.o flash_log_vc.o
-common-$(CONFIG_FLASH_NVMEM)+=nvmem.o
-common-$(CONFIG_FLASH_NVMEM)+=new_nvmem.o
-common-$(CONFIG_FLASH_NVMEM_VARS)+=nvmem_vars.o
common-$(CONFIG_FMAP)+=fmap.o
common-$(CONFIG_GESTURE_SW_DETECTION)+=gesture.o
common-$(CONFIG_HOSTCMD_EVENTS)+=host_event_commands.o
@@ -106,8 +99,6 @@ common-$(CONFIG_MAG_CALIBRATE)+= mag_cal.o math_util.o vec3.o mat33.o mat44.o \
common-$(CONFIG_MKBP_EVENT)+=mkbp_event.o
common-$(CONFIG_ONEWIRE)+=onewire.o
common-$(CONFIG_PECI_COMMON)+=peci.o
-common-$(CONFIG_PHYSICAL_PRESENCE)+=physical_presence.o
-common-$(CONFIG_PINWEAVER)+=pinweaver.o
common-$(CONFIG_POWER_BUTTON)+=power_button.o
common-$(CONFIG_POWER_BUTTON_X86)+=power_button_x86.o
common-$(CONFIG_PSTORE)+=pstore_commands.o
@@ -136,8 +127,6 @@ common-$(CONFIG_TEMP_SENSOR)+=temp_sensor.o
common-$(CONFIG_THROTTLE_AP)+=thermal.o throttle_ap.o
common-$(CONFIG_THROTTLE_AP_ON_BAT_DISCHG_CURRENT)+=throttle_ap.o
common-$(CONFIG_THROTTLE_AP_ON_BAT_VOLTAGE)+=throttle_ap.o
-common-$(CONFIG_TPM_I2CS)+=i2cs_tpm.o
-common-$(CONFIG_U2F)+=u2f.o
common-$(CONFIG_USB_CHARGER)+=usb_charger.o
common-$(CONFIG_USB_CONSOLE_STREAM)+=usb_console_stream.o
common-$(CONFIG_USB_I2C)+=usb_i2c.o
@@ -172,7 +161,6 @@ common-$(HAS_TASK_PDCMD)+=host_command_pd.o
common-$(HAS_TASK_KEYSCAN)+=keyboard_scan.o
common-$(HAS_TASK_LIGHTBAR)+=lb_common.o lightbar.o
common-$(HAS_TASK_MOTIONSENSE)+=motion_sense.o
-common-$(HAS_TASK_TPM)+=tpm_registers.o
ifneq ($(HAVE_PRIVATE_AUDIO_CODEC_WOV_LIBS),y)
common-$(CONFIG_AUDIO_CODEC_WOV)+=hotword_dsp_api.o
diff --git a/common/ccd_config.c b/common/ccd_config.c
deleted file mode 100644
index 91232df295..0000000000
--- a/common/ccd_config.c
+++ /dev/null
@@ -1,1553 +0,0 @@
-/* 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.
- *
- * Case Closed Debug configuration
- */
-
-#include "common.h"
-#include "byteorder.h"
-#include "ccd_config.h"
-#include "console.h"
-#include "cryptoc/sha256.h"
-#include "cryptoc/util.h"
-#include "dcrypto.h"
-#include "extension.h"
-#include "hooks.h"
-#include "nvmem_vars.h"
-#include "physical_presence.h"
-#include "system.h"
-#include "system_chip.h"
-#include "task.h"
-#include "timer.h"
-#include "tpm_registers.h"
-#include "tpm_vendor_cmds.h"
-#include "trng.h"
-#include "wp.h"
-
-#define CPRINTS(format, args...) cprints(CC_CCD, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_CCD, format, ## args)
-
-/* Let's make sure that CCD capability state enum fits into two bits. */
-BUILD_ASSERT(CCD_CAP_STATE_COUNT <= 4);
-
-/* Restriction state for ccdunlock when no password is set */
-enum ccd_unlock_restrict {
- /* Unrestricted */
- CCD_UNLOCK_UNRESTRICTED = 0,
-
- /* Physical presence required for unlock unless disabled by config */
- CCD_UNLOCK_NEED_PP,
-
- /* Unlock not allowed */
- CCD_UNLOCK_DISABLED
-};
-
-/* Minimum time between password attempts */
-#define PASSWORD_RATE_LIMIT_US (3 * SECOND)
-
-/* Current version of case-closed debugging configuration struct */
-#define CCD_CONFIG_VERSION 0x10
-
-/*
- * CCD command header; including the subcommand code used to demultiplex
- * various CCD commands over the same TPM vendor command.
- */
-struct ccd_vendor_cmd_header {
- struct tpm_cmd_header tpm_header;
-
- /* On input, the subcommand. On output, may contain EC return code */
- uint8_t ccd_subcommand;
-} __packed;
-
-/* Size of password salt and digest in bytes */
-#define CCD_PASSWORD_SALT_SIZE 4
-#define CCD_PASSWORD_DIGEST_SIZE 16
-
-/* Way longer than practical. */
-#define CCD_MAX_PASSWORD_SIZE 40
-
-struct ccd_config {
- /* Version (CCD_CONFIG_VERSION) */
- uint8_t version;
-
- /*
- * Flags. These MUST immediately follow version, so that the test
- * lab flag is always the LSBit of the first flags byte.
- */
- uint8_t flags[3];
-
- /* Capabilities */
- uint8_t capabilities[8];
-
- /* Password salt (random) */
- uint8_t password_salt[CCD_PASSWORD_SALT_SIZE];
-
- /*
- * Password digest = truncated
- * SHA256_digest(password_salt+device_id+password)
- */
- uint8_t password_digest[CCD_PASSWORD_DIGEST_SIZE];
-};
-
-/* Nvmem variable name for CCD config */
-static const uint8_t k_ccd_config = NVMEM_VAR_CCD_CONFIG;
-
-/* Flags which can be set via ccd_set_flag() */
-static const uint32_t k_public_flags =
- CCD_FLAG_OVERRIDE_WP_AT_BOOT |
- CCD_FLAG_OVERRIDE_WP_STATE_ENABLED |
- CCD_FLAG_OVERRIDE_BATT_AT_BOOT |
- CCD_FLAG_OVERRIDE_BATT_STATE_CONNECT;
-
-/* List of CCD capability info; must be in same order as enum ccd_capability */
-static const struct ccd_capability_info cap_info[CCD_CAP_COUNT] = CAP_INFO_DATA;
-
-static const char *ccd_state_names[CCD_STATE_COUNT] = CCD_STATE_NAMES;
-static const char *ccd_cap_state_names[CCD_CAP_STATE_COUNT] =
- CCD_CAP_STATE_NAMES;
-
-static enum ccd_state ccd_state = CCD_STATE_LOCKED;
-static struct ccd_config config;
-static uint8_t ccd_config_loaded;
-static uint8_t force_disabled;
-static struct mutex ccd_config_mutex;
-static uint8_t ccd_console_active; /* CCD console command is in progress. */
-
-/******************************************************************************/
-/* Raw config accessors */
-
-/**
- * Get CCD flags.
- *
- * @return the current flags mask.
- */
-static uint32_t raw_get_flags(void)
-{
- return (uint32_t)(config.flags[0] << 0)
- | ((uint32_t)config.flags[1] << 8)
- | ((uint32_t)config.flags[2] << 16);
-}
-
-/**
- * Set a single CCD flag.
- *
- * This does NOT call ccd_save_config() or lock the mutex. Caller must do
- * those.
- *
- * @param flag Flag to set
- * @param value New value for flag (0=clear, non-zero=set)
- */
-static void raw_set_flag(enum ccd_flag flag, int value)
-{
- uint32_t f;
-
- f = raw_get_flags();
- if (value)
- f |= flag;
- else
- f &= ~flag;
-
- config.flags[0] = (uint8_t)(f >> 0);
- config.flags[1] = (uint8_t)(f >> 8);
- config.flags[2] = (uint8_t)(f >> 16);
-}
-
-/**
- * Get a raw capability state from the config
- *
- * @param cap Capability to check
- * @param translate_default If non-zero, translate CCD_CAP_STATE_DEFAULT
- * to the actual default for that config
- * @return The capability state.
- */
-static enum ccd_capability_state raw_get_cap(enum ccd_capability cap,
- int translate_default)
-{
- const uint32_t index = cap / CCD_CAPS_PER_BYTE;
- const uint32_t shift = (cap % CCD_CAPS_PER_BYTE) * CCD_CAP_BITS;
-
- int c = (config.capabilities[index] >> shift) & CCD_CAP_BITMASK;
-
- if (c == CCD_CAP_STATE_DEFAULT && translate_default)
- c = cap_info[cap].default_state;
-
- return c;
-}
-
-/**
- * Set a raw capability to the config.
- *
- * This does NOT call ccd_save_config() or lock the mutex. Caller must do
- * those.
- *
- * @param cap Capability to set
- * @param state New state for capability
- */
-static void raw_set_cap(enum ccd_capability cap,
- enum ccd_capability_state state)
-{
- const uint32_t index = cap / CCD_CAPS_PER_BYTE;
- const uint32_t shift = (cap % CCD_CAPS_PER_BYTE) * CCD_CAP_BITS;
-
- config.capabilities[index] &= ~(CCD_CAP_BITMASK << shift);
- config.capabilities[index] |= (state & CCD_CAP_BITMASK) << shift;
-}
-
-/**
- * Check CCD configuration is reset to default value.
- *
- * @return 1 if it is in default mode.
- * 0 otherwise.
- */
-static int raw_check_all_caps_default(void)
-{
- uint32_t i;
-
- for (i = 0; i < CCD_CAP_COUNT; i++)
- if (raw_get_cap(i, 0) != CCD_CAP_STATE_DEFAULT)
- return 0;
-
- return 1;
-}
-
-/**
- * Check if a password is set.
- * @return 1 if password is set, 0 if it's not
- */
-static int raw_has_password(void)
-{
- uint8_t set = 0;
- int i;
-
- /* Password is set unless salt and digest are all zero */
- for (i = 0; i < sizeof(config.password_salt); i++)
- set |= config.password_salt[i];
- for (i = 0; i < sizeof(config.password_digest); i++)
- set |= config.password_digest[i];
-
- return !!set;
-}
-
-/**
- * Calculate the expected digest for a password.
- *
- * Uses the unique device ID and the salt from the config.
- *
- * @param digest Pointer to a CCD_PASSWORD_DIGEST_SIZE buffer
- * @param password The password to digest
- */
-static void ccd_password_digest(uint8_t *digest, const char *password)
-{
- HASH_CTX sha;
- uint8_t *unique_id;
- int unique_id_len;
-
- unique_id_len = system_get_chip_unique_id(&unique_id);
-
- DCRYPTO_SHA256_init(&sha, 0);
- HASH_update(&sha, config.password_salt, sizeof(config.password_salt));
- HASH_update(&sha, unique_id, unique_id_len);
- HASH_update(&sha, password, strlen(password));
- memcpy(digest, HASH_final(&sha), CCD_PASSWORD_DIGEST_SIZE);
-}
-
-/**
- * Check the password.
- *
- * @param password The password to check
- * @return EC_SUCCESS, EC_ERROR_BUSY if too soon since last attempt, or
- * EC_ERROR_ACCESS_DENIED if mismatch.
- */
-static int raw_check_password(const char *password)
-{
- /*
- * Time of last password attempt; initialized to 0 at boot. Yes, we're
- * only keeping the bottom 32 bits of the timer here, so on a
- * wraparound (every ~4000 seconds) it's possible for an attacker to
- * get one extra attempt. But it still behaves properly at boot,
- * requiring the system to be up PASSWORD_RATE_LIMIT_US before allowing
- * the first attempt.
- */
- static uint32_t last_password_time;
-
- uint8_t digest[CCD_PASSWORD_DIGEST_SIZE];
- uint32_t t;
-
- /* If no password is set, match only an empty password */
- if (!raw_has_password())
- return *password ? EC_ERROR_ACCESS_DENIED : EC_SUCCESS;
-
- /* Rate limit password attempts */
- t = get_time().le.lo;
- if (t - last_password_time < PASSWORD_RATE_LIMIT_US)
- return EC_ERROR_BUSY;
- last_password_time = t;
-
- /* Calculate the digest of the password */
- ccd_password_digest(digest, password);
-
- if (safe_memcmp(digest, config.password_digest,
- sizeof(config.password_digest)))
- return EC_ERROR_ACCESS_DENIED;
-
- return EC_SUCCESS;
-}
-
-/**
- * Clear the password.
- *
- * This does NOT call ccd_save_config() or lock the mutex. Caller must do
- * those.
- */
-static void raw_reset_password(void)
-{
- memset(config.password_salt, 0, sizeof(config.password_salt));
- memset(config.password_digest, 0, sizeof(config.password_digest));
- raw_set_flag(CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED, 0);
-}
-
-/**
- * Set the password.
- *
- * @param password New password; must be non-empty
- */
-static void raw_set_password(const char *password)
-{
- /* Get a new salt */
- rand_bytes(config.password_salt, sizeof(config.password_salt));
-
- /* Update the password digest */
- ccd_password_digest(config.password_digest, password);
-
- /* Track whether we were opened when we set the password */
- raw_set_flag(CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED,
- ccd_state == CCD_STATE_UNLOCKED);
-}
-
-/******************************************************************************/
-/* Internal methods */
-
-/**
- * Set the CCD state.
- *
- * @param state New CCD state
- */
-static void ccd_set_state(enum ccd_state state)
-{
- if (state == ccd_state)
- return;
-
- ccd_state = state;
-
- /* Notify CCD users of configuration change */
- hook_notify(HOOK_CCD_CHANGE);
-}
-
-/**
- * Load CCD config from nvmem_vars
- *
- * @return EC_SUCCESS or non-zero error code.
- */
-static void ccd_load_config(void)
-{
- const struct tuple *t;
-
- /* Don't reload if we're already loaded */
- if (ccd_config_loaded)
- return;
-
- /* Load config data from nvmem */
- t = getvar(&k_ccd_config, sizeof(k_ccd_config));
-
- /* Use defaults if config data is not present */
- if (!t) {
- if (board_is_first_factory_boot()) {
- /* Give factory/RMA access */
- CPRINTS("CCD using factory config");
- ccd_reset_config(CCD_RESET_FACTORY);
- } else {
- /* Somehow we lost our config; normal defaults */
- CPRINTS("CCD using default config");
- ccd_reset_config(CCD_RESET_TEST_LAB);
- }
- goto ccd_is_loaded;
- }
-
- /* Copy the tuple data */
- memcpy(&config, tuple_val(t), MIN(sizeof(config), t->val_len));
-
- /* If version or size is wrong, reset to defaults */
- if (config.version != CCD_CONFIG_VERSION ||
- t->val_len != sizeof(config)) {
- CPRINTS("CCD config mismatch; using defaults");
- /*
- * If the config data was big enough to hold the test lab bit,
- * preserve it. That's guaranteed to be in the same place for
- * all data versions.
- */
- ccd_reset_config(t->val_len < 2 ? CCD_RESET_TEST_LAB : 0);
- }
-
- freevar(t);
-
-ccd_is_loaded:
- ccd_config_loaded = 1;
-
- /* Notify CCD users of configuration change */
- hook_notify(HOOK_CCD_CHANGE);
-}
-
-/**
- * Save CCD config to nvmem_vars
- *
- * @return EC_SUCCESS or non-zero error code.
- */
-static int ccd_save_config(void)
-{
- int rv;
-
- rv = setvar(&k_ccd_config, sizeof(k_ccd_config),
- (const uint8_t *)&config, sizeof(config));
- if (rv)
- return rv;
-
- /*
- * Notify CCD users of configuration change.
- * Protect this notify with the ccd_config_loaded flag so recipients of
- * HOOK_CCD_CHANGE don't call ccd_get/ccd_set before the CCD
- * initialization is complete.
- */
- if (ccd_config_loaded)
- hook_notify(HOOK_CCD_CHANGE);
-
- return rv;
-}
-
-/**
- * Set a CCD capability to a new state.
- *
- * @param cap Capability to set
- * @param state New state for capability
- * @return EC_SUCCESS or non-zero error code.
- */
-static int ccd_set_cap(enum ccd_capability cap, enum ccd_capability_state state)
-{
- if (!ccd_config_loaded)
- return EC_ERROR_BUSY;
-
- if (state == raw_get_cap(cap, 0))
- return EC_SUCCESS; /* Capability not changed */
-
- mutex_lock(&ccd_config_mutex);
- raw_set_cap(cap, state);
- mutex_unlock(&ccd_config_mutex);
-
- return ccd_save_config();
-}
-
-int ccd_reset_config(unsigned int flags)
-{
- int old_lab = ccd_get_flag(CCD_FLAG_TEST_LAB);
-
- mutex_lock(&ccd_config_mutex);
-
- if (flags & CCD_RESET_UNLOCKED_ONLY) {
- /* Only set config options that are mutable when unlocked */
- int i;
-
- /* Reset the password if it was set when unlocked */
- if (ccd_get_flag(CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED))
- raw_reset_password();
-
- /* Reset all capabilities that aren't IfOpened */
- for (i = 0; i < CCD_CAP_COUNT; i++) {
- if (raw_get_cap(i, 1) == CCD_CAP_STATE_IF_OPENED)
- continue;
- raw_set_cap(i, CCD_CAP_STATE_DEFAULT);
- }
-
- /* Flags all require IfOpened, so don't touch those */
- } else {
- /* Reset the entire config */
- memset(&config, 0, sizeof(config));
- config.version = CCD_CONFIG_VERSION;
- /* Update write protect after resetting the config */
- board_wp_follow_ccd_config();
- }
-
- if (flags & CCD_RESET_FACTORY) {
- /* Force factory mode settings */
- int i;
-
- /* Allow all capabilities all the time */
- for (i = 0; i < CCD_CAP_COUNT; i++)
- raw_set_cap(i, CCD_CAP_STATE_ALWAYS);
-
- raw_set_flag(CCD_FLAG_FACTORY_MODE_ENABLED, 1);
-
- /* Force WP disabled at boot */
- raw_set_flag(CCD_FLAG_OVERRIDE_WP_AT_BOOT, 1);
- raw_set_flag(CCD_FLAG_OVERRIDE_WP_STATE_ENABLED, 0);
- board_wp_follow_ccd_config();
- }
-
- /* Restore test lab flag unless explicitly resetting it */
- if (!(flags & CCD_RESET_TEST_LAB))
- raw_set_flag(CCD_FLAG_TEST_LAB, old_lab);
-
- mutex_unlock(&ccd_config_mutex);
-
- return ccd_save_config();
-}
-
-/**
- * Convert a string to a capability index.
- *
- * @param name Capability name to find
- * @return The capability index, or CCD_CAP_COUNT if error
- */
-static enum ccd_capability ccd_cap_from_name(const char *name)
-{
- int i;
-
- for (i = 0; i < CCD_CAP_COUNT; i++) {
- if (!strcasecmp(name, cap_info[i].name))
- return i;
- }
-
- return CCD_CAP_COUNT;
-}
-
-/**
- * Reset the password.
- *
- * @return EC_SUCCESS or non-zero error code.
- */
-static int ccd_reset_password(void)
-{
- mutex_lock(&ccd_config_mutex);
- raw_reset_password();
- mutex_unlock(&ccd_config_mutex);
-
- return ccd_save_config();
-}
-
-/**
- * Set the password.
- *
- * @param password New password; must be non-empty
- * @return EC_SUCCESS or non-zero error code.
- */
-static int ccd_set_password(const char *password)
-{
- mutex_lock(&ccd_config_mutex);
- raw_set_password(password);
- mutex_unlock(&ccd_config_mutex);
-
- return ccd_save_config();
-}
-
-/******************************************************************************/
-/* Handlers for state changes requiring physical presence */
-
-/*
- * Could be invoked synchronously on the TPM task context, or asynchronously,
- * after physical presence is established, on the hooks task context.
- *
- * The appropriate TPM reset entry point needs to be invoked. Also, make sure
- * that the board is always rebooted when TPM is reset.
- *
- * @param sync Non-zero to invoke synchronously.
- */
-static void ccd_open_done(int sync)
-{
- int rv;
-
- /*
- * Wiping the TPM may take a while. Delay sleep long enough for the
- * open process to finish.
- */
- delay_sleep_by(DISABLE_SLEEP_TIME_TPM_WIPE);
-
- if (!ccd_is_cap_enabled(CCD_CAP_OPEN_WITHOUT_TPM_WIPE)) {
- /* Can't open unless wipe succeeds */
- if (sync)
- rv = tpm_sync_reset(1);
- else
- rv = board_wipe_tpm(1);
-
- if (rv != EC_SUCCESS) {
- CPRINTS("CCD open TPM wipe failed");
- return;
- }
- }
-
- if (!ccd_is_cap_enabled(CCD_CAP_UNLOCK_WITHOUT_AP_REBOOT) ||
- (!ccd_is_cap_enabled(CCD_CAP_OPEN_WITHOUT_TPM_WIPE) && sync))
- board_reboot_ap();
-
- CPRINTS("CCD opened");
- ccd_set_state(CCD_STATE_OPENED);
-}
-
-static void ccd_open_done_async(void)
-{
- ccd_open_done(0);
-}
-
-static void ccd_unlock_done(void)
-{
- if (!ccd_is_cap_enabled(CCD_CAP_UNLOCK_WITHOUT_AP_REBOOT))
- board_reboot_ap();
-
- CPRINTS("CCD unlocked");
- ccd_set_state(CCD_STATE_UNLOCKED);
-}
-
-static void ccd_testlab_toggle(void)
-{
- int v = !ccd_get_flag(CCD_FLAG_TEST_LAB);
-
- /* Use raw_set_flag() because the test lab flag is internal */
- mutex_lock(&ccd_config_mutex);
- raw_set_flag(CCD_FLAG_TEST_LAB, v);
- mutex_unlock(&ccd_config_mutex);
-
- if (ccd_save_config() == EC_SUCCESS)
- CPRINTS("CCD test lab mode %sbled", v ? "ena" : "disa");
- else
- CPRINTS("Error setting CCD test lab mode!");
-}
-
-/******************************************************************************/
-/* External interface */
-
-int ccd_has_password(void)
-{
- return raw_has_password();
-}
-
-void ccd_config_init(enum ccd_state state)
-{
- /* Set initial state, after making sure it's a valid one */
- if (state != CCD_STATE_UNLOCKED && state != CCD_STATE_OPENED)
- state = CCD_STATE_LOCKED;
- ccd_state = state;
-
- ccd_load_config();
-}
-
-int ccd_get_flag(enum ccd_flag flag)
-{
- uint32_t f = raw_get_flags();
-
- if (!ccd_config_loaded || force_disabled)
- return 0;
-
- return !!(f & flag);
-}
-
-int ccd_set_flag(enum ccd_flag flag, int value)
-{
- if (force_disabled)
- return EC_ERROR_ACCESS_DENIED;
-
- /* Fail if trying to set a private flag */
- if (flag & ~k_public_flags)
- return EC_ERROR_ACCESS_DENIED;
-
- if (!ccd_config_loaded)
- return EC_ERROR_BUSY;
-
- if (ccd_get_flag(flag) == !!value)
- return EC_SUCCESS;
-
- mutex_lock(&ccd_config_mutex);
- raw_set_flag(flag, value);
- mutex_unlock(&ccd_config_mutex);
- return ccd_save_config();
-}
-
-int ccd_is_cap_enabled(enum ccd_capability cap)
-{
- if (!ccd_config_loaded || force_disabled)
- return 0;
-
- switch (raw_get_cap(cap, 1)) {
- case CCD_CAP_STATE_ALWAYS:
- return 1;
- case CCD_CAP_STATE_UNLESS_LOCKED:
- return ccd_state != CCD_STATE_LOCKED;
- case CCD_CAP_STATE_IF_OPENED:
- default:
- return ccd_state == CCD_STATE_OPENED;
- }
-}
-
-enum ccd_state ccd_get_state(void)
-{
- return ccd_state;
-}
-
-void ccd_disable(void)
-{
- CPRINTS("CCD disabled");
- force_disabled = 1;
- ccd_set_state(CCD_STATE_LOCKED);
-}
-
-int ccd_get_factory_mode(void)
-{
- return ccd_get_flag(CCD_FLAG_FACTORY_MODE_ENABLED);
-}
-
-/******************************************************************************/
-/* Console commands */
-
-static int command_ccd_info(void)
-{
- int i;
-
- ccprintf("State: %s%s\n", ccd_state_names[ccd_state],
- force_disabled ? " (Disabled)" : "");
- ccprintf("Password: %s\n", raw_has_password() ? "set" : "none");
- ccprintf("Flags: 0x%06x\n", raw_get_flags());
-
- ccprintf("Capabilities: %ph\n", HEX_BUF(config.capabilities, 8));
- for (i = 0; i < CCD_CAP_COUNT; i++) {
- int c = raw_get_cap(i, 0);
-
- ccprintf(" %-15s %c %d=%s",
- cap_info[i].name,
- ccd_is_cap_enabled(i) ? 'Y' : '-',
- c, ccd_cap_state_names[c]);
- if (c == CCD_CAP_STATE_DEFAULT)
- ccprintf(" (%s)",
- ccd_cap_state_names[cap_info[i].default_state]);
- ccprintf("\n");
- cflush();
- }
-
- ccprintf("TPM:%s%s\n",
- board_fwmp_allows_unlock() ? "" : " fwmp_lock",
- board_vboot_dev_mode_enabled() ? " dev_mode" : "");
-
- ccprintf("Capabilities are %s.\n", raw_check_all_caps_default() ?
- "default" : "modified");
-
- ccputs("Use 'ccd help' to print subcommands\n");
- return EC_SUCCESS;
-}
-
-static int command_ccd_reset(int argc, char **argv)
-{
- int flags = 0;
-
- if (argc > 1) {
- if (!strcasecmp(argv[1], "factory"))
- flags = CCD_RESET_FACTORY;
- else
- return EC_ERROR_PARAM1;
- }
-
- switch (ccd_state) {
- case CCD_STATE_OPENED:
- ccprintf("%s settings.\n", flags & CCD_RESET_FACTORY ?
- "Opening factory " : "Resetting all");
- /* Note that this does not reset the testlab flag */
- return ccd_reset_config(flags);
-
- case CCD_STATE_UNLOCKED:
- ccprintf("Resetting unlocked settings.\n");
- return ccd_reset_config(CCD_RESET_UNLOCKED_ONLY);
-
- default:
- return EC_ERROR_ACCESS_DENIED;
- }
-}
-
-static int command_ccd_set(int argc, char **argv)
-{
- enum ccd_capability cap;
- enum ccd_capability_state old;
- enum ccd_capability_state new;
-
- /* Only works if unlocked or opened */
- if (ccd_state == CCD_STATE_LOCKED)
- return EC_ERROR_ACCESS_DENIED;
-
- if (argc < 3)
- return EC_ERROR_PARAM_COUNT;
-
- /* Get capability to set */
- cap = ccd_cap_from_name(argv[1]);
- if (cap == CCD_CAP_COUNT)
- return EC_ERROR_PARAM1;
-
- /* Get new state */
- for (new = CCD_CAP_STATE_DEFAULT; new < CCD_CAP_STATE_COUNT; new++) {
- if (!strcasecmp(argv[2], ccd_cap_state_names[new]))
- break;
- }
- if (new == CCD_CAP_STATE_COUNT)
- return EC_ERROR_PARAM2;
-
- /* Get current state */
- old = raw_get_cap(cap, 1);
-
- /* If we're only unlocked, can't change to/from IfOpened */
- if (ccd_state == CCD_STATE_UNLOCKED &&
- (new == CCD_CAP_STATE_IF_OPENED || old == CCD_CAP_STATE_IF_OPENED))
- return EC_ERROR_ACCESS_DENIED;
-
- /* Set new state */
- return ccd_set_cap(cap, new);
-}
-
-static int do_ccd_password(char *password)
-{
- /* Only works if unlocked or opened */
- if (ccd_state == CCD_STATE_LOCKED)
- return EC_ERROR_ACCESS_DENIED;
-
- if (raw_has_password()) {
- const char clear_prefix[] = {'c', 'l', 'e', 'a', 'r', ':'};
-
- /*
- * The only allowed action at this point is to clear the
- * password. To do it the user is supposed to enter
- * 'clear:<passwd>'
- */
- if (strncasecmp(password, clear_prefix, sizeof(clear_prefix)))
- return EC_ERROR_ACCESS_DENIED;
-
- if (raw_check_password(password + sizeof(clear_prefix)) !=
- EC_SUCCESS)
- return EC_ERROR_ACCESS_DENIED;
-
- return ccd_reset_password();
- }
-
- /* Set new password */
- return ccd_set_password(password);
-}
-
-/*
- * Common wrapper for CCD commands which are passed through the TPM task
- * context.
- *
- * All commands could have a single parameter, which is the password (to be
- * set, cleared, or entered to open/unlock). If argc value exceeds 1, the
- * pointer to password is set, it is checked not to exceed maximum size.
- *
- * If the check succeeds, prepare a message containing a TPM vendor command,
- * have the TPM task process the message and report the result to the caller.
- *
- * Message header is always the same, the payload is the password, if
- * supplied.
- *
- * Expected output is nothing on success, or a single byte EC return code.
- */
-static int ccd_command_wrapper(int argc, char *password,
- enum ccd_vendor_subcommands subcmd)
-{
- uint8_t buf[sizeof(struct ccd_vendor_cmd_header) +
- CCD_MAX_PASSWORD_SIZE];
- struct ccd_vendor_cmd_header *vch = (struct ccd_vendor_cmd_header *)buf;
- size_t password_size = 0;
- uint32_t return_code;
-
- if (argc > 1) {
- password_size = strlen(password);
- if (password_size > CCD_MAX_PASSWORD_SIZE)
- return EC_ERROR_PARAM1;
- }
-
- /* Build the extension command to set/clear CCD password. */
- vch->tpm_header.tag = htobe16(0x8001); /* TPM_ST_NO_SESSIONS */
- vch->tpm_header.size = htobe32(sizeof(*vch) + password_size);
- vch->tpm_header.command_code = htobe32(TPM_CC_VENDOR_BIT_MASK);
- vch->tpm_header.subcommand_code = htobe16(VENDOR_CC_CCD);
- vch->ccd_subcommand = subcmd;
-
- memcpy(vch + 1, password, password_size);
- tpm_alt_extension(&vch->tpm_header, sizeof(buf));
-
- /*
- * Return status in the command code field now, in case of error,
- * error code is the first byte after the header.
- */
- return_code = be32toh(vch->tpm_header.command_code);
- if ((return_code != VENDOR_RC_SUCCESS) &&
- (return_code != (VENDOR_RC_IN_PROGRESS|VENDOR_RC_ERR))) {
- return vch->ccd_subcommand;
- }
- return EC_SUCCESS;
-}
-
-static enum vendor_cmd_rc ccd_open(struct vendor_cmd_params *p)
-{
- int is_long = 1;
- int need_pp = 1;
- int rv;
- char *buffer = p->buffer;
- const char *why_denied = "forced";
-
- if (force_disabled)
- goto denied;
-
- if (ccd_state == CCD_STATE_OPENED)
- return VENDOR_RC_SUCCESS;
-
- /* FWMP blocks open even if a password is set */
- if (!board_fwmp_allows_unlock()) {
- why_denied = "fwmp";
- goto denied;
- }
-
- /* Make sure open is allowed */
- if (raw_has_password()) {
- /* Open allowed if correct password is specified */
-
- if (!p->in_size) {
- /* ...which it wasn't */
- p->out_size = 1;
- buffer[0] = EC_ERROR_PARAM_COUNT;
- return VENDOR_RC_PASSWORD_REQUIRED;
- }
-
- /*
- * We know there is plenty of room in the TPM buffer this is
- * stored in.
- */
- buffer[p->in_size] = '\0';
- rv = raw_check_password(buffer);
- if (rv) {
- p->out_size = 1;
- buffer[0] = rv;
- return VENDOR_RC_INTERNAL_ERROR;
- }
- } else if (!board_battery_is_present()) {
- /* Open allowed with no password if battery is removed */
- } else if ((ccd_is_cap_enabled(CCD_CAP_OPEN_WITHOUT_DEV_MODE) ||
- (board_vboot_dev_mode_enabled())) &&
- (ccd_is_cap_enabled(CCD_CAP_OPEN_FROM_USB) ||
- !(p->flags & VENDOR_CMD_FROM_USB))) {
- /*
- * Open allowed with no password if dev mode enabled and
- * command came from the AP. CCD capabilities can be used to
- * bypass these checks.
- */
- } else {
- /*
- * - Battery is present
- * - Either not in developer mode or the command came from USB
- */
- why_denied = "open from AP in devmode or remove batt";
- goto denied;
- }
-
- /* Fail and abort if already checking physical presence */
- if (physical_detect_busy()) {
- physical_detect_abort();
- p->out_size = 1;
- buffer[0] = EC_ERROR_BUSY;
- return VENDOR_RC_INTERNAL_ERROR;
- }
-
- /* Reduce physical presence if enabled via config */
- if (ccd_is_cap_enabled(CCD_CAP_OPEN_WITHOUT_LONG_PP))
- is_long = 0;
- if (!is_long && ccd_is_cap_enabled(CCD_CAP_UNLOCK_WITHOUT_SHORT_PP))
- need_pp = 0;
-
- /* Bypass physical presence check entirely if battery is removed */
- if (ccd_is_cap_enabled(CCD_CAP_REMOVE_BATTERY_BYPASSES_PP) &&
- !board_battery_is_present()) {
- need_pp = 0;
- }
-
- if (need_pp) {
- /* Start physical presence detect */
- ccprintf("Starting CCD open...\n");
- rv = physical_detect_start(is_long, ccd_open_done_async);
- if (rv != EC_SUCCESS) {
- p->out_size = 1;
- buffer[0] = rv;
- return VENDOR_RC_INTERNAL_ERROR;
- }
- return VENDOR_RC_IN_PROGRESS;
- }
-
- /* No physical presence required; go straight to done */
- ccd_open_done(1);
-
- return VENDOR_RC_SUCCESS;
-
-denied:
- /* Open not allowed for some reason */
- CPRINTS("%s denied: %s", __func__, why_denied);
- p->out_size = 1;
- buffer[0] = EC_ERROR_ACCESS_DENIED;
- return VENDOR_RC_NOT_ALLOWED;
-}
-
-static enum vendor_cmd_rc ccd_unlock(struct vendor_cmd_params *p)
-{
- int need_pp = 1;
- int rv;
- char *buffer = p->buffer;
-
- if (force_disabled) {
- p->out_size = 1;
- buffer[0] = EC_ERROR_ACCESS_DENIED;
- return VENDOR_RC_NOT_ALLOWED;
- }
-
- if (ccd_state == CCD_STATE_UNLOCKED)
- return VENDOR_RC_SUCCESS;
-
- /* Can go from opened to unlocked with no delay or password */
- if (ccd_state == CCD_STATE_OPENED) {
- ccd_unlock_done();
- return VENDOR_RC_SUCCESS;
- }
-
- /* Only allowed if password is already set, and not blocked by FWMP */
- if (!raw_has_password() || !board_fwmp_allows_unlock()) {
- p->out_size = 1;
- buffer[0] = EC_ERROR_ACCESS_DENIED;
- return VENDOR_RC_NOT_ALLOWED;
- }
-
- /* Make sure password was specified */
- if (!p->in_size) {
- p->out_size = 1;
- buffer[0] = EC_ERROR_PARAM_COUNT;
- return VENDOR_RC_PASSWORD_REQUIRED;
- }
-
- /*
- * Check the password. We know there is plenty of room in the TPM
- * buffer this is stored in.
- */
- buffer[p->in_size] = '\0';
- rv = raw_check_password(buffer);
- if (rv) {
- p->out_size = 1;
- buffer[0] = rv;
- return VENDOR_RC_INTERNAL_ERROR;
- }
-
- /* Fail and abort if already checking physical presence */
- if (physical_detect_busy()) {
- physical_detect_abort();
- p->out_size = 1;
- buffer[0] = EC_ERROR_BUSY;
- return VENDOR_RC_INTERNAL_ERROR;
- }
-
- /* Bypass physical presence check if configured to do so */
- if (ccd_is_cap_enabled(CCD_CAP_UNLOCK_WITHOUT_SHORT_PP))
- need_pp = 0;
-
- /* Bypass physical presence check entirely if battery is removed */
- if (ccd_is_cap_enabled(CCD_CAP_REMOVE_BATTERY_BYPASSES_PP) &&
- !board_battery_is_present()) {
- need_pp = 0;
- }
-
- if (need_pp) {
- /* Start physical presence detect */
- ccprintf("Starting CCD unlock...\n");
- rv = physical_detect_start(0, ccd_unlock_done);
- if (rv != EC_SUCCESS) {
- p->out_size = 1;
- buffer[0] = rv;
- return VENDOR_RC_INTERNAL_ERROR;
- }
- return VENDOR_RC_IN_PROGRESS;
- }
-
- /* Unlock immediately */
- ccd_unlock_done();
-
- return VENDOR_RC_SUCCESS;
-}
-
-static enum vendor_cmd_rc ccd_lock(struct vendor_cmd_params *p)
-{
- /* Lock always works */
- ccprintf("CCD locked.\n");
- ccd_set_state(CCD_STATE_LOCKED);
- return VENDOR_RC_SUCCESS;
-}
-
-
-
-/* NOTE: Testlab command is console-only; no TPM vendor command for this */
-static int command_ccd_testlab(int argc, char **argv)
-{
- int newflag = 0;
-
- if (force_disabled)
- return EC_ERROR_ACCESS_DENIED;
-
- if (argc < 2) {
- ccprintf("CCD test lab mode %sbled\n",
- ccd_get_flag(CCD_FLAG_TEST_LAB) ? "ena" : "disa");
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "open")) {
- if (!ccd_get_flag(CCD_FLAG_TEST_LAB))
- return EC_ERROR_ACCESS_DENIED;
-
- /* Go directly to open state without wiping TPM or rebooting */
- ccd_set_state(CCD_STATE_OPENED);
- return EC_SUCCESS;
- }
-
- /* All other commands require CCD opened */
- if (ccd_state != CCD_STATE_OPENED)
- return EC_ERROR_ACCESS_DENIED;
-
- if (!parse_bool(argv[1], &newflag))
- return EC_ERROR_PARAM1;
-
- if (newflag == ccd_get_flag(CCD_FLAG_TEST_LAB))
- return EC_SUCCESS; /* No change */
-
- /* If we're still here, need to toggle test lab flag */
- ccprintf("Requesting change of test lab flag.\n");
- if (newflag)
- ccprintf("NOTE: THIS WILL MAKE THIS DEVICE INSECURE!!!\n");
- return physical_detect_start(0, ccd_testlab_toggle);
-}
-
-#ifdef CONFIG_CASE_CLOSED_DEBUG_V1_UNSAFE
-/**
- * Test command to forcibly reset CCD config
- */
-static int command_ccd_oops(void)
-{
- /* Completely reset CCD config and go to opened state */
- force_disabled = 0;
- ccprintf("Aborting physical detect...\n");
- physical_detect_abort();
- ccprintf("Resetting CCD config...\n");
- ccd_reset_config(CCD_RESET_TEST_LAB);
- ccprintf("Opening CCD...\n");
- ccd_set_state(CCD_STATE_OPENED);
- return EC_SUCCESS;
-}
-#endif /* CONFIG_CASE_CLOSED_DEBUG_V1_UNSAFE */
-
-#ifdef CONFIG_CMD_CCD_DISABLE
-static int command_ccd_disable(void)
-{
- ccd_disable();
- return EC_SUCCESS;
-}
-#endif /* CONFIG_CMD_CCD_DISABLE */
-
-static int command_ccd_help(void)
-{
- int i;
-
- ccputs("usage: ccd [cmd [args]]\n\n"
- "get (or just 'ccd')\n"
- "\tPrint current config\n\n"
- "lock\n"
- "unlock [password]\n"
- "open [password]\n"
- "\tSet CCD state\n\n"
- "set <capability> [");
- cflush();
-
- for (i = 0; i < CCD_CAP_STATE_COUNT; i++)
- ccprintf("%s%s", i ? " | " : "", ccd_cap_state_names[i]);
- ccputs("]\n"
- "\tSet capability to state\n\n"
- "password [<new password> | clear]\n"
- "\tSet or clear CCD password\n\n"
- "reset [factory]\n"
- "\tReset CCD config\n\n"
- "testlab [enable | disable | open]\n"
- "\tToggle testlab mode or force CCD open\n\n");
- cflush();
-
-#ifdef CONFIG_CASE_CLOSED_DEBUG_V1_UNSAFE
- ccputs("oops\n"
- "\tForce-reset CCD config\n\n");
-#endif
-#ifdef CONFIG_CMD_CCD_DISABLE
- ccputs("disable\n"
- "\tTemporarily disable CCD\n\n");
-#endif
-
- return EC_SUCCESS;
-}
-
-/**
- * Case closed debugging config command.
- */
-static int command_ccd_body(int argc, char **argv)
-{
- /* If no args or 'get', print info */
- if (argc < 2 || !strcasecmp(argv[1], "get"))
- return command_ccd_info();
-
- /* Check test lab command first */
- if (!strcasecmp(argv[1], "testlab"))
- return command_ccd_testlab(argc - 1, argv + 1);
-
- /* Commands to set state */
- if (!strcasecmp(argv[1], "lock"))
- return ccd_command_wrapper(0, NULL, CCDV_LOCK);
- if (!strcasecmp(argv[1], "unlock")) {
- if (!raw_has_password()) {
- ccprintf("Unlock only allowed after password is set\n");
- return EC_ERROR_ACCESS_DENIED;
- }
- return ccd_command_wrapper(argc - 1, argv[2], CCDV_UNLOCK);
- }
- if (!strcasecmp(argv[1], "open"))
- return ccd_command_wrapper(argc - 1, argv[2], CCDV_OPEN);
-
- /* Commands to configure capabilities */
- if (!strcasecmp(argv[1], "set"))
- return command_ccd_set(argc - 1, argv + 1);
- if (!strcasecmp(argv[1], "password")) {
- if (argc != 3)
- return EC_ERROR_PARAM_COUNT;
- return ccd_command_wrapper(argc - 1, argv[2], CCDV_PASSWORD);
- }
- if (!strcasecmp(argv[1], "reset"))
- return command_ccd_reset(argc - 1, argv + 1);
-
- /* Optional commands */
-#ifdef CONFIG_CASE_CLOSED_DEBUG_V1_UNSAFE
- if (!strcasecmp(argv[1], "oops"))
- return command_ccd_oops();
-#endif
-#ifdef CONFIG_CMD_CCD_DISABLE
- if (!strcasecmp(argv[1], "disable"))
- return command_ccd_disable();
-#endif
-
- /* Anything else (including "help") prints help */
- return command_ccd_help();
-}
-
-static int command_ccd(int argc, char **argv)
-{
- int rv;
-
- ccd_console_active = 1;
- rv = command_ccd_body(argc, argv);
- ccd_console_active = 0;
-
- return rv;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(ccd, command_ccd,
- "[help | ...]",
- "Configure case-closed debugging");
-
-/*
- * Handle the CCVD_PASSWORD subcommand.
- *
- * The payload of the command is a text string to use to set or clear the
- * password.
- */
-static enum vendor_cmd_rc ccd_password(struct vendor_cmd_params *p)
-{
- int rv = EC_SUCCESS;
- char password[CCD_MAX_PASSWORD_SIZE + 1];
- char *response = p->buffer;
-
- /*
- * Only allow setting a password from the AP, not USB. This increases
- * the effort required for an attacker to set one externally, even if
- * they have access to a system someone left in the opened state.
- *
- * An attacker can still set testlab mode or open up the CCD config,
- * but those changes are reversible by the device owner.
- */
- if (p->flags & VENDOR_CMD_FROM_USB) {
- p->out_size = 1;
- *response = EC_ERROR_ACCESS_DENIED;
- return VENDOR_RC_NOT_ALLOWED;
- }
-
- if (!p->in_size || (p->in_size >= sizeof(password))) {
- rv = EC_ERROR_PARAM1;
- } else {
- memcpy(password, p->buffer, p->in_size);
- password[p->in_size] = '\0';
- rv = do_ccd_password(password);
- always_memset(password, 0, p->in_size);
- }
-
- if (rv != EC_SUCCESS) {
- *response = rv;
- p->out_size = 1;
- return VENDOR_RC_INTERNAL_ERROR;
- }
-
- return VENDOR_RC_SUCCESS;
-}
-
-static enum vendor_cmd_rc ccd_pp_poll(struct vendor_cmd_params *p)
-{
- char *buffer = p->buffer;
-
- if ((ccd_state == CCD_STATE_OPENED) ||
- (ccd_state == CCD_STATE_UNLOCKED)) {
- buffer[0] = CCD_PP_DONE;
- } else {
- switch (physical_presense_fsm_state()) {
- case PP_AWAITING_PRESS:
- buffer[0] = CCD_PP_AWAITING_PRESS;
- break;
- case PP_BETWEEN_PRESSES:
- buffer[0] = CCD_PP_BETWEEN_PRESSES;
- break;
- default:
- buffer[0] = CCD_PP_CLOSED;
- break;
- }
- }
- p->out_size = 1;
- return VENDOR_RC_SUCCESS;
-}
-
-static enum vendor_cmd_rc ccd_pp_poll_unlock(struct vendor_cmd_params *p)
-{
- char *buffer = p->buffer;
-
- if ((ccd_state != CCD_STATE_OPENED) &&
- (ccd_state != CCD_STATE_UNLOCKED))
- return ccd_pp_poll(p);
-
- p->out_size = 1;
- buffer[0] = CCD_PP_DONE;
-
- return VENDOR_RC_SUCCESS;
-}
-
-static enum vendor_cmd_rc ccd_pp_poll_open(struct vendor_cmd_params *p)
-{
- char *buffer = p->buffer;
-
- if (ccd_state != CCD_STATE_OPENED)
- return ccd_pp_poll(p);
-
- p->out_size = 1;
- buffer[0] = CCD_PP_DONE;
-
- return VENDOR_RC_SUCCESS;
-}
-
-static enum vendor_cmd_rc ccd_get_info(struct vendor_cmd_params *p)
-{
- int i;
- struct ccd_info_response response = {};
-
- for (i = 0; i < CCD_CAP_COUNT; i++) {
- int index;
- int shift;
-
- /* Each capability takes 2 bits. */
- index = i / (32 / CCD_CAP_BITS);
- shift = (i % (32 / CCD_CAP_BITS)) * CCD_CAP_BITS;
- response.ccd_caps_current[index] |= raw_get_cap(i, 1) << shift;
- response.ccd_caps_defaults[index] |=
- cap_info[i].default_state << shift;
- }
-
- response.ccd_flags = htobe32(raw_get_flags());
- response.ccd_state = ccd_get_state();
- response.ccd_indicator_bitmap = raw_has_password() ?
- CCD_INDICATOR_BIT_HAS_PASSWORD : 0;
- response.ccd_indicator_bitmap |= raw_check_all_caps_default() ?
- CCD_INDICATOR_BIT_ALL_CAPS_DEFAULT : 0;
- response.ccd_force_disabled = force_disabled;
- for (i = 0; i < ARRAY_SIZE(response.ccd_caps_current); i++) {
- response.ccd_caps_current[i] =
- htobe32(response.ccd_caps_current[i]);
- response.ccd_caps_defaults[i] =
- htobe32(response.ccd_caps_defaults[i]);
- }
-
- p->out_size = sizeof(response);
- memcpy(p->buffer, &response, sizeof(response));
-
- return VENDOR_RC_SUCCESS;
-}
-
-/*
- * Common TPM Vendor command handler used to demultiplex various CCD commands
- * which need to be available both throuh CLI and over /dev/tpm0.
- */
-static enum vendor_cmd_rc ccd_vendor(struct vendor_cmd_params *p)
-{
- enum vendor_cmd_rc (*handler)(struct vendor_cmd_params *p);
- enum vendor_cmd_rc rc;
-
- /*
- * The command buffer points to the next byte after tpm header, i.e. to
- * the CCD subcommand. Cache the pointer to make it easier to access
- * and manipulate.
- */
- char *buffer = p->buffer;
-
- /*
- * Make sure the buffer is large enough to accommodate any CCD
- * subcommand response (plus one byte, since the response is shifted),
- * so we can skip size checks in the processing functions.
- */
- if (p->out_size < sizeof(struct ccd_info_response) + 1) {
- p->out_size = 0;
- return VENDOR_RC_RESPONSE_TOO_BIG;
- }
-
- /* Now we can assume no output data unless proven otherwise */
- p->out_size = 0;
-
- /* Pick what to do based on subcommand. */
- switch (buffer[0]) {
- case CCDV_PASSWORD:
- handler = ccd_password;
- break;
-
- case CCDV_OPEN:
- handler = ccd_open;
- break;
-
- case CCDV_UNLOCK:
- handler = ccd_unlock;
- break;
-
- case CCDV_LOCK:
- handler = ccd_lock;
- break;
-
- case CCDV_PP_POLL_UNLOCK:
- handler = ccd_pp_poll_unlock;
- break;
-
- case CCDV_PP_POLL_OPEN:
- handler = ccd_pp_poll_open;
- break;
-
- case CCDV_GET_INFO:
- handler = ccd_get_info;
- break;
-
- default:
- CPRINTS("%s:%d - unknown subcommand", __func__, __LINE__);
- return VENDOR_RC_NO_SUCH_SUBCOMMAND;
- }
-
- /* Shift buffer past the subcommand when calling the handler */
- p->buffer = buffer + 1;
- p->in_size--;
- rc = handler(p);
- p->buffer = buffer;
- p->in_size++;
-
- /*
- * Move response up for the master to see it in the right
- * place in the response buffer. We have to do this because the
- * first byte of the buffer on input was the subcommand, so we
- * passed buffer + 1 in the handler call above.
- */
- memmove(buffer, buffer + 1, p->out_size);
- return rc;
-}
-DECLARE_VENDOR_COMMAND_P(VENDOR_CC_CCD, ccd_vendor);
-
-static enum vendor_cmd_rc ccd_disable_factory_mode(enum vendor_cmd_cc code,
- void *buf,
- size_t input_size,
- size_t *response_size)
-{
- int rv = EC_SUCCESS;
- int error_line;
-
- do {
- if (raw_has_password()) {
- error_line = __LINE__;
- rv = EC_ERROR_ACCESS_DENIED;
- break;
- }
-
- /* Check if physical presence is required to unlock. */
- if (!ccd_is_cap_enabled(CCD_CAP_REMOVE_BATTERY_BYPASSES_PP) ||
- board_battery_is_present()) {
- const uint8_t required_capabilities[] = {
- CCD_CAP_OPEN_WITHOUT_TPM_WIPE,
- CCD_CAP_UNLOCK_WITHOUT_AP_REBOOT,
- CCD_CAP_OPEN_WITHOUT_LONG_PP,
- CCD_CAP_UNLOCK_WITHOUT_SHORT_PP
- };
- unsigned int i;
-
- for (i = 0;
- i < ARRAY_SIZE(required_capabilities);
- i++) {
- if (!ccd_is_cap_enabled
- (required_capabilities[i]))
- break;
- }
-
- if (i < ARRAY_SIZE(required_capabilities)) {
- CPRINTF("Capability %d is not present\n",
- required_capabilities[i]);
- error_line = __LINE__;
- rv = EC_ERROR_ACCESS_DENIED;
- break;
- }
- }
-
- ccd_set_state(CCD_STATE_OPENED);
-
- rv = command_ccd_reset(0, NULL);
- if (rv != EC_SUCCESS) {
- error_line = __LINE__;
- break;
- }
-
-
- ccd_lock(NULL);
-
- /*
- * We do it here to make sure that the device comes out of
- * factory mode with WP enabled, but in general CCD reset needs
- * to enforce WP state.
- *
- * TODO(rspangler): sort out CCD state and WP correlation,
- * b/73075443.
- */
- board_wp_follow_ccd_config();
-
- /*
- * Use raw_set_flag() because the factory mode flag is internal
- */
- mutex_lock(&ccd_config_mutex);
- raw_set_flag(CCD_FLAG_FACTORY_MODE_ENABLED, 0);
- mutex_unlock(&ccd_config_mutex);
-
- *response_size = 0;
- return VENDOR_RC_SUCCESS;
- } while (0);
-
- CPRINTF("%s: error in line %d\n", __func__, error_line);
-
- ((uint8_t *)buf)[0] = (uint8_t)rv;
- *response_size = 1;
- return VENDOR_RC_INTERNAL_ERROR;
-}
-DECLARE_VENDOR_COMMAND(VENDOR_CC_DISABLE_FACTORY, ccd_disable_factory_mode);
diff --git a/common/extension.c b/common/extension.c
deleted file mode 100644
index d2a26a6cd2..0000000000
--- a/common/extension.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/* Copyright 2015 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 "byteorder.h"
-#include "console.h"
-#include "extension.h"
-#include "link_defs.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_EXTENSION, format, ## args)
-
-uint32_t extension_route_command(struct vendor_cmd_params *p)
-{
- struct extension_command *cmd_p;
- struct extension_command *end_p;
- const char *why_ignore = "not found";
-
-#ifdef DEBUG_EXTENSION
- CPRINTS("%s(%d,%s) is=%d os=%d", __func__, p->code,
- p->flags & VENDOR_CMD_FROM_USB ? "USB" : "AP",
- p->in_size, p->out_size);
-#endif
-
- /* Filter commands from USB */
- if (p->flags & VENDOR_CMD_FROM_USB) {
- switch (p->code) {
-#ifdef CR50_DEV
- case VENDOR_CC_IMMEDIATE_RESET:
- case VENDOR_CC_INVALIDATE_INACTIVE_RW:
- case VENDOR_CC_SET_BOARD_ID:
- case VENDOR_CC_TPM_MODE:
- case VENDOR_CC_SN_SET_HASH:
- case VENDOR_CC_SN_INC_RMA:
- case VENDOR_CC_ENDORSEMENT_SEED:
-#endif /* defined(CR50_DEV) */
- case EXTENSION_POST_RESET: /* Always need to reset. */
- case VENDOR_CC_CCD:
- case VENDOR_CC_GET_BOARD_ID:
- case VENDOR_CC_RMA_CHALLENGE_RESPONSE:
- case VENDOR_CC_SPI_HASH: /* Requires physical presence. */
- case VENDOR_CC_TURN_UPDATE_ON:
- break;
- default:
- /* Otherwise, we don't allow this command. */
- why_ignore = "usb";
- goto ignore_cmd;
- }
- }
-
-#ifdef CONFIG_BOARD_ID_SUPPORT
- /*
- * If board ID is mismatched, allow only the commands needed to upgrade
- * Cr50 firmware.
- */
- if (board_id_is_mismatched()) {
- switch (p->code) {
- case EXTENSION_FW_UPGRADE:
- case VENDOR_CC_REPORT_TPM_STATE:
- case VENDOR_CC_TURN_UPDATE_ON:
- case EXTENSION_POST_RESET:
- break;
- default:
- why_ignore = "BoardID mismatch";
- goto ignore_cmd;
- }
- }
-#endif
-
- /* Find the command handler */
- cmd_p = (struct extension_command *)&__extension_cmds;
- end_p = (struct extension_command *)&__extension_cmds_end;
- while (cmd_p != end_p) {
- if (cmd_p->command_code == p->code)
- return cmd_p->handler(p);
- cmd_p++;
- }
-
-ignore_cmd:
- /* Command not found or not allowed */
- CPRINTS("%s: ignore %d: %s", __func__, p->code, why_ignore);
- p->out_size = 0;
- return VENDOR_RC_NO_SUCH_COMMAND;
-}
diff --git a/common/factory_mode.c b/common/factory_mode.c
deleted file mode 100644
index c1d6789b91..0000000000
--- a/common/factory_mode.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/* CCD factory enable */
-
-#include "ccd_config.h"
-#include "console.h"
-#include "extension.h"
-#include "hooks.h"
-#include "system.h"
-#include "tpm_registers.h"
-#include "tpm_vendor_cmds.h"
-
-#define CPRINTS(format, args...) cprints(CC_CCD, format, ## args)
-
-static uint8_t wait_for_factory_ccd_change;
-static uint8_t reset_required_;
-
-static void factory_config_saved(int saved)
-{
- wait_for_factory_ccd_change = 0;
-
- CPRINTS("%s: %s%s", __func__, saved ? "done" : "failed",
- reset_required_ ? ", rebooting" : "");
-
- if (!reset_required_)
- return;
-
- cflush();
- system_reset(SYSTEM_RESET_HARD);
-}
-
-static void ccd_config_changed(void)
-{
- if (!wait_for_factory_ccd_change)
- return;
-
- factory_config_saved(1);
-}
-DECLARE_HOOK(HOOK_CCD_CHANGE, ccd_config_changed, HOOK_PRIO_LAST);
-
-static void force_system_reset(void)
-{
- CPRINTS("ccd hook didn't reset the system");
- factory_config_saved(0);
-}
-DECLARE_DEFERRED(force_system_reset);
-
-static void factory_enable_deferred(void)
-{
- int rv;
-
- if (board_wipe_tpm(reset_required_) != EC_SUCCESS)
- return;
-
- CPRINTS("%s: TPM reset done, enabling factory mode", __func__);
-
- wait_for_factory_ccd_change = 1;
- rv = ccd_reset_config(CCD_RESET_FACTORY);
- if (rv != EC_SUCCESS)
- factory_config_saved(0);
-
- if (reset_required_) {
- /*
- * Cr50 will reset once factory mode is enabled. If it hasn't in
- * TPM_RESET_TIME, declare factory enable failed and force the
- * reset.
- */
- hook_call_deferred(&force_system_reset_data, TPM_RESET_TIME);
- }
-}
-DECLARE_DEFERRED(factory_enable_deferred);
-
-void enable_ccd_factory_mode(int reset_required)
-{
- /*
- * Wiping the TPM may take a while. Delay sleep long enough for the
- * factory enable process to finish.
- */
- delay_sleep_by(DISABLE_SLEEP_TIME_TPM_WIPE);
-
- reset_required_ |= !!reset_required;
- hook_call_deferred(&factory_enable_deferred_data,
- TPM_PROCESSING_TIME);
-}
diff --git a/common/flash_log.c b/common/flash_log.c
deleted file mode 100644
index 798f48a2a6..0000000000
--- a/common/flash_log.c
+++ /dev/null
@@ -1,589 +0,0 @@
-/* Copyright 2019 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 "console.h"
-#include "crc8.h"
-#include "flash_log.h"
-#include "flash.h"
-#include "hooks.h"
-#include "shared_mem.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-/*
- * A few assumptions this log facility design is based on are:
- *
- * - the log is stored in a flash space configured per board/chip combination.
- * Chip level physical access functions are used for writing and erasing.
- *
- * - flash space access control is transparent for the log facility, if
- * necessary, chip driver can register a callback for flash access control.
- *
- * - log events are rare, attempts to log concurrent events could fail.
- *
- * - log events are retrieved by the host periodically, much sooner than log
- * overflows
- *
- * - as presented this facility is not suitable for saving panics'
- * information, because flash drivers usually require OS services like
- * interrupts, events, etc.
- *
- * - at the point of logging an entry there is still 200 bytes or so of stack
- * is available.
- *
- * With the above in mind, here is the basic design:
- *
- * Entries in the log are of variable size, this layer is completely oblivious
- * to the entries' contents. Each entry is saved in the log prepended by a
- * header, which includes the following fields:
- *
- * - entry type, 1 byte
- * - the timestamp the entry is saved at, 4 bytes, if real time is not
- * available a monotonously increasing number is used
- * - entry size, one byte, size is limited to 63 bytes maximum, two top bits
- * of the size byte could be used as flags.
- * - the entry crc, 1 byte
- *
- * To satisfy flash access limitations, this facility pads log entries to a
- * multiple of the physical flash write size. Padding bytes value is set to
- * FE_LOG_PAD. Having a fixed padding value will make it easier to examine log
- * space snapshots by third party software. The users of this service are
- * oblivious to the padding, they write and read back entries of arbitrary not
- * necessarily aligned sizes in 0..MAX_FLASH_LOG_PAYLOAD_SIZE range.
- *
- * The log is kept in one flash page. Entries are of variable size, as defined
- * by entry header. For read accesses log is mapped directly into the address
- * space, write accesses are handled by chip specific drivers.
- *
- * On each startup, if the log is more than three quarters full, the log flash
- * space is erased and a quarter space worth from top of the log is written
- * back at the bottom of the erased space.
- *
- * If an entry would not fit into the log it is silently dropped.
- *
- * Log entries can not be written or read from within interrupt processing
- * routines.
- *
- * Only one read or write access can be in progress at a time. Attempts to log
- * new events while a log entry is being saved or retrieved will be ignored.
- * Attempts to retrieve an entry while another entry is being saved or
- * retrieved will return the appropriate return value.
- *
- * At run time log compaction is attempted if a request to add an entry is
- * made and the log is more than 90% full. If compaction is not possible (for
- * example, if memory allocation fails) and the new entry does not fit, it
- * would be dropped.
- *
- * The above mentioned failures are tracked and when log becomes operational
- * again (for instance memory heap grew back), log entries are added to record
- * previously encountered failures.
- *
- * The API to retrieve log entries gets the timestamp of the last retrieved
- * entry as an input parameter and returns the next entry exists. Sequence of
- * invocations of the log entry retrieval API starting with timestamp of zero
- * and then repeating with the timestamp of the previously retrieved entry
- * allows to traverse the entire log.
- *
- * Initialization function verifies log integrity. When initializing from an
- * erased space, the initialization function saves a new entry of type
- * FE_LOG_START. If log corruption is detected, the initialization function
- * tries to compact the log and adds a new entry of type FE_LOG_CORRUPTED on
- * top of the compacted log.
- */
-
-/*
- * Structure keeping the context of the last entry retrieval access. If the
- * next retrieval passed in timestamp saved in prev_timestamp, log search
- * starts at read_cursor.
- */
-static struct {
- uint16_t read_cursor;
- uint32_t prev_timestamp;
-} log_read_context;
-
-/* Location where next entry is going to be added. */
-static uint16_t log_write_cursor;
-/*
- * Base time in seconds, during init set to the time of the latest present log
- * entry +1, expected be set by the host to current time. Log entries
- * timestamps are set to this value plus uptime.
- */
-static uint32_t log_tstamp_base;
-
-/*
- * Keep track of the last used timestamp value to make sure there are no two
- * entries with the same timestamp.
- */
-test_mockable_static uint32_t last_used_timestamp;
-
-/* Set to True after log has been initialized. */
-static uint8_t log_inited;
-test_mockable_static uint8_t log_event_in_progress;
-test_mockable_static uint32_t lock_failures_count;
-static uint32_t overflow_failures_count;
-
-/*
- * Callback set by the chip if flash log space access requires additional
- * access control.
- */
-static void (*platform_flash_control)(int enable);
-
-/*
- * Helper function, convert offset in the log into a physical address in
- * flash.
- */
-static const void *log_offset_to_addr(uint16_t log_offset)
-{
- return (const void *)(CONFIG_FLASH_LOG_BASE + log_offset);
-}
-
-/* Wrappers around chip flash access functions. */
-static void flash_log_erase(void)
-{
- flash_physical_erase(CONFIG_FLASH_LOG_BASE - CONFIG_PROGRAM_MEMORY_BASE,
- CONFIG_FLASH_LOG_SPACE);
-}
-
-static void flash_log_write(uint16_t log_offset, const void *data,
- size_t data_size)
-{
- flash_physical_write(log_offset + CONFIG_FLASH_LOG_BASE -
- CONFIG_PROGRAM_MEMORY_BASE,
- data_size, data);
-}
-
-/* Wrappers around platform flash control function, if registered. */
-static void flash_log_write_enable(void)
-{
- if (platform_flash_control)
- platform_flash_control(1);
-}
-
-static void flash_log_write_disable(void)
-{
- if (platform_flash_control)
- platform_flash_control(0);
-}
-
-/*
- * Wrapper around crc8 calculation to avoid excessive typecasting throughout
- * the rest of the file.
- */
-static uint8_t calc_crc8(const void *buf, size_t size, uint8_t prev)
-{
- return crc8_arg((const uint8_t *)buf, size, prev);
-}
-
-/* Try grabbing the lock, non blocking, return True if succeeded. */
-static int flash_log_lock_successful(void)
-{
- if (in_interrupt_context())
- return 0;
-
- if (!log_inited)
- return 0;
-
- interrupt_disable();
- if (log_event_in_progress) {
- /* What a coincidence! */
- interrupt_enable();
- return 0;
- }
- log_event_in_progress = 1;
- interrupt_enable();
- return 1;
-}
-
-/*
- * Verify entry validity, i.e. that it does fit into the log, has size within
- * range and its crc8 matches.
- */
-static int entry_is_valid(const struct flash_log_entry *r)
-{
- size_t entry_size;
- uint32_t entry_offset;
- struct flash_log_entry copy;
-
- entry_size = FLASH_LOG_ENTRY_SIZE(r->size);
- entry_offset = (uintptr_t)r - CONFIG_FLASH_LOG_BASE;
-
- if ((entry_offset + entry_size) > CONFIG_FLASH_LOG_SPACE)
- return 0;
-
- /* Crc of the entry is calculated with the crc field set to zero. */
- copy = *r;
- copy.crc = 0;
- copy.crc = calc_crc8(&copy, sizeof(copy), 0);
- copy.crc = calc_crc8(r + 1, FLASH_LOG_PAYLOAD_SIZE(r->size), copy.crc);
- return (copy.crc == r->crc);
-}
-
-/* Attempt compacting the log. Could fail if memory allocation fails. */
-static void try_compacting(void)
-{
- char *buf;
- uint16_t read_cursor = 0;
- uint16_t compac_cursor = 0;
-
- /* Try rewriting the top 25% of the log into its bottom. */
- /*
- * Fist allocate a buffer large enough to keep a quarter of the
- * log.
- */
- if (shared_mem_acquire(COMPACTION_SPACE_PRESERVE, &buf) != EC_SUCCESS)
- return;
-
- while (read_cursor < log_write_cursor) {
- const struct flash_log_entry *r;
- size_t entry_space;
-
- r = log_offset_to_addr(read_cursor);
- if (!entry_is_valid(r))
- break;
-
- entry_space = FLASH_LOG_ENTRY_SIZE(r->size);
-
- if ((log_write_cursor - read_cursor) <=
- COMPACTION_SPACE_PRESERVE) {
- memcpy(buf + compac_cursor, r, entry_space);
- compac_cursor += entry_space;
- }
-
- read_cursor += entry_space;
- }
-
- flash_log_write_enable();
- flash_log_erase();
- flash_log_write(0, buf, compac_cursor);
- log_write_cursor = compac_cursor;
- flash_log_write_disable();
-
- shared_mem_release(buf);
-
- log_read_context.read_cursor = 0;
- log_read_context.prev_timestamp = 0;
-}
-
-static enum ec_error_list flash_log_add_event_core(uint8_t type, uint8_t size,
- void *payload)
-{
- union entry_u e;
- size_t padded_entry_size;
- size_t entry_size;
- enum ec_error_list rv = EC_ERROR_INVAL;
- uint32_t new_timestamp;
-
- if (size > MAX_FLASH_LOG_PAYLOAD_SIZE)
- return rv;
-
- if (!flash_log_lock_successful()) {
- lock_failures_count++;
- return rv;
- }
-
- /* The entry will take this much space in the flash. */
- padded_entry_size = FLASH_LOG_ENTRY_SIZE(size);
-
- if (log_write_cursor > RUN_TIME_LOG_FULL_WATERMARK)
- try_compacting();
-
- if (padded_entry_size > (CONFIG_FLASH_LOG_SPACE - log_write_cursor)) {
- /*
- * Compaction must have failed or was not allowed, and no room
- * to log.
- */
- overflow_failures_count++;
- goto log_add_exit;
- }
-
- /* Copy the payload into the entry if necessary. */
- if (size)
- memcpy(e.r.payload, payload, size);
-
- entry_size = sizeof(e.r) + size;
-
- new_timestamp = flash_log_get_tstamp();
-
- /*
- * Avoid rolling back or logging more than one entry with the same
- * timestamp.
- */
- if (last_used_timestamp >= new_timestamp)
- last_used_timestamp += 1;
- else
- last_used_timestamp = new_timestamp;
-
- e.r.timestamp = last_used_timestamp;
- e.r.size = size;
- e.r.type = type;
- e.r.crc = 0;
- e.r.crc = calc_crc8(e.entry, entry_size, 0);
-
- /* Add padding if necessary. */
- while (entry_size < padded_entry_size)
- e.entry[entry_size++] = FE_LOG_PAD;
-
- flash_log_write_enable();
- flash_log_write(log_write_cursor, e.entry, padded_entry_size);
- flash_log_write_disable();
-
- log_write_cursor += padded_entry_size;
-
- rv = EC_SUCCESS;
-
-log_add_exit:
- log_event_in_progress = 0;
-
- return rv;
-}
-
-/*
- * Report the failure count, using the passed in type. If report attempt is
- * successful, reset the counter.
- *
- * Even though the counter is 4 bytes in size, the log entry payload is a one
- * byte value capped at 255: the failure counter is extremely unlikely to
- * exceed this value, and if it does - we don't really care about the exact
- * number.
- */
-static void report_failure(enum flash_event_type type, uint32_t *counter)
-{
- uint8_t reported_counter;
-
- /*
- * Let's truncate the value at one byte, it is extremely unlikely to
- * exceed it.
- */
- reported_counter = *counter;
- if (reported_counter > 255)
- reported_counter = 255;
-
- if (flash_log_add_event_core(type, sizeof(reported_counter),
- &reported_counter) == EC_SUCCESS)
- *counter = 0;
-}
-
-void flash_log_add_event(uint8_t type, uint8_t size, void *payload)
-{
- if (lock_failures_count)
- report_failure(FE_LOG_LOCKS, &lock_failures_count);
-
- if (overflow_failures_count)
- report_failure(FE_LOG_OVERFLOWS, &overflow_failures_count);
-
- flash_log_add_event_core(type, size, payload);
-}
-
-int flash_log_dequeue_event(uint32_t event_after, void *buffer,
- size_t buffer_size)
-{
- const struct flash_log_entry *r;
- int rv = 0;
- size_t copy_size;
-
- if (!flash_log_lock_successful())
- return -EC_ERROR_BUSY;
-
- if (!event_after || (event_after < log_read_context.prev_timestamp)) {
- /* Will have to start over. */
- log_read_context.read_cursor = 0;
- log_read_context.prev_timestamp = 0;
- }
-
- if (log_read_context.read_cursor >
- (CONFIG_FLASH_LOG_SPACE - sizeof(*r)))
- /* No more room in the log. */
- goto log_read_exit;
-
- do {
- r = log_offset_to_addr(log_read_context.read_cursor);
- if (r->timestamp == CONFIG_FLASH_ERASED_VALUE32)
- /* Points at erased space, no more entries. */
- goto log_read_exit;
-
- if (!entry_is_valid(r)) {
- rv = -EC_ERROR_INVAL;
- goto log_read_exit;
- }
-
- log_read_context.read_cursor += FLASH_LOG_ENTRY_SIZE(r->size);
-
- } while (r->timestamp <= event_after);
-
- /*
- * If we are here, we found the next event, let's see if it fits into
- * the buffer.
- */
- copy_size = FLASH_LOG_PAYLOAD_SIZE(r->size) + sizeof(*r);
- if (copy_size > buffer_size) {
- rv = -EC_ERROR_MEMORY_ALLOCATION;
- /* To be on the safe side will start over next time. */
- log_read_context.read_cursor = 0;
- log_read_context.prev_timestamp = 0;
- goto log_read_exit;
- }
-
- log_read_context.prev_timestamp = r->timestamp;
- memcpy(buffer, r, copy_size);
- rv = copy_size;
-
-log_read_exit:
- log_event_in_progress = 0;
- return rv;
-}
-
-void flash_log_register_flash_control_callback(
- void (*flash_control)(int enable))
-{
- platform_flash_control = flash_control;
-}
-
-test_export_static void flash_log_init(void)
-{
- uint16_t read_cursor = 0;
- const struct flash_log_entry *r;
-
- r = log_offset_to_addr(read_cursor);
- while (entry_is_valid(r)) {
- last_used_timestamp = r->timestamp;
- read_cursor += FLASH_LOG_ENTRY_SIZE(r->size);
- r = log_offset_to_addr(read_cursor);
- }
-
- /* Should be updated by the AP soon after booting. */
- log_tstamp_base = last_used_timestamp + 1;
-
- log_write_cursor = read_cursor;
- log_inited = 1;
-
- flash_log_write_enable();
- if (r->timestamp != CONFIG_FLASH_ERASED_VALUE32) {
- /* Log space must be corrupted, compact it. */
- try_compacting();
- flash_log_add_event(FE_LOG_CORRUPTED, 0, NULL);
- flash_log_write_disable();
- return;
- }
-
- /*
- * Timestamp field is set to all ones, presumably this points to free
- * space in the log.
- *
- * Is there anything at all in the log?
- */
- if (read_cursor) {
- /*
- * Next write will have to come here unless compacting changes
- * that.
- */
- if (read_cursor > STARTUP_LOG_FULL_WATERMARK)
- try_compacting();
- } else {
- flash_log_add_event(FE_LOG_START, 0, NULL);
- }
- flash_log_write_disable();
-}
-DECLARE_HOOK(HOOK_INIT, flash_log_init, HOOK_PRIO_DEFAULT);
-
-uint32_t flash_log_get_tstamp(void)
-{
- return log_tstamp_base + get_time().val/1000000;
-}
-
-enum ec_error_list flash_log_set_tstamp(uint32_t tstamp)
-{
- if (tstamp <= last_used_timestamp)
- return EC_ERROR_INVAL;
-
- log_tstamp_base = tstamp - get_time().val/1000000;
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_CMD_FLASH_LOG
-/*
- * Display Flash event log.
- */
-static int command_flash_log(int argc, char **argv)
-{
- uint32_t stamp = 0;
- union entry_u e;
- int rv;
- uint32_t type;
- size_t size;
- size_t i;
-
- if (argc > 1) {
- if (!strcasecmp(argv[1], "-e")) {
- ccprintf("Erasing flash log\n");
- flash_log_write_enable();
- flash_log_erase();
- flash_log_write_disable();
-
- log_read_context.read_cursor = 0;
- log_read_context.prev_timestamp = 0;
- log_write_cursor = 0;
-
- argc--;
- argv++;
- }
- }
- if (argc < 3) {
- if (argc == 2)
- stamp = atoi(argv[1]);
-
- /* Retrieve entries newer than 'stamp'. */
- while ((rv = flash_log_dequeue_event(stamp, e.entry,
- sizeof(e))) > 0) {
- size_t i;
-
- ccprintf("%10u:%02x", e.r.timestamp, e.r.type);
- for (i = 0; i < FLASH_LOG_PAYLOAD_SIZE(e.r.size); i++) {
- if (i && !(i % 16))
- ccprintf("\n ");
- ccprintf(" %02x", e.r.payload[i]);
- }
- ccprintf("\n");
- cflush();
- stamp = e.r.timestamp;
- }
- if (rv)
- ccprintf("Warning: Last attempt to dequeue returned "
- "%d\n",
- rv);
- return EC_SUCCESS;
- }
-
- if (argc != 3) {
- ccprintf("type and size of the entry are required\n");
- return EC_ERROR_PARAM_COUNT;
- }
-
- type = atoi(argv[1]);
- size = atoi(argv[2]);
-
- if (type >= FLASH_LOG_NO_ENTRY) {
- ccprintf("type must not exceed %d\n", FLASH_LOG_NO_ENTRY - 1);
- return EC_ERROR_PARAM2;
- }
-
- if (size > MAX_FLASH_LOG_PAYLOAD_SIZE) {
- ccprintf("size must not exceed %d\n",
- MAX_FLASH_LOG_PAYLOAD_SIZE);
- return EC_ERROR_PARAM3;
- }
-
- for (i = 0; i < size; i++)
- e.r.payload[i] = type + i;
- flash_log_add_event(type, size, e.r.payload);
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(flog, command_flash_log,
- "[-e] ][[stamp]|[<type> <size>]]",
- "Dump on the console the flash log contents,"
- "optionally erasing it\n"
- "or add a new entry of <type> and <size> bytes");
-#endif
diff --git a/common/flash_log_vc.c b/common/flash_log_vc.c
deleted file mode 100644
index 5d1515a754..0000000000
--- a/common/flash_log_vc.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Copyright 2019 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 "console.h"
-#include "extension.h"
-#include "endian.h"
-#include "flash_log.h"
-#include "util.h"
-
-static enum vendor_cmd_rc vc_pop_log_entry(enum vendor_cmd_cc code, void *buf,
- size_t input_size,
- size_t *response_size)
-{
- uint32_t prev_timestamp;
- int byte_size;
-
- *response_size = 0; /* In case there is an error. */
-
- if (input_size != sizeof(prev_timestamp))
- return VENDOR_RC_BOGUS_ARGS;
-
- memcpy(&prev_timestamp, buf, sizeof(prev_timestamp));
-
- byte_size = flash_log_dequeue_event(
- prev_timestamp, buf,
- FLASH_LOG_ENTRY_SIZE(MAX_FLASH_LOG_PAYLOAD_SIZE));
-
- if (byte_size >= 0) {
- *response_size = byte_size;
- return VENDOR_RC_SUCCESS;
- }
-
- /* Negative value should fit into a byte. */
- *response_size = 1;
- ((uint8_t *)buf)[0] = -byte_size;
-
- return VENDOR_RC_INTERNAL_ERROR;
-}
-DECLARE_VENDOR_COMMAND(VENDOR_CC_POP_LOG_ENTRY, vc_pop_log_entry);
-
-static enum vendor_cmd_rc vc_flog_tstamp(enum vendor_cmd_cc code, void *buf,
- size_t input_size,
- size_t *response_size)
-{
- uint32_t tstamp;
- enum ec_error_list rv;
-
- if (!input_size) {
- /* This is a request to report current flash log time. */
- tstamp = htobe32(flash_log_get_tstamp());
- memcpy(buf, &tstamp, sizeof(tstamp));
- *response_size = sizeof(tstamp);
- return VENDOR_RC_SUCCESS;
- }
-
- if (input_size != sizeof(tstamp))
- return VENDOR_RC_BOGUS_ARGS;
-
- memcpy(&tstamp, buf, sizeof(tstamp));
- tstamp = be32toh(tstamp);
- rv = flash_log_set_tstamp(tstamp);
-
- if (rv == EC_SUCCESS) {
- *response_size = 0;
- return VENDOR_RC_SUCCESS;
- }
-
- *response_size = 1;
- *((uint8_t *)buf) = (uint8_t)rv;
- return VENDOR_RC_BOGUS_ARGS;
-}
-DECLARE_VENDOR_COMMAND(VENDOR_CC_FLOG_TIMESTAMP, vc_flog_tstamp);
diff --git a/common/hooks.c b/common/hooks.c
index dcdb4d8ee4..2dd0289741 100644
--- a/common/hooks.c
+++ b/common/hooks.c
@@ -48,9 +48,6 @@ static const struct hook_ptrs hook_list[] = {
{__hooks_base_attached_change, __hooks_base_attached_change_end},
{__hooks_pwrbtn_change, __hooks_pwrbtn_change_end},
{__hooks_battery_soc_change, __hooks_battery_soc_change_end},
-#ifdef CONFIG_CASE_CLOSED_DEBUG_V1
- {__hooks_ccd_change, __hooks_ccd_change_end},
-#endif
#ifdef CONFIG_USB_SUSPEND
{__hooks_usb_change, __hooks_usb_change_end},
#endif
diff --git a/common/i2cs_tpm.c b/common/i2cs_tpm.c
deleted file mode 100644
index 4518eddbb9..0000000000
--- a/common/i2cs_tpm.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/* Copyright 2016 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 "gpio.h"
-#include "hooks.h"
-#include "i2cs.h"
-#include "registers.h"
-#include "system.h"
-#include "tpm_registers.h"
-
-/*
- * This implements adaptaition layer between i2cs (i2c slave) port and TPM.
- *
- * The adaptation layer is stateless, it processes the i2cs "write complete"
- * interrupts on the interrupt context.
- *
- * Each "write complete" interrupt is associated with some data receved from
- * the master. If the package received from the master contains just one byte
- * payload, the value of this byte is considered the address of the TPM2
- * register to reach, read or write.
- *
- * Real TPM register addresses can be two bytes in size (even within locality
- * zero), to keep the i2c protocol simple and efficient, the real TPM register
- * addresses are re-mapped into i2c specific TPM register addresses.
- *
- * If the payload includes bytes following the address byte - those are the
- * data to be written to the addressed register. The number of bytes of data
- * could be anything between 1 and 62. The HW fifo is 64 bytes deep and that
- * means that only 63 bytes can be written without the write pointer wrapping
- * around to itself. Outside of the TPM fifo register, all other registers are
- * either 1 byte or 4 byte writes.
- *
- * The master knows how many bytes to write into FIFO or to read from it by
- * consulting the "burst size" field of the TPM status register. This happens
- * transparently for this layer.
- *
- * Data destined to and coming from the FIFO register is treated as a byte
- * stream.
- *
- * Data for and from all other registers are either 1 byte or 4 bytes as
- * specified in a register's "reg_size" field of the I2C -> TPM mapping
- * table. Multi-byte registers are received and transmitted in CPU byte order
- * which for the Cr50 is little endian.
- * TODO (scollyer crosbug.com/p/56539): Should modify the register access code
- * so that the Host can access 1-4 bytes of a given register.
- *
- * Master write accesses followed by data result in the register address
- * mapped, data converted, if necessary, and passed to the tpm register task.
- *
- * Master write accesses requesting register reads result in the register
- * address mappend and accessing the tpm task to retrieve the proper register
- * data, converting it, if necessary, and passing it to the 12cs controller to
- * make available for master read accesses.
- *
- * Again, both read and write accesses complete on the same interrupt context
- * they were invoked on.
- */
-
-/* Console output macros */
-#define CPUTS(outstr) cputs(CC_I2C, outstr)
-#define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args)
-
-struct i2c_tpm_reg_map {
- uint8_t i2c_address;
- uint8_t reg_size;
- uint16_t tpm_address;
-};
-static const struct i2c_tpm_reg_map i2c_to_tpm[] = {
- {0, 1, 0}, /* TPM Access */
- {1, 4, 0x18}, /* TPM Status */
- {5, 0, 0x24}, /* TPM Fifo, variable size. */
- {6, 4, 0xf00}, /* TPM DID VID */
- {0xa, 4, 0x14}, /* TPM TPM_INTF_CAPABILITY */
- {0xe, 1, 0xf04}, /* TPM RID */
- {0xf, 0, 0xf90}, /* TPM_FW_VER */
-};
-
-/* Used to track number of times i2cs hw read fifo was adjusted */
-static uint32_t i2cs_fifo_adjust_count;
-/* Used to track number of write mismatch errors */
-static uint32_t i2cs_write_error_count;
-
-static void process_read_access(uint16_t reg_size,
- uint16_t tpm_reg, uint8_t *data)
-{
- int i;
- uint8_t reg_value[4];
-
- /*
- * The master wants to read the register, read the value and pass it
- * to the controller.
- */
- if (reg_size == 1 || reg_size == 4) {
- /* Always read regsize number of bytes */
- tpm_register_get(tpm_reg, reg_value, reg_size);
- /*
- * For 1 or 4 byte register reads there should not be any data
- * buffered in the i2cs hw read fifo. This function will check
- * the current fifo queue depth and if non-zero, will adjust the
- * fw pointer to force it to 0.
- */
- if (i2cs_zero_read_fifo_buffer_depth())
- /* Count each instance that fifo was adjusted */
- i2cs_fifo_adjust_count++;
- for (i = 0; i < reg_size; i++)
- i2cs_post_read_data(reg_value[i]);
- return;
- }
-
- /*
- * FIFO accesses do not require endianness conversion, but to find out
- * how many bytes to read we need to consult the burst size field of
- * the tpm status register.
- */
- reg_size = tpm_get_burst_size();
-
- /*
- * Now, this is a hack, but we are short on SRAM, so let's reuse the
- * receive buffer for the FIFO data sotrage. We know that the ISR has
- * a 64 byte buffer were it moves received data.
- */
- /* Back pointer up by one to point to beginning of buffer */
- data -= 1;
- tpm_register_get(tpm_reg, data, reg_size);
- /* Transfer TPM fifo data to the I2CS HW fifo */
- i2cs_post_read_fill_fifo(data, reg_size);
-}
-
-static void process_write_access(uint16_t reg_size, uint16_t tpm_reg,
- uint8_t *data, size_t i2cs_data_size)
-{
- /* This is an actual write request. */
-
- /*
- * If reg_size is 0, then this is a fifo register write. Send the stream
- * down directly
- */
- if (reg_size == 0) {
- tpm_register_put(tpm_reg, data, i2cs_data_size);
- return;
- }
-
- if (i2cs_data_size != reg_size) {
- i2cs_write_error_count++;
- return;
- }
-
- /* Write the data to the appropriate TPM register */
- tpm_register_put(tpm_reg, data, reg_size);
-}
-
-static void wr_complete_handler(void *i2cs_data, size_t i2cs_data_size)
-{
- size_t i;
- uint16_t tpm_reg;
- uint8_t *data = i2cs_data;
- const struct i2c_tpm_reg_map *i2c_reg_entry = NULL;
- uint16_t reg_size;
-
- if (i2cs_data_size < 1) {
- /*
- * This is a misformatted request, should never happen, just
- * ignore it.
- */
- CPRINTF("%s: empty receive payload\n", __func__);
- return;
- }
-
- /* Let's find real TPM register address. */
- for (i = 0; i < ARRAY_SIZE(i2c_to_tpm); i++)
- if (i2c_to_tpm[i].i2c_address == *data) {
- i2c_reg_entry = i2c_to_tpm + i;
- break;
- }
-
- if (!i2c_reg_entry) {
- CPRINTF("%s: unsupported i2c tpm address 0x%x\n",
- __func__, *data);
- return;
- }
-
- /*
- * OK, we know the tpm register address. Note that only full register
- * accesses are supported for multybyte registers,
- * TODO (scollyer crosbug.com/p/56539): Look at modifying this so we
- * can handle 1 - 4 byte accesses at any any I2C register address we
- * support.
- */
- tpm_reg = i2c_reg_entry->tpm_address;
- reg_size = i2c_reg_entry->reg_size;
-
- i2cs_data_size--;
- data++;
-
- if (!i2cs_data_size)
- process_read_access(reg_size, tpm_reg, data);
- else
- process_write_access(reg_size, tpm_reg,
- data, i2cs_data_size);
-
- /*
- * Since cr50 does not provide i2c clock stretching, we need some
- * onther means of flow controlling the host. Let's generate a pulse
- * on the AP interrupt line for that.
- */
- gpio_set_level(GPIO_INT_AP_L, 0);
- gpio_set_level(GPIO_INT_AP_L, 1);
-}
-
-static void i2cs_if_stop(void)
-{
- i2cs_register_write_complete_handler(NULL);
-}
-
-static void i2cs_if_start(void)
-{
- i2cs_register_write_complete_handler(wr_complete_handler);
-}
-
-static void i2cs_if_register(void)
-{
- if (!board_tpm_uses_i2c())
- return;
-
- tpm_register_interface(i2cs_if_start, i2cs_if_stop);
- i2cs_fifo_adjust_count = 0;
- i2cs_write_error_count = 0;
-}
-DECLARE_HOOK(HOOK_INIT, i2cs_if_register, HOOK_PRIO_LAST);
-
-static int command_i2cs(int argc, char **argv)
-{
- static uint16_t base_read_recovery_count;
- struct i2cs_status status;
-
- i2cs_get_status(&status);
-
- ccprintf("rd fifo adjust cnt = %d\n", i2cs_fifo_adjust_count);
- ccprintf("wr mismatch cnt = %d\n", i2cs_write_error_count);
- ccprintf("read recovered cnt = %d\n", status.read_recovery_count
- - base_read_recovery_count);
- if (argc < 2)
- return EC_SUCCESS;
-
- if (!strcasecmp(argv[1], "reset")) {
- i2cs_fifo_adjust_count = 0;
- i2cs_write_error_count = 0;
- base_read_recovery_count = status.read_recovery_count;
- ccprintf("i2cs error counts reset\n");
- } else
- return EC_ERROR_PARAM1;
-
- return EC_SUCCESS;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(i2cstpm, command_i2cs,
- "reset",
- "Display fifo adjust count");
diff --git a/common/new_nvmem.c b/common/new_nvmem.c
deleted file mode 100644
index 445d731f86..0000000000
--- a/common/new_nvmem.c
+++ /dev/null
@@ -1,3217 +0,0 @@
-/* Copyright 2019 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 <stdint.h>
-#include <string.h>
-
-#include "test/nvmem_test.h"
-
-#include "common.h"
-#include "board.h"
-#include "console.h"
-#include "crypto_api.h"
-#include "flash.h"
-#include "flash_log.h"
-#include "new_nvmem.h"
-#include "nvmem.h"
-#include "nvmem_vars.h"
-#include "shared_mem.h"
-#include "system.h"
-#include "system_chip.h"
-#include "task.h"
-#include "timer.h"
-
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args)
-/*
- * ==== Overview
- *
- * This file is the implementation of the new TPM NVMEM flash storage layer.
- * These are major differences compared to the legacy implementation:
- *
- * NVMEM TPM objects are stored in flash in separate containers, each one
- * protected by hash and possibly encrypted. When nvmem_commit() is invoked,
- * only objects changed in the NVMEM cache are updated in the flash.
- *
- * The (key, value) pairs are also stored in flash in the same kind of
- * separate containers. There is no special area allocated for the (key, value)
- * pairs in flash, they are interleaved with TPM objects.
- *
- * The (key, value) pairs are not kept in the NVMEM cache, they are stored in
- * flash only. This causes a few deviations from the legacy (key, value) pair
- * interface:
- *
- * - no need to initialize (key, value) storage separately, initvars() API is
- * not there.
- *
- * - when the user is retrieving a (key, value) object, he/she is given a
- * dynamically allocated buffer, which needs to be explicitly released by
- * calling the new API: freevar().
- *
- * - the (key. value) pairs, if modified, are updated in flash immediately,
- * not after nvmem_commit() is called.
- *
- * Storing (key, value) pairs in the flash frees up 272 bytes of the cache
- * space previously used, but makes it more difficult to control how flash
- * memory is split between TPM objects and (key, value) pairs. A soft limit of
- * 1K is introduced, limiting the total space used by (key, value) pairs data,
- * not including tuple headers.
- *
- * ===== Organizing flash storage
- *
- * The total space used by the NVMEM in flash is reduced from 24 to 20
- * kilobytes, five 2K pages at the top of each flash bank. These pages are
- * concatenated into a single storage space, based on the page header placed
- * at the bottom of each page (struct nn_page_header). The page header
- * includes a 21 bit page number (this allows to order pages properly on
- * initialization), the offset of the first data object in the page and the
- * hash of the entire header.
- *
- * Yet another limitation of the new scheme is that no object stored in NVMEM
- * can exceed the flash page size less the page header size and container
- * header size. This allows for objects as large as 2035 bytes. Objects can
- * span flash pages. Note that reserved TPM object STATE_CLEAR_DATA exceeds 2K
- * in size, this is why one of its components (the .pcrSave field) is stored
- * in flash separately.
- *
- * ===== Object containers
- *
- * The container header (struct nn_container) describes the contained TPM
- * object or (key, value) pair, along with the size, and also includes the
- * hash of the entire container calculated when the hash field is set to zero.
- *
- * When an object needs to be updated, it is stored at the end of the used
- * flash space in a container with the higher .generation field value, and
- * then the older container's type field is erased, thus marking it as a
- * deleted object. The idea is that when initializing NVMEM cache after reset,
- * in case two instances of the same object are found in the flash because the
- * new instance was saved, but the old instance was not erased because of some
- * failure, the instance with larger .generation field value wins. Note that
- * this error recovery procedure is supplemented by use of transaction
- * delimiter objects described below.
- *
- * The container type field is duplicated in the container header, this allows
- * verification of the container hash after even the object was erased.
- *
- * In order to be able to erase the type the container must start at the 4
- * byte boundary. This in turn requires that each container is padded such
- * that total storage taken by the container is divisible by 4.
- *
- * To be able to tell if two containers contain two instances of the same
- * object, one needs to be able to identify the object stored in the container.
- * For the three distinct types of objects it works as follows:
- *
- * - (key, value) pair: key, stored in the contained tuple.
- *
- * - reserved tpm object: the first byte stored in the container. PCR
- * values from STATE_CLEAR_DATA.pcrSave field are stored as separate
- * reserved objects with the appropriate first bytes.
- *
- * - evictable tpm object: the first 4 bytes stored in the container, the
- * evictable TTPM object ID.
- *
- * Don't forget that the contents are usually encrypted. Decryption is needed
- * each time a stored object needs to be examined.
- *
- * Reserved objects of types STATE_CLEAR_DATA and STATE_RESET_DATA are very
- * big and are stored in the flash in marshaled form. On top of 'regular' TPM2
- * style marshaling, PCRs found in the STATE_CLEAR_DATA object are stored in
- * separate containers.
- *
- * ===== Storage compaction
- *
- * Keeping adding changed values at the end of the flash space would
- * inevitably cause space overflow, unless something is done about it. This is
- * where flash compaction kicks in: as soon as there are just three free flash
- * pages left the stored objects are moved to the end of the space, which
- * results in earlier used pages being freed and added to the pool of
- * available flash pages.
- *
- * A great improvement to this storage compaction process would be grouping
- * the objects such that the rarely changing ones occupy flash pages at the
- * lower page indices. In this case when compaction starts, the pages not
- * containing erased objects would not have to be re-written. This
- * optimization is left as a future enhancement.
- *
- * ===== Committing TPM changes
- *
- * When nvmem_commit() is invoked it is necessary to identify which TPM
- * objects in the cache have changed and require saving. Remember, that (key,
- * value) pairs are not held in the cache any more and are saved in the flash
- * immediately, so they do not have to be dealt with during commit.
- *
- * The commit procedure starts with iterating over the evictable objects space
- * in the NVMEM cache, storing in an array offsets of all evictable objects it
- * finds there. Then it iterates over flash contents skipping over (key,
- * value) pairs.
- *
- * For each reserved object stored in flash, it compares its stored value with
- * the value stored in the cache at known fixed location. If the value has
- * changed, a new reserved object instance is saved in flash. This approach
- * requires that all reserved objects are present in the flash, otherwise
- * there is nothing to compare the cached instance of the object with. This is
- * enforced by the init function.
- *
- * For each evictable object stored in flash, it checks if that object is
- * still in the cache using the previously collected array of offsets. If the
- * object is not in the cache, it must have been deleted by the TPM. The
- * function deletes it from the flash as well. If the object is in the cache,
- * its offset is removed from the array to indicate that the object has been
- * processed. Then if the object value has changed, the new instance is added
- * and the old instance erased. After this the only offsets left in the array
- * are offsets of new objects, not yet saved in the flash. All these remaining
- * objects get saved.
- *
- * To ensure transaction integrity, object deletions are just scheduled and
- * not processed immediately, the deletion happens after all new instances
- * have been saved in flash. See more about transaction delimiters below.
- *
- * ===== Migration from legacy storage and reclaiming flash space
- *
- * To be able to migrate existing devices from the legacy storage format the
- * initialization code checks if a full 12K flash partition is still present,
- * and if so - copies its contents into the cache and invokes the migration
- * function. The function erases the alternative partition and creates a list
- * of 5 pages available for the new format (remember, the flash footprint of
- * the new scheme is smaller, only 10K is available in each half).
- *
- * The (key, value) pairs and TPM objects are stored in the new format as
- * described, and then the legacy partition is erased and its pages are added
- * to the list of free pages. This approach would fail if the existing TPM
- * storage would exceed 10K, but this is extremely unlikely, especially since
- * the large reserved objects are stored by the new scheme in marshaled form.
- * This frees up a lot of flash space.
- *
- * Eventually it will be possible to reclaim the bottom 2K page per flash half
- * currently used by the legacy scheme, but this would be possible only after
- * migration is over. The plan is to keep a few Cr50 versions supporting the
- * migration process, and then drop the migration code and rearrange the
- * memory map and reclaim the freed pages. Chrome OS will always carry a
- * migrating capable Cr50 version along with the latest one to make sure that
- * even Chrome OS devices which had not updated their Cr50 code in a long
- * while can be migrated in two steps.
- *
- * ===== Initialization, including erased/corrupted flash
- *
- * On regular startup (no legacy partition found) the flash pages dedicated to
- * NVMEM storage are examined, pages with valid headers are included in the
- * list of available pages, sorted by the page number. Erased pages are kept
- * in a separate list. Pages which are not fully erased (but do not have a
- * valid header) are considered corrupted, are erased, and added to the second
- * list.
- *
- * After that the contents of the ordered flash pages is read, all discovered
- * TPM objects are verified and saved in the cache.
- *
- * To enforce that all reserved TPM objects are present in the flash, the init
- * routine maintains a bitmap of the reserved objects it found while
- * initializing. In the case when after the scan of the entire NVMEM flash it
- * turns out that some reserved objects have not been encountered, the init
- * routine creates new flash instances of the missing reserved objects with
- * default value of zero. This takes care of both initializing from empty
- * flash and a case when a reserved object disappears due to a bug.
- *
- * ===== Transactions support
- *
- * It is important to make sure that TPM changes are grouped together. It came
- * naturally with the legacy scheme where each time nvmem_save() was called,
- * the entire cache snapshot was saved in the flash. With the new scheme some
- * extra effort is required.
- *
- * Transaction delimiters are represented by containers of the appropriate
- * type and the payload size of zero. When nvmem_save() operation is started,
- * the new objects get written into flash and the objects requiring deletion
- * are kept in the list. Once all new objects are added to the flash, the
- * transaction delimiter is written, ending up at the top of the used flash.
- * After that the objects scheduled for deletion are deleted, and then the
- * transaction delimiter is also marked 'deleted'.
- *
- * So, during initialization the flash could be in one of three states:
- *
- * - thre is an erased transaction delimiter at the top
- * . this is the normal state after successful commit operation.
- *
- * - there is transaction delimiter at the top, but it is not erased.
- * . this is the case where the new objects were saved in flash, but some of
- * the old instances might still be present not erased. The recovery
- * procedure finds all duplicates of the objects present between two most
- * recent delimiters and erases them.
- *
- * - there is no transaction delimiter on the top.
- * . this is the case where nvmem_save() was interrupted before all new
- * values have been written into the flash. The recovery procedure finds
- * all TPM objects above the last valid delimiter in the flash and erases
- * them all.
- *
- * ===== Handling failures
- *
- * This implementation is no better in handling failures than the legacy one,
- * it in fact is even worse, because if a failure happened during legacy
- * commit operation, at least the earlier saved partition would be available.
- * If failure happens during this implementation's save or compaction process,
- * there is a risk of ending up with a corrupted or inconsistent flash
- * contents, even though the use of transaction delimiters narrows the failure
- * window significantly.
- *
- * This first draft is offered for review and to facilitate testing and
- * discussion about how failures should be addressed.
- *
- * ===== Missing stuff
- *
- * Presently not much thought has been given to locking and preventing
- * problems caused by task preemption. The legacy scheme is still in place,
- * but it might require improvements.
- */
-
-/*
- * This code relies on the fact that space dedicated to flash NVMEM storage is
- * sufficient to guarantee that the entire NVMEM snapshot can fit into it
- * comfortably. The assert below is a very liberal computation which
- * guarantees this assumption. Note that marshaling huge reserved structures
- * reduces amount of required flash space, and this is not accounted for in
- * this calculation. Space allocated for 200 container descriptors is also way
- * more than required.
- */
-
-/*
- * Fuzz testing does not enforce proper size definitions, causing the below
- * assert failure.
- */
-BUILD_ASSERT((NEW_NVMEM_TOTAL_PAGES * CONFIG_FLASH_BANK_SIZE) >
- (MAX_VAR_TOTAL_SPACE +
- NV_MEMORY_SIZE +
- 200 * (sizeof(struct nn_container)) +
- CONFIG_FLASH_BANK_SIZE * 2));
-
-/* Maximum number of evictable objects we support. */
-#define MAX_STORED_EVICTABLE_OBJECTS 20
-/*
- * Container for storing (key, value) pairs, a.k.a. vars during read. Actual
- * vars would never be this large, but when looking for vars we need to be
- * able to iterate over and verify all objects in the flash, hence the max
- * body size.
- */
-struct max_var_container {
- struct nn_container c_header;
- struct tuple t_header;
- uint8_t body[CONFIG_FLASH_BANK_SIZE - sizeof(struct nn_container) -
- sizeof(struct tuple)];
-} __packed;
-
-/*
- * Limit of the number of objects which can be updated in one TPM transaction,
- * reserved and evictable total. This is much more than practical maximum.
- */
-#define MAX_DELETE_CANDIDATES 30
-static struct delete_candidates {
- size_t num_candidates;
- const struct nn_container *candidates[MAX_DELETE_CANDIDATES];
-} *del_candidates;
-
-/*
- * This array contains a list of flash pages indices (0..255 range) sorted by
- * the page header page number filed. Erased pages are kept at the tail of the
- * list.
- */
-static uint8_t page_list[NEW_NVMEM_TOTAL_PAGES];
-static uint32_t next_evict_obj_base;
-static uint8_t init_in_progress;
-/*
- * Mutex to protect flash space containing NVMEM objects. All operations
- * modifying the flash contents or relying on its consistency (like searching
- * in the flash) should acquire this mutex before proceeding.
- *
- * The interfaces grabbing this mutex are
- *
- * new_nvmem_migrate()
- * new_nvmem_init()
- * new_nvmem_save()
- * getvar()
- * setvar()
- * nvmem_erase_tpm_data()
- *
- * The only static function using the mutex is browse_flash_contents() which
- * can be invoked from the CLI and while it never modifies the flash contents,
- * it still has to be protected to be able to properly iterate over the entire
- * flash contents.
- */
-static struct mutex flash_mtx;
-
-/*
- * Wrappers around locking/unlocking mutex make it easier to debug issues by
- * adding with minimal code changes like printouts of line numbers where the
- * functions are invoked from.
- */
-static void lock_mutex(int line_num)
-{
- mutex_lock(&flash_mtx);
-}
-
-static void unlock_mutex(int line_num)
-{
- mutex_unlock(&flash_mtx);
-}
-
-/*
- * Total space taken by key, value pairs in flash. It is limited to give TPM
- * objects priority.
- */
-test_export_static uint16_t total_var_space;
-
-/* The main context used when adding objects to NVMEM. */
-test_export_static struct access_tracker master_at;
-
-test_export_static enum ec_error_list browse_flash_contents(int print);
-static enum ec_error_list save_container(struct nn_container *nc);
-static void invalidate_nvmem_flash(void);
-
-/* Log NVMEM problem as per passed in payload and size, and reboot. */
-static void report_failure(struct nvmem_failure_payload *payload,
- size_t payload_union_size)
-{
- if (init_in_progress) {
- /*
- * This must be a rolling reboot, let's invalidate flash
- * storage to stop this.
- */
- invalidate_nvmem_flash();
- }
-
- flash_log_add_event(FE_LOG_NVMEM,
- payload_union_size +
- offsetof(struct nvmem_failure_payload,
- size),
- payload);
-
- ccprintf("Logging failure %d, will %sreinit\n", payload->failure_type,
- init_in_progress ? "" : "not ");
-
- if (init_in_progress) {
- struct nvmem_failure_payload fp;
-
- fp.failure_type = NVMEMF_NVMEM_WIPE;
-
- flash_log_add_event(
- FE_LOG_NVMEM,
- offsetof(struct nvmem_failure_payload, size), &fp);
- }
-
- cflush();
-
- system_reset(SYSTEM_RESET_MANUALLY_TRIGGERED | SYSTEM_RESET_HARD);
-}
-
-static void report_no_payload_failure(enum nvmem_failure_type type)
-{
- struct nvmem_failure_payload fp;
-
- fp.failure_type = type;
- report_failure(&fp, 0);
-}
-
-/*
- * This function allocates a buffer of the requested size.
- *
- * Heap space could be very limited and at times there could be not enough
- * memory in the heap to allocate. This should not be considered a failure,
- * polling should be used instead. On a properly functioning device the memory
- * would become available. If it is not - there is not much we can do, we'll
- * have to reboot adding a log entry.
- */
-static void *get_scratch_buffer(size_t size)
-{
- char *buf;
- int i;
- struct nvmem_failure_payload fp;
-
- /*
- * Wait up to a 5 seconds in case some other operation is under
- * way.
- */
- for (i = 0; i < 50; i++) {
- int rv;
-
- rv = shared_mem_acquire(size, &buf);
- if (rv == EC_SUCCESS) {
- if (i)
- CPRINTS("%s: waited %d cycles!", __func__, i);
- return buf;
- }
- usleep(100 * MSEC);
- }
-
- fp.failure_type = NVMEMF_MALLOC;
- fp.size = size;
- report_failure(&fp, sizeof(fp.size));
-
- /* Just to keep the compiler happy, this is never reached. */
- return NULL;
-}
-
-/* Helper function returning actual size used by NVMEM in flash. */
-static size_t total_used_size(void)
-{
- return master_at.list_index * CONFIG_FLASH_BANK_SIZE +
- master_at.mt.data_offset;
-}
-/*
- * Helper functions to set a bit a bit at a certain index in a bitmap array
- * and to check if the bit is set. The caller must guarantee that the bitmap
- * array is large enough for the index.
- */
-static int bitmap_bit_check(const uint8_t *bitmap, size_t index)
-{
- return bitmap[index / 8] & (1 << (index % 8));
-}
-
-static int bitmap_bit_set(uint8_t *bitmap, size_t index)
-{
- return bitmap[index / 8] |= (1 << (index % 8));
-}
-
-/* Convenience functions used to reduce amount of typecasting. */
-static void app_compute_hash_wrapper(void *buf, size_t size, void *hash,
- size_t hash_size)
-{
- app_compute_hash(buf, size, hash, hash_size);
-}
-
-static STATE_CLEAR_DATA *get_scd(void)
-{
- NV_RESERVED_ITEM ri;
-
- NvGetReserved(NV_STATE_CLEAR, &ri);
-
- return (STATE_CLEAR_DATA *)((uint8_t *)nvmem_cache_base(NVMEM_TPM) +
- ri.offset);
-}
-
-/*
- * Make sure page header hash is different between prod and other types of
- * images.
- */
-static uint32_t calculate_page_header_hash(struct nn_page_header *ph)
-{
- uint32_t hash;
- static const uint32_t salt[] = {1, 2, 3, 4};
-
- BUILD_ASSERT(sizeof(hash) ==
- offsetof(struct nn_page_header, page_hash));
-
- app_cipher(salt, &hash, ph, sizeof(hash));
-
- return hash;
-}
-
-/* Veirify page header hash. */
-static int page_header_is_valid(struct nn_page_header *ph)
-{
- return calculate_page_header_hash(ph) == ph->page_hash;
-}
-
-/* Convert flash page number in 0..255 range into actual flash address. */
-static struct nn_page_header *flash_index_to_ph(uint8_t index)
-{
- return (struct nn_page_header *)((index * CONFIG_FLASH_BANK_SIZE) +
- CONFIG_PROGRAM_MEMORY_BASE);
-}
-
-static const void *page_cursor(const struct page_tracker *pt)
-{
- return (void *)((uintptr_t)pt->ph + pt->data_offset);
-}
-
-/*
- * Return flash page pointed at by a certain page_list element if the page is
- * valid. If the index is out of range, or page is not initialized properly
- * return NULL.
- */
-test_export_static struct nn_page_header *list_element_to_ph(size_t el)
-{
- struct nn_page_header *ph;
-
- if (el >= ARRAY_SIZE(page_list))
- return NULL;
-
- ph = flash_index_to_ph(page_list[el]);
-
- if (page_header_is_valid(ph))
- return ph;
-
- return NULL;
-}
-
-/*
- * Read into buf or skip if buf is NULL the next num_bytes in the storage, at
- * the location determined by the passed in access tracker. Start from the
- * very beginning if the passed in access tracker is empty.
- *
- * If necessary - concatenate contents from different pages bypassing page
- * headers.
- *
- * If user is reading the container header (as specified by the
- * container_fetch argument), save in the context the location of the
- * container.
- *
- * If not enough bytes are available in the storage to satisfy the request -
- * log error and reboot.
- */
-static size_t nvmem_read_bytes(struct access_tracker *at, size_t num_bytes,
- void *buf, int container_fetch)
-{
- size_t togo;
- struct nvmem_failure_payload fp;
-
- if (!at->list_index && !at->mt.data_offset) {
- /* Start from the beginning. */
- at->mt.ph = list_element_to_ph(0);
- at->mt.data_offset = at->mt.ph->data_offset;
- }
-
- if (container_fetch) {
- at->ct.data_offset = at->mt.data_offset;
- at->ct.ph = at->mt.ph;
- }
-
- if ((at->mt.data_offset + num_bytes) < CONFIG_FLASH_BANK_SIZE) {
- /*
- * All requested data fits and does not even reach the top of
- * the page.
- */
- if (buf)
- memcpy(buf, page_cursor(&at->mt), num_bytes);
-
- at->mt.data_offset += num_bytes;
- return num_bytes;
- }
-
- /* Data is split between pages. */
- /* To go in the current page. */
- togo = CONFIG_FLASH_BANK_SIZE - at->mt.data_offset;
- if (buf) {
- memcpy(buf, page_cursor(&at->mt), togo);
- /* Next portion goes here. */
- buf = (uint8_t *)buf + togo;
- }
-
- /*
- * Determine how much is there to read in the next page.
- *
- * Since object size is limited to page size
- * less page header size, we are guaranteed that the object would not
- * span more than one page boundary.
- */
- togo = num_bytes - togo;
-
- /* Move to the next page. */
- at->list_index++;
- at->mt.ph = list_element_to_ph(at->list_index);
-
- if (!at->mt.ph && togo) {
- /*
- * No more data to read. Could the end of used flash be close
- * to the page boundary, so that there is no room to read an
- * erased container header?
- */
- if (!container_fetch) {
- fp.failure_type = NVMEMF_READ_UNDERRUN;
- fp.underrun_size = num_bytes - togo;
- /* This will never return. */
- report_failure(&fp, sizeof(fp.underrun_size));
- }
-
- /*
- * Simulate reading of the container header filled with all
- * ones, which would be an indication of the end of storage,
- * the caller will roll back ph, data_offset and list index as
- * appropriate.
- */
- memset(buf, 0xff, togo);
- } else if (at->mt.ph) {
- if (at->mt.ph->data_offset < (sizeof(*at->mt.ph) + togo)) {
- fp.failure_type = NVMEMF_PH_SIZE_MISMATCH;
- fp.ph.ph_offset = at->mt.ph->data_offset;
- fp.ph.expected = sizeof(*at->mt.ph) + togo;
- /* This will never return. */
- report_failure(&fp, sizeof(fp.ph));
- }
- if (buf)
- memcpy(buf, at->mt.ph + 1, togo);
-
- at->mt.data_offset = sizeof(*at->mt.ph) + togo;
- }
-
- return num_bytes;
-}
-
-/*
- * Convert passed in absolute address into flash memory offset and write the
- * passed in blob into the flash.
- */
-static enum ec_error_list write_to_flash(const void *flash_addr,
- const void *obj, size_t size)
-{
- return flash_physical_write(
- (uintptr_t)flash_addr - CONFIG_PROGRAM_MEMORY_BASE, size, obj);
-}
-
-/*
- * Corrupt headers of all active pages thus invalidating the entire NVMEM
- * flash storage.
- */
-static void invalidate_nvmem_flash(void)
-{
- size_t i;
- struct nn_page_header *ph;
- struct nn_page_header bad_ph;
-
- memset(&bad_ph, 0, sizeof(bad_ph));
-
- for (i = 0; i < ARRAY_SIZE(page_list); i++) {
- ph = list_element_to_ph(i);
- if (!ph)
- continue;
- write_to_flash(ph, &bad_ph, sizeof(*ph));
- }
-}
-
-/*
- * When initializing flash for the first time - set the proper first page
- * header.
- */
-static enum ec_error_list set_first_page_header(void)
-{
- struct nn_page_header ph = {};
- enum ec_error_list rv;
- struct nn_page_header *fph; /* Address in flash. */
-
- ph.data_offset = sizeof(ph);
- ph.page_hash = calculate_page_header_hash(&ph);
- fph = flash_index_to_ph(page_list[0]);
- rv = write_to_flash(fph, &ph, sizeof(ph));
-
- if (rv == EC_SUCCESS) {
- /* Make sure master page tracker is ready. */
- memset(&master_at, 0, sizeof(master_at));
- master_at.mt.data_offset = ph.data_offset;
- master_at.mt.ph = fph;
- }
-
- return rv;
-}
-
-/*
- * Verify that the passed in container is valid, specifically that its hash
- * matches its contents.
- */
-static int container_is_valid(struct nn_container *ch)
-{
- struct nn_container dummy_c;
- uint32_t hash;
- uint32_t preserved_hash;
- uint8_t preserved_type;
-
- preserved_hash = ch->container_hash;
- preserved_type = ch->container_type;
-
- ch->container_type = ch->container_type_copy;
- ch->container_hash = 0;
- app_compute_hash_wrapper(ch, ch->size + sizeof(*ch), &hash,
- sizeof(hash));
-
- ch->container_hash = preserved_hash;
- ch->container_type = preserved_type;
-
- dummy_c.container_hash = hash;
-
- return dummy_c.container_hash == ch->container_hash;
-}
-
-static uint32_t aligned_container_size(const struct nn_container *ch)
-{
- const size_t alignment_mask = CONFIG_FLASH_WRITE_SIZE - 1;
-
- return (ch->size + sizeof(*ch) + alignment_mask) & ~alignment_mask;
-}
-
-/*
- * Function which allows to iterate through all objects stored in flash. The
- * passed in context keeps track of where the previous object retrieval ended.
- *
- * Return:
- * EC_SUCCESS if an object is retrieved and verified
- * EC_ERROR_MEMORY_ALLOCATION if 'erased' object reached (not an error).
- * EC_ERROR_INVAL if verification failed or read is out of sync.
- */
-test_export_static enum ec_error_list get_next_object(struct access_tracker *at,
- struct nn_container *ch,
- int include_deleted)
-{
- uint32_t salt[4];
- uint8_t ctype;
-
- salt[3] = 0;
-
- do {
- size_t aligned_remaining_size;
- struct nn_container temp_ch;
-
- nvmem_read_bytes(at, sizeof(temp_ch), &temp_ch, 1);
- ctype = temp_ch.container_type;
-
- /* Should we check for the container being all 0xff? */
- if (ctype == NN_OBJ_ERASED) {
- /* Roll back container size. */
- at->mt.data_offset = at->ct.data_offset;
- at->mt.ph = at->ct.ph;
-
- /*
- * If the container header happened to span between
- * two pages or end at the page boundary - roll back
- * page index saved in the context.
- */
- if ((CONFIG_FLASH_BANK_SIZE - at->mt.data_offset) <=
- sizeof(struct nn_container))
- at->list_index--;
-
- return EC_ERROR_MEMORY_ALLOCATION;
- }
-
- /*
- * The read data is a container header, copy it into the user
- * provided space and continue reading there.
- */
- *ch = temp_ch;
- aligned_remaining_size =
- aligned_container_size(ch) - sizeof(*ch);
-
- if (aligned_remaining_size) {
- if (aligned_remaining_size >
- (CONFIG_FLASH_BANK_SIZE - sizeof(*ch))) {
- /* Never returns. */
- report_no_payload_failure(
- NVMEMF_INCONSISTENT_FLASH_CONTENTS);
- }
-
- nvmem_read_bytes(at, aligned_remaining_size, ch + 1, 0);
-
- salt[0] = at->ct.ph->page_number;
- salt[1] = at->ct.data_offset;
- salt[2] = ch->container_hash;
-
- /* Decrypt in place. */
- if (!app_cipher(salt, ch + 1, ch + 1, ch->size))
- report_no_payload_failure(NVMEMF_CIPHER_ERROR);
- }
-
- /* And calculate hash. */
- if (!container_is_valid(ch)) {
- struct nvmem_failure_payload fp;
-
- if (!init_in_progress)
- report_no_payload_failure(
- NVMEMF_CONTAINER_HASH_MISMATCH);
- /*
- * During init there might be a way to deal with
- * this, let's just log this and continue.
- */
- fp.failure_type = NVMEMF_CONTAINER_HASH_MISMATCH;
- flash_log_add_event(
- FE_LOG_NVMEM,
- offsetof(struct nvmem_failure_payload, size),
- &fp);
-
- return EC_ERROR_INVAL;
- }
-
- /*
- * Keep track of the most recently encountered delimiter,
- * finalized or not.
- */
- if (ch->container_type_copy == NN_OBJ_TRANSACTION_DEL) {
- include_deleted = 1; /* Always return all delimiters. */
-
- /* But keep track only of finalized ones. */
- if (ch->container_type == NN_OBJ_OLD_COPY) {
- at->dt.ph = at->ct.ph;
- at->dt.data_offset = at->ct.data_offset;
- }
- }
-
- } while (!include_deleted && (ctype == NN_OBJ_OLD_COPY));
-
- return EC_SUCCESS;
-}
-
-/*
- * Add a delimiter object at the top of the flash. The container type field is
- * not erased.
- *
- * This is an indication that after nvmem_commit() invocation all updated
- * objects have been saved in the flash, but the old instances of the objects
- * have not yet been deleted.
- */
-static enum ec_error_list add_delimiter(void)
-{
- struct nn_container ch;
-
- memset(&ch, 0, sizeof(ch));
-
- ch.container_type = ch.container_type_copy = NN_OBJ_TRANSACTION_DEL;
-
- return save_container(&ch);
-}
-
-/*
- * Erase the container type field of the previously saved delimiter, thus
- * indicating that nvmem save transaction is completed.
- */
-static enum ec_error_list finalize_delimiter(const struct nn_container *del)
-{
- struct nn_container c;
-
- c = *del;
- c.container_type = NN_OBJ_OLD_COPY;
-
- return write_to_flash(del, &c, sizeof(c));
-}
-
-/* Add delimiter indicating that flash is in a consistent state. */
-static enum ec_error_list add_final_delimiter(void)
-{
- const struct nn_container *del;
-
- del = page_cursor(&master_at.mt);
- add_delimiter();
-
- return finalize_delimiter(del);
-}
-
-/* Erase flash page and add it to the pool of empty pages. */
-static void release_flash_page(struct access_tracker *at)
-{
- uint8_t page_index = page_list[0];
- void *flash;
-
- flash = flash_index_to_ph(page_index);
- flash_physical_erase((uintptr_t)flash - CONFIG_PROGRAM_MEMORY_BASE,
- CONFIG_FLASH_BANK_SIZE);
- memmove(page_list, page_list + 1,
- (ARRAY_SIZE(page_list) - 1) * sizeof(page_list[0]));
- page_list[ARRAY_SIZE(page_list) - 1] = page_index;
- at->list_index--;
- master_at.list_index--;
-}
-
-/* Reshuffle flash contents dropping deleted objects. */
-test_export_static enum ec_error_list compact_nvmem(void)
-{
- const void *fence_ph;
- enum ec_error_list rv = EC_SUCCESS;
- size_t before;
- struct nn_container *ch;
- struct access_tracker at = {};
- int saved_object_count;
- int final_delimiter_needed = 1;
-
- /* How much space was used before compaction. */
- before = total_used_size();
-
- /* One page is enough even for the largest object. */
- ch = get_scratch_buffer(CONFIG_FLASH_BANK_SIZE);
-
- /*
- * Page where we should stop compaction, all pages before this would
- * be recycled.
- */
- fence_ph = master_at.mt.ph;
- saved_object_count = 0;
-
- do {
- switch (get_next_object(&at, ch, 0)) {
- case EC_SUCCESS:
- break;
-
- case EC_ERROR_MEMORY_ALLOCATION:
- shared_mem_release(ch);
- return EC_SUCCESS;
-
- default:
- /*
- * The error has been reported already.
- *
- * This must be compaction after startup with
- * inconsistent nvmemory state, let's make sure the
- * top page is recycled.
- */
- if (at.mt.ph != fence_ph)
- release_flash_page(&at);
- shared_mem_release(ch);
- return EC_ERROR_INVAL;
- }
-
- /* Re-store the object in compacted flash. */
- switch (ch->container_type) {
- case NN_OBJ_TUPLE:
- case NN_OBJ_TPM_RESERVED:
- case NN_OBJ_TPM_EVICTABLE:
- ch->generation++;
- if (save_container(ch) != EC_SUCCESS) {
- ccprintf("%s: Saving FAILED\n", __func__);
- shared_mem_release(ch);
- return EC_ERROR_INVAL;
- }
- saved_object_count++;
- break;
- default:
- break;
- }
-
- if (at.list_index != 0) {
- /*
- * We are done with a pre-compaction page, use a
- * delimiter to indicate that a bunch of objects are
- * being deleted and finalize the delimiter once the
- * old page is erased.
- *
- * Return the erased page to the pool of empty pages
- * and rearrange the list of active pages.
- */
- const void *del;
-
- if (saved_object_count) {
- del = page_cursor(&master_at.mt);
- add_delimiter();
- }
-
- release_flash_page(&at);
-#if defined(NVMEM_TEST_BUILD)
- if (failure_mode == TEST_FAIL_WHEN_COMPACTING) {
- shared_mem_release(ch);
- return EC_SUCCESS;
- }
-#endif
-
- if (saved_object_count) {
- finalize_delimiter(del);
- saved_object_count = 0;
- }
- /*
- * No need in another delimiter if data ends on a page
- * boundary.
- */
- final_delimiter_needed = 0;
- } else {
- final_delimiter_needed = 1;
- }
- } while (at.mt.ph != fence_ph);
-
- shared_mem_release(ch);
-
- if (final_delimiter_needed)
- add_final_delimiter();
-
- CPRINTS("Compaction done, went from %zd to %zd bytes", before,
- total_used_size());
- return rv;
-}
-
-static void start_new_flash_page(size_t data_size)
-{
- struct nn_page_header ph = {};
-
- ph.data_offset = sizeof(ph) + data_size;
- ph.page_number = master_at.mt.ph->page_number + 1;
- ph.page_hash = calculate_page_header_hash(&ph);
- master_at.list_index++;
- if (master_at.list_index == ARRAY_SIZE(page_list))
- report_no_payload_failure(NVMEMF_PAGE_LIST_OVERFLOW);
-
- master_at.mt.ph =
- (const void *)(((uintptr_t)page_list[master_at.list_index] *
- CONFIG_FLASH_BANK_SIZE) +
- CONFIG_PROGRAM_MEMORY_BASE);
-
- write_to_flash(master_at.mt.ph, &ph, sizeof(ph));
- master_at.mt.data_offset = sizeof(ph);
-}
-
-/*
- * Save in the flash an object represented by the passed in container. Add new
- * pages to the list of used pages if necessary.
- */
-static enum ec_error_list save_object(const struct nn_container *cont)
-{
- const void *save_data = cont;
- size_t save_size = aligned_container_size(cont);
- size_t top_room;
-
-#if defined(NVMEM_TEST_BUILD)
- if (failure_mode == TEST_FAILED_HASH)
- save_size -= sizeof(uint32_t);
-#endif
-
- top_room = CONFIG_FLASH_BANK_SIZE - master_at.mt.data_offset;
- if (save_size >= top_room) {
-
- /* Let's finish the current page. */
- write_to_flash((uint8_t *)master_at.mt.ph +
- master_at.mt.data_offset,
- cont, top_room);
-
- /* Remaining data and size to be written on the next page. */
- save_data = (const void *)((uintptr_t)save_data + top_room);
- save_size -= top_room;
- start_new_flash_page(save_size);
-#if defined(NVMEM_TEST_BUILD)
- if (save_size && (failure_mode == TEST_SPANNING_PAGES)) {
- ccprintf("%s:%d corrupting...\n", __func__, __LINE__);
- return EC_SUCCESS;
- }
-#endif
- }
-
- if (save_size) {
- write_to_flash((uint8_t *)master_at.mt.ph +
- master_at.mt.data_offset,
- save_data, save_size);
- master_at.mt.data_offset += save_size;
- }
-
- return EC_SUCCESS;
-}
-
-/*
- * Functions to check if the passed in blob is all zeros or all 0xff, in both
- * cases would be considered an uninitialized value. This is used when
- * marshaling certaing structures and PCRs.
- */
-static int is_all_value(const uint8_t *p, size_t size, uint8_t value)
-{
- size_t i;
-
- for (i = 0; i < size; i++)
- if (p[i] != value)
- return 0;
-
- return 1;
-}
-
-test_export_static int is_uninitialized(const void *p, size_t size)
-{
- return is_all_value(p, size, 0xff);
-}
-
-static int is_all_zero(const void *p, size_t size)
-{
- return is_all_value(p, size, 0);
-}
-
-static int is_empty(const void *pcr_base, size_t pcr_size)
-{
- return is_uninitialized(pcr_base, pcr_size) ||
- is_all_zero(pcr_base, pcr_size);
-}
-
-/*
- * A convenience function checking if the passed in blob is not empty, and if
- * so - save the blob in the destination memory.
- *
- * Return number of bytes placed in dst or zero, if the blob was empty.
- */
-static size_t copy_pcr(const uint8_t *pcr_base, size_t pcr_size, uint8_t *dst)
-{
- /*
- * We rely on the fact that all 16 PCRs of every PCR bank saved in the
- * NVMEM's reserved space are originally set to all zeros.
- *
- * If all 0xFF is read - this is considered an artifact of trying to
- * retrieve PCRs from legacy flash snapshot from the state when PCRs
- * were not saved in the reserved space at all, i.e. also indicates an
- * empty PCR.
- */
- if (is_empty(pcr_base, pcr_size))
- return 0; /* No need to save this. */
-
- memcpy(dst, pcr_base, pcr_size);
-
- return pcr_size;
-}
-
-/*
- * A convenience structure and array, allowing quick access to PCR banks
- * contained in the STATE_CLEAR_DATA:pcrSave field. This helps when
- * marshailing/unmarshaling PCR contents.
- */
-struct pcr_descriptor {
- uint16_t pcr_array_offset;
- uint8_t pcr_size;
-} __packed;
-
-static const struct pcr_descriptor pcr_arrays[] = {
- {offsetof(PCR_SAVE, sha1), SHA1_DIGEST_SIZE},
- {offsetof(PCR_SAVE, sha256), SHA256_DIGEST_SIZE},
- {offsetof(PCR_SAVE, sha384), SHA384_DIGEST_SIZE},
- {offsetof(PCR_SAVE, sha512), SHA512_DIGEST_SIZE}
-};
-#define NUM_OF_PCRS (ARRAY_SIZE(pcr_arrays) * NUM_STATIC_PCR)
-
-/* Just in case we ever get to reducing the PCR set one way or another. */
-BUILD_ASSERT(ARRAY_SIZE(pcr_arrays) == 4);
-BUILD_ASSERT(NUM_OF_PCRS == 64);
-/*
- * Iterate over PCRs contained in the STATE_CLEAR_DATA structure in the NVMEM
- * cache and save nonempty ones in the flash.
- */
-static void migrate_pcr(STATE_CLEAR_DATA *scd, size_t array_index,
- size_t pcr_index, struct nn_container *ch)
-{
- const struct pcr_descriptor *pdsc;
- uint8_t *p_container_body;
- uint8_t *pcr_base;
- uint8_t reserved_index; /* Unique ID of this PCR in reserved storage. */
-
- p_container_body = (uint8_t *)(ch + 1);
- pdsc = pcr_arrays + array_index;
- pcr_base = (uint8_t *)&scd->pcrSave + pdsc->pcr_array_offset +
- pdsc->pcr_size * pcr_index;
- reserved_index = NV_VIRTUAL_RESERVE_LAST +
- array_index * NUM_STATIC_PCR + pcr_index;
-
- if (!copy_pcr(pcr_base, pdsc->pcr_size, p_container_body + 1))
- return;
-
- p_container_body[0] = reserved_index;
- ch->size = pdsc->pcr_size + 1;
- save_container(ch);
-}
-
-/*
- * Some NVMEM structures end up in the NVMEM cache with a wrong alignment. If
- * a passed in pointer is not aligned at a 4 byte boundary, this function will
- * save the 4 bytes above the blob in the passed in space and then move the
- * blob up so that it is properly aligned.
- */
-static void *preserve_struct(void *p, size_t size, uint32_t *preserved)
-{
- uint32_t misalignment = ((uintptr_t)p & 3);
- void *new_p;
-
- if (!misalignment)
- return p; /* Nothing to adjust. */
-
- memcpy(preserved, (uint8_t *)p + size, sizeof(*preserved));
- new_p = (void *)((((uintptr_t)p) + 3) & ~3);
- memmove(new_p, p, size);
-
- return new_p;
-}
-
-static void maybe_restore_struct(void *new_p, void *old_p, size_t size,
- uint32_t *preserved)
-{
- if (!memcmp(new_p, old_p, size))
- return;
-
- memmove(old_p, new_p, size);
- memcpy((uint8_t *)old_p + size, preserved, sizeof(*preserved));
-}
-
-/*
- * Note that PCRs are not marshaled here, but the rest of the structre, below
- * and above the PCR array is.
- */
-static uint16_t marshal_state_clear(STATE_CLEAR_DATA *scd, uint8_t *dst)
-{
- PCR_AUTHVALUE *new_pav;
- STATE_CLEAR_DATA *new_scd;
- size_t bottom_size;
- size_t i;
- size_t top_size;
- uint32_t preserved;
- uint8_t *base;
- int room;
-
- bottom_size = offsetof(STATE_CLEAR_DATA, pcrSave);
- top_size = sizeof(scd->pcrAuthValues);
-
- if (is_empty(scd, bottom_size) &&
- is_empty(&scd->pcrAuthValues, top_size) &&
- is_empty(&scd->pcrSave.pcrCounter, sizeof(scd->pcrSave.pcrCounter)))
- return 0;
-
- /* Marshaling STATE_CLEAR_DATA will never need this much. */
- room = CONFIG_FLASH_BANK_SIZE;
-
- new_scd = preserve_struct(scd, bottom_size, &preserved);
-
- base = dst;
-
- *dst++ = (!!new_scd->shEnable) | ((!!new_scd->ehEnable) << 1) |
- ((!!new_scd->phEnableNV) << 2);
-
- memcpy(dst, &new_scd->platformAlg, sizeof(new_scd->platformAlg));
- dst += sizeof(new_scd->platformAlg);
-
- room -= (dst - base);
-
- TPM2B_DIGEST_Marshal(&new_scd->platformPolicy, &dst, &room);
-
- TPM2B_AUTH_Marshal(&new_scd->platformAuth, &dst, &room);
-
- memcpy(dst, &new_scd->pcrSave.pcrCounter,
- sizeof(new_scd->pcrSave.pcrCounter));
- dst += sizeof(new_scd->pcrSave.pcrCounter);
- room -= sizeof(new_scd->pcrSave.pcrCounter);
-
- maybe_restore_struct(new_scd, scd, bottom_size, &preserved);
-
- new_pav = preserve_struct(&scd->pcrAuthValues, top_size, &preserved);
- for (i = 0; i < ARRAY_SIZE(new_scd->pcrAuthValues.auth); i++)
- TPM2B_DIGEST_Marshal(new_pav->auth + i, &dst, &room);
-
- maybe_restore_struct(new_pav, &scd->pcrAuthValues, top_size,
- &preserved);
-
- return dst - base;
-}
-
-static uint16_t marshal_state_reset_data(STATE_RESET_DATA *srd, uint8_t *dst)
-{
- STATE_RESET_DATA *new_srd;
- uint32_t preserved;
- uint8_t *base;
- int room;
-
- if (is_empty(srd, sizeof(*srd)))
- return 0;
-
- /* Marshaling STATE_RESET_DATA will never need this much. */
- room = CONFIG_FLASH_BANK_SIZE;
-
- new_srd = preserve_struct(srd, sizeof(*srd), &preserved);
-
- base = dst;
-
- TPM2B_AUTH_Marshal(&new_srd->nullProof, &dst, &room);
- TPM2B_DIGEST_Marshal((TPM2B_DIGEST *)(&new_srd->nullSeed), &dst, &room);
- UINT32_Marshal(&new_srd->clearCount, &dst, &room);
- UINT64_Marshal(&new_srd->objectContextID, &dst, &room);
-
- memcpy(dst, new_srd->contextArray, sizeof(new_srd->contextArray));
- room -= sizeof(new_srd->contextArray);
- dst += sizeof(new_srd->contextArray);
-
- memcpy(dst, &new_srd->contextCounter, sizeof(new_srd->contextCounter));
- room -= sizeof(new_srd->contextCounter);
- dst += sizeof(new_srd->contextCounter);
-
- TPM2B_DIGEST_Marshal(&new_srd->commandAuditDigest, &dst, &room);
- UINT32_Marshal(&new_srd->restartCount, &dst, &room);
- UINT32_Marshal(&new_srd->pcrCounter, &dst, &room);
-
-#ifdef TPM_ALG_ECC
- UINT64_Marshal(&new_srd->commitCounter, &dst, &room);
- TPM2B_NONCE_Marshal(&new_srd->commitNonce, &dst, &room);
-
- memcpy(dst, new_srd->commitArray, sizeof(new_srd->commitArray));
- room -= sizeof(new_srd->commitArray);
- dst += sizeof(new_srd->commitArray);
-#endif
-
- maybe_restore_struct(new_srd, srd, sizeof(*srd), &preserved);
-
- return dst - base;
-}
-
-/*
- * Migrate all reserved objects found in the NVMEM cache after intializing
- * from legacy NVMEM storage.
- */
-static enum ec_error_list migrate_tpm_reserved(struct nn_container *ch)
-{
- STATE_CLEAR_DATA *scd = NULL;
- STATE_RESET_DATA *srd;
- size_t pcr_type_index;
- uint8_t *p_tpm_nvmem = nvmem_cache_base(NVMEM_TPM);
- uint8_t *p_container_body = (uint8_t *)(ch + 1);
- uint8_t index;
-
- ch->container_type = ch->container_type_copy = NN_OBJ_TPM_RESERVED;
-
- for (index = 0; index < NV_VIRTUAL_RESERVE_LAST; index++) {
- NV_RESERVED_ITEM ri;
- int copy_needed = 1;
-
- NvGetReserved(index, &ri);
- p_container_body[0] = index;
-
- switch (index) {
- case NV_STATE_CLEAR:
- scd = (STATE_CLEAR_DATA *)(p_tpm_nvmem + ri.offset);
- ri.size =
- marshal_state_clear(scd, p_container_body + 1);
- copy_needed = 0;
- break;
-
- case NV_STATE_RESET:
- srd = (STATE_RESET_DATA *)(p_tpm_nvmem + ri.offset);
- ri.size = marshal_state_reset_data(
- srd, p_container_body + 1);
- copy_needed = 0;
- break;
- }
-
- if (copy_needed) {
- /*
- * Copy data into the stage area unless already done
- * by marshaling function above.
- */
- memcpy(p_container_body + 1, p_tpm_nvmem + ri.offset,
- ri.size);
- }
-
- ch->size = ri.size + 1;
- save_container(ch);
- }
-
- /*
- * Now all components but the PCRs from STATE_CLEAR_DATA have been
- * saved, let's deal with those PCR arrays. We want to save each PCR
- * in a separate container, as if all PCRs are extended, the total
- * combined size of the arrays would exceed flash page size. Also,
- * PCRs are most likely to change one or very few at a time.
- */
- for (pcr_type_index = 0; pcr_type_index < ARRAY_SIZE(pcr_arrays);
- pcr_type_index++) {
- size_t pcr_index;
-
- for (pcr_index = 0; pcr_index < NUM_STATIC_PCR; pcr_index++)
- migrate_pcr(scd, pcr_type_index, pcr_index, ch);
- }
-
- return EC_SUCCESS;
-}
-
-/*
- * Migrate all evictable objects found in the NVMEM cache after intializing
- * from legacy NVMEM storage.
- */
-static enum ec_error_list migrate_objects(struct nn_container *ch)
-{
- uint32_t next_obj_base;
- uint32_t obj_base;
- uint32_t obj_size;
- void *obj_addr;
-
- ch->container_type = ch->container_type_copy = NN_OBJ_TPM_EVICTABLE;
-
- obj_base = s_evictNvStart;
- obj_addr = nvmem_cache_base(NVMEM_TPM) + obj_base;
- memcpy(&next_obj_base, obj_addr, sizeof(next_obj_base));
-
- while (next_obj_base && (next_obj_base <= s_evictNvEnd)) {
-
- obj_size = next_obj_base - obj_base - sizeof(obj_size);
- memcpy(ch + 1, (uint32_t *)obj_addr + 1, obj_size);
-
- ch->size = obj_size;
- save_container(ch);
-
- obj_base = next_obj_base;
- obj_addr = nvmem_cache_base(NVMEM_TPM) + obj_base;
-
- memcpy(&next_obj_base, obj_addr, sizeof(next_obj_base));
- }
-
- return EC_SUCCESS;
-}
-
-static enum ec_error_list migrate_tpm_nvmem(struct nn_container *ch)
-{
- /* Call this to initialize NVMEM indices. */
- NvEarlyStageFindHandle(0);
-
- migrate_tpm_reserved(ch);
- migrate_objects(ch);
-
- return EC_SUCCESS;
-}
-
-static enum ec_error_list save_var(const uint8_t *key, uint8_t key_len,
- const uint8_t *val, uint8_t val_len,
- struct max_var_container *vc)
-{
- const int total_size =
- key_len + val_len + offsetof(struct max_var_container, body);
- enum ec_error_list rv;
- int local_alloc = !vc;
-
- if (local_alloc) {
- vc = get_scratch_buffer(total_size);
- vc->c_header.generation = 0;
- }
-
- /* Fill up tuple body. */
- vc->t_header.key_len = key_len;
- vc->t_header.val_len = val_len;
- memcpy(vc->body, key, key_len);
- memcpy(vc->body + key_len, val, val_len);
-
- /* Set up container header. */
- vc->c_header.container_type_copy = vc->c_header.container_type =
- NN_OBJ_TUPLE;
- vc->c_header.encrypted = 1;
- vc->c_header.size = sizeof(struct tuple) + val_len + key_len;
-
- rv = save_container(&vc->c_header);
- if (rv == EC_SUCCESS)
- total_var_space += key_len + val_len;
-
- if (local_alloc)
- shared_mem_release(vc);
-
- return rv;
-}
-
-/*
- * Migrate all (key, value) pairs found in the NVMEM cache after intializing
- * from legacy NVMEM storage.
- */
-static enum ec_error_list migrate_vars(struct nn_container *ch)
-{
- const struct tuple *var;
-
- /*
- * During migration (key, value) pairs need to be manually copied from
- * the NVMEM cache.
- */
- set_local_copy();
- var = NULL;
- total_var_space = 0;
-
- while ((var = legacy_getnextvar(var)) != NULL)
- save_var(var->data_, var->key_len, var->data_ + var->key_len,
- var->val_len, (struct max_var_container *)ch);
-
- return EC_SUCCESS;
-}
-
-static int erase_partition(unsigned int act_partition, int erase_backup)
-{
- enum ec_error_list rv;
- size_t flash_base;
-
- /*
- * This is the first time we save using the new scheme, let's prepare
- * the flash space. First determine which half is the backup now and
- * erase it.
- */
- flash_base = (act_partition ^ erase_backup) ? CONFIG_FLASH_NVMEM_BASE_A
- : CONFIG_FLASH_NVMEM_BASE_B;
- flash_base -= CONFIG_PROGRAM_MEMORY_BASE;
-
- rv = flash_physical_erase(flash_base, NVMEM_PARTITION_SIZE);
-
- if (rv != EC_SUCCESS) {
- ccprintf("%s: flash erase failed\n", __func__);
- return -rv;
- }
-
- return flash_base + CONFIG_FLASH_BANK_SIZE;
-}
-
-/*
- * This function is called once in a lifetime, when Cr50 boots up and a legacy
- * partition if found in the flash.
- */
-enum ec_error_list new_nvmem_migrate(unsigned int act_partition)
-{
- int flash_base;
- int i;
- int j;
- struct nn_container *ch;
-
- if (!crypto_enabled())
- return EC_ERROR_INVAL;
-
- /*
- * This is the first time we save using the new scheme, let's prepare
- * the flash space. First determine which half is the backup now and
- * erase it.
- */
- flash_base = erase_partition(act_partition, 1);
- if (flash_base < 0) {
- ccprintf("%s: backup partition erase failed\n", __func__);
- return -flash_base;
- }
-
- ch = get_scratch_buffer(CONFIG_FLASH_BANK_SIZE);
-
- lock_mutex(__LINE__);
-
- /* Populate half of page_list with available page offsets. */
- for (i = 0; i < ARRAY_SIZE(page_list) / 2; i++)
- page_list[i] = flash_base / CONFIG_FLASH_BANK_SIZE + i;
-
- set_first_page_header();
-
- ch->encrypted = 1;
- ch->generation = 0;
-
- migrate_vars(ch);
- migrate_tpm_nvmem(ch);
-
- shared_mem_release(ch);
-
- add_final_delimiter();
-
- unlock_mutex(__LINE__);
-
- if (browse_flash_contents(0) != EC_SUCCESS)
- /* Never returns. */
- report_no_payload_failure(NVMEMF_MIGRATION_FAILURE);
-
- CPRINTS("Migration success, used %zd bytes of flash",
- total_used_size());
-
- /*
- * Now we can erase the active partition and add its flash to the pool.
- */
- flash_base = erase_partition(act_partition, 0);
- if (flash_base < 0)
- /* Never returns. */
- report_no_payload_failure(NVMEMF_LEGACY_ERASE_FAILURE);
-
- /*
- * Populate the second half of the page_list with pages retrieved from
- * legacy partition.
- */
- for (j = 0; j < ARRAY_SIZE(page_list) / 2; j++)
- page_list[i + j] = flash_base / CONFIG_FLASH_BANK_SIZE + j;
-
- return EC_SUCCESS;
-}
-
-/* Check if the passed in flash page is empty, if not - erase it. */
-static void verify_empty_page(void *ph)
-{
- uint32_t *word_p = ph;
- size_t i;
-
- for (i = 0; i < (CONFIG_FLASH_BANK_SIZE / sizeof(*word_p)); i++) {
- if (word_p[i] != (uint32_t)~0) {
- CPRINTS("%s: corrupted page at %pP!", __func__, word_p);
- flash_physical_erase((uintptr_t)word_p -
- CONFIG_PROGRAM_MEMORY_BASE,
- CONFIG_FLASH_BANK_SIZE);
- break;
- }
- }
-}
-
-/*
- * At startup initialize the list of pages which contain NVMEM data and erased
- * pages. The list (in fact an array containing indices of the pages) is
- * sorted by the page number found in the page header. Pages which do not
- * contain valid page header are checked to be erased and are placed at the
- * tail of the list.
- */
-static void init_page_list(void)
-{
- size_t i;
- size_t j;
- size_t page_list_index = 0;
- size_t tail_index;
- struct nn_page_header *ph;
-
- tail_index = ARRAY_SIZE(page_list);
-
- for (i = 0; i < ARRAY_SIZE(page_list); i++) {
- uint32_t page_index;
-
- /*
- * This will yield indices of top pages first, first from the
- * bottom half of the flash, and then from the top half. We
- * know that flash is 512K in size, and pages are 2K in size,
- * the indices will be in 123..127 and 251..255 range.
- */
- if (i < (ARRAY_SIZE(page_list) / 2)) {
- page_index = (CONFIG_FLASH_NEW_NVMEM_BASE_A -
- CONFIG_PROGRAM_MEMORY_BASE) /
- CONFIG_FLASH_BANK_SIZE +
- i;
- } else {
- page_index = (CONFIG_FLASH_NEW_NVMEM_BASE_B -
- CONFIG_PROGRAM_MEMORY_BASE) /
- CONFIG_FLASH_BANK_SIZE -
- ARRAY_SIZE(page_list) / 2 + i;
- }
-
- ph = flash_index_to_ph(page_index);
-
- if (!page_header_is_valid(ph)) {
- /*
- * this is not a valid page, let's plug it in into the
- * tail of the list.
- */
- page_list[--tail_index] = page_index;
- verify_empty_page(ph);
- continue;
- }
-
- /* This seems a valid page, let's put it in order. */
- for (j = 0; j < page_list_index; j++) {
- struct nn_page_header *prev_ph;
-
- prev_ph = list_element_to_ph(j);
-
- if (prev_ph->page_number > ph->page_number) {
- /* Need to move up. */
- memmove(page_list + j + 1, page_list + j,
- sizeof(page_list[0]) *
- (page_list_index - j));
- break;
- }
- }
-
- page_list[j] = page_index;
- page_list_index++;
- }
-
- if (!page_list_index) {
- CPRINTS("Init nvmem from scratch");
- set_first_page_header();
- page_list_index++;
- }
-}
-
-/*
- * The passed in pointer contains marshaled STATE_CLEAR structure as retrieved
- * from flash. This function unmarshals it and places in the NVMEM cache where
- * it belongs. Note that PCRs were not marshaled.
- */
-static void unmarshal_state_clear(uint8_t *pad, int size, uint32_t offset)
-{
- STATE_CLEAR_DATA *real_scd;
- STATE_CLEAR_DATA *scd;
- size_t i;
- uint32_t preserved;
- uint8_t booleans;
-
- real_scd = (STATE_CLEAR_DATA *)((uint8_t *)nvmem_cache_base(NVMEM_TPM) +
- offset);
-
- memset(real_scd, 0, sizeof(*real_scd));
- if (!size)
- return;
-
- memcpy(&preserved, real_scd + 1, sizeof(preserved));
-
- scd = (void *)(((uintptr_t)real_scd + 3) & ~3);
-
- /* Need proper unmarshal. */
- booleans = *pad++;
- scd->shEnable = !!(booleans & 1);
- scd->ehEnable = !!(booleans & (1 << 1));
- scd->phEnableNV = !!(booleans & (1 << 2));
- size--;
-
- memcpy(&scd->platformAlg, pad, sizeof(scd->platformAlg));
- pad += sizeof(scd->platformAlg);
- size -= sizeof(scd->platformAlg);
-
- TPM2B_DIGEST_Unmarshal(&scd->platformPolicy, &pad, &size);
- TPM2B_AUTH_Unmarshal(&scd->platformAuth, &pad, &size);
-
- memcpy(&scd->pcrSave.pcrCounter, pad, sizeof(scd->pcrSave.pcrCounter));
- pad += sizeof(scd->pcrSave.pcrCounter);
- size -= sizeof(scd->pcrSave.pcrCounter);
-
- for (i = 0; i < ARRAY_SIZE(scd->pcrAuthValues.auth); i++)
- TPM2B_DIGEST_Unmarshal(scd->pcrAuthValues.auth + i, &pad,
- &size);
-
- memmove(real_scd, scd, sizeof(*scd));
- memcpy(real_scd + 1, &preserved, sizeof(preserved));
-}
-
-/*
- * The passed in pointer contains marshaled STATE_RESET structure as retrieved
- * from flash. This function unmarshals it and places in the NVMEM cache where
- * it belongs.
- */
-static void unmarshal_state_reset(uint8_t *pad, int size, uint32_t offset)
-{
- STATE_RESET_DATA *real_srd;
- STATE_RESET_DATA *srd;
- uint32_t preserved;
-
- real_srd = (STATE_RESET_DATA *)((uint8_t *)nvmem_cache_base(NVMEM_TPM) +
- offset);
-
- memset(real_srd, 0, sizeof(*real_srd));
- if (!size)
- return;
-
- memcpy(&preserved, real_srd + 1, sizeof(preserved));
-
- srd = (void *)(((uintptr_t)real_srd + 3) & ~3);
-
- TPM2B_AUTH_Unmarshal(&srd->nullProof, &pad, &size);
- TPM2B_DIGEST_Unmarshal((TPM2B_DIGEST *)(&srd->nullSeed), &pad, &size);
- UINT32_Unmarshal(&srd->clearCount, &pad, &size);
- UINT64_Marshal(&srd->objectContextID, &pad, &size);
-
- memcpy(srd->contextArray, pad, sizeof(srd->contextArray));
- size -= sizeof(srd->contextArray);
- pad += sizeof(srd->contextArray);
-
- memcpy(&srd->contextCounter, pad, sizeof(srd->contextCounter));
- size -= sizeof(srd->contextCounter);
- pad += sizeof(srd->contextCounter);
-
- TPM2B_DIGEST_Unmarshal(&srd->commandAuditDigest, &pad, &size);
- UINT32_Unmarshal(&srd->restartCount, &pad, &size);
- UINT32_Unmarshal(&srd->pcrCounter, &pad, &size);
-
-#ifdef TPM_ALG_ECC
- UINT64_Unmarshal(&srd->commitCounter, &pad, &size);
- TPM2B_NONCE_Unmarshal(&srd->commitNonce, &pad, &size);
-
- memcpy(srd->commitArray, pad, sizeof(srd->commitArray));
- size -= sizeof(srd->commitArray);
-#endif
-
- memmove(real_srd, srd, sizeof(*srd));
- memcpy(real_srd + 1, &preserved, sizeof(preserved));
-}
-
-/*
- * Based on the passed in index, find the location of the PCR in the NVMEM
- * cache and copy it there.
- */
-static void restore_pcr(size_t pcr_index, uint8_t *pad, size_t size)
-{
- const STATE_CLEAR_DATA *scd;
- const struct pcr_descriptor *pcrd;
- void *cached; /* This PCR's position in the NVMEM cache. */
-
- if (pcr_index > NUM_OF_PCRS)
- return; /* This is an error. */
-
- pcrd = pcr_arrays + pcr_index / NUM_STATIC_PCR;
- if (pcrd->pcr_size != size)
- return; /* This is an error. */
-
- scd = get_scd();
- cached = (uint8_t *)&scd->pcrSave + pcrd->pcr_array_offset +
- pcrd->pcr_size * (pcr_index % NUM_STATIC_PCR);
-
- memcpy(cached, pad, size);
-}
-
-/* Restore a reserved object found in flash on initialization. */
-static void restore_reserved(void *pad, size_t size, uint8_t *bitmap)
-{
- NV_RESERVED_ITEM ri;
- uint16_t type;
- void *cached;
-
- /*
- * Index is saved as a single byte, update pad to point at the
- * payload.
- */
- type = *(uint8_t *)pad++;
- size--;
-
- if (type < NV_VIRTUAL_RESERVE_LAST) {
- NvGetReserved(type, &ri);
-
- bitmap_bit_set(bitmap, type);
-
- switch (type) {
- case NV_STATE_CLEAR:
- unmarshal_state_clear(pad, size, ri.offset);
- break;
-
- case NV_STATE_RESET:
- unmarshal_state_reset(pad, size, ri.offset);
- break;
-
- default:
- cached = ((uint8_t *)nvmem_cache_base(NVMEM_TPM) +
- ri.offset);
- memcpy(cached, pad, size);
- break;
- }
- return;
- }
-
- restore_pcr(type - NV_VIRTUAL_RESERVE_LAST, pad, size);
-}
-
-/* Restore an evictable object found in flash on initialization. */
-static void restore_object(void *pad, size_t size)
-{
- uint8_t *dest;
-
- if (!next_evict_obj_base)
- next_evict_obj_base = s_evictNvStart;
-
- dest = ((uint8_t *)nvmem_cache_base(NVMEM_TPM) + next_evict_obj_base);
- next_evict_obj_base += size + sizeof(next_evict_obj_base);
- memcpy(dest, &next_evict_obj_base, sizeof(next_evict_obj_base));
-
- dest += sizeof(next_evict_obj_base);
- memcpy(dest, pad, size);
- dest += size;
-
- memset(dest, 0, sizeof(next_evict_obj_base));
-}
-
-/*
- * When starting from scratch (flash fully erased) there would be no reserved
- * objects in NVMEM, and for the commit to work properly, every single
- * reserved object needs to be present in the flash so that its value is
- * compared with the cache contents.
- *
- * There is also an off chance of a bug where a reserved value is lost in the
- * flash - it would never be reinstated even after TPM reinitializes.
- *
- * The reserved_bitmap array is a bitmap of all detected reserved objects,
- * those not in the array are initialized to a dummy initial value.
- */
-static enum ec_error_list verify_reserved(uint8_t *reserved_bitmap,
- struct nn_container *ch)
-{
- enum ec_error_list rv;
- int i;
- uint8_t *container_body;
- int delimiter_needed = 0;
-
- /* All uninitted reserved objects set to zero. */
- memset(ch, 0, CONFIG_FLASH_BANK_SIZE);
-
- ch->container_type = ch->container_type_copy = NN_OBJ_TPM_RESERVED;
- ch->encrypted = 1;
- container_body = (uint8_t *)(ch + 1);
-
- rv = EC_SUCCESS;
-
- for (i = 0; i < NV_VIRTUAL_RESERVE_LAST; i++) {
- NV_RESERVED_ITEM ri;
-
- if (bitmap_bit_check(reserved_bitmap, i))
- continue;
-
- NvGetReserved(i, &ri);
- container_body[0] = i;
-
- switch (i) {
- /*
- * No need to save these on initialization from
- * scratch, unmarshaling code will properly expand
- * size of zero.
- */
- case NV_STATE_CLEAR:
- case NV_STATE_RESET:
- ri.size = 0;
- break;
-
- /*
- * This is used for Ram Index field, prepended by
- * size. Set the size to minimum, the size of the size
- * field.
- */
- case NV_RAM_INDEX_SPACE:
- ri.size = sizeof(uint32_t);
- break;
-
- default:
- break;
- }
-
- delimiter_needed = 1;
-
- ch->size = ri.size + 1;
- rv = save_container(ch);
-
- /* Clean up encrypted contents. */
- memset(container_body + 1, 0, ri.size);
-
- if (rv != EC_SUCCESS)
- break;
- }
-
- if (delimiter_needed && (rv == EC_SUCCESS))
- add_final_delimiter();
-
- return rv;
-}
-
-static enum ec_error_list invalidate_object(const struct nn_container *ch)
-{
- struct nn_container c_copy;
-
- c_copy = *ch;
- c_copy.container_type = NN_OBJ_OLD_COPY;
-
- return write_to_flash(ch, &c_copy, sizeof(uint32_t));
-}
-
-static enum ec_error_list delete_object(const struct access_tracker *at,
- struct nn_container *ch)
-{
- const void *flash_ch;
-
- flash_ch = page_cursor(&at->ct);
-
- if (memcmp(ch, flash_ch, sizeof(uint32_t)))
- report_no_payload_failure(NVMEMF_PRE_ERASE_MISMATCH);
-
- if (!del_candidates)
- return invalidate_object(flash_ch);
-
- /*
- * Do not delete the object yet, save it in the list of delete
- * candidates.
- */
- if (del_candidates->num_candidates ==
- ARRAY_SIZE(del_candidates->candidates))
- report_no_payload_failure(NVMEMF_EXCESS_DELETE_OBJECTS);
-
- del_candidates->candidates[del_candidates->num_candidates++] = flash_ch;
- return EC_SUCCESS;
-}
-
-static enum ec_error_list verify_last_section(
- const struct page_tracker *prev_del, struct nn_container *ch)
-{
- /*
- * This is very inefficient, but we do this only when recovering from
- * botched nvmem saves.
- *
- * For each object found between prev_del and last_del we need to
- * check if there are earlier instances of these objects in the flash
- * which are not yet deleted, and delete them if found.
- */
- struct object {
- uint8_t cont_type;
- union {
- uint32_t handle; /* For evictables. */
- uint8_t id; /* For reserved objects. */
- struct { /* For tuples. */
- uint32_t key_hash;
- uint8_t key_len;
- };
- };
- };
- struct new_objects {
- uint8_t num_objects;
- struct object objects[2 * MAX_DELETE_CANDIDATES];
- };
-
- struct access_tracker at;
- struct new_objects *newobjs;
- struct object *po;
- uint8_t ctype;
- struct page_tracker top_del;
- struct max_var_container *vc;
- int i;
-
- newobjs = get_scratch_buffer(sizeof(struct new_objects));
-
- at.mt = *prev_del;
- for (i = 0; i < ARRAY_SIZE(page_list); i++)
- if (list_element_to_ph(i) == at.mt.ph) {
- at.list_index = i;
- break;
- }
-
- po = newobjs->objects;
-
- while (get_next_object(&at, ch, 0) == EC_SUCCESS) {
- ctype = ch->container_type;
-
- /* Speculative assignment, might be unused. */
- po->cont_type = ctype;
- switch (ctype) {
- case NN_OBJ_TPM_RESERVED:
- po->id = *((uint8_t *)(ch + 1));
- break;
-
- case NN_OBJ_TPM_EVICTABLE:
- po->handle = *((uint32_t *)(ch + 1));
- break;
-
- case NN_OBJ_TUPLE:
- vc = (struct max_var_container *)ch;
- po->key_len = vc->t_header.key_len;
- app_compute_hash_wrapper(vc->t_header.data_,
- po->key_len, &po->key_hash,
- sizeof(po->key_hash));
- break;
- default:
- continue;
- }
- if (++(newobjs->num_objects) == ARRAY_SIZE(newobjs->objects))
- /* Never returns. */
- report_no_payload_failure(NVMEMF_SECTION_VERIFY);
- po++;
- }
-
- /*
- * Last object read from flash should have been a non-finalized
- * delimiter.
- */
- if (ch->container_type != NN_OBJ_TRANSACTION_DEL) {
- struct nvmem_failure_payload fp;
-
- fp.failure_type = NVMEMF_UNEXPECTED_LAST_OBJ;
- fp.last_obj_type = ch->container_type;
- /* Never returns. */
- report_failure(&fp, sizeof(fp.last_obj_type));
- }
-
- /*
- * Now we have a cache of of objects which were updated but their old
- * instances could have been left in the flash. Let's iterate over the
- * flash and delete those if found.
- */
- memset(&at, 0, sizeof(at));
- while ((at.mt.ph != prev_del->ph) &&
- (at.mt.data_offset != prev_del->data_offset)) {
- size_t i;
- size_t key_size;
- uint32_t key;
-
- if (get_next_object(&at, ch, 0) != EC_SUCCESS)
- report_no_payload_failure(NVMEMF_MISSING_OBJECT);
-
- ctype = ch->container_type;
-
- switch (ctype) {
- case NN_OBJ_TPM_RESERVED:
- key = *((uint8_t *)(ch + 1));
- key_size = sizeof(uint8_t);
- break;
-
- case NN_OBJ_TPM_EVICTABLE:
- key = *((uint32_t *)(ch + 1));
- key_size = sizeof(uint32_t);
- break;
-
- case NN_OBJ_TUPLE:
- vc = (struct max_var_container *)ch;
- key_size = vc->t_header.key_len;
- app_compute_hash_wrapper(vc->t_header.data_, key_size,
- &key, sizeof(key));
- break;
-
- default:
- continue;
- }
-
- for (i = 0, po = newobjs->objects; i < newobjs->num_objects;
- i++, po++) {
- if (po->cont_type != ctype)
- continue;
-
- if ((ctype == NN_OBJ_TPM_RESERVED) && (po->id != key))
- continue;
-
- if ((ctype == NN_OBJ_TPM_EVICTABLE) &&
- (po->handle != key))
- continue;
-
- if ((ctype == NN_OBJ_TUPLE) &&
- ((po->key_len != key_size) ||
- (key != po->key_hash)))
- continue;
-
- /*
- * This indeed is a leftover which needs to be
- * deleted.
- */
- delete_object(&at, ch);
- }
- }
- shared_mem_release(newobjs);
- if (master_at.mt.data_offset > sizeof(struct nn_page_header)) {
- top_del.ph = master_at.mt.ph;
- top_del.data_offset =
- master_at.mt.data_offset - sizeof(struct nn_container);
- } else {
- top_del.ph = list_element_to_ph(master_at.list_index - 1);
- top_del.data_offset =
- CONFIG_FLASH_BANK_SIZE - -sizeof(struct nn_container);
- }
-
- return finalize_delimiter(page_cursor(&top_del));
-}
-
-/*
- * This function is called during initialization after the entire flash
- * contents were scanned, to verify that flash is in a valid state.
- */
-static enum ec_error_list verify_delimiter(struct nn_container *nc)
-{
- enum ec_error_list rv;
- /* Used to read starting at last good delimiter. */
- struct access_tracker dpt = {};
-
- if ((master_at.list_index == 0) &&
- (master_at.mt.data_offset == sizeof(struct nn_page_header))) {
- /* This must be an init from scratch, no delimiter yet. */
- if (!master_at.dt.ph)
- return EC_SUCCESS;
-
- /* This is bad, will have to wipe out everything. */
- return EC_ERROR_INVAL;
- }
-
- if (nc->container_type_copy == NN_OBJ_TRANSACTION_DEL) {
- if (nc->container_type == NN_OBJ_OLD_COPY)
- return EC_SUCCESS;
- /*
- * The delimiter is there, but it has not been finalized,
- * which means that there might be objects in the flash which
- * were not updated after the last delimiter was written.
- */
- return verify_last_section(&master_at.dt, nc);
- }
-
- /*
- * The delimiter is not there, everything above the last verified
- * delimiter must go.
- *
- * First, create a context for retrieving objects starting at the last
- * valid delimiter, make sure list index is set properly.
- */
- dpt.mt = master_at.dt;
- if (dpt.mt.ph == master_at.mt.ph) {
- dpt.list_index = master_at.list_index;
- } else {
- uint8_t i;
-
- for (i = 0; i < master_at.list_index; i++)
- if (list_element_to_ph(i) == dpt.mt.ph) {
- dpt.list_index = i;
- break;
- }
- }
-
- while ((rv = get_next_object(&dpt, nc, 0)) == EC_SUCCESS)
- delete_object(&dpt, nc);
-
- if (rv == EC_ERROR_INVAL) {
- /*
- * There must have been an interruption of the saving process,
- * let's wipe out flash to the end of the current page and
- * compact the storage.
- */
- size_t remainder_size;
- const void *p = page_cursor(&master_at.ct);
-
- if (dpt.ct.ph != dpt.mt.ph) {
- /*
- * The last retrieved object is spanning flash page
- * boundary.
- *
- * If this is not the last object in the flash, this
- * is an unrecoverable init failure.
- */
- if ((dpt.mt.ph != master_at.mt.ph) ||
- (list_element_to_ph(dpt.list_index - 1) !=
- dpt.ct.ph))
- report_no_payload_failure(
- NVMEMF_CORRUPTED_INIT);
- /*
- * Let's erase the page where the last object spilled
- * into.
- */
- flash_physical_erase((uintptr_t)dpt.mt.ph -
- CONFIG_PROGRAM_MEMORY_BASE,
- CONFIG_FLASH_BANK_SIZE);
- /*
- * And move it to the available pages part of the
- * pages list.
- */
- master_at.list_index -= 1;
- master_at.mt = dpt.ct;
- }
-
- remainder_size = CONFIG_FLASH_BANK_SIZE - dpt.ct.data_offset;
- memset(nc, 0, remainder_size);
- write_to_flash(p, nc, remainder_size);
- /* Make sure compaction starts with the new page. */
- start_new_flash_page(0);
- compact_nvmem();
- } else {
- /* Add delimiter at the very top. */
- add_final_delimiter();
- }
-
- /* Need to re-read the NVMEM cache. */
- return EC_ERROR_TRY_AGAIN;
-}
-
-/*
- * At startup iterate over flash contents and move TPM objects into the
- * appropriate locations in the NVMEM cache.
- */
-static enum ec_error_list retrieve_nvmem_contents(void)
-{
- int rv;
- int tries;
- struct max_var_container *vc;
- struct nn_container *nc;
- uint8_t res_bitmap[(NV_PSEUDO_RESERVE_LAST + 7) / 8];
-
- /* No saved object will exceed CONFIG_FLASH_BANK_SIZE in size. */
- nc = get_scratch_buffer(CONFIG_FLASH_BANK_SIZE);
-
- /*
- * Depending on the state of flash, we might have to do this three
- * times.
- */
- for (tries = 0; tries < 3; tries++) {
- memset(&master_at, 0, sizeof(master_at));
- memset(nvmem_cache_base(NVMEM_TPM), 0,
- nvmem_user_sizes[NVMEM_TPM]);
- memset(res_bitmap, 0, sizeof(res_bitmap));
- next_evict_obj_base = 0;
-
- while ((rv = get_next_object(&master_at, nc, 0)) ==
- EC_SUCCESS) {
- switch (nc->container_type) {
- case NN_OBJ_TUPLE:
- vc = (struct max_var_container *)nc;
- total_var_space += vc->t_header.key_len +
- vc->t_header.val_len;
- break; /* Keep tuples in flash. */
- case NN_OBJ_TPM_RESERVED:
- restore_reserved(nc + 1, nc->size, res_bitmap);
- break;
-
- case NN_OBJ_TPM_EVICTABLE:
- restore_object(nc + 1, nc->size);
- break;
- default:
- break;
- }
- }
-
- rv = verify_delimiter(nc);
-
- if (rv != EC_ERROR_TRY_AGAIN)
- break;
- }
-
- if (rv != EC_SUCCESS)
- report_no_payload_failure(NVMEMF_UNRECOVERABLE_INIT);
-
- rv = verify_reserved(res_bitmap, nc);
-
- shared_mem_release(nc);
-
- return rv;
-}
-
-enum ec_error_list new_nvmem_init(void)
-{
- enum ec_error_list rv;
- timestamp_t start, init;
-
- if (!crypto_enabled())
- return EC_ERROR_INVAL;
-
- init_in_progress = 1;
-
- total_var_space = 0;
-
- /* Initialize NVMEM indices. */
- NvEarlyStageFindHandle(0);
-
- lock_mutex(__LINE__);
-
- init_page_list();
-
- start = get_time();
-
- rv = retrieve_nvmem_contents();
-
- init = get_time();
-
- unlock_mutex(__LINE__);
-
- init_in_progress = 0;
-
- CPRINTS("init took %d", (uint32_t)(init.val - start.val));
-
- return rv;
-}
-
-/*
- * Browse through the flash storage and save all evictable objects' offsets in
- * the passed in array. This is used to keep track of objects added or deleted
- * by the TPM library.
- */
-test_export_static size_t init_object_offsets(uint16_t *offsets, size_t count)
-{
- size_t num_objects = 0;
- uint32_t next_obj_base;
- uint32_t obj_base;
- void *obj_addr;
-
- obj_base = s_evictNvStart;
- obj_addr = (uint8_t *)nvmem_cache_base(NVMEM_TPM) + obj_base;
- memcpy(&next_obj_base, obj_addr, sizeof(next_obj_base));
-
- while (next_obj_base && (next_obj_base <= s_evictNvEnd)) {
- if (num_objects == count) {
- /* What do we do here?! */
- ccprintf("Too many objects!\n");
- break;
- }
-
- offsets[num_objects++] =
- obj_base - s_evictNvStart + sizeof(next_obj_base);
-
- obj_addr = nvmem_cache_base(NVMEM_TPM) + next_obj_base;
- obj_base = next_obj_base;
- memcpy(&next_obj_base, obj_addr, sizeof(next_obj_base));
- }
-
- return num_objects;
-}
-
-static enum ec_error_list update_object(const struct access_tracker *at,
- struct nn_container *ch,
- void *cached_object, size_t new_size)
-{
- size_t copy_size = new_size;
- size_t preserved_size;
- uint32_t preserved_hash;
- uint8_t *dst = (uint8_t *)(ch + 1);
-
- preserved_size = ch->size;
- preserved_hash = ch->container_hash;
-
- /*
- * Need to copy data into the container, skip reserved type if it is a
- * reserved object.
- */
- if (ch->container_type == NN_OBJ_TPM_RESERVED) {
- dst++;
- copy_size--;
- }
- memcpy(dst, cached_object, copy_size);
-
- ch->generation++;
- ch->size = new_size;
- save_container(ch);
-
- ch->generation--;
- ch->size = preserved_size;
- ch->container_hash = preserved_hash;
- return delete_object(at, ch);
-}
-
-static enum ec_error_list update_pcr(const struct access_tracker *at,
- struct nn_container *ch, uint8_t index,
- uint8_t *cached)
-{
- uint8_t preserved;
-
- cached--;
- preserved = cached[0];
- cached[0] = index;
- update_object(at, ch, cached, ch->size);
- cached[0] = preserved;
-
- return EC_SUCCESS;
-}
-
-static enum ec_error_list save_pcr(struct nn_container *ch,
- uint8_t reserved_index, const void *pcr,
- size_t pcr_size)
-{
- uint8_t *container_body;
-
- ch->container_type = ch->container_type_copy = NN_OBJ_TPM_RESERVED;
- ch->encrypted = 1;
- ch->size = pcr_size + 1;
- ch->generation = 0;
-
- container_body = (uint8_t *)(ch + 1);
- container_body[0] = reserved_index;
- memcpy(container_body + 1, pcr, pcr_size);
-
- return save_container(ch);
-}
-
-static enum ec_error_list maybe_save_pcr(struct nn_container *ch,
- size_t pcr_index)
-{
- const STATE_CLEAR_DATA *scd;
- const struct pcr_descriptor *pcrd;
- const void *cached;
- size_t pcr_size;
-
- pcrd = pcr_arrays + pcr_index / NUM_STATIC_PCR;
- scd = get_scd();
-
- pcr_size = pcrd->pcr_size;
-
- cached = (const uint8_t *)&scd->pcrSave + pcrd->pcr_array_offset +
- pcr_size * (pcr_index % NUM_STATIC_PCR);
-
- if (is_empty(cached, pcr_size))
- return EC_SUCCESS;
-
- return save_pcr(ch, pcr_index + NV_VIRTUAL_RESERVE_LAST, cached,
- pcr_size);
-}
-
-/*
- * The process_XXX functions below are used to check and if necessary add,
- * update or delete objects from the flash based on the NVMEM cache
- * contents.
- */
-static enum ec_error_list process_pcr(const struct access_tracker *at,
- struct nn_container *ch, uint8_t index,
- const uint8_t *saved, uint8_t *pcr_bitmap)
-{
- STATE_CLEAR_DATA *scd;
- const struct pcr_descriptor *pcrd;
- size_t pcr_bitmap_index;
- size_t pcr_index;
- size_t pcr_size;
- uint8_t *cached;
-
- pcr_bitmap_index = index - NV_VIRTUAL_RESERVE_LAST;
-
- if (pcr_bitmap_index > NUM_OF_PCRS)
- return EC_ERROR_INVAL;
-
- pcrd = pcr_arrays + pcr_bitmap_index / NUM_STATIC_PCR;
- pcr_index = pcr_bitmap_index % NUM_STATIC_PCR;
-
- pcr_size = pcrd->pcr_size;
-
- if (pcr_size != (ch->size - 1))
- return EC_ERROR_INVAL; /* This is an error. */
-
- /* Find out base address of the cached PCR. */
- scd = get_scd();
- cached = (uint8_t *)&scd->pcrSave + pcrd->pcr_array_offset +
- pcr_size * pcr_index;
-
- /* Set bitmap bit to indicate that this PCR was looked at. */
- bitmap_bit_set(pcr_bitmap, pcr_bitmap_index);
-
- if (memcmp(saved, cached, pcr_size))
- return update_pcr(at, ch, index, cached);
-
- return EC_SUCCESS;
-}
-
-static enum ec_error_list process_reserved(const struct access_tracker *at,
- struct nn_container *ch,
- uint8_t *pcr_bitmap)
-{
- NV_RESERVED_ITEM ri;
- size_t new_size;
- uint8_t *saved;
- uint8_t index;
- void *cached;
-
- /*
- * Find out this object's location in the cache (first byte of the
- * contents is the index of the reserved object.
- */
- saved = (uint8_t *)(ch + 1);
- index = *saved++;
-
- NvGetReserved(index, &ri);
-
- if (ri.size) {
- void *marshaled;
-
- cached = (uint8_t *)nvmem_cache_base(NVMEM_TPM) + ri.offset;
-
- /*
- * For NV_STATE_CLEAR and NV_STATE_RESET cases Let's marshal
- * cached data to be able to compare it with saved data.
- */
- if (index == NV_STATE_CLEAR) {
- marshaled = ((uint8_t *)(ch + 1)) + ch->size;
- new_size = marshal_state_clear(cached, marshaled);
- cached = marshaled;
- } else if (index == NV_STATE_RESET) {
- marshaled = ((uint8_t *)(ch + 1)) + ch->size;
- new_size = marshal_state_reset_data(cached, marshaled);
- cached = marshaled;
- } else {
- new_size = ri.size;
- }
-
- if ((new_size == (ch->size - 1)) &&
- !memcmp(saved, cached, new_size))
- return EC_SUCCESS;
-
- return update_object(at, ch, cached, new_size + 1);
- }
-
- /* This must be a PCR. */
- return process_pcr(at, ch, index, saved, pcr_bitmap);
-}
-
-static enum ec_error_list process_object(const struct access_tracker *at,
- struct nn_container *ch,
- uint16_t *tpm_object_offsets,
- size_t *num_objects)
-{
- size_t i;
- uint32_t cached_size;
- uint32_t cached_type;
- uint32_t flash_type;
- uint32_t next_obj_base;
- uint8_t *evict_start;
- void *pcache;
-
- evict_start = (uint8_t *)nvmem_cache_base(NVMEM_TPM) + s_evictNvStart;
- memcpy(&flash_type, ch + 1, sizeof(flash_type));
- for (i = 0; i < *num_objects; i++) {
-
- /* Find TPM object in the NVMEM cache. */
- pcache = evict_start + tpm_object_offsets[i];
- memcpy(&cached_type, pcache, sizeof(cached_type));
- if (cached_type == flash_type)
- break;
- }
-
- if (i == *num_objects) {
- /*
- * This object is not in the cache any more, delete it from
- * flash.
- */
- return delete_object(at, ch);
- }
-
- memcpy(&next_obj_base, (uint8_t *)pcache - sizeof(next_obj_base),
- sizeof(next_obj_base));
- cached_size = next_obj_base - s_evictNvStart - tpm_object_offsets[i];
- if ((cached_size != ch->size) || memcmp(ch + 1, pcache, cached_size)) {
- /*
- * Object changed. Let's delete the old copy and save the new
- * one.
- */
- update_object(at, ch, pcache, ch->size);
- }
-
- tpm_object_offsets[i] = tpm_object_offsets[*num_objects - 1];
- *num_objects -= 1;
-
- return EC_SUCCESS;
-}
-
-static enum ec_error_list save_new_object(uint16_t obj_base, void *buf)
-{
- size_t obj_size;
- struct nn_container *ch = buf;
- uint32_t next_obj_base;
- void *obj_addr;
-
- obj_addr = (uint8_t *)nvmem_cache_base(NVMEM_TPM) + obj_base +
- s_evictNvStart;
- memcpy(&next_obj_base, obj_addr - sizeof(next_obj_base),
- sizeof(next_obj_base));
- obj_size = next_obj_base - obj_base - s_evictNvStart;
-
- ch->container_type_copy = ch->container_type = NN_OBJ_TPM_EVICTABLE;
- ch->encrypted = 1;
- ch->size = obj_size;
- ch->generation = 0;
- memcpy(ch + 1, obj_addr, obj_size);
-
- return save_container(ch);
-}
-
-static enum ec_error_list new_nvmem_save_(void)
-{
- const void *fence_ph;
- size_t i;
- size_t num_objs;
- struct nn_container *ch;
- struct access_tracker at = {};
- uint16_t fence_offset;
- /* We don't foresee ever storing this many objects. */
- uint16_t tpm_object_offsets[MAX_STORED_EVICTABLE_OBJECTS];
- uint8_t pcr_bitmap[(NUM_STATIC_PCR * ARRAY_SIZE(pcr_arrays) + 7) / 8];
-
- /* See if compaction is needed. */
- if (master_at.list_index >= (ARRAY_SIZE(page_list) - 3)) {
- enum ec_error_list rv;
-
- rv = compact_nvmem();
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- fence_ph = master_at.mt.ph;
- fence_offset = master_at.mt.data_offset;
-
- num_objs = init_object_offsets(tpm_object_offsets,
- ARRAY_SIZE(tpm_object_offsets));
-
- memset(pcr_bitmap, 0, sizeof(pcr_bitmap));
- del_candidates = get_scratch_buffer(CONFIG_FLASH_BANK_SIZE +
- sizeof(struct delete_candidates));
- ch = (void *)(del_candidates + 1);
- del_candidates->num_candidates = 0;
-
- while ((fence_ph != at.mt.ph) || (fence_offset != at.mt.data_offset)) {
- int rv;
-
- rv = get_next_object(&at, ch, 0);
-
- if (rv == EC_ERROR_MEMORY_ALLOCATION)
- break;
-
- if (rv != EC_SUCCESS) {
- ccprintf("%s: failed to read flash when saving (%d)!\n",
- __func__, rv);
- shared_mem_release(ch);
- return rv;
- }
-
- if (ch->container_type == NN_OBJ_TPM_RESERVED) {
- process_reserved(&at, ch, pcr_bitmap);
- continue;
- }
-
- if (ch->container_type == NN_OBJ_TPM_EVICTABLE) {
- process_object(&at, ch, tpm_object_offsets, &num_objs);
- continue;
- }
- }
-
- /* Now save new objects, if any. */
- for (i = 0; i < num_objs; i++)
- save_new_object(tpm_object_offsets[i], ch);
-
- /* And new pcrs, if any. */
- for (i = 0; i < NUM_OF_PCRS; i++) {
- if (bitmap_bit_check(pcr_bitmap, i))
- continue;
- maybe_save_pcr(ch, i);
- }
-
-#if defined(NVMEM_TEST_BUILD)
- if (failure_mode == TEST_FAIL_WHEN_SAVING) {
- shared_mem_release(del_candidates);
- del_candidates = NULL;
- return EC_SUCCESS;
- }
-#endif
- /*
- * Add a delimiter if there have been new containers added to the
- * flash.
- */
- if (del_candidates->num_candidates ||
- (fence_offset != master_at.mt.data_offset) ||
- (fence_ph != master_at.mt.ph)) {
- const void *del = page_cursor(&master_at.mt);
-
- add_delimiter();
-
- if (del_candidates->num_candidates) {
- /* Now delete objects which need to be deleted. */
- for (i = 0; i < del_candidates->num_candidates; i++)
- invalidate_object(
- del_candidates->candidates[i]);
- }
-
-#if defined(NVMEM_TEST_BUILD)
- if (failure_mode == TEST_FAIL_WHEN_INVALIDATING) {
- shared_mem_release(del_candidates);
- del_candidates = NULL;
- return EC_SUCCESS;
- }
-#endif
- finalize_delimiter(del);
- }
-
- shared_mem_release(del_candidates);
- del_candidates = NULL;
-
- return EC_SUCCESS;
-}
-
-enum ec_error_list new_nvmem_save(void)
-{
- enum ec_error_list rv;
-
- if (!crypto_enabled())
- return EC_ERROR_INVAL;
-
- lock_mutex(__LINE__);
- rv = new_nvmem_save_();
- unlock_mutex(__LINE__);
-
- return rv;
-}
-
-/* Caller must free memory allocated by this function! */
-static struct max_var_container *find_var(const uint8_t *key, size_t key_len,
- struct access_tracker *at)
-{
- int rv;
- struct max_var_container *vc;
-
- vc = get_scratch_buffer(CONFIG_FLASH_BANK_SIZE);
-
- /*
- * Let's iterate over all objects there are and look for matching
- * tuples.
- */
- while ((rv = get_next_object(at, &vc->c_header, 0)) == EC_SUCCESS) {
-
- if (vc->c_header.container_type != NN_OBJ_TUPLE)
- continue;
-
- /* Verify consistency, first that the sizes match */
- if ((vc->t_header.key_len + vc->t_header.val_len +
- sizeof(vc->t_header)) != vc->c_header.size) {
- ccprintf("%s: - inconsistent sizes!\n", __func__);
- /* report error here. */
- continue;
- }
-
- /* Ok, found a tuple, does the key match? */
- if ((key_len == vc->t_header.key_len) &&
- !memcmp(key, vc->body, key_len))
- /* Yes, it does! */
- return vc;
- }
-
- shared_mem_release(vc);
- return NULL;
-}
-
-const struct tuple *getvar(const uint8_t *key, uint8_t key_len)
-{
- const struct max_var_container *vc;
- struct access_tracker at = {};
-
- if (!crypto_enabled())
- return NULL;
-
- if (!key || !key_len)
- return NULL;
-
- lock_mutex(__LINE__);
- vc = find_var(key, key_len, &at);
- unlock_mutex(__LINE__);
-
- if (vc)
- return &vc->t_header;
-
- return NULL;
-}
-
-void freevar(const struct tuple *var)
-{
- void *vc;
-
- if (!var)
- return;
-
- vc = (uint8_t *)var - offsetof(struct max_var_container, t_header);
- shared_mem_release(vc);
-}
-
-static enum ec_error_list save_container(struct nn_container *nc)
-{
- uint32_t hash;
- uint32_t salt[4];
-
- nc->container_hash = 0;
- app_compute_hash_wrapper(nc, sizeof(*nc) + nc->size, &hash,
- sizeof(hash));
- nc->container_hash = hash; /* This will truncate it. */
-
- /* Skip transactions delimiters. */
- if (nc->size) {
- salt[0] = master_at.mt.ph->page_number;
- salt[1] = master_at.mt.data_offset;
- salt[2] = nc->container_hash;
- salt[3] = 0;
-
- if (!app_cipher(salt, nc + 1, nc + 1, nc->size))
- report_no_payload_failure(NVMEMF_CIPHER_ERROR);
- }
-
- return save_object(nc);
-}
-
-static int setvar_(const uint8_t *key, uint8_t key_len, const uint8_t *val,
- uint8_t val_len)
-{
- enum ec_error_list rv;
- int erase_request;
- size_t new_var_space;
- size_t old_var_space;
- struct max_var_container *vc;
- struct access_tracker at = {};
- const struct nn_container *del;
-
- if (!key || !key_len)
- return EC_ERROR_INVAL;
-
- new_var_space = key_len + val_len;
-
- if (new_var_space > MAX_VAR_BODY_SPACE)
- /* Too much space would be needed. */
- return EC_ERROR_INVAL;
-
- erase_request = !val || !val_len;
-
- /* See if compaction is needed. */
- if (!erase_request &&
- (master_at.list_index >= (ARRAY_SIZE(page_list) - 3))) {
- rv = compact_nvmem();
- if (rv != EC_SUCCESS)
- return rv;
- }
-
- vc = find_var(key, key_len, &at);
-
- if (erase_request) {
- if (!vc)
- /* Nothing to erase. */
- return EC_SUCCESS;
-
- rv = invalidate_object(
- (struct nn_container *)((uintptr_t)at.ct.ph +
- at.ct.data_offset));
-
- if (rv == EC_SUCCESS)
- total_var_space -=
- vc->t_header.key_len + vc->t_header.val_len;
-
- shared_mem_release(vc);
- return rv;
- }
-
- /* Is this variable already there? */
- if (!vc) {
- /* No, it is not. Will it fit? */
- if ((new_var_space + total_var_space) > MAX_VAR_TOTAL_SPACE)
- /* No, it will not. */
- return EC_ERROR_OVERFLOW;
-
- rv = save_var(key, key_len, val, val_len, vc);
- if (rv == EC_SUCCESS)
- add_final_delimiter();
-
- return rv;
- }
-
- /* The variable was found, let's see if the value is being changed. */
- if (vc->t_header.val_len == val_len &&
- !memcmp(val, vc->body + key_len, val_len)) {
- shared_mem_release(vc);
- return EC_SUCCESS;
- }
-
- /* Ok, the variable was found, and is of a different value. */
- old_var_space = vc->t_header.val_len + vc->t_header.key_len;
-
- if ((old_var_space < new_var_space) &&
- ((total_var_space + new_var_space - old_var_space) >
- MAX_VAR_TOTAL_SPACE)) {
- shared_mem_release(vc);
- return EC_ERROR_OVERFLOW;
- }
-
- /* Save the new instance first with the larger generation number. */
- vc->c_header.generation++;
- rv = save_var(key, key_len, val, val_len, vc);
- shared_mem_release(vc);
- del = page_cursor(&master_at.mt);
-#if defined(NVMEM_TEST_BUILD)
- if (failure_mode == TEST_FAIL_SAVING_VAR)
- return EC_SUCCESS;
-#endif
- add_delimiter();
- if (rv == EC_SUCCESS) {
- rv = invalidate_object(
- (struct nn_container *)((uintptr_t)at.ct.ph +
- at.ct.data_offset));
- if (rv == EC_SUCCESS) {
- total_var_space -= old_var_space;
-#if defined(NVMEM_TEST_BUILD)
- if (failure_mode != TEST_FAIL_FINALIZING_VAR)
-#endif
- finalize_delimiter(del);
- }
- }
- return rv;
-}
-
-int setvar(const uint8_t *key, uint8_t key_len, const uint8_t *val,
- uint8_t val_len)
-{
- int rv;
-
- if (!crypto_enabled())
- return EC_ERROR_INVAL;
-
- lock_mutex(__LINE__);
- rv = setvar_(key, key_len, val, val_len);
- unlock_mutex(__LINE__);
-
- return rv;
-}
-
-static void dump_contents(const struct nn_container *ch)
-{
- const uint8_t *buf = (const void *)ch;
- size_t i;
- size_t total_size = sizeof(*ch) + ch->size;
-
- for (i = 0; i < total_size; i++) {
- if (!(i % 16)) {
- ccprintf("\n");
- cflush();
- }
- ccprintf(" %02x", buf[i]);
- }
- ccprintf("\n");
-}
-
-/*
- * Clear tpm data from nvmem. First fill up the current top page with erased
- * objects, then compact the flash storage, removing all TPM related objects.
- * This would guarantee that all pages where TPM objecs were stored would be
- * erased.
- */
-int nvmem_erase_tpm_data(void)
-{
- const uint8_t *key;
- const uint8_t *val;
- int rv;
- struct nn_container *ch;
- struct access_tracker at = {};
- uint8_t saved_list_index;
- uint8_t key_len;
-
- if (!crypto_enabled())
- return EC_ERROR_INVAL;
-
- ch = get_scratch_buffer(CONFIG_FLASH_BANK_SIZE);
-
- lock_mutex(__LINE__);
-
- while (get_next_object(&at, ch, 0) == EC_SUCCESS) {
-
- if ((ch->container_type != NN_OBJ_TPM_RESERVED) &&
- (ch->container_type != NN_OBJ_TPM_EVICTABLE))
- continue;
-
- delete_object(&at, ch);
- }
-
- unlock_mutex(__LINE__);
-
- shared_mem_release(ch);
-
- /*
- * Now fill up the current flash page with erased objects to make sure
- * that it would be erased during next compaction. Use dummy key,
- * value pairs as the erase objects.
- */
- saved_list_index = master_at.list_index;
- key = (const uint8_t *)nvmem_erase_tpm_data;
- val = (const uint8_t *)nvmem_erase_tpm_data;
- key_len = MAX_VAR_BODY_SPACE - 255;
- do {
- size_t to_go_in_page;
- uint8_t val_len;
-
- to_go_in_page =
- CONFIG_FLASH_BANK_SIZE - master_at.mt.data_offset;
- if (to_go_in_page >
- (MAX_VAR_BODY_SPACE +
- offsetof(struct max_var_container, body) - 1)) {
- val_len = MAX_VAR_BODY_SPACE - key_len;
- } else {
- /*
- * Let's not write more than we have to get over the
- * page limit. The minimum size we need is:
- *
- * <container header size> + <tuple header size> + 2
- *
- * (where key and value are of one byte each).
- */
- if (to_go_in_page <
- (offsetof(struct max_var_container, body) + 2)) {
- /*
- * There is very little room left, even key
- * and value of size of one each is enough to
- * go over.
- */
- key_len = 1;
- val_len = 1;
- } else {
- size_t need_to_cover;
-
- /* How much space key and value should cover? */
- need_to_cover =
- to_go_in_page -
- offsetof(struct max_var_container,
- body) + 1;
- key_len = need_to_cover / 2;
- val_len = need_to_cover - key_len;
- }
- }
- if (setvar(key, key_len, val, val_len) != EC_SUCCESS)
- ccprintf("%s: adding var failed!\n", __func__);
- if (setvar(key, key_len, NULL, 0) != EC_SUCCESS)
- ccprintf("%s: deleting var failed!\n", __func__);
-
- } while (master_at.list_index != (saved_list_index + 1));
-
- lock_mutex(__LINE__);
- rv = compact_nvmem();
- unlock_mutex(__LINE__);
-
- if (rv == EC_SUCCESS)
- rv = new_nvmem_init();
-
- return rv;
-}
-
-/*
- * Function which verifes flash contents integrity (and printing objects it
- * finds, if requested by the caller). All objects' active and deleted alike
- * integrity is verified by get_next_object().
- */
-test_export_static enum ec_error_list browse_flash_contents(int print)
-{
- int active = 0;
- int count = 0;
- int rv = EC_SUCCESS;
- size_t line_len = 0;
- struct nn_container *ch;
- struct access_tracker at = {};
-
- if (!crypto_enabled()) {
- ccprintf("Crypto services not available\n");
- return EC_ERROR_INVAL;
- }
-
- ch = get_scratch_buffer(CONFIG_FLASH_BANK_SIZE);
- lock_mutex(__LINE__);
-
- while ((rv = get_next_object(&at, ch, 1)) == EC_SUCCESS) {
- uint8_t ctype = ch->container_type;
-
- count++;
-
- if ((ctype != NN_OBJ_OLD_COPY) &&
- (ctype != NN_OBJ_TRANSACTION_DEL))
- active++;
-
- if (print) {
- char erased;
-
- if (ctype == NN_OBJ_OLD_COPY)
- erased = 'x';
- else
- erased = ' ';
-
- if (ch->container_type_copy == NN_OBJ_TPM_RESERVED) {
- ccprintf("%cR:%02x.%d ", erased,
- *((uint8_t *)(ch + 1)),
- ch->generation);
- } else {
- uint32_t index;
- char tag;
-
- switch (ch->container_type_copy) {
- case NN_OBJ_TPM_EVICTABLE:
- tag = 'E';
- break;
-
- case NN_OBJ_TUPLE:
- tag = 'T';
- break;
-
- case NN_OBJ_TRANSACTION_DEL:
- tag = 's'; /* 's' for separator. */
- break;
-
- default:
- tag = '?';
- break;
- }
-
- if (ch->container_type_copy !=
- NN_OBJ_TRANSACTION_DEL)
- memcpy(&index, ch + 1, sizeof(index));
- else
- index = 0;
- ccprintf("%c%c:%08x.%d ", erased, tag, index,
- ch->generation);
- }
- if (print > 1) {
- dump_contents(ch);
- continue;
- }
-
- if (line_len > 70) {
- ccprintf("\n");
- cflush();
- line_len = 0;
- } else {
- line_len += 11;
- }
- }
- }
-
- unlock_mutex(__LINE__);
-
- shared_mem_release(ch);
-
- if (rv == EC_ERROR_MEMORY_ALLOCATION) {
- ccprintf("%schecked %d objects, %d active\n", print ? "\n" : "",
- count, active);
- rv = EC_SUCCESS;
- }
-
- return rv;
-}
-
-static int command_dump_nvmem(int argc, char **argv)
-{
- int print = 1;
-
- nvmem_disable_commits();
-
-#ifdef CR50_DEV
- /* Allow dumping ecnrypted NVMEM contents only to DEV builds. */
- print += (argc > 1);
-#endif
- browse_flash_contents(print);
-
- nvmem_enable_commits();
-
- return 0;
-}
-DECLARE_SAFE_CONSOLE_COMMAND(dump_nvmem, command_dump_nvmem, "", "");
diff --git a/common/nvmem.c b/common/nvmem.c
deleted file mode 100644
index 4b4d8fc590..0000000000
--- a/common/nvmem.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/* Copyright 2016 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 "dcrypto.h"
-#include "flash.h"
-#include "nvmem.h"
-#include "new_nvmem.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args)
-#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args)
-
-/*
- * The NVMEM contents are stored in flash memory. At run time there is an SRAM
- * cache and two instances of the contents in the flash in two partitions.
- *
- * Each instance is protected by a 16 bytes hash and has a 'generation' value
- * associated with it. When NVMEM module is initialized it checks the flash
- * stored instances. If both of them are valid, it considers the newer one
- * (younger generation) to be the proper NVMEM contents and copies it to the
- * SRAM cache. If only one instance is valid, it is used, and if no instances
- * are valid - a new valid partition is created and copied into the SRAM
- * cache.
- *
- * When stored in flash, the contents are encrypted, the hash value is used as
- * the IV for the encryption routine.
- *
- * There is a mutex controlling access to the NVMEM. There are two levels
- * of protection - for read only accesses and for write accesses. When the
- * module is initialized the mutex is opened.
- *
- * If there are no pending writes, each read access locks the mutex, reads out
- * the data and unlocks the mutex, thus multiple tasks could be reading NVMEM,
- * blocking access momentarily.
- *
- * If a write access ever occurs things get more complicated. The write access
- * leaves the mutex locked and stores the flag, indicating that the
- * contents have changed and need to be saved, and stores the task id of the
- * task performing the write access.
- *
- * The mutex remains locked in this case. Next time a read access happens,
- * if it comes from the same task, the unlock in the end of the read is
- * bypassed because the 'write in progress' flag is set. If a read or write
- * request comes from another task, they will be blocked until the first
- * task to write commits.
- *
- * nvmem_commit() calls the nvmem_save() function which checks if the cache
- * contents indeed changed (by calculating the hash again). If there is no
- * change - the mutex is released and the function exits. If there is a
- * change, the new generation value is set, the new hash is calculated
- * and the copy is saved in the least recently used flash partition, and
- * then the lock is released.
- */
-
-/* Table of start addresses for each partition */
-static const uintptr_t nvmem_base_addr[NVMEM_NUM_PARTITIONS] = {
- CONFIG_FLASH_NVMEM_BASE_A,
- CONFIG_FLASH_NVMEM_BASE_B
- };
-
-/* NvMem user buffer start offset table */
-static uint32_t nvmem_user_start_offset[NVMEM_NUM_USERS];
-
-/* A/B partion that is most up to date */
-static int nvmem_act_partition;
-
-/* NvMem cache memory structure */
-struct nvmem_mutex_ {
- task_id_t task;
- int write_in_progress;
- struct mutex mtx;
-};
-
-static struct nvmem_mutex_ nvmem_mutex = { .task = TASK_ID_COUNT };
-static uint8_t nvmem_cache[NVMEM_PARTITION_SIZE] __aligned(4);
-
-static uint8_t commits_enabled;
-
-/* NvMem error state */
-static int nvmem_error_state;
-/* Flag to track if an Nv write/move is not completed */
-static int nvmem_write_error;
-
-static void nvmem_release_cache(void);
-
-/*
- * Given the nvmem tag address calculate the sha value of the nvmem buffer and
- * save it in the provided space. The caller is expected to provide enough
- * space to store CIPHER_SALT_SIZE bytes.
- */
-static void nvmem_compute_sha(struct nvmem_tag *tag, void *sha_buf)
-{
- app_compute_hash(tag->padding, NVMEM_PARTITION_SIZE - NVMEM_SHA_SIZE,
- sha_buf, sizeof(tag->sha));
-}
-
-static int nvmem_save(void)
-{
- enum ec_error_list rv;
-
- rv = new_nvmem_save();
-
- if (rv == EC_SUCCESS)
- nvmem_act_partition = NVMEM_NOT_INITIALIZED;
-
- nvmem_mutex.write_in_progress = 0;
- nvmem_release_cache();
- return rv;
-}
-
-/*
- * Read from flash and verify partition.
- *
- * @param index - index of the partition to verify
- *
- * Returns EC_SUCCESS on verification success
- * EC_ERROR_BUSY in case of malloc failure
- * EC_ERROR_UNKNOWN on failure to decrypt of verify.
- */
-static int nvmem_partition_read_verify(int index)
-{
- uint8_t sha_comp[NVMEM_SHA_SIZE];
- struct nvmem_partition *p_part;
- struct nvmem_partition *p_copy;
- int ret;
-
- p_part = (struct nvmem_partition *)nvmem_base_addr[index];
- p_copy = (struct nvmem_partition *)nvmem_cache;
- memcpy(p_copy, p_part, NVMEM_PARTITION_SIZE);
-
- /* Then decrypt it. */
- if (!app_cipher(p_copy->tag.sha, &p_copy->tag + 1,
- &p_copy->tag + 1,
- NVMEM_PARTITION_SIZE - sizeof(struct nvmem_tag))) {
- CPRINTF("%s: decryption failure\n", __func__);
- return EC_ERROR_UNKNOWN;
- }
-
- /*
- * Check if computed value matches stored value. Nonzero 'ret' value
- * means there was a match.
- */
- nvmem_compute_sha(&p_copy->tag, sha_comp);
- ret = !memcmp(p_copy->tag.sha, sha_comp, NVMEM_SHA_SIZE);
-
- return ret ? EC_SUCCESS : EC_ERROR_UNKNOWN;
-}
-
-static void nvmem_lock_cache(void)
-{
- /*
- * Need to protect the cache contents value from other tasks
- * attempting to do nvmem write operations. However, since this
- * function may be called mutliple times prior to the mutex lock being
- * released, there is a check first to see if the current task holds
- * the lock. If it does then the task number will equal the value in
- * cache.task, no need to wait.
- *
- * If the lock is held by a different task then mutex_lock function
- * will operate as normal.
- */
- if (nvmem_mutex.task == task_get_current())
- return;
-
- mutex_lock(&nvmem_mutex.mtx);
- nvmem_mutex.task = task_get_current();
-}
-
-static void nvmem_release_cache(void)
-{
- if (nvmem_mutex.write_in_progress || !commits_enabled)
- return; /* It will have to be saved first. */
-
- /* Reset task number to max value */
- nvmem_mutex.task = TASK_ID_COUNT;
- /* Release mutex lock here */
- mutex_unlock(&nvmem_mutex.mtx);
-}
-
-static int nvmem_compare_generation(void)
-{
- struct nvmem_partition *p_part;
- uint16_t ver0, ver1;
- uint32_t delta;
-
- p_part = (struct nvmem_partition *)nvmem_base_addr[0];
- ver0 = p_part->tag.generation;
- p_part = (struct nvmem_partition *)nvmem_base_addr[1];
- ver1 = p_part->tag.generation;
-
- /* Compute generation difference accounting for wrap condition */
- delta = (ver0 - ver1 + (1<<NVMEM_GENERATION_BITS)) &
- NVMEM_GENERATION_MASK;
- /*
- * If generation number delta is positive in a circular sense then
- * partition 0 has the newest generation number. Otherwise, it's
- * partition 1.
- */
- return delta < (1<<(NVMEM_GENERATION_BITS-1)) ? 0 : 1;
-}
-
-static int nvmem_find_partition(void)
-{
- int n;
- int newest;
-
- /* Don't know which partition to use yet */
- nvmem_act_partition = NVMEM_NOT_INITIALIZED;
-
- /* Find the newest partition available in flash. */
- newest = nvmem_compare_generation();
-
- /*
- * Find a partition with a valid sha, starting with the newest one.
- */
- for (n = 0; n < NVMEM_NUM_PARTITIONS; n++) {
- int check_part = (n + newest) % NVMEM_NUM_PARTITIONS;
-
- if (nvmem_partition_read_verify(check_part) == EC_SUCCESS) {
- nvmem_act_partition = check_part;
- ccprintf("%s:%d found legacy partition %d\n", __func__,
- __LINE__, check_part);
- return EC_SUCCESS;
- }
- }
-
- /*
- * If active_partition is still not selected, then neither partition
- * is valid. Let's reinitialize the NVMEM - there is nothing else we
- * can do.
- */
- CPRINTS("%s: No Legacy Partitions found.", __func__);
- return EC_ERROR_INVALID_CONFIG;
-}
-
-static int nvmem_generate_offset_table(void)
-{
- int n;
- uint32_t start_offset;
-
- /*
- * Create table of starting offsets within partition for each user
- * buffer that's been defined.
- */
- start_offset = sizeof(struct nvmem_tag);
- for (n = 0; n < NVMEM_NUM_USERS; n++) {
- nvmem_user_start_offset[n] = start_offset;
- start_offset += nvmem_user_sizes[n];
- }
- /* Verify that all defined user buffers fit within the partition */
- if (start_offset > NVMEM_PARTITION_SIZE)
- return EC_ERROR_OVERFLOW;
-
- return EC_SUCCESS;
-}
-
-void *nvmem_cache_base(enum nvmem_users user)
-{
- if ((user < 0) || (user >= NVMEM_NUM_USERS))
- return NULL;
-
- return nvmem_cache + nvmem_user_start_offset[user];
-}
-
-static int nvmem_get_partition_off(int user, uint32_t offset, uint32_t len,
- uint32_t *p_buf_offset)
-{
- uint32_t start_offset;
-
- /* Sanity check for user */
- if (user >= NVMEM_NUM_USERS)
- return EC_ERROR_OVERFLOW;
-
- /* Get offset within the partition for the start of user buffer */
- start_offset = nvmem_user_start_offset[user];
- /*
- * Ensure that read/write operation that is calling this function
- * doesn't exceed the end of its buffer.
- */
- if (offset + len > nvmem_user_sizes[user])
- return EC_ERROR_OVERFLOW;
- /* Compute offset within the partition for the rd/wr operation */
- *p_buf_offset = start_offset + offset;
-
- return EC_SUCCESS;
-}
-
-int nvmem_init(void)
-{
- int ret;
-
- /* Generate start offsets within partiion for user buffers */
- ret = nvmem_generate_offset_table();
- if (ret) {
- CPRINTF("%s:%d\n", __func__, __LINE__);
- return ret;
- }
- nvmem_write_error = 0;
-
- /*
- * Default policy is to allow all commits. This ensures reinitialization
- * succeeds to bootstrap the nvmem area.
- */
- commits_enabled = 1;
-
- /*
- * Try discovering legacy partition(s). If even one is present, need
- * to migrate to the new nvmem storage scheme.
- */
- if (nvmem_find_partition() == EC_SUCCESS)
- ret = new_nvmem_migrate(nvmem_act_partition);
- else
- ret = new_nvmem_init();
-
- nvmem_error_state = ret;
-
- if (ret != EC_SUCCESS) {
- CPRINTF("%s:%d error %d!\n", __func__, __LINE__, ret);
- return ret;
- }
-
- return EC_SUCCESS;
-}
-
-int nvmem_get_error_state(void) { return nvmem_error_state; }
-
-int nvmem_is_different(uint32_t offset, uint32_t size, void *data,
- enum nvmem_users user)
-{
- int ret;
- uint32_t src_offset;
-
- nvmem_lock_cache();
-
- /* Get partition offset for this read operation */
- ret = nvmem_get_partition_off(user, offset, size, &src_offset);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* Advance to the correct byte within the data buffer */
-
- /* Compare NvMem with data */
- ret = memcmp(nvmem_cache + src_offset, data, size);
-
- nvmem_release_cache();
-
- return ret;
-}
-
-int nvmem_read(uint32_t offset, uint32_t size,
- void *data, enum nvmem_users user)
-{
- int ret;
- uint32_t src_offset;
-
- nvmem_lock_cache();
-
- /* Get partition offset for this read operation */
- ret = nvmem_get_partition_off(user, offset, size, &src_offset);
-
- if (ret == EC_SUCCESS)
- /* Copy from src into the caller's destination buffer */
- memcpy(data, nvmem_cache + src_offset, size);
-
- nvmem_release_cache();
-
- return ret;
-}
-
-int nvmem_write(uint32_t offset, uint32_t size,
- void *data, enum nvmem_users user)
-{
- int ret;
- uint8_t *p_dest;
- uint32_t dest_offset;
-
- /* Make sure that the cache buffer is active */
- nvmem_lock_cache();
- nvmem_mutex.write_in_progress = 1;
-
- /* Compute partition offset for this write operation */
- ret = nvmem_get_partition_off(user, offset, size, &dest_offset);
- if (ret != EC_SUCCESS) {
- nvmem_write_error = 1;
- return ret;
- }
-
- /* Advance to correct offset within data buffer */
- p_dest = nvmem_cache + dest_offset;
-
- /* Copy data from caller into destination buffer */
- memcpy(p_dest, data, size);
-
- return EC_SUCCESS;
-}
-
-int nvmem_move(uint32_t src_offset, uint32_t dest_offset, uint32_t size,
- enum nvmem_users user)
-{
- int ret;
- uint8_t *p_src, *p_dest;
- uintptr_t base_addr;
- uint32_t s_buff_offset, d_buff_offset;
-
- /* Make sure that the cache buffer is active */
- nvmem_lock_cache();
- nvmem_mutex.write_in_progress = 1;
-
- /* Compute partition offset for source */
- ret = nvmem_get_partition_off(user, src_offset, size, &s_buff_offset);
- if (ret != EC_SUCCESS) {
- nvmem_write_error = 1;
- return ret;
- }
-
- /* Compute partition offset for destination */
- ret = nvmem_get_partition_off(user, dest_offset, size, &d_buff_offset);
- if (ret != EC_SUCCESS) {
- nvmem_write_error = 1;
- return ret;
- }
-
- base_addr = (uintptr_t)nvmem_cache;
- /* Create pointer to src location within partition */
- p_src = (uint8_t *)(base_addr + s_buff_offset);
- /* Create pointer to dest location within partition */
- p_dest = (uint8_t *)(base_addr + d_buff_offset);
- /* Move the data block in NvMem */
- memmove(p_dest, p_src, size);
-
- return EC_SUCCESS;
-}
-
-int nvmem_enable_commits(void)
-{
- if (commits_enabled)
- return EC_SUCCESS;
-
- if (nvmem_mutex.task != task_get_current()) {
- CPRINTF("%s: locked by task %d, attempt to unlock by task %d\n",
- __func__, nvmem_mutex.task, task_get_current());
- return EC_ERROR_INVAL;
- }
-
- commits_enabled = 1;
- CPRINTS("Committing NVMEM changes.");
- return nvmem_commit();
-}
-
-void nvmem_disable_commits(void)
-{
- /* Will be unlocked when nvmem_enable_commits() is called. */
- nvmem_lock_cache();
-
- commits_enabled = 0;
-}
-
-int nvmem_commit(void)
-{
- if (nvmem_mutex.task == TASK_ID_COUNT) {
- CPRINTF("%s: attempt to commit in unlocked state %d\n",
- __func__, nvmem_mutex.task);
- return EC_ERROR_OVERFLOW; /* Noting to commit. */
- }
-
- if (nvmem_mutex.task != task_get_current()) {
- CPRINTF("%s: locked by task %d, attempt to unlock by task %d\n",
- __func__, nvmem_mutex.task, task_get_current());
- return EC_ERROR_INVAL;
- }
-
- /* Ensure that all writes/moves prior to commit call succeeded */
- if (nvmem_write_error) {
- CPRINTS("%s: Write Error, commit abandoned", __func__);
- /* Clear error state */
- nvmem_write_error = 0;
- commits_enabled = 1;
- nvmem_release_cache();
- return EC_ERROR_UNKNOWN;
- }
-
- if (!commits_enabled) {
- CPRINTS("Skipping commit");
- return EC_SUCCESS;
- }
-
- /* Write active partition to NvMem */
- return nvmem_save();
-}
-
-void nvmem_clear_cache(void)
-{
- /* This will work only if key ladder is disabled. */
- if (DCRYPTO_ladder_is_enabled())
- return;
-
- nvmem_lock_cache();
-
- nvmem_wipe_cache();
-
- nvmem_save();
-}
diff --git a/common/nvmem_vars.c b/common/nvmem_vars.c
deleted file mode 100644
index 2b60dbed0c..0000000000
--- a/common/nvmem_vars.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2016 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 "nvmem.h"
-#include "new_nvmem.h"
-#include "printf.h"
-#include "shared_mem.h"
-#include "util.h"
-
-/****************************************************************************/
-/* Pointer to the RAM copy of the persistent variable store */
-
-test_mockable_static uint8_t *rbuf;
-
-int set_local_copy(void)
-{
- if (rbuf)
- return EC_ERROR_UNKNOWN;
-
- rbuf = nvmem_cache_base(NVMEM_CR50);
-
- return EC_SUCCESS;
-}
-
-/****************************************************************************/
-/* Implementation notes
- *
- * The data_ member of struct tuple is simply the key and val blobs
- * concatenated together.
- *
- * We store the variable entries in flash (and RAM) using the struct tuple
- * defined in nvmem_vars.h. The entries are written sequentially with no
- * padding, starting at offset 0 of the CONFIG_FLASH_NVMEM_VARS_USER_NUM user
- * region. A single uint8_t zero byte will ALWAYS follow the valid entries.
- * Since valid entries have nonzero key_len, we can always detect the presence
- * of valid entries.
- *
- * A valid entry has both key_len and val_len between 1 and 255. The following
- * bytes represent these tuples: <"A","ab">, <"B","cde">:
- *
- * Offset Content Meaning
- * 0 0x01 length of key
- * 1 0x02 length of val
- * 2 0x00 variable flags (unused at present)
- * 3 0x41 'A' (key)
- * 4 0x61 'a' (val byte 1)
- * 5 0x62 'b' (val byte 2)
- * 6 0x01 length of key
- * 7 0x03 length of val
- * 8 0x00 variable flags (unused at present)
- * 9 0x42 'B' (key)
- * 10 0x63 'c' (val byte 1)
- * 11 0x64 'd' (val byte 2)
- * 12 0x65 'e' (val byte 3)
- * 13 0x00 End of variables
- *
- * Note that the keys and values are not null-terminated since they're not
- * strings, just binary blobs. The length of each entry is the size of the
- * struct tuple header, plus the length of its key and value blobs.
- *
- * The .flags field is not currently used (and so is set to zero). It could be
- * used in the future to for per-variable attributes, such as read-only,
- * clear-on-reset, extended-length value, etc.
- */
-
-/****************************************************************************/
-/* API functions */
-
-const struct tuple *legacy_getnextvar(const struct tuple *prev_var)
-{
- const struct tuple *var;
- uintptr_t idx;
-
- if (!prev_var) {
- /*
- * The caller is just starting, let's get the first var, if
- * any.
- */
- if (!rbuf[0])
- return NULL;
- return (const struct tuple *)rbuf;
- }
-
- /* Let's try to get the next one. */
- idx = (uintptr_t)prev_var;
- idx += prev_var->key_len + prev_var->val_len + sizeof(struct tuple);
-
- var = (const struct tuple *)idx;
-
- if (var->key_len)
- return var;
-
- return NULL;
-}
-
-const uint8_t *tuple_key(const struct tuple *t) { return t->data_; }
-
-const uint8_t *tuple_val(const struct tuple *t)
-{
- return t->data_ + t->key_len;
-}
-
-/****************************************************************************/
-#if defined(TEST_BUILD) && !defined(TEST_FUZZ)
-#include "console.h"
-
-static void print_blob(const uint8_t *blob, int blob_len)
-{
- int i;
-
- for (i = 0; i < blob_len; i++)
- ccprintf("%c", isprint(blob[i]) ? blob[i] : '.');
-}
-
-static int command_get(int argc, char **argv)
-{
- const struct tuple *tuple;
-
- if (argc != 2)
- return EC_ERROR_PARAM_COUNT;
-
- tuple = getvar(argv[1], strlen(argv[1]));
- if (!tuple)
- return EC_SUCCESS;
-
- print_blob(tuple_val(tuple), tuple->val_len);
- ccprintf("\n");
- return EC_SUCCESS;
-}
-DECLARE_CONSOLE_COMMAND(get, command_get,
- "VARIABLE",
- "Show the value of the specified variable");
-
-static int command_set(int argc, char **argv)
-{
- int rc;
-
- if (argc != 2 && argc != 3)
- return EC_ERROR_PARAM_COUNT;
-
- if (argc == 2)
- rc = setvar(argv[1], strlen(argv[1]), 0, 0);
- else
- rc = setvar(argv[1], strlen(argv[1]), argv[2], strlen(argv[2]));
-
- return rc;
-}
-DECLARE_CONSOLE_COMMAND(set, command_set, "VARIABLE [VALUE]",
- "Set/clear the value of the specified variable");
-
-static int command_print(int argc, char **argv)
-{
- ccprintf("Print all vars is not yet implemented\n");
- return EC_ERROR_INVAL;
-}
-DECLARE_CONSOLE_COMMAND(print, command_print, "",
- "Print all defined variables");
-
-static int command_clear_nvmem_vars(int argc, char **argv)
-{
- ccprintf("Nvmem clear vars has not yet been implemented\n");
- return EC_ERROR_INVAL;
-}
-DECLARE_CONSOLE_COMMAND(clr_nvmem_vars, command_clear_nvmem_vars, "",
- "Clear the NvMem variables.");
-#endif
diff --git a/common/physical_presence.c b/common/physical_presence.c
deleted file mode 100644
index 5fa97e1218..0000000000
--- a/common/physical_presence.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/* 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.
- *
- * Physical presence detect state machine
- */
-
-#include "common.h"
-#include "console.h"
-#include "hooks.h"
-#include "physical_presence.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPRINTS(format, args...) cprints(CC_CCD, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_CCD, format, ## args)
-
-#ifdef CONFIG_PHYSICAL_PRESENCE_DEBUG_UNSAFE
-/* More lenient physical presence for dev builds */
-#define PP_SHORT_PRESS_COUNT 3
-#define PP_SHORT_PRESS_MIN_INTERVAL_US (100 * MSEC)
-#define PP_SHORT_PRESS_MAX_INTERVAL_US (15 * SECOND)
-#define PP_LONG_PRESS_COUNT (PP_SHORT_PRESS_COUNT + 2)
-#define PP_LONG_PRESS_MIN_INTERVAL_US (2 * SECOND)
-#define PP_LONG_PRESS_MAX_INTERVAL_US (300 * SECOND)
-#else
-/* Stricter physical presence for non-dev builds */
-#define PP_SHORT_PRESS_COUNT 5
-#define PP_SHORT_PRESS_MIN_INTERVAL_US (100 * MSEC)
-#define PP_SHORT_PRESS_MAX_INTERVAL_US (5 * SECOND)
-#define PP_LONG_PRESS_COUNT (PP_SHORT_PRESS_COUNT + 4)
-#define PP_LONG_PRESS_MIN_INTERVAL_US (60 * SECOND)
-#define PP_LONG_PRESS_MAX_INTERVAL_US (300 * SECOND)
-#endif
-
-enum pp_detect_state {
- PP_DETECT_IDLE = 0,
- PP_DETECT_AWAITING_PRESS,
- PP_DETECT_BETWEEN_PRESSES,
- PP_DETECT_FINISHING,
- PP_DETECT_ABORT
-};
-
-/* Physical presence state machine data */
-static enum pp_detect_state pp_detect_state;
-static void (*pp_detect_callback)(void);
-static uint8_t pp_press_count;
-static uint8_t pp_press_count_needed;
-static uint64_t pp_last_press; /* Time of last press */
-
-/*
- * We need a mutex because physical_detect_start() and physical_detect_abort()
- * could be called from multiple threads (TPM or console). And either of those
- * could preempt the deferred functions for the state machine which run in the
- * hook task.
- */
-static struct mutex pp_mutex;
-
-static int pp_detect_in_progress(void)
-{
- return ((pp_detect_state == PP_DETECT_AWAITING_PRESS) ||
- (pp_detect_state == PP_DETECT_BETWEEN_PRESSES));
-}
-
-/******************************************************************************/
-/*
- * Deferred functions
- *
- * These are called by the hook task, so can't preempt each other. But they
- * could be preempted by calls to physical_presence_start() or
- * physical_presence_abort().
- */
-
-/**
- * Clean up at end of physical detect sequence.
- */
-static void physical_detect_done(void)
-{
- /*
- * Note that calling physical_detect_abort() from another thread after
- * the start of physical_detect_done() but before mutex_lock() will
- * result in another call to physical_detect_done() being queued up.
- * That's harmless, because we go back to PP_DETECT_IDLE at the end of
- * this call, so the second call will simply drop through without
- * calling pp_detect_callback().
- */
- mutex_lock(&pp_mutex);
-
- if (!pp_detect_in_progress()) {
- CPRINTF("\nPhysical presence check aborted.\n");
- pp_detect_callback = NULL;
- } else if (pp_press_count < pp_press_count_needed) {
- CPRINTF("\nPhysical presence check timeout.\n");
- pp_detect_callback = NULL;
- }
-
- pp_detect_state = PP_DETECT_FINISHING;
- mutex_unlock(&pp_mutex);
-
- /* No longer care about button presses */
- board_physical_presence_enable(0);
-
- /*
- * Call the callback function. Do this outside the mutex, because the
- * callback may take a while. If we kept holding the mutex, then calls
- * to physical_detect_abort() or physical_detect_start() during the
- * callback would block instead of simply failing.
- */
- if (pp_detect_callback) {
- CPRINTS("PP callback");
- pp_detect_callback();
- pp_detect_callback = NULL;
- }
-
- /* Now go to idle */
- mutex_lock(&pp_mutex);
- pp_detect_state = PP_DETECT_IDLE;
- mutex_unlock(&pp_mutex);
-}
-DECLARE_DEFERRED(physical_detect_done);
-
-/**
- * Print a prompt when we've hit the minimum wait time
- */
-static void physical_detect_prompt(void)
-{
- pp_detect_state = PP_DETECT_AWAITING_PRESS;
- CPRINTF("\n\nPress the physical button now!\n\n");
-}
-DECLARE_DEFERRED(physical_detect_prompt);
-
-/**
- * Handle a physical present button press
- *
- * This is implemented as a deferred function so it can use the mutex.
- */
-static void physical_detect_check_press(void)
-{
- uint64_t now = get_time().val;
- uint64_t dt = now - pp_last_press;
-
- mutex_lock(&pp_mutex);
-
- CPRINTS("PP press dt=%.6lld", dt);
-
- /* If we no longer care about presses, ignore them */
- if (!pp_detect_in_progress())
- goto pdpress_exit;
-
- /* Ignore extra presses we don't need */
- if (pp_press_count >= pp_press_count_needed)
- goto pdpress_exit;
-
- /* Ignore presses outside the expected interval */
- if (pp_press_count < PP_SHORT_PRESS_COUNT) {
- if (dt < PP_SHORT_PRESS_MIN_INTERVAL_US) {
- CPRINTS("PP S too soon");
- goto pdpress_exit;
- }
- if (dt > PP_SHORT_PRESS_MAX_INTERVAL_US) {
- CPRINTS("PP S too late");
- goto pdpress_exit;
- }
- } else {
- if (dt < PP_LONG_PRESS_MIN_INTERVAL_US) {
- CPRINTS("PP L too soon");
- goto pdpress_exit;
- }
- if (dt > PP_LONG_PRESS_MAX_INTERVAL_US) {
- CPRINTS("PP L too late");
- goto pdpress_exit;
- }
- }
-
- /* Ok, we need this press */
- CPRINTS("PP press counted!");
- pp_detect_state = PP_DETECT_BETWEEN_PRESSES;
- pp_last_press = now;
- pp_press_count++;
-
- /* Set up call to done handler for timeout or actually done */
- if (pp_press_count == pp_press_count_needed) {
- /* Done, so call right away */
- hook_call_deferred(&physical_detect_done_data, 0);
- } else if (pp_press_count < PP_SHORT_PRESS_COUNT) {
- hook_call_deferred(&physical_detect_prompt_data,
- PP_SHORT_PRESS_MIN_INTERVAL_US);
- hook_call_deferred(&physical_detect_done_data,
- PP_SHORT_PRESS_MAX_INTERVAL_US);
- } else {
- CPRINTF("Another press will be required soon.\n");
- dt = PP_LONG_PRESS_MAX_INTERVAL_US;
- hook_call_deferred(&physical_detect_prompt_data,
- PP_LONG_PRESS_MIN_INTERVAL_US);
- hook_call_deferred(&physical_detect_done_data,
- PP_LONG_PRESS_MAX_INTERVAL_US);
- }
-
-pdpress_exit:
- mutex_unlock(&pp_mutex);
-}
-DECLARE_DEFERRED(physical_detect_check_press);
-
-/******************************************************************************/
-/* Interface */
-
-int physical_detect_start(int is_long, void (*callback)(void))
-{
- mutex_lock(&pp_mutex);
-
- /* Fail if detection is already in progress */
- if (pp_detect_state != PP_DETECT_IDLE) {
- mutex_unlock(&pp_mutex);
- return EC_ERROR_BUSY;
- }
-
- pp_press_count_needed = is_long ? PP_LONG_PRESS_COUNT :
- PP_SHORT_PRESS_COUNT;
- pp_press_count = 0;
- pp_last_press = get_time().val;
- pp_detect_callback = callback;
- pp_detect_state = PP_DETECT_BETWEEN_PRESSES;
- mutex_unlock(&pp_mutex);
-
- /* Start capturing button presses */
- hook_call_deferred(&physical_detect_check_press_data, -1);
- board_physical_presence_enable(1);
-
- CPRINTS("PP start %s", is_long ? "long" : "short");
-
- /* Initial timeout is for a short press */
- hook_call_deferred(&physical_detect_prompt_data,
- PP_SHORT_PRESS_MIN_INTERVAL_US);
- hook_call_deferred(&physical_detect_done_data,
- PP_SHORT_PRESS_MAX_INTERVAL_US);
-
- return EC_SUCCESS;
-}
-
-int physical_detect_busy(void)
-{
- return pp_detect_state != PP_DETECT_IDLE;
-}
-
-void physical_detect_abort(void)
-{
- mutex_lock(&pp_mutex);
- if (pp_detect_in_progress()) {
- CPRINTS("PP abort");
- pp_detect_state = PP_DETECT_ABORT;
- /* Speed up call to done */
- hook_call_deferred(&physical_detect_prompt_data, -1);
- hook_call_deferred(&physical_detect_check_press_data, -1);
- hook_call_deferred(&physical_detect_done_data, 0);
- }
- mutex_unlock(&pp_mutex);
-}
-
-int physical_detect_press(void)
-{
- /* Ignore presses if we're idle */
- if (pp_detect_state == PP_DETECT_IDLE)
- return EC_ERROR_NOT_HANDLED;
-
- /* Call the deferred function to do the work */
- hook_call_deferred(&physical_detect_check_press_data, 0);
- return EC_SUCCESS;
-}
-
-enum pp_fsm_state physical_presense_fsm_state(void)
-{
- switch (pp_detect_state) {
- case PP_DETECT_AWAITING_PRESS:
- return PP_AWAITING_PRESS;
- case PP_DETECT_BETWEEN_PRESSES:
- return PP_BETWEEN_PRESSES;
- default:
- break;
- }
-
- return PP_OTHER;
-}
-
-#ifdef CONFIG_PHYSICAL_PRESENCE_DEBUG_UNSAFE
-
-/**
- * Test callback function
- */
-static void pp_test_callback(void)
-{
- ccprintf("\nPhysical presence good\n");
-}
-
-/**
- * Test physical presence.
- */
-static int command_ppresence(int argc, char **argv)
-{
- /* Print current status */
- ccprintf("PP state: %d, %d/%d, dt=%.6lld\n",
- pp_detect_state, pp_press_count, pp_press_count_needed,
- get_time().val - pp_last_press);
-
- /* With no args, simulate a button press */
- if (argc < 2) {
- physical_detect_press();
- return EC_SUCCESS;
- }
-
- if (!strcasecmp(argv[1], "short")) {
- return physical_detect_start(0, pp_test_callback);
- } else if (!strcasecmp(argv[1], "long")) {
- return physical_detect_start(1, pp_test_callback);
- } else if (!strcasecmp(argv[1], "abort")) {
- physical_detect_abort();
- return EC_SUCCESS;
- } else {
- return EC_ERROR_PARAM1;
- }
-}
-DECLARE_SAFE_CONSOLE_COMMAND(ppresence, command_ppresence,
- "[short | long | abort]",
- "Test physical presence press or sequence");
-
-#endif
diff --git a/common/pinweaver.c b/common/pinweaver.c
deleted file mode 100644
index 2cc4118c7d..0000000000
--- a/common/pinweaver.c
+++ /dev/null
@@ -1,1543 +0,0 @@
-/* Copyright 2018 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 <compile_time_macros.h>
-#include <console.h>
-#include <dcrypto.h>
-#include <extension.h>
-#include <hooks.h>
-#include <nvmem_vars.h>
-#include <pinweaver.h>
-#include <pinweaver_tpm_imports.h>
-#include <pinweaver_types.h>
-#include <timer.h>
-#include <tpm_vendor_cmds.h>
-#include <trng.h>
-#include <tpm_registers.h>
-#include <util.h>
-
-/* Compile time sanity checks. */
-/* Make sure the hash size is consistent with dcrypto. */
-BUILD_ASSERT(PW_HASH_SIZE >= SHA256_DIGEST_SIZE);
-
-/* sizeof(struct leaf_data_t) % 16 should be zero */
-BUILD_ASSERT(sizeof(struct leaf_sensitive_data_t) % PW_WRAP_BLOCK_SIZE == 0);
-
-BUILD_ASSERT(sizeof(((struct merkle_tree_t *)0)->wrap_key) ==
- AES256_BLOCK_CIPHER_KEY_SIZE);
-
-/* Verify that the nvmem_vars log entries have the correct sizes. */
-BUILD_ASSERT(sizeof(struct pw_long_term_storage_t) +
- sizeof(struct pw_log_storage_t) <= PW_MAX_VAR_USAGE);
-
-/* Verify that the request structs will fit into the message. */
-BUILD_ASSERT(PW_MAX_MESSAGE_SIZE >=
- sizeof(struct pw_request_header_t) +
- sizeof(union {struct pw_request_insert_leaf_t insert_leaf;
- struct pw_request_remove_leaf_t remove_leaf;
- struct pw_request_try_auth_t try_auth;
- struct pw_request_reset_auth_t reset_auth;
- struct pw_request_get_log_t get_log;
- struct pw_request_log_replay_t log_replay; }) +
- sizeof(struct leaf_public_data_t) +
- sizeof(struct leaf_sensitive_data_t) +
- PW_MAX_PATH_SIZE);
-
-#define PW_MAX_RESPONSE_SIZE (sizeof(struct pw_response_header_t) + \
- sizeof(union {struct pw_response_insert_leaf_t insert_leaf; \
- struct pw_response_try_auth_t try_auth; \
- struct pw_response_reset_auth_t reset_auth; \
- struct pw_response_log_replay_t log_replay; }) + \
- PW_LEAF_PAYLOAD_SIZE)
-#define PW_VALID_PCR_CRITERIA_SIZE \
- (sizeof(struct valid_pcr_value_t) * PW_MAX_PCR_CRITERIA_COUNT)
-/* Verify that the request structs will fit into the message. */
-BUILD_ASSERT(PW_MAX_MESSAGE_SIZE >= PW_MAX_RESPONSE_SIZE);
-/* Make sure the largest possible message would fit in
- * (struct tpm_register_file).data_fifo.
- */
-BUILD_ASSERT(PW_MAX_MESSAGE_SIZE + sizeof(struct tpm_cmd_header) <= 2048);
-
-/* PW_MAX_PATH_SIZE should not change unless PW_LEAF_MAJOR_VERSION changes too.
- * Update these statements whenever these constants are changed to remind future
- * maintainers about this requirement.
- *
- * This requirement helps guarantee that forward compatibility across the same
- * PW_LEAF_MAJOR_VERSION doesn't break because of a path length becoming too
- * long after new fields are added to struct wrapped_leaf_data_t or its sub
- * fields.
- */
-BUILD_ASSERT(PW_LEAF_MAJOR_VERSION == 0);
-BUILD_ASSERT(PW_MAX_PATH_SIZE == 1024);
-
-/* If fields are appended to struct leaf_sensitive_data_t, an encryption
- * operation should be performed on them reusing the same IV since the prefix
- * won't change.
- *
- * If any data in the original struct leaf_sensitive_data_t changes, a new IV
- * should be generated and stored as part of the log for a replay to be
- * possible.
- */
-BUILD_ASSERT(sizeof(struct leaf_sensitive_data_t) == 3 * PW_SECRET_SIZE);
-
-#define RESTART_TIMER_THRESHOLD (10 * SECOND)
-
-/* This var caches the restart count so the nvram log structure doesn't need to
- * be walked every time try_auth request is made.
- */
-uint32_t pw_restart_count;
-
-/******************************************************************************/
-/* Struct helper functions.
- */
-
-void import_leaf(const struct unimported_leaf_data_t *unimported,
- struct imported_leaf_data_t *imported)
-{
- imported->head = &unimported->head;
- imported->hmac = unimported->hmac;
- imported->iv = unimported->iv;
- imported->pub = (const struct leaf_public_data_t *)unimported->payload;
- imported->cipher_text = unimported->payload + unimported->head.pub_len;
- imported->hashes = (const uint8_t (*)[PW_HASH_SIZE])(
- imported->cipher_text + unimported->head.sec_len);
-}
-
-/******************************************************************************/
-/* Basic operations required by the Merkle tree.
- */
-
-static int derive_keys(struct merkle_tree_t *merkle_tree)
-{
- struct APPKEY_CTX ctx;
- int ret = EC_SUCCESS;
- const uint32_t KEY_TYPE_AES = 0x0;
- const uint32_t KEY_TYPE_HMAC = 0xffffffff;
- union {
- uint32_t v[8];
- uint8_t bytes[sizeof(uint32_t) * 8];
- } input;
- uint32_t type_field;
- size_t seed_size = sizeof(input);
- size_t x;
-
- get_storage_seed(input.v, &seed_size);
- for (x = 0; x < ARRAY_SIZE(input.bytes) &&
- x < ARRAY_SIZE(merkle_tree->key_derivation_nonce); ++x)
- input.bytes[x] ^= merkle_tree->key_derivation_nonce[x];
- type_field = input.v[6];
-
- if (!DCRYPTO_appkey_init(PINWEAVER, &ctx))
- return PW_ERR_CRYPTO_FAILURE;
-
- input.v[6] = type_field ^ KEY_TYPE_AES;
- if (!DCRYPTO_appkey_derive(PINWEAVER, input.v,
- (uint32_t *)merkle_tree->wrap_key)) {
- ret = PW_ERR_CRYPTO_FAILURE;
- goto cleanup;
- }
-
- input.v[6] = type_field ^ KEY_TYPE_HMAC;
- if (!DCRYPTO_appkey_derive(PINWEAVER, input.v,
- (uint32_t *)merkle_tree->hmac_key)) {
- ret = PW_ERR_CRYPTO_FAILURE;
- }
-cleanup:
- DCRYPTO_appkey_finish(&ctx);
- return ret;
-}
-
-/* Creates an empty merkle_tree with the given parameters. */
-static int create_merkle_tree(struct bits_per_level_t bits_per_level,
- struct height_t height,
- struct merkle_tree_t *merkle_tree)
-{
- uint16_t fan_out = 1 << bits_per_level.v;
- uint8_t temp_hash[PW_HASH_SIZE] = {};
- uint8_t hx;
- uint16_t kx;
- LITE_SHA256_CTX ctx;
-
- merkle_tree->bits_per_level = bits_per_level;
- merkle_tree->height = height;
-
- /* Initialize the root hash. */
- for (hx = 0; hx < height.v; ++hx) {
- DCRYPTO_SHA256_init(&ctx, 0);
- for (kx = 0; kx < fan_out; ++kx)
- HASH_update(&ctx, temp_hash, PW_HASH_SIZE);
- memcpy(temp_hash, HASH_final(&ctx), PW_HASH_SIZE);
- }
- memcpy(merkle_tree->root, temp_hash, PW_HASH_SIZE);
-
- rand_bytes(merkle_tree->key_derivation_nonce,
- sizeof(merkle_tree->key_derivation_nonce));
- return derive_keys(merkle_tree);
-}
-
-/* Computes the HMAC for an encrypted leaf using the key in the merkle_tree. */
-static void compute_hmac(
- const struct merkle_tree_t *merkle_tree,
- const struct imported_leaf_data_t *imported_leaf_data,
- uint8_t result[PW_HASH_SIZE])
-{
- LITE_HMAC_CTX hmac;
-
- DCRYPTO_HMAC_SHA256_init(&hmac, merkle_tree->hmac_key,
- sizeof(merkle_tree->hmac_key));
- HASH_update(&hmac.hash, imported_leaf_data->head,
- sizeof(*imported_leaf_data->head));
- HASH_update(&hmac.hash, imported_leaf_data->iv,
- sizeof(PW_WRAP_BLOCK_SIZE));
- HASH_update(&hmac.hash, imported_leaf_data->pub,
- imported_leaf_data->head->pub_len);
- HASH_update(&hmac.hash, imported_leaf_data->cipher_text,
- imported_leaf_data->head->sec_len);
- memcpy(result, DCRYPTO_HMAC_final(&hmac), PW_HASH_SIZE);
-}
-
-/* Computes the root hash for the specified path and child hash. */
-static void compute_root_hash(const struct merkle_tree_t *merkle_tree,
- struct label_t path,
- const uint8_t hashes[][PW_HASH_SIZE],
- const uint8_t child_hash[PW_HASH_SIZE],
- uint8_t new_root[PW_HASH_SIZE])
-{
- /* This is one less than the fan out, the number of sibling hashes. */
- const uint16_t num_aux = (1 << merkle_tree->bits_per_level.v) - 1;
- const uint16_t path_suffix_mask = num_aux;
- uint8_t temp_hash[PW_HASH_SIZE];
- uint8_t hx = 0;
- uint64_t index = path.v;
-
- compute_hash(hashes, num_aux,
- (struct index_t){index & path_suffix_mask},
- child_hash, temp_hash);
- for (hx = 1; hx < merkle_tree->height.v; ++hx) {
- hashes += num_aux;
- index = index >> merkle_tree->bits_per_level.v;
- compute_hash(hashes, num_aux,
- (struct index_t){index & path_suffix_mask},
- temp_hash, temp_hash);
- }
- memcpy(new_root, temp_hash, sizeof(temp_hash));
-}
-
-/* Checks to see the specified path is valid. The length of the path should be
- * validated prior to calling this function.
- *
- * Returns 0 on success or an error code otherwise.
- */
-static int authenticate_path(const struct merkle_tree_t *merkle_tree,
- struct label_t path,
- const uint8_t hashes[][PW_HASH_SIZE],
- const uint8_t child_hash[PW_HASH_SIZE])
-{
- uint8_t parent[PW_HASH_SIZE];
-
- compute_root_hash(merkle_tree, path, hashes, child_hash, parent);
- if (memcmp(parent, merkle_tree->root, sizeof(parent)) != 0)
- return PW_ERR_PATH_AUTH_FAILED;
- return EC_SUCCESS;
-}
-
-static void init_wrapped_leaf_data(
- struct wrapped_leaf_data_t *wrapped_leaf_data)
-{
- wrapped_leaf_data->head.leaf_version.major = PW_LEAF_MAJOR_VERSION;
- wrapped_leaf_data->head.leaf_version.minor = PW_LEAF_MINOR_VERSION;
- wrapped_leaf_data->head.pub_len = sizeof(wrapped_leaf_data->pub);
- wrapped_leaf_data->head.sec_len =
- sizeof(wrapped_leaf_data->cipher_text);
-}
-
-/* Encrypts the leaf meta data. */
-static int encrypt_leaf_data(const struct merkle_tree_t *merkle_tree,
- const struct leaf_data_t *leaf_data,
- struct wrapped_leaf_data_t *wrapped_leaf_data)
-{
- /* Generate a random IV.
- *
- * If fields are appended to struct leaf_sensitive_data_t, an encryption
- * operation should be performed on them reusing the same IV since the
- * prefix won't change.
- *
- * If any data of in the original struct leaf_sensitive_data_t changes,
- * a new IV should be generated and stored as part of the log for a
- * replay to be possible.
- */
- rand_bytes(wrapped_leaf_data->iv, sizeof(wrapped_leaf_data->iv));
- memcpy(&wrapped_leaf_data->pub, &leaf_data->pub,
- sizeof(leaf_data->pub));
- if (!DCRYPTO_aes_ctr(wrapped_leaf_data->cipher_text,
- merkle_tree->wrap_key,
- sizeof(merkle_tree->wrap_key) << 3,
- wrapped_leaf_data->iv, (uint8_t *)&leaf_data->sec,
- sizeof(leaf_data->sec))) {
- return PW_ERR_CRYPTO_FAILURE;
- }
- return EC_SUCCESS;
-}
-
-/* Decrypts the leaf meta data. */
-static int decrypt_leaf_data(
- const struct merkle_tree_t *merkle_tree,
- const struct imported_leaf_data_t *imported_leaf_data,
- struct leaf_data_t *leaf_data)
-{
- memcpy(&leaf_data->pub, imported_leaf_data->pub,
- MIN(imported_leaf_data->head->pub_len,
- sizeof(struct leaf_public_data_t)));
- if (!DCRYPTO_aes_ctr((uint8_t *)&leaf_data->sec, merkle_tree->wrap_key,
- sizeof(merkle_tree->wrap_key) << 3,
- imported_leaf_data->iv,
- imported_leaf_data->cipher_text,
- sizeof(leaf_data->sec))) {
- return PW_ERR_CRYPTO_FAILURE;
- }
- return EC_SUCCESS;
-}
-
-static int handle_leaf_update(
- const struct merkle_tree_t *merkle_tree,
- const struct leaf_data_t *leaf_data,
- const uint8_t hashes[][PW_HASH_SIZE],
- struct wrapped_leaf_data_t *wrapped_leaf_data,
- uint8_t new_root[PW_HASH_SIZE],
- const struct imported_leaf_data_t *optional_old_wrapped_data)
-{
- int ret;
- struct imported_leaf_data_t ptrs;
-
- init_wrapped_leaf_data(wrapped_leaf_data);
- if (optional_old_wrapped_data == NULL) {
- ret = encrypt_leaf_data(merkle_tree, leaf_data,
- wrapped_leaf_data);
- if (ret != EC_SUCCESS)
- return ret;
- } else {
- memcpy(wrapped_leaf_data->iv, optional_old_wrapped_data->iv,
- sizeof(wrapped_leaf_data->iv));
- memcpy(&wrapped_leaf_data->pub, &leaf_data->pub,
- sizeof(leaf_data->pub));
- memcpy(wrapped_leaf_data->cipher_text,
- optional_old_wrapped_data->cipher_text,
- sizeof(wrapped_leaf_data->cipher_text));
- }
-
- import_leaf((const struct unimported_leaf_data_t *)wrapped_leaf_data,
- &ptrs);
- compute_hmac(merkle_tree, &ptrs, wrapped_leaf_data->hmac);
-
- compute_root_hash(merkle_tree, leaf_data->pub.label,
- hashes, wrapped_leaf_data->hmac,
- new_root);
-
- return EC_SUCCESS;
-}
-
-/******************************************************************************/
-/* Parameter and state validation functions.
- */
-
-static int validate_tree_parameters(struct bits_per_level_t bits_per_level,
- struct height_t height)
-{
- uint8_t fan_out = 1 << bits_per_level.v;
-
- if (bits_per_level.v < BITS_PER_LEVEL_MIN ||
- bits_per_level.v > BITS_PER_LEVEL_MAX)
- return PW_ERR_BITS_PER_LEVEL_INVALID;
-
- if (height.v < HEIGHT_MIN ||
- height.v > HEIGHT_MAX(bits_per_level.v) ||
- ((fan_out - 1) * height.v) * PW_HASH_SIZE > PW_MAX_PATH_SIZE)
- return PW_ERR_HEIGHT_INVALID;
-
- return EC_SUCCESS;
-}
-
-/* Verifies that merkle_tree has been initialized. */
-static int validate_tree(const struct merkle_tree_t *merkle_tree)
-{
- if (validate_tree_parameters(merkle_tree->bits_per_level,
- merkle_tree->height) != EC_SUCCESS)
- return PW_ERR_TREE_INVALID;
- return EC_SUCCESS;
-}
-
-/* Checks the following conditions:
- * Extra index fields should be all zero.
- */
-static int validate_label(const struct merkle_tree_t *merkle_tree,
- struct label_t path)
-{
- uint8_t shift_by = merkle_tree->bits_per_level.v *
- merkle_tree->height.v;
-
- if ((path.v >> shift_by) == 0)
- return EC_SUCCESS;
- return PW_ERR_LABEL_INVALID;
-}
-
-/* Checks the following conditions:
- * Columns should be strictly increasing.
- * Zeroes for filler at the end of the delay_schedule are permitted.
- */
-static int validate_delay_schedule(const struct delay_schedule_entry_t
- delay_schedule[PW_SCHED_COUNT])
-{
- size_t x;
-
- /* The first entry should not be useless. */
- if (delay_schedule[0].time_diff.v == 0)
- return PW_ERR_DELAY_SCHEDULE_INVALID;
-
- for (x = PW_SCHED_COUNT - 1; x > 0; --x) {
- if (delay_schedule[x].attempt_count.v == 0) {
- if (delay_schedule[x].time_diff.v != 0)
- return PW_ERR_DELAY_SCHEDULE_INVALID;
- } else if (delay_schedule[x].attempt_count.v <=
- delay_schedule[x - 1].attempt_count.v ||
- delay_schedule[x].time_diff.v <=
- delay_schedule[x - 1].time_diff.v) {
- return PW_ERR_DELAY_SCHEDULE_INVALID;
- }
- }
- return EC_SUCCESS;
-}
-
-static int validate_pcr_value(const struct valid_pcr_value_t
- valid_pcr_criteria[PW_MAX_PCR_CRITERIA_COUNT])
-{
- size_t index;
- uint8_t sha256_of_selected_pcr[SHA256_DIGEST_SIZE];
-
- for (index = 0; index < PW_MAX_PCR_CRITERIA_COUNT; ++index) {
- /* The criteria with bitmask[0] = bitmask[1] = 0 is considered
- * the end of list criteria. If it happens that the first
- * bitmask is zero, we consider that no criteria has to be
- * satisfied and return success in that case.
- */
- if (valid_pcr_criteria[index].bitmask[0] == 0 &&
- valid_pcr_criteria[index].bitmask[1] == 0) {
- if (index == 0)
- return EC_SUCCESS;
-
- return PW_ERR_PCR_NOT_MATCH;
- }
-
- if (get_current_pcr_digest(valid_pcr_criteria[index].bitmask,
- sha256_of_selected_pcr)) {
- cprints(CC_TASK,
- "PinWeaver: Read PCR error, bitmask: %d, %d",
- valid_pcr_criteria[index].bitmask[0],
- valid_pcr_criteria[index].bitmask[1]);
- return PW_ERR_PCR_NOT_MATCH;
- }
-
- /* Check if the curent PCR digest is the same as expected by
- * criteria.
- */
- if (memcmp(sha256_of_selected_pcr,
- valid_pcr_criteria[index].digest,
- SHA256_DIGEST_SIZE) == 0) {
- return EC_SUCCESS;
- }
- }
-
- cprints(CC_TASK, "PinWeaver: No criteria matches PCR values");
- return PW_ERR_PCR_NOT_MATCH;
-}
-
-static int expected_payload_len(int minor_version)
-{
- switch (minor_version) {
- case 0:
- return PW_LEAF_PAYLOAD_SIZE - PW_VALID_PCR_CRITERIA_SIZE;
- case PW_LEAF_MINOR_VERSION:
- return PW_LEAF_PAYLOAD_SIZE;
- default:
- return 0;
- }
-}
-
-static int validate_leaf_header(const struct leaf_header_t *head,
- uint16_t payload_len, uint16_t aux_hash_len)
-{
- uint32_t leaf_payload_len = head->pub_len + head->sec_len;
-
- if (head->leaf_version.major != PW_LEAF_MAJOR_VERSION)
- return PW_ERR_LEAF_VERSION_MISMATCH;
-
- if (head->leaf_version.minor <= PW_LEAF_MINOR_VERSION &&
- leaf_payload_len !=
- expected_payload_len(head->leaf_version.minor)) {
- return PW_ERR_LENGTH_INVALID;
- }
-
- if (payload_len != leaf_payload_len + aux_hash_len * PW_HASH_SIZE)
- return PW_ERR_LENGTH_INVALID;
-
- return EC_SUCCESS;
-}
-
-/* Common validation for requests that include a path to authenticate. */
-static int validate_request_with_path(const struct merkle_tree_t *merkle_tree,
- struct label_t path,
- const uint8_t hashes[][PW_HASH_SIZE],
- const uint8_t hmac[PW_HASH_SIZE])
-{
- int ret;
-
- ret = validate_tree(merkle_tree);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = validate_label(merkle_tree, path);
- if (ret != EC_SUCCESS)
- return ret;
-
- return authenticate_path(merkle_tree, path, hashes, hmac);
-}
-
-/* Common validation for requests that import a leaf. */
-static int validate_request_with_wrapped_leaf(
- const struct merkle_tree_t *merkle_tree,
- uint16_t payload_len,
- const struct unimported_leaf_data_t *unimported_leaf_data,
- struct imported_leaf_data_t *imported_leaf_data,
- struct leaf_data_t *leaf_data)
-{
- int ret;
- uint8_t hmac[PW_HASH_SIZE];
-
- ret = validate_leaf_header(&unimported_leaf_data->head, payload_len,
- get_path_auxiliary_hash_count(merkle_tree));
- if (ret != EC_SUCCESS)
- return ret;
-
- import_leaf(unimported_leaf_data, imported_leaf_data);
- ret = validate_request_with_path(merkle_tree,
- imported_leaf_data->pub->label,
- imported_leaf_data->hashes,
- imported_leaf_data->hmac);
- if (ret != EC_SUCCESS)
- return ret;
-
- compute_hmac(merkle_tree, imported_leaf_data, hmac);
- /* Safe memcmp is used here to prevent an attacker from being able to
- * brute force a valid HMAC for a crafted wrapped_leaf_data.
- * memcmp provides an attacker a timing side-channel they can use to
- * determine how much of a prefix is correct.
- */
- if (safe_memcmp(hmac, unimported_leaf_data->hmac, sizeof(hmac)))
- return PW_ERR_HMAC_AUTH_FAILED;
-
- ret = decrypt_leaf_data(merkle_tree, imported_leaf_data, leaf_data);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* The code below handles version upgrades. */
- if (unimported_leaf_data->head.leaf_version.minor == 0 &&
- unimported_leaf_data->head.leaf_version.major == 0) {
- /* Populate the leaf_data with default pcr value */
- memset(&leaf_data->pub.valid_pcr_criteria, 0,
- PW_VALID_PCR_CRITERIA_SIZE);
- }
-
- return EC_SUCCESS;
-}
-
-/* Sets the value of ts to the current notion of time. */
-static void update_timestamp(struct pw_timestamp_t *ts)
-{
- ts->timer_value = get_time().val / SECOND;
- ts->boot_count = pw_restart_count;
-}
-
-/* Checks if an auth attempt can be made or not based on the delay schedule.
- * EC_SUCCESS is returned when a new attempt can be made otherwise
- * seconds_to_wait will be updated with the remaining wait time required.
- */
-static int test_rate_limit(struct leaf_data_t *leaf_data,
- struct time_diff_t *seconds_to_wait)
-{
- uint64_t ready_time;
- uint8_t x;
- struct pw_timestamp_t current_time;
- struct time_diff_t delay = {0};
-
- /* This loop ends when x is one greater than the index that applies. */
- for (x = 0; x < ARRAY_SIZE(leaf_data->pub.delay_schedule); ++x) {
- /* Stop if a null entry is reached. The first part of the delay
- * schedule has a list of increasing (attempt_count, time_diff)
- * pairs with any unused entries zeroed out at the end.
- */
- if (leaf_data->pub.delay_schedule[x].attempt_count.v == 0)
- break;
-
- /* Stop once a delay schedule entry is reached whose
- * threshold is greater than the current number of
- * attempts.
- */
- if (leaf_data->pub.attempt_count.v <
- leaf_data->pub.delay_schedule[x].attempt_count.v)
- break;
- }
-
- /* If the first threshold was greater than the current number of
- * attempts, there is no delay. Otherwise, grab the delay from the
- * entry prior to the one that was too big.
- */
- if (x > 0)
- delay = leaf_data->pub.delay_schedule[x - 1].time_diff;
-
- if (delay.v == 0)
- return EC_SUCCESS;
-
- if (delay.v == PW_BLOCK_ATTEMPTS) {
- seconds_to_wait->v = PW_BLOCK_ATTEMPTS;
- return PW_ERR_RATE_LIMIT_REACHED;
- }
-
- update_timestamp(&current_time);
-
- if (leaf_data->pub.timestamp.boot_count == current_time.boot_count)
- ready_time = delay.v + leaf_data->pub.timestamp.timer_value;
- else
- ready_time = delay.v;
-
- if (current_time.timer_value >= ready_time)
- return EC_SUCCESS;
-
- seconds_to_wait->v = ready_time - current_time.timer_value;
- return PW_ERR_RATE_LIMIT_REACHED;
-}
-
-/******************************************************************************/
-/* Logging implementation.
- */
-
-/* Once the storage version is incremented, the update code needs to be written
- * to handle differences in the structs.
- *
- * See the two comments "Add storage format updates here." below.
- */
-BUILD_ASSERT(PW_STORAGE_VERSION == 0);
-
-void force_restart_count(uint32_t mock_value)
-{
- pw_restart_count = mock_value;
-}
-
-/* Returns EC_SUCCESS if the root hash was found. Sets *index to the first index
- * of the log entry with a matching root hash, or the index of the last valid
- * entry.
- */
-static int find_relevant_entry(const struct pw_log_storage_t *log,
- const uint8_t root[PW_HASH_SIZE], int *index)
-{
- /* Find the relevant log entry. */
- for (*index = 0; *index < PW_LOG_ENTRY_COUNT; ++*index) {
- if (log->entries[*index].type.v == PW_MT_INVALID)
- break;
- if (memcmp(root, log->entries[*index].root, PW_HASH_SIZE) == 0)
- return EC_SUCCESS;
- }
- --*index;
- return PW_ERR_ROOT_NOT_FOUND;
-}
-
-static int load_log_data(struct pw_log_storage_t *log)
-{
- const struct tuple *ptr;
- const struct pw_log_storage_t *view;
- int rv = EC_SUCCESS;
-
- ptr = getvar(PW_LOG_VAR0, sizeof(PW_LOG_VAR0) - 1);
- if (ptr == NULL)
- return PW_ERR_NV_EMPTY;
-
- view = (void *)tuple_val(ptr);
- if (ptr->val_len != sizeof(struct pw_log_storage_t))
- rv = PW_ERR_NV_LENGTH_MISMATCH;
- else if (view->storage_version != PW_STORAGE_VERSION)
- rv = PW_ERR_NV_VERSION_MISMATCH;
- else
- memcpy(log, view, ptr->val_len);
-
- freevar(ptr);
-
- return rv;
-}
-
-int store_log_data(const struct pw_log_storage_t *log)
-{
- return setvar(PW_LOG_VAR0, sizeof(PW_LOG_VAR0) - 1, (uint8_t *)log,
- sizeof(struct pw_log_storage_t));
-}
-
-static int load_merkle_tree(struct merkle_tree_t *merkle_tree)
-{
- int ret;
- const struct tuple *ptr;
-
- cprints(CC_TASK, "PinWeaver: Loading Tree!");
-
- /* Handle the immutable data. */
- {
- const struct pw_long_term_storage_t *tree;
-
- ptr = getvar(PW_TREE_VAR, sizeof(PW_TREE_VAR) - 1);
- if (!ptr)
- return PW_ERR_NV_EMPTY;
-
- tree = (void *)tuple_val(ptr);
- /* Add storage format updates here. */
- if (ptr->val_len != sizeof(*tree)) {
- freevar(ptr);
- return PW_ERR_NV_LENGTH_MISMATCH;
- }
- if (tree->storage_version != PW_STORAGE_VERSION) {
- freevar(ptr);
- return PW_ERR_NV_VERSION_MISMATCH;
- }
-
- merkle_tree->bits_per_level = tree->bits_per_level;
- merkle_tree->height = tree->height;
- memcpy(merkle_tree->key_derivation_nonce,
- tree->key_derivation_nonce,
- sizeof(tree->key_derivation_nonce));
- ret = derive_keys(merkle_tree);
- freevar(ptr);
- if (ret != EC_SUCCESS)
- return ret;
- }
-
- /* Handle the root hash. */
- {
- struct pw_log_storage_t *log;
-
- ptr = getvar(PW_LOG_VAR0, sizeof(PW_LOG_VAR0) - 1);
- if (!ptr)
- return PW_ERR_NV_EMPTY;
-
- log = (void *)tuple_val(ptr);
- /* Add storage format updates here. */
- if (ptr->val_len != sizeof(struct pw_log_storage_t)) {
- freevar(ptr);
- return PW_ERR_NV_LENGTH_MISMATCH;
- }
- if (log->storage_version != PW_STORAGE_VERSION) {
- freevar(ptr);
- return PW_ERR_NV_VERSION_MISMATCH;
- }
-
- memcpy(merkle_tree->root, log->entries[0].root,
- sizeof(merkle_tree->root));
-
- /* This forces an NVRAM write for hard reboots for which the
- * timer value gets reset. The TPM restart and reset counters
- * were not used because they do not track the state of the
- * counter.
- *
- * Pinweaver uses the restart_count to know when the time since
- * boot can be used as the elapsed time for the delay schedule,
- * versus when the elapsed time starts from a timestamp.
- */
- if (get_time().val < RESTART_TIMER_THRESHOLD) {
- ++log->restart_count;
- ret = setvar(PW_LOG_VAR0, sizeof(PW_LOG_VAR0) - 1,
- (uint8_t *)log,
- sizeof(struct pw_log_storage_t));
- if (ret != EC_SUCCESS) {
- freevar(ptr);
- return ret;
- }
- }
- pw_restart_count = log->restart_count;
- freevar(ptr);
- }
-
- cprints(CC_TASK, "PinWeaver: Loaded Tree. restart_count = %d",
- pw_restart_count);
-
- return EC_SUCCESS;
-}
-
-/* This should only be called when a new tree is created. */
-int store_merkle_tree(const struct merkle_tree_t *merkle_tree)
-{
- int ret;
-
- /* Handle the immutable data. */
- {
- struct pw_long_term_storage_t data;
-
- data.storage_version = PW_STORAGE_VERSION;
- data.bits_per_level = merkle_tree->bits_per_level;
- data.height = merkle_tree->height;
- memcpy(data.key_derivation_nonce,
- merkle_tree->key_derivation_nonce,
- sizeof(data.key_derivation_nonce));
-
- ret = setvar(PW_TREE_VAR, sizeof(PW_TREE_VAR) - 1,
- (uint8_t *)&data, sizeof(data));
- if (ret != EC_SUCCESS)
- return ret;
- }
-
- /* Handle the root hash. */
- {
- struct pw_log_storage_t log = {};
- struct pw_get_log_entry_t *entry = log.entries;
-
- log.storage_version = PW_STORAGE_VERSION;
- entry->type.v = PW_RESET_TREE;
- memcpy(entry->root, merkle_tree->root,
- sizeof(merkle_tree->root));
-
- ret = store_log_data(&log);
- if (ret == EC_SUCCESS)
- pw_restart_count = 0;
- return ret;
- }
-
-}
-
-static int log_roll_for_append(struct pw_log_storage_t *log)
-{
- int ret;
-
- ret = load_log_data(log);
- if (ret != EC_SUCCESS)
- return ret;
-
- memmove(&log->entries[1], &log->entries[0],
- sizeof(log->entries[0]) * (PW_LOG_ENTRY_COUNT - 1));
- memset(&log->entries[0], 0, sizeof(log->entries[0]));
- return EC_SUCCESS;
-}
-
-int log_insert_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE],
- const uint8_t hmac[PW_HASH_SIZE])
-{
- int ret;
- struct pw_log_storage_t log;
- struct pw_get_log_entry_t *entry = log.entries;
-
- ret = log_roll_for_append(&log);
- if (ret != EC_SUCCESS)
- return ret;
-
- entry->type.v = PW_INSERT_LEAF;
- entry->label.v = label.v;
- memcpy(entry->root, root, sizeof(entry->root));
- memcpy(entry->leaf_hmac, hmac, sizeof(entry->leaf_hmac));
-
- return store_log_data(&log);
-}
-
-int log_remove_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE])
-{
- int ret;
- struct pw_log_storage_t log;
- struct pw_get_log_entry_t *entry = log.entries;
-
- ret = log_roll_for_append(&log);
- if (ret != EC_SUCCESS)
- return ret;
-
- entry->type.v = PW_REMOVE_LEAF;
- entry->label.v = label.v;
- memcpy(entry->root, root, sizeof(entry->root));
-
- return store_log_data(&log);
-}
-
-int log_auth(struct label_t label, const uint8_t root[PW_HASH_SIZE], int code,
- struct pw_timestamp_t timestamp)
-{
- int ret;
- struct pw_log_storage_t log;
- struct pw_get_log_entry_t *entry = log.entries;
-
- ret = log_roll_for_append(&log);
- if (ret != EC_SUCCESS)
- return ret;
-
- entry->type.v = PW_TRY_AUTH;
- entry->label.v = label.v;
- memcpy(entry->root, root, sizeof(entry->root));
- entry->return_code = code;
- memcpy(&entry->timestamp, &timestamp, sizeof(entry->timestamp));
-
- return store_log_data(&log);
-}
-
-/******************************************************************************/
-/* Per-request-type handler implementations.
- */
-
-static int pw_handle_reset_tree(struct merkle_tree_t *merkle_tree,
- const struct pw_request_reset_tree_t *request,
- uint16_t req_size)
-{
- struct merkle_tree_t new_tree = {};
- int ret;
-
- if (req_size != sizeof(*request))
- return PW_ERR_LENGTH_INVALID;
-
- ret = validate_tree_parameters(request->bits_per_level,
- request->height);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = create_merkle_tree(request->bits_per_level, request->height,
- &new_tree);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = store_merkle_tree(&new_tree);
- if (ret != EC_SUCCESS)
- return ret;
-
- memcpy(merkle_tree, &new_tree, sizeof(new_tree));
- return EC_SUCCESS;
-}
-
-static int pw_handle_insert_leaf(struct merkle_tree_t *merkle_tree,
- const struct pw_request_insert_leaf_t *request,
- uint16_t req_size,
- struct pw_response_insert_leaf_t *response,
- uint16_t *response_size)
-{
- int ret = EC_SUCCESS;
- struct leaf_data_t leaf_data = {};
- struct wrapped_leaf_data_t wrapped_leaf_data;
- const uint8_t empty_hash[PW_HASH_SIZE] = {};
- uint8_t new_root[PW_HASH_SIZE];
-
- if (req_size != sizeof(*request) +
- get_path_auxiliary_hash_count(merkle_tree) *
- PW_HASH_SIZE)
- return PW_ERR_LENGTH_INVALID;
-
- ret = validate_request_with_path(merkle_tree, request->label,
- request->path_hashes, empty_hash);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = validate_delay_schedule(request->delay_schedule);
- if (ret != EC_SUCCESS)
- return ret;
-
- memset(&leaf_data, 0, sizeof(leaf_data));
- leaf_data.pub.label.v = request->label.v;
- memcpy(&leaf_data.pub.valid_pcr_criteria, request->valid_pcr_criteria,
- sizeof(request->valid_pcr_criteria));
- memcpy(&leaf_data.pub.delay_schedule, &request->delay_schedule,
- sizeof(request->delay_schedule));
- memcpy(&leaf_data.sec.low_entropy_secret, &request->low_entropy_secret,
- sizeof(request->low_entropy_secret));
- memcpy(&leaf_data.sec.high_entropy_secret,
- &request->high_entropy_secret,
- sizeof(request->high_entropy_secret));
- memcpy(&leaf_data.sec.reset_secret, &request->reset_secret,
- sizeof(request->reset_secret));
-
- ret = handle_leaf_update(merkle_tree, &leaf_data, request->path_hashes,
- &wrapped_leaf_data, new_root, NULL);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = log_insert_leaf(request->label, new_root,
- wrapped_leaf_data.hmac);
- if (ret != EC_SUCCESS)
- return ret;
-
- memcpy(merkle_tree->root, new_root, sizeof(new_root));
-
- memcpy(&response->unimported_leaf_data, &wrapped_leaf_data,
- sizeof(wrapped_leaf_data));
-
- *response_size = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
-
- return ret;
-}
-
-static int pw_handle_remove_leaf(struct merkle_tree_t *merkle_tree,
- const struct pw_request_remove_leaf_t *request,
- uint16_t req_size)
-{
- int ret = EC_SUCCESS;
- const uint8_t empty_hash[PW_HASH_SIZE] = {};
- uint8_t new_root[PW_HASH_SIZE];
-
- if (req_size != sizeof(*request) +
- get_path_auxiliary_hash_count(merkle_tree) *
- PW_HASH_SIZE)
- return PW_ERR_LENGTH_INVALID;
-
- ret = validate_request_with_path(merkle_tree, request->leaf_location,
- request->path_hashes,
- request->leaf_hmac);
- if (ret != EC_SUCCESS)
- return ret;
-
- compute_root_hash(merkle_tree, request->leaf_location,
- request->path_hashes, empty_hash, new_root);
-
- ret = log_remove_leaf(request->leaf_location, new_root);
- if (ret != EC_SUCCESS)
- return ret;
-
- memcpy(merkle_tree->root, new_root, sizeof(new_root));
- return ret;
-}
-
-/* Processes a try_auth request.
- *
- * The valid fields in response based on return code are:
- * EC_SUCCESS -> unimported_leaf_data and high_entropy_secret
- * PW_ERR_RATE_LIMIT_REACHED -> seconds_to_wait
- * PW_ERR_LOWENT_AUTH_FAILED -> unimported_leaf_data
- */
-static int pw_handle_try_auth(struct merkle_tree_t *merkle_tree,
- const struct pw_request_try_auth_t *request,
- uint16_t req_size,
- struct pw_response_try_auth_t *response,
- uint16_t *data_length)
-{
- int ret = EC_SUCCESS;
- struct leaf_data_t leaf_data = {};
- struct imported_leaf_data_t imported_leaf_data;
- struct wrapped_leaf_data_t wrapped_leaf_data;
- struct time_diff_t seconds_to_wait;
- uint8_t zeros[PW_SECRET_SIZE] = {};
- uint8_t new_root[PW_HASH_SIZE];
-
- /* These variables help eliminate the possibility of a timing side
- * channel that would allow an attacker to prevent the log write.
- */
- volatile int auth_result;
-
- volatile struct {
- uint32_t attempts;
- int ret;
- uint8_t *secret;
- uint8_t *reset_secret;
- } results_table[2] = {
- { 0, PW_ERR_LOWENT_AUTH_FAILED, zeros, zeros },
- { 0, EC_SUCCESS, leaf_data.sec.high_entropy_secret,
- leaf_data.sec.reset_secret },
- };
-
- if (req_size < sizeof(*request))
- return PW_ERR_LENGTH_INVALID;
-
- ret = validate_request_with_wrapped_leaf(
- merkle_tree, req_size - sizeof(*request),
- &request->unimported_leaf_data, &imported_leaf_data,
- &leaf_data);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* Check if at least one PCR criteria is satisfied if the leaf is
- * bound to PCR.
- */
- ret = validate_pcr_value(leaf_data.pub.valid_pcr_criteria);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = test_rate_limit(&leaf_data, &seconds_to_wait);
- if (ret != EC_SUCCESS) {
- *data_length = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
- memset(response, 0, *data_length);
- memcpy(&response->seconds_to_wait, &seconds_to_wait,
- sizeof(seconds_to_wait));
- return ret;
- }
-
- update_timestamp(&leaf_data.pub.timestamp);
-
- /* Precompute the failed attempts. */
- results_table[0].attempts = leaf_data.pub.attempt_count.v;
- if (results_table[0].attempts != UINT32_MAX)
- ++results_table[0].attempts;
-
- /**********************************************************************/
- /* After this:
- * 1) results_table should not be changed;
- * 2) the runtime of the code paths for failed and successful
- * authentication attempts should not diverge.
- */
- auth_result = safe_memcmp(request->low_entropy_secret,
- leaf_data.sec.low_entropy_secret,
- sizeof(request->low_entropy_secret)) == 0;
- leaf_data.pub.attempt_count.v = results_table[auth_result].attempts;
-
- /* This has a non-constant time path, but it doesn't convey information
- * about whether a PW_ERR_LOWENT_AUTH_FAILED happened or not.
- */
- ret = handle_leaf_update(merkle_tree, &leaf_data,
- imported_leaf_data.hashes, &wrapped_leaf_data,
- new_root, &imported_leaf_data);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = log_auth(wrapped_leaf_data.pub.label, new_root,
- results_table[auth_result].ret, leaf_data.pub.timestamp);
- if (ret != EC_SUCCESS) {
- memcpy(new_root, merkle_tree->root, sizeof(merkle_tree->root));
- return ret;
- }
- /**********************************************************************/
- /* At this point the log should be written so it should be safe for the
- * runtime of the code paths to diverge.
- */
-
- memcpy(merkle_tree->root, new_root, sizeof(new_root));
-
- *data_length = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
- memset(response, 0, *data_length);
-
- memcpy(&response->unimported_leaf_data, &wrapped_leaf_data,
- sizeof(wrapped_leaf_data));
-
- memcpy(&response->high_entropy_secret,
- results_table[auth_result].secret,
- sizeof(response->high_entropy_secret));
-
- memcpy(&response->reset_secret,
- results_table[auth_result].reset_secret,
- sizeof(response->reset_secret));
-
- return results_table[auth_result].ret;
-}
-
-static int pw_handle_reset_auth(struct merkle_tree_t *merkle_tree,
- const struct pw_request_reset_auth_t *request,
- uint16_t req_size,
- struct pw_response_reset_auth_t *response,
- uint16_t *response_size)
-{
- int ret = EC_SUCCESS;
- struct leaf_data_t leaf_data = {};
- struct imported_leaf_data_t imported_leaf_data;
- struct wrapped_leaf_data_t wrapped_leaf_data;
- uint8_t new_root[PW_HASH_SIZE];
-
- if (req_size < sizeof(*request))
- return PW_ERR_LENGTH_INVALID;
-
- ret = validate_request_with_wrapped_leaf(
- merkle_tree, req_size - sizeof(*request),
- &request->unimported_leaf_data, &imported_leaf_data,
- &leaf_data);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* Safe memcmp is used here to prevent an attacker from being able to
- * brute force the reset secret and use it to unlock the leaf.
- * memcmp provides an attacker a timing side-channel they can use to
- * determine how much of a prefix is correct.
- */
- if (safe_memcmp(request->reset_secret,
- leaf_data.sec.reset_secret,
- sizeof(request->reset_secret)) != 0)
- return PW_ERR_RESET_AUTH_FAILED;
-
- leaf_data.pub.attempt_count.v = 0;
-
- ret = handle_leaf_update(merkle_tree, &leaf_data,
- imported_leaf_data.hashes, &wrapped_leaf_data,
- new_root, &imported_leaf_data);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = log_auth(leaf_data.pub.label, new_root, ret,
- leaf_data.pub.timestamp);
- if (ret != EC_SUCCESS)
- return ret;
-
- memcpy(merkle_tree->root, new_root, sizeof(new_root));
-
- memcpy(&response->unimported_leaf_data, &wrapped_leaf_data,
- sizeof(wrapped_leaf_data));
-
- memcpy(response->high_entropy_secret,
- leaf_data.sec.high_entropy_secret,
- sizeof(response->high_entropy_secret));
-
- *response_size = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
-
- return ret;
-}
-
-static int pw_handle_get_log(const struct merkle_tree_t *merkle_tree,
- const struct pw_request_get_log_t *request,
- uint16_t req_size,
- struct pw_get_log_entry_t response[],
- uint16_t *response_size)
-{
- int ret;
- int x;
- struct pw_log_storage_t log;
-
- if (req_size != sizeof(*request))
- return PW_ERR_LENGTH_INVALID;
-
- ret = validate_tree(merkle_tree);
- if (ret != EC_SUCCESS)
- return ret;
-
- ret = load_log_data(&log);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* Find the relevant log entry. The return value isn't used because if
- * the entry isn't found the entire log is returned. This makes it
- * easier to recover when the log is too short.
- *
- * Here is an example:
- * 50 attempts have been made against a leaf that becomes out of sync
- * because of a disk flush failing. The copy of the leaf on disk is
- * behind by 50 and the log contains less than 50 entries. The CrOS
- * implementation can check the public parameters of the local copy with
- * the log entry to determine that leaf is out of sync. It can then send
- * any valid copy of that leaf with a log replay request that will only
- * succeed if the HMAC of the resulting leaf matches the log entry.
- */
- find_relevant_entry(&log, request->root, &x);
- /* If there are no valid entries, return. */
- if (x < 0)
- return EC_SUCCESS;
-
- /* Copy the entries in reverse order. */
- while (1) {
- memcpy(&response[x], &log.entries[x], sizeof(log.entries[x]));
- *response_size += sizeof(log.entries[x]);
- if (x == 0)
- break;
- --x;
- }
-
- return EC_SUCCESS;
-}
-
-static int pw_handle_log_replay(const struct merkle_tree_t *merkle_tree,
- const struct pw_request_log_replay_t *request,
- uint16_t req_size,
- struct pw_response_log_replay_t *response,
- uint16_t *response_size)
-{
- int ret;
- int x;
- struct pw_log_storage_t log;
- struct leaf_data_t leaf_data = {};
- struct imported_leaf_data_t imported_leaf_data;
- struct wrapped_leaf_data_t wrapped_leaf_data;
- uint8_t hmac[PW_HASH_SIZE];
- uint8_t root[PW_HASH_SIZE];
-
- if (req_size < sizeof(*request))
- return PW_ERR_LENGTH_INVALID;
-
- ret = validate_tree(merkle_tree);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* validate_request_with_wrapped_leaf() isn't used here because the
- * path validation is delayed to allow any valid copy of the same leaf
- * to be used in the replay operation as long as the result passes path
- * validation.
- */
- ret = validate_leaf_header(&request->unimported_leaf_data.head,
- req_size - sizeof(*request),
- get_path_auxiliary_hash_count(merkle_tree));
- if (ret != EC_SUCCESS)
- return ret;
-
- import_leaf(&request->unimported_leaf_data, &imported_leaf_data);
-
- ret = load_log_data(&log);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* Find the relevant log entry. */
- ret = find_relevant_entry(&log, request->log_root, &x);
- if (ret != EC_SUCCESS)
- return ret;
-
- /* The other message types don't need to be handled by Cr50. */
- if (log.entries[x].type.v != PW_TRY_AUTH)
- return PW_ERR_TYPE_INVALID;
-
- compute_hmac(merkle_tree, &imported_leaf_data, hmac);
- if (safe_memcmp(hmac, request->unimported_leaf_data.hmac, sizeof(hmac)))
- return PW_ERR_HMAC_AUTH_FAILED;
-
- ret = decrypt_leaf_data(merkle_tree, &imported_leaf_data, &leaf_data);
- if (ret != EC_SUCCESS)
- return ret;
-
- if (leaf_data.pub.label.v != log.entries[x].label.v)
- return PW_ERR_LABEL_INVALID;
-
- /* Update the metadata to match the log. */
- if (log.entries[x].return_code == EC_SUCCESS)
- leaf_data.pub.attempt_count.v = 0;
- else
- ++leaf_data.pub.attempt_count.v;
- memcpy(&leaf_data.pub.timestamp, &log.entries[x].timestamp,
- sizeof(leaf_data.pub.timestamp));
-
- ret = handle_leaf_update(merkle_tree, &leaf_data,
- imported_leaf_data.hashes, &wrapped_leaf_data,
- root, &imported_leaf_data);
- if (ret != EC_SUCCESS)
- return ret;
-
- if (memcmp(root, log.entries[x].root, PW_HASH_SIZE))
- return PW_ERR_PATH_AUTH_FAILED;
-
- memcpy(&response->unimported_leaf_data, &wrapped_leaf_data,
- sizeof(wrapped_leaf_data));
-
- *response_size = sizeof(*response) + PW_LEAF_PAYLOAD_SIZE;
-
- return EC_SUCCESS;
-}
-
-struct merkle_tree_t pw_merkle_tree;
-
-/*
- * Handle the VENDOR_CC_PINWEAVER command.
- */
-static enum vendor_cmd_rc pw_vendor_specific_command(enum vendor_cmd_cc code,
- void *buf,
- size_t input_size,
- size_t *response_size)
-{
- struct pw_request_t *request = buf;
- struct pw_response_t *response = buf;
-
- if (input_size < sizeof(request->header)) {
- ccprintf("PinWeaver: message smaller than a header (%zd).\n",
- input_size);
- return VENDOR_RC_INTERNAL_ERROR;
- }
-
- if (input_size != request->header.data_length +
- sizeof(request->header)) {
- ccprintf("PinWeaver: header size mismatch %zd != %zd.\n",
- input_size, request->header.data_length +
- sizeof(request->header));
- return VENDOR_RC_REQUEST_TOO_BIG;
- }
-
- /* The response_size is validated by compile time checks. */
-
- /* The return value of this function call is intentionally unused. */
- pw_handle_request(&pw_merkle_tree, request, response);
-
- *response_size = response->header.data_length +
- sizeof(response->header);
-
- /* The response is only sent for EC_SUCCESS so it is used even for
- * errors which are reported through header.return_code.
- */
- return VENDOR_RC_SUCCESS;
-}
-DECLARE_VENDOR_COMMAND(VENDOR_CC_PINWEAVER,
- pw_vendor_specific_command);
-
-/******************************************************************************/
-/* Non-static functions.
- */
-
-void pinweaver_init(void)
-{
- load_merkle_tree(&pw_merkle_tree);
-}
-
-int get_path_auxiliary_hash_count(const struct merkle_tree_t *merkle_tree)
-{
- return ((1 << merkle_tree->bits_per_level.v) - 1) *
- merkle_tree->height.v;
-}
-
-/* Computes the SHA256 parent hash of a set of child hashes given num_hashes
- * sibling hashes in hashes[] and the index of child_hash.
- *
- * Assumptions:
- * num_hashes == fan_out - 1
- * ARRAY_SIZE(hashes) == num_hashes
- * 0 <= location <= num_hashes
- */
-void compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes,
- struct index_t location,
- const uint8_t child_hash[PW_HASH_SIZE],
- uint8_t result[PW_HASH_SIZE])
-{
- LITE_SHA256_CTX ctx;
-
- DCRYPTO_SHA256_init(&ctx, 0);
- if (location.v > 0)
- HASH_update(&ctx, hashes[0], PW_HASH_SIZE * location.v);
- HASH_update(&ctx, child_hash, PW_HASH_SIZE);
- if (location.v < num_hashes)
- HASH_update(&ctx, hashes[location.v],
- PW_HASH_SIZE * (num_hashes - location.v));
- memcpy(result, HASH_final(&ctx), PW_HASH_SIZE);
-}
-
-/* If a request from older protocol comes, this method should make it
- * compatible with the current request structure.
- */
-int make_compatible_request(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- switch (request->header.version) {
- case 0:
- /* The switch from protocol version 0 to 1 means all the
- * requests have the same format, except insert_leaf.
- * Update the request in that case.
- */
- if (request->header.type.v == PW_INSERT_LEAF) {
- unsigned char *src = (unsigned char *)
- (&request->data.insert_leaf00.path_hashes);
- unsigned char *dest = (unsigned char *)
- (&request->data.insert_leaf.path_hashes);
- const int hash_count =
- get_path_auxiliary_hash_count(merkle_tree);
- const uint16_t hashes_size = hash_count * PW_HASH_SIZE;
-
- memmove(dest, src, hashes_size);
- memset(&request->data.insert_leaf.valid_pcr_criteria,
- 0, PW_VALID_PCR_CRITERIA_SIZE);
- request->header.data_length +=
- PW_VALID_PCR_CRITERIA_SIZE;
- }
- /* Fallthrough to make compatible from next version */
- case PW_PROTOCOL_VERSION:
- return 1;
- }
- /* Unsupported version. */
- return 0;
-}
-
-/* Converts the response to be understandable by an older protocol.
- */
-void make_compatible_response(int version, int req_type,
- struct pw_response_t *response)
-{
- if (version >= PW_PROTOCOL_VERSION)
- return;
-
- response->header.version = version;
- if (version == 0) {
- if (req_type == PW_TRY_AUTH) {
- unsigned char *src = (unsigned char *)
- (&response->data.try_auth.unimported_leaf_data);
- unsigned char *dest = (unsigned char *)
- (&response->data.try_auth00.unimported_leaf_data);
- memmove(dest, src,
- PW_LEAF_PAYLOAD_SIZE +
- sizeof(struct unimported_leaf_data_t));
- response->header.data_length -= PW_SECRET_SIZE;
- }
- }
-}
-
-/* Handles the message in request using the context in merkle_tree and writes
- * the results to response. The return value captures any error conditions that
- * occurred or EC_SUCCESS if there were no errors.
- *
- * This implementation is written to handle the case where request and response
- * exist at the same memory location---are backed by the same buffer. This means
- * the implementation requires that no reads are made to request after response
- * has been written to.
- */
-int pw_handle_request(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request,
- struct pw_response_t *response)
-{
- int32_t ret;
- uint16_t resp_length;
- /* Store the message type of the request since it may be overwritten
- * inside the switch whenever response and request overlap in memory.
- */
- struct pw_message_type_t type = request->header.type;
- int version = request->header.version;
-
- resp_length = 0;
-
- if (!make_compatible_request(merkle_tree, request)) {
- ret = PW_ERR_VERSION_MISMATCH;
- goto cleanup;
- }
- switch (type.v) {
- case PW_RESET_TREE:
- ret = pw_handle_reset_tree(merkle_tree,
- &request->data.reset_tree,
- request->header.data_length);
- break;
- case PW_INSERT_LEAF:
- ret = pw_handle_insert_leaf(merkle_tree,
- &request->data.insert_leaf,
- request->header.data_length,
- &response->data.insert_leaf,
- &resp_length);
- break;
- case PW_REMOVE_LEAF:
- ret = pw_handle_remove_leaf(merkle_tree,
- &request->data.remove_leaf,
- request->header.data_length);
- break;
- case PW_TRY_AUTH:
- ret = pw_handle_try_auth(merkle_tree, &request->data.try_auth,
- request->header.data_length,
- &response->data.try_auth,
- &resp_length);
- break;
- case PW_RESET_AUTH:
- ret = pw_handle_reset_auth(merkle_tree,
- &request->data.reset_auth,
- request->header.data_length,
- &response->data.reset_auth,
- &resp_length);
- break;
- case PW_GET_LOG:
- ret = pw_handle_get_log(merkle_tree, &request->data.get_log,
- request->header.data_length,
- (void *)&response->data, &resp_length);
- break;
- case PW_LOG_REPLAY:
- ret = pw_handle_log_replay(merkle_tree,
- &request->data.log_replay,
- request->header.data_length,
- &response->data.log_replay,
- &resp_length);
- break;
- default:
- ret = PW_ERR_TYPE_INVALID;
- break;
- }
-cleanup:
- response->header.version = PW_PROTOCOL_VERSION;
- response->header.data_length = resp_length;
- response->header.result_code = ret;
- memcpy(&response->header.root, merkle_tree->root,
- sizeof(merkle_tree->root));
-
- make_compatible_response(version, type.v, response);
-
- return ret;
-};
diff --git a/common/tpm_registers.c b/common/tpm_registers.c
deleted file mode 100644
index cd1afcd244..0000000000
--- a/common/tpm_registers.c
+++ /dev/null
@@ -1,1096 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/*
- * This implements the register interface for the TPM SPI Hardware Protocol.
- * The master puts or gets between 1 and 64 bytes to a register designated by a
- * 24-bit address. There is no provision for error reporting at this level.
- */
-
-#include "byteorder.h"
-#include "console.h"
-#include "extension.h"
-#include "link_defs.h"
-#include "new_nvmem.h"
-#include "printf.h"
-#include "signed_header.h"
-#include "sps.h"
-#include "system.h"
-#include "system_chip.h"
-#include "task.h"
-#include "tpm_manufacture.h"
-#include "tpm_registers.h"
-#include "util.h"
-#include "watchdog.h"
-#include "wp.h"
-
-/*
- * Do not enable TPM if crypto test is enabled - there is no room in the flash
- * for both.
- */
-#ifndef CRYPTO_TEST_SETUP
-#define ENABLE_TPM
-
-/* TPM2 library includes. */
-#include "ExecCommand_fp.h"
-#include "Platform.h"
-#include "_TPM_Init_fp.h"
-#include "Manufacture_fp.h"
-
-#endif
-
-/****************************************************************************/
-/*
- * CAUTION: Variables defined in this in this file are treated specially.
- *
- * As always, initialized variables are placed in the .data section, and
- * uninitialized variables in the .bss section. This saves space in the
- * executable, because the loader can just zero .bss prior to running the
- * program.
- *
- * In addition to that, the tpm_reset_request() function will zero the .bss of
- * all modules of the TPM library and variables of this file explicitly added
- * to the .bss.Tpm2_common section, which will allow restarting TPM without
- * rebooting the device.
- *
- * On the other hand, initialized variables (in the .data section) are NOT
- * affected by tpm_reset_request(), so any variables that should be
- * reinitialized must be dealt with manually in the tpm_reset_request()
- * function. To prevent initialized variables from being added to the TPM
- * library without notice, the linker will reject any that aren't explicitly
- * flagged.
- */
-
-/* This marks uninitialized variables that tpm_reset_request() should ignore */
-#define __preserved __attribute__((section(".bss.noreinit")))
-
-/*
- * This marks initialized variables that tpm_reset_request() may need to reset
- */
-#define __initialized __attribute__((section(".data.noreinit")))
-
-/****************************************************************************/
-
-#define CPRINTS(format, args...) cprints(CC_TPM, format, ## args)
-#define CPRINTF(format, args...) cprintf(CC_TPM, format, ## args)
-
-/* Register addresses for FIFO mode. */
-#define TPM_ACCESS (0)
-#define TPM_INTF_CAPABILITY (0x14)
-#define TPM_STS (0x18)
-#define TPM_DATA_FIFO (0x24)
-#define TPM_INTERFACE_ID (0x30)
-#define TPM_DID_VID (0xf00)
-#define TPM_RID (0xf04)
-#define TPM_FW_VER (0xf90)
-
-#define GOOGLE_VID 0x1ae0
-#define GOOGLE_DID 0x0028
-#define CR50_RID 0 /* No revision ID yet */
-
-static __preserved uint8_t reset_in_progress;
-
-/* Tpm state machine states. */
-enum tpm_states {
- tpm_state_idle,
- tpm_state_ready,
- tpm_state_receiving_cmd,
- tpm_state_executing_cmd,
- tpm_state_completing_cmd,
-};
-
-/* A preliminary interface capability register value, will be fine tuned. */
-#define IF_CAPABILITY_REG ((3 << 28) | /* TPM2.0 (interface 1.3) */ \
- (3 << 9) | /* up to 64 bytes transfers. */ \
- 0x15) /* Mandatory set to one. */
-
-/* Volatile registers for FIFO mode */
-struct tpm_register_file {
- uint8_t access;
- uint32_t sts;
- uint8_t data_fifo[2048]; /* this might have to be even deeper. */
-};
-
-/*
- * Tpm representation. This is a file scope variable, only one locality is
- * supported.
- */
-static struct {
- enum tpm_states state;
- uint32_t fifo_read_index; /* for read commands */
- uint32_t fifo_write_index; /* for write commands */
- struct tpm_register_file regs;
-} tpm_ __attribute__((section(".bss.Tpm2_common")));
-
-/* Bit definitions for some TPM registers. */
-enum tpm_access_bits {
- tpm_reg_valid_sts = BIT(7),
- active_locality = BIT(5),
- request_use = BIT(1),
- tpm_establishment = BIT(0),
-};
-
-enum tpm_sts_bits {
- tpm_family_shift = 26,
- tpm_family_mask = (BIT(2) - 1), /* 2 bits wide */
- tpm_family_tpm2 = 1,
- reset_establishment_bit = BIT(25),
- command_cancel = BIT(24),
- burst_count_shift = 8,
- burst_count_mask = (BIT(16) - 1), /* 16 bits wide */
- sts_valid = BIT(7),
- command_ready = BIT(6),
- tpm_go = BIT(5),
- data_avail = BIT(4),
- expect = BIT(3),
- self_test_done = BIT(2),
- response_retry = BIT(1),
-};
-
-/* Used to count bytes read in version string */
-static int tpm_fw_ver_index __attribute__((section(".bss.Tpm2_common")));
-/*
- * Used to store the full version string, which includes version of the two RO
- * and two RW regions in the flash as well as the version string of the four
- * cr50 image components. The number is somewhat arbitrary, calculated for the
- * worst case scenario when all compontent trees are 'dirty'.
- */
-static uint8_t tpm_fw_ver[80] __attribute__((section(".bss.Tpm2_common")));
-
-/*
- * We need to be able to report firmware version to the host, both RO and RW
- * sections. This copies the information into a static string so that it can be
- * passed to the host a little bit at a time.
- */
-static void set_version_string(void)
-{
- enum ec_image active_ro, active_rw;
- size_t offset;
-
- active_ro = system_get_ro_image_copy();
- active_rw = system_get_image_copy();
-
- snprintf(tpm_fw_ver, sizeof(tpm_fw_ver), "%s:%d RO_%c:%s",
- system_get_chip_revision(),
- system_get_board_version(),
- (active_ro == EC_IMAGE_RO ? 'A' : 'B'),
- system_get_version(active_ro));
- offset = strlen(tpm_fw_ver);
- if (offset == sizeof(tpm_fw_ver) - 1)
- return;
-
- snprintf(tpm_fw_ver + offset,
- sizeof(tpm_fw_ver) - offset, " RW_%c:%s",
- (active_rw == EC_IMAGE_RW ? 'A' : 'B'),
- system_get_version(active_rw));
-}
-
-static void set_tpm_state(enum tpm_states state)
-{
- CPRINTF("state transition from %d to %d\n", tpm_.state, state);
- tpm_.state = state;
-
- if (state == tpm_state_idle) {
- /* Make sure FIFO is empty. */
- tpm_.fifo_read_index = 0;
- tpm_.fifo_write_index = 0;
- /*
- * Set proper fields of the status register: FIFO depth 63,
- * not ready, no data available.
- */
- tpm_.regs.sts &= ~((burst_count_mask << burst_count_shift) |
- command_ready | data_avail);
- tpm_.regs.sts |= 63 << burst_count_shift;
- }
-}
-
-/*
- * Some TPM registers allow writing of only exactly one bit. This helper
- * function allows to verify that a value is compliant with this
- * requirement
- */
-static int single_bit_set(uint32_t value)
-{
- return value && !(value & (value - 1));
-}
-
-/*
- * NOTE: The put/get functions are called in interrupt context! Don't waste a
- * lot of time here - just copy the data and wake up a task to deal with it
- * later. Although if the implementation mandates a "busy" bit somewhere, you
- * might want to set it now to avoid race conditions with back-to-back
- * interrupts.
- */
-
-static void copy_bytes(uint8_t *dest, uint32_t data_size, uint32_t value)
-{
- unsigned i;
-
- data_size = MIN(data_size, 4);
-
- for (i = 0; i < data_size; i++)
- dest[i] = (value >> (i * 8)) & 0xff;
-}
-
-static void access_reg_write(uint8_t data)
-{
- if (!single_bit_set(data)) {
- CPRINTF("%s: attempt to set acces reg to %02x\n",
- __func__, data);
- return;
- }
-
- switch (data) {
- case request_use:
- /*
- * No multiple localities supported, let's just always honor
- * this request.
- */
- tpm_.regs.access |= active_locality;
- break;
-
- case active_locality:
- switch (tpm_.state) {
- case tpm_state_ready:
- case tpm_state_idle:
- break;
- default:
- /*
- * TODO: need to decide what to do if there is a
- * command in progress.
- */
- CPRINTF("%s: locality release request in state %d\n",
- __func__, tpm_.state);
- break;
- }
- tpm_.regs.access &= ~active_locality;
- /* No matter what we do, fall into idle state. */
- set_tpm_state(tpm_state_idle);
- break;
-
- default:
- CPRINTF("%s: attempt to set access reg to an unsupported value"
- " of 0x%02x\n", __func__, data);
- break;
- }
-}
-
-/*
- * Process writes into the 'important' sts register bits. Actions on all
- * depends on the current state of the device.
- */
-static void sts_reg_write_cr(void)
-{
- switch (tpm_.state) {
- case tpm_state_idle:
- set_tpm_state(tpm_state_ready);
- tpm_.regs.sts |= command_ready;
- break;
- case tpm_state_ready:
- tpm_.regs.sts |= command_ready;
- break;
- case tpm_state_completing_cmd:
- case tpm_state_executing_cmd:
- case tpm_state_receiving_cmd:
- set_tpm_state(tpm_state_idle);
- break;
- }
-}
-
-static void sts_reg_write_tg(void)
-{
- switch (tpm_.state) {
- case tpm_state_completing_cmd:
- case tpm_state_executing_cmd:
- case tpm_state_idle:
- case tpm_state_ready:
- break; /* Ignore setting this bit in these states. */
- case tpm_state_receiving_cmd:
- if (!(tpm_.state & expect)) {
- /* This should trigger actual command execution. */
- set_tpm_state(tpm_state_executing_cmd);
- task_set_event(TASK_ID_TPM, TASK_EVENT_WAKE, 0);
- }
- break;
- }
-}
-
-static void sts_reg_write_rr(void)
-{
- switch (tpm_.state) {
- case tpm_state_idle:
- case tpm_state_ready:
- case tpm_state_receiving_cmd:
- case tpm_state_executing_cmd:
- break;
- case tpm_state_completing_cmd:
- tpm_.fifo_read_index = 0;
- break;
- }
-}
-
-/*
- * TPM_STS register both reports current state machine state and controls some
- * of state machine transitions.
- */
-static void sts_reg_write(const uint8_t *data, uint32_t data_size)
-{
- uint32_t value = 0;
-
- data_size = MIN(data_size, 4);
- memcpy(&value, data, data_size);
-
- /* By definition only one bit can be set at a time. */
- if (!single_bit_set(value)) {
- CPRINTF("%s: attempt to set status reg to %02x\n",
- __func__, value);
- return;
- }
-
- switch (value) {
- case command_ready:
- sts_reg_write_cr();
- break;
- case tpm_go:
- sts_reg_write_tg();
- break;
- case response_retry:
- sts_reg_write_rr();
- break;
- case command_cancel:
- /* TODO: this also needs to be handled, fall through for now. */
- default:
- CPRINTF("requested to write %08x to sts\n", value);
- break;
- }
-}
-
-/* Collect received data in the local buffer and change state accordingly. */
-static void fifo_reg_write(const uint8_t *data, uint32_t data_size)
-{
- uint32_t packet_size;
- struct tpm_cmd_header *tpmh;
-
- /*
- * Make sure we are in the appropriate state, otherwise ignore this
- * access.
- */
- if ((tpm_.state == tpm_state_ready) && (tpm_.fifo_write_index == 0))
- set_tpm_state(tpm_state_receiving_cmd);
-
- if (tpm_.state != tpm_state_receiving_cmd) {
- CPRINTF("%s: ignoring data in state %d\n",
- __func__, tpm_.state);
- return;
- }
-
- if ((tpm_.fifo_write_index + data_size) > sizeof(tpm_.regs.data_fifo)) {
- CPRINTF("%s: receive buffer overflow: %d in addition to %d\n",
- __func__, data_size, tpm_.fifo_write_index);
- tpm_.fifo_write_index = 0;
- set_tpm_state(tpm_state_ready);
- return;
- }
-
- /* Copy data into the local buffer. */
- memcpy(tpm_.regs.data_fifo + tpm_.fifo_write_index,
- data, data_size);
-
- tpm_.fifo_write_index += data_size;
-
- /* Verify that size in the header matches the block size */
- if (tpm_.fifo_write_index < 6) {
- tpm_.regs.sts |= expect; /* More data is needed. */
- return;
- }
-
- tpmh = (struct tpm_cmd_header *)tpm_.regs.data_fifo;
- packet_size = be32toh(tpmh->size);
- if (tpm_.fifo_write_index < packet_size) {
- tpm_.regs.sts |= expect; /* More data is needed. */
- return;
- }
-
- /* All data has been received, Ready for the 'go' command. */
- tpm_.regs.sts &= ~expect;
-}
-
-/* TODO: data_size is between 1 and 64, but is not trustworthy! Don't write
- * past the end of any actual registers if data_size is larger than the spec
- * allows. */
-void tpm_register_put(uint32_t regaddr, const uint8_t *data, uint32_t data_size)
-{
- uint32_t i;
-
- CPRINTF("%s(0x%03x, %d,", __func__, regaddr, data_size);
- for (i = 0; i < data_size && i < 4; i++)
- CPRINTF(" %02x", data[i]);
- if (data_size > 4)
- CPRINTF(" ...");
- CPRINTF(")\n");
-
- switch (regaddr) {
- case TPM_ACCESS:
- /* This is a one byte register, ignore extra data, if any */
- access_reg_write(data[0]);
- break;
- case TPM_STS:
- sts_reg_write(data, data_size);
- break;
- case TPM_DATA_FIFO:
- fifo_reg_write(data, data_size);
- break;
- case TPM_FW_VER:
- /* Reset read byte count */
- tpm_fw_ver_index = 0;
- break;
- default:
- CPRINTF("%s(0x%06x, %d bytes:", __func__, regaddr, data_size);
- for (i = 0; i < data_size; i++)
- CPRINTF(", %02x", data[i]);
- CPRINTF("\n");
- return;
- }
-
-}
-
-static void fifo_reg_read(uint8_t *dest, uint32_t data_size)
-{
- uint32_t still_in_fifo = tpm_.fifo_write_index -
- tpm_.fifo_read_index;
- uint32_t tpm_sts;
-
- data_size = MIN(data_size, still_in_fifo);
- memcpy(dest,
- tpm_.regs.data_fifo + tpm_.fifo_read_index,
- data_size);
-
- tpm_.fifo_read_index += data_size;
-
- tpm_sts = tpm_.regs.sts;
- tpm_sts &= ~(burst_count_mask << burst_count_shift);
- if (tpm_.fifo_write_index == tpm_.fifo_read_index) {
- tpm_sts &= ~(data_avail | command_ready);
- /* Burst size for the following write requests. */
- tpm_sts |= 63 << burst_count_shift;
- } else {
- /*
- * Tell the master how much there is to read in the next
- * burst.
- */
- tpm_sts |= MIN(tpm_.fifo_write_index -
- tpm_.fifo_read_index, 63) << burst_count_shift;
- }
-
- tpm_.regs.sts = tpm_sts;
-}
-
-
-/* TODO: data_size is between 1 and 64, but is not trustworthy! We must return
- * that many bytes, but not leak any secrets if data_size is larger than
- * it should be. Return 0x00 or 0xff or whatever the spec says instead. */
-void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size)
-{
- int i;
-
- reset_in_progress = 0;
-
- CPRINTF("%s(0x%06x, %d)", __func__, regaddr, data_size);
- switch (regaddr) {
- case TPM_DID_VID:
- copy_bytes(dest, data_size, (GOOGLE_DID << 16) | GOOGLE_VID);
- break;
- case TPM_RID:
- copy_bytes(dest, data_size, CR50_RID);
- break;
- case TPM_INTF_CAPABILITY:
- copy_bytes(dest, data_size, IF_CAPABILITY_REG);
- break;
- case TPM_ACCESS:
- copy_bytes(dest, data_size, tpm_.regs.access);
- break;
- case TPM_STS:
- CPRINTF(" %x", tpm_.regs.sts);
- copy_bytes(dest, data_size, tpm_.regs.sts);
- break;
- case TPM_DATA_FIFO:
- fifo_reg_read(dest, data_size);
- break;
- case TPM_FW_VER:
- for (i = 0; i < data_size; i++) {
- /*
- * Only read while the index remains less than the
- * maximum allowed version string size.
- */
- if (tpm_fw_ver_index < sizeof(tpm_fw_ver)) {
- *dest++ = tpm_fw_ver[tpm_fw_ver_index];
- /*
- * If reached end of string, then don't update
- * the index so that it will keep pointing at
- * the end of string character and continue to
- * fill *dest with 0s.
- */
- if (tpm_fw_ver[tpm_fw_ver_index] != '\0')
- tpm_fw_ver_index++;
- } else
- /* Not in a valid state, just stuff 0s */
- *dest++ = 0;
- }
- break;
- default:
- CPRINTS("%s(0x%06x, %d) => ??", __func__, regaddr, data_size);
- return;
- }
- CPRINTF("\n");
-}
-
-static __preserved interface_control_func if_start;
-static __preserved interface_control_func if_stop;
-void tpm_register_interface(interface_control_func interface_start,
- interface_control_func interface_stop)
-{
- if_start = interface_start;
- if_stop = interface_stop;
-}
-
-static void tpm_init(void)
-{
-#ifdef ENABLE_TPM
- /*
- * 0xc0 Means successful endorsement. Actual endorsement reasult code
- * is added in lower bits to indicate endorsement failure, if any.
- */
- uint8_t underrun_char = 0xc0;
-#endif
- /* This is more related to TPM task activity than TPM transactions */
- cprints(CC_TASK, "%s", __func__);
-
- if (system_rolling_reboot_suspected()) {
- cprints(CC_TASK, "%s interrupted", __func__);
- return;
- }
-
- set_tpm_state(tpm_state_idle);
- tpm_.regs.access = tpm_reg_valid_sts;
- /*
- * I2CS writes must limit the burstsize to 63 for fifo writes to work
- * properly. For I2CS fifo writes the first byte is the I2C TPM address
- * and the next up to 62 bytes are the data to write to that register.
- */
- tpm_.regs.sts = (tpm_family_tpm2 << tpm_family_shift) |
- (63 << burst_count_shift) | sts_valid;
-
- /* Create version string to be read by host */
- set_version_string();
-
-#ifdef ENABLE_TPM
- /* TPM2 library functions. */
- _plat__Signal_PowerOn();
-
- watchdog_reload();
-
- /*
- * Make sure NV RAM metadata is initialized, needed to check
- * manufactured status. This is a speculative call which will have to
- * be repeated in case the TPM has not been through the manufacturing
- * sequence yet.
- *
- * No harm in calling it twice in that case.
- */
- _TPM_Init();
-
- if (!tpm_manufactured()) {
- enum manufacturing_status endorse_result;
-
- /*
- * If tpm has not been manufactured yet - this needs to run on
- * every startup. It will wipe out NV RAM, among other things.
- */
- TPM_Manufacture(1);
- _TPM_Init();
- _plat__SetNvAvail();
- endorse_result = tpm_endorse();
-
- ccprints("Endorsement %s",
- (endorse_result == mnf_success) ?
- "succeeded" : "failed");
-
- if (chip_factory_mode()) {
- underrun_char |= endorse_result;
-
- ccprints("Setting underrun character to 0x%x",
- underrun_char);
- sps_tx_status(underrun_char);
- }
- } else {
- if (chip_factory_mode())
- sps_tx_status(underrun_char | mnf_manufactured);
-
- _plat__SetNvAvail();
- }
-#endif
-}
-
-size_t tpm_get_burst_size(void)
-{
- return (tpm_.regs.sts >> burst_count_shift) & burst_count_mask;
-}
-
-#ifdef CONFIG_EXTENSION_COMMAND
-
-/* Recognize both original extension and new vendor-specific command codes */
-#define IS_CUSTOM_CODE(code) \
- ((code == CONFIG_EXTENSION_COMMAND) || \
- (code == TPM_CC_VENDOR_BIT_MASK))
-
-static void call_extension_command(struct tpm_cmd_header *tpmh,
- size_t *total_size,
- uint32_t flags)
-{
- size_t command_size = be32toh(tpmh->size);
- uint32_t rc;
-
- /*
- * Note that we don't look for TPM_CC_VENDOR_CR50 anywhere. All
- * vendor-specific commands are handled the same way for now.
- */
-
- /* Verify there is room for at least the extension command header. */
- if (command_size >= sizeof(struct tpm_cmd_header)) {
- struct vendor_cmd_params p = {
- .code = be16toh(tpmh->subcommand_code),
- /* The header takes room in the buffer. */
- .buffer = tpmh + 1,
- .in_size = command_size - sizeof(struct tpm_cmd_header),
- .out_size = *total_size - sizeof(struct tpm_cmd_header),
- .flags = flags
- };
-
- rc = extension_route_command(&p);
-
- /* Add the header size back. */
- *total_size = p.out_size + sizeof(struct tpm_cmd_header);
- tpmh->size = htobe32(*total_size);
-
- /* Flag errors from commands as vendor-specific */
- if (rc)
- rc |= VENDOR_RC_ERR;
- tpmh->command_code = htobe32(rc);
- } else {
- *total_size = command_size;
- }
-}
-#endif
-
-/*
- * Events used on the TPM task context. Make sure there is no collision with
- * event(s) defined in chip/g/dcrypto/dcrypto_runtime.c
- */
-#define TPM_EVENT_RESET TASK_EVENT_CUSTOM_BIT(1)
-#define TPM_EVENT_COMMIT TASK_EVENT_CUSTOM_BIT(2)
-#define TPM_EVENT_ALT_EXTENSION TASK_EVENT_CUSTOM_BIT(3)
-
-/*
- * Result of executing of the TPM command on the alternative path, could have
- * been interrupted by a reset.
- */
-enum alt_process_result {
- ALT_PROCESS_WAITING,
- ALT_PROCESS_DONE,
- ALT_PROCESS_INTERRUPTED
-};
-
-/*
- * This structure stores the context of the alternative TPM command execution
- * path.
- *
- * The command and response share the buffer, when TPM task finishes
- * processing the command it sets the 'process_result' field to a non-zero
- * value.
- *
- * The mutex ensures that only one alternative TPM command execution is active
- * at a time.
- */
-static __preserved struct alt_tpm_interface {
- struct tpm_cmd_header *alt_hdr;
- size_t alt_buffer_size;
- uint32_t process_result;
- struct mutex if_mutex;
-} alt_if;
-
-void tpm_alt_extension(struct tpm_cmd_header *command, size_t buffer_size)
-{
- mutex_lock(&alt_if.if_mutex);
- memset(&alt_if, 0, sizeof(alt_if));
-
- alt_if.alt_hdr = command;
- alt_if.alt_buffer_size = buffer_size;
-
- do {
- alt_if.process_result = ALT_PROCESS_WAITING;
-
- task_set_event(TASK_ID_TPM, TPM_EVENT_ALT_EXTENSION, 0);
-
- /*
- * This is not very elegant, but simple and acceptable for
- * this TPM command execution path, as in most cases it would
- * be drven by a human operator.
- *
- * Use REG32 to make sure that the field is treated as
- * volatile.
- */
- while (REG32(&alt_if.process_result) == ALT_PROCESS_WAITING)
- msleep(10);
-
- /*
- * Repeat the request if command execution was interrupted by
- * a TPM reset.
- */
- } while (REG32(&alt_if.process_result) != ALT_PROCESS_DONE);
-
- mutex_unlock(&alt_if.if_mutex);
-}
-
-/* Calling task (singular) to notify when the TPM reset has completed */
-static __initialized task_id_t waiting_for_reset = TASK_ID_INVALID;
-
-/* Return value from blocking tpm_reset_request() call */
-static __preserved int wipe_result;
-
-/*
- * Did tpm_reset_request() request nvmem wipe? (intentionally cleared on reset)
- */
-static int wipe_requested __attribute__((section(".bss.Tpm2_common")));
-
-int tpm_reset_request(int wait_until_done, int wipe_nvmem_first)
-{
- uint32_t evt;
-
- cprints(CC_TASK, "%s(%d, %d)", __func__,
- wait_until_done, wipe_nvmem_first);
-
- if (reset_in_progress) {
- cprints(CC_TASK, "%s: already scheduled", __func__);
- return EC_ERROR_BUSY;
- }
-
- reset_in_progress = 1;
- wipe_result = EC_SUCCESS;
-
- /* We can't change our minds about wiping. */
- wipe_requested |= wipe_nvmem_first;
-
- if (wait_until_done)
- /*
- * Completion could take a while, if other things have
- * higher priority.
- */
- waiting_for_reset = task_get_current();
-
- /* Ask the TPM task to reset itself */
- task_set_event(TASK_ID_TPM, TPM_EVENT_RESET, 0);
-
- if (!wait_until_done)
- return EC_SUCCESS;
-
- if (in_interrupt_context() ||
- task_get_current() == TASK_ID_TPM) {
- waiting_for_reset = TASK_ID_INVALID;
- return EC_ERROR_BUSY; /* Can't sleep. Clown'll eat me. */
- }
-
- evt = task_wait_event_mask(TPM_EVENT_RESET, 5 * SECOND);
-
- /* We were notified of completion */
- if (evt & TPM_EVENT_RESET)
- return wipe_result;
-
- /* Timeout is bad */
- return EC_ERROR_TIMEOUT;
-}
-
-/*
- * A timeout hook to reinstate NVMEM commits soon after reset.
- *
- * The TPM task disables nvmem commits during TPM reset, they need to be
- * reinstated on the same task context. This is why an event is raised here to
- * wake up the TPM task and force it to reinstate nvmem commits instead of
- * doing it here directly.
- */
-static void reinstate_nvmem_commits(void)
-{
- tpm_reinstate_nvmem_commits();
-}
-DECLARE_DEFERRED(reinstate_nvmem_commits);
-
-void tpm_reinstate_nvmem_commits(void)
-{
- task_set_event(TASK_ID_TPM, TPM_EVENT_COMMIT, 0);
-}
-
-static void tpm_reset_now(int wipe_first)
-{
- /* TPM is not running in factory mode. */
- if (!chip_factory_mode())
- if_stop();
-
- /* This is more related to TPM task activity than TPM transactions */
- cprints(CC_TASK, "%s(%d)", __func__, wipe_first);
-
- if (wipe_first)
- /* Now wipe the TPM's nvmem */
- wipe_result = nvmem_erase_tpm_data();
- else
- wipe_result = EC_SUCCESS;
-
- /*
- * NOTE: If any __initialized variables need reinitializing after
- * reset, this is the place to do it.
- */
-
- /*
- * If TPM was reset while commits were disabled, save whatever changes
- * might have accumulated.
- */
- nvmem_enable_commits();
-
- /*
- * Clear the TPM library's zero-init data. Note that the linker script
- * includes this file's .bss in the same section, so it will be cleared
- * at the same time.
- */
- memset(&__bss_libtpm2_start, 0,
- (uintptr_t)(&__bss_libtpm2_end) -
- (uintptr_t)(&__bss_libtpm2_start));
-
- /*
- * Prevent NVRAM commits until further notice, unless running in
- * factory mode.
- */
- if (!chip_factory_mode())
- nvmem_disable_commits();
-
- /* Re-initialize our registers */
- tpm_init();
-
- if (waiting_for_reset != TASK_ID_INVALID) {
- /* Wake the waiting task, if any */
- task_set_event(waiting_for_reset, TPM_EVENT_RESET, 0);
- waiting_for_reset = TASK_ID_INVALID;
- }
-
- cprints(CC_TASK, "%s: done", __func__);
-
- /*
- * The host might decide to do it sooner, but let's make sure commits
- * do not stay disabled for more than 3 seconds.
- */
- hook_call_deferred(&reinstate_nvmem_commits_data, 3 * SECOND);
-
- /*
- * In chip factory mode SPI idle byte sent on MISO is used for
- * progress reporting. TPM flow control messes it up, do not start TPM
- * in factory mode.
- */
- if (!chip_factory_mode())
- if_start();
-}
-
-int tpm_sync_reset(int wipe_first)
-{
- tpm_reset_now(wipe_first);
-
- return wipe_result;
-}
-
-void tpm_stop(void)
-{
- /* Stop the TPM interface if it has been initialized. */
- if (if_stop)
- if_stop();
-}
-
-void tpm_task(void *u)
-{
- uint32_t evt = 0;
-
- if (!chip_factory_mode()) {
- /*
- * Just in case there is a resume from deep sleep where AP is
- * not out of reset, let's not proceed until AP is actually
- * up. No need to worry about the AP state in chip factory
- * mode of course.
- */
- while (!ap_is_on()) {
- /*
- * The only events we should expect at this point
- * would be the reset request or a command routed
- * through TPM task context to make use of the large
- * stack.
- */
- evt = task_wait_event(-1);
- if (evt & (TPM_EVENT_RESET | TPM_EVENT_ALT_EXTENSION)) {
- /*
- * No need to remember the reset request: tpm
- * reset will happen as soon as we break out
- * from this while loop,
- */
- evt &= TPM_EVENT_ALT_EXTENSION;
- break;
- }
-
- cprints(CC_TASK, "%s:%d unexpected event %x",
- __func__, __LINE__, evt);
- }
- }
-
- tpm_reset_now(0);
- while (1) {
- uint8_t *response = NULL;
- unsigned response_size;
- uint32_t command_code;
- struct tpm_cmd_header *tpmh;
- size_t buffer_size;
- uint8_t alt_if_command;
-
- /* Process unprocessed events or wait for the next event */
- if (!evt)
- evt = task_wait_event(-1);
-
- if (evt & TPM_EVENT_RESET) {
- tpm_reset_now(wipe_requested);
- if (evt & TPM_EVENT_ALT_EXTENSION) {
- /*
- * Need to tell the waiting task that
- * processing was interrupted.
- */
- alt_if.process_result = ALT_PROCESS_INTERRUPTED;
- }
- /*
- * There is no point in looking at other events in
- * this situation: the nvram will be committed by TPM
- * reset; other tpm commands would be ignored.
- *
- * Let's just continue. This could change if there are
- * other events added to the set.
- */
- evt = 0;
- continue;
- }
-
- if (evt & TPM_EVENT_COMMIT) {
- evt &= ~TPM_EVENT_COMMIT;
- nvmem_enable_commits();
- }
-
- if (evt & TASK_EVENT_WAKE) {
- evt &= ~TASK_EVENT_WAKE;
- tpmh = (struct tpm_cmd_header *)tpm_.regs.data_fifo;
- buffer_size = sizeof(tpm_.regs.data_fifo);
- alt_if_command = 0;
- } else if (evt & TPM_EVENT_ALT_EXTENSION) {
- evt &= ~TPM_EVENT_ALT_EXTENSION;
- tpmh = alt_if.alt_hdr;
- buffer_size = alt_if.alt_buffer_size;
- alt_if_command = 1;
- } else {
- if (evt) {
- cprints(CC_TASK, "%s:%d unexpected event %x",
- __func__, __LINE__, evt);
- evt = 0;
- }
- continue;
- }
-
- command_code = be32toh(tpmh->command_code);
- CPRINTF("%s: received fifo command 0x%04x\n",
- __func__, command_code);
-
- watchdog_reload();
-
-#ifdef CONFIG_EXTENSION_COMMAND
- if (IS_CUSTOM_CODE(command_code)) {
- response_size = buffer_size;
- call_extension_command(tpmh, &response_size,
- alt_if_command ?
- VENDOR_CMD_FROM_USB : 0);
- } else
-#endif
- {
- if (board_id_is_mismatched()) {
- static const char tpm_broken_response[] = {
- 0x80, 0x01, /* TPM_ST_NO_SESSIONS */
- 0, 0, 0, 10, /* Response size. */
- 0, 0, 9, 0x21 /* TPM_RC_LOCKOUT */
- };
- CPRINTF("%s: Ignoring TPM commands\n",
- __func__);
- response = (uint8_t *)tpmh;
- response_size = sizeof(tpm_broken_response);
- memcpy(response, tpm_broken_response,
- response_size);
- } else {
-#ifdef ENABLE_TPM
- ExecuteCommand(tpm_.fifo_write_index,
- (uint8_t *)tpmh,
- &response_size,
- &response);
-#else
- {
- /*
- * This response is sent by actual
- * TPM2 when replying to gibberish
- * input. Copy it here to avoid the
- * need to add conditional compilation
- * cases below.
- */
- const uint8_t bad_cmd_resp[] = {
- 0x00, 0xc4, 0x00, 0x00, 0x00,
- 0x0a, 0x00, 0x00, 0x00, 0x1e
- };
- response = (uint8_t *)tpmh;
- response_size = sizeof(bad_cmd_resp);
- memcpy(response, bad_cmd_resp,
- response_size);
- }
-#endif
- }
- }
- CPRINTF("got %d bytes in response\n", response_size);
- if (response_size &&
- (response_size <= buffer_size)) {
- uint32_t tpm_sts;
- /*
- * TODO(vbendeb): revisit this when
- * crosbug.com/p/55667 has been addressed.
- */
- if (command_code == TPM2_PCR_Read)
- system_process_retry_counter();
-#ifdef CONFIG_EXTENSION_COMMAND
- if (!IS_CUSTOM_CODE(command_code))
-#endif
- {
- /*
- * Extension commands reuse FIFO buffer, the
- * rest need to copy.
- */
- memcpy(tpmh, response, response_size);
- }
- if (alt_if_command) {
- alt_if.process_result = ALT_PROCESS_DONE;
- /* No need to manage TPM registers. */
- continue;
- }
- tpm_.fifo_read_index = 0;
- tpm_.fifo_write_index = response_size;
- set_tpm_state(tpm_state_completing_cmd);
- tpm_sts = tpm_.regs.sts;
- tpm_sts &= ~(burst_count_mask << burst_count_shift);
- tpm_sts |= (MIN(response_size, 63) << burst_count_shift)
- | data_avail;
- tpm_.regs.sts = tpm_sts;
- }
- }
-}
diff --git a/common/u2f.c b/common/u2f.c
deleted file mode 100644
index 8cef638d3a..0000000000
--- a/common/u2f.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/* 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.
- */
-
-/* APDU dispatcher and U2F command handlers. */
-
-#include "console.h"
-#include "cryptoc/p256.h"
-#include "cryptoc/sha256.h"
-#include "dcrypto.h"
-#include "extension.h"
-#include "system.h"
-#include "u2f_impl.h"
-#include "u2f.h"
-#include "util.h"
-
-#define G2F_CERT_NAME "CrOS"
-
-#define CPRINTF(format, args...) cprintf(CC_EXTENSION, format, ##args)
-
-/* Crypto parameters */
-#define AES_BLOCK_LEN 16
-#define KH_LEN 64
-
-/* De-interleave 64 bytes into two 32 arrays. */
-static void deinterleave64(const uint8_t *in, uint8_t *a, uint8_t *b)
-{
- size_t i;
-
- for (i = 0; i < 32; ++i) {
- a[i] = in[2 * i + 0];
- b[i] = in[2 * i + 1];
- }
-}
-
-/* (un)wrap w/ the origin dependent KEK. */
-static int wrap_kh(const uint8_t *origin, const uint8_t *in,
- uint8_t *out, enum encrypt_mode mode)
-{
- uint8_t kek[SHA256_DIGEST_SIZE];
- uint8_t iv[AES_BLOCK_LEN] = {0};
- int i;
-
- /* KEK derivation */
- if (u2f_gen_kek(origin, kek, sizeof(kek)))
- return EC_ERROR_UNKNOWN;
-
- DCRYPTO_aes_init(kek, 256, iv, CIPHER_MODE_CBC, mode);
-
- for (i = 0; i < 4; i++)
- DCRYPTO_aes_block(in + i * AES_BLOCK_LEN,
- out + i * AES_BLOCK_LEN);
-
- return EC_SUCCESS;
-}
-
-static int individual_cert(const p256_int *d, const p256_int *pk_x,
- const p256_int *pk_y, uint8_t *cert, const int n)
-{
- p256_int *serial;
-
- if (system_get_chip_unique_id((uint8_t **)&serial) != P256_NBYTES)
- return 0;
-
- return DCRYPTO_x509_gen_u2f_cert_name(d, pk_x, pk_y, serial,
- G2F_CERT_NAME, cert, n);
-}
-
-int g2f_attestation_cert(uint8_t *buf)
-{
- p256_int d, pk_x, pk_y;
-
- if (g2f_individual_keypair(&d, &pk_x, &pk_y))
- return 0;
-
- /* Note that max length is not currently respected here. */
- return individual_cert(&d, &pk_x, &pk_y,
- buf, G2F_ATTESTATION_CERT_MAX_LEN);
-}
-
-/* U2F GENERATE command */
-static enum vendor_cmd_rc u2f_generate(enum vendor_cmd_cc code,
- void *buf,
- size_t input_size,
- size_t *response_size)
-{
- U2F_GENERATE_REQ *req = buf;
- U2F_GENERATE_RESP *resp;
-
- /* Origin keypair */
- uint8_t od_seed[P256_NBYTES];
- p256_int od, opk_x, opk_y;
-
- /* Key handle */
- uint8_t kh[U2F_FIXED_KH_SIZE];
-
- /* Whether keypair generation succeeded */
- int generate_keypair_rc;
-
- size_t response_buf_size = *response_size;
-
- *response_size = 0;
-
- if (input_size != sizeof(U2F_GENERATE_REQ) ||
- response_buf_size < sizeof(U2F_GENERATE_RESP))
- return VENDOR_RC_BOGUS_ARGS;
-
- /* Maybe enforce user presence, w/ optional consume */
- if (pop_check_presence(req->flags & G2F_CONSUME) != POP_TOUCH_YES &&
- (req->flags & U2F_AUTH_FLAG_TUP) != 0)
- return VENDOR_RC_NOT_ALLOWED;
-
- /* Generate origin-specific keypair */
- do {
- if (!DCRYPTO_ladder_random(&od_seed))
- return VENDOR_RC_INTERNAL_ERROR;
-
- if (u2f_origin_user_keyhandle(req->appId, req->userSecret,
- od_seed, kh) != EC_SUCCESS)
- return VENDOR_RC_INTERNAL_ERROR;
-
- generate_keypair_rc =
- u2f_origin_user_keypair(kh, &od, &opk_x, &opk_y);
- } while (generate_keypair_rc == EC_ERROR_TRY_AGAIN);
-
- if (generate_keypair_rc != EC_SUCCESS)
- return VENDOR_RC_INTERNAL_ERROR;
-
- /*
- * From this point: the request 'req' content is invalid as it is
- * overridden by the response we are building in the same buffer.
- */
- resp = buf;
-
- *response_size = sizeof(*resp);
-
- /* Insert origin-specific public keys into the response */
- p256_to_bin(&opk_x, resp->pubKey.x); /* endianness */
- p256_to_bin(&opk_y, resp->pubKey.y); /* endianness */
-
- resp->pubKey.pointFormat = U2F_POINT_UNCOMPRESSED;
-
- /* Copy key handle to response. */
- memcpy(resp->keyHandle, kh, sizeof(kh));
-
- return VENDOR_RC_SUCCESS;
-}
-DECLARE_VENDOR_COMMAND(VENDOR_CC_U2F_GENERATE, u2f_generate);
-
-static int verify_kh_pubkey(const uint8_t *key_handle,
- const U2F_EC_POINT *public_key, int *matches) {
- int rc;
- U2F_EC_POINT kh_pubkey;
- p256_int od, opk_x, opk_y;
-
- rc = u2f_origin_user_keypair(key_handle, &od, &opk_x, &opk_y);
- if (rc != EC_SUCCESS)
- return rc;
-
- /* Reconstruct the public key. */
- p256_to_bin(&opk_x, kh_pubkey.x);
- p256_to_bin(&opk_y, kh_pubkey.y);
- kh_pubkey.pointFormat = U2F_POINT_UNCOMPRESSED;
-
- *matches =
- safe_memcmp(&kh_pubkey, public_key, sizeof(U2F_EC_POINT)) == 0;
-
- return EC_SUCCESS;
-}
-
-static int verify_kh_owned(const uint8_t *user_secret, const uint8_t *app_id,
- const uint8_t *key_handle, int *owned)
-{
- int rc;
- /* Re-created key handle. */
- uint8_t recreated_kh[KH_LEN];
-
- /*
- * Re-create the key handle and compare against that which
- * was provided. This allows us to verify that the key handle
- * is owned by this combination of device, current user and app_id.
- */
-
- rc = u2f_origin_user_keyhandle(app_id, user_secret, key_handle,
- recreated_kh);
-
- if (rc == EC_SUCCESS)
- *owned = safe_memcmp(recreated_kh, key_handle, KH_LEN) == 0;
-
- return rc;
-}
-
-static int verify_legacy_kh_owned(const uint8_t *app_id,
- const uint8_t *key_handle,
- uint8_t *origin_seed)
-{
- uint8_t unwrapped_kh[KH_LEN];
- uint8_t kh_app_id[U2F_APPID_SIZE];
-
- p256_int app_id_p256;
- p256_int kh_app_id_p256;
-
- /* Unwrap key handle */
- if (wrap_kh(app_id, key_handle, unwrapped_kh, DECRYPT_MODE))
- return 0;
- deinterleave64(unwrapped_kh, kh_app_id, origin_seed);
-
- /* Return whether appId (i.e. origin) matches. */
- p256_from_bin(app_id, &app_id_p256);
- p256_from_bin(kh_app_id, &kh_app_id_p256);
- return p256_cmp(&app_id_p256, &kh_app_id_p256) == 0;
-}
-
-/* Below, we depend on the response not being larger than than the request. */
-BUILD_ASSERT(sizeof(U2F_SIGN_RESP) <= sizeof(U2F_SIGN_REQ));
-
-/* U2F SIGN command */
-static enum vendor_cmd_rc u2f_sign(enum vendor_cmd_cc code,
- void *buf,
- size_t input_size,
- size_t *response_size)
-{
- const U2F_SIGN_REQ *req = buf;
- U2F_SIGN_RESP *resp;
-
- struct drbg_ctx ctx;
-
- /* Whether the key handle is owned by this device. */
- int kh_owned;
-
- /* Origin private key. */
- uint8_t legacy_origin_seed[SHA256_DIGEST_SIZE];
- p256_int origin_d;
-
- /* Hash, and corresponding signature. */
- p256_int h, r, s;
-
- /* Whether the key handle uses the legacy key derivation scheme. */
- int legacy_kh = 0;
-
- /* Response is smaller than request, so no need to check this. */
- *response_size = 0;
-
- if (input_size != sizeof(U2F_SIGN_REQ))
- return VENDOR_RC_BOGUS_ARGS;
-
- if (verify_kh_owned(req->userSecret, req->appId, req->keyHandle,
- &kh_owned) != EC_SUCCESS)
- return VENDOR_RC_INTERNAL_ERROR;
-
- if (!kh_owned) {
- if ((req->flags & SIGN_LEGACY_KH) == 0)
- return VENDOR_RC_PASSWORD_REQUIRED;
-
- /*
- * We have a key handle which is not valid for the new scheme,
- * but may be a valid legacy key handle, and we have been asked
- * to sign legacy key handles.
- */
- if (verify_legacy_kh_owned(req->appId, req->keyHandle,
- legacy_origin_seed))
- legacy_kh = 1;
- else
- return VENDOR_RC_PASSWORD_REQUIRED;
- }
-
- /* We might not actually need to sign anything. */
- if (req->flags == U2F_AUTH_CHECK_ONLY)
- return VENDOR_RC_SUCCESS;
-
- /* Always enforce user presence, with optional consume. */
- if (pop_check_presence(req->flags & G2F_CONSUME) != POP_TOUCH_YES)
- return VENDOR_RC_NOT_ALLOWED;
-
- /* Re-create origin-specific key. */
- if (legacy_kh) {
- if (u2f_origin_key(legacy_origin_seed, &origin_d) != EC_SUCCESS)
- return VENDOR_RC_INTERNAL_ERROR;
- } else {
- if (u2f_origin_user_keypair(req->keyHandle, &origin_d, NULL,
- NULL) != EC_SUCCESS)
- return VENDOR_RC_INTERNAL_ERROR;
- }
-
- /* Prepare hash to sign. */
- p256_from_bin(req->hash, &h);
-
- /* Sign. */
- hmac_drbg_init_rfc6979(&ctx, &origin_d, &h);
- if (!dcrypto_p256_ecdsa_sign(&ctx, &origin_d, &h, &r, &s)) {
- p256_clear(&origin_d);
- return VENDOR_RC_INTERNAL_ERROR;
- }
- p256_clear(&origin_d);
-
- /*
- * From this point: the request 'req' content is invalid as it is
- * overridden by the response we are building in the same buffer.
- * The response is smaller than the request, so we have the space.
- */
- resp = buf;
-
- *response_size = sizeof(*resp);
-
- p256_to_bin(&r, resp->sig_r);
- p256_to_bin(&s, resp->sig_s);
-
- return VENDOR_RC_SUCCESS;
-}
-DECLARE_VENDOR_COMMAND(VENDOR_CC_U2F_SIGN, u2f_sign);
-
-struct G2F_REGISTER_MSG {
- uint8_t reserved;
- uint8_t app_id[U2F_APPID_SIZE];
- uint8_t challenge[U2F_CHAL_SIZE];
- uint8_t key_handle[U2F_APPID_SIZE + sizeof(p256_int)];
- U2F_EC_POINT public_key;
-};
-
-static inline int u2f_attest_verify_reg_resp(const uint8_t *user_secret,
- uint8_t data_size,
- const uint8_t *data)
-{
- struct G2F_REGISTER_MSG *msg = (void *) data;
- int verified;
-
- if (data_size != sizeof(struct G2F_REGISTER_MSG))
- return VENDOR_RC_NOT_ALLOWED;
-
- if (msg->reserved != 0)
- return VENDOR_RC_NOT_ALLOWED;
-
- if (verify_kh_owned(user_secret, msg->app_id, msg->key_handle,
- &verified) != EC_SUCCESS)
- return VENDOR_RC_INTERNAL_ERROR;
-
- if (!verified)
- return VENDOR_RC_NOT_ALLOWED;
-
- if (verify_kh_pubkey(msg->key_handle, &msg->public_key, &verified) !=
- EC_SUCCESS)
- return VENDOR_RC_INTERNAL_ERROR;
-
- if (!verified)
- return VENDOR_RC_NOT_ALLOWED;
-
- return VENDOR_RC_SUCCESS;
-}
-
-static int u2f_attest_verify(const uint8_t *user_secret,
- uint8_t format,
- uint8_t data_size,
- const uint8_t *data)
-{
- switch (format) {
- case U2F_ATTEST_FORMAT_REG_RESP:
- return u2f_attest_verify_reg_resp(user_secret, data_size, data);
- default:
- return VENDOR_RC_NOT_ALLOWED;
- }
-}
-
-static inline size_t u2f_attest_format_size(uint8_t format)
-{
- switch (format) {
- case U2F_ATTEST_FORMAT_REG_RESP:
- return sizeof(struct G2F_REGISTER_MSG);
- default:
- return 0;
- }
-}
-
-/* U2F ATTEST command */
-static enum vendor_cmd_rc u2f_attest(enum vendor_cmd_cc code,
- void *buf,
- size_t input_size,
- size_t *response_size)
-{
- const U2F_ATTEST_REQ *req = buf;
- U2F_ATTEST_RESP *resp;
-
- int verify_ret;
-
- HASH_CTX h_ctx;
- struct drbg_ctx dr_ctx;
-
- /* Data hash, and corresponding signature. */
- p256_int h, r, s;
-
- /* Attestation key */
- p256_int d, pk_x, pk_y;
-
- size_t response_buf_size = *response_size;
-
- *response_size = 0;
-
- if (input_size < offsetof(U2F_ATTEST_REQ, data) ||
- input_size < (offsetof(U2F_ATTEST_REQ, data) + req->dataLen) ||
- input_size > sizeof(U2F_ATTEST_REQ) ||
- response_buf_size < sizeof(*resp))
- return VENDOR_RC_BOGUS_ARGS;
-
- verify_ret = u2f_attest_verify(req->userSecret,
- req->format,
- req->dataLen,
- req->data);
-
- if (verify_ret != VENDOR_RC_SUCCESS)
- return verify_ret;
-
- /* Message signature */
- DCRYPTO_SHA256_init(&h_ctx, 0);
- HASH_update(&h_ctx, req->data, u2f_attest_format_size(req->format));
- p256_from_bin(HASH_final(&h_ctx), &h);
-
- /* Derive G2F Attestation Key */
- if (g2f_individual_keypair(&d, &pk_x, &pk_y)) {
- CPRINTF("G2F Attestation key generation failed");
- return VENDOR_RC_INTERNAL_ERROR;
- }
-
- /* Sign over the response w/ the attestation key */
- hmac_drbg_init_rfc6979(&dr_ctx, &d, &h);
- if (!dcrypto_p256_ecdsa_sign(&dr_ctx, &d, &h, &r, &s)) {
- CPRINTF("Signing error");
- return VENDOR_RC_INTERNAL_ERROR;
- }
- p256_clear(&d);
-
- /*
- * From this point: the request 'req' content is invalid as it is
- * overridden by the response we are building in the same buffer.
- * The response is smaller than the request, so we have the space.
- */
- resp = buf;
-
- *response_size = sizeof(*resp);
-
- p256_to_bin(&r, resp->sig_r);
- p256_to_bin(&s, resp->sig_s);
-
- return VENDOR_RC_SUCCESS;
-}
-DECLARE_VENDOR_COMMAND(VENDOR_CC_U2F_ATTEST, u2f_attest);
diff --git a/common/update_fw.c b/common/update_fw.c
index d0cb35e697..bdb432acd6 100644
--- a/common/update_fw.c
+++ b/common/update_fw.c
@@ -5,7 +5,6 @@
#include "byteorder.h"
#include "console.h"
-#include "extension.h"
#include "flash.h"
#include "hooks.h"
#include "include/compile_time_macros.h"
@@ -106,7 +105,6 @@ static uint8_t check_update_chunk(uint32_t block_offset, size_t body_size)
}
-/* TODO(b/36375666): These need to be overridden for chip/g. */
int update_pdu_valid(struct update_command *cmd_body, size_t cmd_size)
{
return 1;
@@ -283,11 +281,6 @@ void fw_update_command_handler(void *body,
return;
}
- /*
- * TODO(b/36375666): chip/g code has some cr50-specific stuff right
- * here, which should probably be merged into contents_allowed...
- */
-
#ifdef CONFIG_TOUCHPAD_VIRTUAL_OFF
if (is_touchpad_block(block_offset, body_size)) {
if (touchpad_update_write(
@@ -329,7 +322,6 @@ void fw_update_command_handler(void *body,
*error_code = UPDATE_SUCCESS;
}
-/* TODO(b/36375666): This need to be overridden for chip/g. */
void fw_update_complete(void)
{
}
diff --git a/common/usb_update.c b/common/usb_update.c
index 23b3ed4512..cc443163ba 100644
--- a/common/usb_update.c
+++ b/common/usb_update.c
@@ -8,7 +8,6 @@
#include "console.h"
#include "consumer.h"
#include "curve25519.h"
-#include "extension.h"
#include "flash.h"
#include "queue_policies.h"
#include "host_command.h"
diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S
index 3697a72516..9aa1c987ba 100644
--- a/core/cortex-m/ec.lds.S
+++ b/core/cortex-m/ec.lds.S
@@ -220,12 +220,6 @@ SECTIONS
KEEP(*(.rodata.HOOK_BATTERY_SOC_CHANGE))
__hooks_battery_soc_change_end = .;
-#ifdef CONFIG_CASE_CLOSED_DEBUG_V1
- __hooks_ccd_change = .;
- KEEP(*(.rodata.HOOK_CCD_CHANGE))
- __hooks_ccd_change_end = .;
-#endif
-
#ifdef CONFIG_USB_SUSPEND
__hooks_usb_change = .;
KEEP(*(.rodata.HOOK_USB_PM_CHANGE))
diff --git a/extra/usb_updater/Makefile b/extra/usb_updater/Makefile
index 2f8f70a6d3..1dfbc55645 100644
--- a/extra/usb_updater/Makefile
+++ b/extra/usb_updater/Makefile
@@ -4,7 +4,7 @@
CC ?= gcc
PKG_CONFIG ?= pkg-config
-PROGRAMS := gsctool usb_updater2
+PROGRAMS := usb_updater2
LIBS :=
LFLAGS :=
CFLAGS := -std=gnu99 \
@@ -34,27 +34,12 @@ CFLAGS += -I../../include -I../../util -I../../fuzz -I../../test
VPATH = ../../util
-BOARD := cr50
-LIBS_g = $(shell $(PKG_CONFIG) --libs libcrypto)
-CFLAGS_g = $(shell $(PKG_CONFIG) --cflags libcrypto)
-CFLAGS_g += -I../../board/cr50 -I ../../chip/g
-
LIBS_common = -lfmap
all: $(PROGRAMS)
-GSCTOOL_SOURCES := gsctool.c desc_parser.c usb_if.c verify_ro.c
-GSCTOOL_OBJS := $(patsubst %.c,%.o,$(GSCTOOL_SOURCES))
-DEPS := $(patsubst %.c,%.d,$(GSCTOOL_SOURCES))
-
-# chip/g updater
-gsctool: $(GSCTOOL_OBJS) Makefile
- $(CC) $(GSCTOOL_OBJS) $(LFLAGS) $(LIBS) $(LIBS_g) -o $@
-
%.o: %.c
- $(CC) $(CFLAGS) $(CFLAGS_g) -c -MMD -MF $(basename $@).d -o $@ $<
-
-gsctool.o: generated_version.h
+ $(CC) $(CFLAGS) -c -MMD -MF $(basename $@).d -o $@ $<
# common EC code USB updater
usb_updater2: usb_updater2.c Makefile
@@ -62,16 +47,9 @@ usb_updater2: usb_updater2.c Makefile
.PHONY: clean
-generated_version.h: $(GSCTOOL_SOURCES)
- # Make sure ${BOARD} not set to anything when invoking getversion.sh,
- # as even when building with Cr50 enabled, other directories do not
- # matter for gsctool.
- @(cd ../../; BOARD= util/getversion.sh) > $@
-
clean:
- rm -rf $(PROGRAMS) *~ *.o *.d dp generated_version.h
+ rm -rf $(PROGRAMS) *~ *.o *.d dp
parser_debug: desc_parser.c
gcc -g -O0 -DTEST_PARSER desc_parser.c -o dp
--include $(DEPS)
diff --git a/extra/usb_updater/gsctool.c b/extra/usb_updater/gsctool.c
deleted file mode 100644
index 4540814e56..0000000000
--- a/extra/usb_updater/gsctool.c
+++ /dev/null
@@ -1,3027 +0,0 @@
-/*
- * Copyright 2015 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 <asm/byteorder.h>
-#include <ctype.h>
-#include <endian.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <libusb.h>
-#include <openssl/sha.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include "config.h"
-
-#include "ccd_config.h"
-#include "compile_time_macros.h"
-#include "flash_log.h"
-#include "generated_version.h"
-#include "gsctool.h"
-#include "misc_util.h"
-#include "signed_header.h"
-#include "tpm_registers.h"
-#include "tpm_vendor_cmds.h"
-#include "upgrade_fw.h"
-#include "usb_descriptor.h"
-#include "verify_ro.h"
-
-/*
- * This file contains the source code of a Linux application used to update
- * CR50 device firmware.
- *
- * The CR50 firmware image consists of multiple sections, of interest to this
- * app are the RO and RW code sections, two of each. When firmware update
- * session is established, the CR50 device reports locations of backup RW and RO
- * sections (those not used by the device at the time of transfer).
- *
- * Based on this information this app carves out the appropriate sections form
- * the full CR50 firmware binary image and sends them to the device for
- * programming into flash. Once the new sections are programmed and the device
- * is restarted, the new RO and RW are used if they pass verification and are
- * logically newer than the existing sections.
- *
- * There are two ways to communicate with the CR50 device: USB and /dev/tpm0
- * (when this app is running on a chromebook with the CR50 device). Originally
- * different protocols were used to communicate over different channels,
- * starting with version 3 the same protocol is used.
- *
- * This app provides backwards compatibility to ensure that earlier CR50
- * devices still can be updated.
- *
- *
- * The host (either a local AP or a workstation) is the master of the firmware
- * update protocol, it sends data to the cr50 device, which proceeses it and
- * responds.
- *
- * The encapsultation format is different between the /dev/tpm0 and USB cases:
- *
- * 4 bytes 4 bytes 4 bytes variable size
- * +-----------+--------------+---------------+----------~~--------------+
- * + total size| block digest | dest address | data |
- * +-----------+--------------+---------------+----------~~--------------+
- * \ \ /
- * \ \ /
- * \ +----- FW update PDU sent over /dev/tpm0 -----------+
- * \ /
- * +--------- USB frame, requires total size field ------------+
- *
- * The update protocol data unints (PDUs) are passed over /dev/tpm0, the
- * encapsulation includes integritiy verification and destination address of
- * the data (more of this later). /dev/tpm0 transactions pretty much do not
- * have size limits, whereas the USB data is sent in chunks of the size
- * determined when the USB connestion is set up. This is why USB requires an
- * additional encapsulation into frames to communicate the PDU size to the
- * client side so that the PDU can be reassembled before passing to the
- * programming function.
- *
- * In general, the protocol consists of two phases: connection establishment
- * and actual image transfer.
- *
- * The very first PDU of the transfer session is used to establish the
- * connection. The first PDU does not have any data, and the dest. address
- * field is set to zero. Receiving such a PDU signals the programming function
- * that the host intends to transfer a new image.
- *
- * The response to the first PDU varies depending on the protocol version.
- *
- * Note that protocol versions before 5 are described here for completeness,
- * but are not supported any more by this utility.
- *
- * Version 1 is used over /dev/tpm0. The response is either 4 or 1 bytes in
- * size. The 4 byte response is the *base address* of the backup RW section,
- * no support for RO updates. The one byte response is an error indication,
- * possibly reporting flash erase failure, command format error, etc.
- *
- * Version 2 is used over USB. The response is 8 bytes in size. The first four
- * bytes are either the *base address* of the backup RW section (still no RO
- * updates), or an error code, the same as in Version 1. The second 4 bytes
- * are the protocol version number (set to 2).
- *
- * All versions above 2 behave the same over /dev/tpm0 and USB.
- *
- * Version 3 response is 16 bytes in size. The first 4 bytes are the error code
- * the second 4 bytes are the protocol version (set to 3) and then 4 byte
- * *offset* of the RO section followed by the 4 byte *offset* of the RW section.
- *
- * Version 4 response in addition to version 3 provides header revision fields
- * for active RO and RW images running on the target.
- *
- * Once the connection is established, the image to be programmed into flash
- * is transferred to the CR50 in 1K PDUs. In versions 1 and 2 the address in
- * the header is the absolute address to place the block to, in version 3 and
- * later it is the offset into the flash.
- *
- * Protocol version 5 includes RO and RW key ID information into the first PDU
- * response. The key ID could be used to tell between prod and dev signing
- * modes, among other things.
- *
- * Protocol version 6 does not change the format of the first PDU response,
- * but it indicates the target's ablitiy to channel TPM vendor commands
- * through USB connection.
- *
- * When channeling TPM vendor commands the USB frame looks as follows:
- *
- * 4 bytes 4 bytes 4 bytes 2 bytes variable size
- * +-----------+--------------+---------------+-----------+------~~~-------+
- * + total size| block digest | EXT_CMD | Vend. sub.| data |
- * +-----------+--------------+---------------+-----------+------~~~-------+
- *
- * Where 'Vend. sub' is the vendor subcommand, and data field is subcommand
- * dependent. The target tells between update PDUs and encapsulated vendor
- * subcommands by looking at the EXT_CMD value - it is set to 0xbaccd00a and
- * as such is guaranteed not to be a valid update PDU destination address.
- *
- * The vendor command response size is not fixed, it is subcommand dependent.
- *
- * The CR50 device responds to each update PDU with a confirmation which is 4
- * bytes in size in protocol version 2, and 1 byte in size in all other
- * versions. Zero value means success, non zero value is the error code
- * reported by CR50.
- *
- * Again, vendor command responses are subcommand specific.
- */
-
-/* Look for Cr50 FW update interface */
-#define VID USB_VID_GOOGLE
-#define PID CONFIG_USB_PID
-#define SUBCLASS USB_SUBCLASS_GOOGLE_CR50
-#define PROTOCOL USB_PROTOCOL_GOOGLE_CR50_NON_HC_FW_UPDATE
-
-/*
- * Need to create an entire TPM PDU when upgrading over /dev/tpm0 and need to
- * have space to prepare the entire PDU.
- */
-struct upgrade_pkt {
- __be16 tag;
- __be32 length;
- __be32 ordinal;
- __be16 subcmd;
- union {
- /*
- * Upgrade PDUs as opposed to all other vendor and extension
- * commands include two additional fields in the header.
- */
- struct {
- __be32 digest;
- __be32 address;
- char data[0];
- } upgrade;
- struct {
- char data[0];
- } command;
- };
-} __packed;
-
-/*
- * Structure used to simplify mapping command line options into Boolean
- * variables. If an option is present, the corresponding integer value is set
- * to 1.
- */
-struct options_map {
- char opt;
- int *flag;
-};
-
-/*
- * Structure used to combine option description used by getopt_long() and help
- * text for the option.
- */
-struct option_container {
- struct option opt;
- const char *help_text;
-};
-
-/*
- * This by far exceeds the largest vendor command response size we ever
- * expect.
- */
-#define MAX_BUF_SIZE 500
-
-/*
- * Max. length of the board ID string representation.
- *
- * Board ID is either a 4-character ASCII alphanumeric string or an 8-digit
- * hex.
- */
-#define MAX_BOARD_ID_LENGTH 9
-
-/*
- * Length, in bytes, of the SN Bits serial number bits.
- */
-#define SN_BITS_SIZE (96 >> 3)
-
-/*
- * Max. length of FW version in the format of <epoch>.<major>.<minor>
- * (3 uint32_t string representation + 2 separators + NULL terminator).
- */
-#define MAX_FW_VER_LENGTH 33
-
-static int verbose_mode;
-static uint32_t protocol_version;
-static char *progname;
-
-/*
- * List of command line options, ***sorted by the short form***.
- *
- * The help_text field does not include the short and long option strings,
- * they are retrieved from the opt structure. In case the help text needs to
- * have something printed immediately after the option strings (for example,
- * an optional parameter), it should be included in the beginning of help_text
- * string separated by the % character.
- *
- * usage() function which prints out the help message will concatenate the
- * short and long options and the optional parameter, if present, and then
- * print the rest of the text message at a fixed indentation.
- */
-static const struct option_container cmd_line_options[] = {
- /* name has_arg *flag val */
- {{"any", no_argument, NULL, 'a'},
- "Try any interfaces to find Cr50"
- " (-d, -s, -t are all ignored)"},
- {{"background_update_supported", no_argument, NULL, 'B'},
- "Force background update mode (relevant"
- " only when interacting"
- " with Cr50 versions before 0.0.19)"
- },
- {{"binvers", no_argument, NULL, 'b'},
- "Report versions of Cr50 image's "
- "RW and RO headers, do not update"},
- {{"corrupt", no_argument, NULL, 'c'},
- "Corrupt the inactive rw"},
- {{"device", required_argument, NULL, 'd'},
- " VID:PID%USB device (default 18d1:5014)"},
- {{"endorsement_seed", optional_argument, NULL, 'e'},
- "[state]%get/set the endorsement key seed"},
- {{"fwver", no_argument, NULL, 'f'},
- "Report running Cr50 firmware versions"},
- {{"factory", required_argument, NULL, 'F'},
- "[enable|disable]%Control factory mode"},
- {{"help", no_argument, NULL, 'h'},
- "Show this message"},
- {{"ccd_info", no_argument, NULL, 'I'},
- "Get information about CCD state"},
- {{"board_id", optional_argument, NULL, 'i'},
- "[ID[:FLAGS]]%Get or set Info1 board ID fields. ID could be 32 bit "
- "hex or 4 character string."},
- {{"ccd_lock", no_argument, NULL, 'k'},
- "Lock CCD"},
- {{"flog", optional_argument, NULL, 'L'},
- "[prev entry]%Retrieve contents of the flash log"
- " (newer than <prev entry> if specified)"},
- {{"machine", no_argument, NULL, 'M'},
- "Output in a machine-friendly way. "
- "Effective with -b, -f, -i, and -O."},
- {{"tpm_mode", optional_argument, NULL, 'm'},
- "[enable|disable]%Change or query tpm_mode"},
- {{"serial", required_argument, NULL, 'n'},
- "Cr50 CCD serial number"},
- {{"openbox_rma", required_argument, NULL, 'O'},
- "<desc_file>%Verify other device's RO integrity using information "
- "provided in <desc file>"},
- {{"ccd_open", no_argument, NULL, 'o'},
- "Start CCD open sequence"},
- {{"password", no_argument, NULL, 'P'},
- "Set or clear CCD password. Use 'clear:<cur password>' to clear it"},
- {{"post_reset", no_argument, NULL, 'p'},
- "Request post reset after transfer"},
- {{"force_ro", no_argument, NULL, 'q'},
- "Force inactive RO update"},
- {{"sn_rma_inc", required_argument, NULL, 'R'},
- "RMA_INC%Increment SN RMA count by RMA_INC. RMA_INC should be 0-7."},
- {{"rma_auth", optional_argument, NULL, 'r'},
- "[auth_code]%Request RMA challenge, process "
- "RMA authentication code"},
- {{"sn_bits", required_argument, NULL, 'S'},
- "SN_BITS%Set Info1 SN bits fields. SN_BITS should be 96 bit hex."},
- {{"systemdev", no_argument, NULL, 's'},
- "Use /dev/tpm0 (-d is ignored)"},
- {{"tstamp", optional_argument, NULL, 'T'},
- "[<tstamp>]%Get or set flash log timestamp base"},
- {{"trunks_send", no_argument, NULL, 't'},
- "Use `trunks_send --raw' (-d is ignored)"},
- {{"ccd_unlock", no_argument, NULL, 'U'},
- "Start CCD unlock sequence"},
- {{"upstart", no_argument, NULL, 'u'},
- "Upstart mode (strict header checks)"},
- {{"verbose", no_argument, NULL, 'V'},
- "Enable debug messages"},
- {{"version", no_argument, NULL, 'v'},
- "Report this utility version"},
- {{"wp", no_argument, NULL, 'w'},
- "Get the current wp setting"}
-};
-
-/* Helper to print debug messages when verbose flag is specified. */
-static void debug(const char *fmt, ...)
-{
- va_list args;
-
- if (verbose_mode) {
- va_start(args, fmt);
- vprintf(fmt, args);
- va_end(args);
- }
-}
-
-/* Helpers to convert between binary and hex ascii and back. */
-static char to_hexascii(uint8_t c)
-{
- if (c <= 9)
- return '0' + c;
- return 'a' + c - 10;
-}
-
-static int from_hexascii(char c)
-{
- /* convert to lower case. */
- c = tolower(c);
-
- if (c < '0' || c > 'f' || ((c > '9') && (c < 'a')))
- return -1; /* Not an ascii character. */
-
- if (c <= '9')
- return c - '0';
-
- return c - 'a' + 10;
-}
-
-/* Functions to communicate with the TPM over the trunks_send --raw channel. */
-
-/* File handle to share between write and read sides. */
-static FILE *tpm_output;
-static int ts_write(const void *out, size_t len)
-{
- const char *cmd_head = "PATH=\"${PATH}:/usr/sbin\" trunks_send --raw ";
- size_t head_size = strlen(cmd_head);
- char full_command[head_size + 2 * len + 1];
- size_t i;
-
- strcpy(full_command, cmd_head);
- /*
- * Need to convert binary input into hex ascii output to pass to the
- * trunks_send command.
- */
- for (i = 0; i < len; i++) {
- uint8_t c = ((const uint8_t *)out)[i];
-
- full_command[head_size + 2 * i] = to_hexascii(c >> 4);
- full_command[head_size + 2 * i + 1] = to_hexascii(c & 0xf);
- }
-
- /* Make it a proper zero terminated string. */
- full_command[sizeof(full_command) - 1] = 0;
- debug("cmd: %s\n", full_command);
- tpm_output = popen(full_command, "r");
- if (tpm_output)
- return len;
-
- fprintf(stderr, "Error: failed to launch trunks_send --raw\n");
- return -1;
-}
-
-static int ts_read(void *buf, size_t max_rx_size)
-{
- int i;
- int pclose_rv;
- int rv;
- char response[max_rx_size * 2];
-
- if (!tpm_output) {
- fprintf(stderr, "Error: attempt to read empty output\n");
- return -1;
- }
-
- rv = fread(response, 1, sizeof(response), tpm_output);
- if (rv > 0)
- rv -= 1; /* Discard the \n character added by trunks_send. */
-
- debug("response of size %d, max rx size %zd: %s\n",
- rv, max_rx_size, response);
-
- pclose_rv = pclose(tpm_output);
- if (pclose_rv < 0) {
- fprintf(stderr,
- "Error: pclose failed: error %d (%s)\n",
- errno, strerror(errno));
- return -1;
- }
-
- tpm_output = NULL;
-
- if (rv & 1) {
- fprintf(stderr,
- "Error: trunks_send returned odd number of bytes: %s\n",
- response);
- return -1;
- }
-
- for (i = 0; i < rv/2; i++) {
- uint8_t byte;
- char c;
- int nibble;
-
- c = response[2 * i];
- nibble = from_hexascii(c);
- if (nibble < 0) {
- fprintf(stderr, "Error: "
- "trunks_send returned non hex character %c\n",
- c);
- return -1;
- }
- byte = nibble << 4;
-
- c = response[2 * i + 1];
- nibble = from_hexascii(c);
- if (nibble < 0) {
- fprintf(stderr, "Error: "
- "trunks_send returned non hex character %c\n",
- c);
- return -1;
- }
- byte |= nibble;
-
- ((uint8_t *)buf)[i] = byte;
- }
-
- return rv/2;
-}
-
-/*
- * Prepare and transfer a block to either to /dev/tpm0 or through trunks_send
- * --raw, get a reply.
- */
-static int tpm_send_pkt(struct transfer_descriptor *td, unsigned int digest,
- unsigned int addr, const void *data, int size,
- void *response, size_t *response_size,
- uint16_t subcmd)
-{
- /* Used by transfer to /dev/tpm0 */
- static uint8_t outbuf[MAX_BUF_SIZE];
- struct upgrade_pkt *out = (struct upgrade_pkt *)outbuf;
- int len, done;
- int response_offset = offsetof(struct upgrade_pkt, command.data);
- void *payload;
- size_t header_size;
- uint32_t rv;
- const size_t rx_size = sizeof(outbuf);
-
- debug("%s: sending to %#x %d bytes\n", __func__, addr, size);
-
- out->tag = htobe16(0x8001);
- out->subcmd = htobe16(subcmd);
-
- if (subcmd <= LAST_EXTENSION_COMMAND)
- out->ordinal = htobe32(CONFIG_EXTENSION_COMMAND);
- else
- out->ordinal = htobe32(TPM_CC_VENDOR_BIT_MASK);
-
- if (subcmd == EXTENSION_FW_UPGRADE) {
- /* FW Upgrade PDU header includes a couple of extra fields. */
- out->upgrade.digest = digest;
- out->upgrade.address = htobe32(addr);
- header_size = offsetof(struct upgrade_pkt, upgrade.data);
- } else {
- header_size = offsetof(struct upgrade_pkt, command.data);
- }
-
- payload = outbuf + header_size;
- len = size + header_size;
-
- out->length = htobe32(len);
- memcpy(payload, data, size);
-
- if (verbose_mode) {
- int i;
-
- debug("Writing %d bytes to TPM at %x\n", len, addr);
- for (i = 0; i < MIN(len, 20); i++)
- debug("%2.2x ", outbuf[i]);
- debug("\n");
- }
-
- switch (td->ep_type) {
- case dev_xfer:
- done = write(td->tpm_fd, out, len);
- break;
- case ts_xfer:
- done = ts_write(out, len);
- break;
- default:
- fprintf(stderr, "Error: %s:%d: unknown transfer type %d\n",
- __func__, __LINE__, td->ep_type);
- return -1;
- }
-
- if (done < 0) {
- perror("Could not write to TPM");
- return -1;
- } else if (done != len) {
- fprintf(stderr, "Error: Wrote %d bytes, expected to write %d\n",
- done, len);
- return -1;
- }
-
- switch (td->ep_type) {
- case dev_xfer: {
- int read_count;
-
- len = 0;
- do {
- uint8_t *rx_buf = outbuf + len;
- size_t rx_to_go = rx_size - len;
-
- read_count = read(td->tpm_fd, rx_buf, rx_to_go);
-
- len += read_count;
- } while (read_count);
- break;
- }
- case ts_xfer:
- len = ts_read(outbuf, rx_size);
- break;
- default:
- /*
- * This sure will never happen, type is verifed in the
- * previous switch statement.
- */
- len = -1;
- break;
- }
-
- debug("Read %d bytes from TPM\n", len);
- if (len > 0) {
- int i;
-
- for (i = 0; i < len; i++)
- debug("%2.2x ", outbuf[i]);
- debug("\n");
- }
- len = len - response_offset;
- if (len < 0) {
- fprintf(stderr, "Problems reading from TPM, got %d bytes\n",
- len + response_offset);
- return -1;
- }
-
- if (response && response_size) {
- len = MIN(len, *response_size);
- memcpy(response, outbuf + response_offset, len);
- *response_size = len;
- }
-
- /* Return the actual return code from the TPM response header. */
- memcpy(&rv, &((struct upgrade_pkt *)outbuf)->ordinal, sizeof(rv));
- rv = be32toh(rv);
-
- /* Clear out vendor command return value offset.*/
- if ((rv & VENDOR_RC_ERR) == VENDOR_RC_ERR)
- rv &= ~VENDOR_RC_ERR;
-
- return rv;
-}
-
-/* Release USB device and return error to the OS. */
-static void shut_down(struct usb_endpoint *uep)
-{
- usb_shut_down(uep);
- exit(update_error);
-}
-
-static void usage(int errs)
-{
- size_t i;
- const int indent = 27; /* This is the size used by gsctool all along. */
-
- printf("\nUsage: %s [options] [<binary image>]\n"
- "\n"
- "This utility allows to update Cr50 RW firmware, configure\n"
- "various aspects of Cr50 operation, analyze Cr50 binary\n"
- "images, etc.\n\n"
- "<binary image> is the file name of a full RO+RW binary image.\n"
- "\n"
- "Options:\n\n",
- progname);
-
- for (i = 0; i < ARRAY_SIZE(cmd_line_options); i++) {
- const char *help_text = cmd_line_options[i].help_text;
- int printed_length;
- const char *separator;
-
- /*
- * First print the short and long forms of the command line
- * option.
- */
- printed_length = printf(" -%c,--%s",
- cmd_line_options[i].opt.val,
- cmd_line_options[i].opt.name);
-
- /*
- * If there is something to print immediately after the
- * options, print it.
- */
- separator = strchr(help_text, '%');
- if (separator) {
- char buffer[80];
- size_t extra_size;
-
- extra_size = separator - help_text;
- if (extra_size >= sizeof(buffer)) {
- fprintf(stderr, "misformatted help text: %s\n",
- help_text);
- exit(-1);
- }
- memcpy(buffer, help_text, extra_size);
- buffer[extra_size] = '\0';
- printed_length += printf(" %s", buffer);
- help_text = separator + 1;
- }
-
- /*
- * If printed length exceeds or is too close to indent, print
- * help text on the next line.
- */
- if (printed_length >= (indent - 1)) {
- printf("\n");
- printed_length = 0;
- }
-
- while (printed_length++ < indent)
- printf(" ");
- printf("%s\n", help_text);
- }
- printf("\n");
- exit(errs ? update_error : noop);
-}
-
-/* Read file into buffer */
-static uint8_t *get_file_or_die(const char *filename, size_t *len_ptr)
-{
- FILE *fp;
- struct stat st;
- uint8_t *data;
- size_t len;
-
- fp = fopen(filename, "rb");
- if (!fp) {
- perror(filename);
- exit(update_error);
- }
- if (fstat(fileno(fp), &st)) {
- perror("stat");
- exit(update_error);
- }
-
- len = st.st_size;
-
- data = malloc(len);
- if (!data) {
- perror("malloc");
- exit(update_error);
- }
-
- if (1 != fread(data, st.st_size, 1, fp)) {
- perror("fread");
- exit(update_error);
- }
-
- fclose(fp);
-
- *len_ptr = len;
- return data;
-}
-
-/* Returns true if parsed. */
-static int parse_vidpid(const char *input, uint16_t *vid_ptr, uint16_t *pid_ptr)
-{
- char *copy, *s, *e = 0;
-
- copy = strdup(input);
-
- s = strchr(copy, ':');
- if (!s)
- return 0;
- *s++ = '\0';
-
- *vid_ptr = (uint16_t) strtoul(copy, &e, 16);
- if (!*optarg || (e && *e))
- return 0;
-
- *pid_ptr = (uint16_t) strtoul(s, &e, 16);
- if (!*optarg || (e && *e))
- return 0;
-
- return 1;
-}
-
-struct update_pdu {
- uint32_t block_size; /* Total block size, include this field's size. */
- struct upgrade_command cmd;
- /* The actual payload goes here. */
-};
-
-static void do_xfer(struct usb_endpoint *uep, void *outbuf, int outlen,
- void *inbuf, int inlen, int allow_less, size_t *rxed_count)
-{
- if (usb_trx(uep, outbuf, outlen, inbuf, inlen, allow_less, rxed_count))
- shut_down(uep);
-}
-
-static int transfer_block(struct usb_endpoint *uep, struct update_pdu *updu,
- uint8_t *transfer_data_ptr, size_t payload_size)
-{
- size_t transfer_size;
- uint32_t reply;
- int actual;
- int r;
-
- /* First send the header. */
- do_xfer(uep, updu, sizeof(*updu), NULL, 0, 0, NULL);
-
- /* Now send the block, chunk by chunk. */
- for (transfer_size = 0; transfer_size < payload_size;) {
- int chunk_size;
-
- chunk_size = MIN(uep->chunk_len, payload_size - transfer_size);
- do_xfer(uep, transfer_data_ptr, chunk_size, NULL, 0, 0, NULL);
- transfer_data_ptr += chunk_size;
- transfer_size += chunk_size;
- }
-
- /* Now get the reply. */
- r = libusb_bulk_transfer(uep->devh, uep->ep_num | 0x80,
- (void *) &reply, sizeof(reply),
- &actual, 1000);
- if (r) {
- if (r == -7) {
- fprintf(stderr, "Timeout!\n");
- return r;
- }
- USB_ERROR("libusb_bulk_transfer", r);
- shut_down(uep);
- }
-
- reply = *((uint8_t *)&reply);
- if (reply) {
- fprintf(stderr, "Error: status %#x\n", reply);
- exit(update_error);
- }
-
- return 0;
-}
-
-/**
- * Transfer an image section (typically RW or RO).
- *
- * td - transfer descriptor to use to communicate with the target
- * data_ptr - pointer at the section base in the image
- * section_addr - address of the section in the target memory space
- * data_len - section size
- */
-static void transfer_section(struct transfer_descriptor *td,
- uint8_t *data_ptr,
- uint32_t section_addr,
- size_t data_len)
-{
- /*
- * Actually, we can skip trailing chunks of 0xff, as the entire
- * section space must be erased before the update is attempted.
- */
- while (data_len && (data_ptr[data_len - 1] == 0xff))
- data_len--;
-
- /*
- * Make sure total size is 4 bytes aligned, this is required for
- * successful flashing.
- */
- data_len = (data_len + 3) & ~3;
-
- printf("sending 0x%zx bytes to %#x\n", data_len, section_addr);
- while (data_len) {
- size_t payload_size;
- SHA_CTX ctx;
- uint8_t digest[SHA_DIGEST_LENGTH];
- int max_retries;
- struct update_pdu updu;
-
- /* prepare the header to prepend to the block. */
- payload_size = MIN(data_len, SIGNED_TRANSFER_SIZE);
- updu.block_size = htobe32(payload_size +
- sizeof(struct update_pdu));
-
- updu.cmd.block_base = htobe32(section_addr);
-
- /* Calculate the digest. */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, &updu.cmd.block_base,
- sizeof(updu.cmd.block_base));
- SHA1_Update(&ctx, data_ptr, payload_size);
- SHA1_Final(digest, &ctx);
-
- /* Copy the first few bytes. */
- memcpy(&updu.cmd.block_digest, digest,
- sizeof(updu.cmd.block_digest));
- if (td->ep_type == usb_xfer) {
- for (max_retries = 10; max_retries; max_retries--)
- if (!transfer_block(&td->uep, &updu,
- data_ptr, payload_size))
- break;
-
- if (!max_retries) {
- fprintf(stderr,
- "Failed to transfer block, %zd to go\n",
- data_len);
- exit(update_error);
- }
- } else {
- uint8_t error_code[4];
- size_t rxed_size = sizeof(error_code);
- uint32_t block_addr;
-
- block_addr = section_addr;
-
- /*
- * A single byte response is expected, but let's give
- * the driver a few extra bytes to catch cases when a
- * different amount of data is transferred (which
- * would indicate a synchronization problem).
- */
- if (tpm_send_pkt(td,
- updu.cmd.block_digest,
- block_addr,
- data_ptr,
- payload_size, error_code,
- &rxed_size,
- EXTENSION_FW_UPGRADE) < 0) {
- fprintf(stderr,
- "Failed to trasfer block, %zd to go\n",
- data_len);
- exit(update_error);
- }
- if (rxed_size != 1) {
- fprintf(stderr, "Unexpected return size %zd\n",
- rxed_size);
- exit(update_error);
- }
-
- if (error_code[0]) {
- fprintf(stderr, "Error %d\n", error_code[0]);
- exit(update_error);
- }
- }
- data_len -= payload_size;
- data_ptr += payload_size;
- section_addr += payload_size;
- }
-}
-
-/* Information about the target */
-static struct first_response_pdu targ;
-
-/*
- * Each RO or RW section of the new image can be in one of the following
- * states.
- */
-enum upgrade_status {
- not_needed = 0, /* Version below or equal that on the target. */
- not_possible, /*
- * RO is newer, but can't be transferred due to
- * target RW shortcomings.
- */
- needed /*
- * This section needs to be transferred to the
- * target.
- */
-};
-
-/* This array describes all four sections of the new image. */
-static struct {
- const char *name;
- uint32_t offset;
- uint32_t size;
- enum upgrade_status ustatus;
- struct signed_header_version shv;
- uint32_t keyid;
-} sections[] = {
- {"RO_A", CONFIG_RO_MEM_OFF, CONFIG_RO_SIZE},
- {"RW_A", CONFIG_RW_MEM_OFF, CONFIG_RW_SIZE},
- {"RO_B", CHIP_RO_B_MEM_OFF, CONFIG_RO_SIZE},
- {"RW_B", CONFIG_RW_B_MEM_OFF, CONFIG_RW_SIZE}
-};
-
-/*
- * Scan the new image and retrieve versions of all four sections, two RO and
- * two RW.
- */
-static void fetch_header_versions(const void *image)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
- const struct SignedHeader *h;
-
- h = (const struct SignedHeader *)((uintptr_t)image +
- sections[i].offset);
- sections[i].shv.epoch = h->epoch_;
- sections[i].shv.major = h->major_;
- sections[i].shv.minor = h->minor_;
- sections[i].keyid = h->keyid;
- }
-}
-
-
-/* Compare to signer headers and determine which one is newer. */
-static int a_newer_than_b(struct signed_header_version *a,
- struct signed_header_version *b)
-{
- uint32_t fields[][3] = {
- {a->epoch, a->major, a->minor},
- {b->epoch, b->major, b->minor},
- };
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(fields[0]); i++) {
- uint32_t a_value;
- uint32_t b_value;
-
- a_value = fields[0][i];
- b_value = fields[1][i];
-
- /*
- * Let's filter out images where the section is not
- * initialized and the version field value is set to all ones.
- */
- if (a_value == 0xffffffff)
- a_value = 0;
-
- if (b_value == 0xffffffff)
- b_value = 0;
-
- if (a_value != b_value)
- return a_value > b_value;
- }
-
- return 0; /* All else being equal A is no newer than B. */
-}
-/*
- * Pick sections to transfer based on information retrieved from the target,
- * the new image, and the protocol version the target is running.
- */
-static void pick_sections(struct transfer_descriptor *td)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
- uint32_t offset = sections[i].offset;
-
- if ((offset == CONFIG_RW_MEM_OFF) ||
- (offset == CONFIG_RW_B_MEM_OFF)) {
-
- /* Skip currently active section. */
- if (offset != td->rw_offset)
- continue;
- /*
- * Ok, this would be the RW section to transfer to the
- * device. Is it newer in the new image than the
- * running RW section on the device?
- *
- * If not in 'upstart' mode - transfer even if
- * versions are the same, timestamps could be
- * different.
- */
-
- if (a_newer_than_b(&sections[i].shv, &targ.shv[1]) ||
- !td->upstart_mode)
- sections[i].ustatus = needed;
- continue;
- }
-
- /* Skip currently active section. */
- if (offset != td->ro_offset)
- continue;
- /*
- * Ok, this would be the RO section to transfer to the device.
- * Is it newer in the new image than the running RO section on
- * the device?
- */
- if (a_newer_than_b(&sections[i].shv, &targ.shv[0]) ||
- td->force_ro)
- sections[i].ustatus = needed;
- }
-}
-
-static void setup_connection(struct transfer_descriptor *td)
-{
- size_t rxed_size;
- size_t i;
- uint32_t error_code;
-
- /*
- * Need to be backwards compatible, communicate with targets running
- * different protocol versions.
- */
- union {
- struct first_response_pdu rpdu;
- uint32_t legacy_resp;
- } start_resp;
-
- /* Send start request. */
- printf("start\n");
-
- if (td->ep_type == usb_xfer) {
- struct update_pdu updu;
-
- memset(&updu, 0, sizeof(updu));
- updu.block_size = htobe32(sizeof(updu));
- do_xfer(&td->uep, &updu, sizeof(updu), &start_resp,
- sizeof(start_resp), 1, &rxed_size);
- } else {
- rxed_size = sizeof(start_resp);
- if (tpm_send_pkt(td, 0, 0, NULL, 0,
- &start_resp, &rxed_size,
- EXTENSION_FW_UPGRADE) < 0) {
- fprintf(stderr, "Failed to start transfer\n");
- exit(update_error);
- }
- }
-
- /* We got something. Check for errors in response */
- if (rxed_size < 8) {
- fprintf(stderr, "Unexpected response size %zd: ", rxed_size);
- for (i = 0; i < rxed_size; i++)
- fprintf(stderr, " %02x", ((uint8_t *)&start_resp)[i]);
- fprintf(stderr, "\n");
- exit(update_error);
- }
-
- protocol_version = be32toh(start_resp.rpdu.protocol_version);
- if (protocol_version < 5) {
- fprintf(stderr, "Unsupported protocol version %d\n",
- protocol_version);
- exit(update_error);
- }
-
- printf("target running protocol version %d\n", protocol_version);
-
- error_code = be32toh(start_resp.rpdu.return_value);
-
- if (error_code) {
- fprintf(stderr, "Target reporting error %d\n", error_code);
- if (td->ep_type == usb_xfer)
- shut_down(&td->uep);
- exit(update_error);
- }
-
- td->rw_offset = be32toh(start_resp.rpdu.backup_rw_offset);
- td->ro_offset = be32toh(start_resp.rpdu.backup_ro_offset);
-
- /* Running header versions. */
- for (i = 0; i < ARRAY_SIZE(targ.shv); i++) {
- targ.shv[i].minor = be32toh(start_resp.rpdu.shv[i].minor);
- targ.shv[i].major = be32toh(start_resp.rpdu.shv[i].major);
- targ.shv[i].epoch = be32toh(start_resp.rpdu.shv[i].epoch);
- }
-
- for (i = 0; i < ARRAY_SIZE(targ.keyid); i++)
- targ.keyid[i] = be32toh(start_resp.rpdu.keyid[i]);
-
- printf("keyids: RO 0x%08x, RW 0x%08x\n", targ.keyid[0], targ.keyid[1]);
- printf("offsets: backup RO at %#x, backup RW at %#x\n",
- td->ro_offset, td->rw_offset);
-
- pick_sections(td);
-}
-
-/*
- * Channel TPM extension/vendor command over USB. The payload of the USB frame
- * in this case consists of the 2 byte subcommand code concatenated with the
- * command body. The caller needs to indicate if a response is expected, and
- * if it is - of what maximum size.
- */
-static int ext_cmd_over_usb(struct usb_endpoint *uep, uint16_t subcommand,
- const void *cmd_body, size_t body_size,
- void *resp, size_t *resp_size)
-{
- struct update_frame_header *ufh;
- uint16_t *frame_ptr;
- size_t usb_msg_size;
- SHA_CTX ctx;
- uint8_t digest[SHA_DIGEST_LENGTH];
-
- usb_msg_size = sizeof(struct update_frame_header) +
- sizeof(subcommand) + body_size;
-
- ufh = malloc(usb_msg_size);
- if (!ufh) {
- fprintf(stderr, "%s: failed to allocate %zd bytes\n",
- __func__, usb_msg_size);
- return -1;
- }
-
- ufh->block_size = htobe32(usb_msg_size);
- ufh->cmd.block_base = htobe32(CONFIG_EXTENSION_COMMAND);
- frame_ptr = (uint16_t *)(ufh + 1);
- *frame_ptr = htobe16(subcommand);
-
- if (body_size)
- memcpy(frame_ptr + 1, cmd_body, body_size);
-
- /* Calculate the digest. */
- SHA1_Init(&ctx);
- SHA1_Update(&ctx, &ufh->cmd.block_base,
- usb_msg_size -
- offsetof(struct update_frame_header, cmd.block_base));
- SHA1_Final(digest, &ctx);
- memcpy(&ufh->cmd.block_digest, digest, sizeof(ufh->cmd.block_digest));
-
- do_xfer(uep, ufh, usb_msg_size, resp,
- resp_size ? *resp_size : 0, 1, resp_size);
-
- free(ufh);
- return 0;
-}
-
-/*
- * Indicate to the target that update image transfer has been completed. Upon
- * receiveing of this message the target state machine transitions into the
- * 'rx_idle' state. The host may send an extension command to reset the target
- * after this.
- */
-static void send_done(struct usb_endpoint *uep)
-{
- uint32_t out;
-
- /* Send stop request, ignoring reply. */
- out = htobe32(UPGRADE_DONE);
- do_xfer(uep, &out, sizeof(out), &out, 1, 0, NULL);
-}
-
-/*
- * Old cr50 images fail the update if sections are sent out of order. They
- * require each block to have an offset greater than the block that was sent
- * before. RO has a lower offset than RW, so old cr50 images reject RO if it's
- * sent right after RW.
- * This offset restriction expires after 60 seconds. Delay the RO update long
- * enough for cr50 to not care that it has a lower offset than RW.
- *
- * Make the delay 65 seconds instead of 60 to cover differences in the speed of
- * H1's clock and the host clock.
- */
-#define NEXT_SECTION_DELAY 65
-
-/* Support for flashing RO immediately after RW was added in 0.3.20/0.4.20. */
-static int supports_reordered_section_updates(struct signed_header_version *rw)
-{
- return (rw->epoch || rw->major > 4 ||
- (rw->major >= 3 && rw->minor >= 20));
-}
-
-/* Returns number of successfully transmitted image sections. */
-static int transfer_image(struct transfer_descriptor *td,
- uint8_t *data, size_t data_len)
-{
- size_t j;
- int num_txed_sections = 0;
- int needs_delay = !supports_reordered_section_updates(&targ.shv[1]);
-
- /*
- * In case both RO and RW updates are required, make sure the RW
- * section is updated before the RO. The array below keeps sections
- * offsets in the required order.
- */
- const size_t update_order[] = {CONFIG_RW_MEM_OFF,
- CONFIG_RW_B_MEM_OFF,
- CONFIG_RO_MEM_OFF,
- CHIP_RO_B_MEM_OFF};
-
- for (j = 0; j < ARRAY_SIZE(update_order); j++) {
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
- if (sections[i].offset != update_order[j])
- continue;
-
- if (sections[i].ustatus != needed)
- break;
- if (num_txed_sections && needs_delay) {
- /*
- * Delays more than 5 seconds cause the update
- * to timeout. End the update before the delay
- * and set it up after to recover from the
- * timeout.
- */
- if (td->ep_type == usb_xfer)
- send_done(&td->uep);
- printf("Waiting %ds for %s update.\n",
- NEXT_SECTION_DELAY, sections[i].name);
- sleep(NEXT_SECTION_DELAY);
- setup_connection(td);
- }
-
- transfer_section(td,
- data + sections[i].offset,
- sections[i].offset,
- sections[i].size);
- num_txed_sections++;
- }
- }
-
- if (!num_txed_sections)
- printf("nothing to do\n");
- else
- printf("-------\nupdate complete\n");
- return num_txed_sections;
-}
-
-uint32_t send_vendor_command(struct transfer_descriptor *td,
- uint16_t subcommand,
- const void *command_body,
- size_t command_body_size,
- void *response,
- size_t *response_size)
-{
- int32_t rv;
-
- if (td->ep_type == usb_xfer) {
- /*
- * When communicating over USB the response is always supposed
- * to have the result code in the first byte of the response,
- * to be stripped from the actual response body by this
- * function.
- */
- uint8_t temp_response[MAX_BUF_SIZE];
- size_t max_response_size;
-
- if (!response_size) {
- max_response_size = 1;
- } else if (*response_size < (sizeof(temp_response))) {
- max_response_size = *response_size + 1;
- } else {
- fprintf(stderr,
- "Error: Expected response too large (%zd)\n",
- *response_size);
- /* Should happen only when debugging. */
- exit(update_error);
- }
-
- ext_cmd_over_usb(&td->uep, subcommand,
- command_body, command_body_size,
- temp_response, &max_response_size);
- if (!max_response_size) {
- /*
- * we must be talking to an older Cr50 firmware, which
- * does not return the result code in the first byte
- * on success, nothing to do.
- */
- if (response_size)
- *response_size = 0;
- rv = 0;
- } else {
- rv = temp_response[0];
- if (response_size) {
- *response_size = max_response_size - 1;
- memcpy(response,
- temp_response + 1, *response_size);
- }
- }
- } else {
-
- rv = tpm_send_pkt(td, 0, 0,
- command_body, command_body_size,
- response, response_size, subcommand);
-
- if (rv == -1) {
- fprintf(stderr,
- "Error: Failed to send vendor command %d\n",
- subcommand);
- exit(update_error);
- }
- }
-
- return rv; /* This will be converted into uint32_t */
-}
-
-/*
- * Corrupt the header of the inactive rw image to make sure the system can't
- * rollback
- */
-static void invalidate_inactive_rw(struct transfer_descriptor *td)
-{
- /* Corrupt the rw image that is not running. */
- uint32_t rv;
-
- rv = send_vendor_command(td, VENDOR_CC_INVALIDATE_INACTIVE_RW,
- NULL, 0, NULL, NULL);
- if (!rv) {
- printf("Inactive header invalidated\n");
- return;
- }
-
- fprintf(stderr, "*%s: Error %#x\n", __func__, rv);
- exit(update_error);
-}
-
-static struct signed_header_version ver19 = {
- .epoch = 0,
- .major = 0,
- .minor = 19,
-};
-
-static void generate_reset_request(struct transfer_descriptor *td)
-{
- size_t response_size;
- uint8_t response;
- uint16_t subcommand;
- uint8_t command_body[2]; /* Max command body size. */
- size_t command_body_size;
- uint32_t background_update_supported;
- const char *reset_type;
- int rv;
-
- if (protocol_version < 6) {
- if (td->ep_type == usb_xfer) {
- /*
- * Send a second stop request, which should reboot
- * without replying.
- */
- send_done(&td->uep);
- }
- /* Nothing we can do over /dev/tpm0 running versions below 6. */
- return;
- }
-
- /* RW version 0.0.19 and above has support for background updates. */
- background_update_supported = td->background_update_supported ||
- !a_newer_than_b(&ver19, &targ.shv[1]);
-
- /*
- * If this is an upstart request and there is support for background
- * updates, don't post a request now. The target should handle it on
- * the next reboot.
- */
- if (td->upstart_mode && background_update_supported)
- return;
-
- /*
- * If the user explicitly wants it or a reset is needed because h1
- * does not support background updates, request post reset instead of
- * immediate reset. In this case next time the target reboots, the h1
- * will reboot as well, and will consider running the uploaded code.
- *
- * In case target RW version is 19 or above, to reset the target the
- * host is supposed to send the command to enable the uploaded image
- * disabled by default.
- *
- * Otherwise the immediate reset command would suffice.
- */
- /* Most common case. */
- command_body_size = 0;
- response_size = 1;
- if (td->post_reset || td->upstart_mode) {
- subcommand = EXTENSION_POST_RESET;
- reset_type = "posted";
- } else if (background_update_supported) {
- subcommand = VENDOR_CC_TURN_UPDATE_ON;
- command_body_size = sizeof(command_body);
- command_body[0] = 0;
- command_body[1] = 100; /* Reset in 100 ms. */
- reset_type = "requested";
- } else {
- response_size = 0;
- subcommand = VENDOR_CC_IMMEDIATE_RESET;
- reset_type = "triggered";
- }
-
- rv = send_vendor_command(td, subcommand, command_body,
- command_body_size, &response, &response_size);
-
- if (rv) {
- fprintf(stderr, "*%s: Error %#x\n", __func__, rv);
- exit(update_error);
- }
- printf("reboot %s\n", reset_type);
-}
-
-/*
- * Machine output is formatted as "key=value", one key-value pair per line, and
- * parsed by other programs (e.g., debugd). The value part should be specified
- * in the printf-like way. For example:
- *
- * print_machine_output("date", "%d/%d/%d", 2018, 1, 1),
- *
- * which outputs this line in console:
- *
- * date=2018/1/1
- *
- * The key part should not contain '=' or newline. The value part may contain
- * special characters like spaces, quotes, brackets, but not newlines. The
- * newline character means end of value.
- *
- * Any output format change in this function may require similar changes on the
- * programs that are using this gsctool.
- */
-__attribute__((__format__(__printf__, 2, 3)))
-static void print_machine_output(const char *key, const char *format, ...)
-{
- va_list args;
-
- if (strchr(key, '=') != NULL || strchr(key, '\n') != NULL) {
- fprintf(stderr,
- "Error: key %s contains '=' or a newline character.\n",
- key);
- return;
- }
-
- if (strchr(format, '\n') != NULL) {
- fprintf(stderr,
- "Error: value format %s contains a newline character. "
- "\n",
- format);
- return;
- }
-
- va_start(args, format);
-
- printf("%s=", key);
- vprintf(format, args);
- printf("\n");
-
- va_end(args);
-}
-
-/*
- * Prints out the header, including FW versions and board IDs, of the given
- * image. Output in a machine-friendly format if show_machine_output is true.
- */
-static int show_headers_versions(const void *image, bool show_machine_output)
-{
- /*
- * There are 2 FW slots in an image, and each slot has 2 sections, RO
- * and RW. The 2 slots should have identical FW versions and board
- * IDs.
- */
- const struct {
- const char *name;
- uint32_t offset;
- } sections[] = {
- /* Slot A. */
- {"RO", CONFIG_RO_MEM_OFF},
- {"RW", CONFIG_RW_MEM_OFF},
- /* Slot B. */
- {"RO", CHIP_RO_B_MEM_OFF},
- {"RW", CONFIG_RW_B_MEM_OFF}
- };
- const size_t kNumSlots = 2;
- const size_t kNumSectionsPerSlot = 2;
-
- /*
- * String representation of FW version (<epoch>:<major>:<minor>), one
- * string for each FW section.
- */
- char ro_fw_ver[kNumSlots][MAX_FW_VER_LENGTH];
- char rw_fw_ver[kNumSlots][MAX_FW_VER_LENGTH];
-
- uint32_t dev_id0_[kNumSlots];
- uint32_t dev_id1_[kNumSlots];
- uint32_t print_devid = 0;
-
- struct board_id {
- uint32_t id;
- uint32_t mask;
- uint32_t flags;
- } bid[kNumSlots];
-
- char bid_string[kNumSlots][MAX_BOARD_ID_LENGTH];
-
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(sections); i++) {
- const struct SignedHeader *h =
- (const struct SignedHeader *)
- ((uintptr_t)image + sections[i].offset);
- const size_t slot_idx = i / kNumSectionsPerSlot;
-
- uint32_t cur_bid;
- size_t j;
-
- if (sections[i].name[1] == 'O') {
- /* RO. */
- snprintf(ro_fw_ver[slot_idx], MAX_FW_VER_LENGTH,
- "%d.%d.%d", h->epoch_, h->major_, h->minor_);
- /* No need to read board ID in an RO section. */
- continue;
- } else {
- /* RW. */
- snprintf(rw_fw_ver[slot_idx], MAX_FW_VER_LENGTH,
- "%d.%d.%d", h->epoch_, h->major_, h->minor_);
- }
-
- /*
- * For RW sections, retrieves the board ID fields' contents,
- * which are stored XORed with a padding value.
- */
- bid[slot_idx].id = h->board_id_type ^ SIGNED_HEADER_PADDING;
- bid[slot_idx].mask =
- h->board_id_type_mask ^ SIGNED_HEADER_PADDING;
- bid[slot_idx].flags = h->board_id_flags ^ SIGNED_HEADER_PADDING;
-
- dev_id0_[slot_idx] = h->dev_id0_;
- dev_id1_[slot_idx] = h->dev_id1_;
- /* Print the devid if any slot has a non-zero devid. */
- print_devid |= h->dev_id0_ | h->dev_id1_;
-
- /*
- * If board ID is a 4-uppercase-letter string (as it ought to
- * be), print it as 4 letters, otherwise print it as an 8-digit
- * hex.
- */
- cur_bid = bid[slot_idx].id;
- for (j = 0; j < sizeof(cur_bid); ++j)
- if (!isupper(((const char *)&cur_bid)[j]))
- break;
-
- if (j == sizeof(cur_bid)) {
- cur_bid = be32toh(cur_bid);
- snprintf(bid_string[slot_idx], MAX_BOARD_ID_LENGTH,
- "%.4s", (const char *)&cur_bid);
- } else {
- snprintf(bid_string[slot_idx], MAX_BOARD_ID_LENGTH,
- "%08x", cur_bid);
- }
- }
-
- if (show_machine_output) {
- print_machine_output("IMAGE_RO_FW_VER", "%s", ro_fw_ver[0]);
- print_machine_output("IMAGE_RW_FW_VER", "%s", rw_fw_ver[0]);
- print_machine_output("IMAGE_BID_STRING", "%s", bid_string[0]);
- print_machine_output("IMAGE_BID_MASK", "%08x", bid[0].mask);
- print_machine_output("IMAGE_BID_FLAGS", "%08x", bid[0].flags);
- } else {
- printf("RO_A:%s RW_A:%s[%s:%08x:%08x] ",
- ro_fw_ver[0], rw_fw_ver[0],
- bid_string[0], bid[0].mask, bid[0].flags);
- printf("RO_B:%s RW_B:%s[%s:%08x:%08x]\n",
- ro_fw_ver[1], rw_fw_ver[1],
- bid_string[1], bid[1].mask, bid[1].flags);
-
- if (print_devid) {
- printf("DEVID: 0x%08x 0x%08x", dev_id0_[0],
- dev_id1_[0]);
- /*
- * Only print the second devid if it's different.
- * Separate the devids with tabs, so it's easier to
- * read.
- */
- if (dev_id0_[0] != dev_id0_[1] ||
- dev_id1_[0] != dev_id1_[1])
- printf("\t\t\t\tDEVID_B: 0x%08x 0x%08x",
- dev_id0_[1], dev_id1_[1]);
- printf("\n");
- }
- }
-
- return 0;
-}
-
-/*
- * The default flag value will allow to run images built for any hardware
- * generation of a particular board ID.
- */
-#define DEFAULT_BOARD_ID_FLAG 0xff00
-static int parse_bid(const char *opt,
- struct board_id *bid,
- enum board_id_action *bid_action)
-{
- char *e;
- const char *param2;
- size_t param1_length;
-
- if (!opt) {
- *bid_action = bid_get;
- return 1;
- }
-
- /* Set it here to make bailing out easier later. */
- bid->flags = DEFAULT_BOARD_ID_FLAG;
-
- *bid_action = bid_set; /* Ignored by caller on errors. */
-
- /*
- * Pointer to the optional second component of the command line
- * parameter, when present - separated by a colon.
- */
- param2 = strchr(opt, ':');
- if (param2) {
- param1_length = param2 - opt;
- param2++;
- if (!*param2)
- return 0; /* Empty second parameter. */
- } else {
- param1_length = strlen(opt);
- }
-
- if (!param1_length)
- return 0; /* Colon is the first character of the string? */
-
- if (param1_length <= 4) {
- unsigned i;
-
- /* Input must be a symbolic board name. */
- bid->type = 0;
- for (i = 0; i < param1_length; i++)
- bid->type = (bid->type << 8) | opt[i];
- } else {
- bid->type = (uint32_t)strtoul(opt, &e, 0);
- if ((param2 && (*e != ':')) || (!param2 && *e))
- return 0;
- }
-
- if (param2) {
- bid->flags = (uint32_t)strtoul(param2, &e, 0);
- if (*e)
- return 0;
- }
-
- return 1;
-}
-
-/*
- * Reads a two-character hexadecimal byte from a string. If the string is
- * ill-formed, returns 0. Otherwise, |byte| contains the byte value and the
- * return value is non-zero.
- */
-static int read_hex_byte(const char* s, uint8_t* byte) {
- uint8_t b = 0;
- for (const char* end = s + 2; s < end; ++s) {
- if (*s >= '0' && *s <= '9')
- b = b * 16 + *s - '0';
- else if (*s >= 'A' && *s <= 'F')
- b = b * 16 + 10 + *s - 'A';
- else if (*s >= 'a' && *s <= 'f')
- b = b * 16 + 10 + *s - 'a';
- else
- return 0;
- }
- *byte = b;
- return 1;
-}
-
-static int parse_sn_bits(const char *opt, uint8_t *sn_bits)
-{
- size_t len = strlen(opt);
-
- if (!strncmp(opt, "0x", 2)) {
- opt += 2;
- len -= 2;
- }
- if (len != SN_BITS_SIZE * 2) return 0;
-
- for (int i = 0; i < SN_BITS_SIZE; ++i, opt +=2)
- if (!read_hex_byte(opt, sn_bits++)) return 0;
-
- return 1;
-}
-
-static int parse_sn_inc_rma(const char *opt, uint8_t *arg)
-{
- uint32_t inc;
- char *e;
-
- inc = (uint32_t)strtoul(opt, &e, 0);
-
- if (opt == e || *e != '\0' || inc > 7)
- return 0;
-
- *arg = inc;
- return 1;
-}
-
-static uint32_t common_process_password(struct transfer_descriptor *td,
- enum ccd_vendor_subcommands subcmd)
-{
- size_t response_size;
- uint8_t response;
- uint32_t rv;
- char *password = NULL;
- char *password_copy = NULL;
- size_t copy_len = 0;
- size_t len = 0;
- struct termios oldattr, newattr;
-
- /* Suppress command line echo while password is being entered. */
- tcgetattr(STDIN_FILENO, &oldattr);
- newattr = oldattr;
- newattr.c_lflag &= ~ECHO;
- newattr.c_lflag |= (ICANON | ECHONL);
- tcsetattr(STDIN_FILENO, TCSANOW, &newattr);
-
- /* With command line echo suppressed request password entry twice. */
- printf("Enter password:");
- len = getline(&password, &len, stdin);
- printf("Re-enter password:");
- getline(&password_copy, &copy_len, stdin);
-
- /* Restore command line echo. */
- tcsetattr(STDIN_FILENO, TCSANOW, &oldattr);
-
- /* Empty password will still have the newline. */
- if ((len <= 1) || !password_copy) {
- if (password)
- free(password);
- if (password_copy)
- free(password_copy);
- fprintf(stderr, "Error reading password\n");
- exit(update_error);
- }
-
- /* Compare the two inputs. */
- if (strcmp(password, password_copy)) {
- fprintf(stderr, "Entered passwords don't match\n");
- free(password);
- free(password_copy);
- exit(update_error);
- }
-
- /*
- * Ok, we have a password, let's move it in the buffer to overwrite
- * the newline and free a byte to prepend the subcommand code.
- */
- memmove(password + 1, password, len - 1);
- password[0] = subcmd;
- response_size = sizeof(response);
- rv = send_vendor_command(td, VENDOR_CC_CCD,
- password, len,
- &response, &response_size);
- free(password);
- free(password_copy);
-
- if ((rv != VENDOR_RC_SUCCESS) && (rv != VENDOR_RC_IN_PROGRESS))
- fprintf(stderr, "Error sending password: rv %d, response %d\n",
- rv, response_size ? response : 0);
-
- return rv;
-}
-
-static void process_password(struct transfer_descriptor *td)
-{
- if (common_process_password(td, CCDV_PASSWORD) == VENDOR_RC_SUCCESS)
- return;
-
- exit(update_error);
-}
-
-void poll_for_pp(struct transfer_descriptor *td,
- uint16_t command,
- uint8_t poll_type)
-{
- uint8_t response;
- uint8_t prev_response;
- size_t response_size;
- int rv;
-
- prev_response = ~0; /* Guaranteed invalid value. */
-
- while (1) {
- response_size = sizeof(response);
- rv = send_vendor_command(td, command,
- &poll_type, sizeof(poll_type),
- &response, &response_size);
-
- if (((rv != VENDOR_RC_SUCCESS) && (rv != VENDOR_RC_IN_PROGRESS))
- || (response_size != 1)) {
- fprintf(stderr, "Error: rv %d, response %d\n",
- rv, response_size ? response : 0);
- exit(update_error);
- }
-
- if (response == CCD_PP_DONE) {
- printf("PP Done!\n");
- return;
- }
-
- if (response == CCD_PP_CLOSED) {
- fprintf(stderr,
- "Error: Physical presence check timeout!\n");
- exit(update_error);
- }
-
-
- if (response == CCD_PP_AWAITING_PRESS) {
- printf("Press PP button now!\n");
- } else if (response == CCD_PP_BETWEEN_PRESSES) {
- if (prev_response != response)
- printf("Another press will be required!\n");
- } else {
- fprintf(stderr, "Error: unknown poll result %d\n",
- response);
- exit(update_error);
- }
- prev_response = response;
-
- usleep(500 * 1000); /* Poll every half a second. */
- }
-
-}
-
-static void print_ccd_info(void *response, size_t response_size)
-{
- struct ccd_info_response ccd_info;
- size_t i;
- const struct ccd_capability_info cap_info[] = CAP_INFO_DATA;
- const char *state_names[] = CCD_STATE_NAMES;
- const char *cap_state_names[] = CCD_CAP_STATE_NAMES;
- uint32_t caps_bitmap = 0;
-
- if (response_size != sizeof(ccd_info)) {
- fprintf(stderr, "Unexpected CCD info response size %zd\n",
- response_size);
- exit(update_error);
- }
-
- memcpy(&ccd_info, response, sizeof(ccd_info));
-
- /* Convert it back to host endian format. */
- ccd_info.ccd_flags = be32toh(ccd_info.ccd_flags);
- for (i = 0; i < ARRAY_SIZE(ccd_info.ccd_caps_current); i++) {
- ccd_info.ccd_caps_current[i] =
- be32toh(ccd_info.ccd_caps_current[i]);
- ccd_info.ccd_caps_defaults[i] =
- be32toh(ccd_info.ccd_caps_defaults[i]);
- }
-
- /* Now report CCD state on the console. */
- printf("State: %s\n", ccd_info.ccd_state > ARRAY_SIZE(state_names) ?
- "Error" : state_names[ccd_info.ccd_state]);
- printf("Password: %s\n", (ccd_info.ccd_indicator_bitmap &
- CCD_INDICATOR_BIT_HAS_PASSWORD) ? "Set" : "None");
- printf("Flags: %#06x\n", ccd_info.ccd_flags);
- printf("Capabilities, current and default:\n");
- for (i = 0; i < CCD_CAP_COUNT; i++) {
- int is_enabled;
- int index;
- int shift;
- int cap_current;
- int cap_default;
-
- index = i / (32 / CCD_CAP_BITS);
- shift = (i % (32 / CCD_CAP_BITS)) * CCD_CAP_BITS;
-
- cap_current = (ccd_info.ccd_caps_current[index] >> shift)
- & CCD_CAP_BITMASK;
- cap_default = (ccd_info.ccd_caps_defaults[index] >> shift)
- & CCD_CAP_BITMASK;
-
- if (ccd_info.ccd_force_disabled) {
- is_enabled = 0;
- } else {
- switch (cap_current) {
- case CCD_CAP_STATE_ALWAYS:
- is_enabled = 1;
- break;
- case CCD_CAP_STATE_UNLESS_LOCKED:
- is_enabled = (ccd_info.ccd_state !=
- CCD_STATE_LOCKED);
- break;
- default:
- is_enabled = (ccd_info.ccd_state ==
- CCD_STATE_OPENED);
- break;
- }
- }
-
- printf(" %-15s %c %s",
- cap_info[i].name,
- is_enabled ? 'Y' : '-',
- cap_state_names[cap_current]);
-
- if (cap_current != cap_default)
- printf(" (%s)", cap_state_names[cap_default]);
-
- printf("\n");
-
- if (is_enabled)
- caps_bitmap |= (1 << i);
- }
- printf("CCD caps bitmap: %#x\n", caps_bitmap);
- printf("Capabilities are %s.\n", (ccd_info.ccd_indicator_bitmap &
- CCD_INDICATOR_BIT_ALL_CAPS_DEFAULT) ? "default" : "modified");
-}
-
-static void process_ccd_state(struct transfer_descriptor *td, int ccd_unlock,
- int ccd_open, int ccd_lock, int ccd_info)
-{
- uint8_t payload;
- /* Max possible response size is when ccd_info is requested. */
- uint8_t response[sizeof(struct ccd_info_response)];
- size_t response_size;
- int rv;
-
- if (ccd_unlock)
- payload = CCDV_UNLOCK;
- else if (ccd_open)
- payload = CCDV_OPEN;
- else if (ccd_lock)
- payload = CCDV_LOCK;
- else
- payload = CCDV_GET_INFO;
-
- response_size = sizeof(response);
- rv = send_vendor_command(td, VENDOR_CC_CCD,
- &payload, sizeof(payload),
- &response, &response_size);
-
- /*
- * If password is required - try sending the same subcommand
- * accompanied by user password.
- */
- if (rv == VENDOR_RC_PASSWORD_REQUIRED)
- rv = common_process_password(td, payload);
-
- if (rv == VENDOR_RC_SUCCESS) {
- if (ccd_info)
- print_ccd_info(response, response_size);
- return;
- }
-
- if (rv != VENDOR_RC_IN_PROGRESS) {
- fprintf(stderr, "Error: rv %d, response %d\n",
- rv, response_size ? response[0] : 0);
- exit(update_error);
- }
-
- /*
- * Physical presence process started, poll for the state the user
- * asked for. Only two subcommands would return 'IN_PROGRESS'.
- */
- if (ccd_unlock)
- poll_for_pp(td, VENDOR_CC_CCD, CCDV_PP_POLL_UNLOCK);
- else
- poll_for_pp(td, VENDOR_CC_CCD, CCDV_PP_POLL_OPEN);
-}
-
-static void process_wp(struct transfer_descriptor *td)
-{
- size_t response_size;
- uint8_t response;
- int rv = 0;
-
- response_size = sizeof(response);
-
- printf("Getting WP\n");
-
- rv = send_vendor_command(td, VENDOR_CC_WP, NULL, 0,
- &response, &response_size);
- if (rv != VENDOR_RC_SUCCESS) {
- fprintf(stderr, "Error %d getting write protect\n", rv);
- exit(update_error);
- }
- if (response_size != sizeof(response)) {
- fprintf(stderr, "Unexpected response size %zd while getting "
- "write protect\n",
- response_size);
- exit(update_error);
- }
-
- printf("WP: %08x\n", response);
- printf("Flash WP: %s%s\n",
- response & WPV_FORCE ? "forced " : "",
- response & WPV_ENABLE ? "enabled" : "disabled");
- printf(" at boot: %s\n",
- !(response & WPV_ATBOOT_SET) ? "follow_batt_pres" :
- response & WPV_ATBOOT_ENABLE ? "forced enabled" :
- "forced disabled");
-}
-
-
-void process_bid(struct transfer_descriptor *td,
- enum board_id_action bid_action,
- struct board_id *bid,
- bool show_machine_output)
-{
- size_t response_size;
-
- if (bid_action == bid_get) {
-
- response_size = sizeof(*bid);
- send_vendor_command(td, VENDOR_CC_GET_BOARD_ID,
- bid, sizeof(*bid),
- bid, &response_size);
-
- if (response_size != sizeof(*bid)) {
- fprintf(stderr,
- "Error reading board ID: response size %zd, "
- "first byte %#02x\n",
- response_size,
- response_size ? *(uint8_t *)&bid : -1);
- exit(update_error);
- }
-
- if (show_machine_output) {
- print_machine_output(
- "BID_TYPE", "%08x", be32toh(bid->type));
- print_machine_output(
- "BID_TYPE_INV", "%08x", be32toh(bid->type_inv));
- print_machine_output(
- "BID_FLAGS", "%08x", be32toh(bid->flags));
-
- for (int i = 0; i < 4; i++) {
- if (!isupper(((const char *)bid)[i])) {
- print_machine_output(
- "BID_RLZ", "%s", "????");
- return;
- }
- }
-
- print_machine_output(
- "BID_RLZ", "%c%c%c%c",
- ((const char *)bid)[0],
- ((const char *)bid)[1],
- ((const char *)bid)[2],
- ((const char *)bid)[3]);
- } else {
- printf("Board ID space: %08x:%08x:%08x\n",
- be32toh(bid->type),
- be32toh(bid->type_inv),
- be32toh(bid->flags));
-
- }
-
- return;
- }
-
- if (bid_action == bid_set) {
- /* Sending just two fields: type and flags. */
- uint32_t command_body[2];
- uint8_t response;
-
- command_body[0] = htobe32(bid->type);
- command_body[1] = htobe32(bid->flags);
-
- response_size = sizeof(command_body);
- send_vendor_command(td, VENDOR_CC_SET_BOARD_ID,
- command_body, sizeof(command_body),
- command_body, &response_size);
-
- /*
- * Speculative assignment: the response is expected to be one
- * byte in size and be placed in the first byte of the buffer.
- */
- response = *((uint8_t *)command_body);
-
- if (response_size == 1) {
- if (!response)
- return; /* Success! */
-
- fprintf(stderr, "Error %d while setting board id\n",
- response);
- } else {
- fprintf(stderr, "Unexpected response size %zd"
- " while setting board id\n",
- response_size);
- }
- exit(update_error);
- }
-}
-
-static void process_sn_bits(struct transfer_descriptor *td,
- uint8_t *sn_bits)
-{
- int rv;
- uint8_t response_code;
- size_t response_size = sizeof(response_code);
-
- rv = send_vendor_command(td, VENDOR_CC_SN_SET_HASH,
- sn_bits, SN_BITS_SIZE,
- &response_code, &response_size);
-
- if (rv) {
- fprintf(stderr, "Error %d while sending vendor command\n", rv);
- exit(update_error);
- }
-
- if (response_size != 1) {
- fprintf(stderr,
- "Unexpected response size while setting sn bits\n");
- exit(update_error);
- }
-
- if (response_code != 0) {
- fprintf(stderr, "Error %d while setting sn bits\n",
- response_code);
- exit(update_error);
- }
-}
-
-static void process_sn_inc_rma(struct transfer_descriptor *td,
- uint8_t arg)
-{
- int rv;
- uint8_t response_code;
- size_t response_size = sizeof(response_code);
-
- rv = send_vendor_command(td, VENDOR_CC_SN_INC_RMA,
- &arg, sizeof(arg),
- &response_code, &response_size);
- if (rv) {
- fprintf(stderr, "Error %d while sending vendor command\n", rv);
- exit(update_error);
- }
-
- if (response_size != 1) {
- fprintf(stderr,
- "Unexpected response size while "
- "incrementing sn rma count\n");
- exit(update_error);
- }
-
- if (response_code != 0) {
- fprintf(stderr, "Error %d while incrementing rma count\n",
- response_code);
- exit(update_error);
- }
-}
-
-/* Get/Set the primary seed of the info1 manufacture state. */
-static int process_endorsement_seed(struct transfer_descriptor *td,
- const char *endorsement_seed_str)
-{
- uint8_t endorsement_seed[32];
- uint8_t response_seed[32];
- size_t seed_size = sizeof(endorsement_seed);
- size_t response_size = sizeof(response_seed);
- size_t i;
- int rv;
-
- if (!endorsement_seed_str) {
- rv = send_vendor_command(td, VENDOR_CC_ENDORSEMENT_SEED, NULL,
- 0, response_seed, &response_size);
- if (rv) {
- fprintf(stderr, "Error sending vendor command %d\n",
- rv);
- return update_error;
- }
- printf("Endorsement key seed: ");
- for (i = 0; i < response_size; i++)
- printf("%02x", response_seed[i]);
- printf("\n");
- return 0;
- }
- if (seed_size * 2 != strlen(endorsement_seed_str)) {
- printf("Invalid seed %s\n", endorsement_seed_str);
- return update_error;
- }
-
- for (i = 0; i < seed_size; i++) {
- int nibble;
- char c;
-
- c = endorsement_seed_str[2 * i];
- nibble = from_hexascii(c);
- if (nibble < 0) {
- fprintf(stderr, "Error: Non hex character in seed %c\n",
- c);
- return update_error;
- }
- endorsement_seed[i] = nibble << 4;
-
- c = endorsement_seed_str[2 * i + 1];
- nibble = from_hexascii(c);
- if (nibble < 0) {
- fprintf(stderr, "Error: Non hex character in seed %c\n",
- c);
- return update_error;
- }
- endorsement_seed[i] |= nibble;
- }
-
- printf("Setting seed: %s\n", endorsement_seed_str);
- rv = send_vendor_command(td, VENDOR_CC_ENDORSEMENT_SEED,
- endorsement_seed, seed_size,
- response_seed, &response_size);
- if (rv == VENDOR_RC_NOT_ALLOWED) {
- fprintf(stderr, "Seed already set\n");
- return update_error;
- }
- if (rv) {
- fprintf(stderr, "Error sending vendor command %d\n", rv);
- return update_error;
- }
- printf("Updated endorsement key seed.\n");
- return 0;
-}
-
-/*
- * Retrieve the RMA authentication challenge from the Cr50, print out the
- * challenge on the console, then prompt the user for the authentication code,
- * and send the code back to Cr50. The Cr50 would report if the code matched
- * its expectations or not.
- */
-static void process_rma(struct transfer_descriptor *td, const char *authcode)
-{
- char rma_response[81];
- size_t response_size = sizeof(rma_response);
- size_t i;
- size_t auth_size = 0;
-
- if (!authcode) {
- send_vendor_command(td, VENDOR_CC_RMA_CHALLENGE_RESPONSE,
- NULL, 0, rma_response, &response_size);
-
- if (response_size == 1) {
- fprintf(stderr, "error %d\n", rma_response[0]);
- if (td->ep_type == usb_xfer)
- shut_down(&td->uep);
- exit(update_error);
- }
-
- printf("Challenge:");
- for (i = 0; i < response_size; i++) {
- if (!(i % 5)) {
- if (!(i % 40))
- printf("\n");
- printf(" ");
- }
- printf("%c", rma_response[i]);
- }
- printf("\n");
- return;
- }
-
- if (!*authcode) {
- printf("Empty response.\n");
- exit(update_error);
- return;
- }
-
- if (!strcmp(authcode, "disable")) {
- printf("Invalid arg. Try using 'gsctool -F disable'\n");
- exit(update_error);
- return;
- }
-
- printf("Processing response...\n");
- auth_size = strlen(authcode);
- response_size = sizeof(rma_response);
-
- send_vendor_command(td, VENDOR_CC_RMA_CHALLENGE_RESPONSE,
- authcode, auth_size,
- rma_response, &response_size);
-
- if (response_size == 1) {
- fprintf(stderr, "\nrma unlock failed, code %d ",
- *rma_response);
- switch (*rma_response) {
- case VENDOR_RC_BOGUS_ARGS:
- fprintf(stderr, "(wrong authcode size)\n");
- break;
- case VENDOR_RC_INTERNAL_ERROR:
- fprintf(stderr, "(authcode mismatch)\n");
- break;
- default:
- fprintf(stderr, "(unknown error)\n");
- break;
- }
- if (td->ep_type == usb_xfer)
- shut_down(&td->uep);
- exit(update_error);
- }
- printf("RMA unlock succeeded.\n");
-}
-
-/*
- * Enable or disable factory mode. Factory mode will only be enabled if HW
- * write protect is removed.
- */
-static void process_factory_mode(struct transfer_descriptor *td,
- const char *arg)
-{
- uint8_t rma_response;
- size_t response_size = sizeof(rma_response);
- char *cmd_str;
- int rv;
- uint16_t subcommand;
-
- if (!strcasecmp(arg, "disable")) {
- subcommand = VENDOR_CC_DISABLE_FACTORY;
- cmd_str = "dis";
- } else if (!strcasecmp(arg, "enable")) {
- subcommand = VENDOR_CC_RESET_FACTORY;
- cmd_str = "en";
-
- } else {
- fprintf(stderr, "Invalid factory mode arg %s", arg);
- exit(update_error);
- }
-
- printf("%sabling factory mode\n", cmd_str);
- rv = send_vendor_command(td, subcommand, NULL, 0, &rma_response,
- &response_size);
- if (rv) {
- fprintf(stderr, "Failed %sabling factory mode\nvc error "
- "%d\n", cmd_str, rv);
- if (response_size == 1)
- fprintf(stderr, "ec error %d\n", rma_response);
- exit(update_error);
- }
- printf("Factory %sable succeeded.\n", cmd_str);
-}
-
-static void report_version(void)
-{
- /* Get version from the generated file, ignore the underscore prefix. */
- const char *v = strchr(VERSION, '_');
-
- printf("Version: %s, built on %s by %s\n", v ? v + 1 : "?",
- DATE, BUILDER);
- exit(0);
-}
-
-/*
- * Either change or query TPM mode value.
- */
-static int process_tpm_mode(struct transfer_descriptor *td,
- const char *arg)
-{
- int rv;
- size_t command_size;
- size_t response_size;
- uint8_t response;
- uint8_t command_body;
-
- response_size = sizeof(response);
- if (!arg) {
- command_size = 0;
- } else if (!strcasecmp(arg, "disable")) {
- command_size = sizeof(command_body);
- command_body = (uint8_t) TPM_MODE_DISABLED;
- } else if (!strcasecmp(arg, "enable")) {
- command_size = sizeof(command_body);
- command_body = (uint8_t) TPM_MODE_ENABLED;
- } else {
- fprintf(stderr, "Invalid tpm mode arg: %s.\n", arg);
- return update_error;
- }
-
- rv = send_vendor_command(td, VENDOR_CC_TPM_MODE,
- &command_body, command_size,
- &response, &response_size);
- if (rv) {
- fprintf(stderr, "Error %d in setting TPM mode.\n", rv);
- return update_error;
- }
- if (response_size != sizeof(response)) {
- fprintf(stderr, "Error in the size of response,"
- " %zu.\n", response_size);
- return update_error;
- }
- if (response >= TPM_MODE_MAX) {
- fprintf(stderr, "Error in the value of response,"
- " %d.\n", response);
- return update_error;
- }
-
- printf("TPM Mode: %s (%d)\n", (response == TPM_MODE_DISABLED) ?
- "disabled" : "enabled", response);
-
- return rv;
-}
-
-/*
- * Retrieve from H1 flash log entries which are newer than the passed in
- * timestamp.
- *
- * On error retry a few times just in case flash log is locked by a concurrent
- * access.
- */
-static int process_get_flog(struct transfer_descriptor *td, uint32_t prev_stamp)
-{
- int rv;
- const int max_retries = 3;
- int retries = max_retries;
-
- while (retries--) {
- union entry_u entry;
- size_t resp_size;
- size_t i;
-
- resp_size = sizeof(entry);
- rv = send_vendor_command(td, VENDOR_CC_POP_LOG_ENTRY,
- &prev_stamp, sizeof(prev_stamp),
- &entry, &resp_size);
-
- if (rv) {
- /*
- * Flash log could be momentarily locked by a
- * concurrent access, let it settle and try again, 10
- * ms should be enough.
- */
- usleep(10 * 1000);
- continue;
- }
-
- if (resp_size == 0)
- /* No more entries. */
- return 0;
-
- memcpy(&prev_stamp, &entry.r.timestamp, sizeof(prev_stamp));
- printf("%10u:%02x", prev_stamp, entry.r.type);
- for (i = 0; i < FLASH_LOG_PAYLOAD_SIZE(entry.r.size); i++)
- printf(" %02x", entry.r.payload[i]);
- printf("\n");
- retries = max_retries;
- }
-
- fprintf(stderr, "%s: error %d\n", __func__, rv);
-
- return rv;
-}
-
-static int process_tstamp(struct transfer_descriptor *td,
- const char *tstamp_ascii)
-{
- char *e;
- size_t expected_response_size;
- size_t message_size;
- size_t response_size;
- uint32_t rv;
- uint32_t tstamp = 0;
- uint8_t max_response[sizeof(uint32_t)];
-
- if (tstamp_ascii) {
- tstamp = strtoul(tstamp_ascii, &e, 10);
- if (*e) {
- fprintf(stderr, "invalid base timestamp value \"%s\"\n",
- tstamp_ascii);
- return -1;
- }
- tstamp = htobe32(tstamp);
- expected_response_size = 0;
- message_size = sizeof(tstamp);
- } else {
- expected_response_size = 4;
- message_size = 0;
- }
-
- response_size = sizeof(max_response);
- rv = send_vendor_command(td, VENDOR_CC_FLOG_TIMESTAMP, &tstamp,
- message_size, max_response, &response_size);
-
- if (rv) {
- fprintf(stderr, "error: return value %d\n", rv);
- return rv;
- }
- if (response_size != expected_response_size) {
- fprintf(stderr, "error: got %zd bytes, expected %zd\n",
- response_size, expected_response_size);
- return -1; /* Should never happen. */
- }
-
- if (response_size) {
- memcpy(&tstamp, max_response, sizeof(tstamp));
- printf("Current H1 time is %d\n", be32toh(tstamp));
- }
- return 0;
-}
-
-/*
- * Search the passed in zero terminated array of options_map structures for
- * option 'option'.
- *
- * If found - set the corresponding integer to 1 and return 1. If not found -
- * return 0.
- */
-static int check_boolean(const struct options_map *omap, char option)
-{
- do {
- if (omap->opt != option)
- continue;
-
- *omap->flag = 1;
- return 1;
- } while ((++omap)->opt);
-
- return 0;
-}
-
-/*
- * Set the long_opts table and short_opts string.
- *
- * This function allows to avoid maintaining two command line option
- * descriptions, for short and long forms.
- *
- * The long_opts table is built based on the cmd_line_options table contents,
- * and the short form is built based on the long_opts table contents.
- *
- * The 'required_argument' short options are followed by ':'.
- *
- * The passed in long_opts array and short_opts string are guaranteed to
- * accommodate all necessary objects/characters.
- */
-static void set_opt_descriptors(struct option *long_opts, char *short_opts)
-{
- size_t i;
- int j;
-
- for (i = j = 0; i < ARRAY_SIZE(cmd_line_options); i++) {
- long_opts[i] = cmd_line_options[i].opt;
- short_opts[j++] = long_opts[i].val;
- if (long_opts[i].has_arg == required_argument)
- short_opts[j++] = ':';
- }
-}
-
-/*
- * Find the long_opts table index where .val field is set to the passed in
- * short option value.
- */
-static int get_longindex(int short_opt, const struct option *long_opts)
-{
- int i;
-
- for (i = 0; long_opts[i].name; i++)
- if (long_opts[i].val == short_opt)
- return i;
-
- /*
- * We could never come here as the short options list is compiled
- * based on long options table.
- */
- fprintf(stderr, "could not find long opt table index for %d\n",
- short_opt);
- exit(1);
-
- return -1; /* Not reached. */
-}
-
-/*
- * Combine searching for command line parameters and optional arguments.
- *
- * The canonical short options description string does not allow to specify
- * that a command line argument expects an optional parameter. but gsctool
- * users expect to be able to use the following styles for optional
- * parameters:
- *
- * a) -x <param value>
- * b) --x_long <param_value>
- * c) --x_long=<param_value>
- *
- * Styles a) and b) are not supported standard getopt_long(), this function
- * adds ability to handle cases a) and b).
- */
-static int getopt_all(int argc, char *argv[])
-{
- int longindex = -1;
- static char short_opts[2 * ARRAY_SIZE(cmd_line_options)] = {};
- static struct option long_opts[ARRAY_SIZE(cmd_line_options) + 1] = {};
- int i;
-
- if (!short_opts[0])
- set_opt_descriptors(long_opts, short_opts);
-
- i = getopt_long(argc, argv, short_opts, long_opts, &longindex);
- if (i != -1) {
-
- if (longindex < 0) {
- /*
- * longindex is not set, this must have been the short
- * option case, Find the long_opts table index based
- * on the short option value.
- */
- longindex = get_longindex(i, long_opts);
- }
-
- if (long_opts[longindex].has_arg == optional_argument) {
- /*
- * This command line option may include an argument,
- * let's check if it is there as the next token in the
- * command line.
- */
- if (!optarg && argv[optind] && argv[optind][0] != '-')
- /* Yes, it is. */
- optarg = argv[optind++];
- }
- }
-
- return i;
-}
-
-int main(int argc, char *argv[])
-{
- struct transfer_descriptor td;
- int errorcnt;
- uint8_t *data = 0;
- size_t data_len = 0;
- uint16_t vid = 0;
- uint16_t pid = 0;
- int i;
- size_t j;
- int transferred_sections = 0;
- int binary_vers = 0;
- int show_fw_ver = 0;
- int rma = 0;
- const char *rma_auth_code;
- int get_endorsement_seed = 0;
- const char *endorsement_seed_str;
- int corrupt_inactive_rw = 0;
- struct board_id bid;
- enum board_id_action bid_action;
- int password = 0;
- int ccd_open = 0;
- int ccd_unlock = 0;
- int ccd_lock = 0;
- int ccd_info = 0;
- int get_flog = 0;
- uint32_t prev_log_entry = 0;
- int wp = 0;
- int try_all_transfer = 0;
- int tpm_mode = 0;
- bool show_machine_output = false;
- int tstamp = 0;
- const char *tstamp_arg = NULL;
-
- const char *exclusive_opt_error =
- "Options -a, -s and -t are mutually exclusive\n";
- const char *openbox_desc_file = NULL;
- int factory_mode = 0;
- char *factory_mode_arg;
- char *tpm_mode_arg = NULL;
- char *serial = NULL;
- int sn_bits = 0;
- uint8_t sn_bits_arg[SN_BITS_SIZE];
- int sn_inc_rma = 0;
- uint8_t sn_inc_rma_arg;
-
- /*
- * All options which result in setting a Boolean flag to True, along
- * with addresses of the flags. Terminated by a zeroed entry.
- */
- const struct options_map omap[] = {
- { 'B', &td.background_update_supported},
- { 'b', &binary_vers },
- { 'c', &corrupt_inactive_rw },
- { 'f', &show_fw_ver },
- { 'I', &ccd_info },
- { 'k', &ccd_lock },
- { 'o', &ccd_open },
- { 'P', &password },
- { 'p', &td.post_reset },
- { 'U', &ccd_unlock },
- { 'u', &td.upstart_mode },
- { 'V', &verbose_mode },
- { 'w', &wp },
- {},
- };
-
- /*
- * Explicitly sets buffering type to line buffered so that output
- * lines can be written to pipe instantly. This is needed when the
- * cr50-verify-ro.sh execution in verify_ro is moved from crosh to
- * debugd.
- */
- setlinebuf(stdout);
-
- progname = strrchr(argv[0], '/');
- if (progname)
- progname++;
- else
- progname = argv[0];
-
- /* Usb transfer - default mode. */
- memset(&td, 0, sizeof(td));
- td.ep_type = usb_xfer;
-
- bid_action = bid_none;
- errorcnt = 0;
- opterr = 0; /* quiet, you */
-
- while ((i = getopt_all(argc, argv)) != -1) {
- if (check_boolean(omap, i))
- continue;
- switch (i) {
- case 'a':
- if (td.ep_type) {
- errorcnt++;
- fprintf(stderr, "%s", exclusive_opt_error);
- break;
- }
- try_all_transfer = 1;
- /* Try dev_xfer first. */
- td.ep_type = dev_xfer;
- break;
- case 'd':
- if (!parse_vidpid(optarg, &vid, &pid)) {
- fprintf(stderr,
- "Invalid device argument: \"%s\"\n",
- optarg);
- errorcnt++;
- }
- break;
- case 'e':
- get_endorsement_seed = 1;
- endorsement_seed_str = optarg;
- break;
- case 'F':
- factory_mode = 1;
- factory_mode_arg = optarg;
- break;
- case 'h':
- usage(errorcnt);
- break;
- case 'i':
- if (!parse_bid(optarg, &bid, &bid_action)) {
- fprintf(stderr,
- "Invalid board id argument: \"%s\"\n",
- optarg);
- errorcnt++;
- }
- break;
- case 'L':
- get_flog = 1;
- if (optarg)
- prev_log_entry = strtoul(optarg, NULL, 0);
- break;
- case 'M':
- show_machine_output = true;
- break;
- case 'm':
- tpm_mode = 1;
- tpm_mode_arg = optarg;
- break;
- case 'n':
- serial = optarg;
- break;
- case 'O':
- openbox_desc_file = optarg;
- break;
- case 'q':
- td.force_ro = 1;
- break;
- case 'r':
- rma = 1;
- rma_auth_code = optarg;
- break;
- case 'R':
- sn_inc_rma = 1;
- if (!parse_sn_inc_rma(optarg, &sn_inc_rma_arg)) {
- fprintf(stderr,
- "Invalid sn_rma_inc argument: \"%s\"\n",
- optarg);
- errorcnt++;
- }
-
- break;
- case 's':
- if (td.ep_type || try_all_transfer) {
- errorcnt++;
- fprintf(stderr, "%s", exclusive_opt_error);
- break;
- }
- td.ep_type = dev_xfer;
- break;
- case 'S':
- sn_bits = 1;
- if (!parse_sn_bits(optarg, sn_bits_arg)) {
- fprintf(stderr,
- "Invalid sn_bits argument: \"%s\"\n",
- optarg);
- errorcnt++;
- }
-
- break;
- case 't':
- if (td.ep_type || try_all_transfer) {
- errorcnt++;
- fprintf(stderr, "%s", exclusive_opt_error);
- break;
- }
- td.ep_type = ts_xfer;
- break;
- case 'T':
- tstamp = 1;
- tstamp_arg = optarg;
- break;
- case 'v':
- report_version(); /* This will call exit(). */
- break;
- case 0: /* auto-handled option */
- break;
- case '?':
- if (optopt)
- fprintf(stderr, "Unrecognized option: -%c\n",
- optopt);
- else
- fprintf(stderr, "Unrecognized option: %s\n",
- argv[optind - 1]);
- errorcnt++;
- break;
- case ':':
- fprintf(stderr, "Missing argument to %s\n",
- argv[optind - 1]);
- errorcnt++;
- break;
- default:
- fprintf(stderr, "Internal error at %s:%d\n",
- __FILE__, __LINE__);
- exit(update_error);
- }
- }
-
- if (errorcnt)
- usage(errorcnt);
-
- /*
- * If no usb device information was given, default to the using cr50
- * vendor and product id to find the usb device.
- */
- if (!serial && !vid && !pid) {
- vid = VID;
- pid = PID;
- }
-
- if ((bid_action == bid_none) &&
- !ccd_info &&
- !ccd_lock &&
- !ccd_open &&
- !ccd_unlock &&
- !corrupt_inactive_rw &&
- !get_flog &&
- !get_endorsement_seed &&
- !factory_mode &&
- !password &&
- !rma &&
- !show_fw_ver &&
- !sn_bits &&
- !sn_inc_rma &&
- !openbox_desc_file &&
- !tstamp &&
- !tpm_mode &&
- !wp) {
- if (optind >= argc) {
- fprintf(stderr,
- "\nERROR: Missing required <binary image>\n\n");
- usage(1);
- }
-
- data = get_file_or_die(argv[optind], &data_len);
- printf("read %zd(%#zx) bytes from %s\n",
- data_len, data_len, argv[optind]);
- if (data_len != CONFIG_FLASH_SIZE) {
- fprintf(stderr, "Image file is not %d bytes\n",
- CONFIG_FLASH_SIZE);
- exit(update_error);
- }
-
- fetch_header_versions(data);
-
- if (binary_vers)
- exit(show_headers_versions(data, show_machine_output));
- } else {
- if (optind < argc)
- printf("Ignoring binary image %s\n", argv[optind]);
- }
-
-
- if (((bid_action != bid_none) + !!rma + !!password + !!ccd_open +
- !!ccd_unlock + !!ccd_lock + !!ccd_info + !!get_flog +
- !!openbox_desc_file + !!factory_mode + !!wp +
- !!get_endorsement_seed) > 1) {
- fprintf(stderr,
- "ERROR: options"
- "-e, -F, -I, -i, -k, -L, -O, -o, -P, -r, -U and -w "
- "are mutually exclusive\n");
- exit(update_error);
- }
-
- if (td.ep_type == usb_xfer) {
- if (usb_findit(serial, vid, pid, USB_SUBCLASS_GOOGLE_CR50,
- USB_PROTOCOL_GOOGLE_CR50_NON_HC_FW_UPDATE,
- &td.uep))
- exit(update_error);
- } else if (td.ep_type == dev_xfer) {
- td.tpm_fd = open("/dev/tpm0", O_RDWR);
- if (td.tpm_fd < 0) {
- if (!try_all_transfer) {
- perror("Could not open TPM");
- exit(update_error);
- }
- td.ep_type = ts_xfer;
- }
- }
-
- if (openbox_desc_file)
- return verify_ro(&td, openbox_desc_file, show_machine_output);
-
- if (ccd_unlock || ccd_open || ccd_lock || ccd_info)
- process_ccd_state(&td, ccd_unlock, ccd_open,
- ccd_lock, ccd_info);
-
- if (password)
- process_password(&td);
-
- if (bid_action != bid_none)
- process_bid(&td, bid_action, &bid, show_machine_output);
-
- if (get_endorsement_seed)
- exit(process_endorsement_seed(&td, endorsement_seed_str));
-
- if (rma)
- process_rma(&td, rma_auth_code);
-
- if (factory_mode)
- process_factory_mode(&td, factory_mode_arg);
- if (wp)
- process_wp(&td);
-
- if (corrupt_inactive_rw)
- invalidate_inactive_rw(&td);
-
- if (tpm_mode) {
- int rv = process_tpm_mode(&td, tpm_mode_arg);
-
- exit(rv);
- }
-
- if (tstamp)
- return process_tstamp(&td, tstamp_arg);
-
- if (sn_bits)
- process_sn_bits(&td, sn_bits_arg);
-
- if (sn_inc_rma)
- process_sn_inc_rma(&td, sn_inc_rma_arg);
-
- if (get_flog)
- process_get_flog(&td, prev_log_entry);
-
- if (data || show_fw_ver) {
-
- setup_connection(&td);
-
- if (data) {
- transferred_sections = transfer_image(&td,
- data, data_len);
- free(data);
- }
-
- /*
- * Move USB updater sate machine to idle state so that vendor
- * commands can be processed later, if any.
- */
- if (td.ep_type == usb_xfer)
- send_done(&td.uep);
-
- if (transferred_sections)
- generate_reset_request(&td);
-
- if (show_fw_ver) {
- if (show_machine_output) {
- print_machine_output("RO_FW_VER", "%d.%d.%d",
- targ.shv[0].epoch,
- targ.shv[0].major,
- targ.shv[0].minor);
- print_machine_output("RW_FW_VER", "%d.%d.%d",
- targ.shv[1].epoch,
- targ.shv[1].major,
- targ.shv[1].minor);
- } else {
- printf("Current versions:\n");
- printf("RO %d.%d.%d\n", targ.shv[0].epoch,
- targ.shv[0].major, targ.shv[0].minor);
- printf("RW %d.%d.%d\n", targ.shv[1].epoch,
- targ.shv[1].major, targ.shv[1].minor);
- }
- }
- }
-
- if (td.ep_type == usb_xfer) {
- libusb_close(td.uep.devh);
- libusb_exit(NULL);
- }
-
- if (!transferred_sections)
- return noop;
- /*
- * We should indicate if RO update was not done because of the
- * insufficient RW version.
- */
- for (j = 0; j < ARRAY_SIZE(sections); j++)
- if (sections[j].ustatus == not_possible) {
- /* This will allow scripting repeat attempts. */
- printf("Failed to update RO, run the command again\n");
- return rw_updated;
- }
-
- printf("image updated\n");
- return all_updated;
-}
diff --git a/extra/usb_updater/gsctool.h b/extra/usb_updater/gsctool.h
deleted file mode 100644
index 0be6faeb1c..0000000000
--- a/extra/usb_updater/gsctool.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#ifndef __EXTRA_USB_UPDATER_GSCTOOL_H
-#define __EXTRA_USB_UPDATER_GSCTOOL_H
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include "usb_if.h"
-
-/*
- * gsctool uses this structure to keep information about the communications
- * channel used to talk to the Cr50, and about the state of the Cr50 image.
- */
-struct transfer_descriptor {
- /*
- * Set to true for use in an upstart script. Do not reboot after
- * transfer, and do not transfer RW if versions are the same.
- *
- * When using in development environment it is beneficial to transfer
- * RW images with the same version, as they get started based on the
- * header timestamp.
- */
- int upstart_mode;
- /*
- * Override in case updater is used w/ boards that do not follow
- * the cr50 versioning scheme.
- */
- int background_update_supported;
- /*
- * Unconditionally update the inactive RO, helps to make sure both RO
- * sections are at the same level.
- */
- int force_ro;
- /*
- * offsets of RO and WR sections available for update (not currently
- * active).
- */
- uint32_t ro_offset;
- uint32_t rw_offset;
-
- /* Do not reset the H1 immediately after update, wait for TPM reset. */
- int post_reset;
-
- /* Type of channel used to communicate with Cr50. */
- enum transfer_type {
- usb_xfer = 0, /* usb interface. */
- dev_xfer = 1, /* /dev/tpm0 */
- ts_xfer = 2 /* trunks_send */
- } ep_type;
- union {
- struct usb_endpoint uep;
- int tpm_fd;
- };
-};
-
-/*
- * These are values returned by the gsctool utility, they are interpreted by
- * the startup files to decide how to proceed (try to update to a new Cr50
- * image or not).
- */
-enum exit_values {
- noop = 0, /* All up to date, no update needed. */
- all_updated = 1, /* Update completed, reboot required. */
- rw_updated = 2, /* RO was not updated, reboot required. */
- update_error = 3 /* Something went wrong. */
-};
-
-
-struct board_id {
- uint32_t type; /* Board type */
- uint32_t type_inv; /* Board type (inverted) */
- uint32_t flags; /* Flags */
-};
-
-enum board_id_action {
- bid_none,
- bid_get,
- bid_set
-};
-
-/*
- * This function allows to retrieve or set (if not initialized) board ID of
- * the H1 chip. If bid_action is bid_get and show_machine_output is set,
- * prints out board ID in a machine-friendly format.
- */
-void process_bid(struct transfer_descriptor *td,
- enum board_id_action bid_action,
- struct board_id *bid,
- bool show_machine_output);
-
-/*
- * This function can be used to retrieve the current PP status from Cr50 and
- * prompt the user when a PP press is required.
- *
- * Physical presence can be required by different gsctool options, for which
- * Cr50 behavior also differs. The 'command' and 'poll_type' parameters are
- * used by Cr50 to tell what the host is polling for.
- */
-void poll_for_pp(struct transfer_descriptor *td,
- uint16_t command,
- uint8_t poll_type);
-
-/*
- * Function used to send vendor command to the Cr50 and receive a response.
- * Returns the error code from TPM response header, which is set to zero on
- * success.
- */
-uint32_t send_vendor_command(struct transfer_descriptor *td,
- uint16_t subcommand,
- const void *command_body,
- size_t command_body_size,
- void *response,
- size_t *response_size);
-
-
-#endif // __EXTRA_USB_UPDATER_GSCTOOL_H
diff --git a/extra/usb_updater/verify_ro.c b/extra/usb_updater/verify_ro.c
deleted file mode 100644
index 4a4aea792a..0000000000
--- a/extra/usb_updater/verify_ro.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * Copyright 2018 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 <errno.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "config.h"
-#include "desc_parser.h"
-#include "gsctool.h"
-#include "tpm_vendor_cmds.h"
-#include "verify_ro.h"
-
-/* Index of the matching hash variant. */
-static ssize_t matching_variant;
-
-/*
- * Print out passed in buffer contents in hex, 16 bytes per line, each line
- * starting with the base address value.
- *
- * If the passed in base address is not aligned at 16 byte boundary, skip
- * positions in the dump line so that the address is displayed rounded down to
- * the closest lower 16 byte boundary.
- *
- * For instance passing base of 0x4007 and size of 20 will result in a
- * printout like:
- *
- * 004000 e0 00 00 00 00 66 c7 05 04
- * 004010 80 06 e0 06 00 66 c7 05 20 90 06
- *
- * If title is nonzero - print out the string it points to before printing
- * out buffer contents.
- */
-static void print_buffer_aligned(const char *title, uint32_t base,
- size_t size, const void *data)
-{
- const uint8_t *bytes = data;
- size_t i;
- uint8_t alignment;
-
- /*
- * Calculate how many characters we need to skip in the first dump
- * line.
- */
- alignment = base % 16;
- if (alignment) {
- size += alignment;
- base &= ~0xf;
- }
-
- if (title)
- printf("%s\n", title);
-
- /* Let's print data space separated 16 bytes per line. */
- for (i = 0; i < size; i++) {
- if (!(i % 16))
- printf("\n%06zx", base + i);
-
- if (i < alignment)
- printf(" ");
- else
- printf(" %02x", bytes[i - alignment]);
- }
-}
-
-/* Change the DUT spihash range to the new_type value. */
-static int set_new_range(struct transfer_descriptor *td,
- enum range_type_t new_type)
-{
- uint32_t rv;
- struct vendor_cc_spi_hash_request req;
-
- memset(&req, 0, sizeof(req));
-
- /* Need to send command to change spihash mode. */
- switch (new_type) {
- case AP_RANGE:
- req.subcmd = SPI_HASH_SUBCMD_AP;
- break;
- case EC_RANGE:
- req.subcmd = SPI_HASH_SUBCMD_EC;
- break;
- case EC_GANG_RANGE:
- req.subcmd = SPI_HASH_SUBCMD_EC;
- req.flags = SPI_HASH_FLAG_EC_GANG;
- break;
- default: /* Should never happen. */
- return -EINVAL;
- }
-
- rv = send_vendor_command(td, VENDOR_CC_SPI_HASH, &req, sizeof(req),
- 0, NULL);
-
- if (!rv)
- return 0;
-
- if (rv == VENDOR_RC_IN_PROGRESS) {
- /* This will exit() on error. */
- poll_for_pp(td, VENDOR_CC_SPI_HASH, SPI_HASH_PP_POLL);
- } else {
- fprintf(stderr,
- "%s: failed setting range type %d, error %d\n",
- __func__, new_type, rv);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Verify a dump descriptor hash section defined by 'range'. The passed in by
- * pointer structure req has the range offset and size already initialized.
- *
- * Make sure that matching hashes are at the same index in the hash variants
- * arrays within the same board section.
- */
-static int verify_hash_section(struct transfer_descriptor *td,
- struct vendor_cc_spi_hash_request *req,
- struct addr_range *range)
-{
- size_t i;
- uint8_t response[sizeof(range->variants->expected_result)];
- size_t response_size;
- int rv;
-
- /* First retrieve hash from the DUT. */
- response_size = sizeof(response);
- req->subcmd = SPI_HASH_SUBCMD_SHA256;
- rv = send_vendor_command(td, VENDOR_CC_SPI_HASH,
- req, sizeof(*req), response, &response_size);
-
- if (rv) {
- fprintf(stderr,
- "%s: failed retrieving hash at %x, tpm error %d\n",
- __func__, req->offset, rv);
- return -EINVAL;
- }
-
- if (response_size != sizeof(response)) {
- fprintf(stderr, "got %zd bytes in response for range %x:%x\n",
- response_size, req->offset, req->size);
- return -EINVAL;
- }
-
- if (matching_variant < 0) {
- /* This is the first hash range to be processed. */
- struct result_node *variant = range->variants;
-
- for (i = 0; i < range->variant_count; i++) {
- if (!memcmp(variant->expected_result,
- response, response_size)) {
- matching_variant = i;
- return 0;
- }
- variant++;
- }
-
- fprintf(stderr, "no matching hash found for range %x:%x\n",
- req->offset, req->size);
- return -EINVAL;
- }
-
- if (!memcmp(range->variants[matching_variant].expected_result,
- response, response_size))
- return 0;
-
- fprintf(stderr, "hash mismatch for range %x:%x\n",
- req->offset, req->size);
-
- return -EINVAL;
-}
-
-/*
- * Dump DUT's memory in the range defined by contents of the passed in req
- * structure.
- *
- * The Cr50 SPI hash dump vendor command implementation limits size of the
- * dump to 32, so in case the caller requests more than 32 bytes retrieve them
- * in 32 byte blocks.
- *
- * If base address of the range is not aligned at 16, retrieve smaller
- * quantity such that the following transactions retrieve block starting at
- * aligned addresses, this makes for a better looking hex dump.
- */
-static int dump_range(struct transfer_descriptor *td,
- struct vendor_cc_spi_hash_request *req)
-{
- size_t remaining_size = req->size;
- size_t response_size;
- /* Max size of a single shot is 32 bytes. */
- const size_t max_transfer = 32;
- uint8_t response[max_transfer];
-
- req->subcmd = SPI_HASH_SUBCMD_DUMP;
- while (remaining_size) {
- size_t shot_size = max_transfer;
- uint8_t alignment;
- uint32_t rv;
-
- alignment = req->offset % 16;
-
- if (alignment && ((alignment + remaining_size) > max_transfer))
- /* first line should be truncated. */
- shot_size = max_transfer - alignment;
- else if (shot_size > remaining_size)
- shot_size = remaining_size;
-
- req->size = shot_size;
- response_size = shot_size;
- rv = send_vendor_command(td, VENDOR_CC_SPI_HASH,
- req, sizeof(*req), response,
- &response_size);
- if (rv) {
- fprintf(stderr,
- "%s: failed getting dump contents at %x\n",
- __func__, req->offset);
- return -EINVAL;
- }
-
- if (response_size != shot_size) {
- fprintf(stderr,
- "%s: dump error: got %zd bytes, expected %zd\n",
- __func__, response_size, shot_size);
- return -EINVAL;
- }
-
- print_buffer_aligned(NULL, req->offset, shot_size, response);
- remaining_size -= shot_size;
- req->offset += shot_size;
- }
- printf("\n");
-
- return 0;
-}
-
-/*
- * Iterate through sections of a board descriptor database, retrieving hashes
- * or straight memory blocks as defined by description sections.
- */
-static int process_descriptor_sections(struct transfer_descriptor *td)
-{
- struct vendor_cc_spi_hash_request req;
- int rv;
- struct addr_range *range;
- enum range_type_t current_range = NOT_A_RANGE;
-
- do {
- /*
- * Retrieve next range descriptor section from the descriptor
- * database. The function below is guaranteed to set range to
- * NULL on any error.
- */
- rv = parser_get_next_range(&range);
- if (rv) {
- /*
- * ENODATA means all board's sections have been
- * processed.
- */
- if (rv == -ENODATA)
- rv = 0;
- break;
- }
-
- if (current_range != range->range_type) {
- rv = set_new_range(td, range->range_type);
- if (rv)
- break;
- }
-
- memset(&req, 0, sizeof(req));
- req.offset = range->base_addr;
- req.size = range->range_size;
-
- if (range->variant_count)
- rv = verify_hash_section(td, &req, range);
- else
- rv = dump_range(td, &req);
-
- free(range);
- range = NULL;
- } while (!rv);
-
- if (range)
- free(range);
-
- return rv;
-}
-
-int verify_ro(struct transfer_descriptor *td,
- const char *desc_file_name,
- bool show_machine_output)
-{
- /* First find out board ID of the target. */
- struct board_id bid;
- char rlz_code[sizeof(bid.type) + 1];
- int section_count = 0;
- int rv = 0;
-
- /*
- * Find out what Board ID is the device we are talking to. This
- * function calls exit() on any error.
- */
- process_bid(td, bid_get, &bid, show_machine_output);
-
- if (bid.type != ~bid.type_inv) {
- fprintf(stderr, "Inconsistent board ID: %08x != ~%08x\n",
- bid.type, bid.type_inv);
- return -EINVAL;
- }
-
- /*
- * Convert bid from int to asciiz so that it could be used for
- * strcmp() on the descriptor file section headers.
- */
- memcpy(rlz_code, &bid.type, sizeof(rlz_code) - 1);
- rlz_code[sizeof(rlz_code) - 1] = '\0';
-
- while (!parser_find_board(desc_file_name, rlz_code)) {
-
- /*
- * Each board section might have different index of the
- * matching hash variant.
- */
- matching_variant = -1;
-
- section_count++;
- rv = process_descriptor_sections(td);
- if (rv)
- break;
- }
-
- if (section_count != 2) {
- printf("Found wrong number of sections (%d) for board ID %s\n",
- section_count, rlz_code);
- rv = -EINVAL;
- } else if (!rv) {
- /*
- * Check was successful, send command to exit verification
- * mode.
- */
- struct vendor_cc_spi_hash_request req;
-
- memset(&req, 0, sizeof(req));
- req.subcmd = SPI_HASH_SUBCMD_DISABLE;
- rv = send_vendor_command(td, VENDOR_CC_SPI_HASH, &req,
- sizeof(req), 0, NULL);
- if (rv) {
- fprintf(stderr,
- "%s: spi hash disable TPM error %d\n",
- __func__, rv);
- rv = -EINVAL;
- }
- }
-
- parser_done();
- return rv;
-}
diff --git a/extra/usb_updater/verify_ro.h b/extra/usb_updater/verify_ro.h
deleted file mode 100644
index de2443b8b4..0000000000
--- a/extra/usb_updater/verify_ro.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2018 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.
- */
-
-#ifndef __EXTRA_USB_UPDATER_VERIFY_RO_H
-#define __EXTRA_USB_UPDATER_VERIFY_RO_H
-
-#include <stdbool.h>
-
-#include "gsctool.h"
-
-/*
- * Runs RO verification on the target specified in td using the description file
- * desc_file_name. If show_machine_output is set, target's board ID will be
- * outputted in a machine-friendly format. Returns 0 on success or a negative
- * value if there is an error.
- */
-int verify_ro(struct transfer_descriptor *td,
- const char *desc_file_name,
- bool show_machine_output);
-
-#endif // __EXTRA_USB_UPDATER_VERIFY_RO_H
diff --git a/fuzz/fuzz_config.h b/fuzz/fuzz_config.h
index 963075efab..3e3e1f0872 100644
--- a/fuzz/fuzz_config.h
+++ b/fuzz/fuzz_config.h
@@ -12,76 +12,6 @@
/* Disable hibernate: We never want to exit while fuzzing. */
#undef CONFIG_HIBERNATE
-#ifdef TEST_CR50_FUZZ
-#define CONFIG_DCRYPTO
-#define CONFIG_PINWEAVER
-#define CONFIG_UPTO_SHA512
-#define SHA512_SUPPORT
-#define CONFIG_MALLOC
-
-/******************************************************************************/
-/* From chip/g/config_chip.h */
-
-#define CFG_FLASH_HALF (CONFIG_FLASH_SIZE >> 1)
-#define CFG_TOP_SIZE 0x3000
-#define CFG_TOP_A_OFF (CFG_FLASH_HALF - CFG_TOP_SIZE)
-#define CFG_TOP_B_OFF (CONFIG_FLASH_SIZE - CFG_TOP_SIZE)
-
-/******************************************************************************/
-/* From board/cr50/board.h */
-/* Non-volatile counter storage for U2F */
-#define CONFIG_CRC8
-#define CONFIG_FLASH_ERASED_VALUE32 (-1U)
-#define CONFIG_FLASH_LOG
-#define CONFIG_FLASH_LOG_BASE CONFIG_PROGRAM_MEMORY_BASE
-#define CONFIG_FLASH_LOG_SPACE 0x800
-
-/* We're using TOP_A for partition 0, TOP_B for partition 1 */
-#define CONFIG_FLASH_NVMEM
-/* Offset to start of NvMem area from base of flash */
-#define CONFIG_FLASH_NVMEM_OFFSET_A (CFG_TOP_A_OFF)
-#define CONFIG_FLASH_NVMEM_OFFSET_B (CFG_TOP_B_OFF)
-/* Address of start of Nvmem area */
-#define CONFIG_FLASH_NVMEM_BASE_A \
- (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_A)
-#define CONFIG_FLASH_NVMEM_BASE_B \
- (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_B)
-#define CONFIG_FLASH_NEW_NVMEM_BASE_A \
- (CONFIG_FLASH_NVMEM_BASE_A + CONFIG_FLASH_BANK_SIZE)
-#define CONFIG_FLASH_NEW_NVMEM_BASE_B \
- (CONFIG_FLASH_NVMEM_BASE_B + CONFIG_FLASH_BANK_SIZE)
-/* Size partition in NvMem */
-#define NVMEM_PARTITION_SIZE (CFG_TOP_SIZE)
-/* Size in bytes of NvMem area */
-#define CONFIG_FLASH_NVMEM_SIZE (NVMEM_PARTITION_SIZE * NVMEM_NUM_PARTITIONS)
-
-#define NEW_NVMEM_PARTITION_SIZE (NVMEM_PARTITION_SIZE - CONFIG_FLASH_BANK_SIZE)
-#define NEW_NVMEM_TOTAL_PAGES \
- (2 * NEW_NVMEM_PARTITION_SIZE / CONFIG_FLASH_BANK_SIZE)
-
-/* Enable <key, value> variable support. */
-#define CONFIG_FLASH_NVMEM_VARS
-#define NVMEM_CR50_SIZE 272
-#define CONFIG_FLASH_NVMEM_VARS_USER_SIZE NVMEM_CR50_SIZE
-
-#ifndef __ASSEMBLER__
-enum nvmem_users {
- NVMEM_TPM = 0,
- NVMEM_CR50,
- NVMEM_NUM_USERS
-};
-#endif
-
-#define NVMEM_TPM_SIZE \
- (sizeof(((nvmem_partition *)(0))->buffer) - NVMEM_CR50_SIZE)
-
-#define CONFIG_FLASH_NVMEM_VARS_USER_NUM NVMEM_CR50
-
-/******************************************************************************/
-#define CONFIG_SW_CRC
-
-#endif /* TEST_CR50_FUZZ */
-
#ifdef TEST_HOST_COMMAND_FUZZ
#undef CONFIG_HOSTCMD_DEBUG_MODE
diff --git a/include/ccd_config.h b/include/ccd_config.h
deleted file mode 100644
index 3952cb9bc9..0000000000
--- a/include/ccd_config.h
+++ /dev/null
@@ -1,359 +0,0 @@
-/* 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.
- *
- * Case Closed Debugging configuration
- */
-#ifndef __CROS_EC_CCD_CONFIG_H
-#define __CROS_EC_CCD_CONFIG_H
-
-#include <stdint.h>
-#include "common.h"
-#include "compile_time_macros.h"
-
-/* Case-closed debugging state */
-enum ccd_state {
- CCD_STATE_LOCKED = 0,
- CCD_STATE_UNLOCKED,
- CCD_STATE_OPENED,
-
- /* Number of CCD states */
- CCD_STATE_COUNT
-};
-
-/* Flags */
-enum ccd_flag {
- /* Flags that can only be set internally; fill from bottom up */
-
- /*
- * Test lab mode is enabled. This MUST be in the first byte so that
- * it's in a constant position across all versions of CCD config.
- *
- * Note: This is used internally by CCD config. Do NOT test this
- * to control other things; use capabilities for those.
- */
- CCD_FLAG_TEST_LAB = BIT(0),
-
- /*
- * What state were we in when the password was set?
- * (0=opened, 1=unlocked)
- */
- CCD_FLAG_PASSWORD_SET_WHEN_UNLOCKED = BIT(1),
-
- /*
- * Factory mode state
- */
- CCD_FLAG_FACTORY_MODE_ENABLED = BIT(2),
-
- /* (flags in the middle are unused) */
-
- /* Flags that can be set via ccd_set_flags(); fill from top down */
-
- /* Override BATT_PRES_L at boot */
- CCD_FLAG_OVERRIDE_BATT_AT_BOOT = BIT(20),
-
- /*
- * If overriding BATT_PRES_L at boot, set it to what value
- * (0=disconnect, 1=connected)
- */
- CCD_FLAG_OVERRIDE_BATT_STATE_CONNECT = BIT(21),
-
- /* Override write protect at boot */
- CCD_FLAG_OVERRIDE_WP_AT_BOOT = BIT(22),
-
- /*
- * If overriding WP at boot, set it to what value
- * (0=disabled, 1=enabled)
- */
- CCD_FLAG_OVERRIDE_WP_STATE_ENABLED = BIT(23),
-};
-
-/* Capabilities */
-enum ccd_capability {
- /* UARTs to/from AP and EC */
- CCD_CAP_GSC_RX_AP_TX = 0,
- CCD_CAP_GSC_TX_AP_RX = 1,
- CCD_CAP_GSC_RX_EC_TX = 2,
- CCD_CAP_GSC_TX_EC_RX = 3,
-
- /* Access to AP SPI flash */
- CCD_CAP_AP_FLASH = 4,
-
- /* Access to EC flash (SPI or internal) */
- CCD_CAP_EC_FLASH = 5,
-
- /* Override WP temporarily or at boot */
- CCD_CAP_OVERRIDE_WP = 6,
-
- /* Reboot EC or AP */
- CCD_CAP_REBOOT_EC_AP = 7,
-
- /* GSC restricted console commands */
- CCD_CAP_GSC_RESTRICTED_CONSOLE = 8,
-
- /* Allow ccd-unlock or ccd-open without AP reboot */
- CCD_CAP_UNLOCK_WITHOUT_AP_REBOOT = 9,
-
- /* Allow ccd-unlock or ccd-open without short physical presence */
- CCD_CAP_UNLOCK_WITHOUT_SHORT_PP = 10,
-
- /* Allow ccd-open without wiping TPM data */
- CCD_CAP_OPEN_WITHOUT_TPM_WIPE = 11,
-
- /* Allow ccd-open without long physical presence */
- CCD_CAP_OPEN_WITHOUT_LONG_PP = 12,
-
- /* Allow removing the battery to bypass physical presence requirement */
- CCD_CAP_REMOVE_BATTERY_BYPASSES_PP = 13,
-
- /* Allow GSC firmware update without wiping TPM data */
- CCD_CAP_GSC_FW_UPDATE_WITHOUT_TPM_WIPE = 14,
-
- /* Access to I2C via USB */
- CCD_CAP_I2C = 15,
-
- /* Read-only access to hash or dump EC or AP flash */
- CCD_CAP_FLASH_READ = 16,
-
- /* Allow ccd open without dev mode enabled */
- CCD_CAP_OPEN_WITHOUT_DEV_MODE = 17,
-
- /* Allow ccd open from usb */
- CCD_CAP_OPEN_FROM_USB = 18,
-
- /* Override battery presence temporarily or at boot */
- CCD_CAP_OVERRIDE_BATT_STATE = 19,
-
- /* Number of currently defined capabilities */
- CCD_CAP_COUNT
-};
-
-/* Capability states */
-enum ccd_capability_state {
- /* Default value */
- CCD_CAP_STATE_DEFAULT = 0,
-
- /* Always available (state >= CCD_STATE_LOCKED) */
- CCD_CAP_STATE_ALWAYS = 1,
-
- /* Unless locked (state >= CCD_STATE_UNLOCKED) */
- CCD_CAP_STATE_UNLESS_LOCKED = 2,
-
- /* Only if opened (state >= CCD_STATE_OPENED) */
- CCD_CAP_STATE_IF_OPENED = 3,
-
- /* Number of capability states */
- CCD_CAP_STATE_COUNT
-};
-
-struct ccd_capability_info {
- /* Capability name */
- const char *name;
-
- /* Default state, if config set to CCD_CAP_STATE_DEFAULT */
- enum ccd_capability_state default_state;
-};
-
-#ifdef CONFIG_CCD_OPEN_PREPVT
-/* In prepvt images always allow ccd open from the console without dev mode */
-#define CCD_CAP_STATE_OPEN_REQ CCD_CAP_STATE_ALWAYS
-#else
-/* In prod images restrict how ccd can be opened */
-#define CCD_CAP_STATE_OPEN_REQ CCD_CAP_STATE_IF_OPENED
-#endif
-
-#define CAP_INFO_DATA { \
- {"UartGscRxAPTx", CCD_CAP_STATE_ALWAYS}, \
- {"UartGscTxAPRx", CCD_CAP_STATE_ALWAYS}, \
- {"UartGscRxECTx", CCD_CAP_STATE_ALWAYS}, \
- {"UartGscTxECRx", CCD_CAP_STATE_IF_OPENED}, \
- \
- {"FlashAP", CCD_CAP_STATE_IF_OPENED}, \
- {"FlashEC", CCD_CAP_STATE_IF_OPENED}, \
- {"OverrideWP", CCD_CAP_STATE_IF_OPENED}, \
- {"RebootECAP", CCD_CAP_STATE_IF_OPENED}, \
- \
- {"GscFullConsole", CCD_CAP_STATE_IF_OPENED}, \
- {"UnlockNoReboot", CCD_CAP_STATE_ALWAYS}, \
- {"UnlockNoShortPP", CCD_CAP_STATE_ALWAYS}, \
- {"OpenNoTPMWipe", CCD_CAP_STATE_IF_OPENED}, \
- \
- {"OpenNoLongPP", CCD_CAP_STATE_IF_OPENED}, \
- {"BatteryBypassPP", CCD_CAP_STATE_ALWAYS}, \
- {"UpdateNoTPMWipe", CCD_CAP_STATE_ALWAYS}, \
- {"I2C", CCD_CAP_STATE_IF_OPENED}, \
- {"FlashRead", CCD_CAP_STATE_ALWAYS}, \
- {"OpenNoDevMode", CCD_CAP_STATE_OPEN_REQ}, \
- {"OpenFromUSB", CCD_CAP_STATE_OPEN_REQ}, \
- {"OverrideBatt", CCD_CAP_STATE_IF_OPENED}, \
- }
-
-#define CCD_STATE_NAMES { "Locked", "Unlocked", "Opened" }
-#define CCD_CAP_STATE_NAMES { "Default", "Always", "UnlessLocked", "IfOpened" }
-
-/* Macros regarding ccd_capabilities */
-#define CCD_CAP_BITS 2
-#define CCD_CAP_BITMASK (BIT(CCD_CAP_BITS) - 1)
-#define CCD_CAPS_PER_BYTE (8 / CCD_CAP_BITS)
-
-/*
- * Subcommand code, used to pass different CCD commands using the same TPM
- * vendor command.
- */
-enum ccd_vendor_subcommands {
- CCDV_PASSWORD = 0,
- CCDV_OPEN = 1,
- CCDV_UNLOCK = 2,
- CCDV_LOCK = 3,
- CCDV_PP_POLL_UNLOCK = 4,
- CCDV_PP_POLL_OPEN = 5,
- CCDV_GET_INFO = 6
-};
-
-enum ccd_pp_state {
- CCD_PP_CLOSED = 0,
- CCD_PP_AWAITING_PRESS = 1,
- CCD_PP_BETWEEN_PRESSES = 2,
- CCD_PP_DONE = 3
-};
-
-/* Structure to communicate information about CCD state. */
-#define CCD_CAPS_WORDS ((CCD_CAP_COUNT * 2 + 31)/32)
-struct ccd_info_response {
- uint32_t ccd_caps_current[CCD_CAPS_WORDS];
- uint32_t ccd_caps_defaults[CCD_CAPS_WORDS];
- uint32_t ccd_flags;
- uint8_t ccd_state;
- uint8_t ccd_force_disabled;
- /*
- * A bitmap indicating ccd internal state.
- * See "enum ccd_indicator_bits" below.
- */
- uint8_t ccd_indicator_bitmap;
-} __packed;
-
-enum ccd_indicator_bits {
- /* has_password? */
- CCD_INDICATOR_BIT_HAS_PASSWORD = BIT(0),
-
- /* Are CCD capabilities in CCD_CAP_STATE_DEFAULT */
- CCD_INDICATOR_BIT_ALL_CAPS_DEFAULT = BIT(1),
-};
-
-/**
- * Initialize CCD configuration at boot.
- *
- * This must be called before any command which gets/sets the configuration.
- *
- * @param state Initial case-closed debugging state. This should be
- * CCD_STATE_LOCKED unless this is a debug build, or if
- * a previous value is being restored after a low-power
- * resume.
- */
-void ccd_config_init(enum ccd_state state);
-
-/**
- * Get a single CCD flag.
- *
- * @param flag Flag to get
- * @return 1 if flag is set, 0 if flag is clear
- */
-int ccd_get_flag(enum ccd_flag flag);
-
-/**
- * Set a single CCD flag.
- *
- * @param flag Flag to set
- * @param value New value for flag (0=clear, non-zero=set)
- * @return EC_SUCCESS or non-zero error code.
- */
-int ccd_set_flag(enum ccd_flag flag, int value);
-
-/**
- * Check if a CCD capability is enabled in the current CCD mode.
- *
- * @param cap Capability to check
- * @return 1 if capability is enabled, 0 if disabled
- */
-int ccd_is_cap_enabled(enum ccd_capability cap);
-
-/**
- * Get the current CCD state.
- *
- * This is intended for use by the board if it needs to back up the CCD state
- * across low-power states and then restore it when calling ccd_config_init().
- * Do NOT use this to gate debug capabilities; use ccd_is_cap_enabled() or
- * ccd_get_flag() instead.
- *
- * @return The current CCD state.
- */
-enum ccd_state ccd_get_state(void);
-
-/**
- * Force CCD disabled.
- *
- * This should be called if security checks fail and for some reason the board
- * can't immediately reboot. It locks CCD and disables all CCD capabilities
- * until reboot.
- */
-void ccd_disable(void);
-
-/**
- * Get the factory mode state.
- *
- * @return 0 if factory mode is disabled, !=0 if factory mode is enabled.
- */
-int ccd_get_factory_mode(void);
-
-/* Flags for ccd_reset_config() */
-enum ccd_reset_config_flags {
- /* Also reset test lab flag */
- CCD_RESET_TEST_LAB = BIT(0),
-
- /* Only reset Always/UnlessLocked settings */
- CCD_RESET_UNLOCKED_ONLY = BIT(1),
-
- /*
- * Do a factory reset to enable factory mode. Factory mode sets all ccd
- * capabilities to always and disables write protect
- */
- CCD_RESET_FACTORY = BIT(2)
-};
-
-/**
- * Reset CCD config to the desired state.
- *
- * @param flags Reset flags (see enum ccd_reset_config_flags)
- * @return EC_SUCCESS, or non-zero if error.
- */
-int ccd_reset_config(unsigned int flags);
-
-/**
- * Inform CCD about TPM reset so that the password management state machine
- * can be restarted.
- */
-void ccd_tpm_reset_callback(void);
-
-/**
- * Return True if the ccd password is set. It is possible that a pending ccd
- * change would set or clear the password, but we don't think this is a big
- * issue or risk for now.
- *
- * @return 1 if password is set, 0 if it's not
- */
-int ccd_has_password(void);
-
-/**
- * Enter CCD factory mode. This will clear the TPM, update the ccd config, and
- * then do a hard reboot if 'reset_required' is True.
- */
-void enable_ccd_factory_mode(int reset_required);
-
-/*
- * Enable factory mode but not necessarily rebooting the device. This will
- * clear the TPM and disable flash write protection. Will trigger system reset
- * only if 'reset_required' is True.
- */
-void factory_enable(int reset_required);
-
-#endif /* __CROS_EC_CCD_CONFIG_H */
diff --git a/include/config.h b/include/config.h
index 2d1367778f..e3eca279c4 100644
--- a/include/config.h
+++ b/include/config.h
@@ -373,9 +373,6 @@
#undef CONFIG_AUDIO_CODEC_WOV_LANG_BUF_LEN
#undef CONFIG_AUDIO_CODEC_WOV_LANG_BUF_TYPE
-/* Allow proprietary communication protocols' extensions. */
-#undef CONFIG_EXTENSION_COMMAND
-
/*
* Support controlling the display backlight based on the state of the lid
* switch. The EC will disable the backlight when the lid is closed.
@@ -732,13 +729,6 @@
*/
#undef CONFIG_BUTTONS_RUNTIME_CONFIG
-/* Support V1 CCD configuration */
-#undef CONFIG_CASE_CLOSED_DEBUG_V1
-/* Allow unsafe debugging functionality in V1 configuration */
-#undef CONFIG_CASE_CLOSED_DEBUG_V1_UNSAFE
-/* Loosen Open restrictions for prePVT devices */
-#undef CONFIG_CCD_OPEN_PREPVT
-
/*
* Capsense chip has buttons, too.
*/
@@ -1192,7 +1182,6 @@
#define CONFIG_CMD_RETIMER
#undef CONFIG_CMD_BUTTON
#define CONFIG_CMD_CBI
-#undef CONFIG_CMD_CCD_DISABLE /* 'ccd disable' subcommand */
#undef CONFIG_CMD_CHARGEN
#define CONFIG_CMD_CHARGER
#undef CONFIG_CMD_CHARGER_ADC_AMON_BMON
@@ -1431,42 +1420,6 @@
/* Include CRC-8 utility function */
#undef CONFIG_CRC8
-/*
- * When enabled, build in support for software & hardware crypto;
- * only supported on CR50.
- *
- * If this is enabled on the host board, a minimal implementation is included to
- * allow fuzzing targets to fuzz code that depends on dcrypto.
- */
-#undef CONFIG_DCRYPTO
-/*
- * This provides struct definitions and function declarations that can be
- * implemented by unit tests for testing code that depends on dcrypto.
- * This should not be set at the same time as CONFIG_DCRYPTO.
- */
-#undef CONFIG_DCRYPTO_MOCK
-
-/*
- * When enabled, RSA 2048 bit keygen gets a 40% performance boost,
- * at the cost of 2184 bytes of image size increase.
- */
-#undef CONFIG_DCRYPTO_RSA_SPEEDUP
-
-/*
- * When enabled build support for SHA-384/512, requires CONFIG_DCRYPTO.
- */
-#undef CONFIG_UPTO_SHA512
-
-/*
- * When enabled ignore version et al during fw upgrade for chip/g.
- */
-#undef CONFIG_IGNORE_G_UPDATE_CHECKS
-
-/*
- * Enable console shell command 'alerts' that prints chip alerts statistics.
- */
-#undef CONFIG_ENABLE_H1_ALERTS_CONSOLE
-
/*****************************************************************************/
/*
* Debugging config
@@ -1606,9 +1559,6 @@
/* Default debounce time for external power signal */
#define CONFIG_EXTPOWER_DEBOUNCE_MS 30
-/* Add support for CCD factory mode */
-#undef CONFIG_FACTORY_MODE
-
/*****************************************************************************/
/* Number of cooling fans. Undef if none. */
#undef CONFIG_FANS
@@ -1769,34 +1719,6 @@
#undef CONFIG_FP_SENSOR_FPC1145
/*****************************************************************************/
-/* NvMem Configuration */
-/* Enable NV Memory module within flash */
-#undef CONFIG_FLASH_NVMEM
-/* Offset to start of NvMem area from base of flash */
-#undef CONFIG_FLASH_NVMEM_OFFSET_A
-#undef CONFIG_FLASH_NVMEM_OFFSET_B
-/* Address of start of Nvmem area */
-#undef CONFIG_FLASH_NVMEM_BASE_A
-#undef CONFIG_FLASH_NVMEM_BASE_B
-
-/* Flash offsets for the 'new' (as of 1/2019) nvmem storage scheme. */
-#undef CONFIG_FLASH_NEW_NVMEM_BASE_A
-#undef CONFIG_FLASH_NEW_NVMEM_BASE_B
-
-/* Size in bytes of NvMem area */
-#undef CONFIG_FLASH_NVMEM_SIZE
-
-/* Enable <key,value> variable support (requires CONFIG_FLASH_NVMEM) */
-#undef CONFIG_FLASH_NVMEM_VARS
-/*
- * We already have to define nvmem_user_sizes[] to specify the order and size
- * of the user regions. CONFIG_FLASH_NVMEM_VARS looks for two symbols to
- * specify the region number and size for the variable region.
- */
-#undef CONFIG_FLASH_NVMEM_VARS_USER_NUM
-#undef CONFIG_FLASH_NVMEM_VARS_USER_SIZE
-
-/*****************************************************************************/
/* Include a flashmap in the compiled firmware image */
#define CONFIG_FMAP
@@ -2904,19 +2826,6 @@
*/
#undef CONFIG_PECI_TJMAX
-/* Support physical presence detection (via a physical button) */
-#undef CONFIG_PHYSICAL_PRESENCE
-
-/* Enable (unsafe!) developer debug features for physical presence */
-#undef CONFIG_PHYSICAL_PRESENCE_DEBUG_UNSAFE
-
-/*****************************************************************************/
-/* PinWeaver config
- * A feature which exchanges a low entropy secret with rate limits for a high
- * entropy secret. This enables a set of vendor specific commands for Cr50.
- */
-#undef CONFIG_PINWEAVER
-
/*****************************************************************************/
/* PMU config */
@@ -3110,12 +3019,6 @@
#undef CONFIG_RAM_SIZE
#undef CONFIG_ROM_SIZE
-/* Enable rbox peripheral */
-#undef CONFIG_RBOX
-
-/* Enable rbox wakeup */
-#undef CONFIG_RBOX_WAKEUP
-
/* Support IR357x Link voltage regulator debugging / reprogramming */
#undef CONFIG_REGULATOR_IR357X
@@ -3255,14 +3158,6 @@
/* Support deprecated SPI protocol version 2. */
#undef CONFIG_SPI_PROTOCOL_V2
-/*
- * Support SPI Slave interfaces. The first board supporting this is cr50 and
- * in its parlance SPI_SLAVE is called SPS. This convention might be
- * reconsidered later, and the use of "SPI" in different config options needs
- * to be cleaned up. (crbug.com/512613).
- */
-#undef CONFIG_SPS
-
/* Define the SPI port to use to access SPI accelerometer */
#undef CONFIG_SPI_ACCEL_PORT
@@ -3342,9 +3237,6 @@
*/
#undef CONFIG_MCHP_GPSPI
-/* Support testing SPI slave controller driver. */
-#undef CONFIG_SPS_TEST
-
/* Default stack size to use for tasks, in bytes */
#undef CONFIG_STACK_SIZE
@@ -3616,12 +3508,6 @@
#undef CONFIG_TOUCHPAD_HASH_FW
/*****************************************************************************/
-/* TPM-like configuration */
-
-/* Speak to the TPM 2.0 hardware protocol on the I2C slave interface */
-#undef CONFIG_TPM_I2CS
-
-/*****************************************************************************/
/* USART stream config */
#undef CONFIG_STREAM_USART
@@ -3635,10 +3521,6 @@
#undef CONFIG_STREAM_USART4
/*****************************************************************************/
-/* U2F config: second factor authentication */
-#undef CONFIG_U2F
-
-/*****************************************************************************/
/* USB stream config */
#undef CONFIG_STREAM_USB
@@ -4221,9 +4103,6 @@
/* Disable automatic initialization of USB peripheral */
#undef CONFIG_USB_INHIBIT_INIT
-/* Support control of multiple PHY */
-#undef CONFIG_USB_SELECT_PHY
-
/* Support simple control of power to the device's USB ports */
#undef CONFIG_USB_PORT_POWER_DUMB
@@ -4504,12 +4383,6 @@
#undef CONFIG_EXTENDED_VERSION_INFO
/*
- * Define this if board ID support is required. For g chip based boards it
- * allows to nail different images to different boards.
- */
-#undef CONFIG_BOARD_ID_SUPPORT
-
-/*
* Define this to enable Cros Board Info support. I2C_EEPROM_PORT and
* I2C_EEPROM_ADDR must be defined as well.
*/
diff --git a/include/console_channel.inc b/include/console_channel.inc
index f4558bef3c..e240bf4546 100644
--- a/include/console_channel.inc
+++ b/include/console_channel.inc
@@ -22,12 +22,6 @@ CONSOLE_CHANNEL(CC_BLUETOOTH_HCI,"bluetooth_hci")
#ifdef CONFIG_CEC
CONSOLE_CHANNEL(CC_CEC, "cec")
#endif
-#ifdef CONFIG_EXTENSION_COMMAND
-CONSOLE_CHANNEL(CC_EXTENSION, "extension")
-#endif
-#if defined(CONFIG_PHYSICAL_PRESENCE)
-CONSOLE_CHANNEL(CC_CCD, "ccd")
-#endif
CONSOLE_CHANNEL(CC_CHARGER, "charger")
#ifdef HAS_TASK_CHIPSET
CONSOLE_CHANNEL(CC_CHIPSET, "chipset")
@@ -85,12 +79,6 @@ CONSOLE_CHANNEL(CC_PS2, "ps2")
CONSOLE_CHANNEL(CC_PWM, "pwm")
#endif
CONSOLE_CHANNEL(CC_SPI, "spi")
-#ifdef CONFIG_RBOX
-CONSOLE_CHANNEL(CC_RBOX, "rbox")
-#endif
-#ifdef CONFIG_SPS
-CONSOLE_CHANNEL(CC_SPS, "sps")
-#endif
#if defined(CONFIG_SWITCH) || defined(CONFIG_LID_SWITCH)
CONSOLE_CHANNEL(CC_SWITCH, "switch")
#endif
@@ -106,9 +94,6 @@ CONSOLE_CHANNEL(CC_DPTF, "dptf")
CONSOLE_CHANNEL(CC_ALS, "als")
#endif
CONSOLE_CHANNEL(CC_THERMAL, "thermal")
-#ifdef CHIP_G
-CONSOLE_CHANNEL(CC_TPM, "tpm")
-#endif
CONSOLE_CHANNEL(CC_USB, "usb")
CONSOLE_CHANNEL(CC_USBCHARGE, "usbcharge")
#if defined(CONFIG_USB_POWER_DELIVERY) || defined(CONFIG_USB_PD_TCPC)
diff --git a/include/extension.h b/include/extension.h
deleted file mode 100644
index 5ce0410f57..0000000000
--- a/include/extension.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Copyright 2015 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.
- */
-
-#ifndef __EC_INCLUDE_EXTENSION_H
-#define __EC_INCLUDE_EXTENSION_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "common.h"
-#include "tpm_vendor_cmds.h"
-
-/* Flags for vendor or extension commands */
-enum vendor_cmd_flags {
- /*
- * Command is coming from the USB interface (either via the vendor
- * command endpoint or the console). If this flag is not present,
- * the command is coming from the AP.
- */
- VENDOR_CMD_FROM_USB = BIT(0),
-};
-
-/* Parameters for vendor commands */
-struct vendor_cmd_params {
- /* Command code */
- enum vendor_cmd_cc code;
-
- /* On input, data to be processed. On output, response data. */
- void *buffer;
-
- /* Number of bytes of input data */
- size_t in_size;
-
- /*
- * On input, size of output buffer. On output, actual response size.
- * Both in bytes. A single response byte usually indicates an error
- * and contains the error code.
- */
- size_t out_size;
-
- /* Flags; zero or more of enum vendor_cmd_flags */
- uint32_t flags;
-};
-
-/* Type of function handling extension commands. */
-typedef enum vendor_cmd_rc
- (*extension_handler)(struct vendor_cmd_params *params);
-
-/**
- * Find handler for an extension command.
- *
- * Use the interface specific function call in order to check the policies for
- * handling the commands on that interface.
- *
- * @param p Parameters for the command
- * @return The return code from processing the command.
- */
-uint32_t extension_route_command(struct vendor_cmd_params *p);
-
-
-/* Pointer table */
-struct extension_command {
- uint16_t command_code;
- extension_handler handler;
-} __packed;
-
-#define DECLARE_EXTENSION_COMMAND(code, func) \
- static enum vendor_cmd_rc \
- func##_wrap(struct vendor_cmd_params *params) \
- { \
- func(params->buffer, params->in_size, \
- &params->out_size); \
- return VENDOR_RC_SUCCESS; \
- } \
- const struct extension_command __keep __no_sanitize_address \
- __extension_cmd_##code \
- __attribute__((section(".rodata.extensioncmds"))) \
- = {.command_code = code, .handler = func##_wrap }
-
-/* Vendor command which takes params directly */
-#define DECLARE_VENDOR_COMMAND(cmd_code, func) \
- static enum vendor_cmd_rc \
- func##_wrap(struct vendor_cmd_params *params) \
- { \
- return func(params->code, params->buffer, \
- params->in_size, &params->out_size); \
- } \
- const struct extension_command __keep __no_sanitize_address \
- __vendor_cmd_##cmd_code \
- __attribute__((section(".rodata.extensioncmds"))) \
- = {.command_code = cmd_code, .handler = func##_wrap}
-
-/* Vendor command which takes params as struct */
-#define DECLARE_VENDOR_COMMAND_P(cmd_code, func) \
- const struct extension_command __keep __no_sanitize_address \
- __vendor_cmd_##cmd_code \
- __attribute__((section(".rodata.extensioncmds"))) \
- = {.command_code = cmd_code, .handler = func}
-
-#endif /* __EC_INCLUDE_EXTENSION_H */
diff --git a/include/hooks.h b/include/hooks.h
index 9fd45c2853..0860a58d84 100644
--- a/include/hooks.h
+++ b/include/hooks.h
@@ -177,15 +177,6 @@ enum hook_type {
*/
HOOK_BATTERY_SOC_CHANGE,
-#ifdef CONFIG_CASE_CLOSED_DEBUG_V1
- /*
- * Case-closed debugging configuration changed.
- *
- * Hook routines are called from the TICK, console, or TPM task.
- */
- HOOK_CCD_CHANGE,
-#endif
-
#ifdef CONFIG_USB_SUSPEND
/*
* Called when there is a change in USB power management status
diff --git a/include/link_defs.h b/include/link_defs.h
index 5ea500516f..45e9850015 100644
--- a/include/link_defs.h
+++ b/include/link_defs.h
@@ -56,10 +56,6 @@ extern const struct hook_data __hooks_pwrbtn_change[];
extern const struct hook_data __hooks_pwrbtn_change_end[];
extern const struct hook_data __hooks_battery_soc_change[];
extern const struct hook_data __hooks_battery_soc_change_end[];
-#ifdef CONFIG_CASE_CLOSED_DEBUG_V1
-extern const struct hook_data __hooks_ccd_change[];
-extern const struct hook_data __hooks_ccd_change_end[];
-#endif
#ifdef CONFIG_USB_SUSPEND
extern const struct hook_data __hooks_usb_change[];
extern const struct hook_data __hooks_usb_change_end[];
diff --git a/include/new_nvmem.h b/include/new_nvmem.h
deleted file mode 100644
index 37399702f8..0000000000
--- a/include/new_nvmem.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/* Copyright 2019 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.
- */
-#ifndef __TPM2_NVMEM_TEST_NEW_NVMEM_H
-#define __TPM2_NVMEM_TEST_NEW_NVMEM_H
-
-#include "common.h"
-#include "nvmem.h"
-#include "nvmem_vars.h"
-#include "util.h"
-
-#define NVMEM_NOT_INITIALIZED ((unsigned int)-1)
-
-/*
- * A totally arbitrary byte limit for space occupied by (key, value) pairs in
- * the flash. This is an improvement compared to the legacy case where there
- * were just 272 bytes dedicated to the (key, value) pairs storage.
- */
-#define MAX_VAR_TOTAL_SPACE 1000
-
-/*
- * Let's be reasonable: we're unlikely to have keys longer than 40 or so
- * bytes, and leave full 255 bytes for the value. Total data space occupied by
- * a (key, value) pair is not to exceed the value below.
- */
-#define MAX_VAR_BODY_SPACE 300
-
-enum nn_object_type {
- NN_OBJ_OLD_COPY = 0,
- NN_OBJ_TUPLE = 1,
- NN_OBJ_TPM_RESERVED = 2,
- NN_OBJ_TPM_EVICTABLE = 3,
- NN_OBJ_TRANSACTION_DEL = 4,
- NN_OBJ_ESCAPE = 5,
- NN_OBJ_ERASED = 7,
-};
-
-/*
- * Structure placed at the base of each flash page used for NVMEM storage.
- *
- * page_number: allows to arrange pages in order they were added
- *
- * data_offset: the offset of the first element in the page (space above
- * page header and below data_offset could be taken by the
- * 'tail' of the object stored on the previous page).
- *
- * page_hash: is used to verify page header integrity
- */
-struct nn_page_header {
- unsigned int page_number : 21;
- unsigned int data_offset : 11;
- uint32_t page_hash;
-} __packed;
-
-/*
- * Index of the 'virtual' last reserved object. RAM index space and max
- * counter objects stored at fixed location in the NVMEM cache are considered
- * reserved objects by this NVMEM flash layer.
- */
-#define NV_VIRTUAL_RESERVE_LAST (NV_RESERVE_LAST + 2)
-
-/*
- * Container header for all blobs stored in flash.
- *
- * container_type: type of object stored in the container. MAKE SURE THIS
- * FIELD TYPE IS THE FIRST FIELD IN THIS STRUCTURE, it is
- * supposed to be in the first word of the container so that
- * the type can be erased when object is deleted.
- *
- * container_type_copy: immutable copy of the container_type field, used to
- * verify contents of deleted objects.
- *
- * encrypted: set to 1 if contents are encrypted.
- *
- * size: size of the payload, 12 bits allocated, 11 bits would be enough for
- * this use case.
- *
- * generation: a free running counter, used to compare ages of two containers
- *
- * container_hash: hash of the ENTIRE container, both header and body
- * included. This field is set to zero before hash is calculated
- */
-struct nn_container {
- unsigned int container_type : 3;
- unsigned int container_type_copy : 3;
- unsigned int encrypted : 1;
- unsigned int size : 11;
- unsigned int generation : 2;
- unsigned int container_hash : 12;
-} __packed;
-
-/*
- * A structure to keep context of accessing to a page, page header and offset
- * define where the next access would happen.
- */
-struct page_tracker {
- const struct nn_page_header *ph;
- uint16_t data_offset;
-};
-
-/*
- * Helper structure to keep track of accesses to the flash storage.
- *
- * mt: main tracker for read or write accesses.
- *
- * ct: keeps track of container fetches, as the location of containers has
- * special significance: it is both part of the seed used when
- * encrypting/decryping container contents, and also is necessary to
- * unwind reading of the container header when the end of storage is
- * reached and a header of all 0xff is read.
- *
- * dt: keeps track of delimiters which is important when assessing flash
- * contents integrity. If during startup the last item in flash is not a
- * delimiter, this is an indication of a failed transaction, all data
- * after the previous delimiter needs to be discarded.
- *
- * list_index; index of the current page in the list of pages, useful when
- * sequential reading and need to get to the next page in the
- * list.
- */
-
-struct access_tracker {
- struct page_tracker mt; /* Main tracker. */
- struct page_tracker ct; /* Container tracker. */
- struct page_tracker dt; /* Delimiter tracker.*/
- uint8_t list_index;
-};
-
-/*
- * New nvmem interface functions, each of them could be blocking because each
- * of them acquires nvmem flash protectioin mutex before proceeding.
- */
-enum ec_error_list new_nvmem_init(void);
-enum ec_error_list new_nvmem_migrate(unsigned int nvmem_act_partition);
-enum ec_error_list new_nvmem_save(void);
-int nvmem_erase_tpm_data(void);
-
-#if defined(TEST_BUILD) && !defined(TEST_FUZZ)
-#define NVMEM_TEST_BUILD
-enum ec_error_list browse_flash_contents(int);
-enum ec_error_list compact_nvmem(void);
-extern struct access_tracker master_at;
-extern uint16_t total_var_space;
-int is_uninitialized(const void *p, size_t size);
-size_t init_object_offsets(uint16_t *offsets, size_t count);
-struct nn_page_header *list_element_to_ph(size_t el);
-void *evictable_offs_to_addr(uint16_t offset);
-enum ec_error_list get_next_object(struct access_tracker *at,
- struct nn_container *ch,
- int include_deleted);
-#endif
-
-
-#endif /* ! __TPM2_NVMEM_TEST_NEW_NVMEM_H */
diff --git a/include/nvmem.h b/include/nvmem.h
deleted file mode 100644
index f48c9cd9c4..0000000000
--- a/include/nvmem.h
+++ /dev/null
@@ -1,219 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#ifndef __CROS_EC_NVMEM_UTILS_H
-#define __CROS_EC_NVMEM_UTILS_H
-
-#include "crypto_api.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * In order to provide maximum robustness for NvMem operations, the NvMem space
- * is divided into two equal sized partitions. A partition contains a tag
- * and a buffer for each NvMem user.
- *
- * NvMem Partiion
- * ------------------------------------------------------------------------
- * |36 byte tag | User Buffer 0 | User Buffer 1 | .... | User Buffer N-1 |
- * ------------------------------------------------------------------------
- *
- * Physical Block Tag details
- * ------------------------------------------------------------------------
- * | sha | padding | version | generation | reserved |
- * -------------------------------------------------------------------------
- * sha -> 16 bytes of sha1 digest
- * padding -> 16 bytes for future extensions
- * version -> nvmem layout version, currently at 0
- * generation -> 1 byte generation number (0 - 0xfe)
- * reserved -> 2 bytes
- *
- * At initialization time, each partition is scanned to see if it has a good sha
- * entry. One of the two partitions being valid is a supported condition. If
- * neither partiion is valid a new partition is created with generation set to
- * zero.
- *
- * Note that the NvMem partitions can be placed anywhere in flash space, but
- * must be equal in total size. A table is used by the NvMem module to get the
- * correct base address for each partition.
- *
- * A generation number is used to distinguish between two valid partitions with
- * the newsest generation number (in a circular sense) marking the correct
- * partition to use. The parition number 0/1 is tracked via a static
- * variable. When the NvMem contents need to be updated, the flash erase/write
- * of the updated partition will use the inactive partition space in NvMem. This
- * way if there is a critical failure (i.e. loss of power) during the erase or
- * write operation, then the contents of the active partition prior the most
- * recent writes will still be preserved.
- *
- * The following CONFIG_FLASH_NVMEM_ defines are required for this module:
- * CONFIG_FLASH_NVMEM -> enable/disable the module
- * CONFIG_FLASH_NVMEM_OFFSET_(A|B) -> offset to start of each partition
- * CONFIG_FLASH_NVMEM_BASE_(A|B) -> address of start of each partition
- *
- * The board.h file must define a macro or enum named NVMEM_NUM_USERS.
- * The board.c file must implement:
- * nvmem_user_sizes[] -> array of user buffer lengths
- * The chip must provide
- * app_compute_hash() -> function used to compute 16 byte sha (or equivalent)
- *
- * Note that total length of user buffers must satisfy the following:
- * sum(user sizes) <= (NVMEM_PARTITION_SIZE) - sizeof(struct nvmem_tag)
- */
-
-/* NvMem user buffer length table */
-extern uint32_t nvmem_user_sizes[NVMEM_NUM_USERS];
-
-#define NVMEM_NUM_PARTITIONS 2
-#define NVMEM_SHA_SIZE CIPHER_SALT_SIZE
-#define NVMEM_GENERATION_BITS 8
-#define NVMEM_GENERATION_MASK (BIT(NVMEM_GENERATION_BITS) - 1)
-#define NVMEM_PADDING_SIZE 16
-#define NVMEM_LAYOUT_VERSION 0
-
-/* Struct for NV block tag */
-struct nvmem_tag {
- uint8_t sha[NVMEM_SHA_SIZE];
- uint8_t padding[NVMEM_PADDING_SIZE];
- uint8_t layout_version;
- uint8_t generation;
- uint8_t reserved[2];
-};
-
-/* Structure MvMem Partition */
-struct nvmem_partition {
- struct nvmem_tag tag;
- uint8_t buffer[NVMEM_PARTITION_SIZE -
- sizeof(struct nvmem_tag)];
-};
-
-/**
- * Initialize NVMem translation table and state variables
- *
- * @return EC_SUCCESS if a valid translation table is constructed, else
- * error code.
- */
-int nvmem_init(void);
-
-/**
- * Get Nvmem internal error state
- *
- * @return nvmem_error_state variable.
- */
-int nvmem_get_error_state(void);
-
-/**
- * Compare 'size' amount of bytes in NvMem
- *
- * @param offset: Offset (in bytes) into NVmem logical space
- * @param size: Number of bytes to compare
- * @param data: Pointer to data to be compared with
- * @param user: Data section within NvMem space
- * @return 0 if the data is same, non-zero if data is different
- */
-int nvmem_is_different(uint32_t offset, uint32_t size,
- void *data, enum nvmem_users user);
-
-/**
- * Read 'size' amount of bytes from NvMem
- *
- * @param startOffset: Offset (in bytes) into NVmem logical space
- * @param size: Number of bytes to read
- * @param data: Pointer to destination buffer
- * @param user: Data section within NvMem space
- * @return EC_ERROR_OVERFLOW (non-zero) if the read operation would exceed the
- * buffer length of the given user, otherwise EC_SUCCESS.
- */
-int nvmem_read(uint32_t startOffset, uint32_t size,
- void *data, enum nvmem_users user);
-
-/**
- * Write 'size' amount of bytes to NvMem
- *
- * Calling this function will wait for the mutex, then lock it until
- * nvmem_commit() is invoked.
- *
- * @param startOffset: Offset (in bytes) into NVmem logical space
- * @param size: Number of bytes to write
- * @param data: Pointer to source buffer
- * @param user: Data section within NvMem space
- * @return EC_ERROR_OVERFLOW if write exceeds buffer length
- * EC_ERROR_TIMEOUT if nvmem cache buffer is not available
- * EC_SUCCESS if no errors.
- */
-int nvmem_write(uint32_t startOffset, uint32_t size,
- void *data, enum nvmem_users user);
-
-/**
- * Move 'size' amount of bytes within NvMem
- *
- * Calling this function will wait for the mutex, then lock it until
- * nvmem_commit() is invoked.
- *
- * @param src_offset: source offset within NvMem logical space
- * @param dest_offset: destination offset within NvMem logical space
- * @param size: Number of bytes to move
- * @param user: Data section within NvMem space
- * @return EC_ERROR_OVERFLOW if write exceeds buffer length
- * EC_ERROR_TIMEOUT if nvmem cache buffer is not available
- * EC_SUCCESS if no errors.
- */
-int nvmem_move(uint32_t src_offset, uint32_t dest_offset, uint32_t size,
- enum nvmem_users user);
-/**
- * Commit all previous NvMem writes to flash
- *
- * @return EC_SUCCESS if flash erase/operations are successful.
-
- * EC_ERROR_OVERFLOW in case the mutex is not locked when this
- * function is called
- * EC_ERROR_INVAL if task trying to commit is not the one
- * holding the mutex
- * EC_ERROR_UNKNOWN in other error cases
- */
-int nvmem_commit(void);
-
-/*
- * Temporarily stopping NVMEM commits could be beneficial. One use case is
- * when TPM operations need to be sped up.
- *
- * Calling this function will wait for the mutex, then lock it until
- * nvmem_commit() is invoked.
- *
- * Both below functions should be called from the same task.
- */
-void nvmem_disable_commits(void);
-
-/*
- * Only the task holding the mutex is allowed to enable commits.
- *
- * @return error if this task does not hold the lock or commit
- * fails, EC_SUCCESS otherwise.
- */
-int nvmem_enable_commits(void);
-
-/*
- * Function to retrieve the base address of the nvmem cache of the appropriate
- * user. After migration there is only one user and one base address, this
- * function will be eliminated.
- *
- * @return pointer to the base address.
- */
-void *nvmem_cache_base(enum nvmem_users user);
-
-/*
- * Clear all NVMEM cache in SRAM.
- */
-void nvmem_clear_cache(void);
-
-void nvmem_wipe_cache(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CROS_EC_NVMEM_UTILS_H */
diff --git a/include/nvmem_vars.h b/include/nvmem_vars.h
deleted file mode 100644
index 08bd9164c8..0000000000
--- a/include/nvmem_vars.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#ifndef __EC_INCLUDE_NVMEM_VARS_H
-#define __EC_INCLUDE_NVMEM_VARS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * CONFIG_FLASH_NVMEM provides persistent, atomic-update storage in
- * flash. The storage is logically divided into one or more "user regions", as
- * configured in board.h and board.c
- *
- * CONFIG_FLASH_NVMEM_VARS stores a set of <KEY, VALUE> tuples in the nvmem
- * user region designated by CONFIG_FLASH_NVMEM_VARS_USER_NUM (in board.h)
- *
- * Tuples are stored and managed using this struct:
- */
-
-struct tuple {
- uint8_t key_len; /* 1 - 255 */
- uint8_t val_len; /* 1 - 255 */
- uint8_t flags; /* RESERVED, will be zeroed */
- uint8_t data_[0]; /* Opaque. Don't look here. */
-};
-
-/*
- * Both KEY and VALUE can be any binary blob between 1 and 255 bytes (flash
- * memory is limited, so if you need longer values just use two keys and
- * concatenate the blobs). Zero-length KEYs or VALUEs are not allowed.
- * Assigning a zero-length VALUE to a KEY just deletes that tuple (if it
- * existed).
- *
- * The expected usage is:
- *
- * 1. At boot, call initvars() to ensure that the variable storage region is
- * valid. If it isn't, this will initialize it to an empty set.
- *
- * 2. Call getenv() or setenv() as needed. The first call to either will copy
- * the storage regsion from flash into a RAM buffer. Any changes made with
- * setenv() will affect only that RAM buffer.
- *
- * 3. Call writevars() to commit the RAM buffer to flash and free it.
- *
- * CAUTION: The underlying CONFIG_FLASH_NVMEM implementation allows access by
- * multiple tasks, provided each task access only one user region. There is no
- * support for simultaneous access to the *same* user region by multiple tasks.
- * CONFIG_FLASH_NVMEM_VARS stores all variables in one user region, so if
- * variable access by multiple tasks is required, the tasks should establish
- * their own locks or mutexes to fit their usage. In general that would mean
- * aquiring a lock before calling getvar() or setvar(), and releasing it after
- * calling writevars().
- */
-
-/*
- * Initialize the persistent storage. This checks the user region to ensure
- * that all tuples are valid and that there is one additional '\0' at the end.
- * If any discrepancies are found, it erases all values. This should return
- * EC_SUCCESS unless there is a problem writing to flash.
- */
-int initvars(void);
-
-/*
- * Look up the key passed in the input tuple and fill the value, if found.
- *
- * The val_len field in the passed in tuple indicates how much room is
- * available, the actual value size could be smaller.
- *
- * Could block as it acquires the flash protection mutex before proceeding.
- *
- * Return:
- *
- * EC_SUCCESS - if the key was found and there was enough room in the passed
- * in tuple for the value.
- * EC_ERROR_INVAL - if the key was not found.
- *
- * EC_ERROR_MEMORY_ALLOCATION - if the value would not fit into the supplied
- * tuple.
- */
-const struct tuple *getvar(const uint8_t *key, uint8_t key_len);
-
-/*
- * Free memory held by the previously read tuple.
- *
- * Note that tuple address is not the address to be returned to the heap, so
- * the user must use this function to free this memory. If var is NULL this
- * function is a no-op.
- *
- */
-void freevar(const struct tuple *var);
-
-/* Use these to access the data components of a valid struct tuple pointer */
-const uint8_t *tuple_key(const struct tuple *);
-const uint8_t *tuple_val(const struct tuple *);
-
-/*
- * Save the tuple in the RAM buffer. If val is NULL or val_len is 0, the
- * tuple is deleted (if it existed). Returns EC_SUCCESS or error code.
- *
- * Could block as it acquires the flash protection mutex before proceeding.
- */
-int setvar(const uint8_t *key, uint8_t key_len,
- const uint8_t *val, uint8_t val_len);
-
-/*
- * Commit any changes made with setvar() to persistent memory, and invalidate
- * the RAM buffer. Return EC_SUCCESS or error code on failure.
- */
-int writevars(void);
-
-/*
- * A fully contained function which does not use any available nvmem_vars
- * methods, as it is used solely for retrieving vars from legacy storage
- * format. Runs only during migration.
- */
-const struct tuple *legacy_getnextvar(const struct tuple *prev_var);
-
-int set_local_copy(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __EC_INCLUDE_NVMEM_VARS_H */
diff --git a/include/pinweaver.h b/include/pinweaver.h
deleted file mode 100644
index 21571da7b0..0000000000
--- a/include/pinweaver.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/* Copyright 2018 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.
- */
-
-#ifndef __CROS_EC_INCLUDE_PINWEAVER_H
-#define __CROS_EC_INCLUDE_PINWEAVER_H
-
-/* This is required before pinweaver_types.h to provide __packed and __aligned
- * while preserving the ability of pinweaver_types.h to be used in code outside
- * of src/platform/ec.
- */
-#include <common.h>
-#include <pinweaver_types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PW_STORAGE_VERSION 0
-
-#define BITS_PER_LEVEL_MIN 1
-#define BITS_PER_LEVEL_MAX 5
-#define HEIGHT_MIN 1
-/* This will crash for logk == 0 so that condition must not be allowed when
- * using this.
- */
-#define HEIGHT_MAX(logk) ((sizeof(struct label_t) * 8) / logk)
-
-#define PW_LOG_ENTRY_COUNT 2
-
-/* Persistent information used by this feature. */
-struct merkle_tree_t {
- /* log2(Fan out). */
- struct bits_per_level_t bits_per_level;
- /* Height of the tree or param_l / bits_per_level. */
- struct height_t height;
-
- /* Root hash of the Merkle tree. */
- uint8_t root[PW_HASH_SIZE];
-
- /* Random bits used as part of the key derivation process. */
- uint8_t key_derivation_nonce[16];
-
- /* Key used to compute the HMACs of the metadata of the leaves. */
- uint8_t PW_ALIGN_TO_WRD hmac_key[32];
-
- /* Key used to encrypt and decrypt the metadata of the leaves. */
- uint8_t PW_ALIGN_TO_WRD wrap_key[32];
-};
-
-/* Long term flash storage for tree metadata. */
-struct PW_PACKED pw_long_term_storage_t {
- uint16_t storage_version;
-
- /* log2(Fan out). */
- struct bits_per_level_t bits_per_level;
- /* Height of the tree or param_l / bits_per_level. */
- struct height_t height;
-
- /* Random bits used as part of the key derivation process. */
- uint8_t key_derivation_nonce[16];
-};
-
-struct PW_PACKED pw_log_storage_t {
- uint16_t storage_version;
- uint32_t restart_count;
- struct pw_get_log_entry_t entries[PW_LOG_ENTRY_COUNT];
-};
-
-/* Do not remove fields within the same PW_LEAF_MAJOR_VERSION. */
-/* Encrypted part of the leaf data.
- */
-struct PW_PACKED PW_ALIGN_TO_BLK leaf_sensitive_data_t {
- uint8_t low_entropy_secret[PW_SECRET_SIZE];
- uint8_t high_entropy_secret[PW_SECRET_SIZE];
- uint8_t reset_secret[PW_SECRET_SIZE];
-};
-
-/* Represents leaf data in a form that can be exported for storage. */
-struct PW_PACKED wrapped_leaf_data_t {
- /* This is first so that head.leaf_version will be the first field
- * in the struct to keep the meaning of the struct from becoming
- * ambiguous across versions.
- */
- struct leaf_header_t head;
- /* Covers .head, .pub, and .cipher_text. */
- uint8_t hmac[PW_HASH_SIZE];
- uint8_t iv[PW_WRAP_BLOCK_SIZE];
- struct leaf_public_data_t pub;
- uint8_t cipher_text[sizeof(struct leaf_sensitive_data_t)];
-};
-
-/* Represents encrypted leaf data after the lengths and version in the header
- * have been validated.
- */
-struct imported_leaf_data_t {
- /* This is first so that head.leaf_version will be the first field
- * in the struct to keep the meaning of the struct from becoming
- * ambiguous across versions.
- */
- const struct leaf_header_t *head;
- /* Covers .head, .pub, and .cipher_text. */
- const uint8_t *hmac;
- const uint8_t *iv;
- const struct leaf_public_data_t *pub;
- const uint8_t *cipher_text;
- const uint8_t (*hashes)[PW_HASH_SIZE];
-};
-
-/* The leaf data in a clear text working format. */
-struct leaf_data_t {
- struct leaf_public_data_t pub;
- struct leaf_sensitive_data_t sec;
-};
-
-/* Key names for nvmem_vars */
-#define PW_TREE_VAR "pwT0"
-#define PW_LOG_VAR0 "pwL0"
-/* The maximum key-value pair space allowed for the values of PinWeaver until
- * the Cr50 NVRAM implementation is updated to use a separate object per
- * key value pair.
- */
-#define PW_MAX_VAR_USAGE 192
-
-/* Initializes the PinWeaver feature.
- *
- * This needs to be called prior to handling any messages.
- */
-void pinweaver_init(void);
-
-/* Handler for incoming messages after they have been reconstructed.
- *
- * merkle_tree->root needs to be updated with new_root outside of this function.
- */
-int pw_handle_request(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request,
- struct pw_response_t *response);
-
-/******************************************************************************/
-/* Struct helper functions.
- */
-
-/* Sets up pointers to the relevant fields inside an wrapped leaf based on the
- * length fields in the header. These fields should be validated prior to
- * calling this function.
- */
-void import_leaf(const struct unimported_leaf_data_t *unimported,
- struct imported_leaf_data_t *imported);
-
-/* Calculate how much is needed to add to the size of structs containing
- * an struct unimported_leaf_data_t because the variable length fields at the
- * end of the struct are not included by sizeof().
- */
-#define PW_LEAF_PAYLOAD_SIZE (sizeof(struct wrapped_leaf_data_t) - \
- sizeof(struct unimported_leaf_data_t))
-
-
-/******************************************************************************/
-/* Utility functions exported for better test coverage.
- */
-
-/* Computes the total number of the sibling hashes along a path. */
-int get_path_auxiliary_hash_count(const struct merkle_tree_t *merkle_tree);
-
-/* Computes the parent hash for an array of child hashes. */
-void compute_hash(const uint8_t hashes[][PW_HASH_SIZE], uint16_t num_hashes,
- struct index_t location,
- const uint8_t child_hash[PW_HASH_SIZE],
- uint8_t result[PW_HASH_SIZE]);
-
-/* This should only be used in tests. */
-void force_restart_count(uint32_t mock_value);
-
-/* NV RAM log functions exported for use in test code. */
-int store_log_data(const struct pw_log_storage_t *log);
-int store_merkle_tree(const struct merkle_tree_t *merkle_tree);
-int log_insert_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE],
- const uint8_t hmac[PW_HASH_SIZE]);
-int log_remove_leaf(struct label_t label, const uint8_t root[PW_HASH_SIZE]);
-int log_auth(struct label_t label, const uint8_t root[PW_HASH_SIZE], int code,
- struct pw_timestamp_t timestamp);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CROS_EC_INCLUDE_PINWEAVER_H */
diff --git a/include/pinweaver_tpm_imports.h b/include/pinweaver_tpm_imports.h
deleted file mode 100644
index f1ecd24202..0000000000
--- a/include/pinweaver_tpm_imports.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/* Compatibility layer between the TPM code and PinWeaver.
- *
- * This is needed because the headers for the TPM are not compatible with the
- * headers used by pinweaver.c. It also makes it easier to mock the
- * functionality derived from the TPM code.
- */
-
-#ifndef __CROS_EC_INCLUDE_PINWEAVER_TPM_IMPORTS_H
-#define __CROS_EC_INCLUDE_PINWEAVER_TPM_IMPORTS_H
-
-#include <stddef.h>
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* This is used to get the storage seed from the TPM implementation so
- * TPM_Clear() will break the keys used by PinWeaver so that any metadata
- * that persists on the machine storage is unusable by attackers.
- */
-void get_storage_seed(void *buf, size_t *len);
-
-/* Reads PCR values for indexes from bitmask and computes sha256 digest of
- * concatenated values. Populates the digest in |sha256_of_selected_pcr|.
- */
-uint8_t get_current_pcr_digest(const uint8_t bitmask[2],
- uint8_t sha256_of_selected_pcr[32]);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CROS_EC_INCLUDE_PINWEAVER_TPM_IMPORTS_H */
diff --git a/include/pinweaver_types.h b/include/pinweaver_types.h
deleted file mode 100644
index e8787eb29a..0000000000
--- a/include/pinweaver_types.h
+++ /dev/null
@@ -1,420 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/* Shared types between Cr50 and the AP side code. */
-
-#ifndef __CROS_EC_INCLUDE_PINWEAVER_TYPES_H
-#define __CROS_EC_INCLUDE_PINWEAVER_TYPES_H
-
-#include <stdint.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define PW_PACKED __packed
-
-#define PW_PROTOCOL_VERSION 1
-#define PW_LEAF_MAJOR_VERSION 0
-/* The change from version zero is the addition of valid_pcr_value metadata */
-#define PW_LEAF_MINOR_VERSION 1
-
-#define PW_MAX_MESSAGE_SIZE (2048 - 12 /* sizeof(struct tpm_cmd_header) */)
-
-/* The block size of encryption used for wrapped_leaf_data_t. */
-#define PW_WRAP_BLOCK_SIZE 16
-
-#define PW_ALIGN_TO_WRD __aligned(4)
-
-#define PW_ALIGN_TO_BLK __aligned(PW_WRAP_BLOCK_SIZE)
-
-enum pw_error_codes_enum {
- PW_ERR_VERSION_MISMATCH = 0x10000, /* EC_ERROR_INTERNAL_FIRST */
- PW_ERR_TREE_INVALID,
- PW_ERR_LENGTH_INVALID,
- PW_ERR_TYPE_INVALID,
- PW_ERR_BITS_PER_LEVEL_INVALID,
- PW_ERR_HEIGHT_INVALID,
- PW_ERR_LABEL_INVALID,
- PW_ERR_DELAY_SCHEDULE_INVALID,
- PW_ERR_PATH_AUTH_FAILED,
- PW_ERR_LEAF_VERSION_MISMATCH,
- PW_ERR_HMAC_AUTH_FAILED,
- PW_ERR_LOWENT_AUTH_FAILED,
- PW_ERR_RESET_AUTH_FAILED,
- PW_ERR_CRYPTO_FAILURE,
- PW_ERR_RATE_LIMIT_REACHED,
- PW_ERR_ROOT_NOT_FOUND,
- PW_ERR_NV_EMPTY,
- PW_ERR_NV_LENGTH_MISMATCH,
- PW_ERR_NV_VERSION_MISMATCH,
- PW_ERR_PCR_NOT_MATCH,
-};
-
-/* Represents the log2(fan out) of a tree. */
-struct PW_PACKED bits_per_level_t {
- uint8_t v;
-};
-
- /* Represent the height of a tree. */
-struct PW_PACKED height_t {
- uint8_t v;
-};
-
-/* Represents a child index of a node in a tree. */
-struct PW_PACKED index_t {
- uint8_t v;
-};
-
-/* Represents the child index for each level of a tree along a path to a leaf.
- * It is a Little-endian unsigned integer with the following value (MSB->LSB)
- * | Zero padding | 1st level index | ... | leaf index |,
- * where each index is represented by bits_per_level bits.
- */
-struct PW_PACKED label_t {
- uint64_t v;
-};
-
-/* Represents a count of failed login attempts. This is capped at UINT32_MAX. */
-struct PW_PACKED attempt_count_t {
- uint32_t v;
-};
-
-/* Represents a notion of time. */
-struct PW_PACKED pw_timestamp_t {
- /* Number of boots. This is used to track if Cr50 has rebooted since
- * timer_value was recorded.
- */
- uint32_t boot_count;
- /* Seconds since boot. */
- uint64_t timer_value;
-};
-
-/* Represents a time interval in seconds.
- *
- * This only needs to be sufficiently large to represent the longest time
- * between allowed attempts.
- */
-struct PW_PACKED time_diff_t {
- uint32_t v;
-};
-#define PW_BLOCK_ATTEMPTS UINT32_MAX
-
-/* Number of bytes required for a hash or hmac value in the merkle tree. */
-#define PW_HASH_SIZE 32
-
-/* Represents a single entry in a delay schedule table. */
-struct PW_PACKED delay_schedule_entry_t {
- struct attempt_count_t attempt_count;
- struct time_diff_t time_diff;
-};
-
-/* Represents a set of PCR values hashed into a single digest. This is a
- * criterion that can be added to a leaf. A leaf is valid only if at least one
- * of the valid_pcr_value_t criteria it contains is satisfied.
- */
-struct PW_PACKED valid_pcr_value_t {
- /* The set of PCR indexes that have to pass the validation. */
- uint8_t bitmask[2];
- /* The hash digest of the PCR values contained in the bitmask */
- uint8_t digest[32];
-};
-
-/* Represents the number of entries in the delay schedule table which can be
- * used to determine the next time an authentication attempt can be made.
- */
-#define PW_SCHED_COUNT 16
-
-/* Represents the maximum number of criteria for valid PCR values.
- */
-#define PW_MAX_PCR_CRITERIA_COUNT 2
-
-/* Number of bytes required to store a secret.
- */
-#define PW_SECRET_SIZE 32
-
-struct PW_PACKED leaf_version_t {
- /* minor comes first so this struct will be compatibile with uint32_t
- * comparisons for little endian to make version comparisons easier.
- *
- * Changes to minor versions are allowed to add new fields, but not
- * remove existing fields, and they are allowed to be interpreted by
- * previous versions---any extra fields are truncated.
- *
- * Leafs will reject future major versions assuming they are
- * incompatible, so fields in struct leaf_public_data_t and
- * struct leaf_sensitive_data_t may be removed for new major versions.
- * Upgrades across major versions will require explicit logic to
- * map the old struct to the new struct or vice versa.
- */
- uint16_t minor;
- uint16_t major;
-};
-
-/* Do not change this within the same PW_LEAF_MAJOR_VERSION. */
-struct PW_PACKED leaf_header_t {
- /* Always have leaf_version at the beginning of
- * struct wrapped_leaf_data_t to maintain preditable behavior across
- * versions.
- */
- struct leaf_version_t leaf_version;
- uint16_t pub_len;
- uint16_t sec_len;
-};
-
-/* Do not remove fields within the same PW_LEAF_MAJOR_VERSION. */
-/* Unencrypted part of the leaf data.
- */
-struct PW_PACKED leaf_public_data_t {
- struct label_t label;
- struct delay_schedule_entry_t delay_schedule[PW_SCHED_COUNT];
-
- /* State used to rate limit. */
- struct pw_timestamp_t timestamp;
- struct attempt_count_t attempt_count;
- struct valid_pcr_value_t valid_pcr_criteria[PW_MAX_PCR_CRITERIA_COUNT];
-};
-
-/* Represents a struct of unknown length to be imported to process a request. */
-struct PW_PACKED unimported_leaf_data_t {
- /* This is first so that head.leaf_version will be the first field
- * in the struct to make handling different struct versions easier.
- */
- struct leaf_header_t head;
- /* Covers .head, .iv, and .payload (excluding path_hashes) */
- uint8_t hmac[PW_HASH_SIZE];
- uint8_t iv[PW_WRAP_BLOCK_SIZE];
- /* This field is treated as having a zero size by the compiler so the
- * actual size needs to be added to the size of this struct. This allows
- * for forward compatibility using the pub_len and sec_len fields in the
- * header.
- *
- * Has following layout:
- * Required:
- * uint8_t pub_data[head.pub_len];
- * uint8_t ciphter_text[head.sec_len];
- *
- * For Requests only:
- * uint8_t path_hashes[get_path_auxiliary_hash_count(.)][PW_HASH_SIZE];
- */
- uint8_t payload[];
-};
-
-/******************************************************************************/
-/* Message structs
- *
- * The message format is a pw_request_header_t followed by the data
- */
-
-enum pw_message_type_enum {
- PW_MT_INVALID = 0,
-
- /* Request / "Question" types. */
- PW_RESET_TREE = 1,
- PW_INSERT_LEAF,
- PW_REMOVE_LEAF,
- PW_TRY_AUTH,
- PW_RESET_AUTH,
- PW_GET_LOG,
- PW_LOG_REPLAY,
-};
-
-struct PW_PACKED pw_message_type_t {
- uint8_t v;
-};
-
-struct PW_PACKED pw_request_header_t {
- uint8_t version;
- struct pw_message_type_t type;
- uint16_t data_length;
-};
-
-struct PW_PACKED pw_response_header_t {
- uint8_t version;
- uint16_t data_length; /* Does not include the header. */
- uint32_t result_code;
- uint8_t root[PW_HASH_SIZE];
-};
-
-struct PW_PACKED pw_request_reset_tree_t {
- struct bits_per_level_t bits_per_level;
- struct height_t height;
-};
-
-/* This is only used for parsing incoming data of version 0:0 */
-struct PW_PACKED pw_request_insert_leaf00_t {
- struct label_t label;
- struct delay_schedule_entry_t delay_schedule[PW_SCHED_COUNT];
- uint8_t low_entropy_secret[PW_SECRET_SIZE];
- uint8_t high_entropy_secret[PW_SECRET_SIZE];
- uint8_t reset_secret[PW_SECRET_SIZE];
- /* This is a variable length field because it size is determined at
- * runtime based on the chosen tree parameters. Its size is treated as
- * zero by the compiler so the computed size needs to be added to the
- * size of this struct in order to determine the actual size. This field
- * has the form:
- * uint8_t path_hashes[get_path_auxiliary_hash_count(.)][PW_HASH_SIZE];
- */
- uint8_t path_hashes[][PW_HASH_SIZE];
-};
-
-struct PW_PACKED pw_request_insert_leaf_t {
- struct label_t label;
- struct delay_schedule_entry_t delay_schedule[PW_SCHED_COUNT];
- uint8_t low_entropy_secret[PW_SECRET_SIZE];
- uint8_t high_entropy_secret[PW_SECRET_SIZE];
- uint8_t reset_secret[PW_SECRET_SIZE];
- struct valid_pcr_value_t valid_pcr_criteria[PW_MAX_PCR_CRITERIA_COUNT];
- /* This is a variable length field because it size is determined at
- * runtime based on the chosen tree parameters. Its size is treated as
- * zero by the compiler so the computed size needs to be added to the
- * size of this struct in order to determine the actual size. This field
- * has the form:
- * uint8_t path_hashes[get_path_auxiliary_hash_count(.)][PW_HASH_SIZE];
- */
- uint8_t path_hashes[][PW_HASH_SIZE];
-};
-
-struct PW_PACKED pw_response_insert_leaf_t {
- struct unimported_leaf_data_t unimported_leaf_data;
-};
-
-struct PW_PACKED pw_request_remove_leaf_t {
- struct label_t leaf_location;
- uint8_t leaf_hmac[PW_HASH_SIZE];
- /* See (struct pw_request_insert_leaf_t).path_hashes. */
- uint8_t path_hashes[][PW_HASH_SIZE];
-};
-
-struct PW_PACKED pw_request_try_auth_t {
- uint8_t low_entropy_secret[PW_SECRET_SIZE];
- struct unimported_leaf_data_t unimported_leaf_data;
-};
-
-/* This is only used to send response data of version 0:0 */
-struct PW_PACKED pw_response_try_auth00_t {
- /* Valid for the PW_ERR_RATE_LIMIT_REACHED return code only. */
- struct time_diff_t seconds_to_wait;
- /* Valid for the EC_SUCCESS return code only. */
- uint8_t high_entropy_secret[PW_SECRET_SIZE];
- /* Valid for the PW_ERR_LOWENT_AUTH_FAILED and EC_SUCCESS return codes.
- */
- struct unimported_leaf_data_t unimported_leaf_data;
-};
-
-struct PW_PACKED pw_response_try_auth_t {
- /* Valid for the PW_ERR_RATE_LIMIT_REACHED return code only. */
- struct time_diff_t seconds_to_wait;
- /* Valid for the EC_SUCCESS return code only. */
- uint8_t high_entropy_secret[PW_SECRET_SIZE];
- /* Valid for the EC_SUCCESS return code only. */
- uint8_t reset_secret[PW_SECRET_SIZE];
- /* Valid for the PW_ERR_LOWENT_AUTH_FAILED and EC_SUCCESS return codes.
- */
- struct unimported_leaf_data_t unimported_leaf_data;
-};
-
-struct PW_PACKED pw_request_reset_auth_t {
- uint8_t reset_secret[PW_SECRET_SIZE];
- struct unimported_leaf_data_t unimported_leaf_data;
-};
-
-struct PW_PACKED pw_response_reset_auth_t {
- uint8_t high_entropy_secret[PW_SECRET_SIZE];
- struct unimported_leaf_data_t unimported_leaf_data;
-};
-
-struct PW_PACKED pw_request_get_log_t {
- /* The root on the CrOS side that needs to be brought back in sync with
- * the root on Cr50. If this doesn't match a log entry, the entire log
- * is returned.
- */
- uint8_t root[PW_HASH_SIZE];
-};
-
-struct PW_PACKED pw_request_log_replay_t {
- /* The root hash after the desired log event.
- * The log entry that matches this hash contains all the necessary
- * data to update wrapped_leaf_data
- */
- uint8_t log_root[PW_HASH_SIZE];
- struct unimported_leaf_data_t unimported_leaf_data;
-};
-
-struct PW_PACKED pw_response_log_replay_t {
- struct unimported_leaf_data_t unimported_leaf_data;
-};
-
-struct PW_PACKED pw_get_log_entry_t {
- /* The root hash after this operation. */
- uint8_t root[PW_HASH_SIZE];
- /* The label of the leaf that was operated on. */
- struct label_t label;
- /* The type of operation. This should be one of
- * PW_INSERT_LEAF,
- * PW_REMOVE_LEAF,
- * PW_TRY_AUTH.
- *
- * Successful PW_RESET_AUTH events are included
- */
- struct pw_message_type_t type;
- /* Type specific fields. */
- union {
- /* PW_INSERT_LEAF */
- uint8_t leaf_hmac[PW_HASH_SIZE];
- /* PW_REMOVE_LEAF */
- /* PW_TRY_AUTH */
- struct PW_PACKED {
- struct pw_timestamp_t timestamp;
- int32_t return_code;
- };
- };
-};
-
-struct PW_PACKED pw_request_t {
- struct pw_request_header_t header;
- union {
- struct pw_request_reset_tree_t reset_tree;
- struct pw_request_insert_leaf00_t insert_leaf00;
- struct pw_request_insert_leaf_t insert_leaf;
- struct pw_request_remove_leaf_t remove_leaf;
- struct pw_request_try_auth_t try_auth;
- struct pw_request_reset_auth_t reset_auth;
- struct pw_request_get_log_t get_log;
- struct pw_request_log_replay_t log_replay;
- } data;
-};
-
-struct PW_PACKED pw_response_t {
- struct pw_response_header_t header;
- union {
-
- struct pw_response_insert_leaf_t insert_leaf;
- struct pw_response_try_auth00_t try_auth00;
- struct pw_response_try_auth_t try_auth;
- struct pw_response_reset_auth_t reset_auth;
- /* An array with as many entries as are present in the log up to
- * the present time or will fit in the message.
- */
- uint8_t get_log[0];
- struct pw_response_log_replay_t log_replay;
- } data;
-};
-
-/* An explicit limit is set because struct unimported_leaf_data_t can have more
- * than one variable length field so the max length for these fields needs to be
- * defined so that meaningful parameter limits can be set to validate the tree
- * parameters.
- *
- * 1024 was chosen because it is 1/2 of 2048 and allows for a maximum tree
- * height of 10 for the default fan-out of 4.
- */
-#define PW_MAX_PATH_SIZE 1024
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __CROS_EC_INCLUDE_PINWEAVER_TYPES_H */
diff --git a/include/tpm_manufacture.h b/include/tpm_manufacture.h
deleted file mode 100644
index 4d62bb0e3b..0000000000
--- a/include/tpm_manufacture.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright 2016 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.
- */
-
-/*
- * This header declares the TPM manufacture related interface.
- * Individual boards are expected to provide implementations.
- */
-
-#ifndef __CROS_EC_TPM_MANUFACTURE_H
-#define __CROS_EC_TPM_MANUFACTURE_H
-
-/* Returns non-zero if the TPM manufacture steps have been completed. */
-int tpm_manufactured(void);
-
-/* Codes for success and various manufacturing error conditions. */
-enum manufacturing_status {
- mnf_success = 0,
- mnf_no_certs = 1,
- mnf_eps_decr = 2,
- mnf_bad_rsa_size = 3,
- mnf_bad_total_size = 4,
- mnf_bad_rsa_type = 5,
- mnf_bad_ecc_type = 6,
- mnf_hmac_mismatch = 7,
- mnf_rsa_proc = 8,
- mnf_ecc_proc = 9,
- mnf_store = 10,
- mnf_manufactured = 11,
- mnf_unverified_cert = 12,
-};
-
-enum manufacturing_status tpm_endorse(void);
-
-#endif /* __CROS_EC_TPM_MANUFACTURE_H */
diff --git a/include/tpm_nvmem.h b/include/tpm_nvmem.h
deleted file mode 100644
index 2508c9ae65..0000000000
--- a/include/tpm_nvmem.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* Copyright 2018 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.
- *
- * TPM NVMEM definitions.
- */
-#ifndef __CROS_EC_TPM_NVMEM_H
-#define __CROS_EC_TPM_NVMEM_H
-
-#define FIRMWARE_NV_INDEX 0x1007
-#define FWMP_NV_INDEX 0x100a
-
-#endif /* __CROS_EC_TPM_NVMEM_H */
diff --git a/include/tpm_registers.h b/include/tpm_registers.h
deleted file mode 100644
index dcdbe41566..0000000000
--- a/include/tpm_registers.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Copyright 2015 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.
- */
-
-/*
- * This defines the interface functions for TPM SPI Hardware Protocol. The SPI
- * master reads or writes between 1 and 64 bytes to a register designated by a
- * 24-bit address. There is no provision for error reporting at this level.
- */
-
-#ifndef __CROS_EC_TPM_REGISTERS_H
-#define __CROS_EC_TPM_REGISTERS_H
-
-#include <stdint.h>
-
-#include "common.h"
-
-/* The SPI master is writing data into a TPM register. */
-void tpm_register_put(uint32_t regaddr,
- const uint8_t *data, uint32_t data_size);
-
-/* The SPI master is reading data from a TPM register. */
-void tpm_register_get(uint32_t regaddr, uint8_t *dest, uint32_t data_size);
-
-/* Get the current value of the burst size field of the status register. */
-size_t tpm_get_burst_size(void);
-
-/*
- * Register functions to start and stop TPM communications layer. The
- * communications layer should be kept down while TPM is being reset.
- */
-typedef void (*interface_control_func)(void);
-void tpm_register_interface(interface_control_func interface_start,
- interface_control_func interface_stop);
-
-/*
- * This requests the TPM task to reset itself.
- *
- * If wait_until_done is false, it returns EC_SUCCESS immediately. Otherwise it
- * returns EC_SUCCESS after the reset has completed, or an error code on
- * failure.
- *
- * If wipe_nvmem_first is true, the caller is expected to keep the rest of the
- * system in reset until TPM wipeout is completed.
- */
-int tpm_reset_request(int wait_until_done, int wipe_nvmem_first);
-
-/*
- * Tell the TPM task to re-enable nvmem commits.
- *
- * NOTE: This function is NOT to be used freely, but only meant to be used in
- * exceptional cases such as unlocking the console following a TPM wipe.
- */
-void tpm_reinstate_nvmem_commits(void);
-
-/*
- * To be called by functions running on the TPM task context. Returns
- * EC_SUCCESS on successful reset.
- */
-int tpm_sync_reset(int wipe_first);
-
-/*
- * It shuts down the tpm interface, until next tpm reset event.
- */
-void tpm_stop(void);
-
-/*
- * This structure describes the header of all commands and responses sent and
- * received over TPM FIFO.
- *
- * Note that all fields are stored in the network (big endian) byte order.
- */
-
-struct tpm_cmd_header {
- uint16_t tag;
- uint32_t size;
- uint32_t command_code;
- uint16_t subcommand_code; /* Not a standard field. */
-} __packed;
-
-/*
- * This function allows to process a TPM command coming from elsewhere, not
- * from the communications interface.
- *
- * A common use case would be making cryptographic calculation on task
- * contexts where stack the size is not large enough, for instance console
- * commands. This function will block to let the TPM task a chance to run to
- * execute the command and return the result in the same buffer.
- *
- * @param tpmh pointer to a buffer containing a marshalled TPM command, if it
- * arrived over the communications channel. One of the header
- * fields defines the command size.
- *
- * @param buffer_size the size of the buffer pointed to by tpmh - tells the
- * TPM task how much room there is to store the response.
- *
- * Command execution result is reported in the response body.
- *
- * The extension command handler will consider all these commands to come from
- * the USB interface, since the only current users for this are console
- * commands.
- */
-void tpm_alt_extension(struct tpm_cmd_header *tpmh, size_t buffer_size);
-
-/*
- * The only TPM2 command we care about on the driver level, see
- * crosbug.com/p/55667 for detals.
- */
-#define TPM2_PCR_Read 0x0000017e
-#define TPM2_Startup 0x00000144
-
-/* TPM mode */
-enum tpm_modes {
- TPM_MODE_ENABLED_TENTATIVE = 0,
- TPM_MODE_ENABLED = 1,
- TPM_MODE_DISABLED = 2,
- TPM_MODE_MAX,
-};
-
-/*
- * This function returns the current TPM_MODE value.
- */
-enum tpm_modes get_tpm_mode(void);
-
-#endif /* __CROS_EC_TPM_REGISTERS_H */
diff --git a/include/tpm_vendor_cmds.h b/include/tpm_vendor_cmds.h
deleted file mode 100644
index 5afd1fc84b..0000000000
--- a/include/tpm_vendor_cmds.h
+++ /dev/null
@@ -1,252 +0,0 @@
-/* Copyright 2016 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.
- */
-
-#ifndef __INCLUDE_TPM_VENDOR_CMDS_H
-#define __INCLUDE_TPM_VENDOR_CMDS_H
-
-#include "common.h" /* For __packed. */
-#include "compile_time_macros.h" /* For BIT. */
-
-/*
- * This file includes definitions of extended/vendor TPM2 commands and their
- * return codes. The definitions are shared between the embedded code and the
- * gsctool utility running on the host.
- */
-
-/* Extension and vendor commands. */
-enum vendor_cmd_cc {
- /* Original extension commands */
- EXTENSION_AES = 0,
- EXTENSION_HASH = 1,
- EXTENSION_RSA = 2,
- EXTENSION_ECC = 3,
- EXTENSION_FW_UPGRADE = 4,
- EXTENSION_HKDF = 5,
- EXTENSION_ECIES = 6,
- EXTENSION_POST_RESET = 7,
-
- LAST_EXTENSION_COMMAND = 15,
-
- /* Our TPMv2 vendor-specific command codes. 16 bits available. */
- VENDOR_CC_GET_LOCK = 16,
- VENDOR_CC_SET_LOCK = 17,
- VENDOR_CC_SYSINFO = 18,
- /*
- * VENDOR_CC_IMMEDIATE_RESET may have an argument, which is a (uint16_t)
- * time delay (in milliseconds) in doing a reset. Max value is 1000.
- * The command may also be called without an argument, which will be
- * regarded as zero time delay.
- */
- VENDOR_CC_IMMEDIATE_RESET = 19,
- VENDOR_CC_INVALIDATE_INACTIVE_RW = 20,
- VENDOR_CC_COMMIT_NVMEM = 21,
- /* DEPRECATED(22): deep sleep control command. */
- VENDOR_CC_REPORT_TPM_STATE = 23,
- VENDOR_CC_TURN_UPDATE_ON = 24,
- VENDOR_CC_GET_BOARD_ID = 25,
- VENDOR_CC_SET_BOARD_ID = 26,
- VENDOR_CC_U2F_APDU = 27,
- VENDOR_CC_POP_LOG_ENTRY = 28,
- VENDOR_CC_GET_REC_BTN = 29,
- VENDOR_CC_RMA_CHALLENGE_RESPONSE = 30,
- /* DEPRECATED(31): CCD password command (now part of VENDOR_CC_CCD) */
- /*
- * Disable factory mode. Reset all ccd capabilities to default and reset
- * write protect to follow battery presence.
- */
- VENDOR_CC_DISABLE_FACTORY = 32,
- /* DEPRECATED(33): Manage CCD password phase */
- VENDOR_CC_CCD = 34,
- VENDOR_CC_GET_ALERTS_DATA = 35,
- VENDOR_CC_SPI_HASH = 36,
- VENDOR_CC_PINWEAVER = 37,
- /*
- * Check the factory reset settings. If they're all set correctly, do a
- * factory reset to enable ccd factory mode. All capabilities will be
- * set to Always and write protect will be permanently disabled. This
- * mode can't be reset unless VENDOR_CC_DISABLE_FACTORY is called or
- * the 'ccd reset' console command is run.
- */
- VENDOR_CC_RESET_FACTORY = 38,
- /*
- * Get the write protect setting. This will return a single byte with
- * bits communicating the write protect setting as described by the
- * WPV subcommands.
- */
- VENDOR_CC_WP = 39,
- /*
- * Either enable or disable TPM mode. This is allowed for one-time only
- * until next TPM reset EVENT. In other words, once TPM mode is set,
- * then it cannot be altered to the other mode value. The allowed input
- * values are either TPM_MODE_ENABLED or TPM_MODE_DISABLED as defined
- * in 'enum tpm_modes', tpm_registers.h.
- * If the input size is zero, it won't change TPM_MODE.
- * If either the input size is zero or the input value is valid,
- * it will respond with the current tpm_mode value in uint8_t format.
- *
- * Return code:
- * VENDOR_RC_SUCCESS: completed successfully.
- * VENDOR_RC_INTERNAL_ERROR: failed for an internal reason.
- * VENDOR_RC_NOT_ALLOWED: failed in changing TPM_MODE,
- * since it is already set.
- * VENDOR_RC_NO_SUCH_SUBCOMMAND: failed because the given input
- * is undefined.
- */
- VENDOR_CC_TPM_MODE = 40,
- /*
- * Initializes INFO1 SN data space, and sets SN hash. Takes three
- * int32 as parameters, which are written as the SN hash.
- */
- VENDOR_CC_SN_SET_HASH = 41,
- /*
- * Increments the RMA count in the INFO1 SN data space. The space must
- * have been previously initialized with the _SET_HASH command above for
- * this to succeed. Takes one byte as parameter, which indicates the
- * number to increment the RMA count by; this is typically 1 or 0.
- *
- * Incrementing the RMA count by 0 will set the RMA indicator, but not
- * incremement the count. This is useful to mark that a device has been
- * RMA'd, but that we were not able to log the new serial number.
- *
- * Incrementing the count by the maximum RMA count (currently 7) will
- * always set the RMA count to the maximum value, regardless of the
- * previous value. This can be used with any device, regardless of
- * current state, to mark it as RMA'd but with an unknown RMA count.
- */
- VENDOR_CC_SN_INC_RMA = 42,
-
- /*
- * Gets the latched state of a power button press to indicate user
- * recent user presence. The power button state is automatically cleared
- * after PRESENCE_TIMEOUT.
- */
- VENDOR_CC_GET_PWR_BTN = 43,
-
- /*
- * U2F commands.
- */
- VENDOR_CC_U2F_GENERATE = 44,
- VENDOR_CC_U2F_SIGN = 45,
- VENDOR_CC_U2F_ATTEST = 46,
-
- VENDOR_CC_FLOG_TIMESTAMP = 47,
- VENDOR_CC_ENDORSEMENT_SEED = 48,
-
- VENDOR_CC_U2F_MODE = 49,
-
- /*
- * HMAC-SHA256 DRBG invocation for ACVP tests
- */
- VENDOR_CC_DRBG_TEST = 50,
-
- VENDOR_CC_TRNG_TEST = 51,
-
- LAST_VENDOR_COMMAND = 65535,
-};
-
-/*
- * Error codes reported by extension and vendor commands.
- *
- * As defined by the TPM2 spec, the TPM response code is all zero for success,
- * and errors are a little complicated:
- *
- * Bits 31:12 must be zero.
- *
- * Bit 11 S=0 Error
- * Bit 10 T=1 Vendor defined response code
- * Bit 9 r=0 reserved
- * Bit 8 V=1 Conforms to TPMv2 spec
- * Bit 7 F=0 Confirms to Table 14, Format-Zero Response Codes
- * Bits 6:0 num 128 possible failure reasons
- */
-
-enum vendor_cmd_rc {
- /* EXTENSION_HASH error codes */
- /* Attempt to start a session on an active handle. */
- EXC_HASH_DUPLICATED_HANDLE = 1,
- EXC_HASH_TOO_MANY_HANDLES = 2, /* No room to allocate a new context. */
- /* Continuation/finish on unknown context. */
- EXC_HASH_UNKNOWN_CONTEXT = 3,
-
- /* Our TPMv2 vendor-specific response codes. */
- VENDOR_RC_SUCCESS = 0,
- VENDOR_RC_BOGUS_ARGS = 1,
- VENDOR_RC_READ_FLASH_FAIL = 2,
- VENDOR_RC_WRITE_FLASH_FAIL = 3,
- VENDOR_RC_REQUEST_TOO_BIG = 4,
- VENDOR_RC_RESPONSE_TOO_BIG = 5,
- VENDOR_RC_INTERNAL_ERROR = 6,
- VENDOR_RC_NOT_ALLOWED = 7,
- VENDOR_RC_NO_SUCH_SUBCOMMAND = 8,
- VENDOR_RC_IN_PROGRESS = 9,
- VENDOR_RC_PASSWORD_REQUIRED = 10,
-
- /* Maximum possible failure reason. */
- VENDOR_RC_NO_SUCH_COMMAND = 127,
-
- /*
- * Bits 10 and 8 set, this is to be ORed with the rest of the error
- * values to make the combined value compliant with the spec
- * requirements.
- */
- VENDOR_RC_ERR = 0x500,
-};
-
-/*
- * The TPMv2 Spec mandates that vendor-specific command codes have bit 29 set,
- * while bits 15-0 indicate the command. All other bits should be zero.
- * We will define one of those 16-bit command values for Cr50 purposes, and use
- * the subcommand_code in struct tpm_cmd_header to further distinguish the
- * desired operation.
- */
-#define TPM_CC_VENDOR_BIT_MASK 0x20000000
-#define VENDOR_CC_MASK 0x0000ffff
-/* Our vendor-specific command codes go here */
-#define TPM_CC_VENDOR_CR50 0x0000
-
-/*** Structures and constants for VENDOR_CC_SPI_HASH ***/
-
-enum vendor_cc_spi_hash_request_subcmd {
- /* Relinquish the bus */
- SPI_HASH_SUBCMD_DISABLE = 0,
- /* Acquire the bus for AP SPI */
- SPI_HASH_SUBCMD_AP = 1,
- /* Acquire the bus for EC SPI */
- SPI_HASH_SUBCMD_EC = 2,
- /* Hash SPI data */
- SPI_HASH_SUBCMD_SHA256 = 4,
- /* Read SPI data */
- SPI_HASH_SUBCMD_DUMP = 5,
- /* Poll spi hash PP state. */
- SPI_HASH_PP_POLL = 6,
-};
-
-enum vendor_cc_spi_hash_request_flags {
- /* EC uses gang programmer mode */
- SPI_HASH_FLAG_EC_GANG = BIT(0),
-};
-
-/* Structure for VENDOR_CC_SPI_HASH request which follows tpm_header */
-struct vendor_cc_spi_hash_request {
- uint8_t subcmd; /* See vendor_cc_spi_hash_request_subcmd */
- uint8_t flags; /* See vendor_cc_spi_hash_request_flags */
- /* Offset and size used by SHA256 and DUMP; ignored by other subcmds */
- uint32_t offset; /* Offset in flash to hash/read */
- uint32_t size; /* Size in bytes to hash/read */
-} __packed;
-
-/* Maximum size of a response = SHA-256 hash or 1-32 bytes of data */
-#define SPI_HASH_MAX_RESPONSE_BYTES 32
-
-/*
- * Subcommand code, used to set write protect.
- */
-#define WPV_UPDATE BIT(0)
-#define WPV_ENABLE BIT(1)
-#define WPV_FORCE BIT(2)
-#define WPV_ATBOOT_SET BIT(3)
-#define WPV_ATBOOT_ENABLE BIT(4)
-
-#endif /* __INCLUDE_TPM_VENDOR_CMDS_H */
diff --git a/include/u2f.h b/include/u2f.h
deleted file mode 100644
index 0f54dfc990..0000000000
--- a/include/u2f.h
+++ /dev/null
@@ -1,126 +0,0 @@
-// Common U2F raw message format header - Review Draft
-// 2014-10-08
-// Editor: Jakob Ehrensvard, Yubico, jakob@yubico.com
-
-#ifndef __U2F_H_INCLUDED__
-#define __U2F_H_INCLUDED__
-
-#ifdef _MSC_VER // Windows
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned int uint32_t;
-typedef unsigned long int uint64_t;
-#else
-#include <stdint.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// General constants
-
-#define U2F_EC_KEY_SIZE 32 // EC key size in bytes
-#define U2F_EC_POINT_SIZE ((U2F_EC_KEY_SIZE * 2) + 1) // Size of EC point
-#define U2F_MAX_KH_SIZE 128 // Max size of key handle
-#define U2F_MAX_ATT_CERT_SIZE 2048 // Max size of attestation certificate
-#define U2F_MAX_EC_SIG_SIZE 72 // Max size of DER coded EC signature
-#define U2F_CTR_SIZE 4 // Size of counter field
-#define U2F_APPID_SIZE 32 // Size of application id
-#define U2F_CHAL_SIZE 32 // Size of challenge
-#define U2F_MAX_ATTEST_SIZE 256 // Size of largest blob to sign
-#define U2F_P256_SIZE 32
-#define U2F_FIXED_KH_SIZE 64 // Size of fixed size key handles
-
-#define ENC_SIZE(x) ((x + 7) & 0xfff8)
-
-// EC (uncompressed) point
-
-#define U2F_POINT_UNCOMPRESSED 0x04 // Uncompressed point format
-
-typedef struct {
- uint8_t pointFormat; // Point type
- uint8_t x[U2F_EC_KEY_SIZE]; // X-value
- uint8_t y[U2F_EC_KEY_SIZE]; // Y-value
-} U2F_EC_POINT;
-
-// Request Flags.
-
-#define U2F_AUTH_ENFORCE 0x03 // Enforce user presence and sign
-#define U2F_AUTH_CHECK_ONLY 0x07 // Check only
-#define U2F_AUTH_FLAG_TUP 0x01 // Test of user presence set
-
-// TODO(louiscollard): Add Descriptions.
-
-typedef struct {
- uint8_t appId[U2F_APPID_SIZE]; // Application id
- uint8_t userSecret[U2F_P256_SIZE];
- uint8_t flags;
-} U2F_GENERATE_REQ;
-
-typedef struct {
- U2F_EC_POINT pubKey; // Generated public key
- uint8_t keyHandle[U2F_FIXED_KH_SIZE]; // Key handle
-} U2F_GENERATE_RESP;
-
-typedef struct {
- uint8_t appId[U2F_APPID_SIZE]; // Application id
- uint8_t userSecret[U2F_P256_SIZE];
- uint8_t keyHandle[U2F_FIXED_KH_SIZE]; // Key handle
- uint8_t hash[U2F_P256_SIZE];
- uint8_t flags;
-} U2F_SIGN_REQ;
-
-typedef struct {
- uint8_t sig_r[U2F_P256_SIZE]; // Signature
- uint8_t sig_s[U2F_P256_SIZE]; // Signature
-} U2F_SIGN_RESP;
-
-typedef struct {
- uint8_t userSecret[U2F_P256_SIZE];
- uint8_t format;
- uint8_t dataLen;
- uint8_t data[U2F_MAX_ATTEST_SIZE];
-} U2F_ATTEST_REQ;
-
-typedef struct {
- uint8_t sig_r[U2F_P256_SIZE];
- uint8_t sig_s[U2F_P256_SIZE];
-} U2F_ATTEST_RESP;
-
-// Command status responses
-
-#define U2F_SW_NO_ERROR 0x9000 // SW_NO_ERROR
-#define U2F_SW_WRONG_DATA 0x6A80 // SW_WRONG_DATA
-#define U2F_SW_CONDITIONS_NOT_SATISFIED 0x6985 // SW_CONDITIONS_NOT_SATISFIED
-#define U2F_SW_COMMAND_NOT_ALLOWED 0x6986 // SW_COMMAND_NOT_ALLOWED
-#define U2F_SW_INS_NOT_SUPPORTED 0x6D00 // SW_INS_NOT_SUPPORTED
-
-// Protocol extensions
-
-// Non-standardized command status responses
-#define U2F_SW_CLA_NOT_SUPPORTED 0x6E00
-#define U2F_SW_WRONG_LENGTH 0x6700
-#define U2F_SW_WTF 0x6f00
-
-// Additional flags for P1 field
-#define G2F_ATTEST 0x80 // Fixed attestation key
-#define G2F_CONSUME 0x02 // Consume presence
-
-// The key handle format was changed when support for user secrets was added.
-// U2F_SIGN requests that specify this flag will first try to validate the
-// key handle as a new format key handle, and if that fails, will fall back
-// to treating it as a legacy key handle (without user secrets).
-#define SIGN_LEGACY_KH 0x40
-
-// U2F Attest format for U2F Register Response.
-#define U2F_ATTEST_FORMAT_REG_RESP 0
-
-// Vendor command to enable/disable the extensions
-#define U2F_VENDOR_MODE U2F_VENDOR_LAST
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // __U2F_H_INCLUDED__
diff --git a/include/u2f_impl.h b/include/u2f_impl.h
deleted file mode 100644
index 0732a1b72d..0000000000
--- a/include/u2f_impl.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* 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.
- */
-
-/* U2F implementation-specific callbacks and parameters. */
-
-#ifndef __CROS_EC_U2F_IMPL_H
-#define __CROS_EC_U2F_IMPL_H
-
-#include "common.h"
-#include "cryptoc/p256.h"
-
-/* ---- Physical presence ---- */
-
-enum touch_state {
- POP_TOUCH_NO = 0, /* waiting for a user touch */
- POP_TOUCH_YES = 1, /* touch recorded and latched */
-};
-
-/*
- * Check whether the user presence event was latched.
- *
- * @param consume reset the latched touch event and the presence LED.
- * @return POP_TOUCH_NO or POP_TOUCH_YES.
- */
-enum touch_state pop_check_presence(int consume);
-
-/* ---- platform cryptography hooks ---- */
-
-/**
- * Generate an origin-specific ECDSA keypair.
- *
- * Calculates a diversified chip-unique 256b value.
- *
- * @param seed ptr to store 32-byte seed to regenerate this key on this chip
- * @param d pointer to ECDSA private key
- * @param pk_x pointer to public key point
- * @param pk_y pointer to public key point
- *
- * @return EC_SUCCESS if a valid keypair was created.
- */
-int u2f_origin_keypair(uint8_t *seed, p256_int *d,
- p256_int *pk_x, p256_int *pk_y);
-
-/**
- * Reconstitute the origin ECDSA private key from its seed.
- *
- * @param seed value returned by origin_keypair.
- * @param d ptr to store the retrieved private key.
- * @return EC_SUCCESS if we retrieved the key.
- */
-int u2f_origin_key(const uint8_t *seed, p256_int *d);
-
-/**
- * Pack the specified origin, user secret and origin-specific seed
- * into a key handle.
- *
- * @param origin pointer to origin id
- * @param user pointer to user secret
- * @param pointer to origin-specific random seed
- *
- * @return EC_SUCCESS if a valid keypair was created.
- */
-int u2f_origin_user_keyhandle(const uint8_t *origin,
- const uint8_t *user,
- const uint8_t *seed,
- uint8_t *key_handle);
-
-/**
- * Generate an origin and user-specific ECDSA keypair from the specified
- * key handle.
- *
- * If pk_x and pk_y are NULL, public key generation will be skipped.
- *
- * @param key_handle pointer to the 64 byte key handle
- * @param d pointer to ECDSA private key
- * @param pk_x pointer to public key point
- * @param pk_y pointer to public key point
- *
- * @return EC_SUCCESS if a valid keypair was created.
- */
-int u2f_origin_user_keypair(const uint8_t *key_handle,
- p256_int *d,
- p256_int *pk_x,
- p256_int *pk_y);
-
-/***
- * Generate a hardware derived 256b private key.
- *
- * @param kek ptr to store the generated key.
- * @param key_len size of the storage buffer. Should be 32 bytes.
- * @return EC_SUCCESS if a valid key was created.
- */
-int u2f_gen_kek(const uint8_t *origin, uint8_t *kek, size_t key_len);
-
-/**
- * Generate a hardware derived ECDSA keypair for individual attestation.
- *
- * @param seed ptr to store 32-byte seed to regenerate this key on this chip
- * @param d pointer to ECDSA private key
- * @param pk_x pointer to public key point
- * @param pk_y pointer to public key point
- *
- * @return EC_SUCCESS if a valid keypair was created.
- */
-int g2f_individual_keypair(p256_int *d, p256_int *pk_x, p256_int *pk_y);
-
-/***
- * Generates and persists to nvram a new seed that will be used to
- * derive kek in future calls to u2f_gen_kek().
- *
- * @param commit whether to commit nvram changes before returning.
- * @return EC_SUCCESS if seed was successfully created
- * (and persisted if requested).
- */
-int u2f_gen_kek_seed(int commit);
-
-/* Maximum size in bytes of G2F attestation certificate. */
-#define G2F_ATTESTATION_CERT_MAX_LEN 315
-
-/**
- * Gets the x509 certificate for the attestation keypair returned
- * by g2f_individual_keypair().
- *
- * @param buf pointer to a buffer that must be at least
- * G2F_ATTESTATION_CERT_MAX_LEN bytes.
- * @return size of certificate written to buf, 0 on error.
- */
-int g2f_attestation_cert(uint8_t *buf);
-
-#endif /* __CROS_EC_U2F_IMPL_H */
diff --git a/include/usb_api.h b/include/usb_api.h
index 481a77272c..79ee9406e9 100644
--- a/include/usb_api.h
+++ b/include/usb_api.h
@@ -82,11 +82,4 @@ static inline void usb_wake(void) {}
/* Board-specific USB wake, for side-band wake, called by usb_wake above. */
void board_usb_wake(void);
-#ifdef CONFIG_USB_SELECT_PHY
-/* Select which PHY to use. */
-void usb_select_phy(uint32_t phy);
-
-/* Get the current PHY */
-uint32_t usb_get_phy(void);
-#endif
#endif /* __CROS_EC_USB_API_H */
diff --git a/test/build.mk b/test/build.mk
index 2658cca4af..aff698f125 100644
--- a/test/build.mk
+++ b/test/build.mk
@@ -29,7 +29,6 @@ test-list-host += entropy
test-list-host += extpwr_gpio
test-list-host += fan
test-list-host += flash
-test-list-host += flash_log
test-list-host += float
test-list-host += fp
test-list-host += fpsensor
@@ -58,7 +57,6 @@ test-list-host += mutex
test-list-host += newton_fit
test-list-host += online_calibration
test-list-host += pingpong
-test-list-host += pinweaver
test-list-host += power_button
test-list-host += printf
test-list-host += queue
@@ -115,7 +113,6 @@ entropy-y=entropy.o
extpwr_gpio-y=extpwr_gpio.o
fan-y=fan.o
flash-y=flash.o
-flash_log-y=flash_log.o
fpsensor-y=fpsensor.o
fpsensor_crypto-y=fpsensor_crypto.o
fpsensor_state-y=fpsensor_state.o
@@ -141,7 +138,6 @@ kasa-y=kasa.o
mutex-y=mutex.o
newton_fit-y=newton_fit.o
pingpong-y=pingpong.o
-pinweaver-y=pinweaver.o
power_button-y=power_button.o
powerdemo-y=powerdemo.o
printf-y=printf.o
diff --git a/test/flash_log.c b/test/flash_log.c
deleted file mode 100644
index 48c842371e..0000000000
--- a/test/flash_log.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/* Copyright 2019 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.
- *
- * Test Cr-50 Non-Voltatile memory module
- */
-
-#include <stdlib.h>
-
-#include "common.h"
-#include "flash_log.h"
-#include "test_util.h"
-#include "timer.h"
-#include "util.h"
-
-struct log_stats {
- size_t total_size;
- size_t entry_count;
-};
-
-static int verify_single_entry(uint8_t fill_byte, int expected_type)
-{
- int entry_size;
- union entry_u e;
- size_t i;
- uint8_t *log_base = (void *)CONFIG_FLASH_LOG_BASE;
-
- memset(log_base, fill_byte, CONFIG_FLASH_LOG_SPACE);
- last_used_timestamp = 0;
- flash_log_init();
-
- /* After initialization there should be a single log entry. */
- entry_size = flash_log_dequeue_event(0, e.entry, sizeof(e.entry));
- TEST_ASSERT(entry_size == sizeof(e.r));
- TEST_ASSERT(e.r.type == expected_type);
-
- entry_size = flash_log_dequeue_event(e.r.timestamp, e.entry,
- sizeof(e.entry));
- TEST_ASSERT(entry_size == 0);
-
- /* Verify proper entry padding. */
- i = sizeof(e.r);
- TEST_ASSERT(i % CONFIG_FLASH_WRITE_SIZE);
- for (; i % CONFIG_FLASH_WRITE_SIZE; i++)
- TEST_ASSERT(log_base[i] == FE_LOG_PAD);
-
- TEST_ASSERT(log_base[i] == 0xff); /* First byte above padding. */
-
- return EC_SUCCESS;
-}
-
-static int test_init_from_scratch(void)
-{
- return verify_single_entry(0xff, FE_LOG_START);
-}
-
-static int test_init_from_corrupted(void)
-{
- /* Let's mess up the log space. */
- return verify_single_entry(0x55, FE_LOG_CORRUPTED);
-}
-
-static int verify_log(struct log_stats *stats)
-{
- union entry_u e;
- size_t actual_size;
- size_t actual_count;
- int entry_size;
-
- e.r.timestamp = 0;
- actual_size = 0;
- actual_count = 0;
-
- while ((entry_size = flash_log_dequeue_event(e.r.timestamp, e.entry,
- sizeof(e))) > 0) {
- actual_count++;
- actual_size += FLASH_LOG_ENTRY_SIZE(e.r.size);
- }
-
- TEST_ASSERT(entry_size == 0);
-
- stats->total_size = actual_size;
- stats->entry_count = actual_count;
-
- return EC_SUCCESS;
-}
-
-static int fill_to_threshold(size_t threshold, struct log_stats *stats)
-{
- int i;
- uint8_t entry_type;
- uint8_t payload_size;
- uint8_t p[MAX_FLASH_LOG_PAYLOAD_SIZE];
- size_t total_size;
- size_t entry_count;
-
- /* Start with an only entry in the log. */
- TEST_ASSERT(verify_single_entry(0xff, FE_LOG_START) == EC_SUCCESS);
-
- srand(0); /* Let's make sure it is consistent. */
- entry_count = 1;
- total_size = FLASH_LOG_ENTRY_SIZE(0);
-
- /* Let's fill up the log to compaction limit. */
- do {
- entry_type = rand() % 0xfe;
- payload_size = rand() % MAX_FLASH_LOG_PAYLOAD_SIZE;
- for (i = 0; i < payload_size; i++)
- p[i] = (i + entry_type) & 0xff;
-
- flash_log_add_event(entry_type, payload_size, p);
- total_size += FLASH_LOG_ENTRY_SIZE(payload_size);
- entry_count++;
- } while (total_size <= threshold);
-
- TEST_ASSERT(verify_log(stats) == EC_SUCCESS);
- TEST_ASSERT(stats->total_size == total_size);
- TEST_ASSERT(stats->entry_count == entry_count);
-
- /* This should get the log over the compaction threshold. */
- flash_log_add_event(entry_type, payload_size, p);
- TEST_ASSERT(verify_log(stats) == EC_SUCCESS);
-
- return EC_SUCCESS;
-}
-
-static int test_run_time_compaction(void)
-{
- struct log_stats stats;
-
- TEST_ASSERT(fill_to_threshold(RUN_TIME_LOG_FULL_WATERMARK, &stats) ==
- EC_SUCCESS);
-
- /*
- * Compacted space is guaranteed not to exceed the threshold plus the
- * size of the largest possible entry.
- */
- TEST_ASSERT(stats.total_size <
- (COMPACTION_SPACE_PRESERVE +
- FLASH_LOG_ENTRY_SIZE(MAX_FLASH_LOG_PAYLOAD_SIZE)));
-
- return EC_SUCCESS;
-}
-
-static int test_init_time_compaction(void)
-{
- struct log_stats stats;
-
- TEST_ASSERT(fill_to_threshold(STARTUP_LOG_FULL_WATERMARK, &stats) ==
- EC_SUCCESS);
-
- /*
- * Init should roll the log back below the compaction preservation
- * threshold.
- */
- flash_log_init();
- TEST_ASSERT(verify_log(&stats) == EC_SUCCESS);
-
- /*
- * Compacted space is guaranteed not to exceed the threshold plus the
- * size of the largest possible entry.
- */
- TEST_ASSERT(stats.total_size <
- (COMPACTION_SPACE_PRESERVE +
- FLASH_LOG_ENTRY_SIZE(MAX_FLASH_LOG_PAYLOAD_SIZE)));
-
- return EC_SUCCESS;
-}
-
-static int test_lock_failure_reporting(void)
-{
- union entry_u e;
-
- TEST_ASSERT(test_init_from_scratch() == EC_SUCCESS);
- lock_failures_count = 0;
- log_event_in_progress = 1;
-
- /* This should fail. */
- flash_log_add_event(FE_LOG_TEST, 0, NULL);
-
- /* Lock count should have been incremented. */
- TEST_ASSERT(lock_failures_count == 1);
-
- /* This should also fail. */
- TEST_ASSERT(flash_log_dequeue_event(0, e.entry, sizeof(e.entry)) ==
- -EC_ERROR_BUSY);
-
- log_event_in_progress = 0;
- /* This should succeed. */
- flash_log_add_event(FE_LOG_TEST, 0, NULL);
-
- TEST_ASSERT(lock_failures_count == 0);
-
- /* There should be three entries in the log now. */
- flash_log_dequeue_event(0, e.entry, sizeof(e.entry));
- TEST_ASSERT(e.r.type == FE_LOG_START);
-
- flash_log_dequeue_event(e.r.timestamp, e.entry, sizeof(e.entry));
- TEST_ASSERT(e.r.type == FE_LOG_LOCKS);
- TEST_ASSERT(FLASH_LOG_PAYLOAD_SIZE(e.r.size) == 1);
- TEST_ASSERT(e.r.payload[0] == 1);
-
- flash_log_dequeue_event(e.r.timestamp, e.entry, sizeof(e.entry));
- TEST_ASSERT(e.r.type == FE_LOG_TEST);
-
- return EC_SUCCESS;
-}
-
-static int test_setting_base_timestamp(void)
-{
- union entry_u eu;
- uint32_t saved_stamp;
- timestamp_t ts;
- uint32_t delta_time;
- /* Value collected on May 13 2019 */
- uint32_t recent_seconds_since_epoch = 1557793625;
-
- ts.val = 0;
- force_time(ts);
- TEST_ASSERT(verify_single_entry(0xff, FE_LOG_START) == EC_SUCCESS);
- TEST_ASSERT(flash_log_dequeue_event(0, eu.entry, sizeof(eu)) > 0);
-
- saved_stamp = eu.r.timestamp;
-
- /* Let the next log timestamp be 1000 s later. */
- delta_time = 1000;
-
- /*
- * Move internal clock uptime of 1000 s (convert value to microseconds
- * first).
- */
- ts.val = ((uint64_t)saved_stamp + delta_time) * 1000000;
- force_time(ts);
-
- /* Verify that the second event is within 1001 s from the first one. */
- flash_log_add_event(FE_LOG_TEST, 0, NULL);
- TEST_ASSERT(flash_log_dequeue_event(saved_stamp, eu.entry, sizeof(eu)) >
- 0);
- TEST_ASSERT((eu.r.timestamp - saved_stamp - delta_time) < 2);
-
- /* Set timestamp base to current time. */
- TEST_ASSERT(flash_log_set_tstamp(recent_seconds_since_epoch) ==
- EC_SUCCESS);
-
- /* Create an entry with the latest timestamp. */
- flash_log_add_event(FE_LOG_TEST, 0, NULL);
-
- /* Verify that it has been logged with the correct timestamp. */
- TEST_ASSERT(flash_log_dequeue_event(eu.r.timestamp, eu.entry,
- sizeof(eu)) > 0);
- TEST_ASSERT((eu.r.timestamp - recent_seconds_since_epoch) < 2);
-
- /* Verify that it is impossible to roll timestamps back. */
- TEST_ASSERT(flash_log_set_tstamp(recent_seconds_since_epoch - 100) ==
- EC_ERROR_INVAL);
-
- /* But is possible to roll further forward. */
- TEST_ASSERT(flash_log_set_tstamp(recent_seconds_since_epoch + 100) ==
- EC_SUCCESS);
-
- return EC_SUCCESS;
-}
-
-void run_test(void)
-{
- test_reset();
-
- RUN_TEST(test_init_from_scratch);
- RUN_TEST(test_init_from_corrupted);
- RUN_TEST(test_run_time_compaction);
- RUN_TEST(test_init_time_compaction);
- RUN_TEST(test_lock_failure_reporting);
- RUN_TEST(test_setting_base_timestamp);
-
- test_print_result();
-}
diff --git a/test/flash_log.tasklist b/test/flash_log.tasklist
deleted file mode 100644
index 9fc1a80f4d..0000000000
--- a/test/flash_log.tasklist
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Copyright 2019 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.
- */
-
-/**
- * See CONFIG_TASK_LIST in config.h for details.
- */
-#define CONFIG_TEST_TASK_LIST
diff --git a/test/nvmem_test.h b/test/nvmem_test.h
deleted file mode 100644
index 58775d4bcb..0000000000
--- a/test/nvmem_test.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Copyright 2019 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.
- */
-
-#ifndef __EC_TEST_NVMEM_TEST_H
-#define __EC_TEST_NVMEM_TEST_H
-
-#define EMBEDDED_MODE 1
-#define NV_C
-#include "Global.h"
-#undef NV_C
-#include "NV_fp.h"
-#include "tpm_generated.h"
-
-enum test_failure_mode {
- TEST_NO_FAILURE,
- TEST_FAIL_WHEN_SAVING,
- TEST_FAIL_WHEN_INVALIDATING,
- TEST_FAIL_WHEN_COMPACTING,
- TEST_FAIL_SAVING_VAR,
- TEST_FAIL_FINALIZING_VAR,
- TEST_FAILED_HASH,
- TEST_SPANNING_PAGES
-};
-
-extern enum test_failure_mode failure_mode;
-
-size_t add_evictable_obj(void *obj, size_t obj_size);
-void drop_evictable_obj(void *obj);
-
-#endif /* ! __EC_TEST_NVMEM_TEST_H */
diff --git a/test/pinweaver.c b/test/pinweaver.c
deleted file mode 100644
index 63a7e2e067..0000000000
--- a/test/pinweaver.c
+++ /dev/null
@@ -1,2681 +0,0 @@
-/* Copyright 2018 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 <pinweaver.h>
-
-#include <dcrypto.h>
-#include <nvmem_vars.h>
-#include <sha256.h>
-#include <stdint.h>
-#include <string.h>
-#include <timer.h>
-#include <util.h>
-#include <pinweaver_types.h>
-
-#include "test_util.h"
-
-#include <stdlib.h>
-
-struct pw_test_data_t {
- union {
- struct pw_request_t request;
- struct pw_response_t response;
- /* Reserve space for the variable length fields. */
- uint8_t tpm_buffer_size[PW_MAX_MESSAGE_SIZE];
- };
-} PW_ALIGN_TO_WRD;
-
-/******************************************************************************/
-/* Test data
- */
-const int EMPTY_TREE_PATH_LENGTH = 18;
-const struct merkle_tree_t EMPTY_TREE = {
- {2} /* bits_per_level */,
- {6} /* height */,
- /* root */
- {0x81, 0xaa, 0xe9, 0xde, 0x93, 0xf4, 0xdf, 0x88,
- 0x18, 0xfa, 0xff, 0xbd, 0xb7, 0x09, 0xc0, 0x86,
- 0x48, 0xdd, 0xcd, 0x35, 0x00, 0xf2, 0x88, 0xd6,
- 0x3f, 0xa6, 0x5e, 0x80, 0x10, 0x19, 0x41, 0x17},
- /* key derivation nonce. */
- {0x75, 0xf8, 0x43, 0xf7, 0x23, 0xbd, 0x2a, 0x0f,
- 0x8d, 0x34, 0xbf, 0xa6, 0x6d, 0xf9, 0x44, 0x38},
- /* hmac_key */
- {0x96, 0xc6, 0xb1, 0x64, 0xb6, 0xa7, 0xa8, 0x01,
- 0xd5, 0x1d, 0x8e, 0x97, 0x24, 0x86, 0xf8, 0x6f,
- 0xd4, 0x84, 0x0f, 0x95, 0x52, 0x93, 0x8d, 0x7d,
- 0x00, 0xbb, 0xba, 0xc8, 0xed, 0x7f, 0xa4, 0x7a},
- /* wrap_key */
- {0x95, 0xc9, 0x0a, 0xd4, 0xb3, 0x61, 0x1b, 0xcf,
- 0x1b, 0x49, 0x2b, 0xd6, 0x5d, 0xbc, 0x80, 0xa9,
- 0xf4, 0x83, 0xf2, 0x84, 0xd4, 0x04, 0x57, 0x7f,
- 0x02, 0xae, 0x37, 0x64, 0xae, 0xda, 0x71, 0x2a},
-};
-
-const struct leaf_data_t DEFAULT_LEAF = {
- /*pub*/
- {
- /* label = {0, 1, 2, 3, 0, 1} */
- {0x1b1llu},
- /* delay_schedule */
- {{{5}, {20} }, {{6}, {60} }, {{7}, {300} }, {{8}, {600} },
- {{9}, {1800} }, {{10}, {3600} }, {{50}, {PW_BLOCK_ATTEMPTS} },
- {{0}, {0} },
- {{0}, {0} }, {{0}, {0} }, {{0}, {0} }, {{0}, {0} },
- {{0}, {0} }, {{0}, {0} }, {{0}, {0} }, {{0}, {0} }, },
- /*timestamp*/
- {0, 0},
- /* attempt_count */
- {0},
- /* valid_pcr_criteria */
- {{{0, 0}, {0} }, {{0, 0}, {0} } },
- },
- /*sec*/
- {
- /* low_entropy_secret */
- {0xba, 0xbc, 0x98, 0x9d, 0x97, 0x20, 0xcf, 0xea,
- 0xaa, 0xbd, 0xb2, 0xe3, 0xe0, 0x2c, 0x5c, 0x55,
- 0x06, 0x60, 0x93, 0xbd, 0x07, 0xe2, 0xba, 0x92,
- 0x10, 0x19, 0x24, 0xb1, 0x29, 0x33, 0x5a, 0xe2},
- /* high_entropy_secret */
- {0xe3, 0x46, 0xe3, 0x62, 0x01, 0x5d, 0xfe, 0x0a,
- 0xd3, 0x67, 0xd7, 0xef, 0xab, 0x01, 0xad, 0x0e,
- 0x3a, 0xed, 0xe8, 0x2f, 0x99, 0xd1, 0x2d, 0x13,
- 0x4d, 0x4e, 0xe4, 0x02, 0xbe, 0x71, 0x8e, 0x40},
- /* reset_secret */
- {0x8c, 0x33, 0x8c, 0xa7, 0x0f, 0x81, 0xa4, 0xee,
- 0x24, 0xcd, 0x04, 0x84, 0x9c, 0xa8, 0xfd, 0xdd,
- 0x14, 0xb0, 0xad, 0xe6, 0xb7, 0x6a, 0x10, 0xfc,
- 0x03, 0x22, 0xcb, 0x71, 0x31, 0xd3, 0x74, 0xd6},
- },
-};
-
-const struct leaf_header_t DEFAULT_HEAD = {
- {
- .minor = PW_LEAF_MINOR_VERSION,
- .major = PW_LEAF_MAJOR_VERSION,
- },
- sizeof(DEFAULT_LEAF.pub),
- sizeof(DEFAULT_LEAF.sec),
-};
-
-const uint8_t DEFAULT_IV[] = {
- 0xaa, 0x65, 0x97, 0xc7, 0x02, 0x23, 0xb8, 0xdc,
- 0xb3, 0x55, 0xca, 0x3a, 0xab, 0xd0, 0x03, 0x90,
-};
-
-const uint8_t EMPTY_HMAC[32] = {};
-
-const uint32_t DEFAULT_STORAGE_SEED[8] = {
- 0xe9e9880b, 0xb2a9fa0e, 0x9dcf22af, 0xc40156d0,
- 0xca8535dc, 0x748606ee, 0x68f0f627, 0x7df7558a,
-};
-
-/* This is not the actual hmac. */
-const uint8_t DEFAULT_HMAC[] = {
- 0x87, 0x7e, 0xe2, 0xb2, 0x60, 0xeb, 0xf3, 0x4b,
- 0x80, 0x3e, 0xca, 0xcb, 0xe6, 0x24, 0x21, 0x86,
- 0xd9, 0xe3, 0x91, 0xf7, 0x2d, 0x16, 0x59, 0xd8,
- 0x0f, 0x37, 0x0a, 0xf4, 0x64, 0x19, 0x44, 0xe7,
-};
-
-const uint8_t ROOT_WITH_DEFAULT_HMAC[] = {
- 0x24, 0xad, 0xe4, 0xad, 0xf2, 0xdc, 0x40, 0x26,
- 0x15, 0x03, 0x16, 0x6f, 0x3c, 0x32, 0x05, 0x99,
- 0xf8, 0x25, 0x22, 0x92, 0xb9, 0xc7, 0xcd, 0x18,
- 0x37, 0xc2, 0xf2, 0x72, 0x31, 0xdd, 0xc4, 0xaf,
-};
-
-/* This is not the actual hmac. */
-const uint8_t OTHER_HMAC[] = {
- 0xec, 0x64, 0x73, 0x39, 0xcf, 0x53, 0xb7, 0x08,
- 0x85, 0x8f, 0xb6, 0x20, 0x25, 0x98, 0x59, 0x97,
- 0x58, 0x8c, 0x7a, 0x80, 0x10, 0xb4, 0xc1, 0xc8,
- 0x8a, 0xdf, 0xe3, 0x69, 0x07, 0xd1, 0xc4, 0xdc,
-};
-
-const uint8_t ROOT_WITH_OTHER_HMAC[] = {
- 0xdf, 0xce, 0xf4, 0xba, 0x18, 0xe8, 0xd0, 0x1d,
- 0xcb, 0x3b, 0x29, 0x41, 0x44, 0x01, 0x6e, 0x72,
- 0xe3, 0x19, 0x9a, 0x44, 0x62, 0x44, 0x2a, 0xf1,
- 0xaf, 0x66, 0xb6, 0xf0, 0x61, 0x05, 0x9d, 0xc0,
-};
-
-const uint8_t DEFAULT_PCR_DIGEST[] = {
- 0xdf, 0xce, 0xf4, 0xba, 0x18, 0xe8, 0xd0, 0x1d,
- 0xcb, 0x3b, 0x29, 0x41, 0x44, 0x01, 0x6e, 0x72,
- 0xe3, 0x19, 0x9a, 0x44, 0x62, 0x44, 0x2a, 0xf1,
- 0xaf, 0x66, 0xb6, 0xf0, 0x61, 0x05, 0x9d, 0xc0,
-};
-
-/******************************************************************************/
-/* Config Variables and defines for Mocks.
- */
-
-struct pw_long_term_storage_t MOCK_pw_long_term_storage;
-struct pw_log_storage_t MOCK_pw_log_storage;
-int MOCK_getvar_ret = EC_SUCCESS;
-int MOCK_setvar_ret = EC_SUCCESS;
-
-const uint8_t *MOCK_rand_bytes_src;
-size_t MOCK_rand_bytes_offset;
-size_t MOCK_rand_bytes_len;
-
-void (*MOCK_hash_update_cb)(const void *data, size_t len);
-static void auth_hash_update_cb(const void *data, size_t len);
-
-const uint8_t *MOCK_hmac;
-size_t MOCK_DECRYPTO_init_counter;
-size_t MOCK_DECRYPTO_release_counter;
-
-#define MOCK_AES_XOR_BYTE(b) ((uint8_t)(0x77 + (b & 15)))
-int MOCK_aes_fail;
-int MOCK_appkey_derive_fail;
-enum dcrypto_appid MOCK_hwctx_appkey;
-
-#define PW_VALID_PCR_CRITERIA_SIZE \
- (sizeof(struct valid_pcr_value_t) * PW_MAX_PCR_CRITERIA_COUNT)
-
-/******************************************************************************/
-/* Helper functions
- */
-
-static void convert_response_to_new_version(uint8_t req_type,
- struct pw_response_t *response)
-{
- if (response->header.version == 0) {
- if (req_type == PW_TRY_AUTH) {
- unsigned char *src = (unsigned char *)
- (&response->data.try_auth.reset_secret);
- memmove(src + PW_SECRET_SIZE, src,
- PW_LEAF_PAYLOAD_SIZE);
- memcpy(src, DEFAULT_LEAF.sec.reset_secret,
- PW_SECRET_SIZE);
- response->header.data_length += PW_SECRET_SIZE;
- }
- }
-}
-
-static int do_request(struct merkle_tree_t *merkle_tree,
- struct pw_test_data_t *buf)
-{
- uint8_t req_type = buf->request.header.type.v;
- int ret = pw_handle_request(merkle_tree, &buf->request, &buf->response);
- size_t offset = buf->response.header.data_length +
- sizeof(buf->response.header);
-
- /* Zero out bytes that won't be sent for testing.*/
- memset(buf->tpm_buffer_size + offset, 0,
- sizeof(buf->tpm_buffer_size) - offset);
-
- if (buf->request.header.version < PW_PROTOCOL_VERSION)
- convert_response_to_new_version(req_type, &buf->response);
-
- return ret;
-}
-
-static const char *pw_error_str(int code)
-{
- switch (code) {
- case EC_SUCCESS:
- return "EC_SUCCESS";
- case EC_ERROR_UNKNOWN:
- return "EC_ERROR_UNKNOWN";
- case EC_ERROR_UNIMPLEMENTED:
- return "EC_ERROR_UNIMPLEMENTED";
- case PW_ERR_VERSION_MISMATCH:
- return "PW_ERR_VERSION_MISMATCH";
- case PW_ERR_LENGTH_INVALID:
- return "PW_ERR_LENGTH_INVALID";
- case PW_ERR_TYPE_INVALID:
- return "PW_ERR_TYPE_INVALID";
- case PW_ERR_BITS_PER_LEVEL_INVALID:
- return "PW_ERR_BITS_PER_LEVEL_INVALID";
- case PW_ERR_HEIGHT_INVALID:
- return "PW_ERR_HEIGHT_INVALID";
- case PW_ERR_LABEL_INVALID:
- return "PW_ERR_LABEL_INVALID";
- case PW_ERR_DELAY_SCHEDULE_INVALID:
- return "PW_ERR_DELAY_SCHEDULE_INVALID";
- case PW_ERR_PATH_AUTH_FAILED:
- return "PW_ERR_PATH_AUTH_FAILED";
- case PW_ERR_LEAF_VERSION_MISMATCH:
- return "PW_ERR_LEAF_VERSION_MISMATCH";
- case PW_ERR_HMAC_AUTH_FAILED:
- return "PW_ERR_HMAC_AUTH_FAILED";
- case PW_ERR_LOWENT_AUTH_FAILED:
- return "PW_ERR_LOWENT_AUTH_FAILED";
- case PW_ERR_RESET_AUTH_FAILED:
- return "PW_ERR_RESET_AUTH_FAILED";
- case PW_ERR_CRYPTO_FAILURE:
- return "PW_ERR_CRYPTO_FAILURE";
- case PW_ERR_RATE_LIMIT_REACHED:
- return "PW_ERR_RATE_LIMIT_REACHED";
- case PW_ERR_ROOT_NOT_FOUND:
- return "PW_ERR_ROOT_NOT_FOUND";
- case PW_ERR_NV_EMPTY:
- return "PW_ERR_NV_EMPTY";
- case PW_ERR_NV_LENGTH_MISMATCH:
- return "PW_ERR_NV_LENGTH_MISMATCH";
- case PW_ERR_NV_VERSION_MISMATCH:
- return "PW_ERR_NV_VERSION_MISMATCH";
- default:
- return "?";
- }
-}
-
-/* Pinweaver specific return code check. This prints the string representation
- * of the return code instead of just the number.
- */
-#define TEST_RET_EQ(n, m) \
- do { \
- int val1 = n; \
- int val2 = m; \
- if (val1 != val2) { \
- ccprintf("%d: ASSERTION failed: %s (%d) != %s (%d)\n", \
- __LINE__, pw_error_str(val1), val1, \
- pw_error_str(val2), val2); \
- task_dump_trace(); \
- return EC_ERROR_UNKNOWN; \
- } \
- } while (0)
-
-/* Allows mock functions when that don't return success / failure to have
- * assertions.
- */
-#define TEST_ASRT_NORET(n) \
- do { \
- if (!(n)) { \
- int x = 0;\
- ccprintf("%d: ASSERTION failed: %s\n", __LINE__, #n); \
- task_dump_trace(); \
- x = 1 / x; \
- } \
- } while (0)
-
-/* For debugging and generating test data. */
-void print_array(const uint8_t *data, size_t n) __attribute__ ((unused));
-void print_array(const uint8_t *data, size_t n)
-{
- size_t x;
-
- if (n > 0) {
- ccprintf("uint8_t data[] = {");
- for (x = 0; x < n - 1; ++x) {
- if ((x & 7) != 7)
- ccprintf("0x%02x, ", data[x]);
- else
- ccprintf("0x%02x,\n", data[x]);
- }
- ccprintf("0x%02x};\n", data[x]);
- }
-}
-
-/* For exporting structs. This is useful for validating the results of crypto
- * operations.
- */
-void print_hex(const uint8_t *data, size_t n) __attribute__ ((unused));
-void print_hex(const uint8_t *data, size_t n)
-{
- size_t x;
-
- for (x = 0; x < n; ++x)
- ccprintf("%02x ", data[x]);
-}
-
-/* Initialize the log.
- * For num_operations:
- * < 0 only zero out the storage.
- * == 0 only initialize the tree
- * > 0 cyclically applies operations in the following order:
- * insert
- * auth failed
- * auth success
- * remove
- * So for num_operations == 4 the complete set of operations will be written to
- * the log.
- */
-static void setup_storage(int num_operations)
-{
- MOCK_getvar_ret = EC_SUCCESS;
- MOCK_setvar_ret = EC_SUCCESS;
-
- memset(&MOCK_pw_long_term_storage, 0,
- sizeof(MOCK_pw_long_term_storage));
- memset(&MOCK_pw_log_storage, 0, sizeof(MOCK_pw_log_storage));
-
- if (num_operations < 0)
- return;
- --num_operations;
-
- store_merkle_tree(&EMPTY_TREE);
-
- while (num_operations > 0) {
- --num_operations;
-
- log_insert_leaf(DEFAULT_LEAF.pub.label, ROOT_WITH_DEFAULT_HMAC,
- DEFAULT_HMAC);
-
- if (num_operations < 0)
- return;
- --num_operations;
-
- log_auth(DEFAULT_LEAF.pub.label, ROOT_WITH_OTHER_HMAC,
- PW_ERR_LOWENT_AUTH_FAILED,
- (struct pw_timestamp_t) {7, 99});
-
- if (num_operations < 0)
- return;
- --num_operations;
-
- log_auth(DEFAULT_LEAF.pub.label, ROOT_WITH_DEFAULT_HMAC,
- EC_SUCCESS,
- (struct pw_timestamp_t) {10, 100});
-
- if (num_operations < 0)
- return;
- --num_operations;
-
- log_remove_leaf(DEFAULT_LEAF.pub.label, EMPTY_TREE.root);
- }
-}
-
-static void setup_default_empty_path(uint8_t hashes[][PW_HASH_SIZE])
-{
- uint8_t num_siblings = (1 << EMPTY_TREE.bits_per_level.v) - 1;
- const uint8_t level_hashes[5][PW_HASH_SIZE] = {
- /* Values for level 5 are all 0 for empty. */
- /* SHA256 for level 5, values for level 4. */
- {0x38, 0x72, 0x3a, 0x2e, 0x5e, 0x8a, 0x17, 0xaa,
- 0x79, 0x50, 0xdc, 0x00, 0x82, 0x09, 0x94, 0x4e,
- 0x89, 0x8f, 0x69, 0xa7, 0xbd, 0x10, 0xa2, 0x3c,
- 0x83, 0x9d, 0x34, 0x1e, 0x93, 0x5f, 0xd5, 0xca},
- /* SHA256 for level 4, values for level 3. */
- {0xfe, 0xc1, 0x2b, 0x09, 0x33, 0x31, 0x28, 0x34,
- 0x79, 0x1f, 0x07, 0x64, 0x1a, 0xed, 0x30, 0x53,
- 0x11, 0x1f, 0x15, 0x3e, 0x1e, 0x3e, 0xd1, 0xf0,
- 0xcd, 0x16, 0xcb, 0x39, 0x25, 0xfd, 0x5f, 0x84},
- /* SHA256 for level 3, values for level 2. */
- {0xb6, 0xd4, 0x9c, 0x89, 0x76, 0x45, 0x9c, 0xe9,
- 0x9c, 0x0b, 0xad, 0x5d, 0x71, 0xdf, 0x92, 0x77,
- 0xf6, 0x82, 0x62, 0x63, 0x81, 0x9f, 0xc9, 0x2f,
- 0x61, 0x9c, 0x29, 0x67, 0x52, 0x37, 0x01, 0x51},
- /* SHA256 for level 2, values for level 1. */
- {0x87, 0xeb, 0x61, 0x6b, 0x2c, 0x42, 0x07, 0x5e,
- 0x70, 0x2d, 0x48, 0x49, 0xf2, 0xe0, 0x13, 0x11,
- 0xc4, 0xe6, 0x98, 0xfa, 0x22, 0x7e, 0x65, 0xc6,
- 0x66, 0x33, 0x6b, 0xb6, 0xd7, 0xb9, 0x45, 0xfa},
- /* SHA256 for level 1, values for level 0. */
- {0x80, 0x91, 0x04, 0x3f, 0x6c, 0x29, 0x06, 0x35,
- 0x86, 0x99, 0x21, 0x88, 0x1f, 0xd9, 0xae, 0xb8,
- 0x35, 0x94, 0x26, 0x19, 0x64, 0x68, 0x4f, 0x4f,
- 0x4c, 0x66, 0x13, 0xa9, 0x66, 0x69, 0x25, 0x0e},};
- uint8_t hx;
- uint8_t kx;
-
- /* Empty first level. */
- memset(hashes, 0, num_siblings * PW_HASH_SIZE);
- hashes += num_siblings;
-
- for (hx = 1; hx < EMPTY_TREE.height.v; ++hx) {
- for (kx = 0; kx < num_siblings; ++kx) {
- memcpy(hashes, level_hashes[hx - 1], PW_HASH_SIZE);
- ++hashes;
- }
- }
-}
-
-static void setup_default_unimported_leaf_data_and_hashes(
- const struct leaf_data_t *leaf_data,
- const uint8_t hmac[PW_HASH_SIZE],
- const struct leaf_header_t *header,
- struct unimported_leaf_data_t *data)
-{
- memcpy(&data->head, header, sizeof(*header));
- memcpy(data->hmac, hmac, sizeof(data->hmac));
- memcpy(data->iv, DEFAULT_IV, sizeof(DEFAULT_IV));
- memcpy(data->payload, &leaf_data->pub, header->pub_len);
- DCRYPTO_aes_ctr(data->payload + header->pub_len,
- EMPTY_TREE.wrap_key, sizeof(EMPTY_TREE.wrap_key) * 8,
- DEFAULT_IV, (const uint8_t *)&leaf_data->sec,
- header->sec_len);
- setup_default_empty_path((void *)(data->payload + header->pub_len +
- header->sec_len));
-}
-
-static void setup_reset_tree_defaults(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- MOCK_DECRYPTO_init_counter = 0;
- MOCK_DECRYPTO_release_counter = 0;
-
- memset(merkle_tree, 0, sizeof(*merkle_tree));
- memset(&MOCK_pw_long_term_storage, 0,
- sizeof(MOCK_pw_long_term_storage));
- memset(&MOCK_pw_log_storage, 0, sizeof(MOCK_pw_log_storage));
-
- request->header.version = PW_PROTOCOL_VERSION;
- request->header.type.v = PW_RESET_TREE;
- request->header.data_length = sizeof(struct pw_request_reset_tree_t);
-
- request->data.reset_tree.bits_per_level.v = 2; /* k = 4 */
- request->data.reset_tree.height.v = 6; /* L = 12 */
-
- MOCK_rand_bytes_src = (uint8_t *)EMPTY_TREE.key_derivation_nonce;
- MOCK_rand_bytes_offset = 0;
- MOCK_rand_bytes_len = sizeof(EMPTY_TREE.key_derivation_nonce);
- MOCK_appkey_derive_fail = EC_SUCCESS;
- MOCK_setvar_ret = EC_SUCCESS;
-}
-
-static void setup_insert_leaf_defaults(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- MOCK_DECRYPTO_init_counter = 0;
- MOCK_DECRYPTO_release_counter = 0;
-
- memcpy(merkle_tree, &EMPTY_TREE, sizeof(EMPTY_TREE));
- memset(&MOCK_pw_log_storage, 0, sizeof(MOCK_pw_log_storage));
-
- request->header.version = PW_PROTOCOL_VERSION;
- request->header.type.v = PW_INSERT_LEAF;
- request->header.data_length = sizeof(struct pw_request_insert_leaf_t) +
- get_path_auxiliary_hash_count(&EMPTY_TREE) *
- PW_HASH_SIZE;
-
- request->data.insert_leaf.label.v = DEFAULT_LEAF.pub.label.v;
- memcpy(&request->data.insert_leaf.delay_schedule,
- &DEFAULT_LEAF.pub.delay_schedule,
- sizeof(DEFAULT_LEAF.pub.delay_schedule));
- memcpy(&request->data.insert_leaf.valid_pcr_criteria,
- &DEFAULT_LEAF.pub.valid_pcr_criteria,
- sizeof(DEFAULT_LEAF.pub.valid_pcr_criteria));
- memcpy(&request->data.insert_leaf.low_entropy_secret,
- &DEFAULT_LEAF.sec.low_entropy_secret,
- sizeof(DEFAULT_LEAF.sec.low_entropy_secret));
- memcpy(&request->data.insert_leaf.high_entropy_secret,
- &DEFAULT_LEAF.sec.high_entropy_secret,
- sizeof(DEFAULT_LEAF.sec.high_entropy_secret));
- memcpy(&request->data.insert_leaf.reset_secret,
- &DEFAULT_LEAF.sec.reset_secret,
- sizeof(DEFAULT_LEAF.sec.reset_secret));
- setup_default_empty_path(request->data.insert_leaf.path_hashes);
-
- MOCK_rand_bytes_src = DEFAULT_IV;
- MOCK_rand_bytes_offset = 0;
- MOCK_rand_bytes_len = sizeof(DEFAULT_IV);
- MOCK_hash_update_cb = 0;
- MOCK_hmac = DEFAULT_HMAC;
- MOCK_aes_fail = 0;
- MOCK_setvar_ret = EC_SUCCESS;
-}
-
-static void setup_remove_leaf_defaults(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- MOCK_DECRYPTO_init_counter = 0;
- MOCK_DECRYPTO_release_counter = 0;
-
- memcpy(merkle_tree, &EMPTY_TREE, sizeof(EMPTY_TREE));
- memcpy(merkle_tree->root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- memset(&MOCK_pw_log_storage, 0, sizeof(MOCK_pw_log_storage));
-
- request->header.version = PW_PROTOCOL_VERSION;
- request->header.type.v = PW_REMOVE_LEAF;
- request->header.data_length =
- sizeof(struct pw_request_remove_leaf_t) +
- get_path_auxiliary_hash_count(&EMPTY_TREE) *
- PW_HASH_SIZE;
-
- request->data.remove_leaf.leaf_location = DEFAULT_LEAF.pub.label;
- memcpy(request->data.remove_leaf.leaf_hmac, DEFAULT_HMAC,
- sizeof(request->data.remove_leaf.leaf_hmac));
- setup_default_empty_path(request->data.remove_leaf.path_hashes);
-
- MOCK_setvar_ret = EC_SUCCESS;
-}
-
-static void setup_try_auth_defaults_with_leaf(
- const struct leaf_data_t *leaf_data,
- uint8_t protocol_version,
- uint8_t minor_version,
- struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- struct leaf_header_t header = DEFAULT_HEAD;
-
- MOCK_DECRYPTO_init_counter = 0;
- MOCK_DECRYPTO_release_counter = 0;
-
- memcpy(merkle_tree, &EMPTY_TREE, sizeof(EMPTY_TREE));
- if (leaf_data->pub.attempt_count.v != 6 &&
- leaf_data->pub.attempt_count.v != 10) {
- memcpy(merkle_tree->root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
-
- /* Gets overwritten by auth_hash_update_cb. */
- MOCK_hmac = DEFAULT_HMAC;
- } else
- /* Gets overwritten by auth_hash_update_cb. */
- MOCK_hmac = EMPTY_HMAC;
-
- header.leaf_version.minor = minor_version;
- memset(&MOCK_pw_log_storage, 0, sizeof(MOCK_pw_log_storage));
-
- request->header.version = protocol_version;
- request->header.type.v = PW_TRY_AUTH;
- request->header.data_length =
- sizeof(struct pw_request_try_auth_t) +
- PW_LEAF_PAYLOAD_SIZE +
- get_path_auxiliary_hash_count(&EMPTY_TREE) *
- PW_HASH_SIZE;
-
- if (minor_version == 0) {
- header.pub_len -= PW_VALID_PCR_CRITERIA_SIZE;
- request->header.data_length -= PW_VALID_PCR_CRITERIA_SIZE;
- }
-
- memcpy(request->data.try_auth.low_entropy_secret,
- DEFAULT_LEAF.sec.low_entropy_secret,
- sizeof(request->data.try_auth.low_entropy_secret));
- setup_default_unimported_leaf_data_and_hashes(
- leaf_data, MOCK_hmac, &header,
- &request->data.try_auth.unimported_leaf_data);
-
- force_restart_count(0);
- force_time((timestamp_t){.val = 0});
- MOCK_rand_bytes_src = DEFAULT_IV;
- MOCK_rand_bytes_offset = 0;
- MOCK_rand_bytes_len = sizeof(DEFAULT_IV);
- MOCK_hash_update_cb = auth_hash_update_cb;
- MOCK_aes_fail = 0;
- MOCK_setvar_ret = EC_SUCCESS;
-}
-
-static void setup_try_auth_defaults(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- setup_try_auth_defaults_with_leaf(&DEFAULT_LEAF, PW_PROTOCOL_VERSION,
- PW_LEAF_MINOR_VERSION, merkle_tree,
- request);
-}
-
-static void setup_reset_auth_defaults(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- struct leaf_public_data_t *pub =
- (void *)request->data.reset_auth.unimported_leaf_data
- .payload;
-
- MOCK_DECRYPTO_init_counter = 0;
- MOCK_DECRYPTO_release_counter = 0;
- memcpy(merkle_tree, &EMPTY_TREE, sizeof(EMPTY_TREE));
- memset(&MOCK_pw_log_storage, 0, sizeof(MOCK_pw_log_storage));
-
- request->header.version = PW_PROTOCOL_VERSION;
- request->header.type.v = PW_RESET_AUTH;
- request->header.data_length =
- sizeof(struct pw_request_reset_auth_t) +
- PW_LEAF_PAYLOAD_SIZE +
- get_path_auxiliary_hash_count(&EMPTY_TREE) *
- PW_HASH_SIZE;
-
- memcpy(request->data.reset_auth.reset_secret,
- DEFAULT_LEAF.sec.reset_secret,
- sizeof(request->data.reset_auth.reset_secret));
-
- setup_default_unimported_leaf_data_and_hashes(
- &DEFAULT_LEAF, EMPTY_HMAC, &DEFAULT_HEAD,
- &request->data.try_auth.unimported_leaf_data);
- pub->attempt_count.v = 6;
-
- MOCK_rand_bytes_src = DEFAULT_IV;
- MOCK_rand_bytes_offset = 0;
- MOCK_rand_bytes_len = sizeof(DEFAULT_IV);
- MOCK_hash_update_cb = auth_hash_update_cb;
- MOCK_hmac = EMPTY_HMAC; /* Gets overwritten by auth_hash_update_cb. */
- MOCK_aes_fail = 0;
- MOCK_setvar_ret = EC_SUCCESS;
-}
-
-static void setup_get_log_defaults(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- MOCK_DECRYPTO_init_counter = 0;
- MOCK_DECRYPTO_release_counter = 0;
-
- memcpy(merkle_tree, &EMPTY_TREE, sizeof(*merkle_tree));
-
- request->header.version = PW_PROTOCOL_VERSION;
- request->header.type.v = PW_GET_LOG;
- request->header.data_length = sizeof(struct pw_request_get_log_t);
-
- /* Chosen not to match any of the root hashes in the log. */
- memcpy(request->data.get_log.root, OTHER_HMAC,
- sizeof(OTHER_HMAC));
-
- setup_storage(1);
-}
-
-static void setup_log_replay_defaults_with_leaf(
- const struct leaf_data_t *leaf_data,
- struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- MOCK_DECRYPTO_init_counter = 0;
- MOCK_DECRYPTO_release_counter = 0;
-
- memcpy(merkle_tree, &EMPTY_TREE, sizeof(*merkle_tree));
- if (leaf_data->pub.attempt_count.v != 6 &&
- leaf_data->pub.attempt_count.v != 10)
- /* Gets overwritten by auth_hash_update_cb. */
- MOCK_hmac = DEFAULT_HMAC;
- else
- /* Gets overwritten by auth_hash_update_cb. */
- MOCK_hmac = EMPTY_HMAC;
-
- request->header.version = PW_PROTOCOL_VERSION;
- request->header.type.v = PW_LOG_REPLAY;
- request->header.data_length =
- sizeof(struct pw_request_log_replay_t) +
- PW_LEAF_PAYLOAD_SIZE +
- get_path_auxiliary_hash_count(&EMPTY_TREE) *
- PW_HASH_SIZE;
-
- memcpy(request->data.log_replay.log_root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
-
- setup_default_unimported_leaf_data_and_hashes(
- leaf_data, MOCK_hmac, &DEFAULT_HEAD,
- &request->data.try_auth.unimported_leaf_data);
-
- MOCK_hash_update_cb = auth_hash_update_cb;
-
- setup_storage(4);
-}
-
-static void setup_log_replay_defaults(struct merkle_tree_t *merkle_tree,
- struct pw_request_t *request)
-{
- setup_log_replay_defaults_with_leaf(&DEFAULT_LEAF, merkle_tree,
- request);
-}
-
-/* Increases the length of the pub and cipher_text by 4 each. */
-static void setup_mock_future_version(
- struct unimported_leaf_data_t *unimported_leaf_data,
- uint16_t *req_length)
-{
- uint8_t *start = unimported_leaf_data->payload;
- const uint8_t size_increase = 4;
- const uint16_t cipher_text_offset = unimported_leaf_data->head.pub_len;
- const uint16_t hashes_offset = cipher_text_offset +
- unimported_leaf_data->head.sec_len;
-
- /* Shift hashes by 8*/
- memmove(start + hashes_offset + size_increase * 2,
- start + hashes_offset,
- get_path_auxiliary_hash_count(&EMPTY_TREE) *
- PW_HASH_SIZE);
-
- /* Shift cipher_text by 4*/
- memmove(start + cipher_text_offset + size_increase,
- start + cipher_text_offset,
- unimported_leaf_data->head.sec_len);
-
- ++unimported_leaf_data->head.leaf_version.minor;
- unimported_leaf_data->head.pub_len += size_increase;
- unimported_leaf_data->head.sec_len += size_increase;
- *req_length += size_increase * 2;
-}
-
-static int test_handle_short_msg(struct merkle_tree_t *merkle_tree,
- struct pw_test_data_t *buf,
- const uint8_t root[PW_HASH_SIZE])
-{
- int ret = do_request(merkle_tree, buf);
-
- TEST_RET_EQ(buf->response.header.result_code, ret);
- TEST_ASSERT(buf->response.header.version == PW_PROTOCOL_VERSION);
- TEST_ASSERT(buf->response.header.data_length == 0);
- TEST_ASSERT_ARRAY_EQ(buf->response.header.root, root, PW_HASH_SIZE);
- TEST_ASSERT_ARRAY_EQ(buf->response.header.root, merkle_tree->root,
- PW_HASH_SIZE);
- return ret;
-}
-
-/* Changes MOCK_hmac in a deterministic way based on the contents of the data
- * with the goal of making it easier to catch bugs in the handling of try_auth
- * and reset_auth requests.
- */
-static void auth_hash_update_cb(const void *data, size_t len)
-{
- const struct leaf_data_t *leaf_data = data;
-
- if (len != sizeof(leaf_data->pub) && len != sizeof(leaf_data->pub) + 4)
- return;
-
- switch (leaf_data->pub.attempt_count.v) {
- case 10:
- case 6:
- MOCK_hmac = EMPTY_HMAC;
- break;
- case 16:
- MOCK_hmac = OTHER_HMAC;
- break;
- default:
- MOCK_hmac = DEFAULT_HMAC;
- break;
- }
-}
-
-/******************************************************************************/
-/* Mock implementations of TPM functionality.
- */
-
-void get_storage_seed(void *buf, size_t *len)
-{
- *len = *len < sizeof(DEFAULT_STORAGE_SEED) ? *len :
- sizeof(DEFAULT_STORAGE_SEED);
- memcpy(buf, DEFAULT_STORAGE_SEED, *len);
-}
-
-uint8_t get_current_pcr_digest(const uint8_t bitmask[2],
- uint8_t sha256_of_selected_pcr[32])
-{
- memcpy(sha256_of_selected_pcr, DEFAULT_PCR_DIGEST, 32);
- return 0;
-}
-
-/******************************************************************************/
-/* Mock implementations of nvmem_vars functionality.
- */
-const struct tuple *getvar(const uint8_t *key, uint8_t key_len)
-{
- struct tuple *var = NULL;
- size_t i;
-
- const struct {
- size_t key_len;
- const void *key;
- size_t val_size;
- const void *val;
- } vars[] = {
- {sizeof(PW_TREE_VAR) - 1, PW_TREE_VAR,
- sizeof(MOCK_pw_long_term_storage), &MOCK_pw_long_term_storage},
- {sizeof(PW_LOG_VAR0) - 1, PW_LOG_VAR0,
- sizeof(MOCK_pw_log_storage), &MOCK_pw_log_storage},
- };
-
- if (!key || !key_len)
- return NULL;
-
- if (MOCK_getvar_ret != EC_SUCCESS)
- return NULL;
-
- for (i = 0; i < ARRAY_SIZE(vars); i++) {
- if ((key_len != vars[i].key_len) ||
- memcmp(key, vars[i].key, key_len)) {
- continue;
- }
- var = malloc(sizeof(struct tuple) + key_len + vars[i].val_size);
- var->flags = 0;
- var->val_len = vars[i].val_size;
- memcpy(var->data_ + var->key_len, vars[i].val, var->val_len);
- break;
- }
-
- return var;
-}
-
-void freevar(const struct tuple *var)
-{
- if (!var)
- return;
-
- /* This typecast is OK because we know that 'var' came from malloc. */
- free((void *)var);
-}
-const uint8_t *tuple_val(const struct tuple *tpl)
-{
- return tpl->data_ + tpl->key_len;
-}
-
-int setvar(const uint8_t *key, uint8_t key_len, const uint8_t *val,
- uint8_t val_len)
-{
- if (MOCK_setvar_ret != EC_SUCCESS)
- return MOCK_setvar_ret;
-
- if (key_len == (sizeof(PW_TREE_VAR) - 1) &&
- memcmp(key, PW_TREE_VAR, (sizeof(PW_TREE_VAR) - 1)) == 0) {
- TEST_ASSERT(val_len == sizeof(MOCK_pw_long_term_storage));
- memcpy(&MOCK_pw_long_term_storage, val, val_len);
- return EC_SUCCESS;
- } else if (key_len == (sizeof(PW_LOG_VAR0) - 1) &&
- memcmp(key, PW_LOG_VAR0, (sizeof(PW_LOG_VAR0) - 1)) == 0) {
- TEST_ASSERT(val_len == sizeof(struct pw_log_storage_t));
- memcpy(&MOCK_pw_log_storage, val, val_len);
- return EC_SUCCESS;
- } else
- return EC_ERROR_UNKNOWN;
-}
-
-/******************************************************************************/
-/* Mock implementations of TRNG functionality.
- */
-
-void rand_bytes(void *buffer, size_t len)
-{
- if (!MOCK_rand_bytes_src)
- return;
-
- TEST_ASRT_NORET(len <= MOCK_rand_bytes_len - MOCK_rand_bytes_offset);
-
- memcpy(buffer, MOCK_rand_bytes_src + MOCK_rand_bytes_offset, len);
- MOCK_rand_bytes_offset += len;
- if (MOCK_rand_bytes_len == MOCK_rand_bytes_offset)
- MOCK_rand_bytes_offset = 0;
-}
-
-/******************************************************************************/
-/* Mock implementations of Dcrypto functionality.
- */
-
-void HASH_update(struct HASH_CTX *ctx, const void *data, size_t len)
-{
- if (MOCK_hash_update_cb)
- MOCK_hash_update_cb(data, len);
- if (ctx)
- SHA256_update(ctx, data, len);
-}
-
-uint8_t *HASH_final(struct HASH_CTX *ctx)
-{
- ++MOCK_DECRYPTO_release_counter;
- return SHA256_final(ctx);
-}
-
-void DCRYPTO_SHA256_init(LITE_SHA256_CTX *ctx, uint32_t sw_required)
-{
- SHA256_init(ctx);
- ++MOCK_DECRYPTO_init_counter;
-}
-
-void DCRYPTO_HMAC_SHA256_init(LITE_HMAC_CTX *ctx, const void *key,
- unsigned int len)
-{
- TEST_ASRT_NORET(len == sizeof(EMPTY_TREE.hmac_key));
- TEST_ASRT_NORET(memcmp(key, EMPTY_TREE.hmac_key,
- sizeof(EMPTY_TREE.hmac_key)) == 0);
- SHA256_init(&ctx->hash);
- ++MOCK_DECRYPTO_init_counter;
-}
-
-const uint8_t *DCRYPTO_HMAC_final(LITE_HMAC_CTX *ctx)
-{
- ++MOCK_DECRYPTO_release_counter;
- return MOCK_hmac;
-}
-
-/* Perform a symmetric transformation of the data to simulate AES without
- * requiring a full AES-CTR implementation.
- *
- * 1 for success 0 for fail
- */
-int DCRYPTO_aes_ctr(uint8_t *out, const uint8_t *key, uint32_t key_bits,
- const uint8_t *iv, const uint8_t *in, size_t in_len)
-{
- size_t x;
-
- if (MOCK_aes_fail) {
- --MOCK_aes_fail;
- return 0;
- }
-
- TEST_ASSERT(key_bits == 256);
- TEST_ASSERT_ARRAY_EQ(key, EMPTY_TREE.wrap_key,
- sizeof(EMPTY_TREE.wrap_key));
- TEST_ASSERT_ARRAY_EQ(iv, DEFAULT_IV, sizeof(DEFAULT_IV));
- TEST_ASSERT(in_len == sizeof(struct leaf_sensitive_data_t));
-
- for (x = 0; x < in_len; ++x)
- out[x] = MOCK_AES_XOR_BYTE(x) ^ in[x];
- return 1;
-}
-
-/* 1 for success 0 for fail*/
-int DCRYPTO_appkey_init(enum dcrypto_appid appid, struct APPKEY_CTX *ctx)
-{
- MOCK_hwctx_appkey = appid;
- return 1;
-}
-
-void DCRYPTO_appkey_finish(struct APPKEY_CTX *ctx)
-{
- MOCK_hwctx_appkey = 0;
-}
-
-/* 1 for success 0 for fail*/
-int DCRYPTO_appkey_derive(enum dcrypto_appid appid, const uint32_t input[8],
- uint32_t output[8])
-{
- TEST_ASSERT(appid == PINWEAVER);
- TEST_ASSERT(MOCK_hwctx_appkey == appid);
-
- if (MOCK_appkey_derive_fail != EC_SUCCESS)
- return 0;
-
- if (input[6] ^ DEFAULT_STORAGE_SEED[6])
- memcpy(output, EMPTY_TREE.hmac_key,
- sizeof(EMPTY_TREE.hmac_key));
- else
- memcpy(output, EMPTY_TREE.wrap_key,
- sizeof(EMPTY_TREE.wrap_key));
- return 1;
-}
-
-/******************************************************************************/
-/* Reusable test cases.
- */
-
-static int check_dcrypto_mutex_usage(void)
-{
- if (MOCK_DECRYPTO_init_counter == MOCK_DECRYPTO_release_counter)
- return EC_SUCCESS;
- ccprintf("ASSERTION failed: DCRYPTO init(%zd) != DCRYPTO release(%zd)\n",
- MOCK_DECRYPTO_init_counter, MOCK_DECRYPTO_release_counter);
- return EC_ERROR_UNKNOWN;
-}
-
-static int invalid_length_with_leaf_head(
- size_t head_offset,
- void (*defaults)(struct merkle_tree_t *, struct pw_request_t *))
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_header_t *req_head = (void *)&buf + head_offset;
- uint8_t old_root[PW_HASH_SIZE];
-
- defaults(&merkle_tree, &buf.request);
- memcpy(old_root, merkle_tree.root, sizeof(old_root));
-
- buf.request.header.data_length = 0;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, old_root),
- PW_ERR_LENGTH_INVALID);
-
- defaults(&merkle_tree, &buf.request);
-
- ++buf.request.header.data_length;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, old_root),
- PW_ERR_LENGTH_INVALID);
-
- defaults(&merkle_tree, &buf.request);
-
- ++req_head->pub_len;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, old_root),
- PW_ERR_LENGTH_INVALID);
-
- defaults(&merkle_tree, &buf.request);
-
- ++req_head->leaf_version.minor;
- --req_head->pub_len;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, old_root),
- PW_ERR_LENGTH_INVALID);
- return check_dcrypto_mutex_usage();
-
-}
-
-/******************************************************************************/
-/* Basic operation test cases.
- */
-
-static int get_path_auxiliary_hash_count_test(void)
-{
- struct merkle_tree_t merkle_tree;
-
- memcpy(&merkle_tree, &EMPTY_TREE, sizeof(merkle_tree));
-
- TEST_ASSERT(get_path_auxiliary_hash_count(&merkle_tree) ==
- EMPTY_TREE_PATH_LENGTH);
- return EC_SUCCESS;
-}
-
-static int compute_hash_test(void)
-{
- const uint8_t hashes[4][PW_HASH_SIZE] = {
- {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- {0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
- };
- const struct {
- struct index_t index;
- uint8_t result[PW_HASH_SIZE];
- } test_cases[] = {
- {{0},
- {0xd5, 0xd9, 0x25, 0xb6, 0xa9, 0x90, 0x24, 0x12,
- 0x39, 0x0e, 0xfa, 0xd4, 0x8d, 0x55, 0x45, 0xf3,
- 0x23, 0x6c, 0x6d, 0xff, 0xcc, 0xc8, 0xe1, 0x39,
- 0xc7, 0xc3, 0x25, 0xf0, 0xd2, 0xa8, 0xf2, 0x0c}
- },
- {{1},
- {0x64, 0x3e, 0x56, 0xbc, 0xb9, 0xda, 0x18, 0xaf,
- 0xa0, 0x8c, 0x1f, 0xf8, 0x5e, 0xba, 0x58, 0xd0,
- 0xe1, 0x99, 0x61, 0xe0, 0xe2, 0x12, 0xe9, 0x14,
- 0xb5, 0x33, 0x46, 0x35, 0x52, 0x1e, 0xaf, 0x91}
- },
- {{3},
- {0xd0, 0x90, 0xc7, 0x3d, 0x12, 0xfb, 0xbc, 0xbc,
- 0x78, 0xcc, 0xbe, 0x58, 0x21, 0x14, 0xcf, 0x38,
- 0x68, 0x49, 0x20, 0xe9, 0x61, 0xcb, 0x35, 0xc4,
- 0x95, 0xb0, 0x14, 0x5a, 0x35, 0x43, 0x3e, 0x73}
- },
- };
- uint8_t result[PW_HASH_SIZE];
- size_t x;
-
- for (x = 0; x < ARRAY_SIZE(test_cases); ++x) {
- compute_hash(hashes, 3, test_cases[x].index, hashes[3], result);
- TEST_ASSERT_ARRAY_EQ(result, test_cases[x].result,
- sizeof(result));
- }
-
- return EC_SUCCESS;
-}
-
-/******************************************************************************/
-/* Header validation test cases.
- */
-
-static int handle_request_version_mismatch(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_tree_defaults(&merkle_tree, &buf.request);
-
- buf.request.header.version = PW_PROTOCOL_VERSION + 1;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_HMAC),
- PW_ERR_VERSION_MISMATCH);
- return EC_SUCCESS;
-}
-
-static int handle_request_invalid_type(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- memcpy(&merkle_tree, &EMPTY_TREE, sizeof(merkle_tree));
- memset(&buf.response, 0x77, sizeof(buf.response));
-
- buf.request.header.version = PW_PROTOCOL_VERSION;
- buf.request.header.type.v = PW_MT_INVALID;
- buf.request.header.data_length = 0;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_TYPE_INVALID);
- return EC_SUCCESS;
-}
-
-/******************************************************************************/
-/* Reset Tree test cases.
- */
-
-static int handle_reset_tree_invalid_length(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_tree_defaults(&merkle_tree, &buf.request);
-
- ++buf.request.header.data_length;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_HMAC),
- PW_ERR_LENGTH_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_reset_tree_bits_per_level_invalid(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_tree_defaults(&merkle_tree, &buf.request);
-
- /* Test lower bound. */
- buf.request.data.reset_tree.bits_per_level.v = BITS_PER_LEVEL_MIN - 1;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_BITS_PER_LEVEL_INVALID);
-
- setup_reset_tree_defaults(&merkle_tree, &buf.request);
-
- /* Test upper bound. */
- buf.request.data.reset_tree.bits_per_level.v = BITS_PER_LEVEL_MAX + 1;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_HMAC),
- PW_ERR_BITS_PER_LEVEL_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_reset_tree_height_invalid(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_tree_defaults(&merkle_tree, &buf.request);
-
- /* Test lower bound. */
- buf.request.data.reset_tree.height.v = HEIGHT_MIN - 1;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_HEIGHT_INVALID);
-
- setup_reset_tree_defaults(&merkle_tree, &buf.request);
-
- /* Test upper bound. */
- buf.request.data.reset_tree.height.v =
- HEIGHT_MAX(buf.request.data.reset_tree
- .bits_per_level.v) + 1;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_HMAC),
- PW_ERR_HEIGHT_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_reset_tree_crypto_failure(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_tree_defaults(&merkle_tree, &buf.request);
-
- /* Test lower bound. */
- MOCK_appkey_derive_fail = PW_ERR_CRYPTO_FAILURE;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_HMAC),
- PW_ERR_CRYPTO_FAILURE);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_reset_tree_nv_fail(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_tree_defaults(&merkle_tree, &buf.request);
-
- MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_NV_LENGTH_MISMATCH);
- return EC_SUCCESS;
-}
-
-static int handle_reset_tree_success(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_tree_defaults(&merkle_tree, &buf.request);
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ((uint8_t *)&merkle_tree, (uint8_t *)&EMPTY_TREE,
- sizeof(EMPTY_TREE));
-
- TEST_ASSERT(MOCK_pw_long_term_storage.storage_version ==
- PW_STORAGE_VERSION);
- TEST_ASSERT(MOCK_pw_long_term_storage.bits_per_level.v ==
- EMPTY_TREE.bits_per_level.v);
- TEST_ASSERT(MOCK_pw_long_term_storage.height.v ==
- EMPTY_TREE.height.v);
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_long_term_storage.key_derivation_nonce,
- EMPTY_TREE.key_derivation_nonce,
- sizeof(EMPTY_TREE.key_derivation_nonce));
-
- TEST_ASSERT(MOCK_pw_log_storage.storage_version == PW_STORAGE_VERSION);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].type.v == PW_RESET_TREE);
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].root,
- EMPTY_TREE.root, sizeof(EMPTY_TREE.root));
-
- return check_dcrypto_mutex_usage();
-}
-
-/******************************************************************************/
-/* Insert leaf test cases.
- */
-
-static int handle_insert_leaf_invalid_length(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- ++buf.request.header.data_length;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_LENGTH_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_insert_leaf_label_invalid(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- buf.request.data.insert_leaf.label.v |= 0x030000;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_LABEL_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_insert_leaf_delay_schedule_invalid(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct delay_schedule_entry_t (*ds)[PW_SCHED_COUNT] =
- &buf.request.data.insert_leaf.delay_schedule;
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- /* Non-increasing attempt_count. */
- (*ds)[1].attempt_count.v = 0;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_DELAY_SCHEDULE_INVALID);
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- /* Non-increasing time_diff. */
- (*ds)[1].time_diff.v = 0;
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_DELAY_SCHEDULE_INVALID);
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- /* attempt_count noise. */
- (*ds)[14].attempt_count.v = 99;
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_DELAY_SCHEDULE_INVALID);
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- /* time_diff noise. */
- (*ds)[14].time_diff.v = 99;
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_DELAY_SCHEDULE_INVALID);
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- /* Empty delay_schedule. */
- memset(&(*ds)[0], 0, sizeof(*ds));
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_DELAY_SCHEDULE_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_insert_leaf_path_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- buf.request.data.insert_leaf.path_hashes[0][0] ^= 0xff;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_PATH_AUTH_FAILED);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_insert_leaf_crypto_failure(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- MOCK_aes_fail = 1;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_CRYPTO_FAILURE);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_insert_leaf_nv_fail(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_NV_LENGTH_MISMATCH);
- return EC_SUCCESS;
-}
-
-static int handle_insert_leaf_success(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- size_t x;
- const uint8_t *plain_text = (const uint8_t *)&DEFAULT_LEAF.sec;
- struct wrapped_leaf_data_t *wrapped_leaf_data =
- (void *)&buf.response.data.insert_leaf
- .unimported_leaf_data;
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT(buf.response.header.version == PW_PROTOCOL_VERSION);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(buf.response.data.insert_leaf) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf.response.header.result_code, EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- PW_HASH_SIZE);
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.insert_leaf.unimported_leaf_data.hmac,
- DEFAULT_HMAC, sizeof(DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(
- (uint8_t *)&wrapped_leaf_data->pub,
- (uint8_t *)&DEFAULT_LEAF.pub, sizeof(DEFAULT_LEAF.pub));
- for (x = 0; x < sizeof(DEFAULT_LEAF.sec); ++x)
- TEST_ASSERT(plain_text[x] ==
- (wrapped_leaf_data->cipher_text[x] ^
- MOCK_AES_XOR_BYTE(x)));
-
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].type.v == PW_INSERT_LEAF);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].label.v ==
- DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].root,
- ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].leaf_hmac,
- DEFAULT_HMAC,
- sizeof(DEFAULT_HMAC));
-
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_insert_leaf_old_protocol_success(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- size_t x;
- int hash_count;
- unsigned char *src;
- const uint8_t *plain_text = (const uint8_t *)&DEFAULT_LEAF.sec;
- struct wrapped_leaf_data_t *wrapped_leaf_data =
- (void *)&buf.response.data.insert_leaf
- .unimported_leaf_data;
-
- setup_insert_leaf_defaults(&merkle_tree, &buf.request);
-
- // Make changes to simulate the protocol 0 request.
- buf.request.header.version = 0;
- hash_count =
- get_path_auxiliary_hash_count(&merkle_tree);
- src = (unsigned char *)
- (&buf.request.data.insert_leaf.valid_pcr_criteria);
- memmove(src, src + PW_VALID_PCR_CRITERIA_SIZE,
- hash_count * PW_HASH_SIZE);
- buf.request.header.data_length -= PW_VALID_PCR_CRITERIA_SIZE;
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT(buf.response.header.version == 0);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(buf.response.data.insert_leaf) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf.response.header.result_code, EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- PW_HASH_SIZE);
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.insert_leaf.unimported_leaf_data.hmac,
- DEFAULT_HMAC, sizeof(DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(
- (uint8_t *)&wrapped_leaf_data->pub,
- (uint8_t *)&DEFAULT_LEAF.pub, sizeof(DEFAULT_LEAF.pub));
- for (x = 0; x < sizeof(DEFAULT_LEAF.sec); ++x)
- TEST_ASSERT(plain_text[x] ==
- (wrapped_leaf_data->cipher_text[x] ^
- MOCK_AES_XOR_BYTE(x)));
-
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].type.v == PW_INSERT_LEAF);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].label.v ==
- DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].root,
- ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].leaf_hmac,
- DEFAULT_HMAC,
- sizeof(DEFAULT_HMAC));
-
- return check_dcrypto_mutex_usage();
-}
-
-/******************************************************************************/
-/* Remove leaf test cases.
- */
-
-static int handle_remove_leaf_invalid_length(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_remove_leaf_defaults(&merkle_tree, &buf.request);
-
- ++buf.request.header.data_length;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf,
- ROOT_WITH_DEFAULT_HMAC),
- PW_ERR_LENGTH_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_remove_leaf_label_invalid(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_remove_leaf_defaults(&merkle_tree, &buf.request);
-
- buf.request.data.remove_leaf.leaf_location.v |= 0x030000;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf,
- ROOT_WITH_DEFAULT_HMAC),
- PW_ERR_LABEL_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_remove_leaf_path_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_remove_leaf_defaults(&merkle_tree, &buf.request);
-
- buf.request.data.remove_leaf.path_hashes[0][0] ^= 0xff;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf,
- ROOT_WITH_DEFAULT_HMAC),
- PW_ERR_PATH_AUTH_FAILED);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_remove_leaf_nv_fail(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_remove_leaf_defaults(&merkle_tree, &buf.request);
-
- MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_NV_LENGTH_MISMATCH);
- return EC_SUCCESS;
-}
-
-static int handle_remove_leaf_success(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_remove_leaf_defaults(&merkle_tree, &buf.request);
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- EC_SUCCESS);
-
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].type.v ==
- PW_REMOVE_LEAF);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].label.v ==
- DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].root,
- EMPTY_TREE.root, sizeof(EMPTY_TREE.root));
- return check_dcrypto_mutex_usage();
-}
-
-/******************************************************************************/
-/* Try auth test cases.
- */
-
-static int handle_try_auth_invalid_length(void)
-{
- return invalid_length_with_leaf_head(
- (size_t)&((struct pw_request_t *)0)->data.try_auth
- .unimported_leaf_data.head,
- setup_try_auth_defaults);
-}
-
-static int handle_try_auth_leaf_version_mismatch(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_header_t *req_head =
- &buf.request.data.try_auth.unimported_leaf_data.head;
-
- setup_try_auth_defaults(&merkle_tree, &buf.request);
-
- ++req_head->leaf_version.major;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf,
- ROOT_WITH_DEFAULT_HMAC),
- PW_ERR_LEAF_VERSION_MISMATCH);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_try_auth_label_invalid(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_data_t leaf_data;
-
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(DEFAULT_LEAF));
- leaf_data.pub.label.v |= 0x030000;
- setup_try_auth_defaults_with_leaf(&leaf_data, PW_PROTOCOL_VERSION,
- PW_LEAF_MINOR_VERSION, &merkle_tree,
- &buf.request);
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf,
- ROOT_WITH_DEFAULT_HMAC),
- PW_ERR_LABEL_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_try_auth_path_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- uint8_t (*path_hashes)[32] =
- (void *)buf.request.data.try_auth.unimported_leaf_data
- .payload +
- sizeof(struct leaf_public_data_t) +
- sizeof(struct leaf_sensitive_data_t);
-
- setup_try_auth_defaults(&merkle_tree, &buf.request);
-
- (*path_hashes)[0] ^= 0xff;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf,
- ROOT_WITH_DEFAULT_HMAC),
- PW_ERR_PATH_AUTH_FAILED);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_try_auth_hmac_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_try_auth_defaults(&merkle_tree, &buf.request);
-
- MOCK_hash_update_cb = 0;
- MOCK_hmac = EMPTY_TREE.root;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf,
- ROOT_WITH_DEFAULT_HMAC),
- PW_ERR_HMAC_AUTH_FAILED);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_try_auth_crypto_failure(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_try_auth_defaults(&merkle_tree, &buf.request);
-
- MOCK_aes_fail = 1;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf,
- ROOT_WITH_DEFAULT_HMAC),
- PW_ERR_CRYPTO_FAILURE);
- return check_dcrypto_mutex_usage();
-}
-
-static int check_try_auth_rate_limit_reached_response(
- struct merkle_tree_t *merkle_tree,
- struct pw_test_data_t *buf,
- const struct time_diff_t seconds_to_wait)
-{
- uint8_t old_root[PW_HASH_SIZE];
-
- memcpy(old_root, merkle_tree->root, sizeof(old_root));
-
- TEST_RET_EQ(do_request(merkle_tree, buf), PW_ERR_RATE_LIMIT_REACHED);
-
- TEST_ASSERT(buf->response.header.version == PW_PROTOCOL_VERSION);
- TEST_ASSERT(buf->response.header.data_length ==
- sizeof(struct pw_response_try_auth_t) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf->response.header.result_code,
- PW_ERR_RATE_LIMIT_REACHED);
- TEST_ASSERT_ARRAY_EQ(buf->response.header.root, old_root,
- sizeof(old_root));
- TEST_ASSERT_ARRAY_EQ(buf->response.header.root, merkle_tree->root,
- sizeof(merkle_tree->root));
- TEST_ASSERT(buf->response.data.try_auth.seconds_to_wait.v ==
- seconds_to_wait.v);
- TEST_ASSERT_MEMSET(buf->response.data.try_auth.high_entropy_secret,
- 0, PW_SECRET_SIZE);
- TEST_ASSERT_MEMSET((uint8_t *)&buf->response.data.try_auth
- .unimported_leaf_data, 0,
- sizeof(buf->response.data.try_auth
- .unimported_leaf_data) + PW_LEAF_PAYLOAD_SIZE);
-
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_try_auth_rate_limit_reached(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_data_t leaf_data = {};
-
- /* Test PW_BLOCK_ATTEMPTS. */
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(DEFAULT_LEAF));
- leaf_data.pub.attempt_count.v = 51;
- force_restart_count(1);
- force_time((timestamp_t){.val = 7200llu * SECOND});
- setup_try_auth_defaults_with_leaf(&leaf_data, PW_PROTOCOL_VERSION,
- PW_LEAF_MINOR_VERSION, &merkle_tree,
- &buf.request);
-
- TEST_RET_EQ(check_try_auth_rate_limit_reached_response(
- &merkle_tree, &buf,
- (const struct time_diff_t){PW_BLOCK_ATTEMPTS}),
- EC_SUCCESS);
-
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(DEFAULT_LEAF));
- memset(leaf_data.pub.delay_schedule, 0,
- sizeof(leaf_data.pub.delay_schedule));
- leaf_data.pub.delay_schedule[0].attempt_count.v = 5;
- leaf_data.pub.delay_schedule[0].time_diff.v = PW_BLOCK_ATTEMPTS;
- leaf_data.pub.attempt_count.v = 6;
- force_restart_count(1);
- force_time((timestamp_t){.val = 7200llu * SECOND});
- setup_try_auth_defaults_with_leaf(&leaf_data, PW_PROTOCOL_VERSION,
- PW_LEAF_MINOR_VERSION, &merkle_tree,
- &buf.request);
-
- TEST_RET_EQ(check_try_auth_rate_limit_reached_response(
- &merkle_tree, &buf,
- (const struct time_diff_t){PW_BLOCK_ATTEMPTS}),
- EC_SUCCESS);
-
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(DEFAULT_LEAF));
- memset(leaf_data.pub.delay_schedule, 0,
- sizeof(leaf_data.pub.delay_schedule));
- leaf_data.pub.delay_schedule[0].attempt_count.v = 5;
- leaf_data.pub.delay_schedule[0].time_diff.v = PW_BLOCK_ATTEMPTS;
- leaf_data.pub.attempt_count.v = 6;
- force_restart_count(1);
- force_time((timestamp_t){.val = 7200llu * SECOND});
- setup_try_auth_defaults_with_leaf(&leaf_data, PW_PROTOCOL_VERSION,
- PW_LEAF_MINOR_VERSION, &merkle_tree,
- &buf.request);
-
- TEST_RET_EQ(check_try_auth_rate_limit_reached_response(
- &merkle_tree, &buf,
- (const struct time_diff_t){PW_BLOCK_ATTEMPTS}),
- EC_SUCCESS);
-
- /* Test same boot_count case. */
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(DEFAULT_LEAF));
- leaf_data.pub.attempt_count.v = 10;
- leaf_data.pub.timestamp.boot_count = 0;
- leaf_data.pub.timestamp.timer_value = 7200llu;
- setup_try_auth_defaults_with_leaf(&leaf_data, PW_PROTOCOL_VERSION,
- PW_LEAF_MINOR_VERSION, &merkle_tree,
- &buf.request);
- force_restart_count(0);
- force_time((timestamp_t){.val = (leaf_data.pub.timestamp.timer_value +
- 3599llu) * SECOND});
-
- TEST_RET_EQ(check_try_auth_rate_limit_reached_response(
- &merkle_tree, &buf, (const struct time_diff_t){1}),
- EC_SUCCESS);
-
- /* Test boot_count + 1 case. */
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(DEFAULT_LEAF));
- leaf_data.pub.attempt_count.v = 10;
- leaf_data.pub.timestamp.boot_count = 0;
- leaf_data.pub.timestamp.timer_value = 7200llu;
- setup_try_auth_defaults_with_leaf(&leaf_data, PW_PROTOCOL_VERSION,
- PW_LEAF_MINOR_VERSION, &merkle_tree,
- &buf.request);
- force_restart_count(1);
- force_time((timestamp_t){.val = 3599llu * SECOND});
-
- TEST_RET_EQ(check_try_auth_rate_limit_reached_response(
- &merkle_tree, &buf, (const struct time_diff_t){1}),
- EC_SUCCESS);
-
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_try_auth_nv_fail(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_try_auth_defaults(&merkle_tree, &buf.request);
- force_restart_count(0);
- force_time((timestamp_t){.val = 65 * SECOND});
-
- MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_NV_LENGTH_MISMATCH);
- return EC_SUCCESS;
-}
-
-static int handle_try_auth_lowent_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_data_t leaf_data = {};
- struct leaf_public_data_t *pub =
- (void *)buf.response.data.try_auth.unimported_leaf_data
- .payload;
- struct leaf_sensitive_data_t sec = {};
- uint8_t *resp_cipher_text = (void *)pub + sizeof(*pub);
-
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(DEFAULT_LEAF));
- leaf_data.pub.attempt_count.v = 5;
- leaf_data.sec.low_entropy_secret[
- sizeof(leaf_data.sec.low_entropy_secret) - 1] =
- ~leaf_data.sec.low_entropy_secret[
- sizeof(leaf_data.sec.low_entropy_secret) - 1];
-
- setup_try_auth_defaults_with_leaf(&leaf_data, PW_PROTOCOL_VERSION,
- PW_LEAF_MINOR_VERSION, &merkle_tree,
- &buf.request);
-
- force_restart_count(1);
- force_time((timestamp_t){.val = (65ull * SECOND)});
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), PW_ERR_LOWENT_AUTH_FAILED);
-
- TEST_ASSERT(buf.response.header.version == PW_PROTOCOL_VERSION);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(struct pw_response_try_auth_t) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf.response.header.result_code, PW_ERR_LOWENT_AUTH_FAILED);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, EMPTY_TREE.root,
- sizeof(EMPTY_TREE.root));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- sizeof(merkle_tree.root));
-
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.try_auth.unimported_leaf_data.hmac,
- EMPTY_HMAC, sizeof(EMPTY_HMAC));
- TEST_ASSERT_ARRAY_EQ(buf.response.data.try_auth.unimported_leaf_data.iv,
- DEFAULT_IV, sizeof(DEFAULT_IV));
- DCRYPTO_aes_ctr((uint8_t *)&sec, EMPTY_TREE.wrap_key,
- sizeof(EMPTY_TREE.wrap_key) * 8, DEFAULT_IV,
- resp_cipher_text, sizeof(sec));
- TEST_ASSERT(pub->label.v == leaf_data.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(
- (uint8_t *)&pub->delay_schedule,
- (uint8_t *)&leaf_data.pub.delay_schedule,
- sizeof(leaf_data.pub.delay_schedule));
- TEST_ASSERT_ARRAY_EQ((uint8_t *)&sec, (uint8_t *)&leaf_data.sec,
- sizeof(leaf_data.sec));
- TEST_ASSERT(pub->attempt_count.v == leaf_data.pub.attempt_count.v + 1);
- TEST_ASSERT(pub->timestamp.boot_count == 1);
-
- TEST_ASSERT_MEMSET(buf.response.data.try_auth.high_entropy_secret,
- 0, PW_SECRET_SIZE);
-
- /* A threshold of 100 is used since some time will pass after
- * force_time() is called.
- */
- TEST_ASSERT(pub->timestamp.timer_value - 65ull < 100);
-
- /* Validate the log entry for a failed auth attempt. */
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].type.v == PW_TRY_AUTH);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].label.v ==
- DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].return_code ==
- PW_ERR_LOWENT_AUTH_FAILED);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].timestamp.boot_count ==
- pub->timestamp.boot_count);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].timestamp.timer_value ==
- pub->timestamp.timer_value);
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].root,
- EMPTY_TREE.root,
- sizeof(EMPTY_TREE.root));
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_try_auth_pcr_mismatch(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_data_t leaf_data = {};
-
- /* Test same boot_count case. */
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(leaf_data));
- leaf_data.pub.attempt_count.v = 6;
- leaf_data.pub.valid_pcr_criteria[0].bitmask[0] = 1;
- memset(leaf_data.pub.valid_pcr_criteria[0].digest, 0, 32);
- setup_try_auth_defaults_with_leaf(&leaf_data, PW_PROTOCOL_VERSION,
- PW_LEAF_MINOR_VERSION, &merkle_tree,
- &buf.request);
- force_restart_count(0);
- force_time((timestamp_t){.val = 65 * SECOND});
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), PW_ERR_PCR_NOT_MATCH);
-
- return check_dcrypto_mutex_usage();
-}
-
-static int try_auth_success(uint8_t protocol_version,
- uint8_t minor_version)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_data_t leaf_data = {};
- struct leaf_public_data_t *pub =
- (void *)buf.response.data.try_auth.unimported_leaf_data
- .payload;
- struct leaf_sensitive_data_t sec = {};
- uint8_t *resp_cipher_text = (void *)pub + sizeof(*pub);
-
- /* Test same boot_count case. */
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(leaf_data));
- leaf_data.pub.attempt_count.v = 6;
- leaf_data.pub.valid_pcr_criteria[0].bitmask[0] = 1;
- memcpy(leaf_data.pub.valid_pcr_criteria[0].digest,
- DEFAULT_PCR_DIGEST, 32);
- setup_try_auth_defaults_with_leaf(&leaf_data, protocol_version,
- minor_version, &merkle_tree,
- &buf.request);
- force_restart_count(0);
- force_time((timestamp_t){.val = 65 * SECOND});
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT(buf.response.header.version == protocol_version);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(struct pw_response_try_auth_t) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf.response.header.result_code, EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- sizeof(merkle_tree.root));
-
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.try_auth.unimported_leaf_data.hmac,
- DEFAULT_HMAC, sizeof(DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(buf.response.data.try_auth.unimported_leaf_data.iv,
- DEFAULT_IV, sizeof(DEFAULT_IV));
- DCRYPTO_aes_ctr((uint8_t *)&sec, EMPTY_TREE.wrap_key,
- sizeof(EMPTY_TREE.wrap_key) * 8, DEFAULT_IV,
- resp_cipher_text, sizeof(sec));
- TEST_ASSERT(pub->label.v == leaf_data.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(
- (uint8_t *)&pub->delay_schedule,
- (uint8_t *)&leaf_data.pub.delay_schedule,
- sizeof(leaf_data.pub.delay_schedule));
- if (protocol_version == PW_PROTOCOL_VERSION) {
- TEST_ASSERT_ARRAY_EQ((uint8_t *)&sec,
- (uint8_t *)&DEFAULT_LEAF.sec,
- sizeof(DEFAULT_LEAF.sec));
- }
- TEST_ASSERT(pub->attempt_count.v == 0);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.data.try_auth.high_entropy_secret,
- DEFAULT_LEAF.sec.high_entropy_secret,
- sizeof(DEFAULT_LEAF.sec.high_entropy_secret));
-
- TEST_ASSERT_ARRAY_EQ(buf.response.data.try_auth.reset_secret,
- DEFAULT_LEAF.sec.reset_secret,
- sizeof(DEFAULT_LEAF.sec.reset_secret));
-
- /* Validate the log entry on success. */
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].type.v == PW_TRY_AUTH);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].label.v ==
- DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].return_code == EC_SUCCESS);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].timestamp.boot_count ==
- pub->timestamp.boot_count);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].timestamp.timer_value ==
- pub->timestamp.timer_value);
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].root,
- ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
-
- /* Test boot_count + 1 case. */
- leaf_data.pub.attempt_count.v = 6;
- leaf_data.pub.timestamp.boot_count = 0;
- leaf_data.pub.timestamp.timer_value = 7200llu;
- setup_try_auth_defaults_with_leaf(&leaf_data, protocol_version,
- minor_version, &merkle_tree,
- &buf.request);
- force_restart_count(1);
- force_time((timestamp_t){.val = 65llu * SECOND});
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT(buf.response.header.version == protocol_version);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(struct pw_response_try_auth_t) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf.response.header.result_code, EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- sizeof(merkle_tree.root));
-
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.try_auth.unimported_leaf_data.hmac,
- DEFAULT_HMAC, sizeof(DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(buf.response.data.try_auth.unimported_leaf_data.iv,
- DEFAULT_IV, sizeof(DEFAULT_IV));
- DCRYPTO_aes_ctr((uint8_t *)&sec, EMPTY_TREE.wrap_key,
- sizeof(EMPTY_TREE.wrap_key) * 8, DEFAULT_IV,
- resp_cipher_text, sizeof(sec));
- TEST_ASSERT(pub->label.v == leaf_data.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(
- (uint8_t *)&pub->delay_schedule,
- (uint8_t *)&leaf_data.pub.delay_schedule,
- sizeof(leaf_data.pub.delay_schedule));
- if (protocol_version == PW_PROTOCOL_VERSION) {
- TEST_ASSERT_ARRAY_EQ((uint8_t *)&sec,
- (uint8_t *)&DEFAULT_LEAF.sec,
- sizeof(DEFAULT_LEAF.sec));
- }
- TEST_ASSERT(pub->attempt_count.v == 0);
- TEST_ASSERT_ARRAY_EQ(buf.response.data.try_auth.high_entropy_secret,
- DEFAULT_LEAF.sec.high_entropy_secret,
- sizeof(DEFAULT_LEAF.sec.high_entropy_secret));
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_try_auth_success(void)
-{
- return try_auth_success(PW_PROTOCOL_VERSION, PW_LEAF_MINOR_VERSION);
-}
-
-static int handle_try_auth_old_protocol_old_leaf_success(void)
-{
- return try_auth_success(0, 0);
-}
-
-static int handle_try_auth_old_protocol_new_leaf_success(void)
-{
- return try_auth_success(0, PW_LEAF_MINOR_VERSION);
-}
-
-/******************************************************************************/
-/* Reset auth test cases.
- */
-
-static int handle_reset_auth_invalid_length(void)
-{
- return invalid_length_with_leaf_head(
- (size_t)&((struct pw_request_t *)0)->data.reset_auth
- .unimported_leaf_data.head,
- setup_reset_auth_defaults);
-}
-
-static int handle_reset_auth_label_invalid(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_public_data_t *pub =
- (void *)buf.request.data.reset_auth.unimported_leaf_data
- .payload;
-
- setup_reset_auth_defaults(&merkle_tree, &buf.request);
- pub->label.v |= 0x030000;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_LABEL_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_reset_auth_path_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- uint8_t (*path_hashes)[32] =
- (void *)buf.request.data.reset_auth.unimported_leaf_data
- .payload +
- sizeof(struct leaf_public_data_t) +
- sizeof(struct leaf_sensitive_data_t);
-
- setup_reset_auth_defaults(&merkle_tree, &buf.request);
-
- (*path_hashes)[0] ^= 0xff;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_PATH_AUTH_FAILED);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_reset_auth_hmac_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_auth_defaults(&merkle_tree, &buf.request);
-
- MOCK_hash_update_cb = 0;
- MOCK_hmac = EMPTY_TREE.root;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_HMAC_AUTH_FAILED);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_reset_auth_crypto_failure(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_auth_defaults(&merkle_tree, &buf.request);
-
- MOCK_aes_fail = 1;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_CRYPTO_FAILURE);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_reset_auth_reset_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_auth_defaults(&merkle_tree, &buf.request);
-
- buf.request.data.reset_auth.reset_secret[0] ^= 0xff;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_RESET_AUTH_FAILED);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_reset_auth_nv_fail(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_reset_auth_defaults(&merkle_tree, &buf.request);
-
- MOCK_setvar_ret = PW_ERR_NV_LENGTH_MISMATCH;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, merkle_tree.root),
- PW_ERR_NV_LENGTH_MISMATCH);
- return EC_SUCCESS;
-}
-
-static int handle_reset_auth_success(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_public_data_t *pub =
- (void *)buf.response.data.reset_auth
- .unimported_leaf_data.payload;
- struct leaf_sensitive_data_t sec = {};
- uint8_t *resp_cipher_text = (void *)pub + sizeof(*pub);
-
- setup_reset_auth_defaults(&merkle_tree, &buf.request);
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT(buf.response.header.version == PW_PROTOCOL_VERSION);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(struct pw_response_reset_auth_t) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf.response.header.result_code, EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- sizeof(merkle_tree.root));
-
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.reset_auth.high_entropy_secret,
- DEFAULT_LEAF.sec.high_entropy_secret,
- sizeof(DEFAULT_LEAF.sec.high_entropy_secret));
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.reset_auth.unimported_leaf_data.hmac,
- DEFAULT_HMAC, sizeof(DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.reset_auth.unimported_leaf_data.iv,
- DEFAULT_IV, sizeof(DEFAULT_IV));
- DCRYPTO_aes_ctr((uint8_t *)&sec, EMPTY_TREE.wrap_key,
- sizeof(EMPTY_TREE.wrap_key) * 8, DEFAULT_IV,
- resp_cipher_text, sizeof(sec));
- TEST_ASSERT(pub->label.v == DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(
- (const uint8_t *)&pub->delay_schedule,
- (const uint8_t *)&DEFAULT_LEAF.pub.delay_schedule,
- sizeof(DEFAULT_LEAF.pub.delay_schedule));
- TEST_ASSERT_ARRAY_EQ((uint8_t *)&sec, (uint8_t *)&DEFAULT_LEAF.sec,
- sizeof(DEFAULT_LEAF.sec));
- TEST_ASSERT(pub->attempt_count.v == 0);
-
- /* Validate the log entry on success. */
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].type.v == PW_TRY_AUTH);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].label.v ==
- DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].return_code == EC_SUCCESS);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].timestamp.boot_count ==
- pub->timestamp.boot_count);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].timestamp.timer_value ==
- pub->timestamp.timer_value);
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].root,
- ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
-
- /* Test with different minor version and struct lengths. */
- setup_reset_auth_defaults(&merkle_tree, &buf.request);
- setup_mock_future_version(
- &buf.request.data.reset_auth.unimported_leaf_data,
- &buf.request.header.data_length);
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT(buf.response.header.version == PW_PROTOCOL_VERSION);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(struct pw_response_reset_auth_t) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf.response.header.result_code, EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- sizeof(merkle_tree.root));
-
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.reset_auth.high_entropy_secret,
- DEFAULT_LEAF.sec.high_entropy_secret,
- sizeof(DEFAULT_LEAF.sec.high_entropy_secret));
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.reset_auth.unimported_leaf_data.hmac,
- DEFAULT_HMAC, sizeof(DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.reset_auth.unimported_leaf_data.iv,
- DEFAULT_IV, sizeof(DEFAULT_IV));
- DCRYPTO_aes_ctr((uint8_t *)&sec, EMPTY_TREE.wrap_key,
- sizeof(EMPTY_TREE.wrap_key) * 8, DEFAULT_IV,
- resp_cipher_text, sizeof(sec));
- TEST_ASSERT(pub->label.v == DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(
- (const uint8_t *)&pub->delay_schedule,
- (const uint8_t *)&DEFAULT_LEAF.pub.delay_schedule,
- sizeof(DEFAULT_LEAF.pub.delay_schedule));
- TEST_ASSERT_ARRAY_EQ((uint8_t *)&sec, (uint8_t *)&DEFAULT_LEAF.sec,
- sizeof(DEFAULT_LEAF.sec));
- TEST_ASSERT(pub->attempt_count.v == 0);
-
- /* Validate the log entry on success. */
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].type.v == PW_TRY_AUTH);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].label.v ==
- DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].return_code == EC_SUCCESS);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].timestamp.boot_count ==
- pub->timestamp.boot_count);
- TEST_ASSERT(MOCK_pw_log_storage.entries[0].timestamp.timer_value ==
- pub->timestamp.timer_value);
- TEST_ASSERT_ARRAY_EQ(MOCK_pw_log_storage.entries[0].root,
- ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- return check_dcrypto_mutex_usage();
-}
-
-/******************************************************************************/
-/* Get log test cases.
- */
-
-static int handle_get_log_invalid_length(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_get_log_defaults(&merkle_tree, &buf.request);
-
- ++buf.request.header.data_length;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_LENGTH_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_get_log_nv_fail(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_get_log_defaults(&merkle_tree, &buf.request);
-
- MOCK_getvar_ret = PW_ERR_NV_EMPTY;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_NV_EMPTY);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_get_log_success(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- const struct pw_get_log_entry_t (*view)[PW_LOG_ENTRY_COUNT] =
- (void *)buf.response.data.get_log;
-
- setup_get_log_defaults(&merkle_tree, &buf.request);
- setup_storage(4);
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, EMPTY_TREE.root,
- sizeof(EMPTY_TREE.root));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- sizeof(merkle_tree.root));
-
- TEST_ASSERT(buf.response.header.version == PW_PROTOCOL_VERSION);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(struct pw_get_log_entry_t) * PW_LOG_ENTRY_COUNT);
- TEST_RET_EQ(buf.response.header.result_code, EC_SUCCESS);
-
- TEST_ASSERT(buf.response.header.version == PW_PROTOCOL_VERSION);
-
- TEST_ASSERT((*view)[0].type.v == PW_REMOVE_LEAF);
- TEST_ASSERT((*view)[0].label.v == DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT_ARRAY_EQ((*view)[0].root, EMPTY_TREE.root,
- sizeof(EMPTY_TREE.root));
-
- TEST_ASSERT((*view)[1].type.v == PW_TRY_AUTH);
- TEST_ASSERT((*view)[1].label.v == DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT((*view)[1].return_code == EC_SUCCESS);
- TEST_ASSERT((*view)[1].timestamp.boot_count == 10);
- TEST_ASSERT((*view)[1].timestamp.timer_value == 100);
- TEST_ASSERT_ARRAY_EQ((*view)[1].root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
-
- setup_get_log_defaults(&merkle_tree, &buf.request);
- setup_storage(2);
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT((*view)[0].type.v == PW_TRY_AUTH);
- TEST_ASSERT((*view)[0].label.v == DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT((*view)[0].return_code == PW_ERR_LOWENT_AUTH_FAILED);
- TEST_ASSERT((*view)[0].timestamp.boot_count == 7);
- TEST_ASSERT((*view)[0].timestamp.timer_value == 99);
- TEST_ASSERT_ARRAY_EQ((*view)[0].root, ROOT_WITH_OTHER_HMAC,
- sizeof(ROOT_WITH_OTHER_HMAC));
-
- TEST_ASSERT((*view)[1].type.v == PW_INSERT_LEAF);
- TEST_ASSERT((*view)[1].label.v == DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT_ARRAY_EQ((*view)[1].root, ROOT_WITH_DEFAULT_HMAC,
- sizeof(ROOT_WITH_DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ((*view)[1].leaf_hmac, DEFAULT_HMAC,
- sizeof(DEFAULT_HMAC));
-
- setup_get_log_defaults(&merkle_tree, &buf.request);
- setup_storage(0);
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT((*view)[0].type.v == PW_RESET_TREE);
- TEST_ASSERT_ARRAY_EQ((*view)[0].root, EMPTY_TREE.root,
- sizeof(EMPTY_TREE.root));
-
- return check_dcrypto_mutex_usage();
-}
-
-/******************************************************************************/
-/* Log replay test cases.
- */
-
-static int handle_log_replay_invalid_length(void)
-{
- return invalid_length_with_leaf_head(
- (size_t)&((struct pw_request_t *)0)->data.log_replay
- .unimported_leaf_data.head,
- setup_log_replay_defaults);
-}
-
-static int handle_log_replay_nv_fail(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_log_replay_defaults(&merkle_tree, &buf.request);
-
- MOCK_getvar_ret = PW_ERR_NV_EMPTY;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_NV_EMPTY);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_log_replay_root_not_found(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_log_replay_defaults(&merkle_tree, &buf.request);
-
- memcpy(buf.request.data.log_replay.log_root, DEFAULT_HMAC,
- sizeof(DEFAULT_HMAC));
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_ROOT_NOT_FOUND);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_log_replay_type_invalid(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
-
- setup_log_replay_defaults(&merkle_tree, &buf.request);
-
- memcpy(buf.request.data.log_replay.log_root, EMPTY_TREE.root,
- sizeof(EMPTY_TREE.root));
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_TYPE_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_log_replay_hmac_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_data_t leaf_data = {};
-
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(leaf_data));
- leaf_data.pub.attempt_count.v = 7;
- setup_log_replay_defaults_with_leaf(&leaf_data, &merkle_tree,
- &buf.request);
-
- memcpy(buf.request.data.log_replay.unimported_leaf_data.hmac,
- EMPTY_HMAC, sizeof(EMPTY_HMAC));
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_HMAC_AUTH_FAILED);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_log_replay_crypto_failure(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_data_t leaf_data = {};
-
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(leaf_data));
- leaf_data.pub.attempt_count.v = 7;
- setup_log_replay_defaults_with_leaf(&leaf_data, &merkle_tree,
- &buf.request);
-
- MOCK_aes_fail = 1;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_CRYPTO_FAILURE);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_log_replay_label_invalid(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_data_t leaf_data = {};
-
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(leaf_data));
- leaf_data.pub.label.v = 0;
- setup_log_replay_defaults_with_leaf(&leaf_data, &merkle_tree,
- &buf.request);
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_LABEL_INVALID);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_log_replay_path_auth_failed(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- uint8_t (*path_hashes)[32] =
- (void *)buf.request.data.log_replay.unimported_leaf_data
- .payload +
- sizeof(struct leaf_public_data_t) +
- sizeof(struct leaf_sensitive_data_t);
-
- setup_log_replay_defaults(&merkle_tree, &buf.request);
-
- (*path_hashes)[0] ^= 0xff;
-
- TEST_RET_EQ(test_handle_short_msg(&merkle_tree, &buf, EMPTY_TREE.root),
- PW_ERR_PATH_AUTH_FAILED);
- return check_dcrypto_mutex_usage();
-}
-
-static int handle_log_replay_success(void)
-{
- struct merkle_tree_t merkle_tree;
- struct pw_test_data_t buf;
- struct leaf_data_t leaf_data = {};
- struct leaf_public_data_t *pub =
- (void *)buf.response.data.log_replay
- .unimported_leaf_data.payload;
- struct leaf_sensitive_data_t sec = {};
- uint8_t *resp_cipher_text = (void *)pub + sizeof(*pub);
-
- /*
- * Test for auth success.
- */
- setup_log_replay_defaults(&merkle_tree, &buf.request);
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT(buf.response.header.version == PW_PROTOCOL_VERSION);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(struct pw_response_log_replay_t) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf.response.header.result_code, EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, EMPTY_TREE.root,
- sizeof(EMPTY_TREE.root));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- sizeof(merkle_tree.root));
-
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.log_replay.unimported_leaf_data.hmac,
- DEFAULT_HMAC, sizeof(DEFAULT_HMAC));
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.log_replay.unimported_leaf_data.iv,
- DEFAULT_IV, sizeof(DEFAULT_IV));
- DCRYPTO_aes_ctr((uint8_t *)&sec, EMPTY_TREE.wrap_key,
- sizeof(EMPTY_TREE.wrap_key) * 8, DEFAULT_IV,
- resp_cipher_text, sizeof(sec));
- TEST_ASSERT(pub->label.v == DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(
- (const uint8_t *)&pub->delay_schedule,
- (const uint8_t *)&DEFAULT_LEAF.pub.delay_schedule,
- sizeof(DEFAULT_LEAF.pub.delay_schedule));
- TEST_ASSERT_ARRAY_EQ((uint8_t *)&sec, (uint8_t *)&DEFAULT_LEAF.sec,
- sizeof(DEFAULT_LEAF.sec));
- TEST_ASSERT(pub->attempt_count.v == 0);
- TEST_ASSERT(pub->timestamp.boot_count == 10);
- TEST_ASSERT(pub->timestamp.timer_value == 100);
-
- /*
- * Test for auth failed.
- */
- memcpy(&leaf_data, &DEFAULT_LEAF, sizeof(leaf_data));
- leaf_data.pub.attempt_count.v = 15;
- setup_log_replay_defaults_with_leaf(&leaf_data, &merkle_tree,
- &buf.request);
- memcpy(buf.request.data.log_replay.log_root, ROOT_WITH_OTHER_HMAC,
- sizeof(ROOT_WITH_OTHER_HMAC));
- setup_storage(2);
-
- TEST_RET_EQ(do_request(&merkle_tree, &buf), EC_SUCCESS);
-
- TEST_ASSERT(buf.response.header.version == PW_PROTOCOL_VERSION);
- TEST_ASSERT(buf.response.header.data_length ==
- sizeof(struct pw_response_log_replay_t) +
- PW_LEAF_PAYLOAD_SIZE);
- TEST_RET_EQ(buf.response.header.result_code, EC_SUCCESS);
-
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, EMPTY_TREE.root,
- sizeof(EMPTY_TREE.root));
- TEST_ASSERT_ARRAY_EQ(buf.response.header.root, merkle_tree.root,
- sizeof(merkle_tree.root));
-
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.log_replay.unimported_leaf_data.hmac,
- OTHER_HMAC, sizeof(OTHER_HMAC));
- TEST_ASSERT_ARRAY_EQ(
- buf.response.data.log_replay.unimported_leaf_data.iv,
- DEFAULT_IV, sizeof(DEFAULT_IV));
- DCRYPTO_aes_ctr((uint8_t *)&sec, EMPTY_TREE.wrap_key,
- sizeof(EMPTY_TREE.wrap_key) * 8, DEFAULT_IV,
- resp_cipher_text, sizeof(sec));
- TEST_ASSERT(pub->label.v == DEFAULT_LEAF.pub.label.v);
- TEST_ASSERT_ARRAY_EQ(
- (const uint8_t *)&pub->delay_schedule,
- (const uint8_t *)&DEFAULT_LEAF.pub.delay_schedule,
- sizeof(DEFAULT_LEAF.pub.delay_schedule));
- TEST_ASSERT_ARRAY_EQ((uint8_t *)&sec, (uint8_t *)&DEFAULT_LEAF.sec,
- sizeof(DEFAULT_LEAF.sec));
- TEST_ASSERT(pub->attempt_count.v == 16);
- TEST_ASSERT(pub->timestamp.boot_count == 7);
- TEST_ASSERT(pub->timestamp.timer_value == 99);
- return check_dcrypto_mutex_usage();
-}
-
-/******************************************************************************/
-/* Main test function. Encapsulates the test cases..
- */
-
-void run_test(void)
-{
- test_reset();
-
- /* Test basic operations. */
- RUN_TEST(get_path_auxiliary_hash_count_test);
- RUN_TEST(compute_hash_test);
-
- /* Test header validation. */
- RUN_TEST(handle_request_version_mismatch);
- RUN_TEST(handle_request_invalid_type);
-
- /* Test reset tree. */
- RUN_TEST(handle_reset_tree_invalid_length);
- RUN_TEST(handle_reset_tree_bits_per_level_invalid);
- RUN_TEST(handle_reset_tree_height_invalid);
- RUN_TEST(handle_reset_tree_crypto_failure);
- RUN_TEST(handle_reset_tree_nv_fail);
- RUN_TEST(handle_reset_tree_success);
-
- /* Test insert leaf. */
- RUN_TEST(handle_insert_leaf_invalid_length);
- RUN_TEST(handle_insert_leaf_label_invalid);
- RUN_TEST(handle_insert_leaf_delay_schedule_invalid);
- RUN_TEST(handle_insert_leaf_path_auth_failed);
- RUN_TEST(handle_insert_leaf_crypto_failure);
- RUN_TEST(handle_insert_leaf_nv_fail);
- RUN_TEST(handle_insert_leaf_success);
- RUN_TEST(handle_insert_leaf_old_protocol_success);
-
- /* Test remove leaf. */
- RUN_TEST(handle_remove_leaf_invalid_length);
- RUN_TEST(handle_remove_leaf_label_invalid);
- RUN_TEST(handle_remove_leaf_path_auth_failed);
- RUN_TEST(handle_remove_leaf_nv_fail);
- RUN_TEST(handle_remove_leaf_success);
-
- /* Test try auth. */
- RUN_TEST(handle_try_auth_invalid_length);
- RUN_TEST(handle_try_auth_leaf_version_mismatch);
- RUN_TEST(handle_try_auth_label_invalid);
- RUN_TEST(handle_try_auth_path_auth_failed);
- RUN_TEST(handle_try_auth_hmac_auth_failed);
- RUN_TEST(handle_try_auth_crypto_failure);
- RUN_TEST(handle_try_auth_rate_limit_reached);
- RUN_TEST(handle_try_auth_nv_fail);
- RUN_TEST(handle_try_auth_lowent_auth_failed);
- RUN_TEST(handle_try_auth_pcr_mismatch);
- RUN_TEST(handle_try_auth_success);
- RUN_TEST(handle_try_auth_old_protocol_old_leaf_success);
- RUN_TEST(handle_try_auth_old_protocol_new_leaf_success);
-
- /* Test reset auth. */
- RUN_TEST(handle_reset_auth_invalid_length);
- RUN_TEST(handle_reset_auth_label_invalid);
- RUN_TEST(handle_reset_auth_path_auth_failed);
- RUN_TEST(handle_reset_auth_hmac_auth_failed);
- RUN_TEST(handle_reset_auth_crypto_failure);
- RUN_TEST(handle_reset_auth_reset_auth_failed);
- RUN_TEST(handle_reset_auth_nv_fail);
- RUN_TEST(handle_reset_auth_success);
-
- /* Test get log. */
- RUN_TEST(handle_get_log_invalid_length);
- RUN_TEST(handle_get_log_nv_fail);
- RUN_TEST(handle_get_log_success);
-
- /* Test log replay. */
- RUN_TEST(handle_log_replay_invalid_length);
- RUN_TEST(handle_log_replay_nv_fail);
- RUN_TEST(handle_log_replay_root_not_found);
- RUN_TEST(handle_log_replay_type_invalid);
- RUN_TEST(handle_log_replay_hmac_auth_failed);
- RUN_TEST(handle_log_replay_crypto_failure);
- RUN_TEST(handle_log_replay_label_invalid);
- RUN_TEST(handle_log_replay_path_auth_failed);
- RUN_TEST(handle_log_replay_success);
-
- test_print_result();
-}
diff --git a/test/pinweaver.tasklist b/test/pinweaver.tasklist
deleted file mode 100644
index 24870f2abb..0000000000
--- a/test/pinweaver.tasklist
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Copyright 2018 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.
- */
-
-/**
- * See CONFIG_TASK_LIST in config.h for details.
- */
-#define CONFIG_TEST_TASK_LIST
diff --git a/test/rma_auth.tasklist b/test/rma_auth.tasklist
deleted file mode 100644
index 7150f17cbd..0000000000
--- a/test/rma_auth.tasklist
+++ /dev/null
@@ -1,9 +0,0 @@
-/* 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.
- */
-
-/**
- * See CONFIG_TASK_LIST in config.h for details.
- */
-#define CONFIG_TEST_TASK_LIST /* No test task */
diff --git a/test/test_config.h b/test/test_config.h
index 65e8ccffd4..ce49862647 100644
--- a/test/test_config.h
+++ b/test/test_config.h
@@ -456,43 +456,6 @@ int ncp15wb_calculate_temp(uint16_t adc);
#define CONFIG_USB_PD_PORT_MAX_COUNT 2
#endif
-#if defined(TEST_NVMEM) || defined(TEST_NVMEM_VARS)
-#define CONFIG_CRC8
-#define CONFIG_FLASH_ERASED_VALUE32 (-1U)
-#define CONFIG_FLASH_LOG
-#define CONFIG_FLASH_LOG_BASE CONFIG_PROGRAM_MEMORY_BASE
-#define CONFIG_FLASH_LOG_SPACE 0x800
-#define CONFIG_FLASH_NVMEM
-#define CONFIG_FLASH_NVMEM_OFFSET_A 0x3d000
-#define CONFIG_FLASH_NVMEM_OFFSET_B 0x7d000
-#define CONFIG_FLASH_NVMEM_BASE_A \
- (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_A)
-#define CONFIG_FLASH_NVMEM_BASE_B \
- (CONFIG_PROGRAM_MEMORY_BASE + CONFIG_FLASH_NVMEM_OFFSET_B)
-#define CONFIG_FLASH_NEW_NVMEM_BASE_A (CONFIG_FLASH_NVMEM_BASE_A + 0x800)
-#define CONFIG_FLASH_NEW_NVMEM_BASE_B (CONFIG_FLASH_NVMEM_BASE_B + 0x800)
-#define CONFIG_MALLOC
-/* This is legacy NVMEM partition size. */
-#define NVMEM_PARTITION_SIZE 0x3000
-#define NEW_FLASH_HALF_NVMEM_SIZE \
- (NVMEM_PARTITION_SIZE - CONFIG_FLASH_BANK_SIZE)
-#define NEW_NVMEM_PARTITION_SIZE (NVMEM_PARTITION_SIZE - CONFIG_FLASH_BANK_SIZE)
-#define NEW_NVMEM_TOTAL_PAGES \
- (2 * NEW_NVMEM_PARTITION_SIZE / CONFIG_FLASH_BANK_SIZE)
-#define CONFIG_SW_CRC
-#define CONFIG_FLASH_NVMEM_VARS
-
-#ifndef __ASSEMBLER__
-enum nvmem_users { NVMEM_TPM = 0, NVMEM_CR50, NVMEM_NUM_USERS };
-#endif
-#endif
-
-#ifdef TEST_PINWEAVER
-#define CONFIG_DCRYPTO_MOCK
-#define CONFIG_PINWEAVER
-#define CONFIG_SHA256
-#endif /* TEST_PINWEAVER */
-
#ifdef TEST_RTC
#define CONFIG_HOSTCMD_RTC
#endif
diff --git a/util/g_regs b/util/g_regs
deleted file mode 100755
index 28e6f4a53d..0000000000
--- a/util/g_regs
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/usr/bin/perl
-# Copyright 2015 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.
-
-use strict;
-our $opt_D;
-
-use File::Basename;
-my $progdir = dirname($0);
-my $prog = basename($0);
-
-use Getopt::Std;
-my $usage = "
-Usage: $prog [HEADER]
-
-This converts the FPGA release's generated C header file into the
-hw_regdefs.h file that is included by chip/g/registers.h.
-Mostly it just prefaces the macros with GC_ to avoid name collision.
-
-";
-getopts('D') or die $usage;
-
-
-print "/*
- * Copyright 2015 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.
- */
-
-/* This file is autogenerated by the $prog utility. Do not edit. */
-
-";
-
-while(<>)
-{
- if ( s/\b\w+_REGDEFS_H/__EC_CHIP_G_CR50_FPGA_REGDEFS_H/g )
- {
- print;
- next;
- }
-
- if ( s/__ENABLE_FLASH_DFT_DEFINITIONS__/GC__ENABLE_FLASH_DFT_DEFINITIONS__/g )
- {
- print;
- next;
- }
-
- if ( s/\bFLASH_DFT/GC_FLASH_DFT/g )
- {
- print;
- next;
- }
-
- if ( m/^#define\s+(\S+)\s+(\S+)\s*$/ )
- {
- my ($k,$v) = ($1,$2);
-
- if ($k =~ m/^IRQNUM/) {
- # irqnums must be decimal
- $v = 0 + hex($v);
- }
- $k = "GC_$k";
- printf("#define %-40s %s\n", $k, $v);
- if ( $k =~ m/0_BASE_ADDR$/ ) {
- $k =~ s/0_BASE_ADDR/_BASE_ADDR/;
- printf("#define %-40s %s\n", $k, $v);
- }
- next;
- }
-
- next if m!//!;
- next if m!/\*! .. m!\*/!;
-
- print;
-}
-
diff --git a/util/signer/bs b/util/signer/bs
deleted file mode 100755
index 23ee46039a..0000000000
--- a/util/signer/bs
+++ /dev/null
@@ -1,342 +0,0 @@
-#!/bin/bash
-
-#
-# Copyright 2016 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.
-#
-# This script is a utility which allows to create differently signed CR50
-# images from different sources.
-#
-set -e
-set -u
-
-progname=$(basename $0)
-
-OD="/usr/bin/od"
-
-tmpf="/tmp/bs_manifest.$$"
-trap "{ if [[ -f 1.flat ]]; then rm -rf [01].flat ${tmpf} ; fi; }" EXIT
-
-usage() {
- local rv="${1}"
- cat <<EOF
-
-This script allows to sign CR50 RW images. By default it uses ec.RW.elf and
-ec.RW_B.elf in build/cr50/RW as inputs and util/signer/ec_RW-manifest-dev.json
-as the manifest, and places the newly signed images into build/cr50/ec.bin.
-
-The only outside dependency of this script is the signing utility itself,
-which is expected to be available as /usr/bin/cr50-codesigner.
-
-The utility can be installed by running 'sudo emerge cr50-utils',
-
-The following command line options are accepted:
-
- b1 - generate signature for the b1 version of the H1 chip
- elves <elf1> <elf2> - sign the supplied elf files instead of the default
- ones. Handy if the builder generated files need to be signed
- help - print this message
- hex - generate hex output instead of binary (place in 0.signed.hex and
- 1.signed.hex in the local directory)
- prod - sign with prod key (no debug image will be signed)
-
-This script also allows to sign dev images for running on prod RO. To do that
-invoke this script as follows:
-
- H1_DEVIDS='<dev id0> <dev id1>' ${progname} [other options, if any]
-
-where <dev id0> <dev id1> are values reported by sysinfo command in the
-DEV_ID: line when run on the CR50 for which the image is built.
-
-The same values can be obtained in the lsusb command output:
-
- lsusb -vd 18d1:5014 | grep -i serial
-
-note that the lsusb reported values are in hex and need to be prefixed with
-0x.
-
-Finally, this script also allows to specify the board ID fields of the RW
-headers. The fields come from the evironment variable CR50_BOARD_ID, which is
-required to include three colon separated fields. The first field is a four
-letter board RLZ code, the second field is board id mask in hex, no 0x prefix,
-and the third field - board ID flags, again, hex, no 0x prefix.
-
-CR50_BOARD_ID='XXYY:ffffff00:ff00' ${progname} [other options, if any]
-
-both H1_DEVIDS and CR50_BOARD_ID can be defined independently.
-
-EOF
- exit "${rv}"
-}
-
-# This function modifies the manifest to include device ID and board ID nodes,
-# if H1_DEVIDS and CR50_BOARD_ID are defined in the environment, respectively,
-tweak_manifest () {
- local sub
-
- # If defined, plug in dev ID nodes before the 'fuses' node.
- if [[ -z "${do_prod}" && -n "${H1_DEVIDS}" ]]; then
- echo "creating a customized DEV image for DEV IDS ${H1_DEVIDS}"
- sub=$(printf "\\\n \"DEV_ID0\": %s,\\\n \"DEV_ID1\": %s," ${H1_DEVIDS})
- sed -i "s/\"fuses\": {/\"fuses\": {${sub}/" "${tmpf}"
- fi
-
- if [[ -z "${CR50_BOARD_ID}" ]]; then
- return
- fi
-
- # CR50_BOARD_ID is set, let's parse it and plug in the board ID related
- # nodes into manifest before the 'fuses' node.
- local bid_params
- local rlz
-
- bid_params=( $(echo $CR50_BOARD_ID | sed 's/:/ /g') )
- # A very basic sanity check: it needs to consist of three colon separated
- # fields.
- if [[ ${#bid_params[@]} != 3 ]]; then
- echo "Wrong board ID string \"$CR50_BOARD_ID\"}" >&2
- exit 1
- fi
-
- if [[ "${bid_params[0]}" == "0" ]] ; then
- rlz="0"
- elif [[ ${#bid_params[0]} == 4 ]] ; then
- # Convert 4 char board RLZ code from ASCII to hex
- rlz="0x$(echo -n ${bid_params[0]} | hexdump -ve '/1 "%02x"')"
- else
- echo "Invalid RLZ ${bid_params[0]}"
- exit 1
- fi
-
- # Prepare text of all three board ID related nodes
- sub="$(printf "\\\n\"board_id\": %s,\\\n" "${rlz}")"
- sub+="$(printf "\"board_id_mask\": %s,\\\n" "0x${bid_params[1]}")"
- sub+="$(printf "\"board_id_flags\": %s,\\\n" "0x${bid_params[2]}")"
- sed -i "s/\"fuses\": {/${sub}\"fuses\": {/" "${tmpf}"
-}
-
-# This function accepts two arguments, names of two binary files.
-#
-# It searches the first passed in file for the first 8 bytes of the second
-# passed in file. The od utility is used to generate full hex dump of the
-# first file (16 bytes per line) and the first 8 bytes of the second file.
-#
-# grep is used to check if the pattern is present in the full dump. If the
-# pattern is not found, the first file is dumped again, this time with an 8
-# byte offset into the file. This makes sure that if the match is present, but
-# is spanning two lines of the original hex dump, it is in a single dump line
-# the second time around.
-find_blob_in_blob() {
- local main_blob="${1}"
- local pattern_blob="${2}"
- local pattern
- local od_options="-An -tx1"
-
- # Get the first 8 bytes of the pattern blob.
- pattern="$(${OD} ${od_options} -N8 "${pattern_blob}")"
-
- if "${OD}" ${od_options} "${main_blob}" | grep "${pattern}" > /dev/null; then
- return 0
- fi
-
- # Just in case pattern was wrapped in the previous od output, let's do it
- # again with an 8 bytes offset
- if "${OD}" ${od_options} -j8 "${main_blob}" |
- grep "${pattern}" > /dev/null; then
- return 0
- fi
-
- return 1
-}
-
-# This function accepts two arguments, names of the two elf files.
-#
-# The files are searched for test RMA public key patterns - x25519 or p256,
-# both files are supposed to have pattern of one of these keys and not the
-# other. If this holds true the function prints the public key base name. If
-# not both files include the same key, or include more than one key, the
-# function reports failure and exits the script.
-determine_rma_key_base() {
- local base_name="${EC_ROOT}/board/cr50/rma_key_blob"
- local curve
- local curves=( "x25519" "p256" )
- local elf
- local elves=( "$1" "$2" )
- local key_file
- local mask=1
- local result=0
-
- for curve in ${curves[@]}; do
- key_file="${base_name}.${curve}.test"
- for elf in ${elves[@]}; do
- if find_blob_in_blob "${elf}" "${key_file}"; then
- result=$(( result | mask ))
- fi
- mask=$(( mask << 1 ))
- done
- done
-
- case "${result}" in
- (3) curve="x25519";;
- (12) curve="p256";;
- (*) echo "could not determine key type in the elves" >&2
- exit 1
- ;;
- esac
-
- echo "${base_name}.${curve}"
-}
-
-SIGNER="cr50-codesigner"
-if ! which "${SIGNER}" 2>/dev/null > /dev/null; then
- echo "${SIGNER} is not available, try running 'sudo emerge cr50-utils'" >&2
- exit 1
-fi
-
-# This is where the new signed image will be pasted into.
-: ${RESULT_FILE=build/cr50/ec.bin}
-TMP_RESULT_FILE="${RESULT_FILE}.tmp"
-
-if [[ -z "${CROS_WORKON_SRCROOT}" ]]; then
- echo "${progname}: This script must run inside Chrome OS chroot" >&2
- exit 1
-fi
-
-: ${CR50_BOARD_ID=}
-: ${H1_DEVIDS=}
-EC_ROOT="${CROS_WORKON_SRCROOT}/src/platform/ec"
-EC_BIN_ROOT="${EC_ROOT}/util/signer"
-
-do_hex=
-do_b1=
-do_prod=
-
-# Prepare the default manifest.
-cp "${EC_BIN_ROOT}/ec_RW-manifest-dev.json" "${tmpf}"
-
-elves=( build/cr50/RW/ec.RW.elf build/cr50/RW/ec.RW_B.elf )
-cd "${EC_ROOT}"
-while (( $# )); do
- param="${1}"
- case "${param}" in
- (hex) do_hex='true';;
- (b1)
- do_b1='true'
- sed -i 's/\(.*FW_DEFINED_DATA_BLK0.*\): 2/\1: 0/' "${tmpf}"
- ;;
- (elves)
- if [[ (( $# < 3 )) ]]; then
- echo "two elf file names are required" >&2
- exit 1
- fi
- elves=( $2 $3 )
- shift
- shift
- ;;
- (prod)
- do_prod='true'
- ;;
- (help)
- usage 0
- ;;
- (*)
- usage 1
- ;;
- esac
- shift
-done
-
-if [[ -z "${do_hex}" && ! -f "${RESULT_FILE}" ]]; then
- echo "${RESULT_FILE} not found. Run 'make BOARD=cr50' first" >&2
- exit 1
-fi
-
-if [[ -n "${do_prod}" && -n "${do_b1}" ]]; then
- echo "can not build prod images for B1, sorry..."
- exit 1
-fi
-
-# If signing a chip factory image (version 0.0.22) do not try figuring out the
-# RMA keys.
-ignore_rma_keys="$(awk '
- BEGIN {count = 0};
- /"major": 0,/ {count += 1};
- /"minor": 22,/ {count += 1};
- END {{if (count == 2) {print "yes"};}}' \
- "${EC_BIN_ROOT}/ec_RW-manifest-prod.json")"
-
-if [ "${ignore_rma_keys}" != "yes" ]; then
- rma_key_base="$(determine_rma_key_base ${elves[@]})"
-else
- echo "Ignofing RMA keys for factory branch"
-fi
-
-signer_command_params=()
-signer_command_params+=(--b -x ${EC_BIN_ROOT}/fuses.xml)
-if [[ -z "${do_prod}" ]]; then
- signer_command_params+=(-k ${EC_BIN_ROOT}/cr50_rom0-dev-blsign.pem.pub)
-else
- cp "${EC_BIN_ROOT}/ec_RW-manifest-prod.json" "${tmpf}"
- signer_command_params+=(-k ${EC_BIN_ROOT}/cr50_RW-prod.pem.pub)
- # Swap test public RMA server key with the prod version.
- if [ "${ignore_rma_keys}" != "yes" ]; then
- signer_command_params+=(-S "${rma_key_base}.test","${rma_key_base}.prod")
- fi
-fi
-signer_command_params+=(-j ${tmpf})
-
-if [[ -n "${do_hex}" ]]; then
- dst_suffix='signed.hex'
-else
- signer_command_params+=(--format=bin)
- dst_suffix='flat'
-fi
-
-tweak_manifest
-
-count=0
-for elf in ${elves[@]}; do
- if [[ -n "${do_prod}" ]]; then
- if strings "${elf}" | egrep -q "(DBG|SQA)/cr50"; then
- echo "Will not sign debug or SQA image with prod keys" >&2
- exit 1
- fi
- fi
- signed_file="${count}.${dst_suffix}"
-
- # Make sure output file is not owned by root
- touch "${signed_file}"
- command="${SIGNER} ${signer_command_params[@]} -i ${elf} -o ${signed_file}"
- if ! ${command}; then
- echo "${progname}: \"${command}\" failed" >&2
- exit 1
- fi
-
- if [ "${ignore_rma_keys}" != "yes" ]; then
- if find_blob_in_blob "${signed_file}" "${rma_key_base}.test"; then
- echo "${progname}: test RMA key in the signed image!" >&2
- rm *."${dst_suffix}"
- exit 1
- fi
-
- if ! find_blob_in_blob "${signed_file}" "${rma_key_base}.prod"; then
- echo "${progname}: prod RMA key not in the signed image!" >&2
- rm *."${dst_suffix}"
- exit 1
- fi
- fi
- : $(( count++ ))
-done
-
-if [[ -z "${do_hex}" ]]; then
- # Full binary image is required, paste the newly signed blobs into the
- # output image, preserving it in case dd fails for whatever reason.
- cp "${RESULT_FILE}" "${TMP_RESULT_FILE}"
- dd if="0.flat" of="${TMP_RESULT_FILE}" seek=16384 bs=1 conv=notrunc
- dd if="1.flat" of="${TMP_RESULT_FILE}" seek=278528 bs=1 conv=notrunc
- rm [01].flat
- mv "${TMP_RESULT_FILE}" "${RESULT_FILE}"
-fi
-
-echo "SUCCESS!!!"
diff --git a/util/signer/cr50_RW-prod.pem.pub b/util/signer/cr50_RW-prod.pem.pub
deleted file mode 100644
index f043eea161..0000000000
--- a/util/signer/cr50_RW-prod.pem.pub
+++ /dev/null
@@ -1,9 +0,0 @@
------BEGIN PUBLIC KEY-----
-MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAthqml36PUHk5MgurodTG
-puEsqK9/28/gEiCZGgfKL2rZKzU7CSiD82nmMgMoaxNTcPZgln+WELXIZUv81Up3
-GT6dA2dSDSQgmdgI1/x3OkEf9BkmHajuvhZTDteI18X/9TsXwly9zoxEFRy/JW8X
-Cz9/eOE7xcgoIzji0WmnosMKyxiOv67hhH+JvJ01uQhcxOag2606uIBknovHZT7l
-kf3RsEquoZqGK2WFwin9gl4KXv8yQ2F0h9LnfezIURWuz4J6pNc8EI7jYeP5eBrJ
-AfE8HsnDD6I2OpoNNM0BnbPq7gbn5CJJn5bZ6dNM4YBH8saJgNVBYOV9XqHdtiLV
-uwIBAw==
------END PUBLIC KEY-----
diff --git a/util/signer/cr50_rom0-dev-blsign.pem.pub b/util/signer/cr50_rom0-dev-blsign.pem.pub
deleted file mode 100644
index 4e4e765ca5..0000000000
--- a/util/signer/cr50_rom0-dev-blsign.pem.pub
+++ /dev/null
@@ -1,9 +0,0 @@
------BEGIN PUBLIC KEY-----
-MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEA3BvAb0OUrzmPfwQPOz7D
-c5JOiiv6p9Es42XR4kLajBPIJog4ZMIFHrTk8R3IvQkt5TQb7SbvAv/rDESVLplM
-OJX9/5i5MK4Wh6j/msopEwRfdCgHD5dXOSN3mqC8bqyWhspF0L9fUlZXAsPD0zUe
-sXNL0dTSuvE4GZ53WoE8bM9d1w5A6L9NzODAgI1hOFqg9qnpir9R/CWiH0/JwlbP
-k5amvRfVFPeyivq4zRW4LGa6I3woVjp36iRUYEktbvabq6/qmAGDiL4hy4AHhLGn
-2g7s1sY6V9W9cYQQ7sja8x+xqH4Mwt1QxlLoGrVfhf0sh0hUETnUPSXwZFRQqU+0
-4QIBAw==
------END PUBLIC KEY-----
diff --git a/util/signer/create_released_image.sh b/util/signer/create_released_image.sh
deleted file mode 100755
index f5d4673887..0000000000
--- a/util/signer/create_released_image.sh
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/bin/bash
-
-#
-# 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.
-#
-# This script is a utility which allows to sign prod CR50 images for release
-# and place them in a tarball suitable for uploading to the BCS.
-#
-# The util/signer/ec_RW-manifest-prod.json manifest present in the EC
-# directory is used for signing.
-#
-
-set -u
-
-# A very crude RO verification function. The key signature found at a fixed
-# offset into the RO blob must match the RO type. Prod keys have bit D2 set to
-# one, dev keys have this bit set to zero.
-verify_ro() {
- local ro_bin="${1}"
- local type_expected="${2}"
- local key_byte
-
- if [ ! -f "${ro_bin}" ]; then
- echo "${ro_bin} not a file!" >&2
- exit 1
- fi
-
- # Key signature's lowest byte is byte #5 in the line at offset 0001a0.
- key_byte="$(od -Ax -t x1 -v "${ro_bin}" | awk '/0001a0/ {print $6};')"
- case "${key_byte}" in
- (?[4567cdef])
- if [ "${type_expected}" == "prod" ]; then
- return 0
- fi
- ;;
- (?[012389ab])
- if [ "${type_expected}" == "dev" ]; then
- return 0
- fi
- ;;
- esac
-
- echo "RO key in ${ro_bin} does not match type ${type_expected}" >&2
- exit 1
-}
-
-# This function prepares a full CR50 image, consisting of two ROs and two RWs
-# placed at their respective offsets into the resulting blob. It invokes the
-# bs (binary signer) script to actually convert elf versions of RWs into
-# binaries and sign them.
-#
-# The signed image is placed in the directory named as concatenation of RO and
-# RW version numbers and board ID fields, if set to non-default. The ebuild
-# downloading the tarball from the BCS expects the image to be in that
-# directory.
-prepare_image() {
- local awk_prog
- local count=0
- local extra_param=
- local image_type="${1}"
- local raw_version
- local ro_a_hex="$(readlink -f "${2}")"
- local ro_b_hex="$(readlink -f "${3}")"
- local rw_a="$(readlink -f "${4}")"
- local rw_b="$(readlink -f "${5}")"
- local version
-
- for f in "${ro_a_hex}" "${ro_b_hex}"; do
- if ! objcopy -I ihex "${f}" -O binary "${TMPD}/${count}.bin"; then
- echo "failed to convert ${f} from hex to bin" >&2
- exit 1
- fi
- verify_ro "${TMPD}/${count}.bin" "${image_type}"
- : $(( count += 1 ))
- done
-
- if [ "${image_type}" == "prod" ]; then
- extra_param+=' prod'
- fi
-
- if ! "${EC_ROOT}/util/signer/bs" ${extra_param} elves \
- "${rw_a}" "${rw_b}" > /dev/null;
- then
- echo "Failed invoking ${EC_ROOT}/util/signer/bs ${extra_param} " \
- "elves ${rw_a} ${rw_b}" >&2
- exit 1
- fi
-
- dd if="${TMPD}/0.bin" of="${RESULT_FILE}" conv=notrunc
- dd if="${TMPD}/1.bin" of="${RESULT_FILE}" seek=262144 bs=1 conv=notrunc
-
- # A typical Cr50 version reported by gsctool looks as follows:
- # RO_A:0.0.10 RW_A:0.0.22[ABCD:00000013:00000012] ...(the same for R[OW]_B).
- #
- # In case Board ID field is not set in the image, it is reported as
- # [00000000:00000000:00000000]
- #
- # We want the generated tarball file name to include all relevant version
- # fields. Let's retrieve the version string and process it using awk to
- # generate the proper file name. Only the RO_A and RW_A version numbers are
- # used, this script trusts the user to submit for processing a proper image
- # where both ROs and both RWs are of the same version respectively.
- #
- # As a result, blob versions are converted as follows:
- # RO_A:0.0.10 RW_A:0.0.22[ABCD:00000013:00000012] into
- # r0.0.10.w0.0.22_ABCD_00000013_00000012
- #
- # RO_A:0.0.10 RW_A:0.0.22[00000000:00000000:00000000] into
- # r0.0.10.w0.0.22
- #
- # The below awk program accomplishes this preprocessing.
- awk_prog='/^RO_A:/ {
- # drop the RO_A/RW_A strings
- gsub(/R[OW]_A:/, "")
- # Drop default mask value completely.
- gsub(/\[00000000:00000000:00000000\]/, "")
- # If there is a non-default mask:
- # - replace opening brackets and colons with underscores.
- gsub(/[\[\:]/, "_")
- # - drop the trailing bracket.
- gsub(/\]/, "")
- # Print filtered out RO_A and RW_A values
- print "r" $1 ".w" $2
-}'
-
- raw_version="$("${GSCTOOL}" -b "${RESULT_FILE}")" ||
- ( echo "${ME}: Failed to retrieve blob version" >&2 && exit 1 )
-
- version="$(awk "${awk_prog}" <<< "${raw_version}" )"
- if [ -z "${dest_dir}" ]; then
- # Note that this is a global variable
- dest_dir="cr50.${version}"
- if [ ! -d "${dest_dir}" ]; then
- mkdir "${dest_dir}"
- else
- echo "${dest_dir} already exists, will overwrite" >&2
- fi
- elif [ "${dest_dir}" != "cr50.${version}" ]; then
- echo "dev and prod versions mismatch!" >&2
- exit 1
- fi
-
- cp "${RESULT_FILE}" "${dest_dir}/cr50.bin.${image_type}"
- echo "saved ${image_type} binary in ${dest_dir}/cr50.bin.${image_type}"
-}
-
-# Execution starts here ===========================
-ME="$(basename $0)"
-
-if [ -z "${CROS_WORKON_SRCROOT}" ]; then
- echo "${ME}: This script must run inside Chrome OS chroot" >&2
- exit 1
-fi
-
-SCRIPT_ROOT="${CROS_WORKON_SRCROOT}/src/scripts"
-. "${SCRIPT_ROOT}/build_library/build_common.sh" || exit 1
-
-TMPD="$(mktemp -d /tmp/${ME}.XXXXX)"
-trap "/bin/rm -rf ${TMPD}" SIGINT SIGTERM EXIT
-
-EC_ROOT="${CROS_WORKON_SRCROOT}/src/platform/ec"
-RESULT_FILE="${TMPD}/release.bin"
-dest_dir=
-IMAGE_SIZE='524288'
-export RESULT_FILE
-
-GSCTOOL="/usr/sbin/gsctool"
-if [[ ! -x "${GSCTOOL}" ]]; then
- emerge_command="USE=cr50_onboard sudo -E emerge ec-utils"
- echo "${ME}: gsctool not found, run \"${emerge_command}\"" >&2
- exit 1
-fi
-
-DEFINE_string cr50_board_id "" \
- "Optional string representing Board ID field of the Cr50 RW header.
-Consists of three fields separated by colon: <RLZ>:<hex mask>:<hex flags>"
-
-# Do not put this before the DEFINE_ invocations - they routinely experience
-# error return values.
-set -e
-
-FLAGS_HELP="usage: ${ME} [flags] <blobs>
-
-blobs are:
- <prod RO A>.hex <prod RO B>.hex <RW.elf> <RW_B.elf>
- or
- <prod RO A>.hex <prod RO B>.hex <dir>
- where <dir> contains files named ec.RW.elf and ec.RW_B.elf
-"
-
-# Parse command line.
-FLAGS "$@" || exit 1
-
-eval set -- "${FLAGS_ARGV}"
-
-if [[ $# == 3 && -d "${3}" ]]; then
- rw_a="${3}/ec.RW.elf"
- rw_b="${3}/ec.RW_B.elf"
-elif [[ $# == 4 ]]; then
- rw_a="${3}"
- rw_b="${4}"
-else
- flags_help
- exit 1
-fi
-
-prod_ro_a="${1}"
-prod_ro_b="${2}"
-
-dd if=/dev/zero bs="${IMAGE_SIZE}" count=1 2>/dev/null |
- tr \\000 \\377 > "${RESULT_FILE}"
-if [ "$(stat -c '%s' "${RESULT_FILE}")" != "${IMAGE_SIZE}" ]; then
- echo "Failed creating ${RESULT_FILE}" >&2
- exit 1
-fi
-
-# Used by the bs script.
-export CR50_BOARD_ID="${FLAGS_cr50_board_id}"
-
-prepare_image 'prod' "${prod_ro_a}" "${prod_ro_b}" "${rw_a}" "${rw_b}"
-tarball="${dest_dir}.tbz2"
-tar jcf "${tarball}" "${dest_dir}"
-rm -rf "${dest_dir}"
-
-bcs_path="gs://chromeos-localmirror-private/distfiles/cr50"
-echo "SUCCESS!!!!!!"
-echo "use the below commands to copy the new image to the GFS"
-echo "gsutil cp ${tarball} ${bcs_path}"
-echo "gsutil acl ch -g cr50-firmware@google.com:R ${bcs_path}/${tarball}"
-
diff --git a/util/signer/ec_RW-manifest-dev.json b/util/signer/ec_RW-manifest-dev.json
deleted file mode 100644
index 1f65d68e91..0000000000
--- a/util/signer/ec_RW-manifest-dev.json
+++ /dev/null
@@ -1,48 +0,0 @@
-{
-// List of fuses and their expected values.
-"fuses": {
- "FLASH_PERSO_PAGE_LOCK": 5, // individualized
- "FW_DEFINED_DATA_BLK0": 2, // kevin EVT 1
- "FW_DEFINED_DATA_EXTRA_BLK6": 0 // escape hatch
-},
-// Rollback state.
-"info": {
- "2": -1, "3": -1, "4": -1, "5": -1, "6": -1,
- "7": -1, "8": -1, "9": -1, "10": -1, "11": -1, "12": -1 , "13": -1,
- "14": -1, "15": -1, "16": -1, "17": -1, "18": -1, "19": -1, "20": -1,
- "21": -1, "22": -1, "23": -1, "24": -1, "25": -1, "26": -1, "27": -1,
- "28": -1, "29": -1, "30": -1, "31": -1, "32": -1, "33": -1, "34": -1,
- "35": -1, "36": -1, "37": -1, "38": -1, "39": -1, "40": -1, "41": -1,
- "42": -1, "43": -1, "44": -1, "45": -1, "46": -1, "47": -1, "48": -1,
- "49": -1, "50": -1, "51": -1, "52": -1, "53": -1, "54": -1, "55": -1,
- "56": -1, "57": -1, "58": -1, "59": -1, "60": -1, "61": -1, "62": -1,
- "63": -1, "64": -1, "65": -1, "66": -1, "67": -1, "68": -1, "69": -1,
- "70": -1, "71": -1, "72": -1, "73": -1, "74": -1, "75": -1, "76": -1,
- "77": -1, "78": -1, "79": -1, "80": -1, "81": -1, "82": -1, "83": -1,
- "84": -1, "85": -1, "86": -1, "87": -1, "88": -1, "89": -1, "90": -1,
- "91": -1, "92": -1, "93": -1, "94": -1, "95": -1, "96": -1, "97": -1,
- "98": -1, "99": -1, "100": -1, "101": -1, "102": -1, "103": -1, "104": -1,
-"105": -1, "106": -1, "107": -1, "108": -1, "109": -1, "110": -1, "111": -1,
-"112": -1, "113": -1, "114": -1, "115": -1, "116": -1, "117": -1, "118": -1,
-"119": -1, "120": -1, "121": -1, "122": -1, "123": -1, "124": -1, "125": -1,
-"126": -1, "127": -1
-},
-
- // Note: tag needs to match what cros_personalize anticipated!
- // https://cs.corp.google.com/search/?q=kCrosFwr
- "tag": "00000000000000000000000000000000000000000000000000000000",
-
- // cros_loader uses b1-dev key as key to verify RW with
- "keyid": 860844255, // b1-dev, RO 0.0.11 key
-
- "p4cl": 177, // P4 sync cl for XML we link against. 177 == 0xb1.
-
- "timestamp": 0,
- "epoch": 0, // FWR diversification contributor, 32 bits.
- "major": 4, // FW2_HIK_CHAIN counter.
- "minor": 24, // Mostly harmless version field.
- "applysec": -1, // Mask to and with fuse BROM_APPLYSEC.
- "config1": 13, // Which BROM_CONFIG1 actions to take before launching.
- "err_response": 0, // Mask to or with fuse BROM_ERR_RESPONSE.
- "expect_response": 3 // purgatory level when expectation fails.
-}
diff --git a/util/signer/ec_RW-manifest-prod.json b/util/signer/ec_RW-manifest-prod.json
deleted file mode 100644
index 4d725af315..0000000000
--- a/util/signer/ec_RW-manifest-prod.json
+++ /dev/null
@@ -1,52 +0,0 @@
-{
-// List of fuses and their expected values.
-"fuses": {
- "FLASH_PERSO_PAGE_LOCK": 5, // individualized
- "FW_DEFINED_DATA_BLK0": 2, // cros SKU
- "FW_DEFINED_DATA_EXTRA_BLK6": 0 // escape hatch
-},
-// Rollback state.
-"info": {
- "2": -1, "3": -1, "4": -1, "5": -1, "6": -1,
- "7": -1, "8": -1, "9": -1, "10": -1, "11": -1, "12": -1 , "13": -1,
- "14": -1, "15": -1, "16": -1, "17": -1, "18": -1, "19": -1, "20": -1,
- "21": -1, "22": -1, "23": -1, "24": -1, "25": -1, "26": -1, "27": -1,
- "28": -1, "29": -1, "30": -1, "31": -1, "32": -1, "33": -1, "34": -1,
- "35": -1, "36": -1, "37": -1, "38": -1, "39": -1, "40": -1, "41": -1,
- "42": -1, "43": -1, "44": -1, "45": -1, "46": -1, "47": -1, "48": -1,
- "49": -1, "50": -1, "51": -1, "52": -1, "53": -1, "54": -1, "55": -1,
- "56": -1, "57": -1, "58": -1, "59": -1, "60": -1, "61": -1, "62": -1,
- "63": -1, "64": -1, "65": -1, "66": -1, "67": -1, "68": -1, "69": -1,
- "70": -1, "71": -1, "72": -1, "73": -1, "74": -1, "75": -1, "76": -1,
- "77": -1, "78": -1, "79": -1, "80": -1, "81": -1, "82": -1, "83": -1,
- "84": -1, "85": -1, "86": -1, "87": -1, "88": -1, "89": -1, "90": -1,
- "91": -1, "92": -1, "93": -1, "94": -1, "95": -1, "96": -1, "97": -1,
- "98": -1, "99": -1, "100": -1, "101": -1, "102": -1, "103": -1, "104": -1,
-"105": -1, "106": -1, "107": -1, "108": -1, "109": -1, "110": -1, "111": -1,
-"112": -1, "113": -1, "114": -1, "115": -1, "116": -1, "117": -1, "118": -1,
-"119": -1, "120": -1, "121": -1, "122": -1, "123": -1, "124": -1, "125": -1,
-"126": -1, "127": -1
-},
-
- // Note: tag needs to match what cros_personalize anticipated!
- // https://cs.corp.google.com/search/?q=kCrosFwr
- "tag": "00000000000000000000000000000000000000000000000000000000",
-
- // cros_loader uses b1-dev key as key to verify RW with
- //"keyid": -1187158727, // b1-dev key
- "keyid": -561489779, // prod RW key
-
- "p4cl": 177, // P4 sync cl for XML we link against. 177 == 0xb1.
-
- // Make sure a value is there so that current time is not used, and make
- // sure the value is small so that any dev build with the same
- // epoch/major/minor would be preferred
- "timestamp": 1,
- "epoch": 0, // FWR diversification contributor, 32 bits.
- "major": 3, // FW2_HIK_CHAIN counter.
- "minor": 24, // Mostly harmless version field.
- "applysec": -1, // Mask to and with fuse BROM_APPLYSEC.
- "config1": 13, // Which BROM_CONFIG1 actions to take before launching.
- "err_response": 0, // Mask to or with fuse BROM_ERR_RESPONSE.
- "expect_response": 3 // purgatory level when expectation fails.
-}
diff --git a/util/signer/fuses.xml b/util/signer/fuses.xml
deleted file mode 100644
index 627c8796b8..0000000000
--- a/util/signer/fuses.xml
+++ /dev/null
@@ -1,2034 +0,0 @@
-<ArrayType>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK0_INTG_CHKSUM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>0</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>24</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK0_INTG_LOCK</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>1</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>DS_GRP0</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>2</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>9</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>DS_GRP1</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>3</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>9</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>DS_GRP2</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>4</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>9</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>DEV_ID0</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>5</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>32</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>DEV_ID1</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>6</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>32</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK1_INTG_CHKSUM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>7</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>24</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK1_INTG_LOCK</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>8</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB0_POST_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>9</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB0_POST_PATCNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>10</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB0_POST_WARMUP_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>11</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB0_POST_WARMUP_CNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>12</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB1_POST_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>13</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB1_POST_PATCNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>14</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB1_POST_WARMUP_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>15</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB1_POST_WARMUP_CNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>16</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB2_POST_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>17</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB2_POST_PATCNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>18</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB2_POST_WARMUP_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>19</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB2_POST_WARMUP_CNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>20</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB3_POST_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>21</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB3_POST_PATCNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>22</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB3_POST_WARMUP_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>23</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB3_POST_WARMUP_CNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>24</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB4_POST_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>25</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB4_POST_PATCNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>26</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB4_POST_WARMUP_OVRD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>27</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LB4_POST_WARMUP_CNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>28</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>MBIST_POST_SEQ</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>29</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>25</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LBIST_POST_SEQ</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>30</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>25</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>LBIST_VIA_TAP_DIS</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>31</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>MBIST_VIA_TAP_DIS</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>32</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>TAP_DISABLE</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>33</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RNGBIST_AR_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>34</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>TESTMODE_KEYS_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>35</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>PKG_ID</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>36</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BIN_ID</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>37</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_JTR_OSC48_CC_TRIM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>38</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_JTR_OSC48_CC_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>39</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_JTR_OSC60_CC_TRIM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>40</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_JTR_OSC60_CC_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>41</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_TIMER_OSC48_CC_TRIM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>42</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_TIMER_OSC48_CC_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>43</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_TIMER_OSC48_FC_TRIM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>44</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>5</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_TIMER_OSC48_FC_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>45</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_RTC_OSC256K_CC_TRIM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>46</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RC_RTC_OSC256K_CC_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>47</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>SEL_VREG_REG_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>48</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>SEL_VREF_REG</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>49</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>4</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>SEL_VREF_BATMON_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>50</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>SEL_VREF_BATMON</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>51</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>X_OSC_LDO_CTRL_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>52</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>X_OSC_LDO_CTRL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>53</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>4</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>TEMP_OFFSET_CAL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>54</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>12</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>TRNG_LDO_CTRL_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>55</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>TRNG_LDO_CTRL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>56</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>5</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>TRNG_ANALOG_CTRL_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>57</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>TRNG_ANALOG_CTRL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>58</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>4</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>EXT_XTAL_PDB</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>59</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>DIS_EXT_XTAL_CLK_TREE</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>60</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>OBFUSCATION_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>61</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>HIK_CREATE_LOCK</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>62</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK2_INTG_CHKSUM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>63</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>24</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK2_INTG_LOCK</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>64</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>TESTMODE_OTPW_DIS</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>65</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>HKEY_WDOG_TIMER_EN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>66</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FLASH_PERSO_PAGE_LOCK</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>67</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>ALERT_RSP_CFG</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>68</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK3_INTG_CHKSUM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>69</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>24</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK3_INTG_LOCK</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>70</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_DATA_BLK0</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>71</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_BROM_ERR_RESPONSE</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>72</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>16</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_BROM_APPLYSEC</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>73</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>12</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_BROM_CONFIG0</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>74</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_BROM_CONFIG1</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>75</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_MODE_DBG_OVRD_DIS</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>76</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_MODE_OUTPUT_OVRD_DIS</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>77</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>7</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_CLK10HZ_COUNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>78</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>16</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_SHORT_DELAY_COUNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>79</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>16</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_LONG_DELAY_COUNT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>80</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_DEBOUNCE_PERIOD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>81</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>16</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_DEBOUNCE_BYPASS_PWRB</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>82</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_DEBOUNCE_BYPASS_KEY0</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>83</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_DEBOUNCE_BYPASS_KEY1</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>84</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_KEY_COMBO0_VAL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>85</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_KEY_COMBO1_VAL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>86</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_KEY_COMBO2_VAL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>87</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_KEY_COMBO0_HOLD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>88</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_KEY_COMBO1_HOLD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>89</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_KEY_COMBO2_HOLD</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>90</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_BLOCK_KEY0_SEL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>91</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_BLOCK_KEY1_SEL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>92</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_BLOCK_KEY0_VAL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>93</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_BLOCK_KEY1_VAL</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>94</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_POL_AC_PRESENT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>95</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_POL_PWRB_IN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>96</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_POL_PWRB_OUT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>97</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_POL_KEY0_IN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>98</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_POL_KEY0_OUT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>99</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_POL_KEY1_IN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>100</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_POL_KEY1_OUT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>101</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_POL_EC_RST</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>102</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_POL_BATT_DISABLE</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>103</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>1</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_TERM_AC_PRESENT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>104</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_TERM_ENTERING_RW</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>105</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_TERM_PWRB_IN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>106</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_TERM_PWRB_OUT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>107</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_TERM_KEY0_IN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>108</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_TERM_KEY0_OUT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>109</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_TERM_KEY1_IN</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>110</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_TERM_KEY1_OUT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>111</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_DRIVE_PWRB_OUT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>112</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_DRIVE_KEY0_OUT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>113</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_DRIVE_KEY1_OUT</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>114</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_DRIVE_EC_RST</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>115</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>RBOX_DRIVE_BATT_DISABLE</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>116</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>2</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK4_INTG_CHKSUM</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>117</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>24</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>BNK4_INTG_LOCK</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>118</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>3</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_DATA_EXTRA_BLK0</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>119</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_DATA_EXTRA_BLK1</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>120</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_DATA_EXTRA_BLK2</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>121</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_DATA_EXTRA_BLK3</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>122</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_DATA_EXTRA_BLK4</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>123</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_DATA_EXTRA_BLK5</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>124</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>8</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
- <HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>FW_DEFINED_DATA_EXTRA_BLK6</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>125</Value>
- </HashItem>
- <HashItem>
- <Key>Width</Key>
- <Value>5</Value>
- </HashItem>
- </HashType>
-</ArrayItem>
-<ArrayItem>
-<HashType>
- <HashItem>
- <Key>RegName</Key>
- <Value>SWDP_P4_LAST_SYNC</Value>
- </HashItem>
- <HashItem>
- <Key>Default</Key>
- <Value>177</Value>
- </HashItem>
- <HashItem>
- <Key>FuseLogicalOffset</Key>
- <Value>0</Value>
- </HashItem>
-</HashType>
-</ArrayItem>
-</ArrayType>
diff --git a/util/signer/loader-testkey-A.pem b/util/signer/loader-testkey-A.pem
deleted file mode 100644
index ea16e603e9..0000000000
--- a/util/signer/loader-testkey-A.pem
+++ /dev/null
@@ -1,27 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIEogIBAAKCAQEAp/kh8/NGr1GUMA6c0tq9cRhVMaMwhYCF6mkpeW/D+1k3lL5q
-pkjqDcYBZG4xbhdCgEH9ppPYKzwKBVieWuqf7uymLBlCLmaPA6P4J+IwhS001WoD
-0kACEhnbL4xeP21fwuz9/u6ucoM8kJsFV/gacADmuOKTrU89Kyj2J5iLWVQPMMAM
-BOk+3BNamWwnCRk+CvcT+EQHtzcFkK2avm4HUQNSzhL407NbvsHwUjv7N6wtjeu5
-VLaTLTHxk9Z5savcn2jgxWASn4M59dpD7KSTYi4LsY8NPUWswz0E2a0vk8rfthtA
-amTkU4MT9ohVYq2JTCj5DC3DV/0Z7xiZ+ZsYPQIBAwKCAQBv+2v394R04Q11XxM3
-PH5LZY4hF3WuVa6cRhumSoKnkM+4fvHEMJwJLquYSXZJZNcAK/5vDTrHfVwDkGmR
-8b/0ncQdZiwe7woCbVAalssDc3iORq021Va2u+d1CD7U85Usnf6p9HRMV321vK46
-pWb1Ve8l7GJziijHcKQaZbI7jEq4JKyk9lL7seEWjf2zHyiLnh8wxQK7Ebizrqw9
-EIH3tmC6JKvbGJPizQ6tz1O0bVwiaHmZObouRxBTE8fL2zuSmJunqsYK4xqWfRsb
-+RcSDndzBTW89qZr7i3h22g8jUsMiPBqV9/l9w1dOxnWwAtQSHfebcCA2u3OxUGM
-9dpTAoGBANhm0GYySwuCJc8lJpsBUl2tbuw7pzRdDe8BuqGv2aaEHx7arwFat1AA
-ZHVlQquWaKxwCuyFY/QlGq4uTNHhkBgygnFeEvtZ0KaKSVBBXY0Fbhq+N6rsX7FQ
-eRb4sz7We/aFR2K1V52dHaetOjMBfLhX1e7dZRwX8xnSSKuQeB6DAoGBAMa1uKLb
-LLbgYrnScI97GCOMGvjzdU9BjoGBbPay+53ZUqLcLPWwVy3qKeToQlISn3bqRBZp
-fAfCrKro6/weUusRAYXrzO41XeuJ1UsBUWPBqj3Gz5G1dAHQ3qkOMNRievieBnUV
-iXbdctg9dXufEL/75lZhJAZ+wZtmqAwVsjI/AoGBAJBEiu7MMgesGTTDbxIA4ZPI
-9J19GiLos/Sr0cEf5m8Cv2nnH1Y8ejVVmE5Dgce5mx2gB0hY7U1uEcl0MzaWYBAh
-rEuUDKeRNcRcMOArk7NY9BHUJRydlSDgULn7IinkUqRY2kHOOmkTaRpzfCIA/dA6
-jp8+Q2gP92aMMHJgUBRXAoGBAIR5JcHncySVlyaMSwpSEBeyvKX3o4ortFZWSKR3
-Umk7jGySyKPK5MlGxpia1uFhv6ScLWRGUq/XHcdF8qgUN0dgq66dM0l46UexONyr
-i5fWcX6EimEjoqvglHC0II2W/KW+rvi5Bk8+TJAo+P0UtdVSmY7rbVmp1meZxV1j
-zCF/AoGAcm2nAn275kfGZjXkTCYTZ6IXJgxcc4vXhv573UfNIJnC0Sg9rsgFiXHc
-nuQwFh5pTm4hU7uEknc/IobFLdCqM9mqujuYmboj0pmbRfOsjV9hqcmuo1OrSbJa
-gozzsNqU2I6srVW5SlCwWu1c4rBlBZvcdUtBRRb2b6bnhe29ykg=
------END RSA PRIVATE KEY-----
diff --git a/util/signer/rom-testkey-A.pem b/util/signer/rom-testkey-A.pem
deleted file mode 100644
index 77a69d8448..0000000000
--- a/util/signer/rom-testkey-A.pem
+++ /dev/null
@@ -1,39 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIG4AIBAAKCAYB7AIp3IzOv+FL4TNw2NwTD/Zx/ZOXmRYN14bICBHv9SufXlHT3
-klWR6GYZdGrY4/8VViz+Ax2JU6Rjgm7R4+Dh0Ny8TSlhIFloyVE2Dgb463hONrH+
-N09r7xPM34dMNJRQcd/2ptYD1Q+fnsg874EZtLXY2/b11jjj9mxyDru33MzNcQYm
-lTcAMayQs/nvBzsaUqJvMn89OtMg9BnKJwapcLvFywtNrCiC4iywqQSiqLt/FrbK
-nZd03Z/dT42fHt5h4MYfvT61S6XnkeOgFXD3lDHMbtD/Xg7eDT5Oh+wkSyXlpZHr
-HRLWkvZGSbHwywU91G/K8O05jnhv1q9Tawvxs5AKuqvOjNrhY8u8LgoJ88XhGvGQ
-yzhJuOeuEWomV/9F4CZqbFJ/+mFPRUfbjpRoauX0GCoO/BSSIgijlF2Ax1SoaZoi
-bY8E2TJUBXvxifMvHg/zdxiHeAR/8G5g43jfZz4HJ8PIHdmXRz5/IeK5IdEgSnxx
-5b3Rv/amI6vOe40CAQMCggGAUgBcT2zNH/rh+t3oJCSt1/5oVO3umYOs+UEhVq2n
-/jHv5Q2jT7bjtpruu6Lx5e1UuOQd/qy+W40YQlb0i+1Alos90t4blhWQ8IY2JAlZ
-+0eliXnL/s+KR/S33epaMs24NaE/+cSOrTi1FRSFffUAu83OkJKko+Ql7U7y9rR9
-JT3d3ktZbw4kqsvIYHf79K98vDcW9MxU03yMwKK73BoEcPXSg9yyM8gbAewdyxtY
-bHB8/2R53GkPoz5qk4peahSTRslgZHmnUc4zHp0lmy8LOvaGm++wb1m+5sw/8cte
-Kjdyh7KFYH1Sdzin5Fw5oabdIz+oercj34JJP1Gx1TV0oQA7yjCWDfVfnGgoN7AX
-3QNSW5HonmkaY5TYZ+la7kGocxewN1pLtun03OZDQlpF73dXWYZFWfky4Lc2Egkk
-rE2LjmFQQ5YlYOB+qaxaZCOM7i8BYJHwAMT1kKDXoqqdqqqLwcJcorXdYXME0IMS
-OIfFDhhYgUF1f5Ex/DgcG0RrAoHBAPl7mWuOjpCo6eNcFICvIoR64dNF0ud9lvUG
-RiUD5wTnR0cyGuWqvfDFYw1G4gUQsVsE/dOWPkevetb4RZAMie0tvbR2FIYL0ZgV
-vdbV7puSLWjZF3Ap2AnX9dH7HrxADPd1y84JvhQK3zTurz35AhGEQZM4GyAunxEh
-zfMew3fCKoMzsmky92q+IN4Za6HZPkOMzfJDlc/nRZIU5riCQsoKFWboO2Y9hQUg
-royXy7+CE18jE8QJ6qzt5JgdiPYOxQKBwH43HB14NSntb1ZKFrafvZqnhg9BdXDZ
-2Y7UmD7S9+AQstLnrvS2WTL4l2J4eXlACC3v9T9H+SKbj7nj3wOOUxMFeKb7tjOQ
-+d6x0ZHP96LcnO7m/TMDuKqBrUA4QwS1daHG0klbItmQks79M7oOKW+zoVqWpufX
-qS/taZVn4waQ2M+j71PZX4jKU3dpiLl7YYZKv/BYmrZpTpTqRDRhSZVdVv2b/W3P
-iH/6CLnFe6TUFiwC4+v5ouV4RxOx+K+GKQKBwQCmUmZHtF8LG0aXkrhVyhcC/JaM
-2TdE/mSjWYQYrUSt74TaIWdDxylLLkII2ewDYHY8rf6NDtQvylHkpYO1XbFIySki
-+WMEB+EQDn6POUm9DB5F5g+gG+Vb5U6L/L8oKrNPo900Bn64Bz94nx9+pgFhAtZi
-JWdqyb9gwTP3adelLBxXd8xGIfpHKWs+u50WkNQtCIlMLQ6Kmi5hY0R7AYHcBrjv
-RXzu064Dax8IZTJ/rAzqF2KCsUcd8+26vltOtIMCgcBUJL1o+s4b85+O3A8kan5n
-GllfgPj15pEJ4xAp4fqVYHc3RR9NzuYh+w+W+vumKrAen/jU2qYXEl/RQpStCYy3
-WPsZ/SQiYKaUdou2iqUXPb30mf4iAnscVnOAJYIDI6PBLzbbkhc7tbc0qM0mtBuf
-zRY8ZG9FOnDKnkZjmpdZteXfwp+NO5UF3Dek8QXQ/Ouu3H/1kGckRjRjRtgi64Zj
-k49TvVOeilr//AXRLlJt4rlyrJfypmyY+toNIVB1BBsCgcEA5IYJrpO5qGVWlfnX
-70deEyhKUhEXs91b6Vcf8KJNtxBao3H2B8uGtPrx0nCtxgI7XPYDiqIZ3cQDrjct
-4cLTah0hwaxnoKsB0aGbRWccpn6uDpqa5TVMBIVwUiyWVd+spAxxRDNIcSWn8lYM
-pK6Hc54XEJbaXJXTrAPGj8r4eCScRvJDqJnSzVDTztu1EoHvHrFVFkTMELFhIEmf
-duSuLGNMweNghh8yN5ipOSVp3qog2/hv3l79HIPhVHf3G17j
------END RSA PRIVATE KEY-----