libavb_atx: Remove GSK rollback index and increase key size.

- The GSK rollback index was redundant with existing vbmeta rollback
protection. It has been removed.
- ATX now uses 4096-bit keys.
- Added a test data generator script.

This change breaks compatibility of ATX data structures.

Bug: 35767054
Test: unit tests
Change-Id: Ifff377c88abd531a394afe9e71fbc1307a7f834e
diff --git a/avbtool b/avbtool
index 6ebbd8c..a855e84 100755
--- a/avbtool
+++ b/avbtool
@@ -2570,14 +2570,8 @@
     signature = bytearray()
     if authority_key_path:
       padding_and_hash = bytearray()
-      algorithm_name = None
-      hasher = None
-      if is_intermediate_authority:
-        hasher = hashlib.sha512()
-        algorithm_name = 'SHA512_RSA4096'
-      else:
-        hasher = hashlib.sha256()
-        algorithm_name = 'SHA256_RSA2048'
+      algorithm_name = 'SHA512_RSA4096'
+      hasher = hashlib.sha512()
       padding_and_hash.extend(ALGORITHMS[algorithm_name].padding)
       hasher.update(signed_data)
       padding_and_hash.extend(hasher.digest())
@@ -2602,14 +2596,15 @@
     Raises:
       AvbError: If an argument is incorrect.
     """
-    if len(product_id) != 16:
+    EXPECTED_PRODUCT_ID_SIZE = 16
+    if len(product_id) != EXPECTED_PRODUCT_ID_SIZE:
       raise AvbError('Invalid Product ID length.')
     output.write(struct.pack('<I', 1))  # Format Version
     write_rsa_key(output, Crypto.PublicKey.RSA.importKey(root_authority_key))
     output.write(product_id)
 
   def make_atx_metadata(self, output, intermediate_key_certificate,
-                        product_key_certificate, google_key_version):
+                        product_key_certificate):
     """Implements the 'make_atx_metadata' command.
 
     Android Things metadata are included in vbmeta images to facilitate
@@ -2624,20 +2619,18 @@
       product_key_certificate: A certificate file as output by
                                make_atx_certificate with
                                is_intermediate_authority set to false.
-      google_key_version: The version of the Google Signing Key used in the
-                          associated vbmeta image.
 
     Raises:
       AvbError: If an argument is incorrect.
     """
-    if len(intermediate_key_certificate) != 1108:
+    EXPECTED_CERTIFICATE_SIZE = 1620
+    if len(intermediate_key_certificate) != EXPECTED_CERTIFICATE_SIZE:
       raise AvbError('Invalid intermediate key certificate length.')
-    if len(product_key_certificate) != 852:
+    if len(product_key_certificate) != EXPECTED_CERTIFICATE_SIZE:
       raise AvbError('Invalid product key certificate length.')
     output.write(struct.pack('<I', 1))  # Format Version
     output.write(intermediate_key_certificate)
     output.write(product_key_certificate)
-    output.write(struct.pack('<Q', google_key_version))
 
 
 def calc_hash_level_offsets(image_size, block_size, digest_size):
@@ -3098,10 +3091,6 @@
                             help='Path to product key certificate file',
                             type=argparse.FileType('rb'),
                             required=True)
-    sub_parser.add_argument('--google_key_version',
-                            help=('Version of the Google signing key'),
-                            type=parse_number,
-                            default=0)
     sub_parser.set_defaults(func=self.make_atx_metadata)
 
     args = parser.parse_args(argv[1:])
@@ -3203,8 +3192,7 @@
     """Implements the 'make_atx_metadata' sub-command."""
     self.avb.make_atx_metadata(args.output,
                                args.intermediate_key_certificate.read(),
-                               args.product_key_certificate.read(),
-                               args.google_key_version)
+                               args.product_key_certificate.read())
 
 
 if __name__ == '__main__':
diff --git a/libavb_atx/avb_atx_types.h b/libavb_atx/avb_atx_types.h
index ae1b438..6d69859 100644
--- a/libavb_atx/avb_atx_types.h
+++ b/libavb_atx/avb_atx_types.h
@@ -39,46 +39,36 @@
 /* Size in bytes of an Android Things product ID. */
 #define AVB_ATX_PRODUCT_ID_SIZE 16
 
-/* Size in bytes of a serialized public key with a 2048-bit modulus. */
-#define AVB_ATX_PUBLIC_KEY_SIZE_2048 (sizeof(AvbRSAPublicKeyHeader) + 512)
-
 /* Size in bytes of a serialized public key with a 4096-bit modulus. */
-#define AVB_ATX_PUBLIC_KEY_SIZE_4096 (sizeof(AvbRSAPublicKeyHeader) + 1024)
+#define AVB_ATX_PUBLIC_KEY_SIZE (sizeof(AvbRSAPublicKeyHeader) + 1024)
 
 /* Data structure of Android Things permanent attributes. */
 typedef struct AvbAtxPermanentAttributes {
   uint32_t version;
-  uint8_t product_root_public_key[AVB_ATX_PUBLIC_KEY_SIZE_4096];
+  uint8_t product_root_public_key[AVB_ATX_PUBLIC_KEY_SIZE];
   uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE];
 } AVB_ATTR_PACKED AvbAtxPermanentAttributes;
 
 /* Data structure of signed fields in an Android Things certificate. */
 typedef struct AvbAtxCertificateSignedData {
   uint32_t version;
-  uint8_t public_key[AVB_ATX_PUBLIC_KEY_SIZE_2048];
+  uint8_t public_key[AVB_ATX_PUBLIC_KEY_SIZE];
   uint8_t subject[AVB_SHA256_DIGEST_SIZE];
   uint8_t usage[AVB_SHA256_DIGEST_SIZE];
   uint64_t key_version;
 } AVB_ATTR_PACKED AvbAtxCertificateSignedData;
 
-/* Data structure of a certificate signed by a 4096-bit key. */
-typedef struct AvbAtxCertificate4096 {
+/* Data structure of an Android Things certificate. */
+typedef struct AvbAtxCertificate {
   AvbAtxCertificateSignedData signed_data;
   uint8_t signature[AVB_RSA4096_NUM_BYTES];
-} AVB_ATTR_PACKED AvbAtxCertificate4096;
-
-/* Data structure of a certificate signed by a 2048-bit key. */
-typedef struct AvbAtxCertificate2048 {
-  AvbAtxCertificateSignedData signed_data;
-  uint8_t signature[AVB_RSA2048_NUM_BYTES];
-} AVB_ATTR_PACKED AvbAtxCertificate2048;
+} AVB_ATTR_PACKED AvbAtxCertificate;
 
 /* Data structure of Android Things public key metadata in vbmeta. */
 typedef struct AvbAtxPublicKeyMetadata {
   uint32_t version;
-  AvbAtxCertificate4096 product_intermediate_key_certificate;
-  AvbAtxCertificate2048 product_signing_key_certificate;
-  uint64_t google_signing_key_version;
+  AvbAtxCertificate product_intermediate_key_certificate;
+  AvbAtxCertificate product_signing_key_certificate;
 } AVB_ATTR_PACKED AvbAtxPublicKeyMetadata;
 
 #ifdef __cplusplus
diff --git a/libavb_atx/avb_atx_validate.c b/libavb_atx/avb_atx_validate.c
index 7a29d66..fb200c1 100644
--- a/libavb_atx/avb_atx_validate.c
+++ b/libavb_atx/avb_atx_validate.c
@@ -74,17 +74,16 @@
   return true;
 }
 
-/* Verifies signature and fields of a PIK certificate. */
-static bool verify_pik_certificate(
-    AvbAtxCertificate4096* certificate,
-    uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE_4096],
-    uint64_t minimum_version) {
+/* Verifies the format, key version, usage, and signature of a certificate. */
+static bool verify_certificate(AvbAtxCertificate* certificate,
+                               uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
+                               uint64_t minimum_key_version,
+                               uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE]) {
   const AvbAlgorithmData* algorithm_data;
   uint8_t certificate_hash[AVB_SHA512_DIGEST_SIZE];
-  uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
 
   if (certificate->signed_data.version != 1) {
-    avb_error("Unsupported PIK certificate format.\n");
+    avb_error("Unsupported certificate format.\n");
     return false;
   }
   algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA512_RSA4096);
@@ -92,25 +91,39 @@
          sizeof(AvbAtxCertificateSignedData),
          certificate_hash);
   if (!avb_rsa_verify(authority,
-                      AVB_ATX_PUBLIC_KEY_SIZE_4096,
+                      AVB_ATX_PUBLIC_KEY_SIZE,
                       certificate->signature,
                       AVB_RSA4096_NUM_BYTES,
                       certificate_hash,
                       AVB_SHA512_DIGEST_SIZE,
                       algorithm_data->padding,
                       algorithm_data->padding_len)) {
-    avb_error("Invalid PIK certificate signature.\n");
+    avb_error("Invalid certificate signature.\n");
     return false;
   }
-  sha256_str("com.google.android.things.vboot.ca", expected_usage);
+  if (certificate->signed_data.key_version < minimum_key_version) {
+    avb_error("Key rollback detected.\n");
+    return false;
+  }
   if (0 != avb_safe_memcmp(certificate->signed_data.usage,
                            expected_usage,
                            AVB_SHA256_DIGEST_SIZE)) {
-    avb_error("Invalid PIK certificate usage.\n");
+    avb_error("Invalid certificate usage.\n");
     return false;
   }
-  if (certificate->signed_data.key_version < minimum_version) {
-    avb_error("PIK rollback detected.\n");
+  return true;
+}
+
+/* Verifies signature and fields of a PIK certificate. */
+static bool verify_pik_certificate(AvbAtxCertificate* certificate,
+                                   uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
+                                   uint64_t minimum_version) {
+  uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
+
+  sha256_str("com.google.android.things.vboot.ca", expected_usage);
+  if (!verify_certificate(
+          certificate, authority, minimum_version, expected_usage)) {
+    avb_error("Invalid PIK certificate.\n");
     return false;
   }
   return true;
@@ -118,31 +131,17 @@
 
 /* Verifies signature and fields of a PSK certificate. */
 static bool verify_psk_certificate(
-    AvbAtxCertificate2048* certificate,
-    uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE_2048],
+    AvbAtxCertificate* certificate,
+    uint8_t authority[AVB_ATX_PUBLIC_KEY_SIZE],
     uint64_t minimum_version,
     uint8_t product_id[AVB_ATX_PRODUCT_ID_SIZE]) {
-  const AvbAlgorithmData* algorithm_data;
-  uint8_t certificate_hash[AVB_SHA256_DIGEST_SIZE];
   uint8_t expected_subject[AVB_SHA256_DIGEST_SIZE];
   uint8_t expected_usage[AVB_SHA256_DIGEST_SIZE];
-  if (certificate->signed_data.version != 1) {
-    avb_error("Unsupported PSK certificate format.\n");
-    return false;
-  }
-  algorithm_data = avb_get_algorithm_data(AVB_ALGORITHM_TYPE_SHA256_RSA2048);
-  sha256((const uint8_t*)&certificate->signed_data,
-         sizeof(AvbAtxCertificateSignedData),
-         certificate_hash);
-  if (!avb_rsa_verify(authority,
-                      AVB_ATX_PUBLIC_KEY_SIZE_2048,
-                      certificate->signature,
-                      AVB_RSA2048_NUM_BYTES,
-                      certificate_hash,
-                      AVB_SHA256_DIGEST_SIZE,
-                      algorithm_data->padding,
-                      algorithm_data->padding_len)) {
-    avb_error("Invalid PSK certificate signature.\n");
+
+  sha256_str("com.google.android.things.vboot", expected_usage);
+  if (!verify_certificate(
+          certificate, authority, minimum_version, expected_usage)) {
+    avb_error("Invalid PSK certificate.\n");
     return false;
   }
   sha256(product_id, AVB_ATX_PRODUCT_ID_SIZE, expected_subject);
@@ -152,17 +151,6 @@
     avb_error("Product ID mismatch.\n");
     return false;
   }
-  sha256_str("com.google.android.things.vboot", expected_usage);
-  if (0 != avb_safe_memcmp(certificate->signed_data.usage,
-                           expected_usage,
-                           AVB_SHA256_DIGEST_SIZE)) {
-    avb_error("Invalid PSK certificate usage.\n");
-    return false;
-  }
-  if (certificate->signed_data.key_version < minimum_version) {
-    avb_error("PSK rollback detected.\n");
-    return false;
-  }
   return true;
 }
 
@@ -179,7 +167,8 @@
   AvbAtxPublicKeyMetadata metadata;
   uint64_t minimum_version;
 
-  /* Be pessimistic so we can exit early without having to remember to clear. */
+  /* Be pessimistic so we can exit early without having to remember to clear.
+   */
   *out_is_trusted = false;
 
   /* Read and verify permanent attributes. */
@@ -240,30 +229,18 @@
   }
 
   /* Verify the PSK is the same key that verified vbmeta. */
-  if (public_key_length != AVB_ATX_PUBLIC_KEY_SIZE_2048) {
+  if (public_key_length != AVB_ATX_PUBLIC_KEY_SIZE) {
     avb_error("Public key length mismatch.\n");
     return AVB_IO_RESULT_OK;
   }
   if (0 != avb_safe_memcmp(
                metadata.product_signing_key_certificate.signed_data.public_key,
                public_key_data,
-               AVB_ATX_PUBLIC_KEY_SIZE_2048)) {
+               AVB_ATX_PUBLIC_KEY_SIZE)) {
     avb_error("Public key mismatch.\n");
     return AVB_IO_RESULT_OK;
   }
 
-  /* Verify the GSK minimum version. */
-  result = ops->read_rollback_index(
-      ops, AVB_ATX_GSK_VERSION_LOCATION, &minimum_version);
-  if (result != AVB_IO_RESULT_OK) {
-    avb_error("Failed to read GSK minimum version.\n");
-    return result;
-  }
-  if (metadata.google_signing_key_version < minimum_version) {
-    avb_error("Google signing key rollback detected.\n");
-    return AVB_IO_RESULT_OK;
-  }
-
   *out_is_trusted = true;
   return AVB_IO_RESULT_OK;
 }
diff --git a/libavb_atx/avb_atx_validate.h b/libavb_atx/avb_atx_validate.h
index 07c154e..41faac1 100644
--- a/libavb_atx/avb_atx_validate.h
+++ b/libavb_atx/avb_atx_validate.h
@@ -40,7 +40,6 @@
 /* Rollback index locations for Android Things key versions. */
 #define AVB_ATX_PIK_VERSION_LOCATION 0x1000
 #define AVB_ATX_PSK_VERSION_LOCATION 0x1001
-#define AVB_ATX_GSK_VERSION_LOCATION 0x1002
 
 /* An implementation of validate_vbmeta_public_key for Android Things. See
  * libavb/avb_ops.h for details on validate_vbmeta_public_key in general. This
@@ -59,10 +58,6 @@
  *   - Product Signing Key (PSK): This key is a rotated authority for a specific
  *                                Android Things product. It is certified by a
  *                                PIK and must match |public_key_data|.
- *   - Google Signing Key (GSK): This key is a rotated authority for system and
- *                               boot partitions built by Google. The key is
- *                               already verified as part of vbmeta so only the
- *                               key version needs verification here.
  *   - Product ID: This value is provided in permanent attributes and is unique
  *                 to a specific Android Things product. This value must match
  *                 the subject of the PSK certificate.
diff --git a/test/avb_atx_generate_test_data b/test/avb_atx_generate_test_data
new file mode 100755
index 0000000..019c845
--- /dev/null
+++ b/test/avb_atx_generate_test_data
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use, copy,
+# modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+
+# This shell-script generates ATX test data in the working directory.
+# An avbtool executable is assumed to reside in the parent directory
+# of this script.
+#
+# The *atx* test data in the test/data/ directory was generated with
+# this script. It is consistent with the expectations of avbtool unit
+# tests and ATX unit tests. This script exists as a record of how the
+# data was generated and as a convenience if it ever needs to be
+# generated again.
+#
+# Typical usage:
+#
+#  $ cd test/data; ../avb_atx_generate_test_data
+
+set -e
+
+TMP_FILE=$(mktemp /tmp/atx_generator.XXXXXXXXXX)
+trap "rm -f '${TMP_FILE}'" EXIT
+
+AVBTOOL=$(dirname "$0")/../avbtool
+
+echo AVBTOOL = ${AVBTOOL}
+
+# Get a random product ID.
+head -c 16 /dev/urandom > atx_product_id.bin
+
+# Generate key pairs.
+openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -outform PEM \
+  -out testkey_atx_prk.pem
+openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -outform PEM \
+  -out testkey_atx_pik.pem
+openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 -outform PEM \
+  -out testkey_atx_psk.pem
+
+# Construct permanent attributes.
+${AVBTOOL} make_atx_permanent_attributes --output=atx_permanent_attributes.bin \
+  --product_id=atx_product_id.bin --root_authority_key=testkey_atx_prk.pem
+
+# Construct a PIK certificate.
+echo -n "fake PIK subject" > ${TMP_FILE}
+${AVBTOOL} make_atx_certificate --output=atx_pik_certificate.bin \
+  --subject=${TMP_FILE} --subject_key=testkey_atx_pik.pem \
+  --subject_is_intermediate_authority --subject_key_version 42 \
+  --authority_key=testkey_atx_prk.pem
+
+# Construct a PSK certificate.
+${AVBTOOL} make_atx_certificate --output=atx_psk_certificate.bin \
+  --subject=atx_product_id.bin --subject_key=testkey_atx_psk.pem \
+  --subject_key_version 42 --authority_key=testkey_atx_pik.pem
+
+# Construct metadata.
+${AVBTOOL} make_atx_metadata --output=atx_metadata.bin \
+  --intermediate_key_certificate=atx_pik_certificate.bin \
+  --product_key_certificate=atx_psk_certificate.bin
+
diff --git a/test/avb_atx_validate_unittest.cc b/test/avb_atx_validate_unittest.cc
index 6efa856..1436b0b 100644
--- a/test/avb_atx_validate_unittest.cc
+++ b/test/avb_atx_validate_unittest.cc
@@ -42,8 +42,8 @@
 const char kMetadataPath[] = "test/data/atx_metadata.bin";
 const char kPermanentAttributesPath[] =
     "test/data/atx_permanent_attributes.bin";
-const char kPRKPrivateKeyPath[] = "test/data/testkey_rsa4096.pem";
-const char kPIKPrivateKeyPath[] = "test/data/testkey_rsa2048.pem";
+const char kPRKPrivateKeyPath[] = "test/data/testkey_atx_prk.pem";
+const char kPIKPrivateKeyPath[] = "test/data/testkey_atx_pik.pem";
 
 class ScopedRSA {
  public:
@@ -59,24 +59,16 @@
     }
   }
 
-  // PKCS #1 v1.5 signature using SHA512 if |rsa_| is 4096 bits, SHA256
-  // otherwise. Returns true on success.
+  // PKCS #1 v1.5 signature using SHA512. Returns true on success.
   bool Sign(const void* data_to_sign, size_t length, uint8_t signature[]) {
-    bool use_sha512 = (RSA_size(rsa_) == AVB_RSA4096_NUM_BYTES);
     uint8_t digest[AVB_SHA512_DIGEST_SIZE];
-    unsigned int digest_size =
-        use_sha512 ? AVB_SHA512_DIGEST_SIZE : AVB_SHA256_DIGEST_SIZE;
     const unsigned char* data_to_sign_buf =
         reinterpret_cast<const unsigned char*>(data_to_sign);
-    if (use_sha512) {
-      SHA512(data_to_sign_buf, length, digest);
-    } else {
-      SHA256(data_to_sign_buf, length, digest);
-    }
+    SHA512(data_to_sign_buf, length, digest);
     unsigned int signature_length = 0;
-    return (1 == RSA_sign(use_sha512 ? NID_sha512 : NID_sha256,
+    return (1 == RSA_sign(NID_sha512,
                           digest,
-                          digest_size,
+                          AVB_SHA512_DIGEST_SIZE,
                           signature,
                           &signature_length,
                           rsa_));
@@ -98,9 +90,8 @@
     ReadDefaultData();
     ops_.set_delegate(this);
     ops_.set_permanent_attributes(attributes_);
-    ops_.set_stored_rollback_indexes({{AVB_ATX_PIK_VERSION_LOCATION, 0},
-                                      {AVB_ATX_PSK_VERSION_LOCATION, 0},
-                                      {AVB_ATX_GSK_VERSION_LOCATION, 0}});
+    ops_.set_stored_rollback_indexes(
+        {{AVB_ATX_PIK_VERSION_LOCATION, 0}, {AVB_ATX_PSK_VERSION_LOCATION, 0}});
   }
 
   // FakeAvbOpsDelegate methods.
@@ -137,9 +128,7 @@
     if ((fail_read_pik_rollback_index_ &&
          rollback_index_slot == AVB_ATX_PIK_VERSION_LOCATION) ||
         (fail_read_psk_rollback_index_ &&
-         rollback_index_slot == AVB_ATX_PSK_VERSION_LOCATION) ||
-        (fail_read_gsk_rollback_index_ &&
-         rollback_index_slot == AVB_ATX_GSK_VERSION_LOCATION)) {
+         rollback_index_slot == AVB_ATX_PSK_VERSION_LOCATION)) {
       return AVB_IO_RESULT_ERROR_IO;
     }
     return ops_.read_rollback_index(
@@ -188,7 +177,7 @@
     return avb_atx_validate_vbmeta_public_key(
         ops_.avb_ops(),
         metadata_.product_signing_key_certificate.signed_data.public_key,
-        AVB_ATX_PUBLIC_KEY_SIZE_2048,
+        AVB_ATX_PUBLIC_KEY_SIZE,
         reinterpret_cast<const uint8_t*>(&metadata_),
         sizeof(metadata_),
         is_trusted);
@@ -208,7 +197,7 @@
   void SignPSKCertificate() {
     memset(metadata_.product_signing_key_certificate.signature,
            0,
-           AVB_RSA2048_NUM_BYTES);
+           AVB_RSA4096_NUM_BYTES);
     ScopedRSA key(kPIKPrivateKeyPath);
     ASSERT_TRUE(key.Sign(&metadata_.product_signing_key_certificate.signed_data,
                          sizeof(AvbAtxCertificateSignedData),
@@ -222,7 +211,6 @@
   bool fail_read_permanent_attributes_hash_{false};
   bool fail_read_pik_rollback_index_{false};
   bool fail_read_psk_rollback_index_{false};
-  bool fail_read_gsk_rollback_index_{false};
 
  private:
   void ReadDefaultData() {
@@ -251,7 +239,7 @@
   std::string old_psk_sig(
       reinterpret_cast<char*>(
           metadata_.product_signing_key_certificate.signature),
-      AVB_RSA2048_NUM_BYTES);
+      AVB_RSA4096_NUM_BYTES);
   SignPIKCertificate();
   SignPSKCertificate();
   std::string new_pik_sig(
@@ -261,7 +249,7 @@
   std::string new_psk_sig(
       reinterpret_cast<char*>(
           metadata_.product_signing_key_certificate.signature),
-      AVB_RSA2048_NUM_BYTES);
+      AVB_RSA4096_NUM_BYTES);
   EXPECT_EQ(old_pik_sig, new_pik_sig);
   EXPECT_EQ(old_psk_sig, new_psk_sig);
   bool is_trusted = false;
@@ -307,7 +295,7 @@
     return avb_atx_validate_vbmeta_public_key(
         ops_.avb_ops(),
         metadata_.product_signing_key_certificate.signed_data.public_key,
-        AVB_ATX_PUBLIC_KEY_SIZE_2048,
+        AVB_ATX_PUBLIC_KEY_SIZE,
         reinterpret_cast<const uint8_t*>(&metadata_),
         GetParam(),
         is_trusted);
@@ -407,8 +395,7 @@
       {{AVB_ATX_PIK_VERSION_LOCATION,
         metadata_.product_intermediate_key_certificate.signed_data.key_version +
             1},
-       {AVB_ATX_PSK_VERSION_LOCATION, 0},
-       {AVB_ATX_GSK_VERSION_LOCATION, 0}});
+       {AVB_ATX_PSK_VERSION_LOCATION, 0}});
   bool is_trusted = true;
   EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
   EXPECT_FALSE(is_trusted);
@@ -484,8 +471,8 @@
   ops_.set_stored_rollback_indexes(
       {{AVB_ATX_PIK_VERSION_LOCATION, 0},
        {AVB_ATX_PSK_VERSION_LOCATION,
-        metadata_.product_signing_key_certificate.signed_data.key_version + 1},
-       {AVB_ATX_GSK_VERSION_LOCATION, 0}});
+        metadata_.product_signing_key_certificate.signed_data.key_version +
+            1}});
   bool is_trusted = true;
   EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
   EXPECT_FALSE(is_trusted);
@@ -518,43 +505,25 @@
                         AvbAtxValidateTestWithPublicKeyLength,
                         ::testing::Values(0,
                                           1,
-                                          AVB_ATX_PUBLIC_KEY_SIZE_2048 - 1,
-                                          AVB_ATX_PUBLIC_KEY_SIZE_2048 + 1,
-                                          AVB_ATX_PUBLIC_KEY_SIZE_4096,
+                                          AVB_ATX_PUBLIC_KEY_SIZE - 1,
+                                          AVB_ATX_PUBLIC_KEY_SIZE + 1,
+                                          AVB_ATX_PUBLIC_KEY_SIZE - 512,
                                           -1));
 
 TEST_F(AvbAtxValidateTest, PSKMismatch) {
-  uint8_t bad_key[AVB_ATX_PUBLIC_KEY_SIZE_2048] = {};
+  uint8_t bad_key[AVB_ATX_PUBLIC_KEY_SIZE] = {};
   bool is_trusted = true;
   EXPECT_EQ(AVB_IO_RESULT_OK,
             avb_atx_validate_vbmeta_public_key(
                 ops_.avb_ops(),
                 bad_key,
-                AVB_ATX_PUBLIC_KEY_SIZE_2048,
+                AVB_ATX_PUBLIC_KEY_SIZE,
                 reinterpret_cast<const uint8_t*>(&metadata_),
                 sizeof(metadata_),
                 &is_trusted));
   EXPECT_FALSE(is_trusted);
 }
 
-TEST_F(AvbAtxValidateTest, FailReadGSKRollbackIndex) {
-  fail_read_gsk_rollback_index_ = true;
-  bool is_trusted = true;
-  EXPECT_EQ(AVB_IO_RESULT_ERROR_IO, Validate(&is_trusted));
-  EXPECT_FALSE(is_trusted);
-}
-
-TEST_F(AvbAtxValidateTest, GSKRollback) {
-  ops_.set_stored_rollback_indexes(
-      {{AVB_ATX_PIK_VERSION_LOCATION, 0},
-       {AVB_ATX_PSK_VERSION_LOCATION, 0},
-       {AVB_ATX_GSK_VERSION_LOCATION,
-        metadata_.google_signing_key_version + 1}});
-  bool is_trusted = true;
-  EXPECT_EQ(AVB_IO_RESULT_OK, Validate(&is_trusted));
-  EXPECT_FALSE(is_trusted);
-}
-
 // A fixture for testing avb_slot_verify() with ATX.
 class AvbAtxSlotVerifyTest : public BaseAvbToolTest, public FakeAvbOpsDelegate {
  public:
@@ -571,8 +540,7 @@
                                       {2, 0},
                                       {3, 0},
                                       {AVB_ATX_PIK_VERSION_LOCATION, 0},
-                                      {AVB_ATX_PSK_VERSION_LOCATION, 0},
-                                      {AVB_ATX_GSK_VERSION_LOCATION, 0}});
+                                      {AVB_ATX_PSK_VERSION_LOCATION, 0}});
     ops_.set_stored_is_device_unlocked(false);
   }
 
@@ -665,13 +633,13 @@
   std::string metadata_option = "--public_key_metadata=";
   metadata_option += kMetadataPath;
   GenerateVBMetaImage("vbmeta_a.img",
-                      "SHA256_RSA2048",
+                      "SHA512_RSA4096",
                       0,
-                      base::FilePath("test/data/testkey_rsa2048.pem"),
+                      base::FilePath("test/data/testkey_atx_psk.pem"),
                       metadata_option);
 
   ops_.set_expected_public_key(
-      PublicKeyAVB(base::FilePath("test/data/testkey_rsa2048.pem")));
+      PublicKeyAVB(base::FilePath("test/data/testkey_atx_psk.pem")));
 
   AvbSlotVerifyData* slot_data = NULL;
   const char* requested_partitions[] = {"boot", NULL};
diff --git a/test/avbtool_unittest.cc b/test/avbtool_unittest.cc
index 924dfbb..be53d55 100644
--- a/test/avbtool_unittest.cc
+++ b/test/avbtool_unittest.cc
@@ -1424,21 +1424,24 @@
 }
 
 TEST_F(AvbToolTest, MakeAtxPikCertificate) {
+  base::FilePath subject_path = testdir_.Append("tmp_subject");
+  ASSERT_TRUE(base::WriteFile(subject_path, "fake PIK subject", 16));
   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
   EXPECT_COMMAND(
       0,
-      "openssl pkey -pubout -in test/data/testkey_rsa2048.pem -out %s",
+      "openssl pkey -pubout -in test/data/testkey_atx_pik.pem -out %s",
       pubkey_path.value().c_str());
 
   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
   EXPECT_COMMAND(0,
                  "./avbtool make_atx_certificate"
-                 " --subject test/data/small_blob.bin"
+                 " --subject %s"
                  " --subject_key %s"
                  " --subject_key_version 42"
                  " --subject_is_intermediate_authority"
-                 " --authority_key test/data/testkey_rsa4096.pem"
+                 " --authority_key test/data/testkey_atx_prk.pem"
                  " --output %s",
+                 subject_path.value().c_str(),
                  pubkey_path.value().c_str(),
                  output_path.value().c_str());
 
@@ -1451,7 +1454,7 @@
   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
   EXPECT_COMMAND(
       0,
-      "openssl pkey -pubout -in test/data/testkey_rsa2048.pem -out %s",
+      "openssl pkey -pubout -in test/data/testkey_atx_psk.pem -out %s",
       pubkey_path.value().c_str());
 
   base::FilePath output_path = testdir_.Append("tmp_certificate.bin");
@@ -1460,7 +1463,7 @@
                  " --subject test/data/atx_product_id.bin"
                  " --subject_key %s"
                  " --subject_key_version 42"
-                 " --authority_key test/data/testkey_rsa2048.pem"
+                 " --authority_key test/data/testkey_atx_pik.pem"
                  " --output %s",
                  pubkey_path.value().c_str(),
                  output_path.value().c_str());
@@ -1474,7 +1477,7 @@
   base::FilePath pubkey_path = testdir_.Append("tmp_pubkey.pem");
   EXPECT_COMMAND(
       0,
-      "openssl pkey -pubout -in test/data/testkey_rsa4096.pem -out %s",
+      "openssl pkey -pubout -in test/data/testkey_atx_prk.pem -out %s",
       pubkey_path.value().c_str());
 
   base::FilePath output_path = testdir_.Append("tmp_attributes.bin");
@@ -1499,7 +1502,6 @@
       "./avbtool make_atx_metadata"
       " --intermediate_key_certificate test/data/atx_pik_certificate.bin"
       " --product_key_certificate test/data/atx_psk_certificate.bin"
-      " --google_key_version 42"
       " --output %s",
       output_path.value().c_str());
 
diff --git a/test/data/atx_metadata.bin b/test/data/atx_metadata.bin
index 3b53bbc..0915664 100644
--- a/test/data/atx_metadata.bin
+++ b/test/data/atx_metadata.bin
Binary files differ
diff --git a/test/data/atx_permanent_attributes.bin b/test/data/atx_permanent_attributes.bin
index be63c86..fe53db2 100644
--- a/test/data/atx_permanent_attributes.bin
+++ b/test/data/atx_permanent_attributes.bin
Binary files differ
diff --git a/test/data/atx_pik_certificate.bin b/test/data/atx_pik_certificate.bin
index d0b4a7b..6e01e6c 100644
--- a/test/data/atx_pik_certificate.bin
+++ b/test/data/atx_pik_certificate.bin
Binary files differ
diff --git a/test/data/atx_product_id.bin b/test/data/atx_product_id.bin
index d5648fa..59f5893 100644
--- a/test/data/atx_product_id.bin
+++ b/test/data/atx_product_id.bin
@@ -1 +1 @@
-t‹ùAö®÷ ìí=±]
\ No newline at end of file
+?8œË¾VÌ=л5…§Ò
\ No newline at end of file
diff --git a/test/data/atx_psk_certificate.bin b/test/data/atx_psk_certificate.bin
index abec3ce..6710ae4 100644
--- a/test/data/atx_psk_certificate.bin
+++ b/test/data/atx_psk_certificate.bin
Binary files differ
diff --git a/test/data/testkey_atx_pik.pem b/test/data/testkey_atx_pik.pem
new file mode 100644
index 0000000..5f34cb9
--- /dev/null
+++ b/test/data/testkey_atx_pik.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+WM8yjCL8U3+kfP4L6uIgmAuVcmbrX68=
+-----END PRIVATE KEY-----
diff --git a/test/data/testkey_atx_prk.pem b/test/data/testkey_atx_prk.pem
new file mode 100644
index 0000000..17a8cce
--- /dev/null
+++ b/test/data/testkey_atx_prk.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+MSKHJYIcbmEACtr9tALUhZo5SkjMLrQ=
+-----END PRIVATE KEY-----
diff --git a/test/data/testkey_atx_psk.pem b/test/data/testkey_atx_psk.pem
new file mode 100644
index 0000000..71bfebf
--- /dev/null
+++ b/test/data/testkey_atx_psk.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+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
+PqPOQDQM7f0JPuFGA9kFRaKUQygQckw=
+-----END PRIVATE KEY-----