// Copyright 2018 The Fuchsia 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 "types.h"

#include "src/connectivity/bluetooth/core/bt-host/hci/hci_constants.h"
#include "src/connectivity/bluetooth/core/bt-host/sm/smp.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace bt::sm {
namespace {

bool IsEncryptedKey(hci::LinkKeyType lk_type) {
  return (lk_type == hci::LinkKeyType::kDebugCombination ||
          lk_type == hci::LinkKeyType::kUnauthenticatedCombination192 ||
          lk_type == hci::LinkKeyType::kUnauthenticatedCombination256 ||
          lk_type == hci::LinkKeyType::kAuthenticatedCombination192 ||
          lk_type == hci::LinkKeyType::kAuthenticatedCombination256);
}

bool IsAuthenticatedKey(hci::LinkKeyType lk_type) {
  return (lk_type == hci::LinkKeyType::kAuthenticatedCombination192 ||
          lk_type == hci::LinkKeyType::kAuthenticatedCombination256);
}

bool IsSecureConnectionsKey(hci::LinkKeyType lk_type) {
  return (lk_type == hci::LinkKeyType::kUnauthenticatedCombination256 ||
          lk_type == hci::LinkKeyType::kAuthenticatedCombination256);
}

}  // namespace

PairingFeatures::PairingFeatures() { std::memset(this, 0, sizeof(*this)); }

PairingFeatures::PairingFeatures(bool initiator, bool sc, bool will_bond,
                                 std::optional<CrossTransportKeyAlgo> algo, PairingMethod method,
                                 uint8_t enc_key_size, KeyDistGenField local_kd,
                                 KeyDistGenField remote_kd)
    : initiator(initiator),
      secure_connections(sc),
      will_bond(will_bond),
      generate_ct_key(algo),
      method(method),
      encryption_key_size(enc_key_size),
      local_key_distribution(local_kd),
      remote_key_distribution(remote_kd) {}

bool HasKeysToDistribute(PairingFeatures features) {
  return DistributableKeys(features.local_key_distribution) ||
         DistributableKeys(features.remote_key_distribution);
}

const char* LevelToString(SecurityLevel level) {
  switch (level) {
    case SecurityLevel::kEncrypted:
      return "encrypted";
    case SecurityLevel::kAuthenticated:
      return "encrypted (MITM)";
    case SecurityLevel::kSecureAuthenticated:
      return "encrypted (MITM) with Secure Connections and 128-bit key";
    default:
      break;
  }
  return "not secure";
}

SecurityProperties::SecurityProperties() : SecurityProperties(false, false, false, 0u) {}

SecurityProperties::SecurityProperties(bool encrypted, bool authenticated, bool secure_connections,
                                       size_t enc_key_size)
    : properties_(0u), enc_key_size_(enc_key_size) {
  properties_ |= (encrypted ? Property::kEncrypted : 0u);
  properties_ |= (authenticated ? Property::kAuthenticated : 0u);
  properties_ |= (secure_connections ? Property::kSecureConnections : 0u);
}

SecurityProperties::SecurityProperties(SecurityLevel level, size_t enc_key_size,
                                       bool secure_connections)
    : SecurityProperties((level >= SecurityLevel::kEncrypted),
                         (level >= SecurityLevel::kAuthenticated), secure_connections,
                         enc_key_size) {}
// All BR/EDR link keys, even those from legacy pairing or based on 192-bit EC
// points, are stored in 128 bits, according to Core Spec v5.0, Vol 2, Part H
// Section 3.1 "Key Types."
SecurityProperties::SecurityProperties(hci::LinkKeyType lk_type)
    : SecurityProperties(IsEncryptedKey(lk_type), IsAuthenticatedKey(lk_type),
                         IsSecureConnectionsKey(lk_type), kMaxEncryptionKeySize) {
  ZX_DEBUG_ASSERT_MSG(lk_type != hci::LinkKeyType::kChangedCombination,
                      "Can't infer security information from a Changed Combination Key");
}

SecurityLevel SecurityProperties::level() const {
  auto level = SecurityLevel::kNoSecurity;
  if (properties_ & Property::kEncrypted) {
    level = SecurityLevel::kEncrypted;
    if (properties_ & Property::kAuthenticated) {
      level = SecurityLevel::kAuthenticated;
      if (enc_key_size_ == kMaxEncryptionKeySize && (properties_ & Property::kSecureConnections)) {
        level = SecurityLevel::kSecureAuthenticated;
      }
    }
  }
  return level;
}

std::optional<hci::LinkKeyType> SecurityProperties::GetLinkKeyType() const {
  if (level() == SecurityLevel::kNoSecurity) {
    return std::nullopt;
  }
  if (authenticated()) {
    if (secure_connections()) {
      return hci::LinkKeyType::kAuthenticatedCombination256;
    } else {
      return hci::LinkKeyType::kAuthenticatedCombination192;
    }
  } else {
    if (secure_connections()) {
      return hci::LinkKeyType::kUnauthenticatedCombination256;
    } else {
      return hci::LinkKeyType::kUnauthenticatedCombination192;
    }
  }
}

std::string SecurityProperties::ToString() const {
  if (level() == SecurityLevel::kNoSecurity) {
    return "[no security]";
  }
  return fxl::StringPrintf("[%s%s%skey size: %lu]", encrypted() ? "encrypted " : "",
                           authenticated() ? "authenticated (MITM) " : "",
                           secure_connections() ? "secure connections " : "legacy authentication ",
                           enc_key_size());
}

bool SecurityProperties::IsAsSecureAs(const SecurityProperties& other) const {
  // clang-format off
  return
    (encrypted() || !other.encrypted()) &&
    (authenticated() || !other.authenticated()) &&
    (secure_connections() || !other.secure_connections()) &&
    (enc_key_size_ >= other.enc_key_size_);
  // clang-format on
}

LTK::LTK(const SecurityProperties& security, const hci::LinkKey& key)
    : security_(security), key_(key) {}

Key::Key(const SecurityProperties& security, const UInt128& value)
    : security_(security), value_(value) {}

}  // namespace bt::sm
