/*
 * Copyright (C) 2016 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.
 */

#define LOG_TAG "gatekeeper_hidl_hal_test"

#include <algorithm>
#include <cmath>
#include <string>
#include <vector>

#include <inttypes.h>
#include <unistd.h>

#include <gtest/gtest.h>
#include <hardware/hw_auth_token.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>

#include <android/log.h>
#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
#include <android/hardware/gatekeeper/1.0/types.h>

#include <log/log.h>

using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::gatekeeper::V1_0::IGatekeeper;
using ::android::hardware::gatekeeper::V1_0::GatekeeperResponse;
using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

struct GatekeeperRequest {
  uint32_t uid;
  uint64_t challenge;
  hidl_vec<uint8_t> curPwdHandle;
  hidl_vec<uint8_t> curPwd;
  hidl_vec<uint8_t> newPwd;
  GatekeeperRequest() : uid(0), challenge(0) {}
};

// ASSERT_* macros generate return "void" internally
// we have to use EXPECT_* if we return anything but "void"
static const hw_auth_token_t *toAuthToken(GatekeeperResponse &rsp) {
  const hw_auth_token_t *auth_token =
      reinterpret_cast<hw_auth_token_t *>(rsp.data.data());
  const size_t auth_token_size = rsp.data.size();

  EXPECT_NE(nullptr, auth_token);
  EXPECT_EQ(sizeof(hw_auth_token_t), auth_token_size);

  if (auth_token != nullptr && auth_token_size >= sizeof(*auth_token)) {
    // these are in network order: translate to host
    uint32_t auth_type = ntohl(auth_token->authenticator_type);
    uint64_t auth_tstamp = ntohq(auth_token->timestamp);

    EXPECT_EQ(HW_AUTH_PASSWORD, auth_type);
    EXPECT_NE(UINT64_C(~0), auth_tstamp);
    EXPECT_EQ(HW_AUTH_TOKEN_VERSION, auth_token->version);
    //        EXPECT_NE(UINT64_C(0), auth_token->authenticator_id);
    ALOGI("Authenticator ID: %016" PRIX64, auth_token->authenticator_id);
    EXPECT_NE(UINT32_C(0), auth_token->user_id);
  }
  return auth_token;
}

// The main test class for Gatekeeper HIDL HAL.
class GatekeeperHidlTest : public ::testing::TestWithParam<std::string> {
 protected:
  void setUid(uint32_t uid) { uid_ = uid; }

  void doEnroll(GatekeeperRequest &req, GatekeeperResponse &rsp) {
    while (true) {
      auto ret = gatekeeper_->enroll(
          uid_, req.curPwdHandle, req.curPwd, req.newPwd,
          [&rsp](const GatekeeperResponse &cbRsp) { rsp = cbRsp; });
      ASSERT_TRUE(ret.isOk());
      if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
      ALOGI("%s: got retry code; retrying in 1 sec", __func__);
      sleep(1);
    }
  }

  void doVerify(GatekeeperRequest &req, GatekeeperResponse &rsp) {
    while (true) {
      auto ret = gatekeeper_->verify(
          uid_, req.challenge, req.curPwdHandle, req.newPwd,
          [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
      ASSERT_TRUE(ret.isOk());
      if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
      ALOGI("%s: got retry code; retrying in 1 sec", __func__);
      sleep(1);
    }
  }

  void doDeleteUser(GatekeeperResponse &rsp) {
    while (true) {
      auto ret = gatekeeper_->deleteUser(
          uid_, [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
      ASSERT_TRUE(ret.isOk());
      if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
      ALOGI("%s: got retry code; retrying in 1 sec", __func__);
      sleep(1);
    }
  }

  void doDeleteAllUsers(GatekeeperResponse &rsp) {
    while (true) {
      auto ret = gatekeeper_->deleteAllUsers(
          [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
      ASSERT_TRUE(ret.isOk());
      if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
      ALOGI("%s: got retry code; retrying in 1 sec", __func__);
      sleep(1);
    }
  }

  void generatePassword(hidl_vec<uint8_t> &password, uint8_t seed) {
    password.resize(16);
    memset(password.data(), seed, password.size());
  }

  void checkEnroll(GatekeeperResponse &rsp, bool expectSuccess) {
    if (expectSuccess) {
      EXPECT_EQ(GatekeeperStatusCode::STATUS_OK, rsp.code);
      EXPECT_NE(nullptr, rsp.data.data());
      EXPECT_GT(rsp.data.size(), UINT32_C(0));
    } else {
      EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, rsp.code);
      EXPECT_EQ(UINT32_C(0), rsp.data.size());
    }
  }

  void checkVerify(GatekeeperResponse &rsp, uint64_t challenge,
                   bool expectSuccess) {
    if (expectSuccess) {
      EXPECT_GE(rsp.code, GatekeeperStatusCode::STATUS_OK);
      EXPECT_LE(rsp.code, GatekeeperStatusCode::STATUS_REENROLL);

      const hw_auth_token_t *auth_token = toAuthToken(rsp);
      ASSERT_NE(nullptr, auth_token);
      EXPECT_EQ(challenge, auth_token->challenge);
    } else {
      EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, rsp.code);
      EXPECT_EQ(UINT32_C(0), rsp.data.size());
    }
  }

  void enrollNewPassword(hidl_vec<uint8_t> &password, GatekeeperResponse &rsp,
                         bool expectSuccess) {
    GatekeeperRequest req;
    req.newPwd.setToExternal(password.data(), password.size());
    doEnroll(req, rsp);
    checkEnroll(rsp, expectSuccess);
  }

  void verifyPassword(hidl_vec<uint8_t> &password,
                      hidl_vec<uint8_t> &passwordHandle, uint64_t challenge,
                      GatekeeperResponse &verifyRsp, bool expectSuccess) {
    GatekeeperRequest verifyReq;

    // build verify request for the same password (we want it to succeed)
    verifyReq.newPwd = password;
    // use enrolled password handle we've got
    verifyReq.curPwdHandle = passwordHandle;
    verifyReq.challenge = challenge;
    doVerify(verifyReq, verifyRsp);
    checkVerify(verifyRsp, challenge, expectSuccess);
  }

 protected:
  sp<IGatekeeper> gatekeeper_;
  uint32_t uid_;

 public:
  GatekeeperHidlTest() : uid_(0) {}
  virtual void SetUp() override {
    GatekeeperResponse rsp;
    gatekeeper_ = IGatekeeper::getService(GetParam());
    ASSERT_NE(nullptr, gatekeeper_.get());
    doDeleteAllUsers(rsp);
  }

  virtual void TearDown() override {
    GatekeeperResponse rsp;
    doDeleteAllUsers(rsp);
  }
};

/**
 * Ensure we can enroll new password
 */
TEST_P(GatekeeperHidlTest, EnrollSuccess) {
  hidl_vec<uint8_t> password;
  GatekeeperResponse rsp;
  ALOGI("Testing Enroll (expected success)");
  generatePassword(password, 0);
  enrollNewPassword(password, rsp, true);
  ALOGI("Testing Enroll done");
}

/**
 * Ensure we can not enroll empty password
 */
TEST_P(GatekeeperHidlTest, EnrollNoPassword) {
  hidl_vec<uint8_t> password;
  GatekeeperResponse rsp;
  ALOGI("Testing Enroll (expected failure)");
  enrollNewPassword(password, rsp, false);
  ALOGI("Testing Enroll done");
}

/**
 * Ensure we can successfully verify previously enrolled password
 */
TEST_P(GatekeeperHidlTest, VerifySuccess) {
  GatekeeperResponse enrollRsp;
  GatekeeperResponse verifyRsp;
  hidl_vec<uint8_t> password;

  ALOGI("Testing Enroll+Verify (expected success)");
  generatePassword(password, 0);
  enrollNewPassword(password, enrollRsp, true);
  verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
  ALOGI("Testing Enroll+Verify done");
}

/**
 * Ensure we can securely update password (keep the same
 * secure user_id) if we prove we know old password
 */
TEST_P(GatekeeperHidlTest, TrustedReenroll) {
  GatekeeperResponse enrollRsp;
  GatekeeperRequest reenrollReq;
  GatekeeperResponse reenrollRsp;
  GatekeeperResponse verifyRsp;
  GatekeeperResponse reenrollVerifyRsp;
  hidl_vec<uint8_t> password;
  hidl_vec<uint8_t> newPassword;

  generatePassword(password, 0);

  ALOGI("Testing Trusted Reenroll (expected success)");
  enrollNewPassword(password, enrollRsp, true);
  verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
  ALOGI("Primary Enroll+Verify done");

  generatePassword(newPassword, 1);
  reenrollReq.newPwd.setToExternal(newPassword.data(), newPassword.size());
  reenrollReq.curPwd.setToExternal(password.data(), password.size());
  reenrollReq.curPwdHandle.setToExternal(enrollRsp.data.data(),
                                         enrollRsp.data.size());

  doEnroll(reenrollReq, reenrollRsp);
  checkEnroll(reenrollRsp, true);
  verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
  ALOGI("Trusted ReEnroll+Verify done");

  const hw_auth_token_t *first = toAuthToken(verifyRsp);
  const hw_auth_token_t *second = toAuthToken(reenrollVerifyRsp);
  if (first != nullptr && second != nullptr) {
    EXPECT_EQ(first->user_id, second->user_id);
  }
  ALOGI("Testing Trusted Reenroll done");
}

/**
 * Ensure we can update password (and get new
 * secure user_id) if we don't know old password
 */
TEST_P(GatekeeperHidlTest, UntrustedReenroll) {
  GatekeeperResponse enrollRsp;
  GatekeeperResponse reenrollRsp;
  GatekeeperResponse verifyRsp;
  GatekeeperResponse reenrollVerifyRsp;
  hidl_vec<uint8_t> password;
  hidl_vec<uint8_t> newPassword;

  ALOGI("Testing Untrusted Reenroll (expected success)");
  generatePassword(password, 0);
  enrollNewPassword(password, enrollRsp, true);
  verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
  ALOGI("Primary Enroll+Verify done");

  generatePassword(newPassword, 1);
  enrollNewPassword(newPassword, reenrollRsp, true);
  verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
  ALOGI("Untrusted ReEnroll+Verify done");

  const hw_auth_token_t *first = toAuthToken(verifyRsp);
  const hw_auth_token_t *second = toAuthToken(reenrollVerifyRsp);
  if (first != nullptr && second != nullptr) {
    EXPECT_NE(first->user_id, second->user_id);
  }
  ALOGI("Testing Untrusted Reenroll done");
}

/**
 * Ensure we dont get successful verify with invalid data
 */
TEST_P(GatekeeperHidlTest, VerifyNoData) {
  hidl_vec<uint8_t> password;
  hidl_vec<uint8_t> passwordHandle;
  GatekeeperResponse verifyRsp;

  ALOGI("Testing Verify (expected failure)");
  verifyPassword(password, passwordHandle, 0, verifyRsp, false);
  EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, verifyRsp.code);
  ALOGI("Testing Verify done");
}

/**
 * Ensure we can not verify password after we enrolled it and then deleted user
 */
TEST_P(GatekeeperHidlTest, DeleteUserTest) {
  hidl_vec<uint8_t> password;
  GatekeeperResponse enrollRsp;
  GatekeeperResponse verifyRsp;
  GatekeeperResponse delRsp;
  ALOGI("Testing deleteUser (expected success)");
  setUid(10001);
  generatePassword(password, 0);
  enrollNewPassword(password, enrollRsp, true);
  verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
  ALOGI("Enroll+Verify done");
  doDeleteUser(delRsp);
  EXPECT_EQ(UINT32_C(0), delRsp.data.size());
  EXPECT_TRUE(delRsp.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
              delRsp.code == GatekeeperStatusCode::STATUS_OK);
  ALOGI("DeleteUser done");
  if (delRsp.code == GatekeeperStatusCode::STATUS_OK) {
    verifyPassword(password, enrollRsp.data, 0, verifyRsp, false);
    EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, verifyRsp.code);
    ALOGI("Verify after Delete done (must fail)");
  }
  ALOGI("Testing deleteUser done: rsp=%" PRIi32, delRsp.code);
}

/**
 * Ensure we can not delete a user that does not exist
 */
TEST_P(GatekeeperHidlTest, DeleteInvalidUserTest) {
  hidl_vec<uint8_t> password;
  GatekeeperResponse enrollRsp;
  GatekeeperResponse verifyRsp;
  GatekeeperResponse delRsp1;
  GatekeeperResponse delRsp2;
  ALOGI("Testing deleteUser (expected failure)");
  setUid(10002);
  generatePassword(password, 0);
  enrollNewPassword(password, enrollRsp, true);
  verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
  ALOGI("Enroll+Verify done");

  // Delete the user
  doDeleteUser(delRsp1);
  EXPECT_EQ(UINT32_C(0), delRsp1.data.size());
  EXPECT_TRUE(delRsp1.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
              delRsp1.code == GatekeeperStatusCode::STATUS_OK);

  // Delete the user again
  doDeleteUser(delRsp2);
  EXPECT_EQ(UINT32_C(0), delRsp2.data.size());
  EXPECT_TRUE(delRsp2.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
              delRsp2.code == GatekeeperStatusCode::ERROR_GENERAL_FAILURE);
  ALOGI("DeleteUser done");
  ALOGI("Testing deleteUser done: rsp=%" PRIi32, delRsp2.code);
}

/**
 * Ensure we can not verify passwords after we enrolled them and then deleted
 * all users
 */
TEST_P(GatekeeperHidlTest, DeleteAllUsersTest) {
  struct UserData {
    uint32_t userId;
    hidl_vec<uint8_t> password;
    GatekeeperResponse enrollRsp;
    GatekeeperResponse verifyRsp;
    UserData(int id) { userId = id; }
  } users[3]{10001, 10002, 10003};
  GatekeeperResponse delAllRsp;
  ALOGI("Testing deleteAllUsers (expected success)");

  // enroll multiple users
  for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
    setUid(users[i].userId);
    generatePassword(users[i].password, (i % 255) + 1);
    enrollNewPassword(users[i].password, users[i].enrollRsp, true);
  }
  ALOGI("Multiple users enrolled");

  // verify multiple users
  for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
    setUid(users[i].userId);
    verifyPassword(users[i].password, users[i].enrollRsp.data, 0,
                   users[i].verifyRsp, true);
  }
  ALOGI("Multiple users verified");

  doDeleteAllUsers(delAllRsp);
  EXPECT_EQ(UINT32_C(0), delAllRsp.data.size());
  EXPECT_TRUE(delAllRsp.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
              delAllRsp.code == GatekeeperStatusCode::STATUS_OK);
  ALOGI("All users deleted");

  if (delAllRsp.code == GatekeeperStatusCode::STATUS_OK) {
    // verify multiple users after they are deleted; all must fail
    for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
      setUid(users[i].userId);
      verifyPassword(users[i].password, users[i].enrollRsp.data, 0,
                     users[i].verifyRsp, false);
      EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE,
                users[i].verifyRsp.code);
    }
    ALOGI("Multiple users verified after delete (all must fail)");
  }

  ALOGI("Testing deleteAllUsers done: rsp=%" PRIi32, delAllRsp.code);
}

INSTANTIATE_TEST_SUITE_P(
        PerInstance, GatekeeperHidlTest,
        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGatekeeper::descriptor)),
        android::hardware::PrintInstanceNameToString);
