Support using different GSI keys for verification

The GSI images might be signed by any of the three GSI keys.
Allowing all of them for verification as they're all official
keys. With this, we don't have to require using VTS package
from a specific branch.

Bug: 149806657
Test: vts-tradefed run vts -m VtsSecurityAvb
Change-Id: I22aee50f0efb4bd38e49f2d1813e6128fb60b035
diff --git a/avb/Android.bp b/avb/Android.bp
index d2e1930..bacec5f 100644
--- a/avb/Android.bp
+++ b/avb/Android.bp
@@ -38,7 +38,9 @@
         "vts-core",
     ],
     data: [
+        ":q-gsi_avbpubkey",
         ":r-gsi_avbpubkey",
+        ":s-gsi_avbpubkey",
     ],
 }
 
diff --git a/avb/AndroidTest.xml b/avb/AndroidTest.xml
index 3c27035..5d5301d 100644
--- a/avb/AndroidTest.xml
+++ b/avb/AndroidTest.xml
@@ -18,7 +18,9 @@
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
         <option name="abort-on-push-failure" value="false" />
         <option name="push-group" value="HalHidlTargetTest.push"/>
-        <option name="push" value="DATA/avb/r-gsi.avbpubkey->/data/local/tmp/gsi.avbpubkey" />
+        <option name="push" value="DATA/avb/q-gsi.avbpubkey->/data/local/tmp/q-gsi.avbpubkey" />
+        <option name="push" value="DATA/avb/r-gsi.avbpubkey->/data/local/tmp/r-gsi.avbpubkey" />
+        <option name="push" value="DATA/avb/s-gsi.avbpubkey->/data/local/tmp/s-gsi.avbpubkey" />
     </target_preparer>
     <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
         <option name="test-module-name" value="VtsSecurityAvb" />
diff --git a/avb/VtsSecurityAvbTest.cpp b/avb/VtsSecurityAvbTest.cpp
index 64b4050..2fb98ce 100644
--- a/avb/VtsSecurityAvbTest.cpp
+++ b/avb/VtsSecurityAvbTest.cpp
@@ -359,29 +359,36 @@
   return "";
 }
 
-// Reads GSI public key from the path specified in VTS configuration.
-//
-// Returns:
-//   The GSI public key read from the path.
-//   An empty string if any file operation fails.
-static std::string ReadGsiPublicKey() {
-  std::string key_blob;
-  if (android::base::ReadFileToString("/data/local/tmp/gsi.avbpubkey",
-                                      &key_blob)) {
-    return key_blob;
-  }
-  return "";
-}
-
 // Converts descriptor.hash_algorithm to std::string.
 static std::string GetHashAlgorithm(const AvbHashtreeDescriptor &descriptor) {
   return std::string(reinterpret_cast<const char *>(descriptor.hash_algorithm));
 }
 
+// Checks whether the public key is an official GSI key or not.
+static bool ValidatePublicKeyBlob(const std::string &key_blob_to_validate) {
+  if (key_blob_to_validate.empty()) {
+    ALOGE("Failed to validate an empty key");
+    return false;
+  }
+
+  std::string allowed_key_blob;
+  std::vector<std::string> allowed_key_paths = {
+      "/data/local/tmp/q-gsi.avbpubkey", "/data/local/tmp/r-gsi.avbpubkey",
+      "/data/local/tmp/s-gsi.avbpubkey"};
+  for (const auto &path : allowed_key_paths) {
+    if (android::base::ReadFileToString(path, &allowed_key_blob)) {
+      if (key_blob_to_validate == allowed_key_blob) {
+        ALOGE("Found matching GSI key: %s", path.c_str());
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 // Gets the system partition's AvbHashtreeDescriptor and device file path.
 //
 // Arguments:
-//  expected_key_blob: The key to verify the system's vbmeta.
 //  out_verify_result: The result of vbmeta verification.
 //  out_system_path: The system's device file path.
 //
@@ -390,7 +397,6 @@
 //   nullptr if any operation fails.
 static std::unique_ptr<android::fs_mgr::FsAvbHashtreeDescriptor>
 GetSystemHashtreeDescriptor(
-    const std::string &expected_key_blob,
     android::fs_mgr::VBMetaVerifyResult *out_verify_result,
     std::string *out_system_path) {
   android::fs_mgr::Fstab default_fstab;
@@ -419,13 +425,23 @@
   std::string out_avb_partition_name;
   std::unique_ptr<android::fs_mgr::VBMetaData> vbmeta =
       android::fs_mgr::LoadAndVerifyVbmeta(
-          *system_fstab_entry, expected_key_blob, &out_public_key_data,
+          *system_fstab_entry, "" /* expected_key_blob */, &out_public_key_data,
           &out_avb_partition_name, out_verify_result);
   if (vbmeta == nullptr) {
     ALOGE("LoadAndVerifyVbmeta fails");
     return nullptr;
   }
 
+  if (out_public_key_data.empty()) {
+    ALOGE("The GSI image is not signed");
+    return nullptr;
+  }
+
+  if (!ValidatePublicKeyBlob(out_public_key_data)) {
+    ALOGE("The GSI image is not signed by an official key");
+    return nullptr;
+  }
+
   std::unique_ptr<android::fs_mgr::FsAvbHashtreeDescriptor> descriptor =
       android::fs_mgr::GetHashtreeDescriptor("system", std::move(*vbmeta));
   if (descriptor == nullptr) {
@@ -439,14 +455,10 @@
 // Loads contents and metadata of logical system partition, calculates
 // the hashtree, and compares with the metadata.
 TEST(AvbTest, SystemHashtree) {
-  std::string expected_key_blob = ReadGsiPublicKey();
-  EXPECT_NE(expected_key_blob, "") << "Fail to read expected GSI key.";
-
   android::fs_mgr::VBMetaVerifyResult verify_result;
   std::string system_path;
   std::unique_ptr<android::fs_mgr::FsAvbHashtreeDescriptor> descriptor =
-      GetSystemHashtreeDescriptor(expected_key_blob, &verify_result,
-                                  &system_path);
+      GetSystemHashtreeDescriptor(&verify_result, &system_path);
   ASSERT_TRUE(descriptor);
 
   ALOGI("System partition is %s", system_path.c_str());
@@ -516,14 +528,11 @@
 // Compares device mapper table with system hashtree descriptor.
 TEST(AvbTest, SystemDescriptor) {
   // Get system hashtree descriptor.
-  std::string expected_key_blob = ReadGsiPublicKey();
-  EXPECT_NE(expected_key_blob, "") << "Fail to read expected GSI key.";
 
   android::fs_mgr::VBMetaVerifyResult verify_result;
   std::string system_path;
   std::unique_ptr<android::fs_mgr::FsAvbHashtreeDescriptor> descriptor =
-      GetSystemHashtreeDescriptor(expected_key_blob, &verify_result,
-                                  &system_path);
+      GetSystemHashtreeDescriptor(&verify_result, &system_path);
   ASSERT_TRUE(descriptor);
 
   // TODO: Assert when running with compliance configuration.
diff --git a/avb/vts_security_avb_test.xml b/avb/vts_security_avb_test.xml
index b5265f6..5d27704 100644
--- a/avb/vts_security_avb_test.xml
+++ b/avb/vts_security_avb_test.xml
@@ -18,7 +18,9 @@
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="vts_security_avb_test->/data/local/tmp/vts_security_avb_test" />
-        <option name="push" value="r-gsi.avbpubkey->/data/local/tmp/gsi.avbpubkey" />
+        <option name="push" value="q-gsi.avbpubkey->/data/local/tmp/q-gsi.avbpubkey" />
+        <option name="push" value="r-gsi.avbpubkey->/data/local/tmp/r-gsi.avbpubkey" />
+        <option name="push" value="s-gsi.avbpubkey->/data/local/tmp/s-gsi.avbpubkey" />
     </target_preparer>
     <option name="test-suite-tag" value="vts-core" />
     <test class="com.android.tradefed.testtype.GTest" >