build_utils: Add support to boot custom kernels without wiping

The following is implemented:
* Add hashtree footer to vendor_dlkm.
* Add SPL to boot.img

This allows developers to flash a custom kernel on an unlocked device
without having to wipe the device (based on SPL) or disable verification
(based on AVB hashtree requirement).

Test: verify custom boot.img boots without wiping on O6
Test: verify custom vendor_dlkm.img boots without wiping on O6
Bug: 274825778
Change-Id: I685199eb11bfc5a4bdf545170ec136b327f992ad
Signed-off-by: Will McVicker <willmcvicker@google.com>
diff --git a/build_utils.sh b/build_utils.sh
index f8d2aa0..2307615 100644
--- a/build_utils.sh
+++ b/build_utils.sh
@@ -394,6 +394,11 @@
   fi
   build_image "${VENDOR_DLKM_STAGING_DIR}" "${vendor_dlkm_props_file}" \
     "${DIST_DIR}/vendor_dlkm.img" /dev/null
+
+  avbtool add_hashtree_footer \
+    --partition_name vendor_dlkm \
+    --hash_algorithm sha256 \
+    --image "${DIST_DIR}/vendor_dlkm.img"
 }
 
 function check_mkbootimg_path() {
@@ -642,30 +647,44 @@
   echo "${!boot_size_var}"
 }
 
-# gki_add_avb_footer <image> <partition_size>
+# gki_add_avb_footer <image> <partition_size> <security_patch_month>
 function gki_add_avb_footer() {
+  local spl_month="$3"
+  local additional_props=""
+  if [ -n "${spl_month}" ]; then
+    additional_props="--prop com.android.build.boot.security_patch:$(date +'%Y')-${spl_month}-05"
+  fi
+
   avbtool add_hash_footer --image "$1" \
-    --partition_name boot --partition_size "$2"
+    --partition_name boot --partition_size "$2" \
+    ${additional_props}
 }
 
-# gki_dry_run_certify_bootimg <boot_image> <gki_artifacts_info_file>
+# gki_dry_run_certify_bootimg <boot_image> <gki_artifacts_info_file> <security_patch_month>
 # The certify_bootimg script will be executed on a server over a GKI
 # boot.img during the official certification process, which embeds
 # a GKI certificate into the boot.img. The certificate is for Android
 # VTS to verify that a GKI boot.img is authentic.
 # Dry running the process here so we can catch related issues early.
 function gki_dry_run_certify_bootimg() {
+  local spl_month="$3"
+  local additional_props=()
+  if [ -n "${spl_month}" ]; then
+    additional_props+=("--extra_footer_args" \
+      "--prop com.android.build.boot.security_patch:$(date +'%Y')-${spl_month}-05")
+  fi
+
   certify_bootimg --boot_img "$1" \
     --algorithm SHA256_RSA4096 \
     --key tools/mkbootimg/gki/testdata/testkey_rsa4096.pem \
     --gki_info "$2" \
-    --output "$1"
+    --output "$1" \
+    "${additional_props[@]}"
 }
 
 # build_gki_artifacts_info <output_gki_artifacts_info_file>
 function build_gki_artifacts_info() {
-  local artifacts_info="certify_bootimg_extra_args=--prop ARCH:${ARCH} \
---prop BRANCH:${BRANCH}"
+  local artifacts_info="certify_bootimg_extra_args=--prop ARCH:${ARCH} --prop BRANCH:${BRANCH}"
 
   if [ -n "${BUILD_NUMBER}" ]; then
     artifacts_info="${artifacts_info} --prop BUILD_NUMBER:${BUILD_NUMBER}"
@@ -686,6 +705,11 @@
 # kernel images are optional, e.g., ${DIST_DIR}/Image.gz.
 function build_gki_boot_images() {
   local uncompressed_kernel_path=$1
+  local spl_month=$(date +'%m')
+  if [ $((${spl_month} % 3)) -gt 0 ]; then
+    # Round up to the closest quarterly month
+    spl_month=$((${spl_month} + 3 - (${spl_month} % 3)))
+  fi
 
   if ! [ -f "${uncompressed_kernel_path}" ]; then
     echo "ERROR: '${uncompressed_kernel_path}' doesn't exist" >&2
@@ -722,9 +746,9 @@
     "${MKBOOTIMG_PATH}" "${GKI_MKBOOTIMG_ARGS[@]}"
 
     gki_add_avb_footer "${boot_image_path}" \
-      "$(gki_get_boot_img_size "${compression}")"
+      "$(gki_get_boot_img_size "${compression}")" "${spl_month}"
     gki_dry_run_certify_bootimg "${boot_image_path}" \
-      "${GKI_ARTIFACTS_INFO_FILE}"
+      "${GKI_ARTIFACTS_INFO_FILE}" "${spl_month}"
     images_to_pack+=("${boot_image}")
   done