Merge "platform: msm-shared: Include date in boot security patch"
diff --git a/include/km_main.h b/include/km_main.h
index 544dc55..117c24e 100644
--- a/include/km_main.h
+++ b/include/km_main.h
@@ -72,6 +72,7 @@
     KEYMASTER_MILESTONE_CALL				= (KEYMASTER_UTILS_CMD_ID + 4UL),
     KEYMASTER_SECURE_WRITE_PROTECT			= (KEYMASTER_UTILS_CMD_ID + 6UL),
     KEYMASTER_SET_VBH					= (KEYMASTER_UTILS_CMD_ID + 17UL),
+    KEYMASTER_GET_DATE_SUPPORT				= (KEYMASTER_UTILS_CMD_ID + 21UL),
 
     KEYMASTER_LAST_CMD_ENTRY				= (int)0xFFFFFFFFULL
 } keymaster_cmd_t;
@@ -279,4 +280,12 @@
 	int status;
 } __attribute__ ((packed)) km_set_vbh_rsp_t;
 
+typedef struct {
+	uint32_t cmd_id;
+} __attribute__ ((packed)) km_get_date_support_req;
+
+typedef struct {
+	int32_t status;
+} __attribute__ ((packed)) km_get_date_support_rsp;
+
 #endif /* KM_MAIN_H */
diff --git a/platform/msm_shared/avb/VerifiedBoot.c b/platform/msm_shared/avb/VerifiedBoot.c
index 642747d..7a06655 100644
--- a/platform/msm_shared/avb/VerifiedBoot.c
+++ b/platform/msm_shared/avb/VerifiedBoot.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-2019, 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
@@ -48,6 +48,7 @@
 #define MAX_PART_NAME_SIZE		10
 #define MAX_NUM_REQ_PARTITION	8
 #define BOOT_HEADER_VERSION_ZERO	0
+#define MAX_PROPERTY_SIZE        10
 
 char *avb_verify_partition_name[] = {
 	"boot",
@@ -359,6 +360,43 @@
 	}
 }
 
+static UINT32 ParseBootSecurityLevel (const CHAR8 *BootSecurityLevel,
+                                      size_t BootSecurityLevelStrSize)
+{
+	UINT32 PatchLevelDate = 0;
+	UINT32 PatchLevelMonth = 0;
+	UINT32 PatchLevelYear = 0;
+	UINT32 SeparatorCount = 0;
+	UINT32 Count = 0;
+
+	/*Parse the value of security patch as per YYYY-MM-DD format*/
+	while (Count < BootSecurityLevelStrSize) {
+		if (BootSecurityLevel[Count] == '-') {
+			SeparatorCount++;
+		}
+		else if (SeparatorCount == 2) {
+			PatchLevelDate *= 10;
+			PatchLevelDate += (BootSecurityLevel[Count] - '0');
+		}
+		else if (SeparatorCount == 1) {
+			PatchLevelMonth *= 10;
+			PatchLevelMonth += (BootSecurityLevel[Count] - '0');
+		}
+		else if (SeparatorCount == 0) {
+			PatchLevelYear *= 10;
+			PatchLevelYear += (BootSecurityLevel[Count] - '0');
+		}
+		else {
+			return -1;
+		}
+		Count++;
+	}
+
+	PatchLevelDate = PatchLevelDate << 11;
+	PatchLevelYear = (PatchLevelYear - 2000) << 4;
+	return (PatchLevelDate | PatchLevelYear | PatchLevelMonth);
+}
+
 static VOID ComputeVbMetaDigest (AvbSlotVerifyData* SlotData, CHAR8* Digest) {
 	size_t Index;
 	AvbSHA256Ctx Ctx;
@@ -397,6 +435,9 @@
 	AvbHashtreeErrorMode VerityFlags = AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE;
 	device_info DevInfo_vb;
 	CHAR8 Digest[AVB_SHA256_DIGEST_SIZE] = {0};
+	const CHAR8 *BootSecurityLevelStr = NULL;
+	size_t BootSecurityLevelStrSize = 0;
+	INT32 BootSecurityLevel = 0;
 
 	HeaderVersion = Info->header_version;
 	Info->boot_state = RED;
@@ -568,7 +609,28 @@
 	GUARD_OUT(AppendVBCommonCmdLine(Info));
 	GUARD_OUT(Appendvbcmdline(Info, SlotData->cmdline));
 	DevInfo_vb.is_unlocked = !is_device_locked();
-	set_os_version(ADD_SALT_BUFF_OFFSET(Info->images[0].image_buffer));
+
+	/* Send date value in security patch only when KM TA supports it and the
+	*  property is available in vbmeta data, send the old value in other cases
+	*/
+	BootSecurityLevelStr = avb_property_lookup (
+						SlotData->vbmeta_images[0].vbmeta_data,
+						SlotData->vbmeta_images[0].vbmeta_size,
+						"com.android.build.boot.security_patch",
+						0, &BootSecurityLevelStrSize);
+
+	if (BootSecurityLevelStr != NULL &&
+		BootSecurityLevelStrSize == MAX_PROPERTY_SIZE) {
+		BootSecurityLevel = ParseBootSecurityLevel (BootSecurityLevelStr,
+								BootSecurityLevelStrSize);
+		if (BootSecurityLevel < 0) {
+			dprintf (CRITICAL, "System security patch level format invalid\n");
+			Status = EFI_INVALID_PARAMETER;
+			goto out;
+		}
+	}
+
+	set_os_version_with_date(ADD_SALT_BUFF_OFFSET(Info->images[0].image_buffer), BootSecurityLevel);
 	if(!send_rot_command((uint32_t)DevInfo_vb.is_unlocked))
 		return EFI_LOAD_ERROR;
 
diff --git a/platform/msm_shared/boot_verifier.c b/platform/msm_shared/boot_verifier.c
index 4bc0995..caee469 100644
--- a/platform/msm_shared/boot_verifier.c
+++ b/platform/msm_shared/boot_verifier.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2016, 2019 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
@@ -779,6 +779,25 @@
 	return oem_keystore;
 }
 
+void set_os_version_with_date(unsigned char* img_addr, uint32_t system_security_level)
+{
+	boot_img_hdr *img_hdr = NULL;
+	bool supported;
+	int ret = get_date_support (&supported);
+
+	/* Extract the os version and patch level */
+	if (img_addr) {
+		img_hdr = (boot_img_hdr *)img_addr;
+		boot_state_info.system_version = (img_hdr->os_version & 0xFFFFF800) >> 11;
+		if(!ret && supported && system_security_level)
+			boot_state_info.system_security_level = system_security_level;
+		else
+			boot_state_info.system_security_level = (img_hdr->os_version & 0x7FF);
+	} else {
+		dprintf(CRITICAL, "Image address should not be NULL\n");
+	}
+}
+
 #if OSVERSION_IN_BOOTIMAGE
 void set_os_version(unsigned char* img_addr)
 {
@@ -825,3 +844,26 @@
 	}
 	return ret;
 }
+
+int get_date_support (bool *supported)
+{
+	int status = 0;
+	km_get_date_support_req date_support_req = {0};
+	km_get_date_support_rsp date_support_rsp = {0};
+	int app_handle = get_secapp_handle();
+
+	date_support_req.cmd_id = KEYMASTER_GET_DATE_SUPPORT;
+	status = qseecom_send_command (app_handle, (void *)&date_support_req, sizeof (date_support_req), (void *)&date_support_rsp, sizeof (date_support_rsp));
+	if (status != 0 || date_support_rsp.status != 0 ) {
+		dprintf(CRITICAL, "QSEEcom command to get date support returned error, status: %d\n",date_support_rsp.status);
+
+		if (status == 0 && date_support_rsp.status == KM_ERROR_INVALID_TAG) {
+			dprintf(INFO, "Date in patch level NOT supported in keymaster\n");
+		}
+		*supported = false;
+		return status;
+	}
+
+	*supported = true;
+	return status;
+}
diff --git a/platform/msm_shared/include/boot_verifier.h b/platform/msm_shared/include/boot_verifier.h
index 5525a7a..6d2b2db 100644
--- a/platform/msm_shared/include/boot_verifier.h
+++ b/platform/msm_shared/include/boot_verifier.h
@@ -178,6 +178,7 @@
 bool send_rot_command(uint32_t is_unlocked);
 /* function to set the os version and patch level. */
 void set_os_version(unsigned char* img_addr);
+void set_os_version_with_date(unsigned char* img_addr, uint32_t system_security_level);
 unsigned char* get_boot_fingerprint(unsigned int* buf_size);
 bool boot_verify_compare_sha256(unsigned char *image_ptr,
 		unsigned int image_size, unsigned char *signature_ptr, RSA *rsa);
@@ -185,4 +186,7 @@
 uint32_t read_der_message_length(unsigned char* input, unsigned sz);
 /* Function to set verified boot hash in keymaster */
 int set_verified_boot_hash (const char *vbh, size_t vbh_size);
+/* Function to check date support in keymaster */
+int get_date_support (bool *supported);
+
 #endif