// Copyright 2021 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 "metrics/structured/key_data.h"

#include <memory>
#include <utility>

#include <base/check.h>
#include <base/check_op.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/rand_util.h>
#include <base/strings/strcat.h>
#include <base/strings/string_number_conversions.h>
#include <base/time/time.h>
#include <base/unguessable_token.h>
#include <crypto/hmac.h>
#include <crypto/sha2.h>

#include "metrics/structured/structured_events.h"

namespace metrics {
namespace structured {
namespace {

// The expected size of a key, in bytes.
constexpr size_t kKeySize = 32;

// The default maximum number of days before rotating keys.
constexpr int kDefaultRotationPeriod = 90;

// Generates a key, which is the string representation of
// base::UnguessableToken, and is of size |kKeySize| bytes.
std::string GenerateKey() {
  const std::string key = base::UnguessableToken::Create().ToString();
  DCHECK_EQ(key.size(), kKeySize);
  return key;
}

std::string HashToHex(const uint64_t hash) {
  return base::HexEncode(&hash, sizeof(uint64_t));
}

}  // namespace

KeyData::KeyData(const std::string& path)
    : proto_(std::make_unique<PersistentProto<KeyDataProto>>(path)) {}

KeyData::~KeyData() = default;

//---------------
// Key management
//---------------

base::Optional<std::string> KeyData::ValidateAndGetKey(
    const uint64_t project_name_hash) {
  const int now = (base::Time::Now() - base::Time::UnixEpoch()).InDays();
  KeyProto& key = (*(proto_.get()->get()->mutable_keys()))[project_name_hash];

  // Generate or rotate key.
  const int last_rotation = key.last_rotation();
  if (key.key().empty() || last_rotation == 0) {
    // If the key is empty, generate a new one. Set the last rotation to a
    // uniformly selected day between today and |kDefaultRotationPeriod| days
    // ago, to uniformly distribute users amongst rotation cohorts.
    const int rotation_seed = base::RandInt(0, kDefaultRotationPeriod - 1);
    UpdateKey(&key, now - rotation_seed, kDefaultRotationPeriod);
  } else if (now - last_rotation > kDefaultRotationPeriod) {
    // If the key is outdated, generate a new one. Update the last rotation such
    // that the user stays in the same cohort.
    const int new_last_rotation =
        now - (now - last_rotation) % kDefaultRotationPeriod;
    UpdateKey(&key, new_last_rotation, kDefaultRotationPeriod);
  }

  // Return the key unless it's the wrong size, in which case return nullopt.
  const std::string key_string = key.key();
  if (key_string.size() != kKeySize)
    return base::nullopt;
  return key_string;
}

void KeyData::UpdateKey(KeyProto* key,
                        const int last_rotation,
                        const int rotation_period) {
  key->set_key(GenerateKey());
  key->set_last_rotation(last_rotation);
  key->set_rotation_period(rotation_period);
  proto_->Write();
}

//----------------
// IDs and hashing
//----------------

uint64_t KeyData::Id(const uint64_t project_name_hash) {
  // Retrieve the key for |project_name_hash|.
  const base::Optional<std::string> key = ValidateAndGetKey(project_name_hash);
  if (!key) {
    NOTREACHED();
    return 0u;
  }

  // Compute and return the hash.
  uint64_t hash;
  crypto::SHA256HashString(key.value(), &hash, sizeof(uint64_t));
  return hash;
}

uint64_t KeyData::HmacMetric(const uint64_t project_name_hash,
                             const uint64_t metric_name_hash,
                             const std::string& value) {
  // Retrieve the key for |project_name_hash|.
  const base::Optional<std::string> key = ValidateAndGetKey(project_name_hash);
  if (!key) {
    NOTREACHED();
    return 0u;
  }

  // Initialize the HMAC.
  crypto::HMAC hmac(crypto::HMAC::HashAlgorithm::SHA256);
  CHECK(hmac.Init(key.value()));

  // Compute and return the digest.
  const std::string salted_value =
      base::StrCat({HashToHex(metric_name_hash), value});
  uint64_t digest;
  CHECK(hmac.Sign(salted_value, reinterpret_cast<uint8_t*>(&digest),
                  sizeof(digest)));
  return digest;
}

}  // namespace structured
}  // namespace metrics
