//
// Copyright (C) 2012 The Android Open Source Project
//
// 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 "update_engine/certificate_checker.h"

#include <string>

#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <android-base/stringprintf.h>
#include <curl/curl.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>

#include "update_engine/common/constants.h"
#include "update_engine/common/prefs_interface.h"
#include "update_engine/common/utils.h"

using std::string;

namespace chromeos_update_engine {

bool OpenSSLWrapper::GetCertificateDigest(X509_STORE_CTX* x509_ctx,
                                          int* out_depth,
                                          unsigned int* out_digest_length,
                                          uint8_t* out_digest) const {
  TEST_AND_RETURN_FALSE(out_digest);
  X509* certificate = X509_STORE_CTX_get_current_cert(x509_ctx);
  TEST_AND_RETURN_FALSE(certificate);
  int depth = X509_STORE_CTX_get_error_depth(x509_ctx);
  if (out_depth)
    *out_depth = depth;

  unsigned int len;
  const EVP_MD* digest_function = EVP_sha256();
  bool success = X509_digest(certificate, digest_function, out_digest, &len);

  if (success && out_digest_length)
    *out_digest_length = len;
  return success;
}

// static
CertificateChecker* CertificateChecker::cert_checker_singleton_ = nullptr;

CertificateChecker::CertificateChecker(PrefsInterface* prefs,
                                       OpenSSLWrapper* openssl_wrapper)
    : prefs_(prefs), openssl_wrapper_(openssl_wrapper) {}

CertificateChecker::~CertificateChecker() {
  if (cert_checker_singleton_ == this)
    cert_checker_singleton_ = nullptr;
}

void CertificateChecker::Init() {
  CHECK(cert_checker_singleton_ == nullptr);
  cert_checker_singleton_ = this;
}

// static
CURLcode CertificateChecker::ProcessSSLContext(CURL* curl_handle,
                                               SSL_CTX* ssl_ctx,
                                               void* ptr) {
  ServerToCheck* server_to_check = reinterpret_cast<ServerToCheck*>(ptr);

  if (!cert_checker_singleton_) {
    DLOG(WARNING) << "No CertificateChecker singleton initialized.";
    return CURLE_FAILED_INIT;
  }

  // From here we set the SSL_CTX to another callback, from the openssl library,
  // which will be called after each server certificate is validated. However,
  // since openssl does not allow us to pass our own data pointer to the
  // callback, the certificate check will have to be done statically. Since we
  // need to know which update server we are using in order to check the
  // certificate, we hardcode Chrome OS's two known update servers here, and
  // define a different static callback for each. Since this code should only
  // run in official builds, this should not be a problem. However, if an update
  // server different from the ones listed here is used, the check will not
  // take place.
  int (*verify_callback)(int, X509_STORE_CTX*);
  switch (*server_to_check) {
    case ServerToCheck::kDownload:
      verify_callback = &CertificateChecker::VerifySSLCallbackDownload;
      break;
    case ServerToCheck::kUpdate:
      verify_callback = &CertificateChecker::VerifySSLCallbackUpdate;
      break;
    case ServerToCheck::kNone:
      verify_callback = nullptr;
      break;
  }

  SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, verify_callback);
  return CURLE_OK;
}

// static
int CertificateChecker::VerifySSLCallbackDownload(int preverify_ok,
                                                  X509_STORE_CTX* x509_ctx) {
  return VerifySSLCallback(preverify_ok, x509_ctx, ServerToCheck::kDownload);
}

// static
int CertificateChecker::VerifySSLCallbackUpdate(int preverify_ok,
                                                X509_STORE_CTX* x509_ctx) {
  return VerifySSLCallback(preverify_ok, x509_ctx, ServerToCheck::kUpdate);
}

// static
int CertificateChecker::VerifySSLCallback(int preverify_ok,
                                          X509_STORE_CTX* x509_ctx,
                                          ServerToCheck server_to_check) {
  CHECK(cert_checker_singleton_ != nullptr);
  return cert_checker_singleton_->CheckCertificateChange(
             preverify_ok, x509_ctx, server_to_check)
             ? 1
             : 0;
}

bool CertificateChecker::CheckCertificateChange(int preverify_ok,
                                                X509_STORE_CTX* x509_ctx,
                                                ServerToCheck server_to_check) {
  TEST_AND_RETURN_FALSE(prefs_ != nullptr);

  // If pre-verification failed, we are not interested in the current
  // certificate. We store a report to UMA and just propagate the fail result.
  if (!preverify_ok) {
    NotifyCertificateChecked(server_to_check, CertificateCheckResult::kFailed);
    return false;
  }

  int depth;
  unsigned int digest_length;
  uint8_t digest[EVP_MAX_MD_SIZE];

  if (!openssl_wrapper_->GetCertificateDigest(
          x509_ctx, &depth, &digest_length, digest)) {
    LOG(WARNING) << "Failed to generate digest of X509 certificate "
                 << "from update server.";
    NotifyCertificateChecked(server_to_check, CertificateCheckResult::kValid);
    return true;
  }

  // We convert the raw bytes of the digest to an hex string, for storage in
  // prefs.
  string digest_string = base::HexEncode(digest, digest_length);

  string storage_key =
      android::base::StringPrintf("%s-%d-%d",
                                  kPrefsUpdateServerCertificate,
                                  static_cast<int>(server_to_check),
                                  depth);
  string stored_digest;
  // If there's no stored certificate, we just store the current one and return.
  if (!prefs_->GetString(storage_key, &stored_digest)) {
    if (!prefs_->SetString(storage_key, digest_string)) {
      LOG(WARNING) << "Failed to store server certificate on storage key "
                   << storage_key;
    }
    NotifyCertificateChecked(server_to_check, CertificateCheckResult::kValid);
    return true;
  }

  // Certificate changed, we store a report to UMA and store the most recent
  // certificate.
  if (stored_digest != digest_string) {
    if (!prefs_->SetString(storage_key, digest_string)) {
      LOG(WARNING) << "Failed to store server certificate on storage key "
                   << storage_key;
    }
    LOG(INFO) << "Certificate changed from " << stored_digest << " to "
              << digest_string << ".";
    NotifyCertificateChecked(server_to_check,
                             CertificateCheckResult::kValidChanged);
    return true;
  }

  NotifyCertificateChecked(server_to_check, CertificateCheckResult::kValid);
  // Since we don't perform actual SSL verification, we return success.
  return true;
}

void CertificateChecker::NotifyCertificateChecked(
    ServerToCheck server_to_check, CertificateCheckResult result) {
  if (observer_)
    observer_->CertificateChecked(server_to_check, result);
}

}  // namespace chromeos_update_engine
