Split payload application code into a subdirectory.

This patch splits from the main libupdate_engine code the part that
is strictly used to download and apply a payload into a new static
library, moving the code to subdirectories. The new library is divided
in two subdirectories: common/ and payload_consumer/, and should not
depend on other update_engine files outside those two subdirectories.
The main difference between those two is that the common/ tools are more
generic and not tied to the payload consumer process, but otherwise they
are both compiled together.

There are still dependencies from the new libpayload_consumer library
into the main directory files and DBus generated files. Those will be
addressed in follow up CLs.

Bug: 25197634
Test: FEATURES=test emerge-link update_engine; `mm` on Brillo.

Change-Id: Id8d0204ea573627e6e26ca9ea17b9592ca95bc23
diff --git a/common/certificate_checker.cc b/common/certificate_checker.cc
new file mode 100644
index 0000000..87f9848
--- /dev/null
+++ b/common/certificate_checker.cc
@@ -0,0 +1,202 @@
+//
+// 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/common/certificate_checker.h"
+
+#include <string>
+
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/strings/string_util.h>
+#include <base/strings/stringprintf.h>
+#include <curl/curl.h>
+#include <openssl/evp.h>
+#include <openssl/ssl.h>
+
+#include "metrics/metrics_library.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 {
+
+namespace {
+// This should be in the same order of CertificateChecker::ServerToCheck, with
+// the exception of kNone.
+static const char* kReportToSendKey[2] =
+    {kPrefsCertificateReportToSendUpdate,
+     kPrefsCertificateReportToSendDownload};
+}  // namespace
+
+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
+SystemState* CertificateChecker::system_state_ = nullptr;
+
+// static
+OpenSSLWrapper* CertificateChecker::openssl_wrapper_ = nullptr;
+
+// static
+CURLcode CertificateChecker::ProcessSSLContext(CURL* curl_handle,
+                                               SSL_CTX* ssl_ctx,
+                                               void* ptr) {
+  // 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.
+  ServerToCheck* server_to_check = reinterpret_cast<ServerToCheck*>(ptr);
+
+  // We check which server to check and set the appropriate static callback.
+  if (*server_to_check == kUpdate)
+    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, VerifySSLCallbackUpdateCheck);
+  if (*server_to_check == kDownload)
+    SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, VerifySSLCallbackDownload);
+
+  return CURLE_OK;
+}
+
+// static
+int CertificateChecker::VerifySSLCallbackUpdateCheck(int preverify_ok,
+                                                     X509_STORE_CTX* x509_ctx) {
+  return CertificateChecker::CheckCertificateChange(
+      kUpdate, preverify_ok, x509_ctx) ? 1 : 0;
+}
+
+// static
+int CertificateChecker::VerifySSLCallbackDownload(int preverify_ok,
+                                                  X509_STORE_CTX* x509_ctx) {
+  return CertificateChecker::CheckCertificateChange(
+      kDownload, preverify_ok, x509_ctx) ? 1 : 0;
+}
+
+// static
+bool CertificateChecker::CheckCertificateChange(
+    ServerToCheck server_to_check, int preverify_ok,
+    X509_STORE_CTX* x509_ctx) {
+  static const char kUMAActionCertChanged[] =
+      "Updater.ServerCertificateChanged";
+  static const char kUMAActionCertFailed[] = "Updater.ServerCertificateFailed";
+  TEST_AND_RETURN_FALSE(system_state_ != nullptr);
+  TEST_AND_RETURN_FALSE(system_state_->prefs() != nullptr);
+  TEST_AND_RETURN_FALSE(server_to_check != kNone);
+
+  // 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) {
+    LOG_IF(WARNING, !system_state_->prefs()->SetString(
+        kReportToSendKey[server_to_check], kUMAActionCertFailed))
+        << "Failed to store UMA report on a failure to validate "
+        << "certificate from update server.";
+    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.";
+    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 = base::StringPrintf("%s-%d-%d",
+                                          kPrefsUpdateServerCertificate,
+                                          server_to_check,
+                                          depth);
+  string stored_digest;
+  // If there's no stored certificate, we just store the current one and return.
+  if (!system_state_->prefs()->GetString(storage_key, &stored_digest)) {
+    LOG_IF(WARNING, !system_state_->prefs()->SetString(storage_key,
+                                                       digest_string))
+        << "Failed to store server certificate on storage key " << storage_key;
+    return true;
+  }
+
+  // Certificate changed, we store a report to UMA and store the most recent
+  // certificate.
+  if (stored_digest != digest_string) {
+    LOG_IF(WARNING, !system_state_->prefs()->SetString(
+        kReportToSendKey[server_to_check], kUMAActionCertChanged))
+        << "Failed to store UMA report on a change on the "
+        << "certificate from update server.";
+    LOG_IF(WARNING, !system_state_->prefs()->SetString(storage_key,
+                                                       digest_string))
+        << "Failed to store server certificate on storage key " << storage_key;
+  }
+
+  // Since we don't perform actual SSL verification, we return success.
+  return true;
+}
+
+// static
+void CertificateChecker::FlushReport() {
+  // This check shouldn't be needed, but it is useful for testing.
+  TEST_AND_RETURN(system_state_);
+  TEST_AND_RETURN(system_state_->metrics_lib());
+  TEST_AND_RETURN(system_state_->prefs());
+
+  // We flush reports for both servers.
+  for (size_t i = 0; i < arraysize(kReportToSendKey); i++) {
+    string report_to_send;
+    if (system_state_->prefs()->GetString(kReportToSendKey[i], &report_to_send)
+        && !report_to_send.empty()) {
+      // There is a report to be sent. We send it and erase it.
+      LOG(INFO) << "Found report #" << i << ". Sending it";
+      LOG_IF(WARNING, !system_state_->metrics_lib()->SendUserActionToUMA(
+          report_to_send))
+          << "Failed to send server certificate report to UMA: "
+          << report_to_send;
+      LOG_IF(WARNING, !system_state_->prefs()->Delete(kReportToSendKey[i]))
+          << "Failed to erase server certificate report to be sent to UMA";
+    }
+  }
+}
+
+}  // namespace chromeos_update_engine