// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cryptohome/bootlockbox/tpm2_nvspace_utility.h"

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <tpm_manager/common/mock_tpm_nvram_interface.h>
#include <trunks/mock_tpm_utility.h>
#include <trunks/trunks_factory_for_test.h>

using testing::_;
using testing::Invoke;
using testing::NiceMock;
using testing::Return;

namespace {

// A helper function to serialize a uint16_t.
std::string uint16_to_string(uint16_t value) {
  const char* bytes = reinterpret_cast<const char*>(&value);
  return std::string(bytes, sizeof(uint16_t));
}

}  // namespace

namespace cryptohome {

class TPM2NVSpaceUtilityTest : public testing::Test {
 public:
  void SetUp() override {
    factory_.set_tpm_utility(&mock_trunks_tpm_utility_);
    nvspace_utility_ = std::make_unique<TPM2NVSpaceUtility>(
        &mock_tpm_manager_nvram_, &factory_);
    nvspace_utility_->Initialize();
  }

 protected:
  NiceMock<tpm_manager::MockTpmNvramInterface> mock_tpm_manager_nvram_;
  trunks::TrunksFactoryForTest factory_;
  NiceMock<trunks::MockTpmUtility> mock_trunks_tpm_utility_;
  std::unique_ptr<TPM2NVSpaceUtility> nvspace_utility_;
};

TEST_F(TPM2NVSpaceUtilityTest, DefineNVSpaceSuccess) {
  EXPECT_CALL(mock_tpm_manager_nvram_, DefineSpace(_, _))
      .WillOnce(
          Invoke([](const tpm_manager::DefineSpaceRequest& request,
                    const tpm_manager::TpmNvramInterface::DefineSpaceCallback&
                        callback) {
            EXPECT_TRUE(request.has_index());
            EXPECT_EQ(kBootLockboxNVRamIndex, request.index());
            EXPECT_TRUE(request.has_size());
            EXPECT_EQ(kNVSpaceSize, request.size());
            tpm_manager::DefineSpaceReply reply;
            reply.set_result(tpm_manager::NVRAM_RESULT_SUCCESS);
            callback.Run(reply);
          }));
  EXPECT_TRUE(nvspace_utility_->DefineNVSpace());
}

TEST_F(TPM2NVSpaceUtilityTest, DefineNVSpaceFail) {
  EXPECT_CALL(mock_tpm_manager_nvram_, DefineSpace(_, _))
      .WillOnce(
          Invoke([](const tpm_manager::DefineSpaceRequest& request,
                    const tpm_manager::TpmNvramInterface::DefineSpaceCallback&
                        callback) {
            tpm_manager::DefineSpaceReply reply;
            reply.set_result(tpm_manager::NVRAM_RESULT_IPC_ERROR);
            callback.Run(reply);
          }));
  EXPECT_FALSE(nvspace_utility_->DefineNVSpace());
}

TEST_F(TPM2NVSpaceUtilityTest, DefineNVSpaceBeforeOwned) {
  EXPECT_CALL(mock_trunks_tpm_utility_,
              DefineNVSpace(kBootLockboxNVRamIndex, kNVSpaceSize, _,
                            kWellKnownPassword, "", _))
      .WillOnce(Return(trunks::TPM_RC_SUCCESS));
  EXPECT_TRUE(nvspace_utility_->DefineNVSpaceBeforeOwned());
}

TEST_F(TPM2NVSpaceUtilityTest, ReadNVSpaceLengthFail) {
  EXPECT_CALL(mock_trunks_tpm_utility_, ReadNVSpace(_, _, _, _, _, _))
      .WillOnce(
          Invoke([](uint32_t index, uint32_t offset, size_t num_bytes,
                    bool using_owner_authorization, std::string* nvram_data,
                    trunks::AuthorizationDelegate* delegate) -> trunks::TPM_RC {
            *nvram_data = uint16_to_string(1) /* version */ +
                          uint16_to_string(0) /* flags */ +
                          std::string(3, '\x3');
            return trunks::TPM_RC_SUCCESS;  // return success to trigger error.
          }));
  std::string data;
  NVSpaceState state;
  EXPECT_FALSE(nvspace_utility_->ReadNVSpace(&data, &state));
}

TEST_F(TPM2NVSpaceUtilityTest, ReadNVSpaceVersionFail) {
  EXPECT_CALL(mock_trunks_tpm_utility_, ReadNVSpace(_, _, _, _, _, _))
      .WillOnce(
          Invoke([](uint32_t index, uint32_t offset, size_t num_bytes,
                    bool using_owner_authorization, std::string* nvram_data,
                    trunks::AuthorizationDelegate* delegate) -> trunks::TPM_RC {
            BootLockboxNVSpace data;
            data.version = 2;
            *nvram_data =
                std::string(reinterpret_cast<char*>(&data), kNVSpaceSize);
            return trunks::TPM_RC_SUCCESS;
          }));
  std::string data;
  NVSpaceState state;
  EXPECT_FALSE(nvspace_utility_->ReadNVSpace(&data, &state));
}

TEST_F(TPM2NVSpaceUtilityTest, ReadNVSpaceSuccess) {
  std::string test_digest(SHA256_DIGEST_LENGTH, 'a');
  EXPECT_CALL(mock_trunks_tpm_utility_, ReadNVSpace(_, _, _, _, _, _))
      .WillOnce(Invoke(
          [test_digest](
              uint32_t index, uint32_t offset, size_t num_bytes,
              bool using_owner_authorization, std::string* nvram_data,
              trunks::AuthorizationDelegate* delegate) -> trunks::TPM_RC {
            BootLockboxNVSpace data;
            data.version = 1;
            data.flags = 0;
            memcpy(data.digest, test_digest.c_str(), SHA256_DIGEST_LENGTH);
            *nvram_data =
                std::string(reinterpret_cast<char*>(&data), kNVSpaceSize);
            return trunks::TPM_RC_SUCCESS;
          }));
  std::string data;
  NVSpaceState state;
  EXPECT_TRUE(nvspace_utility_->ReadNVSpace(&data, &state));
  EXPECT_EQ(data, test_digest);
}

TEST_F(TPM2NVSpaceUtilityTest, WriteNVSpaceSuccess) {
  std::string nvram_data(SHA256_DIGEST_LENGTH, 'a');
  EXPECT_CALL(mock_trunks_tpm_utility_,
              WriteNVSpace(kBootLockboxNVRamIndex, 0,
                           uint16_to_string(1) /* version */ +
                               uint16_to_string(0) /* flags */ + nvram_data,
                           false, false, _));
  EXPECT_TRUE(nvspace_utility_->WriteNVSpace(nvram_data));
}

TEST_F(TPM2NVSpaceUtilityTest, WriteNVSpaceInvalidLength) {
  std::string nvram_data = "data of invalid length";
  EXPECT_CALL(mock_trunks_tpm_utility_, WriteNVSpace(_, _, _, _, _, _))
      .Times(0);
  EXPECT_FALSE(nvspace_utility_->WriteNVSpace(nvram_data));
}

TEST_F(TPM2NVSpaceUtilityTest, LockNVSpace) {
  EXPECT_CALL(mock_trunks_tpm_utility_,
              LockNVSpace(kBootLockboxNVRamIndex, false, true, false, _));
  EXPECT_TRUE(nvspace_utility_->LockNVSpace());
}

}  // namespace cryptohome
