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/app/aboot/aboot.c b/app/aboot/aboot.c
index 09ba226..b16e432 100644
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -187,7 +187,11 @@
 
 struct verified_boot_verity_mode vbvm[] =
 {
+#if ENABLE_VB_ATTEST
+	{false, "eio"},
+#else
 	{false, "logging"},
+#endif
 	{true, "enforcing"},
 };
 struct verified_boot_state_name vbsn[] =
@@ -199,7 +203,8 @@
 };
 #endif
 #endif
-
+/*As per spec delay wait time before shutdown in Red state*/
+#define DELAY_WAIT 30000
 static unsigned page_size = 0;
 static unsigned page_mask = 0;
 static unsigned mmc_blocksize = 0;
@@ -810,7 +815,11 @@
 #if !VBOOT_MOTA
 	if (device.verity_mode == 0) {
 #if FBCON_DISPLAY_MSG
+#if ENABLE_VB_ATTEST
+		display_bootverify_menu(DISPLAY_MENU_EIO);
+#else
 		display_bootverify_menu(DISPLAY_MENU_LOGGING);
+#endif
 		wait_for_users_action();
 #else
 		dprintf(CRITICAL,
@@ -959,7 +968,12 @@
 		case RED:
 #if FBCON_DISPLAY_MSG
 			display_bootverify_menu(DISPLAY_MENU_RED);
+#if ENABLE_VB_ATTEST
+			mdelay(DELAY_WAIT);
+			shutdown_device();
+#else
 			wait_for_users_action();
+#endif
 #else
 			dprintf(CRITICAL,
 					"Your device has failed verification and may not work properly.\nWait for 5 seconds before proceeding\n");
@@ -3935,7 +3949,11 @@
 		device.verity_mode = 1;
 		write_device_info(&device);
 	}
+#if ENABLE_VB_ATTEST
+	else if (reboot_mode == DM_VERITY_EIO)
+#else
 	else if (reboot_mode == DM_VERITY_LOGGING)
+#endif
 	{
 		device.verity_mode = 0;
 		write_device_info(&device);
diff --git a/app/aboot/bootimg.h b/app/aboot/bootimg.h
index 8320470..b119b1e 100644
--- a/app/aboot/bootimg.h
+++ b/app/aboot/bootimg.h
@@ -2,7 +2,7 @@
  * Copyright (C) 2008 The Android Open Source Project
  * All rights reserved.
  *
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014,2016 The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -54,9 +54,13 @@
 
     unsigned tags_addr;    /* physical addr for kernel tags */
     unsigned page_size;    /* flash page size we assume */
+#if OSVERSION_IN_BOOTIMAGE
+    uint32_t unused;    /* future expansion: should be 0 */
+    uint32_t os_version; /* version << 11 | patch_level */
+#else
     unsigned dt_size;      /* device_tree in bytes */
     unsigned unused;    /* future expansion: should be 0 */
-
+#endif
     unsigned char name[BOOT_NAME_SIZE]; /* asciiz product name */
     
     unsigned char cmdline[BOOT_ARGS_SIZE];
diff --git a/include/km_main.h b/include/km_main.h
index fa606ad..946683e 100644
--- a/include/km_main.h
+++ b/include/km_main.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -31,6 +31,7 @@
 #define KM_MAIN_H
 
 #include <sys/types.h>
+#include <boot_verifier.h>
 /**
  * Commands supported
  */
@@ -62,7 +63,9 @@
     KEYMASTER_UPDATE						= (KEYMASTER_CMD_ID + 17UL),
     KEYMASTER_FINISH						= (KEYMASTER_CMD_ID + 18UL),
     KEYMASTER_ABORT							= (KEYMASTER_CMD_ID + 19UL),
+    KEYMASTER_SET_BOOT_STATE                = (KEYMASTER_UTILS_CMD_ID + 8UL),
 
+    KEYMASTER_GET_VERSION                   = (KEYMASTER_UTILS_CMD_ID + 0UL),
     KEYMASTER_SET_ROT						= (KEYMASTER_UTILS_CMD_ID + 1UL),
     KEYMASTER_READ_LK_DEVICE_STATE			= (KEYMASTER_UTILS_CMD_ID + 2UL),
     KEYMASTER_WRITE_LK_DEVICE_STATE			= (KEYMASTER_UTILS_CMD_ID + 3UL),
@@ -205,4 +208,59 @@
 	uint32 swp_read_data_len;
 }__attribute__((packed)) secure_write_prot_rsp_t;
 
+/*
+ *  * Structures for get_version
+ *   */
+typedef struct _km_get_version_req_t
+{
+	uint32_t cmd_id;
+}__attribute__((packed)) km_get_version_req_t;
+
+typedef struct _km_get_version_rsp_t
+{
+	int status;
+	uint32_t major_version;
+	uint32_t minor_version;
+	uint32_t ta_major_version;
+	uint32_t ta_minor_version;
+}__attribute__((packed)) km_get_version_rsp_t;
+
+typedef struct _km_boot_state_t
+{
+	bool                   is_unlocked;
+	uint8_t                public_key[32];
+	uint32_t               color;
+	uint32_t               system_version;
+	uint32_t               system_security_level;
+}__attribute__((packed))  km_boot_state_t;
+
+/**
+ *  @brief
+ *  Data structure
+ *  @param[in]   cmd_id             Requested command
+ *  @param[in]   boot_state_ofset   Offset from the top of the struct.
+ *  @param[in]   boot_state_size    Size of the Boot state
+ *
+ *  The offset contains the following
+ *  km_boot_state_t
+ **/
+typedef struct _km_set_boot_state_req_t
+{
+	uint32_t        cmd_id;
+	uint32_t        version;
+	uint32_t        boot_state_offset;
+	uint32_t        boot_state_size;
+}__attribute__((packed)) km_set_boot_state_req_t;
+
+/**
+ *  @brief
+ *  Data structure
+ *
+ *  @param[out]   status      Status of the request
+ **/
+typedef struct _km_set_boot_state_rsp_t
+{
+	int status;
+}__attribute__((packed)) km_set_boot_state_rsp_t;
+
 #endif /* KM_MAIN_H */
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