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

#ifndef TINK_UTIL_SECRET_DATA_H_
#define TINK_UTIL_SECRET_DATA_H_

#include <memory>
#include <type_traits>
#include <vector>

#include "absl/strings/string_view.h"
#include "tink/util/secret_data_internal.h"

namespace crypto {
namespace tink {
namespace util {

// Stores secret (sensitive) data and makes sure it's marked as such and
// destroyed in a safe way.
// This should be the first choice when handling key/key derived values.
//
// Example:
// class MyCryptoPrimitive {
//  public:
//   MyCryptoPrimitive(absl::string_view key_value) :
//     key_(SecretDataFromStringView(key_value)) {}
//   [...]
//  private:
//   const util::SecretData key_;
// }
using SecretData = std::vector<uint8_t, internal::SanitizingAllocator<uint8_t>>;

// Stores secret (sensitive) object and makes sure it's marked as such and
// destroyed in a safe way.
// The object needs to be trivially destructible (to make sure it does not
// allocate memory internally).
// SecretUniquePtr MUST be constructed using MakeSecretUniquePtr function.
// Generally SecretUniquePtr should be used iff SecretData is unsuitable.
//
// Example:
// class MyCryptoPrimitive {
//  public:
//   MyEncryptionPrimitive(absl::string_view key_value) {
//     AES_set_encrypt_key(key_value.data(), key_value.size() * 8, key_.get());
//   }
//   [...]
//  private:
//   util::SecretUniquePtr<AES_KEY> key_ = util::MakeSecretUniquePtr<AES_KEY>();
// }
template <typename T>
class SecretUniquePtr {
 private:
  using Value = std::unique_ptr<T, internal::SanitizingDeleter<T>>;

 public:
  using pointer = typename Value::pointer;
  using element_type = typename Value::element_type;
  using deleter_type = typename Value::deleter_type;
  static_assert(std::is_trivially_destructible<T>::value,
                "SecureUniquePtr only supports trivially destructible types");
  SecretUniquePtr() {}

  pointer get() const { return value_.get(); }
  deleter_type& get_deleter() { return value_.get_deleter(); }
  const deleter_type& get_deleter() const { return value_.get_deleter(); }
  void swap(SecretUniquePtr& other) { value_.swap(other.value_); }
  void reset() { value_.reset(); }

  typename std::add_lvalue_reference<T>::type operator*() const {
    return value_.operator*();
  }
  pointer operator->() const { return value_.operator->(); }
  explicit operator bool() const { return value_.operator bool(); }

 private:
  template <typename S, typename... Args>
  friend SecretUniquePtr<S> MakeSecretUniquePtr(Args&&... args);
  explicit SecretUniquePtr(Value&& value) : value_(std::move(value)) {}
  Value value_;
};

template <typename T, typename... Args>
SecretUniquePtr<T> MakeSecretUniquePtr(Args&&... args) {
  T* ptr = internal::SanitizingAllocator<T>().allocate(1);
  new (ptr)
      T(std::forward<Args>(args)...);  // Invoke constructor "placement new"
  return SecretUniquePtr<T>({ptr, internal::SanitizingDeleter<T>()});
}

// Convenience conversion functions
inline absl::string_view SecretDataAsStringView(const SecretData& secret) {
  return {reinterpret_cast<const char*>(secret.data()), secret.size()};
}

inline SecretData SecretDataFromStringView(absl::string_view secret) {
  return {secret.begin(), secret.end()};
}

inline void SafeZeroMemory(volatile char* ptr, std::size_t size) {
  internal::SafeZeroMemory(ptr, size);
}

inline void SafeZeroString(std::string* str) {
  SafeZeroMemory(&(*str)[0], str->size());
}

}  // namespace util
}  // namespace tink
}  // namespace crypto

#endif  // TINK_UTIL_SECRET_DATA_H_
