/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// Test that metadata encryption is working, via:
//
// - Correctness tests.  These test the standard metadata encryption formats
//   supported by Android R and higher via dm-default-key v2.
//
// - Randomness test.  This runs on all devices that use metadata encryption.
//
// The correctness tests create a temporary default-key mapping over the raw
// userdata partition, read from it, and verify that the data got decrypted
// correctly.  This only tests decryption, since this avoids having to find a
// region on disk that can safely be modified.  This should be good enough since
// the device wouldn't work anyway if decryption didn't invert encryption.
//
// Note that this temporary default-key mapping will overlap the device's "real"
// default-key mapping, if the device has one.  The kernel allows this.  The
// tests don't use a loopback device instead, since dm-default-key over a
// loopback device can't use the real inline encryption hardware.
//
// The correctness tests cover the following settings:
//
//    metadata_encryption=aes-256-xts
//    metadata_encryption=adiantum
//    metadata_encryption=aes-256-xts:wrappedkey_v0
//
// The tests don't check which one of those settings, if any, the device is
// actually using; they just try to test everything they can.
//
// These tests don't specifically test that file contents aren't encrypted
// twice.  That's already implied by the file-based encryption test cases,
// provided that the device actually has metadata encryption enabled.
//

#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <asm/byteorder.h>
#include <fcntl.h>
#include <fstab/fstab.h>
#include <gtest/gtest.h>
#include <libdm/dm.h>
#include <linux/types.h>
#include <stdlib.h>
#include <unistd.h>

#include <chrono>

#include "vts_kernel_encryption.h"

using namespace android::dm;

namespace android {
namespace kernel {

#define cpu_to_le64 __cpu_to_le64
#define le64_to_cpu __le64_to_cpu

// Alignment to use for direct I/O reads of block devices
static constexpr int kDirectIOAlignment = 4096;

// Assumed size of filesystem blocks, in bytes
static constexpr int kFilesystemBlockSize = 4096;

// Checks whether the kernel supports version 2 or higher of dm-default-key.
static bool IsDmDefaultKeyV2Supported(DeviceMapper &dm) {
  DmTargetTypeInfo info;
  if (!dm.GetTargetByName("default-key", &info)) {
    GTEST_LOG_(INFO) << "dm-default-key not enabled";
    return false;
  }
  if (!info.IsAtLeast(2, 0, 0)) {
    // The legacy version of dm-default-key (which was never supported by the
    // Android common kernels) used a vendor-specific on-disk format, so it's
    // not testable by a vendor-independent test.
    GTEST_LOG_(INFO) << "Detected legacy dm-default-key";
    return false;
  }
  return true;
}

// Reads |count| bytes from the beginning of |blk_device|, using direct I/O to
// avoid getting any stale cached data.  Direct I/O requires using a hardware
// sector size aligned buffer.
static bool ReadBlockDevice(const std::string &blk_device, size_t count,
                            std::vector<uint8_t> *data) {
  GTEST_LOG_(INFO) << "Reading " << count << " bytes from " << blk_device;
  std::unique_ptr<void, void (*)(void *)> buf_mem(
      aligned_alloc(kDirectIOAlignment, count), free);
  if (buf_mem == nullptr) {
    ADD_FAILURE() << "out of memory";
    return false;
  }
  uint8_t *buffer = static_cast<uint8_t *>(buf_mem.get());

  android::base::unique_fd fd(
      open(blk_device.c_str(), O_RDONLY | O_DIRECT | O_CLOEXEC));
  if (fd < 0) {
    ADD_FAILURE() << "Failed to open " << blk_device << Errno();
    return false;
  }
  if (!android::base::ReadFully(fd, buffer, count)) {
    ADD_FAILURE() << "Failed to read from " << blk_device << Errno();
    return false;
  }

  *data = std::vector<uint8_t>(buffer, buffer + count);
  return true;
}

class DmDefaultKeyTest : public ::testing::Test {
  // Filesystem whose underlying partition the test will use
  static constexpr const char *kTestMountpoint = "/data";

  // Size of the dm-default-key crypto sector size (data unit size) in bytes
  static constexpr int kCryptoSectorSize = 4096;

  // Size of the test data in crypto sectors
  static constexpr int kTestDataSectors = 256;

  // Size of the test data in bytes
  static constexpr int kTestDataBytes = kTestDataSectors * kCryptoSectorSize;

  // Device-mapper API sector size in bytes.
  // This is unrelated to the crypto sector size.
  static constexpr int kDmApiSectorSize = 512;

 protected:
  void SetUp() override;
  void TearDown() override;
  bool CreateTestDevice(const std::string &cipher,
                        const std::vector<uint8_t> &key, bool is_wrapped_key);
  void VerifyDecryption(const std::vector<uint8_t> &key, const Cipher &cipher);
  void DoTest(const std::string &cipher_string, const Cipher &cipher);
  std::string test_dm_device_name_;
  bool skip_test_ = false;
  DeviceMapper *dm_ = nullptr;
  std::string raw_blk_device_;
  std::string dm_device_path_;
};

// Test setup procedure.  Checks for the needed kernel support, finds the raw
// partition to use, and does other preparations.  skip_test_ is set to true if
// the test should be skipped.
void DmDefaultKeyTest::SetUp() {
  dm_ = &DeviceMapper::Instance();

  if (!IsDmDefaultKeyV2Supported(*dm_)) {
    int first_api_level;
    ASSERT_TRUE(GetFirstApiLevel(&first_api_level));
    // Devices launching with R or higher must support dm-default-key v2.
    ASSERT_LE(first_api_level, __ANDROID_API_Q__);
    GTEST_LOG_(INFO)
        << "Skipping test because dm-default-key v2 is unsupported";
    skip_test_ = true;
    return;
  }
  test_dm_device_name_ =
      android::base::StringPrintf("DmDefaultKeyTest.%d", getpid());

  FilesystemInfo fs_info;
  ASSERT_TRUE(GetFilesystemInfo(kTestMountpoint, &fs_info));
  raw_blk_device_ = fs_info.raw_blk_device;

  dm_->DeleteDevice(test_dm_device_name_.c_str());
}

void DmDefaultKeyTest::TearDown() { dm_->DeleteDevice(test_dm_device_name_); }

// Creates the test dm-default-key mapping using the given key and settings.
// If the dm device creation fails, then it is assumed the kernel doesn't
// support the given encryption settings, and a failure is not added.
bool DmDefaultKeyTest::CreateTestDevice(const std::string &cipher,
                                        const std::vector<uint8_t> &key,
                                        bool is_wrapped_key) {
  static_assert(kTestDataBytes % kDmApiSectorSize == 0);
  std::unique_ptr<DmTargetDefaultKey> target =
      std::make_unique<DmTargetDefaultKey>(0, kTestDataBytes / kDmApiSectorSize,
                                           cipher.c_str(), BytesToHex(key),
                                           raw_blk_device_, 0);
  target->SetSetDun();
  if (is_wrapped_key) target->SetWrappedKeyV0();

  DmTable table;
  if (!table.AddTarget(std::move(target))) {
    ADD_FAILURE() << "Failed to add default-key target to table";
    return false;
  }
  if (!table.valid()) {
    ADD_FAILURE() << "Device-mapper table failed to validate";
    return false;
  }
  if (!dm_->CreateDevice(test_dm_device_name_, table, &dm_device_path_,
                         std::chrono::seconds(5))) {
    GTEST_LOG_(INFO) << "Unable to create default-key mapping" << Errno()
                     << ".  Assuming that the encryption settings cipher=\""
                     << cipher << "\", is_wrapped_key=" << is_wrapped_key
                     << " are unsupported and skipping the test.";
    return false;
  }
  GTEST_LOG_(INFO) << "Created default-key mapping at " << dm_device_path_
                   << " using cipher=\"" << cipher
                   << "\", key=" << BytesToHex(key)
                   << ", is_wrapped_key=" << is_wrapped_key;
  return true;
}

void DmDefaultKeyTest::VerifyDecryption(const std::vector<uint8_t> &key,
                                        const Cipher &cipher) {
  std::vector<uint8_t> raw_data;
  std::vector<uint8_t> decrypted_data;

  ASSERT_TRUE(ReadBlockDevice(raw_blk_device_, kTestDataBytes, &raw_data));
  ASSERT_TRUE(
      ReadBlockDevice(dm_device_path_, kTestDataBytes, &decrypted_data));

  // Verify that the decrypted data encrypts to the raw data.

  GTEST_LOG_(INFO) << "Verifying correctness of decrypted data";

  // Initialize the IV for crypto sector 0.
  ASSERT_GE(cipher.ivsize(), sizeof(__le64));
  std::unique_ptr<__le64> iv(new (::operator new(cipher.ivsize())) __le64);
  memset(iv.get(), 0, cipher.ivsize());

  // Encrypt each sector.
  std::vector<uint8_t> encrypted_data(kTestDataBytes);
  static_assert(kTestDataBytes % kCryptoSectorSize == 0);
  for (size_t i = 0; i < kTestDataBytes; i += kCryptoSectorSize) {
    ASSERT_TRUE(cipher.Encrypt(key, reinterpret_cast<const uint8_t *>(iv.get()),
                               &decrypted_data[i], &encrypted_data[i],
                               kCryptoSectorSize));

    // Update the IV by incrementing the crypto sector number.
    *iv = cpu_to_le64(le64_to_cpu(*iv) + 1);
  }

  ASSERT_EQ(encrypted_data, raw_data);
}

void DmDefaultKeyTest::DoTest(const std::string &cipher_string,
                              const Cipher &cipher) {
  if (skip_test_) return;

  std::vector<uint8_t> key = GenerateTestKey(cipher.keysize());

  if (!CreateTestDevice(cipher_string, key, false)) return;

  VerifyDecryption(key, cipher);
}

// Tests dm-default-key parameters matching metadata_encryption=aes-256-xts.
TEST_F(DmDefaultKeyTest, TestAes256Xts) {
  DoTest("aes-xts-plain64", Aes256XtsCipher());
}

// Tests dm-default-key parameters matching metadata_encryption=adiantum.
TEST_F(DmDefaultKeyTest, TestAdiantum) {
  DoTest("xchacha12,aes-adiantum-plain64", AdiantumCipher());
}

// Tests dm-default-key parameters matching
// metadata_encryption=aes-256-xts:wrappedkey_v0.
TEST_F(DmDefaultKeyTest, TestHwWrappedKey) {
  if (skip_test_) return;

  std::vector<uint8_t> master_key, exported_key;
  if (!CreateHwWrappedKey(&master_key, &exported_key)) return;

  if (!CreateTestDevice("aes-xts-plain64", exported_key, true)) return;

  std::vector<uint8_t> enc_key;
  ASSERT_TRUE(DeriveHwWrappedEncryptionKey(master_key, &enc_key));

  VerifyDecryption(enc_key, Aes256XtsCipher());
}

// Tests that if the device uses metadata encryption, then the first
// kFilesystemBlockSize bytes of the userdata partition appear random.  For ext4
// and f2fs, this block should contain the filesystem superblock; it therefore
// should be initialized and metadata-encrypted.  Ideally we'd check additional
// blocks too, but that would require awareness of the filesystem structure.
//
// This isn't as strong a test as the correctness tests, but it's useful because
// it applies regardless of the encryption format and key.  Thus it runs even on
// old devices, including ones that used a vendor-specific encryption format.
TEST(MetadataEncryptionTest, TestRandomness) {
  constexpr const char *mountpoint = "/data";

  android::fs_mgr::Fstab fstab;
  ASSERT_TRUE(android::fs_mgr::ReadDefaultFstab(&fstab));
  const fs_mgr::FstabEntry *entry = GetEntryForMountPoint(&fstab, mountpoint);
  ASSERT_TRUE(entry != nullptr);

  if (entry->metadata_key_dir.empty()) {
    int first_api_level;
    ASSERT_TRUE(GetFirstApiLevel(&first_api_level));
    ASSERT_LE(first_api_level, __ANDROID_API_Q__)
        << "Metadata encryption is required";
    GTEST_LOG_(INFO)
        << "Skipping test because device doesn't use metadata encryption";
    return;
  }

  GTEST_LOG_(INFO) << "Verifying randomness of ciphertext";
  std::vector<uint8_t> raw_data;
  FilesystemInfo fs_info;
  ASSERT_TRUE(GetFilesystemInfo(mountpoint, &fs_info));
  ASSERT_TRUE(
      ReadBlockDevice(fs_info.raw_blk_device, kFilesystemBlockSize, &raw_data));
  ASSERT_TRUE(VerifyDataRandomness(raw_data));
}

}  // namespace kernel
}  // namespace android
