// 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 "net/cert/internal/trust_store_in_memory_starboard.h"

#include "base/files/file_path.h"
#include "base/path_service.h"
#include "base/time/time.h"
#include "net/cert/internal/cert_errors.h"
#include "net/cert/pem_tokenizer.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "starboard/directory.h"
#include "starboard/file.h"
#include "starboard/string.h"
#include "third_party/boringssl/src/include/openssl/digest.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
#include "third_party/boringssl/src/include/openssl/x509.h"

namespace net {

namespace {
// PEM encoded DER cert is usually around or less than 2000 bytes long.
const short kCertBufferSize = 8 * 1024;
// Each certificate file name is 8 bit hash + ".0" suffix.
const short kCertFileNameLength = 10;
const char kCertificateHeader[] = "CERTIFICATE";
const char kSSLDirName[] = "ssl";
const char kCertsDirName[] = "certs";

// Essentially an X509_NAME_hash without using X509_NAME. We did not use the
// boringSSL function directly because net does not store certs with X509
// struct anymore and converting binary certs to X509_NAME is slightly
// expensive.
unsigned long CertNameHash(const void* data, size_t length) {
  unsigned long ret = 0;
  unsigned char md[SHA_DIGEST_LENGTH];
  if (!EVP_Digest(data, length, md, NULL, EVP_sha1(), NULL))
    return 0;

  ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
         ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)) &
        0xffffffffL;
  return ret;
}

base::FilePath GetCertificateDirPath() {
  base::FilePath cert_path;
  base::PathService::Get(base::DIR_EXE, &cert_path);
  cert_path = cert_path.Append(kSSLDirName).Append(kCertsDirName);
  return std::move(cert_path);
}

std::unordered_set<std::string> GetCertNamesOnDisk() {
  auto sb_certs_directory =
      SbDirectoryOpen(GetCertificateDirPath().value().c_str(), nullptr);
  if (!SbDirectoryIsValid(sb_certs_directory)) {
// Unit tests, for example, do not use production certificates.
#if defined(STARBOARD_BUILD_TYPE_QA) || defined(STARBOARD_BUILD_TYPE_GOLD)
    SB_CHECK(false);
#else
    DLOG(WARNING) << "ssl/certs directory is not valid, no root certificates"
                     " will be loaded";
#endif
    return std::unordered_set<std::string>();
  }

  std::unordered_set<std::string> trusted_certs_on_disk;
#if SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
  std::vector<char> dir_entry(SB_FILE_MAX_NAME);

  while (SbDirectoryGetNext(sb_certs_directory, dir_entry.data(),
                            dir_entry.size())) {
    if (SbStringGetLength(dir_entry.data()) != kCertFileNameLength) {
      continue;
    }
    trusted_certs_on_disk.emplace(dir_entry.data());
  }
#else   // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION
  SbDirectoryEntry dir_entry;

  while (SbDirectoryGetNext(sb_certs_directory, &dir_entry)) {
    if (SbStringGetLength(dir_entry.name) != kCertFileNameLength) {
      continue;
    }
    trusted_certs_on_disk.emplace(dir_entry.name);
  }
#endif  // SB_API_VERSION >= SB_FEATURE_RUNTIME_CONFIGS_VERSION

  SbDirectoryClose(sb_certs_directory);
  return std::move(trusted_certs_on_disk);
}
}  // namespace

scoped_refptr<ParsedCertificate> TrustStoreInMemoryStarboard::TryLoadCert(
    const base::StringPiece& cert_name) const {
  auto hash = CertNameHash(cert_name.data(), cert_name.length());
  char cert_file_name[256];
  SbStringFormatF(cert_file_name, 256, "%08lx.%d", hash, 0);

  if (trusted_cert_names_on_disk_.find(cert_file_name) ==
      trusted_cert_names_on_disk_.end()) {
    // The requested certificate is not found.
    return nullptr;
  }

  SbFileError out_error;
  char cert_buffer[kCertBufferSize];
  base::FilePath cert_path = GetCertificateDirPath().Append(cert_file_name);
  SbFile sb_cert_file =
      SbFileOpen(cert_path.value().c_str(), kSbFileOpenOnly | kSbFileRead,
                 nullptr, &out_error);
  // The file was in certs directory when we iterated the directory at startup,
  // opening it should not fail.
  if (!SbFileIsValid(sb_cert_file)) {
    NOTREACHED() << "ssl/certs/" << cert_path << " failed to open.";
    return nullptr;
  }
  int cert_size = SbFileReadAll(sb_cert_file, cert_buffer, kCertBufferSize);
  SbFileClose(sb_cert_file);
  PEMTokenizer pem_tokenizer(base::StringPiece(cert_buffer, cert_size),
                             {kCertificateHeader});
  pem_tokenizer.GetNext();
  std::string decoded(pem_tokenizer.data());
  DCHECK(!pem_tokenizer.GetNext());
  bssl::UniquePtr<CRYPTO_BUFFER> crypto_buffer =
      X509Certificate::CreateCertBufferFromBytes(decoded.data(),
                                                 decoded.length());
  DCHECK(crypto_buffer);
  CertErrors errors;
  auto parsed = ParsedCertificate::Create(
      bssl::UpRef(crypto_buffer.get()),
      x509_util::DefaultParseCertificateOptions(), &errors);
  CHECK(parsed) << errors.ToDebugString();
  return parsed;
}

TrustStoreInMemoryStarboard::TrustStoreInMemoryStarboard()
    : trusted_cert_names_on_disk_(std::move(GetCertNamesOnDisk())) {}

TrustStoreInMemoryStarboard::~TrustStoreInMemoryStarboard() = default;

void TrustStoreInMemoryStarboard::SyncGetIssuersOf(
    const ParsedCertificate* cert,
    ParsedCertificateList* issuers) {
  DCHECK(issuers);
  DCHECK(issuers->empty());
  starboard::ScopedLock scoped_lock(load_mutex_);
  // Look up the request certificate first in the trust store in memory.
  underlying_trust_store_.SyncGetIssuersOf(cert, issuers);
  if (issuers->empty()) {
    // If the requested certificate is not found, compute certificate hash name
    // and see if the certificate is stored on disk.
    auto parsed_cert = TryLoadCert(cert->normalized_issuer().AsStringPiece());
    if (parsed_cert.get()) {
      issuers->push_back(parsed_cert);
      underlying_trust_store_.AddTrustAnchor(parsed_cert);
    }
  }
}

void TrustStoreInMemoryStarboard::GetTrust(
    const scoped_refptr<ParsedCertificate>& cert,
    CertificateTrust* trust) const {
  DCHECK(trust);
  starboard::ScopedLock scoped_lock(load_mutex_);
  // Loop up the request certificate first in the trust store in memory.
  underlying_trust_store_.GetTrust(cert, trust);
  if (trust->HasUnspecifiedTrust()) {
    // If the requested certificate is not found, compute certificate hash name
    // and see if the certificate is stored on disk.
    auto parsed_cert = TryLoadCert(cert->normalized_subject().AsStringPiece());
    if (parsed_cert.get()) {
      *trust = CertificateTrust::ForTrustAnchor();
      const_cast<TrustStoreInMemoryStarboard*>(this)
          ->underlying_trust_store_.AddTrustAnchor(parsed_cert);
    }
  }
}

}  // namespace net
