platform: msm-shared: Include date in boot security patch

Read the value of boot security patch containing
date information, from the property com.android.
build.boot.security_patch in vbmeta data and send
it to keymaster TA. This new patch value contains
date information as well. If the property is not
defined or keymaster TA is not updated, send the
security patch value read from boot image header
as before.

Change-Id: I46544a1d37d5f08fd819802410e2960da2d326e8
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