boot_verifier: Implement updated verified boot spec

Update the verified boot flow to send device state, boot state, unlocked
flag, hash of public key, system version, system security level to trust zone,
add support to pass eio mode for dm-verity and update the display messages for
all the states.

Change-Id: Idc29c1c2686c431158caf69d9669352df9d6b4cd
diff --git a/platform/msm_shared/boot_verifier.c b/platform/msm_shared/boot_verifier.c
index d3ce07a..7d22eb9 100644
--- a/platform/msm_shared/boot_verifier.c
+++ b/platform/msm_shared/boot_verifier.c
@@ -44,6 +44,7 @@
 #include <qseecom_lk_api.h>
 #include <secapp_loader.h>
 #include <target.h>
+#include "bootimg.h"
 
 #define ASN1_ENCODED_SHA256_SIZE 0x33
 #define ASN1_ENCODED_SHA256_OFFSET 0x13
@@ -56,6 +57,9 @@
 RSA *rsa_from_cert = NULL;
 unsigned char fp[EVP_MAX_MD_SIZE];
 uint32_t fp_size;
+#if OSVERSION_IN_BOOTIMAGE
+km_boot_state_t boot_state_info;
+#endif
 
 ASN1_SEQUENCE(AUTH_ATTR) ={
 	ASN1_SIMPLE(AUTH_ATTR, target, ASN1_PRINTABLESTRING),
@@ -397,6 +401,53 @@
 	return dev_boot_state;
 }
 
+#if OSVERSION_IN_BOOTIMAGE
+static void boot_verify_send_boot_state(km_boot_state_t *boot_state)
+{
+	km_get_version_req_t version_req;
+	km_get_version_rsp_t version_rsp;
+	int ret;
+	int app_handle = get_secapp_handle();
+	km_set_boot_state_req_t *bs_req = NULL;
+	km_set_boot_state_rsp_t boot_state_rsp;
+	uint8_t *boot_state_ptr;
+
+	version_req.cmd_id = KEYMASTER_GET_VERSION;
+	ret = qseecom_send_command(app_handle, (void*) &version_req, sizeof(version_req), (void*) &version_rsp, sizeof(version_rsp));
+	if (ret < 0 || version_rsp.status < 0)
+	{
+		dprintf(CRITICAL, "QSEEcom command for getting keymaster version returned error: %d\n", version_rsp.status);
+		ASSERT(0);
+	}
+
+	if (version_rsp.major_version >= 0x2)
+	{
+		bs_req = malloc(sizeof(km_set_boot_state_req_t) + sizeof(km_boot_state_t));
+		ASSERT(bs_req);
+
+		boot_state_ptr = (uint8_t *) bs_req + sizeof(km_set_boot_state_req_t);
+		/* copy the boot state data */
+		memscpy(boot_state_ptr, sizeof(km_boot_state_t), &boot_state_info, sizeof(boot_state_info));
+
+		bs_req->cmd_id = KEYMASTER_SET_BOOT_STATE;
+		bs_req->version = 0x0;
+		bs_req->boot_state_offset = sizeof(km_set_boot_state_req_t);
+		bs_req->boot_state_size = sizeof(km_boot_state_t);
+
+		ret = qseecom_send_command(app_handle, (void *)bs_req, sizeof(*bs_req) + sizeof(km_boot_state_t), (void *) &boot_state_rsp, sizeof(boot_state_rsp));
+		if (ret < 0 || boot_state_rsp.status < 0)
+		{
+			dprintf(CRITICAL, "QSEEcom command for Sending boot state returned error: %d\n", boot_state_rsp.status);
+			free(bs_req);
+			ASSERT(0);
+		}
+	}
+
+	if (bs_req)
+		free(bs_req);
+}
+#endif
+
 bool send_rot_command(uint32_t is_unlocked)
 {
 	int ret = 0;
@@ -513,6 +564,13 @@
 		free(rot_input);
 		return false;
 	}
+
+#if OSVERSION_IN_BOOTIMAGE
+	boot_state_info.is_unlocked = is_unlocked;
+	boot_state_info.color = boot_verify_get_state();
+	memscpy(boot_state_info.public_key, sizeof(boot_state_info.public_key), digest, 32);
+	boot_verify_send_boot_state(&boot_state_info);
+#endif
 	dprintf(SPEW, "Sending Root of Trust to trustzone: end\n");
 	if(input)
 		free(input);
@@ -537,6 +595,9 @@
 	unsigned char* sig_addr = (unsigned char*)(img_addr + img_size);
 	uint32_t sig_len = 0;
 	unsigned char *signature = NULL;
+#if OSVERSION_IN_BOOTIMAGE
+	struct boot_img_hdr *img_hdr = NULL;
+#endif
 
 	if(dev_boot_state == ORANGE)
 	{
@@ -585,6 +646,13 @@
 
 	ret = verify_image_with_sig(img_addr, img_size, pname, sig, user_keystore);
 
+#if OSVERSION_IN_BOOTIMAGE
+	/* Extract the os version and patch level */
+	img_hdr = (struct boot_img_hdr *)img_addr;
+	boot_state_info.system_version = (img_hdr->os_version & 0xFFFFF8) >> 11;
+	boot_state_info.system_security_level = (img_hdr->os_version & 0x7FF);
+#endif
+
 	if(sig != NULL)
 		VERIFIED_BOOT_SIG_free(sig);
 verify_image_error:
diff --git a/platform/msm_shared/display_menu.c b/platform/msm_shared/display_menu.c
index cea4937..1d1be46 100644
--- a/platform/msm_shared/display_menu.c
+++ b/platform/msm_shared/display_menu.c
@@ -55,18 +55,21 @@
 				"Press the Volume Up/Down buttons to select Yes "\
 				"or No. Then press the Power button to continue.\n";
 
-#define YELLOW_WARNING_MSG	"Your device has loaded a different operating "\
-				"system\n\nTo learn more, visit:\n"
+#define YELLOW_WARNING_MSG	"Your device has loaded a different operating system\n\n "\
+				"Visit this link on another device:\n g.co/ABH"
 
-#define ORANGE_WARNING_MSG	"Your device has been unlocked and can't "\
-				"be trusted\n\nTo learn more, visit:\n"
+#define ORANGE_WARNING_MSG	"Your device software can't be\n checked for corruption. Please lock the bootloader\n\n"\
+				"Visit this link on another device:\n g.co/ABH"
 
-#define RED_WARNING_MSG	"Your device has failed verification and may "\
-				"not work properly\n\nTo learn more, visit:\n"
+#define RED_WARNING_MSG	"Your device is corrupt. It can't be\ntrusted and will not boot\n\n" \
+				"Visit this link on another device:\n g.co/ABH"
 
 #define LOGGING_WARNING_MSG	"The dm-verity is not started in enforcing mode and may "\
 				"not work properly\n\nTo learn more, visit:\n"
 
+#define EIO_WARNING_MSG		"Your device is corrupt. It can't be\n trusted and may not work properly.\n\n"\
+				"Visit this link on another device:\n g.co/ABH"
+
 static bool is_thread_start = false;
 static struct select_msg_info msg_info;
 
@@ -80,7 +83,8 @@
 			[DISPLAY_MENU_RED] = {FBCON_RED_MSG, RED_WARNING_MSG},
 			[DISPLAY_MENU_YELLOW] = {FBCON_YELLOW_MSG, YELLOW_WARNING_MSG},
 			[DISPLAY_MENU_ORANGE] = {FBCON_ORANGE_MSG, ORANGE_WARNING_MSG},
-			[DISPLAY_MENU_LOGGING] = {FBCON_RED_MSG, LOGGING_WARNING_MSG}};
+			[DISPLAY_MENU_LOGGING] = {FBCON_RED_MSG, LOGGING_WARNING_MSG},
+			[DISPLAY_MENU_EIO] = {FBCON_RED_MSG, EIO_WARNING_MSG}};
 #endif
 
 static char *verify_option_menu[] = {
diff --git a/platform/msm_shared/include/display_menu.h b/platform/msm_shared/include/display_menu.h
index b757916..5320be6 100644
--- a/platform/msm_shared/include/display_menu.h
+++ b/platform/msm_shared/include/display_menu.h
@@ -43,6 +43,7 @@
 	DISPLAY_MENU_FASTBOOT,
 	DISPLAY_MENU_UNLOCK_CRITICAL,
 	DISPLAY_MENU_LOGGING,
+	DISPLAY_MENU_EIO,
 };
 
 struct menu_info {
diff --git a/platform/msm_shared/menu_keys_detect.c b/platform/msm_shared/menu_keys_detect.c
index 7430329..efea07e 100644
--- a/platform/msm_shared/menu_keys_detect.c
+++ b/platform/msm_shared/menu_keys_detect.c
@@ -251,6 +251,7 @@
 		case DISPLAY_MENU_ORANGE:
 		case DISPLAY_MENU_RED:
 		case DISPLAY_MENU_LOGGING:
+		case DISPLAY_MENU_EIO:
 			reason = CONTINUE;
 			break;
 		case DISPLAY_MENU_MORE_OPTION:
@@ -320,6 +321,11 @@
 		boot_warning_volume_keys_func,
 		power_key_func,
 	},
+	[DISPLAY_MENU_EIO] = {
+		boot_warning_volume_keys_func,
+		boot_warning_volume_keys_func,
+		power_key_func,
+	},
 	[DISPLAY_MENU_MORE_OPTION] = {
 		menu_volume_up_func,
 		menu_volume_down_func,
diff --git a/platform/msm_shared/reboot.h b/platform/msm_shared/reboot.h
index 2794d72..7d439f6 100644
--- a/platform/msm_shared/reboot.h
+++ b/platform/msm_shared/reboot.h
@@ -36,7 +36,11 @@
 	RECOVERY_MODE		= 0x01,
 	FASTBOOT_MODE		= 0x02,
 	ALARM_BOOT		= 0x03,
+#if ENABLE_VB_ATTEST
+	DM_VERITY_EIO		= 0x04,
+#else
 	DM_VERITY_LOGGING	= 0x04,
+#endif
 	DM_VERITY_ENFORCING	= 0x05,
 	DM_VERITY_KEYSCLEAR	= 0x06,
 #else
@@ -44,7 +48,11 @@
 	RECOVERY_MODE		= 0x77665502,
 	FASTBOOT_MODE		= 0x77665500,
 	ALARM_BOOT		= 0x77665503,
+#if ENABLE_VB_ATTEST
+	DM_VERITY_EIO	        = 0x77665508,
+#else
 	DM_VERITY_LOGGING	= 0x77665508,
+#endif
 	DM_VERITY_ENFORCING	= 0x77665509,
 	DM_VERITY_KEYSCLEAR	= 0x7766550A,
 #endif