summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/rwsig.c3
-rw-r--r--common/update_fw.c3
-rw-r--r--common/vboot/vb21_lib.c64
-rw-r--r--include/ec_commands.h42
-rw-r--r--include/vboot.h8
-rw-r--r--util/ectool.c177
6 files changed, 284 insertions, 13 deletions
diff --git a/common/rwsig.c b/common/rwsig.c
index 8bccd2acb1..0d0a8e765c 100644
--- a/common/rwsig.c
+++ b/common/rwsig.c
@@ -21,6 +21,7 @@
#include "usb_pd.h"
#include "util.h"
#include "vb21_struct.h"
+#include "vboot.h"
#include "version.h"
/* Console output macros */
@@ -142,7 +143,7 @@ int rwsig_check_signature(void)
sig = (const uint8_t *)CONFIG_RW_SIG_ADDR;
rwlen = CONFIG_RW_SIZE - CONFIG_RW_SIG_SIZE;
#elif defined(CONFIG_RWSIG_TYPE_RWSIG)
- vb21_key = (const struct vb21_packed_key *)CONFIG_RO_PUBKEY_ADDR;
+ vb21_key = vb21_get_packed_key();
vb21_sig = (const struct vb21_signature *)CONFIG_RW_SIG_ADDR;
if (vb21_key->c.magic != VB21_MAGIC_PACKED_KEY ||
diff --git a/common/update_fw.c b/common/update_fw.c
index 2501f29934..f9927fec9d 100644
--- a/common/update_fw.c
+++ b/common/update_fw.c
@@ -17,6 +17,7 @@
#include "update_fw.h"
#include "util.h"
#include "vb21_struct.h"
+#include "vboot.h"
#if defined(CONFIG_TOUCHPAD_VIRTUAL_OFF) && defined(CONFIG_TOUCHPAD_HASH_FW)
#define CONFIG_TOUCHPAD_FW_CHUNKS \
@@ -203,7 +204,7 @@ void fw_update_start(struct first_response_pdu *rpdu)
#endif
#ifdef CONFIG_RWSIG_TYPE_RWSIG
- vb21_key = (const struct vb21_packed_key *)CONFIG_RO_PUBKEY_ADDR;
+ vb21_key = vb21_get_packed_key();
rpdu->common.key_version = htobe32(vb21_key->key_version);
#endif
diff --git a/common/vboot/vb21_lib.c b/common/vboot/vb21_lib.c
index c85ecbbd75..a2b6993c13 100644
--- a/common/vboot/vb21_lib.c
+++ b/common/vboot/vb21_lib.c
@@ -8,8 +8,10 @@
*/
#include "common.h"
+#include "host_command.h"
#include "rsa.h"
#include "rwsig.h"
+#include "system.h"
#include "vb21_struct.h"
#include "vboot.h"
@@ -42,3 +44,65 @@ int vb21_is_signature_valid(const struct vb21_signature *sig,
return EC_ERROR_VBOOT_DATA_SIZE;
return EC_SUCCESS;
}
+
+const struct vb21_packed_key *vb21_get_packed_key(void)
+{
+ return (const struct vb21_packed_key *)(CONFIG_RO_PUBKEY_ADDR);
+}
+
+static void read_rwsig_info(struct ec_response_rwsig_info *r)
+{
+
+ const struct vb21_packed_key *vb21_key;
+ int rv;
+
+ vb21_key = vb21_get_packed_key();
+
+ r->sig_alg = vb21_key->sig_alg;
+ r->hash_alg = vb21_key->hash_alg;
+ r->key_version = vb21_key->key_version;
+ { BUILD_ASSERT(sizeof(r->key_id) == sizeof(vb21_key->id),
+ "key ID sizes must match"); }
+ { BUILD_ASSERT(sizeof(vb21_key->id) == sizeof(vb21_key->id.raw),
+ "key ID sizes must match"); }
+ memcpy(r->key_id, vb21_key->id.raw, sizeof(r->key_id));
+
+ rv = vb21_is_packed_key_valid(vb21_key);
+ r->key_is_valid = (rv == EC_SUCCESS);
+}
+
+static int command_rwsig_info(int argc, char **argv)
+{
+ int i;
+ struct ec_response_rwsig_info r;
+
+ read_rwsig_info(&r);
+
+ ccprintf("sig_alg: %d\n", r.sig_alg);
+ ccprintf("key_version: %d\n", r.key_version);
+ ccprintf("hash_alg: %d\n", r.hash_alg);
+ ccprintf("key_is_valid: %d\n", r.key_is_valid);
+
+ ccprintf("key_id: ");
+ for (i = 0; i < sizeof(r.key_id); i++)
+ ccprintf("%x", r.key_id[i]);
+ ccprintf("\n");
+
+ return EC_SUCCESS;
+}
+DECLARE_CONSOLE_COMMAND(rwsiginfo, command_rwsig_info, NULL,
+ "Display rwsig info on console.");
+
+static enum ec_status
+host_command_rwsig_info(struct host_cmd_handler_args *args)
+{
+ struct ec_response_rwsig_info *r = args->response;
+
+ read_rwsig_info(r);
+ args->response_size = sizeof(*r);
+
+ return EC_RES_SUCCESS;
+}
+
+DECLARE_HOST_COMMAND(EC_CMD_RWSIG_INFO, host_command_rwsig_info,
+ EC_VER_MASK(EC_VER_RWSIG_INFO));
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 1f6e746510..2b7cb31f90 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -1783,6 +1783,48 @@ struct ec_response_rand_num {
BUILD_ASSERT(sizeof(struct ec_response_rand_num) == 0);
+/**
+ * Get information about the key used to sign the RW firmware.
+ * For more details on the fields, see "struct vb21_packed_key".
+ */
+#define EC_CMD_RWSIG_INFO 0x001B
+#define EC_VER_RWSIG_INFO 0
+
+#define VBOOT2_KEY_ID_BYTES 20
+
+#ifdef CHROMIUM_EC
+/* Don't force external projects to depend on the vboot headers. */
+#include "vb21_struct.h"
+BUILD_ASSERT(sizeof(struct vb2_id) == VBOOT2_KEY_ID_BYTES);
+#endif
+
+struct ec_response_rwsig_info {
+ /**
+ * Signature algorithm used by the key
+ * (enum vb2_signature_algorithm).
+ */
+ uint16_t sig_alg;
+
+ /**
+ * Hash digest algorithm used with the key
+ * (enum vb2_hash_algorithm).
+ */
+ uint16_t hash_alg;
+
+ /** Key version. */
+ uint32_t key_version;
+
+ /** Key ID (struct vb2_id). */
+ uint8_t key_id[VBOOT2_KEY_ID_BYTES];
+
+ uint8_t key_is_valid;
+
+ /** Alignment padding. */
+ uint8_t reserved[3];
+} __ec_align4;
+
+BUILD_ASSERT(sizeof(struct ec_response_rwsig_info) == 32);
+
/*****************************************************************************/
/* PWM commands */
diff --git a/include/vboot.h b/include/vboot.h
index d757d0a3e7..776cc16441 100644
--- a/include/vboot.h
+++ b/include/vboot.h
@@ -25,6 +25,14 @@ int vb21_is_packed_key_valid(const struct vb21_packed_key *key);
int vb21_is_signature_valid(const struct vb21_signature *sig,
const struct vb21_packed_key *key);
+
+/**
+ * Returns the public key in RO that was used to sign RW.
+ *
+ * @return pointer to key, never NULL
+ */
+const struct vb21_packed_key *vb21_get_packed_key(void);
+
/**
* Check data region is filled with ones
*
diff --git a/util/ectool.c b/util/ectool.c
index c7cac69a7c..b73b8ce1e0 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -265,9 +265,14 @@ const char help_str[] =
" Set real-time clock alarm to go off in <sec> seconds\n"
" rwhashpd <dev_id> <HASH[0] ... <HASH[4]>\n"
" Set entry in PD MCU's device rw_hash table.\n"
- " rwsigaction\n"
+ " rwsig <info|dump|action|status> ...\n"
+ " info: get all info about rwsig\n"
+ " dump: show individual rwsig field\n"
+ " action: Control the behavior of RWSIG task.\n"
+ " status: Run RW signature verification and get status.\n{"
+ " rwsigaction (DEPRECATED; use \"rwsig action\")\n"
" Control the behavior of RWSIG task.\n"
- " rwsigstatus\n"
+ " rwsigstatus (DEPRECATED; use \"rwsig status\"\n"
" Run RW signature verification and get status.\n"
" sertest\n"
" Serial output test for COM2\n"
@@ -1452,18 +1457,13 @@ int cmd_rwsig_status(int argc, char *argv[])
return 0;
}
-int cmd_rwsig_action(int argc, char *argv[])
+static int rwsig_action(const char *command)
{
struct ec_params_rwsig_action req;
- if (argc < 2) {
- fprintf(stderr, "Usage: %s abort | continue\n", argv[0]);
- return -1;
- }
-
- if (!strcasecmp(argv[1], "abort"))
+ if (!strcasecmp(command, "abort"))
req.action = RWSIG_ACTION_ABORT;
- else if (!strcasecmp(argv[1], "continue"))
+ else if (!strcasecmp(command, "continue"))
req.action = RWSIG_ACTION_CONTINUE;
else
return -1;
@@ -1471,6 +1471,160 @@ int cmd_rwsig_action(int argc, char *argv[])
return ec_command(EC_CMD_RWSIG_ACTION, 0, &req, sizeof(req), NULL, 0);
}
+int cmd_rwsig_action_legacy(int argc, char *argv[])
+{
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s [abort | continue]\n", argv[0]);
+ return -1;
+ }
+
+ return rwsig_action(argv[1]);
+}
+
+int cmd_rwsig_action(int argc, char *argv[])
+{
+ if (argc < 2) {
+ fprintf(stderr, "Usage: ectool rwsig action [abort | "
+ "continue]\n");
+ return -1;
+ }
+
+ return rwsig_action(argv[1]);
+}
+
+enum rwsig_info_fields {
+ RWSIG_INFO_FIELD_SIG_ALG = BIT(0),
+ RWSIG_INFO_FIELD_KEY_VERSION = BIT(1),
+ RWSIG_INFO_FIELD_HASH_ALG = BIT(2),
+ RWSIG_INFO_FIELD_KEY_IS_VALID = BIT(3),
+ RWSIG_INFO_FIELD_KEY_ID = BIT(4),
+ RWSIG_INFO_FIELD_ALL = RWSIG_INFO_FIELD_SIG_ALG |
+ RWSIG_INFO_FIELD_KEY_VERSION | RWSIG_INFO_FIELD_HASH_ALG |
+ RWSIG_INFO_FIELD_KEY_IS_VALID | RWSIG_INFO_FIELD_KEY_ID
+};
+
+static int rwsig_info(enum rwsig_info_fields fields)
+{
+ int i;
+ int rv;
+ struct ec_response_rwsig_info r;
+ bool print_prefix = false;
+
+ rv = ec_command(EC_CMD_RWSIG_INFO, EC_VER_RWSIG_INFO, NULL, 0, &r,
+ sizeof(r));
+ if (rv < 0) {
+ fprintf(stderr, "rwsig info command failed\n");
+ return -1;
+ }
+
+ if ((fields & RWSIG_INFO_FIELD_ALL) == RWSIG_INFO_FIELD_ALL)
+ print_prefix = true;
+
+ if (fields & RWSIG_INFO_FIELD_SIG_ALG) {
+ if (print_prefix)
+ printf("sig_alg: ");
+
+ printf("%d\n", r.sig_alg);
+ }
+ if (fields & RWSIG_INFO_FIELD_KEY_VERSION) {
+ if (print_prefix)
+ printf("key_version: ");
+
+ printf("%d\n", r.key_version);
+ }
+ if (fields & RWSIG_INFO_FIELD_HASH_ALG) {
+ if (print_prefix)
+ printf("hash_alg: ");
+
+ printf("%d\n", r.hash_alg);
+ }
+ if (fields & RWSIG_INFO_FIELD_KEY_IS_VALID) {
+ if (print_prefix)
+ printf("key_is_valid: ");
+
+ printf("%d\n", r.key_is_valid);
+ }
+ if (fields & RWSIG_INFO_FIELD_KEY_ID) {
+ if (print_prefix)
+ printf("key_id: ");
+
+ for (i = 0; i < sizeof(r.key_id); i++)
+ printf("%x", r.key_id[i]);
+ printf("\n");
+ }
+
+ return 0;
+}
+
+static int cmd_rwsig_info(int argc, char *argv[])
+{
+ int i;
+
+ struct rwsig_dump_cmds {
+ const char *cmd;
+ enum rwsig_info_fields field;
+ };
+
+ struct rwsig_dump_cmds cmd_map[] = {
+ { "sig_alg", RWSIG_INFO_FIELD_SIG_ALG },
+ { "key_version", RWSIG_INFO_FIELD_KEY_VERSION },
+ { "hash_alg", RWSIG_INFO_FIELD_HASH_ALG },
+ { "key_valid", RWSIG_INFO_FIELD_KEY_IS_VALID },
+ { "key_id", RWSIG_INFO_FIELD_KEY_ID },
+ };
+
+ if (argc == 0)
+ return -1;
+
+ if (strcmp(argv[0], "info") == 0)
+ return rwsig_info(RWSIG_INFO_FIELD_ALL);
+
+ if (strcmp(argv[0], "dump") == 0) {
+ if (argc != 2) {
+ fprintf(stderr,
+ "Usage: rwsig dump "
+ "[sig_alg|key_version|hash_alg|key_valid|key_id]\n");
+ return -1;
+ }
+ for (i = 0; i < ARRAY_SIZE(cmd_map); i++)
+ if (strcmp(argv[1], cmd_map[i].cmd) == 0)
+ return rwsig_info(cmd_map[i].field);
+
+ return -1;
+ }
+
+ return -1;
+}
+
+int cmd_rwsig(int argc, char **argv)
+{
+ struct rwsig_subcommand {
+ const char *subcommand;
+ int (*handler)(int argc, char *argv[]);
+ };
+
+ const struct rwsig_subcommand rwsig_subcommands[] = {
+ { "info", cmd_rwsig_info },
+ { "dump", cmd_rwsig_info },
+ { "action", cmd_rwsig_action },
+ { "status", cmd_rwsig_status }
+ };
+
+ int i;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s <info|dump|action|status>\n",
+ argv[0]);
+ return -1;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rwsig_subcommands); i++)
+ if (strcmp(argv[1], rwsig_subcommands[i].subcommand) == 0)
+ return rwsig_subcommands[i].handler(--argc, &argv[1]);
+
+ return -1;
+}
+
int cmd_rollback_info(int argc, char *argv[])
{
struct ec_response_rollback_info r;
@@ -9150,7 +9304,8 @@ const struct command commands[] = {
{"rtcset", cmd_rtc_set},
{"rtcsetalarm", cmd_rtc_set_alarm},
{"rwhashpd", cmd_rw_hash_pd},
- {"rwsigaction", cmd_rwsig_action},
+ {"rwsig", cmd_rwsig},
+ {"rwsigaction", cmd_rwsig_action_legacy},
{"rwsigstatus", cmd_rwsig_status},
{"sertest", cmd_serial_test},
{"stress", cmd_stress_test},