app: aboot: Verified boot changes for aboot

This change adds support to support verified boot

Change-Id: Ie77a16059b257743e201667df077fc5ef5a2f309
diff --git a/app/aboot/aboot.c b/app/aboot/aboot.c
index 389f6e4..fa80f28 100755
--- a/app/aboot/aboot.c
+++ b/app/aboot/aboot.c
@@ -68,6 +68,11 @@
 #include "board.h"
 #include "scm.h"
 
+#if VERIFIED_BOOT
+#include "boot_verifier.h"
+#include "secapp_loader.h"
+#endif
+
 extern  bool target_use_signed_kernel(void);
 extern void platform_uninit(void);
 extern void target_uninit(void);
@@ -101,6 +106,12 @@
 #define RECOVERY_MODE   0x77665502
 #define FASTBOOT_MODE   0x77665500
 
+#if VERIFIED_BOOT
+#define DM_VERITY_LOGGING    0x77665508
+#define DM_VERITY_ENFORCING  0x77665509
+#define DM_VERITY_KEYSCLEAR  0x7766550A
+#endif
+
 /* make 4096 as default size to ensure EFS,EXT4's erasing */
 #define DEFAULT_ERASE_SIZE  4096
 #define MAX_PANEL_BUF_SIZE 128
@@ -126,6 +137,26 @@
 static const char *baseband_dsda2   = " androidboot.baseband=dsda2";
 static const char *baseband_sglte2  = " androidboot.baseband=sglte2";
 
+#if VERIFIED_BOOT
+static const char *verity_mode = " androidboot.veritymode=";
+static const char *verified_state= " androidboot.verifiedbootstate=";
+
+//indexed based on enum values, green is 0 by default
+
+struct verified_boot_verity_mode vbvm[] =
+{
+	{false, "logging"},
+	{true, "enforcing"},
+};
+struct verified_boot_state_name vbsn[] =
+{
+	{GREEN, "green"},
+	{ORANGE, "orange"},
+	{YELLOW,"yellow"},
+	{RED,"red" },
+};
+#endif
+
 static unsigned page_size = 0;
 static unsigned page_mask = 0;
 static char ffbm_mode_string[FFBM_MODE_BUF_SIZE];
@@ -134,7 +165,11 @@
 /* Assuming unauthorized kernel image by default */
 static int auth_kernel_img = 0;
 
+#if VERIFIED_BOOT
+static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0, 1};
+#else
 static device_info device = {DEVICE_MAGIC, 0, 0, 0, 0};
+#endif
 
 struct atag_ptbl_entry
 {
@@ -209,6 +244,10 @@
 	unsigned char *cmdline_final = NULL;
 	int pause_at_bootup = 0;
 	bool gpt_exists = partition_gpt_exists();
+#if VERIFIED_BOOT
+    uint32_t boot_state = boot_verify_get_state();
+#endif
+
 
 	if (cmdline && cmdline[0]) {
 		cmdline_len = strlen(cmdline);
@@ -221,6 +260,12 @@
 	cmdline_len += strlen(usb_sn_cmdline);
 	cmdline_len += strlen(sn_buf);
 
+#if VERIFIED_BOOT
+	cmdline_len += strlen(verified_state) + strlen(vbsn[boot_state].name);
+	cmdline_len += strlen(verity_mode) + strlen(vbvm[device.verity_mode].name);
+#endif
+
+
 	if (boot_into_recovery && gpt_exists)
 		cmdline_len += strlen(secondary_gpt_enable);
 
@@ -303,7 +348,22 @@
 			have_cmdline = 1;
 			while ((*dst++ = *src++));
 		}
+#if VERIFIED_BOOT
+		src = verified_state;
+		if(have_cmdline) --dst;
+		have_cmdline = 1;
+		while ((*dst++ = *src++));
+		src = vbsn[boot_state].name;
+		if(have_cmdline) --dst;
+		while ((*dst++ = *src++));
 
+		src = verity_mode;
+		if(have_cmdline) --dst;
+		while ((*dst++ = *src++));
+		src = vbvm[device.verity_mode].name;
+		if(have_cmdline) -- dst;
+		while ((*dst++ = *src++));
+#endif
 		src = usb_sn_cmdline;
 		if (have_cmdline) --dst;
 		have_cmdline = 1;
@@ -585,17 +645,36 @@
 static void verify_signed_bootimg(uint32_t bootimg_addr, uint32_t bootimg_size)
 {
 	int ret;
+#if !VERIFIED_BOOT
+#if IMAGE_VERIF_ALGO_SHA1
+	uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA1;
+#else
+	uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
+#endif
+#endif
 
 	/* Assume device is rooted at this time. */
 	device.is_tampered = 1;
 
 	dprintf(INFO, "Authenticating boot image (%d): start\n", bootimg_size);
-
+#if VERIFIED_BOOT
+	if(boot_into_recovery)
+	{
+		ret = boot_verify_image((unsigned char *)bootimg_addr,
+				bootimg_size, "/recovery");
+	}
+	else
+	{
+		ret = boot_verify_image((unsigned char *)bootimg_addr,
+				bootimg_size, "/boot");
+	}
+	boot_verify_print_state();
+#else
 	ret = image_verify((unsigned char *)bootimg_addr,
 					   (unsigned char *)(bootimg_addr + bootimg_size),
 					   bootimg_size,
 					   CRYPTO_AUTH_ALG_SHA256);
-
+#endif
 	dprintf(INFO, "Authenticating boot image: done return value = %d\n", ret);
 
 	if (ret)
@@ -607,7 +686,24 @@
 #if USE_PCOM_SECBOOT
 	set_tamper_flag(device.is_tampered);
 #endif
-
+#if VERIFIED_BOOT
+	switch(boot_verify_get_state())
+	{
+		case RED:
+				dprintf(CRITICAL,
+						"Your device has failed verification and may not work properly.\nWait for 5 seconds before proceeding\n");
+				mdelay(5000);
+				break;
+		case YELLOW:
+				dprintf(CRITICAL,
+						"Your device has loaded a different operating system.\nWait for 5 seconds before proceeding\n");
+				mdelay(5000);
+				break;
+		default:
+				break;
+	}
+#endif
+#if !VERIFIED_BOOT
 	if(device.is_tampered)
 	{
 		write_device_info_mmc(&device);
@@ -619,6 +715,7 @@
 		ASSERT(0);
 	#endif
 	}
+#endif
 }
 
 static bool check_format_bit()
@@ -663,6 +760,27 @@
 	free(buf);
 	return ret;
 }
+#if VERIFIED_BOOT
+void boot_verifier_init()
+{
+	uint32_t boot_state;
+	/* Check if device unlock */
+	if(device.is_unlocked)
+	{
+		boot_verify_send_event(DEV_UNLOCK);
+		boot_verify_print_state();
+		dprintf(CRITICAL, "Device is unlocked! Skipping verification...\n");
+		return;
+	}
+	else
+	{
+		boot_verify_send_event(BOOT_INIT);
+	}
+
+	/* Initialize keystore */
+	boot_state = boot_verify_keystore_init();
+}
+#endif
 
 int boot_linux_from_mmc(void)
 {
@@ -769,6 +887,11 @@
 	}
 #endif
 
+#if VERIFIED_BOOT
+	boot_verifier_init();
+#endif
+
+
 	/* Authenticate Kernel */
 	dprintf(INFO, "use_signed_kernel=%d, is_unlocked=%d, is_tampered=%d.\n",
 		(int) target_use_signed_kernel(),
@@ -985,6 +1108,19 @@
 		}
 		#endif
 	}
+#if VERIFIED_BOOT
+	if(boot_verify_get_state() == ORANGE)
+	{
+		dprintf(CRITICAL,
+				"Your device has been unlocked and can't be trusted.\nWait for 5 seconds before proceeding\n");
+		mdelay(5000);
+	}
+
+	// send root of trust
+	if(!send_rot_command((uint32_t)device.is_unlocked))
+		ASSERT(0);
+#endif
+
 
 	if (boot_into_recovery && !device.is_unlocked && !device.is_tampered)
 		target_load_ssd_keystore();
@@ -1311,7 +1447,9 @@
 		info->is_unlocked = 0;
 		info->is_tampered = 0;
 		info->charger_screen_enabled = 0;
-
+#if VERIFIED_BOOT
+		info->verity_mode = 1;
+#endif
 		write_device_info_mmc(info);
 	}
 	memcpy(dev, info, sizeof(device_info));
@@ -1664,11 +1802,25 @@
 		return;
 	}
 #endif
+#if VERIFIED_BOOT
+	if(!(strncmp(arg, "userdata", 8)))
+		if(send_delete_keys_to_tz())
+			ASSERT(0);
+#endif
 	fastboot_okay("");
 }
 
 void cmd_erase(const char *arg, void *data, unsigned sz)
 {
+
+#if VERIFIED_BOOT
+	if(!device.is_unlocked)
+	{
+		fastboot_fail("device is locked. Cannot erase");
+		return;
+	}
+#endif
+
 	if(target_is_emmc_boot())
 		cmd_erase_mmc(arg, data, sz);
 	else
@@ -1973,11 +2125,29 @@
 	}
 #endif /* SSD_ENABLE */
 
+#if VERIFIED_BOOT
+	if(!device.is_unlocked)
+	{
+		fastboot_fail("device is locked. Cannot flash images");
+		return;
+	}
+#endif
+
 	sparse_header = (sparse_header_t *) data;
 	if (sparse_header->magic != SPARSE_HEADER_MAGIC)
 		cmd_flash_mmc_img(arg, data, sz);
 	else
 		cmd_flash_mmc_sparse_img(arg, data, sz);
+
+#if VERIFIED_BOOT
+	if((!strncmp(arg, "system", 6)) && !device.verity_mode)
+	{
+		// reset dm_verity mode to enforcing
+		device.verity_mode = 1;
+		write_device_info(&device);
+	}
+#endif
+
 	return;
 }
 
@@ -2089,12 +2259,35 @@
 	fastboot_okay("");
 }
 
+void cmd_oem_lock(const char *arg, void *data, unsigned sz)
+{
+	struct recovery_message msg;
+	if(device.is_unlocked)
+	{
+		device.is_unlocked = 0;
+		write_device_info(&device);
+		// upon oem lock, reboot to recovery to wipe user data
+		snprintf(msg.recovery, sizeof(msg.recovery), "recovery\n--wipe_data");
+		write_misc(0, &msg, sizeof(msg));
+		fastboot_okay("");
+		reboot_device(RECOVERY_MODE);
+	}
+	fastboot_okay("");
+}
+
+
 void cmd_oem_unlock(const char *arg, void *data, unsigned sz)
 {
 	if(!device.is_unlocked)
 	{
 		device.is_unlocked = 1;
 		write_device_info(&device);
+		struct recovery_message msg;
+		snprintf(msg.recovery, sizeof(msg.recovery), "recovery\n--wipe_data");
+		write_misc(0, &msg, sizeof(msg));
+
+		fastboot_okay("");
+		reboot_device(RECOVERY_MODE);
 	}
 	fastboot_okay("");
 }
@@ -2318,6 +2511,7 @@
 											{"reboot", cmd_reboot},
 											{"reboot-bootloader", cmd_reboot_bootloader},
 											{"oem unlock", cmd_oem_unlock},
+											{"oem lock", cmd_oem_lock},
 											{"oem device-info", cmd_oem_devinfo},
 											{"preflash", cmd_preflash},
 											{"oem enable-charger-screen", cmd_oem_enable_charger_screen},
@@ -2426,6 +2620,17 @@
 		boot_into_recovery = 1;
 	} else if(reboot_mode == FASTBOOT_MODE) {
 		boot_into_fastboot = true;
+#if VERIFIED_BOOT
+	} else if(reboot_mode == DM_VERITY_ENFORCING) {
+		device.verity_mode = 1;
+		write_device_info(&device);
+	} else if(reboot_mode == DM_VERITY_LOGGING) {
+		device.verity_mode = 0;
+		write_device_info(&device);
+	} else if(reboot_mode == DM_VERITY_KEYSCLEAR) {
+		if(send_delete_keys_to_tz())
+			ASSERT(0);
+#endif
 	}
 
 	if (!boot_into_fastboot)
diff --git a/app/aboot/devinfo.h b/app/aboot/devinfo.h
index a0d8743..108f252 100644
--- a/app/aboot/devinfo.h
+++ b/app/aboot/devinfo.h
@@ -43,6 +43,7 @@
 	bool is_tampered;
 	bool charger_screen_enabled;
 	char display_panel[MAX_PANEL_ID_LEN];
+	bool verity_mode; // 1 = enforcing, 0 = logging
 };
 
 #endif