//
// Copyright (C) 2014 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/hmac_authorization_delegate.h"

#include <base/logging.h>
#include <base/stl_util.h>
#include <crypto/secure_util.h>
#include <openssl/aes.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>

namespace trunks {

namespace {

const uint32_t kDigestBits = 256;
const uint16_t kNonceMinSize = 16;
const uint16_t kNonceMaxSize = 32;
const uint8_t kDecryptSession = 1 << 5;
const uint8_t kEncryptSession = 1 << 6;
const uint8_t kLabelSize = 4;
const size_t kAesIVSize = 16;
const uint32_t kTpmBufferSize = 4096;

}  // namespace

HmacAuthorizationDelegate::HmacAuthorizationDelegate()
    : session_handle_(0),
      is_parameter_encryption_enabled_(false),
      nonce_generated_(false),
      future_authorization_value_set_(false),
      use_entity_authorization_for_encryption_only_(false) {
  tpm_nonce_.size = 0;
  caller_nonce_.size = 0;
}

HmacAuthorizationDelegate::~HmacAuthorizationDelegate() {}

bool HmacAuthorizationDelegate::GetCommandAuthorization(
    const std::string& command_hash,
    bool is_command_parameter_encryption_possible,
    bool is_response_parameter_encryption_possible,
    std::string* authorization) {
  if (!session_handle_) {
    authorization->clear();
    LOG(ERROR) << "Delegate being used before Initialization,";
    return false;
  }
  TPMS_AUTH_COMMAND auth;
  auth.session_handle = session_handle_;
  if (!nonce_generated_) {
    RegenerateCallerNonce();
  }
  auth.nonce = caller_nonce_;
  auth.session_attributes = kContinueSession;
  if (is_parameter_encryption_enabled_) {
    if (is_command_parameter_encryption_possible) {
      auth.session_attributes |= kDecryptSession;
    }
    if (is_response_parameter_encryption_possible) {
      auth.session_attributes |= kEncryptSession;
    }
  }
  // We reset the |nonce_generated| flag in preperation of the next command.
  nonce_generated_ = false;
  std::string attributes_bytes;
  CHECK_EQ(Serialize_TPMA_SESSION(auth.session_attributes, &attributes_bytes),
           TPM_RC_SUCCESS)
      << "Error serializing session attributes.";

  std::string hmac_data;
  std::string hmac_key;
  if (!use_entity_authorization_for_encryption_only_) {
    hmac_key = session_key_ + entity_authorization_value_;
  } else {
    hmac_key = session_key_;
  }
  hmac_data.append(command_hash);
  hmac_data.append(reinterpret_cast<const char*>(caller_nonce_.buffer),
                   caller_nonce_.size);
  hmac_data.append(reinterpret_cast<const char*>(tpm_nonce_.buffer),
                   tpm_nonce_.size);
  hmac_data.append(attributes_bytes);
  std::string digest = HmacSha256(hmac_key, hmac_data);
  auth.hmac = Make_TPM2B_DIGEST(digest);

  TPM_RC serialize_error = Serialize_TPMS_AUTH_COMMAND(auth, authorization);
  if (serialize_error != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Could not serialize command auth.";
    return false;
  }
  return true;
}

bool HmacAuthorizationDelegate::CheckResponseAuthorization(
    const std::string& response_hash,
    const std::string& authorization) {
  if (!session_handle_) {
    return false;
  }
  TPMS_AUTH_RESPONSE auth_response;
  std::string mutable_auth_string(authorization);
  TPM_RC parse_error;
  parse_error =
      Parse_TPMS_AUTH_RESPONSE(&mutable_auth_string, &auth_response, nullptr);
  if (parse_error != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Could not parse authorization response.";
    return false;
  }
  if (auth_response.hmac.size != kHashDigestSize) {
    LOG(ERROR) << "TPM auth hmac was incorrect size.";
    return false;
  }
  if (auth_response.nonce.size < kNonceMinSize ||
      auth_response.nonce.size > kNonceMaxSize) {
    LOG(ERROR) << "TPM_nonce is not the correct length.";
    return false;
  }
  tpm_nonce_ = auth_response.nonce;
  std::string attributes_bytes;
  CHECK_EQ(Serialize_TPMA_SESSION(auth_response.session_attributes,
                                  &attributes_bytes),
           TPM_RC_SUCCESS)
      << "Error serializing session attributes.";

  std::string hmac_data;
  std::string hmac_key;
  if (!use_entity_authorization_for_encryption_only_) {
    // In a special case with TPM2_HierarchyChangeAuth, we need to use the
    // auth_value that was set.
    if (future_authorization_value_set_) {
      hmac_key = session_key_ + future_authorization_value_;
      future_authorization_value_set_ = false;
    } else {
      hmac_key = session_key_ + entity_authorization_value_;
    }
  } else {
    hmac_key = session_key_;
  }
  hmac_data.append(response_hash);
  hmac_data.append(reinterpret_cast<const char*>(tpm_nonce_.buffer),
                   tpm_nonce_.size);
  hmac_data.append(reinterpret_cast<const char*>(caller_nonce_.buffer),
                   caller_nonce_.size);
  hmac_data.append(attributes_bytes);
  std::string digest = HmacSha256(hmac_key, hmac_data);
  CHECK_EQ(digest.size(), auth_response.hmac.size);
  if (!crypto::SecureMemEqual(digest.data(), auth_response.hmac.buffer,
                              digest.size())) {
    LOG(ERROR) << "Authorization response hash did not match expected value.";
    return false;
  }
  return true;
}

bool HmacAuthorizationDelegate::EncryptCommandParameter(
    std::string* parameter) {
  CHECK(parameter);
  if (!session_handle_) {
    LOG(ERROR) << __func__ << ": Invalid session handle.";
    return false;
  }
  if (!is_parameter_encryption_enabled_) {
    // No parameter encryption enabled.
    return true;
  }
  if (parameter->size() > kTpmBufferSize) {
    LOG(ERROR) << "Parameter size is too large for TPM decryption.";
    return false;
  }
  RegenerateCallerNonce();
  nonce_generated_ = true;
  AesOperation(parameter, caller_nonce_, tpm_nonce_, AES_ENCRYPT);
  return true;
}

bool HmacAuthorizationDelegate::DecryptResponseParameter(
    std::string* parameter) {
  CHECK(parameter);
  if (!session_handle_) {
    LOG(ERROR) << __func__ << ": Invalid session handle.";
    return false;
  }
  if (!is_parameter_encryption_enabled_) {
    // No parameter decryption enabled.
    return true;
  }
  if (parameter->size() > kTpmBufferSize) {
    LOG(ERROR) << "Parameter size is too large for TPM encryption.";
    return false;
  }
  AesOperation(parameter, tpm_nonce_, caller_nonce_, AES_DECRYPT);
  return true;
}

bool HmacAuthorizationDelegate::InitSession(TPM_HANDLE session_handle,
                                            const TPM2B_NONCE& tpm_nonce,
                                            const TPM2B_NONCE& caller_nonce,
                                            const std::string& salt,
                                            const std::string& bind_auth_value,
                                            bool enable_parameter_encryption) {
  session_handle_ = session_handle;
  if (caller_nonce.size < kNonceMinSize || caller_nonce.size > kNonceMaxSize ||
      tpm_nonce.size < kNonceMinSize || tpm_nonce.size > kNonceMaxSize) {
    LOG(INFO) << "Session Nonces have to be between 16 and 32 bytes long.";
    return false;
  }
  tpm_nonce_ = tpm_nonce;
  caller_nonce_ = caller_nonce;
  std::string session_key_label("ATH", kLabelSize);
  is_parameter_encryption_enabled_ = enable_parameter_encryption;
  if (salt.length() == 0 && bind_auth_value.length() == 0) {
    // SessionKey is set to the empty string for unsalted and
    // unbound sessions.
    session_key_ = std::string();
  } else {
    session_key_ = CreateKey(bind_auth_value + salt, session_key_label,
                             tpm_nonce_, caller_nonce_);
  }
  return true;
}

void HmacAuthorizationDelegate::set_future_authorization_value(
    const std::string& auth_value) {
  future_authorization_value_ = auth_value;
  future_authorization_value_set_ = true;
}

std::string HmacAuthorizationDelegate::CreateKey(
    const std::string& hmac_key,
    const std::string& label,
    const TPM2B_NONCE& nonce_newer,
    const TPM2B_NONCE& nonce_older) {
  std::string counter;
  std::string digest_size_bits;
  if (Serialize_uint32_t(1, &counter) != TPM_RC_SUCCESS ||
      Serialize_uint32_t(kDigestBits, &digest_size_bits) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error serializing uint32_t during session key generation.";
    return std::string();
  }
  CHECK_EQ(counter.size(), sizeof(uint32_t));
  CHECK_EQ(digest_size_bits.size(), sizeof(uint32_t));
  CHECK_EQ(label.size(), kLabelSize);

  std::string data;
  data.append(counter);
  data.append(label);
  data.append(reinterpret_cast<const char*>(nonce_newer.buffer),
              nonce_newer.size);
  data.append(reinterpret_cast<const char*>(nonce_older.buffer),
              nonce_older.size);
  data.append(digest_size_bits);
  std::string key = HmacSha256(hmac_key, data);
  return key;
}

std::string HmacAuthorizationDelegate::HmacSha256(const std::string& key,
                                                  const std::string& data) {
  unsigned char digest[EVP_MAX_MD_SIZE];
  unsigned int digest_length;
  HMAC(EVP_sha256(), key.data(), key.size(),
       reinterpret_cast<const unsigned char*>(data.data()), data.size(), digest,
       &digest_length);
  CHECK_EQ(digest_length, kHashDigestSize);
  return std::string(reinterpret_cast<char*>(digest), digest_length);
}

void HmacAuthorizationDelegate::AesOperation(std::string* parameter,
                                             const TPM2B_NONCE& nonce_newer,
                                             const TPM2B_NONCE& nonce_older,
                                             int operation_type) {
  std::string label("CFB", kLabelSize);
  std::string compound_key =
      CreateKey(session_key_ + entity_authorization_value_, label, nonce_newer,
                nonce_older);
  CHECK_EQ(compound_key.size(), kAesKeySize + kAesIVSize);
  unsigned char aes_key[kAesKeySize];
  unsigned char aes_iv[kAesIVSize];
  memcpy(aes_key, &compound_key[0], kAesKeySize);
  memcpy(aes_iv, &compound_key[kAesKeySize], kAesIVSize);
  AES_KEY key;
  int iv_offset = 0;
  AES_set_encrypt_key(aes_key, kAesKeySize * 8, &key);
  unsigned char decrypted[kTpmBufferSize];
  AES_cfb128_encrypt(reinterpret_cast<const unsigned char*>(parameter->data()),
                     decrypted, parameter->size(), &key, aes_iv, &iv_offset,
                     operation_type);
  memcpy(string_as_array(parameter), decrypted, parameter->size());
}

void HmacAuthorizationDelegate::RegenerateCallerNonce() {
  CHECK(session_handle_);
  // RAND_bytes takes a signed number, but since nonce_size is guaranteed to be
  // less than 32 bytes and greater than 16 we dont have to worry about it.
  CHECK_EQ(RAND_bytes(caller_nonce_.buffer, caller_nonce_.size), 1)
      << "Error regnerating a cryptographically random nonce.";
}

}  // namespace trunks
