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

#include "trunks/session_manager_impl.h"

#include <string>

#include <base/logging.h>
#include <base/stl_util.h>
#include <crypto/openssl_util.h>
#include <crypto/scoped_openssl_types.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#if defined(OPENSSL_IS_BORINGSSL)
#include <openssl/mem.h>
#endif
#include <openssl/rand.h>
#include <openssl/rsa.h>

#include "trunks/error_codes.h"
#include "trunks/tpm_generated.h"
#include "trunks/tpm_utility.h"

namespace {
const size_t kWellKnownExponent = 0x10001;

std::string GetOpenSSLError() {
  BIO* bio = BIO_new(BIO_s_mem());
  ERR_print_errors(bio);
  char* data = nullptr;
  int data_len = BIO_get_mem_data(bio, &data);
  std::string error_string(data, data_len);
  BIO_free(bio);
  return error_string;
}
}  // namespace

namespace trunks {

SessionManagerImpl::SessionManagerImpl(const TrunksFactory& factory)
    : factory_(factory), session_handle_(kUninitializedHandle) {
  crypto::EnsureOpenSSLInit();
}

SessionManagerImpl::~SessionManagerImpl() {
  CloseSession();
}

void SessionManagerImpl::CloseSession() {
  if (session_handle_ == kUninitializedHandle) {
    return;
  }
  TPM_RC result = factory_.GetTpm()->FlushContextSync(session_handle_, nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(WARNING) << "Error closing tpm session: " << GetErrorString(result);
  }
  session_handle_ = kUninitializedHandle;
}

TPM_RC SessionManagerImpl::StartSession(
    TPM_SE session_type,
    TPMI_DH_ENTITY bind_entity,
    const std::string& bind_authorization_value,
    bool enable_encryption,
    HmacAuthorizationDelegate* delegate) {
  CHECK(delegate);
  // If we already have an active session, close it.
  CloseSession();

  std::string salt(SHA256_DIGEST_SIZE, 0);
  unsigned char* salt_buffer =
      reinterpret_cast<unsigned char*>(base::string_as_array(&salt));
  CHECK_EQ(RAND_bytes(salt_buffer, salt.size()), 1)
      << "Error generating a cryptographically random salt.";
  // First we encrypt the cryptographically secure salt using PKCS1_OAEP
  // padded RSA public key encryption. This is specified in TPM2.0
  // Part1 Architecture, Appendix B.10.2.
  std::string encrypted_salt;
  TPM_RC salt_result = EncryptSalt(salt, &encrypted_salt);
  if (salt_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error encrypting salt: " << GetErrorString(salt_result);
    return salt_result;
  }

  TPM2B_ENCRYPTED_SECRET encrypted_secret =
      Make_TPM2B_ENCRYPTED_SECRET(encrypted_salt);
  // Then we use TPM2_StartAuthSession to start a HMAC session with the TPM.
  // The tpm returns the tpm_nonce and the session_handle referencing the
  // created session.
  TPMI_ALG_HASH hash_algorithm = TPM_ALG_SHA256;
  TPMT_SYM_DEF symmetric_algorithm;
  symmetric_algorithm.algorithm = TPM_ALG_AES;
  symmetric_algorithm.key_bits.aes = 128;
  symmetric_algorithm.mode.aes = TPM_ALG_CFB;

  TPM2B_NONCE nonce_caller;
  TPM2B_NONCE nonce_tpm;
  // We use sha1_digest_size here because that is the minimum length
  // needed for the nonce.
  nonce_caller.size = SHA1_DIGEST_SIZE;
  CHECK_EQ(RAND_bytes(nonce_caller.buffer, nonce_caller.size), 1)
      << "Error generating a cryptographically random nonce.";

  Tpm* tpm = factory_.GetTpm();
  // The TPM2 command below needs no authorization. This is why we can use
  // the empty string "", when referring to the handle names for the salting
  // key and the bind entity.
  TPM_RC tpm_result = tpm->StartAuthSessionSync(
      kSaltingKey,
      "",  // salt_handle_name.
      bind_entity,
      "",  // bind_entity_name.
      nonce_caller, encrypted_secret, session_type, symmetric_algorithm,
      hash_algorithm, &session_handle_, &nonce_tpm,
      nullptr);  // No Authorization.
  if (tpm_result) {
    LOG(ERROR) << "Error creating an authorization session: "
               << GetErrorString(tpm_result);
    return tpm_result;
  }
  bool hmac_result =
      delegate->InitSession(session_handle_, nonce_tpm, nonce_caller, salt,
                            bind_authorization_value, enable_encryption);
  if (!hmac_result) {
    LOG(ERROR) << "Failed to initialize an authorization session delegate.";
    return TPM_RC_FAILURE;
  }
  return TPM_RC_SUCCESS;
}

TPM_RC SessionManagerImpl::EncryptSalt(const std::string& salt,
                                       std::string* encrypted_salt) {
  TPM2B_NAME out_name;
  TPM2B_NAME qualified_name;
  TPM2B_PUBLIC public_data;
  public_data.public_area.unique.rsa.size = 0;
  TPM_RC result = factory_.GetTpm()->ReadPublicSync(
      kSaltingKey, "" /*object_handle_name (not used)*/, &public_data,
      &out_name, &qualified_name, nullptr /*authorization_delegate*/);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error fetching salting key public info: "
               << GetErrorString(result);
    return result;
  }
  if (public_data.public_area.type != TPM_ALG_RSA ||
      public_data.public_area.unique.rsa.size != 256) {
    LOG(ERROR) << "Invalid salting key attributes.";
    return TRUNKS_RC_SESSION_SETUP_ERROR;
  }
  crypto::ScopedRSA salting_key_rsa(RSA_new());
  salting_key_rsa->e = BN_new();
  if (!salting_key_rsa->e) {
    LOG(ERROR) << "Error creating exponent for RSA: " << GetOpenSSLError();
    return TRUNKS_RC_SESSION_SETUP_ERROR;
  }
  BN_set_word(salting_key_rsa->e, kWellKnownExponent);
  salting_key_rsa->n =
      BN_bin2bn(public_data.public_area.unique.rsa.buffer,
                public_data.public_area.unique.rsa.size, nullptr);
  if (!salting_key_rsa->n) {
    LOG(ERROR) << "Error setting public area of rsa key: " << GetOpenSSLError();
    return TRUNKS_RC_SESSION_SETUP_ERROR;
  }
  crypto::ScopedEVP_PKEY salting_key(EVP_PKEY_new());
  if (!EVP_PKEY_set1_RSA(salting_key.get(), salting_key_rsa.get())) {
    LOG(ERROR) << "Error setting up EVP_PKEY: " << GetOpenSSLError();
    return TRUNKS_RC_SESSION_SETUP_ERROR;
  }
  // Label for RSAES-OAEP. Defined in TPM2.0 Part1 Architecture,
  // Appendix B.10.2.
  const size_t kOaepLabelSize = 7;
  const char kOaepLabelValue[] = "SECRET\0";
  // EVP_PKEY_CTX_set0_rsa_oaep_label takes ownership so we need to malloc.
  uint8_t* oaep_label = static_cast<uint8_t*>(OPENSSL_malloc(kOaepLabelSize));
  memcpy(oaep_label, kOaepLabelValue, kOaepLabelSize);
  crypto::ScopedEVP_PKEY_CTX salt_encrypt_context(
      EVP_PKEY_CTX_new(salting_key.get(), nullptr));
  if (!EVP_PKEY_encrypt_init(salt_encrypt_context.get()) ||
      !EVP_PKEY_CTX_set_rsa_padding(salt_encrypt_context.get(),
                                    RSA_PKCS1_OAEP_PADDING) ||
      !EVP_PKEY_CTX_set_rsa_oaep_md(salt_encrypt_context.get(), EVP_sha256()) ||
      !EVP_PKEY_CTX_set_rsa_mgf1_md(salt_encrypt_context.get(), EVP_sha256()) ||
      !EVP_PKEY_CTX_set0_rsa_oaep_label(salt_encrypt_context.get(), oaep_label,
                                        kOaepLabelSize)) {
    LOG(ERROR) << "Error setting up salt encrypt context: "
               << GetOpenSSLError();
    return TRUNKS_RC_SESSION_SETUP_ERROR;
  }
  size_t out_length = EVP_PKEY_size(salting_key.get());
  encrypted_salt->resize(out_length);
  if (!EVP_PKEY_encrypt(
          salt_encrypt_context.get(),
          reinterpret_cast<uint8_t*>(base::string_as_array(encrypted_salt)),
          &out_length, reinterpret_cast<const uint8_t*>(salt.data()),
          salt.size())) {
    LOG(ERROR) << "Error encrypting salt: " << GetOpenSSLError();
    return TRUNKS_RC_SESSION_SETUP_ERROR;
  }
  encrypted_salt->resize(out_length);
  return TPM_RC_SUCCESS;
}

}  // namespace trunks
