// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// 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 "cobalt/browser/device_authentication.h"

#include <algorithm>
#include <map>

#include "base/base64.h"
#include "base/base64url.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "crypto/hmac.h"
#include "net/base/escape.h"
#include "starboard/system.h"

namespace cobalt {
namespace browser {

namespace {

constexpr size_t kSHA256DigestSize = 32;

bool ComputeSignatureWithSystemPropertySecret(const std::string& message,
                                              uint8_t* signature) {
  const size_t kBase64EncodedCertificationSecretLength = 1023;
  char base_64_secret_property[kBase64EncodedCertificationSecretLength + 1] = {
      0};
  bool result = SbSystemGetProperty(
      kSbSystemPropertyBase64EncodedCertificationSecret,
      base_64_secret_property, kBase64EncodedCertificationSecretLength);
  if (!result) {
    return false;
  }

  ComputeHMACSHA256SignatureWithProvidedKey(message, base_64_secret_property,
                                            signature, kSHA256DigestSize);
  return true;
}

bool ComputeSignatureFromSignAPI(const std::string& message,
                                 uint8_t* signature) {
  return SbSystemSignWithCertificationSecretKey(
      reinterpret_cast<const uint8_t*>(message.data()), message.size(),
      signature, kSHA256DigestSize);
}

// Check to see if we can query the platform for the secret key.  If so,
// go ahead and use it to sign the message, otherwise try to use the
// SbSystemSignWithCertificationSecretKey() method to sign the message.  If
// both methods fail, return an empty string.
std::string ComputeBase64Signature(const std::string& message) {
  uint8_t signature[kSHA256DigestSize];

  if (ComputeSignatureFromSignAPI(message, signature)) {
    DLOG(INFO) << "Using certification signature provided by "
               << "SbSystemSignWithCertificationSecretKey().";
  } else if (ComputeSignatureWithSystemPropertySecret(message, signature)) {
    DLOG(INFO) << "Using certification key from SbSystemGetProperty().";
  } else {
    return std::string();
  }

  std::string base_64_url_signature;
  base::Base64UrlEncode(std::string(signature, signature + kSHA256DigestSize),
                        base::Base64UrlEncodePolicy::OMIT_PADDING,
                        &base_64_url_signature);
  return base_64_url_signature;
}

std::string NumberToFourByteString(size_t n) {
  std::string str;
  str += static_cast<char>(((n & 0xff000000) >> 24));
  str += static_cast<char>(((n & 0x00ff0000) >> 16));
  str += static_cast<char>(((n & 0x0000ff00) >> 8));
  str += static_cast<char>((n & 0x000000ff));
  return str;
}

// Used by ComputeMessage() to create a message component as a string.
std::string BuildMessageFragment(const std::string& key,
                                 const std::string& value) {
  std::string msg_fragment = NumberToFourByteString(key.length()) + key +
                             NumberToFourByteString(value.length()) + value;
  return msg_fragment;
}

// Returns the certification scope provided by the platform to use with device
// authentication.
std::string GetCertScopeFromPlatform() {
  // Get cert_scope and base_64_secret
  const size_t kCertificationScopeLength = 1023;
  char cert_scope_property[kCertificationScopeLength + 1] = {0};
  bool result =
      SbSystemGetProperty(kSbSystemPropertyCertificationScope,
                          cert_scope_property, kCertificationScopeLength);
  if (!result) {
    DLOG(ERROR) << "Unable to get kSbSystemPropertyCertificationScope";
    return std::string();
  }

  return cert_scope_property;
}

// Returns the start time provided by the platform for use with device
// authentication.
std::string GetStartTime() {
  return std::to_string(static_cast<int64_t>(base::Time::Now().ToDoubleT()));
}

}  // namespace

std::string GetDeviceAuthenticationSignedURLQueryString() {
  std::string cert_scope = GetCertScopeFromPlatform();
  if (cert_scope.empty()) {
    LOG(WARNING) << "Error retrieving certification scope required for "
                 << "device authentication.";
    return std::string();
  }
  std::string start_time = GetStartTime();
  CHECK(!start_time.empty());

  std::string base64_signature =
      ComputeBase64Signature(ComputeMessage(cert_scope, start_time));

  return GetDeviceAuthenticationSignedURLQueryStringFromComponents(
      cert_scope, start_time, base64_signature);
}

std::string GetDeviceAuthenticationSignedURLQueryStringFromComponents(
    const std::string& cert_scope, const std::string& start_time,
    const std::string& base64_signature) {
  CHECK(!cert_scope.empty());
  CHECK(!start_time.empty());

  if (base64_signature.empty()) {
    return std::string();
  }

  std::map<std::string, std::string> signed_query_components;
  signed_query_components["cert_scope"] = cert_scope;
  signed_query_components["start_time"] = start_time;
  signed_query_components["sig"] = base64_signature;

  std::string query;
  for (const auto& query_component : signed_query_components) {
    const std::string& key = query_component.first;
    const std::string& value = query_component.second;

    if (!query.empty()) query += "&";
    query += net::EscapeQueryParamValue(key, true);
    if (!value.empty()) {
      query += "=" + net::EscapeQueryParamValue(value, true);
    }
  }

  return query;
}

// Combine multiple message components into a string that will be used as the
// message that we will sign.
std::string ComputeMessage(const std::string& cert_scope,
                           const std::string& start_time) {
  // Build message from cert_scope and start_time.
  return BuildMessageFragment("cert_scope", cert_scope) +
         BuildMessageFragment("start_time", start_time);
}

void ComputeHMACSHA256SignatureWithProvidedKey(const std::string& message,
                                               const std::string& base64_key,
                                               uint8_t* signature,
                                               size_t signature_size_in_bytes) {
  CHECK_GE(signature_size_in_bytes, 32U);

  std::string key;
  base::Base64Decode(base64_key, &key);

  // Generate signature from message using HMAC-SHA256.
  crypto::HMAC hmac(crypto::HMAC::SHA256);
  if (!hmac.Init(key)) {
    DLOG(ERROR) << "Unable to initialize HMAC-SHA256.";
  }
  if (!hmac.Sign(message, signature, signature_size_in_bytes)) {
    DLOG(ERROR) << "Unable to sign HMAC-SHA256.";
  }
}

}  // namespace browser
}  // namespace cobalt
