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

#include "chaps/opencryptoki_importer.h"

#include <map>
#include <string>
#include <vector>

#include <base/check.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>

#include "chaps/chaps_factory.h"
#include "chaps/chaps_utility.h"
#include "chaps/object.h"
#include "chaps/object_pool.h"
#include "chaps/tpm_utility.h"
#include "pkcs11/cryptoki.h"

using base::FilePath;
using brillo::SecureBlob;
using std::map;
using std::string;
using std::vector;

namespace {

// Extracts a 32-bit integer by reinterpreting bytes.
uint32_t ExtractUint32(const void* data) {
  uint32_t value;
  memcpy(&value, data, sizeof(value));
  return value;
}

}  // namespace

namespace chaps {

OpencryptokiImporter::OpencryptokiImporter(int slot,
                                           const FilePath& path,
                                           TPMUtility* tpm,
                                           ChapsFactory* factory)
    : slot_(slot),
      path_(path),
      tpm_(tpm),
      factory_(factory),
      private_root_key_(0),
      private_leaf_key_(0),
      public_root_key_(0),
      public_leaf_key_(0) {}

OpencryptokiImporter::~OpencryptokiImporter() {}

bool OpencryptokiImporter::ImportObjects(ObjectPool* object_pool) {
  const char kOpencryptokiDir[] = ".tpm";
  const char kOpencryptokiObjectDir[] = "TOK_OBJ";
  const char kOpencryptokiRootKey[] = "MK_PRIVATE";
  const char kOpencryptokiObjectIndex[] = "OBJ.IDX";

  LOG(INFO) << "Importing opencryptoki objects.";
  FilePath base_path = path_.DirName().Append(kOpencryptokiDir);
  FilePath object_path = base_path.Append(kOpencryptokiObjectDir);
  FilePath index_path = object_path.Append(kOpencryptokiObjectIndex);
  root_key_path_ = base_path.Append(kOpencryptokiRootKey);
  if (!base::PathExists(index_path)) {
    LOG(WARNING) << "Did not find any opencryptoki objects to import.";
    return true;
  }
  string index;
  if (!base::ReadFileToString(index_path, &index)) {
    LOG(ERROR) << "Failed to read object index.";
    return false;
  }
  vector<string> object_files =
      base::SplitString(index, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
                        base::SPLIT_WANT_NONEMPTY);
  vector<AttributeMap> ready_for_import;
  LOG(INFO) << "Found " << object_files.size() << " object files.";
  // Try to read and process each file listed in the index file. If a problem
  // occurs just move on the next one.
  for (size_t i = 0; i < object_files.size(); ++i) {
    string object_file_content;
    if (!base::ReadFileToString(object_path.Append(object_files[i]),
                                &object_file_content)) {
      LOG(WARNING) << "Failed to read object file: " << object_files[i];
      continue;
    }
    bool is_encrypted = false;
    string flat_object;
    if (!ExtractObjectData(object_file_content, &is_encrypted, &flat_object)) {
      LOG(WARNING) << "Failed to parse object file: " << object_files[i];
      continue;
    }
    if (is_encrypted) {
      // We can't process encrypted files until we have the root key.
      encrypted_objects_[object_files[i]] = flat_object;
      continue;
    }
    AttributeMap attributes;
    if (!UnflattenObject(flat_object, object_files[i], false, &attributes)) {
      LOG(WARNING) << "Failed to parse object attributes: " << object_files[i];
      continue;
    }
    if (!ProcessInternalObject(attributes, object_pool)) {
      // This is an ordinary object.
      ready_for_import.push_back(attributes);
    }
  }
  if (encrypted_objects_.size() == 0 && ready_for_import.size() == 0) {
    // Nothing to import, our job is done.
    LOG(INFO) << "Did not find any opencryptoki objects to import.";
    return true;
  }
  LOG(INFO) << "Found objects: " << encrypted_objects_.size() << " private, "
            << ready_for_import.size() << " public.";
  // Objects that have opencryptoki internal attributes such as tpm-protected
  // blobs need to be moved to the chaps format.
  int num_imported = 0;
  for (size_t i = 0; i < ready_for_import.size(); ++i) {
    if (IsPrivateKey(ready_for_import[i])) {
      // Private keys need authorization data decrypted which requires the TPM.
      // Queue up the object for later processing.
      unflattened_objects_.push_back(ready_for_import[i]);
      continue;
    }
    Object* object = NULL;
    if (!CreateObjectInstance(ready_for_import[i], &object)) {
      LOG(WARNING) << "Failed to create an object instance.";
      continue;
    }
    if (object_pool->Import(object) == ObjectPool::Result::Success)
      ++num_imported;
  }
  LOG(INFO) << "Imported: " << num_imported << "; Pending: "
            << encrypted_objects_.size() + unflattened_objects_.size();
  return true;
}

bool OpencryptokiImporter::FinishImportAsync(ObjectPool* object_pool) {
  // If there are any encrypted objects, now is the time to decrypt them.
  if (!DecryptPendingObjects()) {
    LOG(WARNING) << "Failed to decrypt encrypted objects. Only public objects"
                 << " can be imported.";
  }
  // Objects that have opencryptoki internal attributes such as tpm-protected
  // blobs need to be moved to the chaps format.
  int num_imported = 0;
  for (size_t i = 0; i < unflattened_objects_.size(); ++i) {
    if (!ConvertToChapsFormat(&unflattened_objects_[i])) {
      LOG(WARNING) << "Failed to convert an object to Chaps format.";
      continue;
    }
    Object* object = NULL;
    if (!CreateObjectInstance(unflattened_objects_[i], &object)) {
      LOG(WARNING) << "Failed to create an object instance.";
      continue;
    }
    if (object_pool->Import(object) == ObjectPool::Result::Success)
      ++num_imported;
  }
  LOG(INFO) << "Finished importing " << num_imported << " pending objects.";
  return true;
}

bool OpencryptokiImporter::ExtractObjectData(const string& object_file_content,
                                             bool* is_encrypted,
                                             string* object_data) {
  // An object file has a header formatted as follows:
  // * Total Length - 4 bytes
  // * Private Indicator - 1 byte
  // * Object Data - All remaining bytes.
  if (object_file_content.length() < 5)
    return false;
  size_t total_length = ExtractUint32(object_file_content.data());
  if (total_length != object_file_content.length())
    return false;
  *is_encrypted = (0 != object_file_content[4]);
  *object_data = object_file_content.substr(5);
  return true;
}

bool OpencryptokiImporter::UnflattenObject(const string& object_data,
                                           const string& object_name,
                                           bool is_encrypted,
                                           AttributeMap* attributes) {
  // A flattened object is laid out as follows:
  // * Object Class - 4 bytes (ignored).
  // * Number of Attributes - 4 bytes.
  // * Object Name - 8 bytes.
  // * Attribute List - No padding between items, each item as follows:
  //   ** CK_ATTRIBUTE with 32-bit fields - 12 bytes.
  //   ** CK_ATTRIBUTE::ulValueLen bytes of data.
  if (object_data.length() < 16)
    return false;
  // If this exact number of attributes cannot be extracted the object will be
  // considered corrupted.
  int num_attrs = ExtractUint32(&object_data[4]);
  // This is not needed but we'll consider the object corrupted if it doesn't
  // match the file name from where this object data was extracted.
  string stored_object_name(object_data.substr(8, 8));
  if (stored_object_name != object_name) {
    LOG(ERROR) << "Object name mismatch: " << object_name << ", "
               << stored_object_name;
    return false;
  }
  size_t pos = 16;
  for (int i = 0; i < num_attrs; ++i) {
    if (object_data.size() < pos + 12)
      return false;
    CK_ATTRIBUTE_TYPE type = ExtractUint32(&object_data[pos]);
    size_t length = ExtractUint32(&object_data[pos + 8]);
    pos += 12;
    if (object_data.size() < pos + length)
      return false;
    string data = object_data.substr(pos, length);
    pos += length;
    if (type == CKA_PRIVATE) {
      if (data.size() < 1)
        return false;
      bool is_private = (data[0] != CK_FALSE);
      if (is_encrypted != is_private) {
        LOG(ERROR) << "Object privacy mismatch.";
        return false;
      }
    }
    (*attributes)[type] = data;
  }
  return true;
}

bool OpencryptokiImporter::ProcessInternalObject(const AttributeMap& attributes,
                                                 ObjectPool* object_pool) {
  const CK_ATTRIBUTE_TYPE kOpencryptokiHidden = CKA_VENDOR_DEFINED + 0x01000000;
  const CK_ATTRIBUTE_TYPE kOpencryptokiOpaque = CKA_VENDOR_DEFINED + 1;
  const char kPrivateRootKeyID[] = "PRIVATE ROOT KEY";
  const char kPrivateLeafKeyID[] = "PRIVATE LEAF KEY";
  const char kPublicRootKeyID[] = "PUBLIC ROOT KEY";
  const char kPublicLeafKeyID[] = "PUBLIC LEAF KEY";

  // The primary indicator we use to determine if this object is an internal
  // object is the opencryptoki hidden attribute (aka CKA_HIDDEN).
  AttributeMap::const_iterator it = attributes.find(kOpencryptokiHidden);
  if (it == attributes.end() || !it->second[0])
    return false;

  // From here on we will return 'true' even if we fail to import the object
  // because we don't want an internal object to get treated as an ordinary
  // object. The public key objects are not useful so we'll discard them. From
  // the private key objects we'll extract the TPM-wrapped blobs.
  it = attributes.find(CKA_CLASS);
  if (it == attributes.end() || it->second.size() != 4)
    return true;
  CK_OBJECT_CLASS object_class = ExtractUint32(it->second.data());
  if (object_class != CKO_PRIVATE_KEY)
    return true;
  // Extract the TPM-wrapped blob.
  it = attributes.find(kOpencryptokiOpaque);
  if (it == attributes.end())
    return true;
  string blob = it->second;
  // Extract the ID so we can determine which object this is. If we don't
  // recognize the ID then the object will be discarded.
  it = attributes.find(CKA_ID);
  if (it == attributes.end())
    return true;
  string id = it->second;
  if (id == kPrivateRootKeyID) {
    if (!object_pool->SetInternalBlob(kLegacyPrivateRootKey, blob)) {
      LOG(ERROR) << "Failed to write private root key blob.";
      return true;
    }
    private_root_blob_ = blob;
  } else if (id == kPrivateLeafKeyID) {
    private_leaf_blob_ = blob;
  } else if (id == kPublicRootKeyID) {
    if (!object_pool->SetInternalBlob(kLegacyPublicRootKey, blob)) {
      LOG(ERROR) << "Failed to write public root key blob.";
      return true;
    }
    public_root_blob_ = blob;
  } else if (id == kPublicLeafKeyID) {
    public_leaf_blob_ = blob;
  }
  return true;
}

bool OpencryptokiImporter::LoadKeyHierarchy(bool load_private) {
  const char kDefaultAuthData[] = "111111";
  string& root_blob = load_private ? private_root_blob_ : public_root_blob_;
  string& leaf_blob = load_private ? private_leaf_blob_ : public_leaf_blob_;
  int& root_key = load_private ? private_root_key_ : public_root_key_;
  int& leaf_key = load_private ? private_leaf_key_ : public_leaf_key_;
  // Check if the requested hierarchy is already loaded.
  if (root_key && leaf_key)
    return true;
  // We need both the root and leaf blobs in order to proceed.
  if (root_blob.empty() || leaf_blob.empty())
    return false;
  // Load the root key.
  if (!tpm_->LoadKey(slot_, root_blob, SecureBlob(), &root_key))
    return false;
  // Load the leaf key.
  SecureBlob leaf_auth_data = Sha1(
      SecureBlob(std::begin(kDefaultAuthData), std::end(kDefaultAuthData)));
  if (!tpm_->LoadKeyWithParent(slot_, leaf_blob, leaf_auth_data, root_key,
                               &leaf_key))
    return false;
  return true;
}

bool OpencryptokiImporter::DecryptRootKey(const string& encrypted_root_key,
                                          SecureBlob* root_key) {
  if (!LoadKeyHierarchy(true)) {
    LOG(ERROR) << "Failed to load private key hierarchy.";
    return false;
  }
  // Trousers defines the handle value 0 as NULL_HKEY so this check works.
  CHECK(private_leaf_key_);
  // The root key is encrypted with a simple bind to the private leaf key.
  string root_key_str;
  if (!tpm_->Unbind(private_leaf_key_, encrypted_root_key, &root_key_str)) {
    LOG(ERROR) << "Failed to decrypt root key.";
    return false;
  }
  *root_key = SecureBlob(root_key_str.begin(), root_key_str.end());
  brillo::SecureClearContainer(root_key_str);
  return true;
}

bool OpencryptokiImporter::DecryptObject(const SecureBlob& key,
                                         const string& encrypted_object_data,
                                         string* object_data) {
  // Objects are encrypted with AES-256-CBC and a hard-coded IV.
  const char kOpencryptokiIV[] = ")#%&!*)^!()$&!&N";
  const size_t kSha1OutputBytes = 20;
  string decrypted;
  if (!RunCipher(false, key, kOpencryptokiIV, encrypted_object_data,
                 &decrypted))
    return false;
  // The data is formatted as follows:
  // * Length of object data - 4 bytes.
  // * Object data - 'length' bytes.
  // * SHA-1 of object data - 20 bytes.
  if (decrypted.length() < 24)
    return false;
  size_t length = ExtractUint32(decrypted.data());
  if (decrypted.size() != 4 + length + kSha1OutputBytes)
    return false;
  *object_data = decrypted.substr(4, length);
  if (Sha1(*object_data) != decrypted.substr(4 + length))
    return false;
  return true;
}

bool OpencryptokiImporter::ConvertToChapsFormat(AttributeMap* attributes) {
  // There are two special attributes of private keys that need to be converted:
  // 1. The tpm-wrapped blob (aka CKA_IBM_OPAQUE).
  // 2. The encrypted authorization data (aka CKA_ENC_AUTHDATA).
  const CK_ATTRIBUTE_TYPE kOpencryptokiOpaque = CKA_VENDOR_DEFINED + 1;
  const CK_ATTRIBUTE_TYPE kOpencryptokiAuthData =
      CKA_VENDOR_DEFINED + 0x01000001;

  // Sanity check for mandatory attributes that we need.
  AttributeMap::iterator class_it = attributes->find(CKA_CLASS);
  AttributeMap::iterator private_it = attributes->find(CKA_PRIVATE);
  if (class_it == attributes->end() || class_it->second.size() < 4 ||
      private_it == attributes->end() || private_it->second.size() < 1)
    return false;

  // If the object is not a private key, we can leave it as is.
  CK_OBJECT_CLASS object_class = ExtractUint32(class_it->second.data());
  if (object_class != CKO_PRIVATE_KEY)
    return true;

  // It is possible that these two attributes are missing and in that case we
  // can leave the object untouched. If the blob attribute exists but the
  // authorization data attribute doesn't, then it is considered a failure.
  AttributeMap::iterator blob_it = attributes->find(kOpencryptokiOpaque);
  if (blob_it == attributes->end())
    return true;
  string tpm_wrapped_blob = blob_it->second;
  AttributeMap::iterator auth_it = attributes->find(kOpencryptokiAuthData);
  if (auth_it == attributes->end())
    return false;
  string encrypted_auth_data = auth_it->second;

  // The value of CKA_PRIVATE tells us which hierarchy we're working with.
  CK_BBOOL is_private = private_it->second[0];
  int leaf_key_handle = is_private ? private_leaf_key_ : public_leaf_key_;
  if (!LoadKeyHierarchy(is_private)) {
    LOG(ERROR) << "Failed to load key hierarchy: private=" << is_private;
    return false;
  }
  // Trousers defines the handle value 0 as NULL_HKEY so this check works.
  CHECK(leaf_key_handle);

  // Decrypt the authorization data.
  string auth_data;
  if (!tpm_->Unbind(leaf_key_handle, encrypted_auth_data, &auth_data)) {
    LOG(ERROR) << "Failed to unbind authorization data.";
    return false;
  }

  // Remove the opencryptoki-specific attributes from the object and insert the
  // expected chaps-specific attributes.
  attributes->erase(kOpencryptokiOpaque);
  attributes->erase(kOpencryptokiAuthData);
  (*attributes)[kKeyBlobAttribute] = tpm_wrapped_blob;
  (*attributes)[kAuthDataAttribute] = auth_data;
  (*attributes)[kKeyInSoftware] = string(1, CK_FALSE);
  (*attributes)[kLegacyAttribute] = string(1, CK_TRUE);
  return true;
}

bool OpencryptokiImporter::CreateObjectInstance(const AttributeMap& attributes,
                                                Object** object) {
  *object = factory_->CreateObject();
  for (AttributeMap::const_iterator it = attributes.begin();
       it != attributes.end(); ++it) {
    (*object)->SetAttributeString(it->first, it->second);
  }
  CK_RV result = (*object)->FinalizeNewObject();
  if (result != CKR_OK) {
    LOG(ERROR) << "Failed to validate new object: " << CK_RVToString(result);
    return false;
  }
  return true;
}

bool OpencryptokiImporter::IsPrivateKey(const AttributeMap& attributes) {
  AttributeMap::const_iterator class_it = attributes.find(CKA_CLASS);
  if (class_it == attributes.end() || class_it->second.size() < 4)
    return false;
  CK_OBJECT_CLASS object_class = ExtractUint32(class_it->second.data());
  return (object_class == CKO_PRIVATE_KEY);
}

bool OpencryptokiImporter::DecryptPendingObjects() {
  if (encrypted_objects_.size() > 0) {
    string encrypted_root_key;
    if (!base::PathExists(root_key_path_) ||
        !base::ReadFileToString(root_key_path_, &encrypted_root_key)) {
      LOG(ERROR) << "Failed to read encrypted root key.";
      return false;
    }
    SecureBlob root_key;
    if (!DecryptRootKey(encrypted_root_key, &root_key)) {
      LOG(ERROR) << "Failed to decrypt the root key.";
      return false;
    }
    for (map<string, string>::iterator iter = encrypted_objects_.begin();
         iter != encrypted_objects_.end(); ++iter) {
      string flat_object;
      if (!DecryptObject(root_key, iter->second, &flat_object)) {
        LOG(WARNING) << "Failed to decrypt an encrypted object: "
                     << iter->first;
        continue;
      }
      AttributeMap attributes;
      if (!UnflattenObject(flat_object, iter->first, true, &attributes)) {
        LOG(WARNING) << "Failed to parse object attributes: " << iter->first;
        continue;
      }
      unflattened_objects_.push_back(attributes);
    }
  }
  return true;
}

}  // namespace chaps
