/*
 *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/boringssl_identity.h"

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/pool.h>
#include <stdint.h>
#include <string.h>

#include <memory>
#include <utility>
#include <vector>

#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/openssl.h"
#include "rtc_base/openssl_utility.h"

namespace rtc {

BoringSSLIdentity::BoringSSLIdentity(
    std::unique_ptr<OpenSSLKeyPair> key_pair,
    std::unique_ptr<BoringSSLCertificate> certificate)
    : key_pair_(std::move(key_pair)) {
  RTC_DCHECK(key_pair_ != nullptr);
  RTC_DCHECK(certificate != nullptr);
  std::vector<std::unique_ptr<SSLCertificate>> certs;
  certs.push_back(std::move(certificate));
  cert_chain_.reset(new SSLCertChain(std::move(certs)));
}

BoringSSLIdentity::BoringSSLIdentity(std::unique_ptr<OpenSSLKeyPair> key_pair,
                                     std::unique_ptr<SSLCertChain> cert_chain)
    : key_pair_(std::move(key_pair)), cert_chain_(std::move(cert_chain)) {
  RTC_DCHECK(key_pair_ != nullptr);
  RTC_DCHECK(cert_chain_ != nullptr);
}

BoringSSLIdentity::~BoringSSLIdentity() = default;

std::unique_ptr<BoringSSLIdentity> BoringSSLIdentity::CreateInternal(
    const SSLIdentityParams& params) {
  auto key_pair = OpenSSLKeyPair::Generate(params.key_params);
  if (key_pair) {
    std::unique_ptr<BoringSSLCertificate> certificate(
        BoringSSLCertificate::Generate(key_pair.get(), params));
    if (certificate != nullptr) {
      return absl::WrapUnique(
          new BoringSSLIdentity(std::move(key_pair), std::move(certificate)));
    }
  }
  RTC_LOG(LS_ERROR) << "Identity generation failed.";
  return nullptr;
}

// static
std::unique_ptr<BoringSSLIdentity> BoringSSLIdentity::CreateWithExpiration(
    absl::string_view common_name,
    const KeyParams& key_params,
    time_t certificate_lifetime) {
  SSLIdentityParams params;
  params.key_params = key_params;
  params.common_name = std::string(common_name);
  time_t now = time(nullptr);
  params.not_before = now + kCertificateWindowInSeconds;
  params.not_after = now + certificate_lifetime;
  if (params.not_before > params.not_after)
    return nullptr;
  return CreateInternal(params);
}

std::unique_ptr<BoringSSLIdentity> BoringSSLIdentity::CreateForTest(
    const SSLIdentityParams& params) {
  return CreateInternal(params);
}

std::unique_ptr<SSLIdentity> BoringSSLIdentity::CreateFromPEMStrings(
    absl::string_view private_key,
    absl::string_view certificate) {
  std::unique_ptr<BoringSSLCertificate> cert(
      BoringSSLCertificate::FromPEMString(certificate));
  if (!cert) {
    RTC_LOG(LS_ERROR)
        << "Failed to create BoringSSLCertificate from PEM string.";
    return nullptr;
  }

  auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key);
  if (!key_pair) {
    RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string.";
    return nullptr;
  }

  return absl::WrapUnique(
      new BoringSSLIdentity(std::move(key_pair), std::move(cert)));
}

std::unique_ptr<SSLIdentity> BoringSSLIdentity::CreateFromPEMChainStrings(
    absl::string_view private_key,
    absl::string_view certificate_chain) {
  bssl::UniquePtr<BIO> bio(
      BIO_new_mem_buf(certificate_chain.data(),
                      rtc::dchecked_cast<int>(certificate_chain.size())));
  if (!bio) {
    return nullptr;
  }
  BIO_set_mem_eof_return(bio.get(), 0);
  std::vector<std::unique_ptr<SSLCertificate>> certs;
  while (true) {
    char* name;
    char* header;
    unsigned char* data;
    long len;  // NOLINT
    int ret = PEM_read_bio(bio.get(), &name, &header, &data, &len);
    if (ret == 0) {
      uint32_t err = ERR_peek_error();
      if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
          ERR_GET_REASON(err) == PEM_R_NO_START_LINE) {
        err = ERR_get_error();
        break;
      }
      RTC_LOG(LS_ERROR) << "Failed to parse certificate from PEM string.";
      return nullptr;
    }
    bssl::UniquePtr<char> owned_name(name);
    bssl::UniquePtr<char> owned_header(header);
    bssl::UniquePtr<unsigned char> owned_data(data);
    if (strcmp(owned_name.get(), PEM_STRING_X509) != 0) {
      RTC_LOG(LS_ERROR)
          << "Non-certificate found while parsing certificate chain: "
          << owned_name.get();
      return nullptr;
    }
    bssl::UniquePtr<CRYPTO_BUFFER> crypto_buffer(
        CRYPTO_BUFFER_new(data, len, openssl::GetBufferPool()));
    if (!crypto_buffer) {
      return nullptr;
    }
    certs.emplace_back(new BoringSSLCertificate(std::move(crypto_buffer)));
  }
  if (certs.empty()) {
    RTC_LOG(LS_ERROR) << "Found no certificates in PEM string.";
    return nullptr;
  }

  auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key);
  if (!key_pair) {
    RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string.";
    return nullptr;
  }

  return absl::WrapUnique(new BoringSSLIdentity(
      std::move(key_pair), std::make_unique<SSLCertChain>(std::move(certs))));
}

const BoringSSLCertificate& BoringSSLIdentity::certificate() const {
  return *static_cast<const BoringSSLCertificate*>(&cert_chain_->Get(0));
}

const SSLCertChain& BoringSSLIdentity::cert_chain() const {
  return *cert_chain_.get();
}

std::unique_ptr<SSLIdentity> BoringSSLIdentity::CloneInternal() const {
  // We cannot use std::make_unique here because the referenced
  // BoringSSLIdentity constructor is private.
  return absl::WrapUnique(
      new BoringSSLIdentity(key_pair_->Clone(), cert_chain_->Clone()));
}

bool BoringSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) {
  std::vector<CRYPTO_BUFFER*> cert_buffers;
  for (size_t i = 0; i < cert_chain_->GetSize(); ++i) {
    cert_buffers.push_back(
        static_cast<const BoringSSLCertificate*>(&cert_chain_->Get(i))
            ->cert_buffer());
  }
  // 1 is the documented success return code.
  if (1 != SSL_CTX_set_chain_and_key(ctx, &cert_buffers[0], cert_buffers.size(),
                                     key_pair_->pkey(), nullptr)) {
    openssl::LogSSLErrors("Configuring key and certificate");
    return false;
  }
  return true;
}

std::string BoringSSLIdentity::PrivateKeyToPEMString() const {
  return key_pair_->PrivateKeyToPEMString();
}

std::string BoringSSLIdentity::PublicKeyToPEMString() const {
  return key_pair_->PublicKeyToPEMString();
}

bool BoringSSLIdentity::operator==(const BoringSSLIdentity& other) const {
  return *this->key_pair_ == *other.key_pair_ &&
         this->certificate() == other.certificate();
}

bool BoringSSLIdentity::operator!=(const BoringSSLIdentity& other) const {
  return !(*this == other);
}

}  // namespace rtc
