/*
 * 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.
 */

#include <iostream>

#include <endian.h>
#include <inttypes.h>
#include <string.h>

#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>

#include <libavb/libavb.h>

#include "avb_unittest_util.h"

namespace avb {

class VerifyTest : public BaseAvbToolTest {
 public:
  VerifyTest() {}

 protected:
  // Helper function for ModificationDetection test. Modifies
  // boot_image_ in a number of places in the sub-array at |offset| of
  // size |length| and checks that avb_vbmeta_image_verify() returns
  // |expected_result|.
  bool test_modification(AvbVBMetaVerifyResult expected_result,
                         size_t offset,
                         size_t length);
};

TEST_F(VerifyTest, BootImageStructSize) {
  EXPECT_EQ(256UL, sizeof(AvbVBMetaImageHeader));
}

TEST_F(VerifyTest, CheckSHA256RSA2048) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, CheckSHA256RSA4096) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA4096",
                      0,
                      base::FilePath("test/data/testkey_rsa4096.pem"));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, CheckSHA256RSA8192) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA8192",
                      0,
                      base::FilePath("test/data/testkey_rsa8192.pem"));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, CheckSHA512RSA2048) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA512_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, CheckSHA512RSA4096) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA512_RSA4096",
                      0,
                      base::FilePath("test/data/testkey_rsa4096.pem"));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, CheckSHA512RSA8192) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA512_RSA8192",
                      0,
                      base::FilePath("test/data/testkey_rsa8192.pem"));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, CheckUnsigned) {
  GenerateVBMetaImage("vbmeta.img", "", 0, base::FilePath(""));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK_NOT_SIGNED,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, CheckBiggerLength) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));
  // Check that it's OK if we pass a bigger length than what the
  // header indicates.
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size() + 8192, NULL, NULL));
}

TEST_F(VerifyTest, BadMagic) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));
  vbmeta_image_[0] = 'Z';
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, MajorVersionCheck) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  // Bail if it's a different major version.
  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());
  h->required_libavb_version_major = htobe32(1 + AVB_VERSION_MAJOR);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, MinorVersionCheck) {
  GenerateVBMetaImage("vbmeta.img", "", 0, base::FilePath(""));

  // Bail if required_libavb_version_minor exceeds our libavb version.
  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());
  h->required_libavb_version_minor = htobe32(1 + AVB_VERSION_MINOR);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_UNSUPPORTED_VERSION,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, NulTerminatedReleaseString) {
  GenerateVBMetaImage("vbmeta.img", "", 0, base::FilePath(""));

  // Bail if |release_string| isn't NUL-terminated.
  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());
  for (size_t n = 0; n < AVB_RELEASE_STRING_SIZE; n++) {
    h->release_string[n] = 'a';
  }
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, BlockSizesAddUpToLessThanLength) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());
  AvbVBMetaImageHeader backup = *h;

  // Check that the sum of the two block lengths is less than passed
  // in size. Use a size that's a multiple of 64 to avoid failure on
  // earlier check.
  uint64_t size = vbmeta_image_.size() & (~0x3f);

  h->authentication_data_block_size = htobe64(size);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
  *h = backup;

  h->auxiliary_data_block_size = htobe64(size);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
  *h = backup;

  // Overflow checks - choose overflow candidate so it's a multiple of
  // 64 otherwise we'll fail on an earlier check.
  size = 0xffffffffffffffc0UL;

  h->authentication_data_block_size = htobe64(size);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
  *h = backup;

  h->auxiliary_data_block_size = htobe64(size);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
  *h = backup;

  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, BlockSizesMultipleOf64) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());
  AvbVBMetaImageHeader backup = *h;

  h->authentication_data_block_size =
      htobe32(be32toh(h->authentication_data_block_size) - 32);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size() - 32, NULL, NULL));
  *h = backup;

  h->auxiliary_data_block_size =
      htobe32(be32toh(h->auxiliary_data_block_size) - 32);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size() - 32, NULL, NULL));
  *h = backup;

  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, HashOutOfBounds) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());

  // Check we catch when hash data goes out of bounds.
  h->hash_offset = htobe64(4);
  h->hash_size = htobe64(be64toh(h->authentication_data_block_size));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));

  // Overflow checks.
  h->hash_offset = htobe64(4);
  h->hash_size = htobe64(0xfffffffffffffffeUL);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, SignatureOutOfBounds) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());

  // Check we catch when signature data goes out of bounds.
  h->signature_offset = htobe64(4);
  h->signature_size = htobe64(be64toh(h->authentication_data_block_size));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));

  // Overflow checks.
  h->signature_offset = htobe64(4);
  h->signature_size = htobe64(0xfffffffffffffffeUL);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, PublicKeyOutOfBounds) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());

  // Check we catch when public key data goes out of bounds.
  h->public_key_offset = htobe64(4);
  h->public_key_size = htobe64(be64toh(h->auxiliary_data_block_size));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));

  // Overflow checks.
  h->public_key_offset = htobe64(4);
  h->public_key_size = htobe64(0xfffffffffffffffeUL);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, PublicKeyMetadataOutOfBounds) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());

  // Check we catch when public key metadata data goes out of bounds.
  h->public_key_metadata_offset = htobe64(4);
  h->public_key_metadata_size = htobe64(be64toh(h->auxiliary_data_block_size));
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));

  // Overflow checks.
  h->public_key_metadata_offset = htobe64(4);
  h->public_key_metadata_size = htobe64(0xfffffffffffffffeUL);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, InvalidAlgorithmField) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());
  AvbVBMetaImageHeader backup = *h;

  // Check we bail on unknown algorithm.
  h->algorithm_type = htobe32(_AVB_ALGORITHM_NUM_TYPES);
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
  *h = backup;
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

TEST_F(VerifyTest, PublicKeyBlockTooSmall) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  AvbVBMetaImageHeader* h =
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data());
  AvbVBMetaImageHeader backup = *h;

  // Check we bail if the auxiliary data block is too small.
  uint64_t change = be64toh(h->auxiliary_data_block_size) - 64;
  h->auxiliary_data_block_size = htobe64(change);
  EXPECT_EQ(
      AVB_VBMETA_VERIFY_RESULT_INVALID_VBMETA_HEADER,
      avb_vbmeta_image_verify(
          vbmeta_image_.data(), vbmeta_image_.size() - change, NULL, NULL));
  *h = backup;
  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));
}

bool VerifyTest::test_modification(AvbVBMetaVerifyResult expected_result,
                                   size_t offset,
                                   size_t length) {
  uint8_t* d = reinterpret_cast<uint8_t*>(vbmeta_image_.data());
  const int kNumCheckpoints = 16;

  // Test |kNumCheckpoints| modifications in the start, middle, and
  // end of given sub-array.
  for (int n = 0; n <= kNumCheckpoints; n++) {
    size_t o = std::min(length * n / kNumCheckpoints, length - 1) + offset;
    d[o] ^= 0x80;
    AvbVBMetaVerifyResult result = avb_vbmeta_image_verify(
        vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL);
    d[o] ^= 0x80;
    if (result != expected_result) {
      return false;
    }
  }

  return true;
}

TEST_F(VerifyTest, ModificationDetection) {
  GenerateVBMetaImage("vbmeta.img",
                      "SHA256_RSA2048",
                      0,
                      base::FilePath("test/data/testkey_rsa2048.pem"));

  EXPECT_EQ(AVB_VBMETA_VERIFY_RESULT_OK,
            avb_vbmeta_image_verify(
                vbmeta_image_.data(), vbmeta_image_.size(), NULL, NULL));

  AvbVBMetaImageHeader h;
  avb_vbmeta_image_header_to_host_byte_order(
      reinterpret_cast<AvbVBMetaImageHeader*>(vbmeta_image_.data()), &h);

  size_t header_block_offset = 0;
  size_t authentication_block_offset =
      header_block_offset + sizeof(AvbVBMetaImageHeader);
  size_t auxiliary_block_offset =
      authentication_block_offset + h.authentication_data_block_size;

  // Ensure we detect modification of the header data block. Do this
  // in a field that's not validated so INVALID_VBMETA_HEADER
  // isn't returned.
  EXPECT_TRUE(test_modification(
      AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH,
      offsetof(AvbVBMetaImageHeader, reserved),
      sizeof(AvbVBMetaImageHeader) - offsetof(AvbVBMetaImageHeader, reserved)));
  // Also check the |reserved| field.
  EXPECT_TRUE(test_modification(AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH,
                                offsetof(AvbVBMetaImageHeader, reserved),
                                sizeof(AvbVBMetaImageHeader().reserved)));

  // Ensure we detect modifications in the auxiliary data block.
  EXPECT_TRUE(test_modification(AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH,
                                auxiliary_block_offset,
                                h.auxiliary_data_block_size));

  // Modifications in the hash part of the Authentication data block
  // should also yield HASH_MISMATCH. This is because the hash check
  // compares the calculated hash against the stored hash.
  EXPECT_TRUE(test_modification(AVB_VBMETA_VERIFY_RESULT_HASH_MISMATCH,
                                authentication_block_offset + h.hash_offset,
                                h.hash_size));

  // Modifications in the signature part of the Authentication data
  // block, should not cause a hash mismatch ... but will cause a
  // signature mismatch.
  EXPECT_TRUE(
      test_modification(AVB_VBMETA_VERIFY_RESULT_SIGNATURE_MISMATCH,
                        authentication_block_offset + h.signature_offset,
                        h.signature_size));

  // Mofications outside the hash and signature parts of the
  // Authentication data block are not detected. This is because it's
  // not part of the hash calculation.
  uint64_t offset = h.signature_offset + h.signature_size;
  ASSERT_LT(h.hash_offset, h.signature_offset);
  ASSERT_LT(offset + 1, h.authentication_data_block_size);
  EXPECT_TRUE(test_modification(AVB_VBMETA_VERIFY_RESULT_OK,
                                authentication_block_offset + offset,
                                h.authentication_data_block_size - offset));
}

TEST_F(VerifyTest, VBMetaHeaderByteswap) {
  AvbVBMetaImageHeader h;
  AvbVBMetaImageHeader s;
  uint32_t n32;
  uint64_t n64;

  n32 = 0x11223344;
  n64 = 0x1122334455667788;

  h.required_libavb_version_major = htobe32(n32);
  n32++;
  h.required_libavb_version_minor = htobe32(n32);
  n32++;
  h.authentication_data_block_size = htobe64(n64);
  n64++;
  h.auxiliary_data_block_size = htobe64(n64);
  n64++;
  h.algorithm_type = htobe32(n32);
  n32++;
  h.hash_offset = htobe64(n64);
  n64++;
  h.hash_size = htobe64(n64);
  n64++;
  h.signature_offset = htobe64(n64);
  n64++;
  h.signature_size = htobe64(n64);
  n64++;
  h.public_key_offset = htobe64(n64);
  n64++;
  h.public_key_size = htobe64(n64);
  n64++;
  h.public_key_metadata_offset = htobe64(n64);
  n64++;
  h.public_key_metadata_size = htobe64(n64);
  n64++;
  h.descriptors_offset = htobe64(n64);
  n64++;
  h.descriptors_size = htobe64(n64);
  n64++;
  h.rollback_index = htobe64(n64);
  n64++;
  h.flags = htobe32(n32);
  n32++;

  avb_vbmeta_image_header_to_host_byte_order(&h, &s);

  n32 = 0x11223344;
  n64 = 0x1122334455667788;

  EXPECT_EQ(n32, s.required_libavb_version_major);
  n32++;
  EXPECT_EQ(n32, s.required_libavb_version_minor);
  n32++;
  EXPECT_EQ(n64, s.authentication_data_block_size);
  n64++;
  EXPECT_EQ(n64, s.auxiliary_data_block_size);
  n64++;
  EXPECT_EQ(n32, s.algorithm_type);
  n32++;
  EXPECT_EQ(n64, s.hash_offset);
  n64++;
  EXPECT_EQ(n64, s.hash_size);
  n64++;
  EXPECT_EQ(n64, s.signature_offset);
  n64++;
  EXPECT_EQ(n64, s.signature_size);
  n64++;
  EXPECT_EQ(n64, s.public_key_offset);
  n64++;
  EXPECT_EQ(n64, s.public_key_size);
  n64++;
  EXPECT_EQ(n64, s.public_key_metadata_offset);
  n64++;
  EXPECT_EQ(n64, s.public_key_metadata_size);
  n64++;
  EXPECT_EQ(n64, s.descriptors_offset);
  n64++;
  EXPECT_EQ(n64, s.descriptors_size);
  n64++;
  EXPECT_EQ(n64, s.rollback_index);
  n64++;
  EXPECT_EQ(n32, s.flags);
  n32++;

  // If new fields are added, the following will fail. This is to
  // remind that byteswapping code (in avb_util.c) and unittests for
  // this should be updated.
  static_assert(offsetof(AvbVBMetaImageHeader, reserved) == 176,
                "Remember to unittest byteswapping of newly added fields");
}

}  // namespace avb