futility: show .vbprivk files

BUG=none
BRANCH=none
TEST=make runtests

futility show tests/devkeys/*.vbprivk

Change-Id: Ic062a193c7ee3d7f9837698e1c8fc6bb1e3d7757
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/245503
Reviewed-by: Randall Spangler <rspangler@chromium.org>
diff --git a/futility/cmd_show.c b/futility/cmd_show.c
index ca566c8..dc7c814 100644
--- a/futility/cmd_show.c
+++ b/futility/cmd_show.c
@@ -89,7 +89,7 @@
 	printf("\n");
 }
 
-int futil_cb_show_key(struct futil_traverse_state_s *state)
+int futil_cb_show_pubkey(struct futil_traverse_state_s *state)
 {
 	VbPublicKey *pubkey = (VbPublicKey *)state->my_area->buf;
 
@@ -105,6 +105,24 @@
 	return 0;
 }
 
+int futil_cb_show_privkey(struct futil_traverse_state_s *state)
+{
+	VbPrivateKey key;
+	int alg_okay;
+
+	key.algorithm = *(typeof(key.algorithm) *)state->my_area->buf;
+
+	printf("Private Key file:      %s\n", state->in_filename);
+	alg_okay = key.algorithm < kNumAlgorithms;
+	printf("  Algorithm:           %" PRIu64 " %s\n", key.algorithm,
+	       alg_okay ? algo_strings[key.algorithm] : "(unknown)");
+
+	if (alg_okay)
+		state->my_area->_flags |= AREA_IS_VALID;
+
+	return 0;
+}
+
 int futil_cb_show_gbb(struct futil_traverse_state_s *state)
 {
 	uint8_t *buf = state->my_area->buf;
diff --git a/futility/file_type.c b/futility/file_type.c
index 0c91586..7d56ca2 100644
--- a/futility/file_type.c
+++ b/futility/file_type.c
@@ -31,6 +31,7 @@
 	"raw firmware",
 	"raw kernel",
 	"chromiumos disk image",
+	"VbPrivateKey",
 };
 BUILD_ASSERT(ARRAY_SIZE(type_strings) == NUM_FILE_TYPES);
 
@@ -48,6 +49,7 @@
 	&recognize_bios_image,
 	&recognize_gbb,
 	&recognize_vblock1,
+	&recognize_privkey,
 };
 
 /* Try to figure out what we're looking at */
diff --git a/futility/file_type.h b/futility/file_type.h
index f8aa97e..a94ff2c 100644
--- a/futility/file_type.h
+++ b/futility/file_type.h
@@ -22,6 +22,7 @@
 	FILE_TYPE_RAW_KERNEL,			/* vmlinuz, *.uimg, etc. */
 
 	FILE_TYPE_CHROMIUMOS_DISK,		/* At least it has a GPT */
+	FILE_TYPE_PRIVKEY,			/* VbPrivateKey */
 
 	NUM_FILE_TYPES
 };
@@ -46,5 +47,6 @@
 enum futil_file_type recognize_gbb(uint8_t *buf, uint32_t len);
 enum futil_file_type recognize_vblock1(uint8_t *buf, uint32_t len);
 enum futil_file_type recognize_gpt(uint8_t *buf, uint32_t len);
+enum futil_file_type recognize_privkey(uint8_t *buf, uint32_t len);
 
 #endif	/* VBOOT_REFERENCE_FUTILITY_FILE_TYPE_H_ */
diff --git a/futility/traversal.c b/futility/traversal.c
index a661d9a..3c3b422 100644
--- a/futility/traversal.c
+++ b/futility/traversal.c
@@ -23,13 +23,14 @@
 	futil_cb_show_fw_preamble,	/* CB_FMAP_VBLOCK_B */
 	futil_cb_show_fw_main,		/* CB_FMAP_FW_MAIN_A */
 	futil_cb_show_fw_main,		/* CB_FMAP_FW_MAIN_B */
-	futil_cb_show_key,		/* CB_PUBKEY */
+	futil_cb_show_pubkey,		/* CB_PUBKEY */
 	futil_cb_show_keyblock,		/* CB_KEYBLOCK */
 	futil_cb_show_gbb,		/* CB_GBB */
 	futil_cb_show_fw_preamble,	/* CB_FW_PREAMBLE */
 	futil_cb_show_kernel_preamble,	/* CB_KERN_PREAMBLE */
 	NULL,				/* CB_RAW_FIRMWARE */
 	NULL,				/* CB_RAW_KERNEL */
+	futil_cb_show_privkey,		/* CB_PRIVKEY */
 };
 BUILD_ASSERT(ARRAY_SIZE(cb_show_funcs) == NUM_CB_COMPONENTS);
 
@@ -49,6 +50,7 @@
 	futil_cb_resign_kernel_part,	/* CB_KERN_PREAMBLE */
 	futil_cb_sign_raw_firmware,	/* CB_RAW_FIRMWARE */
 	futil_cb_create_kernel_part,	/* CB_RAW_KERNEL */
+	NULL,				/* CB_PRIVKEY */
 };
 BUILD_ASSERT(ARRAY_SIZE(cb_sign_funcs) == NUM_CB_COMPONENTS);
 
@@ -77,6 +79,7 @@
 	{CB_RAW_FIRMWARE,  "raw firmware"},	/* FILE_TYPE_RAW_FIRMWARE */
 	{CB_RAW_KERNEL,    "raw kernel"},	/* FILE_TYPE_RAW_KERNEL */
 	{0,                "chromiumos disk"},	/* FILE_TYPE_CHROMIUMOS_DISK */
+	{CB_PRIVKEY,       "VbPrivateKey"},	/* FILE_TYPE_PRIVKEY */
 };
 BUILD_ASSERT(ARRAY_SIZE(direct_callback) == NUM_FILE_TYPES);
 
@@ -148,10 +151,10 @@
 	"CB_KERN_PREAMBLE",
 	"CB_RAW_FIRMWARE",
 	"CB_RAW_KERNEL",
+	"CB_PRIVKEY",
 };
 BUILD_ASSERT(ARRAY_SIZE(futil_cb_component_str) == NUM_CB_COMPONENTS);
 
-
 static int invoke_callback(struct futil_traverse_state_s *state,
 			   enum futil_cb_component c, const char *name,
 			   uint32_t offset, uint8_t *buf, uint32_t len)
diff --git a/futility/traversal.h b/futility/traversal.h
index 47dd71b..53088d5 100644
--- a/futility/traversal.h
+++ b/futility/traversal.h
@@ -35,6 +35,7 @@
 	CB_KERN_PREAMBLE,
 	CB_RAW_FIRMWARE,
 	CB_RAW_KERNEL,
+	CB_PRIVKEY,
 
 	NUM_CB_COMPONENTS
 };
@@ -75,12 +76,13 @@
 
 /* These are invoked by the traversal. They also return nonzero on error. */
 int futil_cb_show_begin(struct futil_traverse_state_s *state);
-int futil_cb_show_key(struct futil_traverse_state_s *state);
+int futil_cb_show_pubkey(struct futil_traverse_state_s *state);
 int futil_cb_show_gbb(struct futil_traverse_state_s *state);
 int futil_cb_show_keyblock(struct futil_traverse_state_s *state);
 int futil_cb_show_fw_main(struct futil_traverse_state_s *state);
 int futil_cb_show_fw_preamble(struct futil_traverse_state_s *state);
 int futil_cb_show_kernel_preamble(struct futil_traverse_state_s *state);
+int futil_cb_show_privkey(struct futil_traverse_state_s *state);
 
 int futil_cb_sign_pubkey(struct futil_traverse_state_s *state);
 int futil_cb_sign_fw_main(struct futil_traverse_state_s *state);
diff --git a/futility/vb1_helper.c b/futility/vb1_helper.c
index 292a0f2..f40b7ac 100644
--- a/futility/vb1_helper.c
+++ b/futility/vb1_helper.c
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <openssl/rsa.h>
 
 #include "file_type.h"
 #include "futility.h"
@@ -737,3 +738,24 @@
 
 	return FILE_TYPE_UNKNOWN;
 }
+
+enum futil_file_type recognize_privkey(uint8_t *buf, uint32_t len)
+{
+	VbPrivateKey key;
+	const unsigned char *start;
+
+	if (len < sizeof(key.algorithm))
+		return FILE_TYPE_UNKNOWN;
+
+	key.algorithm = *(typeof(key.algorithm) *)buf;
+	start = buf + sizeof(key.algorithm);
+	key.rsa_private_key = d2i_RSAPrivateKey(NULL, &start,
+						len - sizeof(key.algorithm));
+
+	if (key.rsa_private_key) {
+		RSA_free(key.rsa_private_key);
+		return FILE_TYPE_PRIVKEY;
+	}
+
+	return FILE_TYPE_UNKNOWN;
+}