// Copyright (c) 2012 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.

// Contains the implementation of class Pkcs11Init.

#include "cryptohome/pkcs11_init.h"

#include <memory>
#include <string.h>

#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/stl_util.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/cryptohome.h>
#include <chaps/isolate.h>
#include <chaps/token_manager_client.h>
#include <errno.h>

using base::FilePath;

namespace cryptohome {

// Static members of Pkcs11Init
constexpr char Pkcs11Init::kDefaultPin[];
constexpr char Pkcs11Init::kDefaultSystemLabel[];
constexpr char Pkcs11Init::kDefaultUserLabelPrefix[];

Pkcs11Init::Pkcs11Init()
    : default_platform_(new Platform), platform_(default_platform_.get()) {}

Pkcs11Init::~Pkcs11Init() {}

void Pkcs11Init::GetTpmTokenInfo(std::string* OUT_label,
                                 std::string* OUT_user_pin) {
  *OUT_label = kDefaultSystemLabel;
  *OUT_user_pin = kDefaultPin;
}

void Pkcs11Init::GetTpmTokenInfoForUser(const std::string& username,
                                        std::string* OUT_label,
                                        std::string* OUT_user_pin) {
  *OUT_label = GetTpmTokenLabelForUser(username);
  *OUT_user_pin = kDefaultPin;
}

std::string Pkcs11Init::GetTpmTokenLabelForUser(const std::string& username) {
  // Use a truncated sanitized username in the token label so a label collision
  // is extremely unlikely.
  return std::string(kDefaultUserLabelPrefix) +
         brillo::cryptohome::home::SanitizeUserName(username).substr(0, 16);
}

bool Pkcs11Init::GetTpmTokenSlotForPath(const FilePath& path,
                                        CK_SLOT_ID_PTR slot) {
  CK_RV rv;
  rv = C_Initialize(NULL);
  if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
    LOG(WARNING) << __func__ << ": C_Initialize failed.";
    return false;
  }
  CK_ULONG num_slots = 0;
  rv = C_GetSlotList(CK_TRUE, NULL, &num_slots);
  if (rv != CKR_OK) {
    LOG(WARNING) << __func__ << ": C_GetSlotList(NULL) failed.";
    return false;
  }
  std::unique_ptr<CK_SLOT_ID[]> slot_list(new CK_SLOT_ID[num_slots]);
  rv = C_GetSlotList(CK_TRUE, slot_list.get(), &num_slots);
  if (rv != CKR_OK) {
    LOG(WARNING) << __func__ << ": C_GetSlotList failed.";
    return false;
  }
  chaps::TokenManagerClient token_manager;
  for (CK_ULONG i = 0; i < num_slots; ++i) {
    FilePath slot_path;
    if (token_manager.GetTokenPath(
            chaps::IsolateCredentialManager::GetDefaultIsolateCredential(),
            slot_list[i], &slot_path) &&
        (path == slot_path)) {
      *slot = slot_list[i];
      return true;
    }
  }
  LOG(WARNING) << __func__ << ": Path not found.";
  return false;
}

bool Pkcs11Init::IsUserTokenOK() {
  CK_RV rv;
  rv = C_Initialize(NULL);
  if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
    LOG(WARNING) << __func__ << ": C_Initialize failed.";
    return false;
  }
  CK_ULONG num_slots = 0;
  rv = C_GetSlotList(CK_TRUE, NULL, &num_slots);
  if (rv != CKR_OK) {
    LOG(WARNING) << __func__ << ": C_GetSlotList(NULL) failed.";
    return false;
  }
  std::unique_ptr<CK_SLOT_ID[]> slot_list(new CK_SLOT_ID[num_slots]);
  rv = C_GetSlotList(CK_TRUE, slot_list.get(), &num_slots);
  if (rv != CKR_OK) {
    LOG(WARNING) << __func__ << ": C_GetSlotList failed.";
    return false;
  }

  // Check if at least one valid user token exists.
  for (CK_ULONG i = 0; i < num_slots; ++i) {
    if (CheckTokenInSlot(slot_list[i], kDefaultUserLabelPrefix)) {
      LOG(INFO) << "User PKCS #11 token looks ok.";
      return true;
    }
  }

  LOG(WARNING) << "Cannot find valid user token.";
  return false;
}

bool Pkcs11Init::IsSystemTokenOK() {
  return CheckTokenInSlot(0, kDefaultSystemLabel);
}

bool Pkcs11Init::CheckTokenInSlot(CK_SLOT_ID slot_id,
                                  const std::string& expected_label_prefix) {
  CK_RV rv;
  CK_SESSION_HANDLE session_handle = 0;
  CK_SESSION_INFO session_info;
  CK_TOKEN_INFO token_info;

  rv = C_Initialize(NULL);
  if (rv != CKR_OK && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
    LOG(WARNING) << "C_Initialize failed while checking token: " << std::hex
                 << rv;
    return false;
  }

  rv = C_OpenSession(slot_id, CKF_RW_SESSION | CKF_SERIAL_SESSION, NULL, NULL,
                     &session_handle);
  if (rv != CKR_OK) {
    LOG(WARNING) << "Could not open session on slot " << slot_id
                 << " while checking token." << std::hex << rv;
    C_CloseAllSessions(slot_id);
    return false;
  }

  memset(&session_info, 0, sizeof(session_info));
  rv = C_GetSessionInfo(session_handle, &session_info);
  if (rv != CKR_OK || session_info.slotID != slot_id) {
    LOG(WARNING) << "Could not get session info on " << slot_id
                 << " while checking token: " << std::hex << rv;
    C_CloseAllSessions(slot_id);
    return false;
  }

  rv = C_GetTokenInfo(slot_id, &token_info);
  if (rv != CKR_OK || !(token_info.flags & CKF_TOKEN_INITIALIZED)) {
    LOG(WARNING) << "Could not get token info on " << slot_id
                 << " while checking token: " << std::hex << rv;
    C_CloseAllSessions(slot_id);
    return false;
  }

  std::string label(reinterpret_cast<const char*>(token_info.label),
                    base::size(token_info.label));
  if (!base::StartsWith(label, expected_label_prefix,
                        base::CompareCase::SENSITIVE)) {
    LOG(WARNING) << "Token Label (" << label << ") does not match expected "
                 << "label prefix (" << expected_label_prefix << ")";
    return false;
  }

  C_CloseAllSessions(slot_id);
  return true;
}

}  // namespace cryptohome
