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

#if SB_API_VERSION >= 11

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.";
  }
}

#endif  // SB_API_VERSION >= 11

}  // namespace browser
}  // namespace cobalt
