Automated commit: libchrome r1453062 uprev

Merge with upstream commit 3857e595cdb02d5b1d0535395d743600748cc7c7

New patches:
- backward-compatibility-1800-Revert-base-remove-base-numerics-aliases.patch

BUG=414697720
TEST=sudo emerge libchrome

Change-Id: I3e8293775f0f5208f5c1b734cb7fadf2f94858f1
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/libchrome/+/6498606
Reviewed-by: Di Wu <diwux@google.com>
Commit-Queue: Jeff Lin <jeffulin@google.com>
Tested-by: Georg Neis <neis@chromium.org>
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/BASE_VER b/BASE_VER
new file mode 100644
index 0000000..d28b5c4
--- /dev/null
+++ b/BASE_VER
@@ -0,0 +1 @@
+1453062
diff --git a/BUILD.IGNORE b/BUILD.IGNORE
new file mode 100644
index 0000000..d84edf6
--- /dev/null
+++ b/BUILD.IGNORE
@@ -0,0 +1,10 @@
+android
+components/policy
+fuzzer
+perftest
+power_monitor
+test_runner
+tests
+trace_event
+ui/gfx
+unittest
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..4cb95e2
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,1583 @@
+# Copyright 2018 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# BUILD.gn doesn't compile all files in the directory to reduce build size.
+# Missing files can be added if needed.
+
+import("//common-mk/mojom_bindings_generator.gni")
+import("//common-mk/mojom_type_mappings_generator.gni")
+import("//common-mk/pkg_config.gni")
+import("//common-mk/proto_library.gni")
+import("//libchrome/base/allocator/partition_allocator/src/partition_alloc/buildflag_header.gni")
+import("//libchrome/build/buildflag_header.gni")
+
+libchrome_basever = read_file("BASE_VER", "trim string")
+
+# Enable //base/allocator shim for non-sanitizer builds.
+use_allocator_shim = !(use.asan || use.fuzzer || use.msan || use.ubsan)
+
+# We don't require legacy Mojo Core support if ipcz is enabled.
+mojo_support_legacy_core = !use.ipcz
+
+group("all") {
+  deps = [
+    ":install_basever",
+    ":install_buildflag_header",
+    ":install_header",
+    ":install_protozero_generated",
+    ":libchrome",
+    ":libchrome-test",
+  ]
+  if (use.mojo) {
+    deps += [
+      ":install_mojom_generated",
+      ":libmojo",
+    ]
+  }
+}
+
+group("all_buildflags") {
+  deps = [
+    ":allocator_buildflags",
+    ":allocator_logging_buildflags",
+    ":blink_buildflags",
+    ":branding_buildflags",
+    ":cfi_buildflags",
+    ":chromecast_buildflags",
+    ":chromeos_buildflags",
+    ":clang_profiling_buildflags",
+    ":compiler_buildflags",
+    ":debugging_buildflags",
+    ":feature_list_buildflags",
+    ":fuzzing_buildflags",
+    ":ios_buildflags",
+    ":ios_cronet_buildflags",
+    ":ipc_buildflags",
+    ":message_pump_buildflags",
+    ":mojo_buildflags",
+    ":mojo_cpp_bindings_buildflags",
+    ":partition_allocator_buildflags",
+    ":profiler_buildflags",
+    ":rust_buildflags",
+    ":synchronization_buildflags",
+    ":tracing_buildflags",
+    ":protected_memory_buildflags",
+  ]
+}
+
+config("libchrome_config") {
+  # TODO(hidehiko): Consolidate with build_config.h.
+  defines = [
+    "OS_CHROMEOS",
+    "USE_NSS_CERTS",
+    "USE_SYSTEM_LIBEVENT",
+    "NO_TCMALLOC",
+    "MOJO_BACKWARDS_COMPAT",
+    "BASE_USE_PERFETTO_CLIENT_LIBRARY",
+    "PERFETTO_ENABLE_LEGACY_TRACE_EVENTS",
+  ]
+  if (use.asan) {
+    defines += [
+      "LEAK_SANITIZER",
+      "DISABLE_ALLOCATOR_SANITIZER",
+    ]
+  }
+  if (use.ipcz) {
+    defines += [ "ENABLE_IPCZ_ON_CHROMEOS" ]
+  }
+  if (mojo_support_legacy_core) {
+    defines += [
+      "MOJO_CORE_LEGACY_PROTOCOL",
+    ]
+  }
+
+  include_dirs = [
+    ".",
+    "${root_gen_dir}/libchrome",  # for generated buildflags headers
+    "third_party/perfetto/include",  # for generated protozero headers
+  ]
+  cflags = [
+    "-Wno-deprecated-register",
+    "-Wno-narrowing",
+    "-Wno-unreachable-code-return",
+    "-Wno-unused-local-typedefs",
+    # TODO(b/314188050): Reenable Wvla-extension after Chrome cleans it up.
+    "-Wno-error=vla-cxx-extension",
+    "-Xclang-only=-Wno-char-subscripts",
+  ]
+
+  # Prevent --gc-sections from removing unused perfetto symbols, because
+  # clients of libchrome (e.g., libbrillo) may need them. This avoids having to
+  # statically link separate copies of perfetto into each library.
+  ldflags = [ "-Wl,--undefined-glob=*perfetto*SystemProducer*" ]
+
+  # Address sanitizer + coverage builds do not support -z,defs.
+  if (!(use.asan || use.coverage)) {
+    ldflags += [ "-Wl,-z,defs" ]
+  }
+}
+
+config("base_core_config") {
+  cflags = [
+    # Suppressing warning in base/strings/stringprintf.cc.
+    "-Wno-format-nonliteral",
+
+    # This is for _exit(1) in base/debug/debugger_posix.cc.
+    "-Wno-unreachable-code",
+
+    # For double-conversion/strtod.cc
+    "-Wno-unused-function",
+  ]
+}
+
+config("base_export_config") {
+  defines = [
+    "COMPONENT_BUILD",
+    "BASE_IMPLEMENTATION",
+    "IS_PARTITION_ALLOC_IMPL",
+  ]
+}
+
+config("crypto_export_config") {
+  defines = [
+    "COMPONENT_BUILD",
+    "CRYPTO_IMPLEMENTATION",
+  ]
+}
+
+config("dbus_export_config") {
+  defines = [
+    "COMPONENT_BUILD",
+    "DBUS_IMPLEMENTATION",
+  ]
+}
+
+config("policy_export_config") {
+  defines = [
+    "COMPONENT_BUILD",
+    "POLICY_COMPONENT_IMPLEMENTATION",
+  ]
+}
+
+config("mojo_export_config") {
+  defines = [ "COMPONENT_BUILD" ]
+}
+
+source_set("buildflag_header_h") {
+  sources = [ "build/buildflag.h" ]
+}
+
+buildflag_header("allocator_buildflags") {
+  header = "base/allocator/buildflags.h"
+  flags = [
+    "USE_ALLOCATOR_SHIM=$use_allocator_shim",
+    "USE_PARTITION_ALLOC=false",
+    "USE_PARTITION_ALLOC_AS_MALLOC=false",
+    "USE_BACKUP_REF_PTR=false",
+    "USE_ASAN_BACKUP_REF_PTR=false",
+    "USE_MTE_CHECKED_PTR=false",
+  ]
+}
+
+buildflag_header("allocator_logging_buildflags") {
+  header = "base/allocator/partition_allocator/src/partition_alloc/logging_buildflags.h"
+
+  flags = [ "PA_ENABLE_LOG_ERROR_NOT_REACHED=false" ]
+}
+
+pa_buildflag_header("partition_allocator_buildflags") {
+  # Copied from base/allocator/partition_allocator/src/partition_alloc/partition_alloc.gni without
+  # using is_nacl.
+  if (current_cpu == "x64" || current_cpu == "arm64") {
+    has_64_bit_pointers = true
+  } else if (current_cpu == "x86" || current_cpu == "arm") {
+    has_64_bit_pointers = false
+  } else {
+    assert(false, "Unknown CPU: $current_cpu")
+  }
+
+  header = "base/allocator/partition_allocator/src/partition_alloc/buildflags.h"
+  flags = [
+    "HAS_64_BIT_POINTERS=$has_64_bit_pointers",
+    "USE_PARTITION_ALLOC=false",
+    "USE_PARTITION_ALLOC_AS_MALLOC=false",
+    "USE_ASAN_BACKUP_REF_PTR=false",
+    "USE_HOOKABLE_RAW_PTR=false",
+    "USE_RAW_PTR_ASAN_UNOWNED_IMPL=false",
+    "USE_RAW_PTR_BACKUP_REF_IMPL=false",
+    "USE_RAW_PTR_HOOKABLE_IMPL=false",
+    "USE_ALLOCATOR_SHIM=$use_allocator_shim",
+    "BACKUP_REF_PTR_POISON_OOB_PTR=false",
+    "ENABLE_PARTITION_ALLOC_AS_MALLOC_SUPPORT=false",
+    "ENABLE_BACKUP_REF_PTR_SUPPORT=false",
+    "ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=false",
+    "ENABLE_DANGLING_RAW_PTR_CHECKS=false",
+    "PUT_REF_COUNT_IN_PREVIOUS_SLOT=false",
+    "ENABLE_MTE_CHECKED_PTR_SUPPORT=false",
+    "RECORD_ALLOC_INFO=false",
+    "GLUE_CORE_POOLS=false",
+    "ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS=false",
+    "USE_STARSCAN=false",
+    "PA_USE_BASE_TRACING=false",
+    "ENABLE_PKEYS=false",
+    "ENABLE_POINTER_COMPRESSION=false",
+    "USE_ASAN_UNOWNED_PTR=false",
+    "FORCE_ENABLE_RAW_PTR_EXCLUSION=false",
+    "ENABLE_RAW_PTR_EXPERIMENTAL=false",
+    "ENABLE_THREAD_ISOLATION=false",
+    "USE_FREESLOT_BITMAP=false",
+    "ENABLE_POINTER_ARITHMETIC_TRAIT_CHECK=false",
+    "HAS_MEMORY_TAGGING=false",
+    "FORWARD_THROUGH_MALLOC=false",
+    "ENABLE_BACKUP_REF_PTR_INSTANCE_TRACER=false",
+    "ASSERT_CPP_20=true",
+    "USE_LARGE_EMPTY_SLOT_SPAN_RING=false",
+    "RAW_PTR_ZERO_ON_CONSTRUCT=true",
+    "RAW_PTR_ZERO_ON_MOVE=true",
+    "RAW_PTR_ZERO_ON_DESTRUCT=false",
+    "IS_CAST_ANDROID=false",
+    "IS_CASTOS=false",
+    "IS_CHROMEOS=true",
+    "DCHECKS_ARE_ON=false",
+    "DCHECK_ALWAYS_ON=false",
+    "EXPENSIVE_DCHECKS_ARE_ON=false",
+    "DCHECK_IS_CONFIGURABLE=false",
+    "CAN_UNWIND_WITH_FRAME_POINTERS=false",
+    "IS_ANDROID=false",
+    "USE_PARTITION_COOKIE=false",
+    "IS_DEBUG=false",
+    "IS_HWASAN=false",
+    "ENABLE_PARTITION_LOCK_REENTRANCY_CHECK=false",
+    "ENABLE_PARTITION_LOCK_PRIORITY_INHERITANCE=false",
+    "SHIM_SUPPORTS_SIZED_DEALLOC=false",
+  ]
+}
+
+buildflag_header("blink_buildflags") {
+  header = "build/blink_buildflags.h"
+
+  flags = [ "USE_BLINK=false" ]
+}
+
+buildflag_header("branding_buildflags") {
+  header = "build/branding_buildflags.h"
+
+  flags = [
+    "CHROMIUM_BRANDING=true",
+    "GOOGLE_CHROME_BRANDING=false",
+  ]
+}
+
+buildflag_header("cfi_buildflags") {
+  header = "base/cfi_buildflags.h"
+  flags = [
+    "CFI_DIAG=false",
+    "CFI_ICALL_CHECK=false",
+    "CFI_ENFORCEMENT_TRAP=false",
+  ]
+}
+
+buildflag_header("chromecast_buildflags") {
+  header = "build/chromecast_buildflags.h"
+  flags = [ "IS_CHROME_CAST=false" ]
+}
+
+buildflag_header("chromeos_buildflags") {
+  header = "build/chromeos_buildflags.h"
+  flags = [
+    "IS_CHROMEOS_DEVICE=false",
+    "IS_CHROMEOS_LACROS=false",
+    "IS_CHROMEOS_ASH=true",
+
+    # "IS_CHROMEOS_WITH_HW_DETAILS=",
+    # "IS_REVEN=",
+  ]
+}
+
+buildflag_header("clang_profiling_buildflags") {
+  header = "base/clang_profiling_buildflags.h"
+  flags = [
+    "CLANG_PROFILING=false",
+    # "CLANG_PROFILING_INSIDE_SANDBOX=",
+    # "USE_CLANG_COVERAGE=",
+  ]
+}
+
+buildflag_header("compiler_buildflags") {
+  header = "build/config/compiler/compiler_buildflags.h"
+  flags = [
+    "CLANG_PGO=0",
+    "SYMBOL_LEVEL=1",
+    "HAS_SYMBOLS=0",
+  ]
+}
+
+buildflag_header("debugging_buildflags") {
+  header = "base/debug/debugging_buildflags.h"
+  flags = [
+    "DCHECK_IS_CONFIGURABLE=false",
+    "ENABLE_LOCATION_SOURCE=true",
+    "FROM_HERE_USES_LOCATION_BUILTINS=true",
+    "ENABLE_PROFILING=false",
+    "CAN_UNWIND_WITH_FRAME_POINTERS=true",
+    "ENABLE_COMMANDLINE_SEQUENCE_CHECKS=true",
+
+    # "UNSAFE_DEVELOPER_BUILD=",
+    "CAN_UNWIND_WITH_CFI_TABLE=false",
+
+    # "EXCLUDE_UNWIND_TABLES=",
+    "ENABLE_GDBINIT_WARNING=false",
+
+    # "ENABLE_LLDBINIT_WARNING=",
+    "EXPENSIVE_DCHECKS_ARE_ON=false",
+
+    # "ENABLE_STACK_TRACE_LINE_NUMBERS=",
+    "PRINT_UNSYMBOLIZED_STACK_TRACES=false",
+  ]
+}
+
+buildflag_header("feature_list_buildflags") {
+  header = "base/feature_list_buildflags.h"
+  flags = [ "ENABLE_BANNED_BASE_FEATURE_PREFIX=false" ]
+}
+
+buildflag_header("fuzzing_buildflags") {
+  header = "base/fuzzing_buildflags.h"
+  flags = [ "USE_FUZZING_ENGINE=false" ]
+}
+
+buildflag_header("ios_buildflags") {
+  header = "build/ios_buildflags.h"
+  flags = [ "IS_IOS_APP_EXTENSION=false" ]
+}
+
+buildflag_header("ios_cronet_buildflags") {
+  header = "base/message_loop/ios_cronet_buildflags.h"
+  flags = [ "CRONET_BUILD=false" ]
+}
+
+buildflag_header("ipc_buildflags") {
+  header = "ipc/ipc_buildflags.h"
+  flags = [ "IPC_MESSAGE_LOG_ENABLED=false" ]
+}
+
+buildflag_header("message_pump_buildflags") {
+  header = "base/message_loop/message_pump_buildflags.h"
+  flags = [ "ENABLE_MESSAGE_PUMP_EPOLL=true" ]
+}
+
+buildflag_header("mojo_buildflags") {
+  header = "mojo/buildflags.h"
+  flags = [
+    "MOJO_USE_APPLE_CHANNEL=false",
+    "MOJO_SUPPORT_LEGACY_CORE=$mojo_support_legacy_core",
+  ]
+}
+
+buildflag_header("mojo_cpp_bindings_buildflags") {
+  header = "mojo/public/cpp/bindings/mojo_buildflags.h"
+  flags = [
+    "MOJO_TRACE_ENABLED=false",
+    "MOJO_RANDOM_DELAYS_ENABLED=false",
+  ]
+}
+
+buildflag_header("profiler_buildflags") {
+  header = "base/profiler/profiler_buildflags.h"
+  flags = [
+    "ENABLE_ARM_CFI_TABLE=false",
+    "IOS_STACK_PROFILER_ENABLED=true",
+    "USE_ANDROID_UNWINDER_V2=false",
+  ]
+}
+
+buildflag_header("rust_buildflags") {
+  header = "base/rust_buildflags.h"
+  flags = [
+    "BUILD_RUST_JSON_READER=false",
+    "BUILD_RUST_BASE_CONVERSIONS=false",
+  ]
+}
+
+buildflag_header("synchronization_buildflags") {
+  header = "base/synchronization/synchronization_buildflags.h"
+  flags = [ "ENABLE_MUTEX_PRIORITY_INHERITANCE=false" ]
+}
+
+buildflag_header("tracing_buildflags") {
+  header = "base/tracing_buildflags.h"
+  flags = [
+    "ENABLE_BASE_TRACING=true",
+    "USE_PERFETTO_CLIENT_LIBRARY=true",
+    "USE_PERFETTO_TRACE_PROCESSOR=false",
+
+    # "OPTIONAL_TRACE_EVENTS_ENABLED=",
+  ]
+}
+
+buildflag_header("protected_memory_buildflags") {
+  header = "base/memory/protected_memory_buildflags.h"
+  flags = [
+    "PROTECTED_MEMORY_ENABLED=false"
+  ]
+}
+
+protozero_library("tracing_protozero") {
+  proto_in_dir = "base/tracing/protos"
+  proto_out_dir = "include/base/tracing/protos"
+  sources = [ "base/tracing/protos/chrome_track_event.proto" ]
+}
+
+libbase_sublibs = [
+  {
+    name = "base-core"
+    deps = [ ":tracing_protozero" ]
+    libs = [
+      "dl",
+      "double-conversion",
+      "pthread",
+      "rt",
+      "modp_b64",
+    ]
+    pkg_deps = [
+      "absl",
+      "glib-2.0",
+      "libevent",
+      "perfetto",
+    ]
+    configs = [
+      ":base_core_config",
+      ":base_export_config",
+    ]
+    sources = [
+      "base/allocator/partition_allocator/src/partition_alloc/oom.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/oom_callback.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/check.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/alias.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_linux.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_posix.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/log_message.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/memory/page_size_posix.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/posix/safe_strerror.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/cstring_builder.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/string_util.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/stringprintf.cc",
+      "base/allocator/partition_allocator/src/partition_alloc/tagging.cc",
+      "base/allocator/dispatcher/reentry_guard.cc",
+      "base/allocator/dispatcher/tls.cc",
+      "base/at_exit.cc",
+      "base/barrier_closure.cc",
+      "base/base64.cc",
+      "base/base64url.cc",
+      "base/base_switches.cc",
+      "base/callback_list.cc",
+      "base/check.cc",
+      "base/check_is_test.cc",
+      "base/check_op.cc",
+      "base/command_line.cc",
+      "base/containers/intrusive_heap.cc",
+      "base/containers/linked_list.cc",
+      "base/cpu.cc",
+      "base/debug/alias.cc",
+      "base/debug/crash_logging.cc",
+      "base/debug/debugger.cc",
+      "base/debug/debugger_posix.cc",
+      "base/debug/dump_without_crashing.cc",
+      "base/debug/elf_reader.cc",
+      "base/debug/stack_trace.cc",
+      "base/debug/stack_trace_posix.cc",
+      "base/debug/task_trace.cc",
+      "base/environment.cc",
+      "base/feature_list.cc",
+      "base/features.cc",
+      "base/file_descriptor_posix.cc",
+      "base/files/file.cc",
+      "base/files/file_descriptor_watcher_posix.cc",
+      "base/files/file_enumerator.cc",
+      "base/files/file_enumerator_posix.cc",
+      "base/files/file_path.cc",
+      "base/files/file_path_watcher.cc",
+      "base/files/file_path_watcher_inotify.cc",
+      "base/files/file_posix.cc",
+      "base/files/file_tracing.cc",
+      "base/files/file_util.cc",
+      "base/files/file_util_posix.cc",
+      "base/files/important_file_writer.cc",
+      "base/files/important_file_writer_cleaner.cc",
+      "base/files/memory_mapped_file.cc",
+      "base/files/memory_mapped_file_posix.cc",
+      "base/files/scoped_file.cc",
+      "base/files/scoped_file_linux.cc",
+      "base/files/scoped_temp_dir.cc",
+      "base/files/scoped_temp_file.cc",
+      "base/functional/callback_helpers.cc",
+      "base/functional/callback_internal.cc",
+      "base/hash/hash.cc",
+      "base/hash/md5_nacl.cc",
+      "base/hash/sha1_nacl.cc",
+      "base/json/json_file_value_serializer.cc",
+      "base/json/json_parser.cc",
+      "base/json/json_reader.cc",
+      "base/json/json_string_value_serializer.cc",
+      "base/json/json_value_converter.cc",
+      "base/json/json_writer.cc",
+      "base/json/string_escape.cc",
+      "base/json/values_util.cc",
+      "base/lazy_instance_helpers.cc",
+      "base/location.cc",
+      "base/logging.cc",
+      "base/logging_chromeos.cc",
+      "base/memory/aligned_memory.cc",
+      "base/memory/memory_pressure_listener.cc",
+      "base/memory/page_size_posix.cc",
+      "base/memory/platform_shared_memory_handle.cc",
+      "base/memory/platform_shared_memory_mapper_posix.cc",
+      "base/memory/platform_shared_memory_region.cc",
+      "base/memory/platform_shared_memory_region_posix.cc",
+      "base/memory/read_only_shared_memory_region.cc",
+      "base/memory/ref_counted.cc",
+      "base/memory/ref_counted_memory.cc",
+      "base/memory/shared_memory_mapper.cc",
+      "base/memory/shared_memory_mapping.cc",
+      "base/memory/shared_memory_security_policy.cc",
+      "base/memory/shared_memory_tracker.cc",
+      "base/memory/unsafe_shared_memory_region.cc",
+      "base/memory/weak_ptr.cc",
+      "base/memory/writable_shared_memory_region.cc",
+      "base/message_loop/io_watcher.cc",
+      "base/message_loop/io_watcher.h",
+      "base/message_loop/message_pump.cc",
+      "base/message_loop/message_pump_default.cc",
+      "base/message_loop/message_pump_epoll.cc",
+      "base/message_loop/message_pump_glib.cc",
+      "base/message_loop/watchable_io_message_pump_posix.cc",
+      "base/message_loop/work_id_provider.cc",
+      "base/metrics/bucket_ranges.cc",
+      "base/metrics/crc32.cc",
+      "base/metrics/dummy_histogram.cc",
+      "base/metrics/field_trial.cc",
+      "base/metrics/field_trial_param_associator.cc",
+      "base/metrics/field_trial_params.cc",
+      "base/metrics/histogram.cc",
+      "base/metrics/histogram_base.cc",
+      "base/metrics/histogram_functions.cc",
+      "base/metrics/histogram_samples.cc",
+      "base/metrics/histogram_snapshot_manager.cc",
+      "base/metrics/metrics_hashes.cc",
+      "base/metrics/persistent_histogram_allocator.cc",
+      "base/metrics/persistent_memory_allocator.cc",
+      "base/metrics/persistent_sample_map.cc",
+      "base/metrics/ranges_manager.cc",
+      "base/metrics/sample_map.cc",
+      "base/metrics/sample_vector.cc",
+      "base/metrics/sparse_histogram.cc",
+      "base/metrics/statistics_recorder.cc",
+      "base/native_library.cc",
+      "base/native_library_posix.cc",
+      "base/observer_list_internal.cc",
+      "base/observer_list_threadsafe.cc",
+      "base/observer_list_types.cc",
+      "base/pending_task.cc",
+      "base/pickle.cc",
+      "base/posix/can_lower_nice_to.cc",
+      "base/posix/file_descriptor_shuffle.cc",
+      "base/posix/global_descriptors.cc",
+      "base/posix/safe_strerror.cc",
+      "base/posix/unix_domain_socket.cc",
+      "base/power_monitor/power_monitor.cc",
+      "base/power_monitor/power_monitor_device_source.cc",
+      "base/power_monitor/power_monitor_device_source_chromeos.cc",
+      "base/power_monitor/power_monitor_source.cc",
+      "base/process/current_process.cc",
+      "base/process/environment_internal.cc",
+      "base/process/internal_linux.cc",
+      "base/process/kill.cc",
+      "base/process/kill_posix.cc",
+      "base/process/launch.cc",
+      "base/process/launch_posix.cc",
+      "base/process/memory.cc",
+      "base/process/memory_linux.cc",
+      "base/process/process_handle.cc",
+      "base/process/process_handle_linux.cc",
+      "base/process/process_handle_posix.cc",
+      "base/process/process_iterator.cc",
+      "base/process/process_iterator_linux.cc",
+      "base/process/process_linux.cc",
+      "base/process/process_metrics.cc",
+      "base/process/process_metrics_linux.cc",
+      "base/process/process_metrics_posix.cc",
+      "base/process/process_posix.cc",
+      "base/profiler/frame.cc",
+      "base/profiler/metadata_recorder.cc",
+      "base/profiler/module_cache.cc",
+      "base/profiler/module_cache_posix.cc",
+      "base/profiler/periodic_sampling_scheduler.cc",
+      "base/profiler/sample_metadata.cc",
+      "base/profiler/sampling_profiler_thread_token.cc",
+      "base/profiler/stack_base_address_posix.cc",
+      "base/profiler/stack_buffer.cc",
+      "base/profiler/stack_copier.cc",
+      "base/profiler/stack_copier_signal.cc",
+      "base/profiler/stack_sampler.cc",
+      "base/profiler/stack_sampler_posix.cc",
+      "base/profiler/stack_sampling_profiler.cc",
+      "base/profiler/stack_unwind_data.cc",
+      "base/profiler/thread_delegate_posix.cc",
+      "base/profiler/thread_group_profiler.cc",
+      "base/profiler/unwinder.cc",
+      "base/rand_util.cc",
+      "base/rand_util_posix.cc",
+      "base/run_loop.cc",
+      "base/sampling_heap_profiler/lock_free_address_hash_set.cc",
+      "base/sampling_heap_profiler/poisson_allocation_sampler.cc",
+      "base/scoped_native_library.cc",
+      "base/sequence_checker.cc",
+      "base/sequence_checker_impl.cc",
+      "base/sequence_token.cc",
+      "base/strings/escape.cc",
+      "base/strings/pattern.cc",
+      "base/strings/safe_sprintf.cc",
+      "base/strings/strcat.cc",
+      "base/strings/string_number_conversions.cc",
+      "base/strings/string_split.cc",
+      "base/strings/string_util.cc",
+      "base/strings/string_util_constants.cc",
+      "base/strings/stringprintf.cc",
+      "base/strings/sys_string_conversions_posix.cc",
+      "base/strings/utf_offset_string_conversions.cc",
+      "base/strings/utf_ostream_operators.cc",
+      "base/strings/utf_string_conversion_utils.cc",
+      "base/strings/utf_string_conversions.cc",
+      "base/sync_socket.cc",
+      "base/sync_socket_posix.cc",
+      "base/synchronization/atomic_flag.cc",
+      "base/synchronization/condition_variable_posix.cc",
+      "base/synchronization/lock.cc",
+      "base/synchronization/lock_impl_posix.cc",
+      "base/synchronization/waitable_event.cc",
+      "base/synchronization/waitable_event_posix.cc",
+      "base/synchronization/waitable_event_watcher_posix.cc",
+      "base/system/sys_info.cc",
+      "base/system/sys_info_chromeos.cc",
+      "base/system/sys_info_linux.cc",
+      "base/system/sys_info_posix.cc",
+      "base/task/cancelable_task_tracker.cc",
+      "base/task/common/checked_lock_impl.cc",
+      "base/task/common/lazy_now.cc",
+      "base/task/common/operations_controller.cc",
+      "base/task/common/scoped_defer_task_posting.cc",
+      "base/task/common/task_annotator.cc",
+      "base/task/current_thread.cc",
+      "base/task/default_delayed_task_handle_delegate.cc",
+      "base/task/delayed_task_handle.cc",
+      "base/task/lazy_thread_pool_task_runner.cc",
+      "base/task/post_job.cc",
+      "base/task/scoped_set_task_priority_for_current_thread.cc",
+      "base/task/sequence_manager/associated_thread_id.cc",
+      "base/task/sequence_manager/atomic_flag_set.cc",
+      "base/task/sequence_manager/delayed_task_handle_delegate.cc",
+      "base/task/sequence_manager/enqueue_order_generator.cc",
+      "base/task/sequence_manager/fence.cc",
+      "base/task/sequence_manager/sequence_manager.cc",
+      "base/task/sequence_manager/sequence_manager_impl.cc",
+      "base/task/sequence_manager/sequenced_task_source.cc",
+      "base/task/sequence_manager/task_order.cc",
+      "base/task/sequence_manager/task_queue.cc",
+      "base/task/sequence_manager/task_queue_impl.cc",
+      "base/task/sequence_manager/task_queue_selector.cc",
+      "base/task/sequence_manager/tasks.cc",
+      "base/task/sequence_manager/thread_controller.cc",
+      "base/task/sequence_manager/thread_controller_impl.cc",
+      "base/task/sequence_manager/thread_controller_power_monitor.cc",
+      "base/task/sequence_manager/thread_controller_with_message_pump_impl.cc",
+      "base/task/sequence_manager/time_domain.cc",
+      "base/task/sequence_manager/wake_up_queue.cc",
+      "base/task/sequence_manager/work_deduplicator.cc",
+      "base/task/sequence_manager/work_queue.cc",
+      "base/task/sequence_manager/work_queue_sets.cc",
+      "base/task/sequence_manager/work_tracker.cc",
+      "base/task/sequenced_task_runner.cc",
+      "base/task/single_thread_task_executor.cc",
+      "base/task/single_thread_task_runner.cc",
+      "base/task/task_features.cc",
+      "base/task/task_runner.cc",
+      "base/task/task_traits.cc",
+      "base/task/thread_pool.cc",
+      "base/task/thread_pool/delayed_task_manager.cc",
+      "base/task/thread_pool/environment_config.cc",
+      "base/task/thread_pool/job_task_source.cc",
+      "base/task/thread_pool/pooled_parallel_task_runner.cc",
+      "base/task/thread_pool/pooled_sequenced_task_runner.cc",
+      "base/task/thread_pool/pooled_single_thread_task_runner_manager.cc",
+      "base/task/thread_pool/pooled_task_runner_delegate.cc",
+      "base/task/thread_pool/priority_queue.cc",
+      "base/task/thread_pool/sequence.cc",
+      "base/task/thread_pool/service_thread.cc",
+      "base/task/thread_pool/task.cc",
+      "base/task/thread_pool/task_source.cc",
+      "base/task/thread_pool/task_source_sort_key.cc",
+      "base/task/thread_pool/task_tracker.cc",
+      "base/task/thread_pool/thread_group.cc",
+      "base/task/thread_pool/thread_group_impl.cc",
+      "base/task/thread_pool/thread_pool_impl.cc",
+      "base/task/thread_pool/thread_pool_instance.cc",
+      "base/task/thread_pool/worker_thread.cc",
+      "base/task/thread_pool/worker_thread_set.cc",
+      "base/third_party/cityhash/city.cc",
+      "base/third_party/nspr/prtime.cc",
+      "base/third_party/superfasthash/superfasthash.c",
+      "base/threading/hang_watcher.cc",
+      "base/threading/platform_thread.cc",
+      "base/threading/platform_thread_cros.cc",
+      "base/threading/platform_thread_internal_posix.cc",
+      "base/threading/platform_thread_linux.cc",
+      "base/threading/platform_thread_linux_base.cc",
+      "base/threading/platform_thread_posix.cc",
+      "base/threading/platform_thread_ref.cc",
+      "base/threading/post_task_and_reply_impl.cc",
+      "base/threading/scoped_blocking_call.cc",
+      "base/threading/scoped_blocking_call_internal.cc",
+      "base/threading/sequence_local_storage_map.cc",
+      "base/threading/sequence_local_storage_slot.cc",
+      "base/threading/simple_thread.cc",
+      "base/threading/thread.cc",
+      "base/threading/thread_checker.cc",
+      "base/threading/thread_checker_impl.cc",
+      "base/threading/thread_collision_warner.cc",
+      "base/threading/thread_id_name_manager.cc",
+      "base/threading/thread_local_storage.cc",
+      "base/threading/thread_local_storage_posix.cc",
+      "base/threading/thread_restrictions.cc",
+      "base/threading/thread_type_delegate.cc",
+      "base/threading/watchdog.cc",
+      "base/time/clock.cc",
+      "base/time/default_clock.cc",
+      "base/time/default_tick_clock.cc",
+      "base/time/tick_clock.cc",
+      "base/time/time.cc",
+      "base/time/time_conversion_posix.cc",
+      "base/time/time_delta_from_string.cc",
+      "base/time/time_exploded_posix.cc",
+      "base/time/time_now_posix.cc",
+      "base/time/time_override.cc",
+      "base/timer/elapsed_timer.cc",
+      "base/timer/lap_timer.cc",
+      "base/timer/timer.cc",
+      "base/timer/wall_clock_timer.cc",
+      "base/token.cc",
+      "base/trace_event/heap_profiler_allocation_context_tracker.cc",
+      "base/trace_event/histogram_scope.cc",
+      "base/trace_event/interned_args_helper.cc",
+      "base/trace_event/malloc_dump_provider.cc",
+      "base/trace_event/memory_allocator_dump.cc",
+      "base/trace_event/memory_allocator_dump_guid.cc",
+      "base/trace_event/memory_dump_manager.cc",
+      "base/trace_event/memory_dump_provider_info.cc",
+      "base/trace_event/memory_dump_request_args.cc",
+      "base/trace_event/memory_dump_scheduler.cc",
+      "base/trace_event/memory_infra_background_allowlist.cc",
+      "base/trace_event/memory_pressure_level_proto.cc",
+      "base/trace_event/memory_usage_estimator.cc",
+      "base/trace_event/perfetto_proto_appender.cc",
+      "base/trace_event/process_memory_dump.cc",
+      "base/trace_event/trace_arguments.cc",
+      "base/trace_event/trace_buffer.cc",
+      "base/trace_event/trace_config.cc",
+      "base/trace_event/trace_config_category_filter.cc",
+      "base/trace_event/trace_event_impl.cc",
+      "base/trace_event/trace_id_helper.cc",
+      "base/trace_event/trace_log.cc",
+      "base/trace_event/traced_value.cc",
+      "base/unguessable_token.cc",
+      "base/uuid.cc",
+      "base/value_iterators.cc",
+      "base/values.cc",
+      "base/version.cc",
+      "base/vlog.cc",
+      "dump_without_crashing.cc",
+    ]
+
+    if (use_allocator_shim) {
+      sources += [
+        "base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.cc",
+        "base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc",
+      ]
+    }
+
+    # ARM and X86 doesn't have implementations for frame pointer unwinder.
+    # ARM and X86 has stack profiler disabled.
+    if (current_cpu == "x64" || current_cpu == "arm64") {
+      sources += [
+        "base/profiler/frame_pointer_unwinder.cc",
+      ]
+    }
+  },
+
+  {
+    name = "base-policy"
+    deps = [ ":base-core" ]
+    libs = [ "re2" ]
+    configs = [ ":policy_export_config" ]
+    sources = [
+      "components/policy/core/common/json_schema_constants.cc",
+      "components/policy/core/common/registry_dict.cc",
+      "components/policy/core/common/schema.cc",
+    ]
+  },
+
+  {
+    name = "base-base_test_support"
+    deps = [ ":tracing_protozero" ]
+    testonly = true
+    sources = [
+      "base/test/metrics/histogram_tester.cc",
+      "base/test/mock_entropy_provider.cc",
+      "base/test/mock_log.cc",
+      "base/test/power_monitor_test.cc",
+      "base/test/scoped_chromeos_version_info.cc",
+      "base/test/scoped_command_line.cc",
+      "base/test/scoped_feature_list.cc",
+      "base/test/scoped_run_loop_timeout.cc",
+      "base/test/simple_test_clock.cc",
+      "base/test/simple_test_tick_clock.cc",
+      "base/test/task_environment.cc",
+      "base/test/test_file_util.cc",
+      "base/test/test_file_util_linux.cc",
+      "base/test/test_file_util_posix.cc",
+      "base/test/test_mock_time_task_runner.cc",
+      "base/test/test_pending_task.cc",
+      "base/test/test_simple_task_runner.cc",
+      "base/test/test_switches.cc",
+      "base/test/test_timeouts.cc",
+      "base/timer/mock_timer.cc",
+    ]
+  },
+]
+
+if (use.crypto) {
+  libbase_sublibs += [
+    {
+      name = "base-crypto"
+      deps = [ ":base-core" ]
+      libs = [
+        "dl",
+        "pthread",
+      ]
+      pkg_deps = [
+        "nss",
+        "openssl",
+      ]
+      configs = [ ":crypto_export_config" ]
+      sources = [
+        "crypto/hmac.cc",
+        "crypto/hmac_nss.cc",
+
+        # Added to libchrome only (not upstream) to support OpenSSL 1.1 API
+        "crypto/libcrypto-compat.c",
+        "crypto/nss_key_util.cc",
+        "crypto/nss_util.cc",
+        "crypto/openssl_util.cc",
+        "crypto/random.cc",
+        "crypto/rsa_private_key.cc",
+        "crypto/rsa_private_key_nss.cc",
+        "crypto/scoped_test_nss_db.cc",
+        "crypto/secure_hash.cc",
+        "crypto/secure_util.cc",
+        "crypto/sha2.cc",
+        "crypto/signature_creator_nss.cc",
+        "crypto/signature_verifier_nss.cc",
+        "crypto/symmetric_key_nss.cc",
+        "crypto/third_party/nss/rsawrapr.c",
+        "crypto/third_party/nss/sha512.cc",
+      ]
+    },
+  ]
+}
+
+if (use.dbus) {
+  libbase_sublibs += [
+    {
+      name = "base-dbus"
+      deps = [ ":base-core" ]
+      pkg_deps = [
+        "absl",
+        "dbus-1",
+      ]
+      if (use.fuzzer) {
+        pkg_deps += [ "protobuf" ]
+      } else {
+        pkg_deps += [ "protobuf-lite" ]
+      }
+      configs = [ ":dbus_export_config" ]
+      sources = [
+        "dbus/bus.cc",
+        "dbus/dbus_statistics.cc",
+        "dbus/error.cc",
+        "dbus/exported_object.cc",
+        "dbus/message.cc",
+        "dbus/object_manager.cc",
+        "dbus/object_path.cc",
+        "dbus/object_proxy.cc",
+        "dbus/property.cc",
+        "dbus/scoped_dbus_error.cc",
+        "dbus/string_util.cc",
+        "dbus/util.cc",
+        "dbus/values_util.cc",
+      ]
+    },
+
+    {
+      name = "base-dbus_test_support"
+      testonly = true
+      pkg_deps = [ "dbus-1" ]
+      if (use.fuzzer) {
+        pkg_deps += [ "protobuf" ]
+      } else {
+        pkg_deps += [ "protobuf-lite" ]
+      }
+      sources = [
+        "dbus/mock_bus.cc",
+        "dbus/mock_exported_object.cc",
+        "dbus/mock_object_manager.cc",
+        "dbus/mock_object_proxy.cc",
+      ]
+    },
+  ]
+}
+
+# Generate static/shared libraries.
+foreach(attr, libbase_sublibs) {
+  if (defined(attr.pkg_deps)) {
+    # If it depends on external packages, introduces -pkg-config config.
+    pkg_config(attr.name + "-pkg-config") {
+      pkg_deps = attr.pkg_deps
+    }
+  }
+
+  if (defined(attr.testonly) && attr.testonly) {
+    buildtype = "static_library"
+  } else {
+    buildtype = "shared_library"
+  }
+  target(buildtype, attr.name) {
+    sources = attr.sources
+    deps = [ ":all_buildflags" ]
+    if (defined(attr.deps)) {
+      deps += attr.deps
+    }
+
+    if (defined(attr.libs)) {
+      libs = attr.libs
+    }
+
+    if (defined(attr.pkg_deps)) {
+      configs += [ ":" + attr.name + "-pkg-config" ]
+    }
+    configs += [ ":libchrome_config" ]
+    if (buildtype == "static_library") {
+      configs -= [ "//common-mk:use_thin_archive" ]
+      configs += [ "//common-mk:nouse_thin_archive" ]
+    }
+    if (defined(attr.configs)) {
+      configs += attr.configs
+    }
+  }
+}
+
+action("base") {
+  deps = []
+  foreach(attr, libbase_sublibs) {
+    if (!defined(attr.testonly) || !attr.testonly) {
+      deps += [ ":" + attr.name ]
+    }
+  }
+
+  script = "//common-mk/write_args.py"
+  outputs = [ "${root_out_dir}/lib/lib${target_name}.so" ]
+  args = [ "--output" ] + outputs + [ "--" ] + [
+           "GROUP",
+           "(",
+           "AS_NEEDED",
+           "(",
+         ]
+  foreach(attr, libbase_sublibs) {
+    if (!defined(attr.testonly) || !attr.testonly) {
+      args += [ "-l" + attr.name ]
+    }
+  }
+  args += [
+    ")",
+    ")",
+  ]
+}
+
+libchrome_exported_cflags = [
+  "-I/usr/include/libchrome",
+  "-Wno-unused-local-typedefs",
+  "-DBASE_VER=${libchrome_basever}",
+  "-DBASE_USE_PERFETTO_CLIENT_LIBRARY",
+  "-DPERFETTO_ENABLE_LEGACY_TRACE_EVENTS=1",
+]
+
+if (use.asan) {
+  libchrome_exported_cflags += [
+    "-DLEAK_SANITIZER",
+    "-DDISABLE_ALLOCATOR_SANITIZER",
+  ]
+}
+
+if (use.ipcz) {
+  libchrome_exported_cflags += [
+    "-DENABLE_IPCZ_ON_CHROMEOS",
+  ]
+}
+
+generate_pkg_config("libchrome") {
+  deps = [ ":base" ]
+  description = "chrome base library"
+  version = "${libchrome_basever}"
+  requires = [ "absl" ]
+  requires_private = []
+  foreach(attr, libbase_sublibs) {
+    if ((!defined(attr.testonly) || !attr.testonly) && defined(attr.pkg_deps)) {
+      requires_private += attr.pkg_deps
+    }
+  }
+
+  # base/synchronization/lock_impl.h has function inlined that uses pthread.
+  libs = [
+    "-lbase",
+    "-lpthread",
+  ]
+  libs_private = []
+  foreach(attr, libbase_sublibs) {
+    if (!defined(attr.testonly) || !attr.testonly) {
+      libs_private += [ "-l" + attr.name ]
+      if (defined(attr.libs)) {
+        foreach(lib, attr.libs) {
+          libs_private += [ "-l" + lib ]
+        }
+      }
+    }
+  }
+  cflags = libchrome_exported_cflags
+}
+
+action("base-test") {
+  deps = []
+  foreach(attr, libbase_sublibs) {
+    if (defined(attr.testonly) && attr.testonly) {
+      deps += [ ":" + attr.name ]
+    }
+  }
+
+  script = "//common-mk/write_args.py"
+  outputs = [ "${root_out_dir}/lib${target_name}.a" ]
+  args = [ "--output" ] + outputs + [ "--" ] + [
+           "GROUP",
+           "(",
+           "AS_NEEDED",
+           "(",
+         ]
+  foreach(attr, libbase_sublibs) {
+    if (defined(attr.testonly) && attr.testonly) {
+      args += [ "-l" + attr.name ]
+    }
+  }
+  args += [
+    ")",
+    ")",
+  ]
+}
+
+generate_pkg_config("libchrome-test") {
+  deps = [ ":base-test" ]
+  description = "chrome base test library"
+  version = "${libchrome_basever}"
+  requires_private = []
+  foreach(attr, libbase_sublibs) {
+    if (defined(attr.testonly) && attr.testonly && defined(attr.pkg_deps)) {
+      requires_private += attr.pkg_deps
+    }
+  }
+  libs = [ "-lbase-test" ]
+  libs_private = []
+  foreach(attr, libbase_sublibs) {
+    if (defined(attr.testonly) && attr.testonly) {
+      libs_private += [ "-l" + attr.name ]
+      if (defined(attr.libs)) {
+        libs_private += [ "-l" + lib ]
+      }
+    }
+  }
+  cflags = libchrome_exported_cflags
+}
+
+if (use.mojo) {
+  generate_mojom_type_mappings("mojom_type_mappings") {
+    mojom_type_mappings_generator =
+        "libchrome_tools/mojom_generate_type_mappings.py"
+    sources = [
+      "mojo/public/cpp/base/file.typemap",
+      "mojo/public/cpp/base/file_error.typemap",
+      "mojo/public/cpp/base/file_info.typemap",
+      "mojo/public/cpp/base/file_path.typemap",
+      "mojo/public/cpp/base/memory_allocator_dump_cross_process_uid.typemap",
+      "mojo/public/cpp/base/process_id.typemap",
+      "mojo/public/cpp/base/read_only_buffer.typemap",
+      "mojo/public/cpp/base/shared_memory.typemap",
+      "mojo/public/cpp/base/text_direction.typemap",
+      "mojo/public/cpp/base/thread_priority.typemap",
+      "mojo/public/cpp/base/time.typemap",
+      "mojo/public/cpp/base/unguessable_token.typemap",
+      "mojo/public/cpp/base/values.typemap",
+    ]
+  }
+  generate_mojom_bindings_gen("mojom_bindings_gen") {
+    mojom_bindings_generator =
+        "mojo/public/tools/bindings/mojom_bindings_generator.py"
+    mojom_parser = "mojo/public/tools/mojom/mojom_parser.py"
+
+    # TODO(fqj): revisit typemaps after uprev.
+    # typemaps = get_target_outputs(":mojom_type_mappings")
+    sources = [
+      "ipc/ipc.mojom",
+
+      # TODO(fqj): Revisit these 3 files after uprev.
+      "mojo/public/interfaces/bindings/interface_control_messages.mojom",
+      "mojo/public/interfaces/bindings/native_struct.mojom",
+      "mojo/public/interfaces/bindings/pipe_control_messages.mojom",
+      "mojo/public/mojom/base/file.mojom",
+      "mojo/public/mojom/base/file_error.mojom",
+      "mojo/public/mojom/base/file_info.mojom",
+      "mojo/public/mojom/base/file_path.mojom",
+      "mojo/public/mojom/base/generic_pending_associated_receiver.mojom",
+      "mojo/public/mojom/base/generic_pending_receiver.mojom",
+      "mojo/public/mojom/base/memory_allocator_dump_cross_process_uid.mojom",
+      "mojo/public/mojom/base/process_id.mojom",
+      "mojo/public/mojom/base/read_only_buffer.mojom",
+      "mojo/public/mojom/base/shared_memory.mojom",
+      "mojo/public/mojom/base/text_direction.mojom",
+      "mojo/public/mojom/base/thread_type.mojom",
+      "mojo/public/mojom/base/time.mojom",
+      "mojo/public/mojom/base/unguessable_token.mojom",
+      "mojo/public/mojom/base/values.mojom",
+      "ui/gfx/geometry/mojom/geometry.mojom",
+      "ui/gfx/range/mojom/range.mojom",
+    ]
+  }
+
+  # TODO(fqj): Revisit these 3 files after uprev.
+  # generate_mojom_bindings_gen("mojom_bindings_native_gen") {
+  #   mojom_bindings_generator =
+  #       "mojo/public/tools/bindings/mojom_bindings_generator.py"
+  #   mojom_parser = "mojo/public/tools/mojom/mojom_parser.py"
+  #   sources = [
+  #   ]
+  #   disallow_native_types = true
+  #   disallow_interfaces = true
+  # }
+
+  if (use.ipcz) {
+    pkg_config("mojo-ipcz-pkg-config") {
+      pkg_deps = [ "absl" ]
+    }
+  }
+
+  # Probably we should consider build libmojo as a part of libchrome.
+  # crbug.com/924035.
+  shared_library("mojo") {
+    deps = [
+      ":all_buildflags",
+      ":base-core",
+      ":base-crypto",
+      ":mojom_bindings_gen",
+      ":mojom_bindings_gen",
+
+      # ":mojom_bindings_native_gen",
+      # ":mojom_type_mappings",
+    ]
+    libs = [ "pthread" ]
+
+    # TODO(hidehiko): Consolidate with build_config.h.
+    configs += [
+      ":libchrome_config",
+      ":mojo_export_config",
+      "//common-mk:visibility_default",
+    ]
+
+    sources =
+        [
+          "ipc/ipc_message.cc",
+          "ipc/ipc_message_attachment_set.cc",
+          "ipc/native_handle_type_converters.cc",
+          "mojo/core/broker_host.cc",
+          "mojo/core/broker_posix.cc",
+          "mojo/core/channel.cc",
+          "mojo/core/channel_linux.cc",
+          "mojo/core/channel_posix.cc",
+          "mojo/core/configuration.cc",
+          "mojo/core/connection_params.cc",
+          "mojo/core/core_ipcz.cc",
+          "mojo/core/embedder/embedder.cc",
+          "mojo/core/embedder/features.cc",
+          "mojo/core/embedder/scoped_ipc_support.cc",
+          "mojo/core/ipcz_api.cc",
+          "mojo/core/ipcz_driver/base_shared_memory_service.cc",
+          "mojo/core/ipcz_driver/data_pipe.cc",
+          "mojo/core/ipcz_driver/driver.cc",
+          "mojo/core/ipcz_driver/invitation.cc",
+          "mojo/core/ipcz_driver/mojo_message.cc",
+          "mojo/core/ipcz_driver/mojo_trap.cc",
+          "mojo/core/ipcz_driver/object.cc",
+          "mojo/core/ipcz_driver/ring_buffer.cc",
+          "mojo/core/ipcz_driver/shared_buffer.cc",
+          "mojo/core/ipcz_driver/shared_buffer_mapping.cc",
+          "mojo/core/ipcz_driver/transmissible_platform_handle.cc",
+          "mojo/core/ipcz_driver/transport.cc",
+          "mojo/core/ipcz_driver/wrapped_platform_handle.cc",
+          "mojo/core/platform_handle_in_transit.cc",
+          "mojo/core/platform_handle_utils.cc",
+          "mojo/core/scoped_ipcz_handle.cc",
+          "mojo/public/c/system/thunks.cc",
+          "mojo/public/cpp/bindings/async_flusher.cc",
+          "mojo/public/cpp/bindings/connection_group.cc",
+          "mojo/public/cpp/bindings/features.cc",
+          "mojo/public/cpp/bindings/lib/array_internal.cc",
+          "mojo/public/cpp/bindings/lib/associated_group.cc",
+          "mojo/public/cpp/bindings/lib/associated_group_controller.cc",
+          "mojo/public/cpp/bindings/lib/associated_interface_ptr_state.cc",
+          "mojo/public/cpp/bindings/lib/associated_receiver.cc",
+          "mojo/public/cpp/bindings/lib/binding_state.cc",
+          "mojo/public/cpp/bindings/lib/buffer.cc",
+          "mojo/public/cpp/bindings/lib/connector.cc",
+          "mojo/public/cpp/bindings/lib/control_message_handler.cc",
+          "mojo/public/cpp/bindings/lib/control_message_proxy.cc",
+          "mojo/public/cpp/bindings/lib/generated_code_util.cc",
+          "mojo/public/cpp/bindings/lib/handle_serialization.cc",
+          "mojo/public/cpp/bindings/lib/interface_endpoint_client.cc",
+          "mojo/public/cpp/bindings/lib/interface_ptr_state.cc",
+          "mojo/public/cpp/bindings/lib/message.cc",
+          "mojo/public/cpp/bindings/lib/message_dispatcher.cc",
+          "mojo/public/cpp/bindings/lib/message_header_validator.cc",
+          "mojo/public/cpp/bindings/lib/message_internal.cc",
+          "mojo/public/cpp/bindings/lib/multiplex_router.cc",
+          "mojo/public/cpp/bindings/lib/pending_receiver_state.cc",
+          "mojo/public/cpp/bindings/lib/pending_remote_state.cc",
+          "mojo/public/cpp/bindings/lib/pipe_control_message_handler.cc",
+          "mojo/public/cpp/bindings/lib/pipe_control_message_proxy.cc",
+          "mojo/public/cpp/bindings/lib/proxy_to_responder.cc",
+          "mojo/public/cpp/bindings/lib/scoped_interface_endpoint_handle.cc",
+          "mojo/public/cpp/bindings/lib/send_message_helper.cc",
+          "mojo/public/cpp/bindings/lib/sequence_local_sync_event_watcher.cc",
+          "mojo/public/cpp/bindings/lib/sync_call_restrictions.cc",
+          "mojo/public/cpp/bindings/lib/sync_event_watcher.cc",
+          "mojo/public/cpp/bindings/lib/sync_handle_registry.cc",
+          "mojo/public/cpp/bindings/lib/sync_handle_watcher.cc",
+          "mojo/public/cpp/bindings/lib/task_runner_helper.cc",
+          "mojo/public/cpp/bindings/lib/thread_safe_forwarder_base.cc",
+          "mojo/public/cpp/bindings/lib/validation_context.cc",
+          "mojo/public/cpp/bindings/lib/validation_errors.cc",
+          "mojo/public/cpp/bindings/lib/validation_util.cc",
+          "mojo/public/cpp/bindings/pending_flush.cc",
+          "mojo/public/cpp/bindings/receiver_set.cc",
+          "mojo/public/cpp/bindings/urgent_message_scope.cc",
+          "mojo/public/cpp/platform/platform_channel.cc",
+          "mojo/public/cpp/platform/platform_channel_endpoint.cc",
+          "mojo/public/cpp/platform/platform_channel_server.cc",
+          "mojo/public/cpp/platform/platform_channel_server_endpoint.cc",
+          "mojo/public/cpp/platform/platform_channel_server_posix.cc",
+          "mojo/public/cpp/platform/platform_handle.cc",
+          "mojo/public/cpp/platform/socket_utils_posix.cc",
+          "mojo/public/cpp/system/handle_signal_tracker.cc",
+          "mojo/public/cpp/system/buffer.cc",
+          "mojo/public/cpp/system/invitation.cc",
+          "mojo/public/cpp/system/isolated_connection.cc",
+          "mojo/public/cpp/system/platform_handle.cc",
+          "mojo/public/cpp/system/simple_watcher.cc",
+          "mojo/public/cpp/system/trap.cc",
+          "mojo/public/cpp/system/wait.cc",
+          "mojo/public/cpp/system/wait_set.cc",
+        ] + get_target_outputs(":mojom_bindings_gen")  # +
+
+    include_dirs = [
+      "third_party/ipcz/include",
+      "third_party/ipcz/src",
+    ]
+
+    if (mojo_support_legacy_core) {
+      sources += [
+        "mojo/core/atomic_flag.cc",
+        "mojo/core/core.cc",
+        "mojo/core/data_pipe_consumer_dispatcher.cc",
+        "mojo/core/data_pipe_control_message.cc",
+        "mojo/core/data_pipe_producer_dispatcher.cc",
+        "mojo/core/dispatcher.cc",
+        "mojo/core/entrypoints.cc",
+        "mojo/core/handle_table.cc",
+        "mojo/core/invitation_dispatcher.cc",
+        "mojo/core/message_pipe_dispatcher.cc",
+        "mojo/core/node_channel.cc",
+        "mojo/core/node_controller.cc",
+        "mojo/core/platform_handle_dispatcher.cc",
+        "mojo/core/platform_shared_memory_mapping.cc",
+        "mojo/core/request_context.cc",
+        "mojo/core/shared_buffer_dispatcher.cc",
+        "mojo/core/user_message_impl.cc",
+        "mojo/core/watch.cc",
+        "mojo/core/watcher_dispatcher.cc",
+        "mojo/core/watcher_set.cc",
+        "mojo/core/ports/event.cc",
+        "mojo/core/ports/message_queue.cc",
+        "mojo/core/ports/name.cc",
+        "mojo/core/ports/node.cc",
+        "mojo/core/ports/port.cc",
+        "mojo/core/ports/port_locker.cc",
+        "mojo/core/ports/port_ref.cc",
+        "mojo/core/ports/user_message.cc",
+      ]
+    }
+
+    if (use.ipcz) {
+      configs += [ ":mojo-ipcz-pkg-config" ]
+      cflags = [ "-Wno-invalid-offsetof" ]
+
+      sources += [
+        "third_party/ipcz/src/api.cc",
+        "third_party/ipcz/src/ipcz/api_context.cc",
+        "third_party/ipcz/src/ipcz/api_object.cc",
+        "third_party/ipcz/src/ipcz/application_object.cc",
+        "third_party/ipcz/src/ipcz/block_allocator.cc",
+        "third_party/ipcz/src/ipcz/block_allocator_pool.cc",
+        "third_party/ipcz/src/ipcz/box.cc",
+        "third_party/ipcz/src/ipcz/buffer_pool.cc",
+        "third_party/ipcz/src/ipcz/driver_memory.cc",
+        "third_party/ipcz/src/ipcz/driver_memory_mapping.cc",
+        "third_party/ipcz/src/ipcz/driver_object.cc",
+        "third_party/ipcz/src/ipcz/driver_transport.cc",
+        "third_party/ipcz/src/ipcz/features.cc",
+        "third_party/ipcz/src/ipcz/fragment.cc",
+        "third_party/ipcz/src/ipcz/fragment_ref.cc",
+        "third_party/ipcz/src/ipcz/link_side.cc",
+        "third_party/ipcz/src/ipcz/link_type.cc",
+        "third_party/ipcz/src/ipcz/local_router_link.cc",
+        "third_party/ipcz/src/ipcz/message.cc",
+        "third_party/ipcz/src/ipcz/node.cc",
+        "third_party/ipcz/src/ipcz/node_connector.cc",
+        "third_party/ipcz/src/ipcz/node_link.cc",
+        "third_party/ipcz/src/ipcz/node_link_memory.cc",
+        "third_party/ipcz/src/ipcz/node_messages.cc",
+        "third_party/ipcz/src/ipcz/node_name.cc",
+        "third_party/ipcz/src/ipcz/parcel.cc",
+        "third_party/ipcz/src/ipcz/parcel_wrapper.cc",
+        "third_party/ipcz/src/ipcz/pending_transaction_set.cc",
+        "third_party/ipcz/src/ipcz/ref_counted_fragment.cc",
+        "third_party/ipcz/src/ipcz/remote_router_link.cc",
+        "third_party/ipcz/src/ipcz/route_edge.cc",
+        "third_party/ipcz/src/ipcz/router.cc",
+        "third_party/ipcz/src/ipcz/router_link_state.cc",
+        "third_party/ipcz/src/ipcz/trap_event_dispatcher.cc",
+        "third_party/ipcz/src/ipcz/trap_set.cc",
+        "third_party/ipcz/src/util/ref_counted.cc",
+      ]
+    } else {
+      sources += [
+        "third_party/ipcz/src/disable_api.cc",
+      ]
+    }
+
+    #get_target_outputs(":mojom_bindings_native_gen")
+
+    if (use.asan || use.fuzzer || use.msan || use.ubsan) {
+      sources += [
+        "ipc/ipc_message_attachment.cc",
+        "ipc/ipc_mojo_handle_attachment.cc",
+        "ipc/ipc_platform_file_attachment_posix.cc",
+      ]
+    }
+  }
+
+  generate_pkg_config("libmojo") {
+    deps = [ ":mojo" ]
+    description = "Chrome Mojo IPC library"
+    version = "${libchrome_basever}"
+    libs = [ "-lmojo" ]
+    cflags = [
+      "-I/usr/include/libchrome",
+      "-Wno-cast-qual",
+      "-Wno-cast-align",
+    ]
+  }
+}
+
+install_config("install_basever") {
+  sources = [ "BASE_VER" ]
+  install_path = "/usr/share/libchrome"
+}
+
+install_config("install_header") {
+  sources = []
+  sources += [
+    "base/*.h",
+    "base/allocator/*.h",
+    "base/allocator/partition_allocator/src/partition_alloc/*.h",
+    "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/*.h",
+    "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/augmentations/*.h",
+    "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cxx_wrapper/*.h",
+    "base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/types/*.h",
+    "base/allocator/partition_allocator/src/partition_alloc/pointers/*.h",
+    "base/allocator/partition_allocator/src/partition_alloc/starscan/*.h",
+    "base/containers/*.h",
+    "base/debug/*.h",
+    "base/files/*.h",
+    "base/functional/*.h",
+    "base/hash/*.h",
+    "base/i18n/*.h",
+    "base/json/*.h",
+    "base/logging/*.h",
+    "base/macros/*.h",
+    "base/memory/*.h",
+    "base/message_loop/*.h",
+    "base/metrics/*.h",
+    "base/numerics/*.h",
+    "base/posix/*.h",
+    "base/power_monitor/*.h",
+    "base/process/*.h",
+    "base/profiler/*.h",
+    "base/ranges/*.h",
+    "base/strings/*.h",
+    "base/synchronization/*.h",
+    "base/system/*.h",
+    "base/task/*.h",
+    "base/task/common/*.h",
+    "base/task/sequence_manager/*.h",
+    "base/task/thread_pool/*.h",
+    "base/third_party/icu/*.h",
+    "base/third_party/nspr/*.h",
+    "base/third_party/valgrind/*.h",
+    "base/threading/*.h",
+    "base/time/*.h",
+    "base/timer/*.h",
+    "base/trace_event/*.h",
+    "base/trace_event/common/*.h",
+    "base/types/*.h",
+    "build/*.h",
+    "components/policy/*.h",
+    "components/policy/core/common/*.h",
+    "testing/gmock/include/gmock/*.h",
+    "testing/gtest/include/gtest/*.h",
+  ]
+  if (use.dbus) {
+    sources += [ "dbus/*.h" ]
+  }
+  if (use.mojo) {
+    sources += [
+      "ipc/*.h",
+      "mojo/core/*.h",
+      "mojo/core/embedder/*.h",
+      "mojo/core/ports/*.h",
+      "mojo/public/c/system/*.h",
+      "mojo/public/cpp/base/*.h",
+      "mojo/public/cpp/bindings/*.h",
+      "mojo/public/cpp/bindings/lib/*.h",
+      "mojo/public/cpp/platform/*.h",
+      "mojo/public/cpp/system/*.h",
+    ]
+  }
+  sources += [
+    "base/test/allow_check_is_test_to_be_called.h",
+    "base/test/bind.h",
+    "base/test/gmock_callback_support.h",
+    "base/test/metrics/histogram_tester.h",
+    "base/test/mock_callback.h",
+    "base/test/mock_log.h",
+    "base/test/power_monitor_test.h",
+    "base/test/repeating_test_future.h",
+    "base/test/scoped_chromeos_version_info.h",
+    "base/test/scoped_command_line.h",
+    "base/test/scoped_feature_list.h",
+    "base/test/scoped_logging_settings.h",
+    "base/test/scoped_run_loop_timeout.h",
+    "base/test/scoped_running_on_chromeos.h",
+    "base/test/simple_test_clock.h",
+    "base/test/simple_test_tick_clock.h",
+    "base/test/task_environment.h",
+    "base/test/test_file_util.h",
+    "base/test/test_future.h",
+    "base/test/test_future_internal.h",
+    "base/test/test_mock_time_task_runner.h",
+    "base/test/test_pending_task.h",
+    "base/test/test_switches.h",
+    "base/test/test_timeouts.h",
+  ]
+  sources += [
+    "third_party/abseil-cpp/**/*.h",
+    "third_party/ipcz/**/*.h",
+    "third_party/libevent/*.h",
+    "third_party/perfetto/**/*.h",
+  ]
+  if (use.crypto) {
+    sources += [
+      "crypto/crypto_export.h",
+      "crypto/hmac.h",
+      "crypto/libcrypto-compat.h",
+      "crypto/nss_key_util.h",
+      "crypto/nss_util.h",
+      "crypto/nss_util_internal.h",
+      "crypto/openssl_util.h",
+      "crypto/p224.h",
+      "crypto/p224_spake.h",
+      "crypto/random.h",
+      "crypto/rsa_private_key.h",
+      "crypto/scoped_nss_types.h",
+      "crypto/scoped_openssl_types.h",
+      "crypto/scoped_test_nss_db.h",
+      "crypto/secure_hash.h",
+      "crypto/secure_util.h",
+      "crypto/sha2.h",
+      "crypto/signature_creator.h",
+      "crypto/signature_verifier.h",
+    ]
+  }
+  install_path = "/usr/include/libchrome"
+  glob = true
+  tree_relative_to = "."
+}
+
+install_config("install_mojom_generated") {
+  sources = [
+    "${root_gen_dir}/include/mojo/public/interfaces/bindings/*.h",
+    "${root_gen_dir}/include/mojo/public/mojom/base/*.h",
+  ]
+  glob = true
+  tree_relative_to = "${root_gen_dir}/include"
+  install_path = "/usr/include/libchrome"
+}
+
+install_config("install_buildflag_header") {
+  sources = [
+    "${root_gen_dir}/libchrome/base/**/*buildflags.h",
+    "${root_gen_dir}/libchrome/build/**/*buildflags.h",
+  ]
+  if (use.mojo) {
+    sources += [
+      "${root_gen_dir}/libchrome/ipc/**/*buildflags.h",
+      "${root_gen_dir}/libchrome/mojo/**/*buildflags.h",
+    ]
+  }
+  install_path = "/usr/include/libchrome"
+  glob = true
+  tree_relative_to = "${root_gen_dir}/libchrome"
+}
+
+install_config("install_protozero_generated") {
+  sources = [
+    "${root_gen_dir}/include/base/tracing/protos/chrome_track_event.pbzero.h",
+  ]
+  deps = [ ":tracing_protozero" ]
+  tree_relative_to = "${root_gen_dir}/include"
+  install_path = "/usr/include/libchrome"
+}
diff --git a/DIR_METADATA b/DIR_METADATA
new file mode 100644
index 0000000..2b46d93
--- /dev/null
+++ b/DIR_METADATA
@@ -0,0 +1,58 @@
+# Metadata information for this directory.
+#
+# For more information on DIR_METADATA files, see:
+#   https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md
+#
+# For the schema of this file, see Metadata message:
+#   https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+
+buganizer {
+  component_id: 656538  # ChromeOS > Software > Eng Velocity > libchrome
+}
+
+team_email: "chromeos-libchrome@google.com"
+
+chromeos {
+  cq {
+    # See go/cros-cq-test-config.
+    source_test_plans {
+      test_plan_starlark_files {
+        host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/legacy_default_tast_hw.star"
+      }
+      test_plan_starlark_files {
+        host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/legacy_default_autotest_hw.star"
+      }
+      test_plan_starlark_files {
+        host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/legacy_default_vm.star"
+      }
+      test_plan_starlark_files {
+        host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/fingerprint_cq.star"
+      }
+      # Skip testing on developer-tools.
+      path_regexp_excludes: "libchrome_tools/developer-tools/.*"
+    }
+    source_test_plans {
+      test_plan_starlark_files {
+      	host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/bvt_tast_cq_each_arch.star"
+      }
+      test_plan_starlark_files {
+      	host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/libchrome_cq.star"
+      }
+      path_regexps: "BASE_VER"
+      path_regexps: "libchrome_tools/patches"
+      path_regexps: ".*buildflags.h"
+    }
+  }
+}
diff --git a/MODULE_LICENSE_BSD b/MODULE_LICENSE_BSD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_BSD
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..15b7060
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//    * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//    * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//    * Neither the name of Google LLC nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..285b4f2
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,8 @@
+diwux@google.com
+fqj@google.com
+hashimoto@google.com
+hidehiko@google.com
+hscham@google.com
+jorgelo@google.com
+neis@google.com
+chromeos-ci-prod@chromeos-bot.iam.gserviceaccount.com # for automated uprevs
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
new file mode 100644
index 0000000..8a0f3b7
--- /dev/null
+++ b/PRESUBMIT.cfg
@@ -0,0 +1,12 @@
+# Files are verbatim copies of Chromium code base. Disable CrOS license check.
+# Specifically, generated files and files under third_party for mojom tools
+# are using non-chrome standard style. Disable style checks, too.
+[Options]
+ignore_merged_commits: true
+[Hook Scripts]
+check-patches = libchrome_tools/developer-tools/presubmit/check-patches.py --commit ${PRESUBMIT_COMMIT}
+[Hook Overrides]
+cros_license_check: false
+long_line_check: false
+stray_whitespace_check: false
+tab_check: false
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..775cc5a
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+# libchrome
+
+## Overview
+This directory includes the source from Chrome's libbase for use in Chrome OS.
+
+See [libchrome.md](https://chromium.googlesource.com/chromiumos/docs/+/HEAD/packages/libchrome.md)
+for more info.
diff --git a/base/android/java/src/org/chromium/base/BuildConfig.java b/base/android/java/src/org/chromium/base/BuildConfig.java
new file mode 100644
index 0000000..b8fa432
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/BuildConfig.java
@@ -0,0 +1,21 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+/**
+ *  Build configuration. Generated on a per-target basis.
+ */
+public class BuildConfig {
+
+
+    public static final String FIREBASE_APP_ID = "";
+
+    public static final boolean DCHECK_IS_ON = false;
+
+    // The ID of the android string resource that stores the product version.
+    // This layer of indirection is necessary to make the resource dependency
+    // optional for android_apk targets/base_java (ex. for cronet).
+    public static final int R_STRING_PRODUCT_VERSION = 0;
+}
diff --git a/base/base_paths_posix.cc b/base/base_paths_posix.cc
index 284e538..7f2e57a 100644
--- a/base/base_paths_posix.cc
+++ b/base/base_paths_posix.cc
@@ -19,7 +19,8 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
-#include "base/nix/xdg_util.h"
+// Unused, and this file is not ported to libchrome.
+// #include "base/nix/xdg_util.h"
 #include "base/notreached.h"
 #include "base/path_service.h"
 #include "base/posix/sysctl.h"
@@ -72,6 +73,8 @@
       return true;
 #endif
     }
+// Following paths are not supported in libchrome/libmojo.
+#if 0
     case DIR_SRC_TEST_DATA_ROOT: {
       FilePath path;
       // On POSIX, unit tests execute two levels deep from the source root.
@@ -95,6 +98,7 @@
       *result = cache_dir;
       return true;
     }
+#endif
   }
   return false;
 }
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index f484a2f..84a86b5 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -7,6 +7,11 @@
 
 #include "build/build_config.h"
 
+#if defined(ANDROID)
+// Prefer Android's libbase definitions to our own.
+#include <android-base/macros.h>
+#endif  // defined(ANDROID)
+
 #if defined(COMPILER_MSVC) && !defined(__clang__)
 #error "Only clang-cl is supported on Windows, see https://crbug.com/988071"
 #endif
diff --git a/base/generated_build_date.h b/base/generated_build_date.h
new file mode 100644
index 0000000..8ed0af3
--- /dev/null
+++ b/base/generated_build_date.h
@@ -0,0 +1,3 @@
+#ifndef BUILD_DATE
+#define BUILD_DATE __DATE__ " " __TIME__ " PST"
+#endif // BUILD_DATE
diff --git a/base/json/json_value_serializer_unittest.cc b/base/json/json_value_serializer_unittest.cc
index 12e10a4..2d93f07 100644
--- a/base/json/json_value_serializer_unittest.cc
+++ b/base/json/json_value_serializer_unittest.cc
@@ -393,7 +393,7 @@
   ScopedTempDir temp_dir_;
 };
 
-TEST_F(JSONFileValueSerializerTest, Roundtrip) {
+TEST_F(JSONFileValueSerializerTest, DISABLED_Roundtrip) {
   FilePath original_file_path;
   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
   original_file_path = original_file_path.AppendASCII("serializer_test.json");
@@ -431,7 +431,7 @@
   EXPECT_TRUE(DeleteFile(written_file_path));
 }
 
-TEST_F(JSONFileValueSerializerTest, RoundtripNested) {
+TEST_F(JSONFileValueSerializerTest, DISABLED_RoundtripNested) {
   FilePath original_file_path;
   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
   original_file_path =
@@ -457,7 +457,7 @@
   EXPECT_TRUE(DeleteFile(written_file_path));
 }
 
-TEST_F(JSONFileValueSerializerTest, NoWhitespace) {
+TEST_F(JSONFileValueSerializerTest, DISABLED_NoWhitespace) {
   FilePath source_file_path;
   ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &source_file_path));
   source_file_path =
diff --git a/base/location.cc b/base/location.cc
index 931758a..e7fb2b3 100644
--- a/base/location.cc
+++ b/base/location.cc
@@ -17,6 +17,7 @@
 
 namespace {
 
+#if 0
 // Returns the length of the given null terminated c-string.
 constexpr size_t StrLen(const char* str) {
   size_t str_len = 0;
@@ -73,6 +74,12 @@
               "The file name does not match the expected prefix format.");
 #endif
 
+#else
+
+constexpr size_t kStrippedPrefixLength = 0;
+
+#endif
+
 }  // namespace
 
 Location::Location() = default;
diff --git a/base/logging_buildflags.h b/base/logging_buildflags.h
new file mode 100644
index 0000000..eedae7b
--- /dev/null
+++ b/base/logging_buildflags.h
@@ -0,0 +1,13 @@
+// This buildflag header file will remain manually edited since value of NDEBUG
+// or DCHECK_ALWAYS_ON cannot be passed from BUILD.gn using buildflag_header.
+
+#ifndef BASE_LOGGING_BUILDFLAGS_H_
+#define BASE_LOGGING_BUILDFLAGS_H_
+#include "build/buildflag.h"
+#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
+#define BUILDFLAG_INTERNAL_ENABLE_LOG_ERROR_NOT_REACHED() (1)
+#else
+#define BUILDFLAG_INTERNAL_ENABLE_LOG_ERROR_NOT_REACHED() (0)
+#endif
+#define BUILDFLAG_INTERNAL_USE_RUNTIME_VLOG() (1)
+#endif  // BASE_LOGGING_BUILDFLAGS_H_
diff --git a/base/message_loop/message_pump_for_ui.h b/base/message_loop/message_pump_for_ui.h
index 458c29b..20a27c2 100644
--- a/base/message_loop/message_pump_for_ui.h
+++ b/base/message_loop/message_pump_for_ui.h
@@ -18,7 +18,7 @@
 #include "base/message_loop/message_pump.h"
 #elif BUILDFLAG(IS_NACL) || BUILDFLAG(IS_AIX)
 // No MessagePumpForUI, see below.
-#elif defined(USE_GLIB)
+#elif defined(USE_GLIB) && !defined(ANDROID)
 #include "base/message_loop/message_pump_glib.h"
 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_BSD)
 #include "base/message_loop/message_pump_epoll.h"
@@ -41,7 +41,7 @@
 #elif BUILDFLAG(IS_NACL) || BUILDFLAG(IS_AIX)
 // Currently NaCl and AIX don't have a MessagePumpForUI.
 // TODO(abarth): Figure out if we need this.
-#elif defined(USE_GLIB)
+#elif defined(USE_GLIB) && !defined(ANDROID)
 using MessagePumpForUI = MessagePumpGlib;
 #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_BSD)
 using MessagePumpForUI = MessagePumpEpoll;
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc
index d61a242..a360b0c 100644
--- a/base/process/process_metrics_unittest.cc
+++ b/base/process/process_metrics_unittest.cc
@@ -977,6 +977,8 @@
 
 }  // namespace
 
+// ARC note: don't compile as SpawnMultiProcessTestChild brings in a lot of
+// extra dependency.
 TEST(ProcessMetricsTest, GetChildOpenFdCount) {
   ScopedTempDir temp_dir;
   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
diff --git a/base/task/common/task_annotator.h b/base/task/common/task_annotator.h
index f8ca973..e87f097 100644
--- a/base/task/common/task_annotator.h
+++ b/base/task/common/task_annotator.h
@@ -33,6 +33,7 @@
  public:
   class ObserverForTesting {
    public:
+    virtual ~ObserverForTesting() = default;
     // Invoked just before RunTask() in the scope in which the task is about to
     // be executed.
     virtual void BeforeRunTask(const PendingTask* pending_task) = 0;
diff --git a/base/task/current_thread.h b/base/task/current_thread.h
index b6e265e..684cbb8 100644
--- a/base/task/current_thread.h
+++ b/base/task/current_thread.h
@@ -238,7 +238,7 @@
   raw_ptr<sequence_manager::internal::SequenceManagerImpl> current_;
 };
 
-#if !BUILDFLAG(IS_NACL)
+#if !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_ANDROID)
 
 // UI extension of CurrentThread.
 class BASE_EXPORT CurrentUIThread : public CurrentThread {
@@ -293,7 +293,7 @@
   MessagePumpForUI* GetMessagePumpForUI() const;
 };
 
-#endif  // !BUILDFLAG(IS_NACL)
+#endif  // !BUILDFLAG(IS_NACL) && !BUILDFLAG(IS_ANDROID)
 
 // ForIO extension of CurrentThread.
 class BASE_EXPORT CurrentIOThread : public CurrentThread {
diff --git a/base/test/multiprocess_test.cc b/base/test/multiprocess_test.cc
index d0bd49a..80b5229 100644
--- a/base/test/multiprocess_test.cc
+++ b/base/test/multiprocess_test.cc
@@ -53,6 +53,8 @@
 
 MultiProcessTest::MultiProcessTest() = default;
 
+// Don't compile on ARC.
+#if 0
 Process MultiProcessTest::SpawnChild(const std::string& procname) {
   LaunchOptions options;
 #if BUILDFLAG(IS_WIN)
@@ -65,6 +67,7 @@
                                                 const LaunchOptions& options) {
   return SpawnMultiProcessTestChild(procname, MakeCmdLine(procname), options);
 }
+#endif
 
 CommandLine MultiProcessTest::MakeCmdLine(const std::string& procname) {
   CommandLine command_line = GetMultiProcessTestChildBaseCommandLine();
diff --git a/base/test/test_pending_task.cc b/base/test/test_pending_task.cc
index 54a56b6..400c756 100644
--- a/base/test/test_pending_task.cc
+++ b/base/test/test_pending_task.cc
@@ -41,6 +41,8 @@
 
 TestPendingTask::~TestPendingTask() = default;
 
+// Unsupported in libchrome.
+#if 0
 void TestPendingTask::AsValueInto(base::trace_event::TracedValue* state) const {
   state->SetInteger("run_at", GetTimeToRun().ToInternalValue());
   state->SetString("posting_function", location.ToString());
@@ -64,10 +66,14 @@
   AsValueInto(state.get());
   return std::move(state);
 }
+#endif
 
 std::string TestPendingTask::ToString() const {
   std::string output("TestPendingTask(");
+// Unsupported in libchrome.
+#if 0
   AsValue()->AppendAsTraceFormat(&output);
+#endif
   output += ")";
   return output;
 }
diff --git a/base/test/test_pending_task.h b/base/test/test_pending_task.h
index 5ceb674..7b5ed6a 100644
--- a/base/test/test_pending_task.h
+++ b/base/test/test_pending_task.h
@@ -67,10 +67,13 @@
   TimeDelta delay;
   TestNestability nestability;
 
+// Unsupported in libchrome.
+#if 0
   // Functions for using test pending task with tracing, useful in unit
   // testing.
   void AsValueInto(base::trace_event::TracedValue* state) const;
   std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue() const;
+#endif
   std::string ToString() const;
 };
 
diff --git a/base/third_party/double_conversion/double-conversion/double-conversion.h b/base/third_party/double_conversion/double-conversion/double-conversion.h
new file mode 100644
index 0000000..1552f0b
--- /dev/null
+++ b/base/third_party/double_conversion/double-conversion/double-conversion.h
@@ -0,0 +1 @@
+#include <double-conversion/double-conversion.h>
diff --git a/base/third_party/libevent/event.h b/base/third_party/libevent/event.h
new file mode 100644
index 0000000..d47d797
--- /dev/null
+++ b/base/third_party/libevent/event.h
@@ -0,0 +1,10 @@
+// The Chromium build contains its own checkout of libevent. This stub is used
+// when building the Chrome OS or Android libchrome package to instead use the
+// system headers.
+#if defined(__ANDROID__) || defined(__ANDROID_HOST__)
+#include <event2/event.h>
+#include <event2/event_compat.h>
+#include <event2/event_struct.h>
+#else
+#include <event.h>
+#endif
diff --git a/base/third_party/symbolize/symbolize.h b/base/third_party/symbolize/symbolize.h
new file mode 100644
index 0000000..59beafb
--- /dev/null
+++ b/base/third_party/symbolize/symbolize.h
@@ -0,0 +1,15 @@
+// Copyright (C) 2018 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.
+
+#error "symbolize support was removed from libchrome"
diff --git a/base/threading/thread_id_name_manager.cc b/base/threading/thread_id_name_manager.cc
index 2ee7ca1..2d41cf5 100644
--- a/base/threading/thread_id_name_manager.cc
+++ b/base/threading/thread_id_name_manager.cc
@@ -99,7 +99,7 @@
   // cause a deadlock when the first allocation happens in the
   // ThreadIdNameManager itself when holding the lock.
   trace_event::AllocationContextTracker::SetCurrentThreadName(
-      leaked_str->c_str());
+    leaked_str->c_str());
 }
 
 const char* ThreadIdNameManager::GetName(PlatformThreadId id) {
diff --git a/base/threading/thread_local_storage.h b/base/threading/thread_local_storage.h
index c33ef6b..8ed3154 100644
--- a/base/threading/thread_local_storage.h
+++ b/base/threading/thread_local_storage.h
@@ -89,6 +89,13 @@
   // GetTLSValue() to retrieve the value of slot as it has already been reset
   // in Posix.
   static void OnThreadExit(void* value);
+  // Normally, Chrome runs as a process, so freeing the TLS is not needed since
+  // the OS will perform that while it's reclaiming the process' memory upon
+  // termination. If, however, this code is used inside a library that is
+  // dynamically loaded and unloaded, the consumer is responsible for calling
+  // this after all Chrome threads have stopped and prior to unloading the
+  // library.
+  static void ForceFreeTLS();
 #endif
 };
 
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py
index f12a7f0..85ee132 100644
--- a/build/android/gyp/util/build_utils.py
+++ b/build/android/gyp/util/build_utils.py
@@ -22,8 +22,16 @@
 import textwrap
 import zipfile
 
+# pylib conflicts with mojo/public/tools/bindings/pylib. Prioritize
+# build/android/pylib.
+# PYTHONPATH wouldn't help in this case, because soong put source files under
+# temp directory for each build, so the abspath is unknown until the
+# execution.
 sys.path.append(os.path.join(os.path.dirname(__file__),
                              os.pardir, os.pardir, os.pardir))
+# For soong build
+sys.path.insert(0, os.path.join(os.path.dirname(__file__),
+                                os.pardir, os.pardir))
 import gn_helpers
 
 # Use relative paths to improved hermetic property of build scripts.
diff --git a/build/build_config.h b/build/build_config.h
index e31bc76..9e5ca91 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -64,7 +64,7 @@
 // __native_client__ must be first, so that other OS_ defines are not set.
 #define OS_NACL 1
 #elif defined(ANDROID)
-#define OS_ANDROID 1
+#define OS_ANDROID
 #elif defined(__APPLE__)
 // Only include TargetConditionals after testing ANDROID as some Android builds
 // on the Mac have this header available and it's not needed unless the target
diff --git a/build/buildflag_header.gni b/build/buildflag_header.gni
index f7b42f7..e414086 100644
--- a/build/buildflag_header.gni
+++ b/build/buildflag_header.gni
@@ -93,9 +93,10 @@
 #       "SPAM_SERVER_URL=\"http://www.example.com/\"",
 #     ]
 #   }
+
 template("buildflag_header") {
   action(target_name) {
-    script = "//build/write_buildflag_header.py"
+    script = "build/write_buildflag_header.py"
 
     if (defined(invoker.header_dir)) {
       header_file = "${invoker.header_dir}/${invoker.header}"
@@ -132,6 +133,6 @@
                              "visibility",
                            ])
 
-    public_deps = [ "//build:buildflag_header_h" ]
+    public_deps = [ ":buildflag_header_h" ]
   }
 }
diff --git a/crypto/crypto_export.h b/crypto/crypto_export.h
new file mode 100644
index 0000000..66bd53c
--- /dev/null
+++ b/crypto/crypto_export.h
@@ -0,0 +1,32 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_CRYPTO_EXPORT_H_
+#define CRYPTO_CRYPTO_EXPORT_H_
+
+// Defines CRYPTO_EXPORT so that functionality implemented by the crypto module
+// can be exported to consumers.
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(CRYPTO_IMPLEMENTATION)
+#define CRYPTO_EXPORT __declspec(dllexport)
+#else
+#define CRYPTO_EXPORT __declspec(dllimport)
+#endif  // defined(CRYPTO_IMPLEMENTATION)
+
+#else  // defined(WIN32)
+#if defined(CRYPTO_IMPLEMENTATION)
+#define CRYPTO_EXPORT __attribute__((visibility("default")))
+#else
+#define CRYPTO_EXPORT
+#endif
+#endif
+
+#else  // defined(COMPONENT_BUILD)
+#define CRYPTO_EXPORT
+#endif
+
+#endif  // CRYPTO_CRYPTO_EXPORT_H_
diff --git a/crypto/crypto_unittests.isolate b/crypto/crypto_unittests.isolate
new file mode 100644
index 0000000..3c7e42a
--- /dev/null
+++ b/crypto/crypto_unittests.isolate
@@ -0,0 +1,42 @@
+# Copyright 2015 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'variables': {
+    'command': [
+      '../testing/test_env.py',
+      '<(PRODUCT_DIR)/crypto_unittests<(EXECUTABLE_SUFFIX)',
+      '--brave-new-test-launcher',
+      '--test-launcher-bot-mode',
+      '--asan=<(asan)',
+      '--msan=<(msan)',
+      '--tsan=<(tsan)',
+    ],
+  },
+  'conditions': [
+    ['OS=="linux" or OS=="mac" or OS=="win"', {
+      'variables': {
+        'files': [
+          '../testing/test_env.py',
+        ],
+      },
+    }],
+    ['OS=="mac" and asan==1 and fastbuild==0', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/crypto_unittests.dSYM/',
+        ],
+      },
+    }],
+    ['OS=="win" and (fastbuild==0 or fastbuild==1)', {
+      'variables': {
+        'files': [
+          '<(PRODUCT_DIR)/crypto_unittests.exe.pdb',
+        ],
+      },
+    }],
+  ],
+  'includes': [
+    '../base/base.isolate',
+  ],
+}
diff --git a/crypto/hmac.cc b/crypto/hmac.cc
new file mode 100644
index 0000000..0c505f6
--- /dev/null
+++ b/crypto/hmac.cc
@@ -0,0 +1,61 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/hmac.h"
+
+#include <stddef.h>
+
+#include <algorithm>
+#include <memory>
+
+#include "base/logging.h"
+#include "base/notreached.h"
+#include "crypto/secure_util.h"
+#include "crypto/symmetric_key.h"
+
+namespace crypto {
+
+bool HMAC::Init(SymmetricKey* key) {
+  std::string raw_key;
+  bool result = key->GetRawKey(&raw_key) && Init(raw_key);
+  // Zero out key copy.  This might get optimized away, but one can hope.
+  // Using std::string to store key info at all is a larger problem.
+  std::fill(raw_key.begin(), raw_key.end(), 0);
+  return result;
+}
+
+size_t HMAC::DigestLength() const {
+  switch (hash_alg_) {
+    case SHA1:
+      return 20;
+    case SHA256:
+      return 32;
+    default:
+      NOTREACHED();
+      return 0;
+  }
+}
+
+bool HMAC::Verify(std::string_view data,
+                  std::string_view digest) const {
+  if (digest.size() != DigestLength())
+    return false;
+  return VerifyTruncated(data, digest);
+}
+
+bool HMAC::VerifyTruncated(std::string_view data,
+                           std::string_view digest) const {
+  if (digest.empty())
+    return false;
+  size_t digest_length = DigestLength();
+  std::unique_ptr<unsigned char[]> computed_digest(
+      new unsigned char[digest_length]);
+  if (!Sign(data, computed_digest.get(), digest_length))
+    return false;
+
+  return SecureMemEqual(digest.data(), computed_digest.get(),
+                        std::min(digest.size(), digest_length));
+}
+
+}  // namespace crypto
diff --git a/crypto/hmac.h b/crypto/hmac.h
new file mode 100644
index 0000000..479676c
--- /dev/null
+++ b/crypto/hmac.h
@@ -0,0 +1,96 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Utility class for calculating the HMAC for a given message. We currently
+// only support SHA1 for the hash algorithm, but this can be extended easily.
+
+#ifndef CRYPTO_HMAC_H_
+#define CRYPTO_HMAC_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <string_view>
+
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// Simplify the interface and reduce includes by abstracting out the internals.
+struct HMACPlatformData;
+class SymmetricKey;
+
+class CRYPTO_EXPORT HMAC {
+ public:
+  // The set of supported hash functions. Extend as required.
+  enum HashAlgorithm {
+    SHA1,
+    SHA256,
+  };
+
+  explicit HMAC(HashAlgorithm hash_alg);
+
+  HMAC(const HMAC&) = delete;
+  HMAC& operator=(const HMAC&) = delete;
+
+  ~HMAC();
+
+  // Returns the length of digest that this HMAC will create.
+  size_t DigestLength() const;
+
+  // TODO(abarth): Add a PreferredKeyLength() member function.
+
+  // Initializes this instance using |key| of the length |key_length|. Call Init
+  // only once. It returns false on the second or later calls.
+  //
+  // NOTE: the US Federal crypto standard FIPS 198, Section 3 says:
+  //   The size of the key, K, shall be equal to or greater than L/2, where L
+  //   is the size of the hash function output.
+  // In FIPS 198-1 (and SP-800-107, which describes key size recommendations),
+  // this requirement is gone.  But a system crypto library may still enforce
+  // this old requirement.  If the key is shorter than this recommended value,
+  // Init() may fail.
+  [[nodiscard]] bool Init(const unsigned char* key, size_t key_length);
+
+  // Initializes this instance using |key|. Call Init
+  // only once. It returns false on the second or later calls.
+  [[nodiscard]] bool Init(SymmetricKey* key);
+
+  // Initializes this instance using |key|. Call Init only once. It returns
+  // false on the second or later calls.
+  [[nodiscard]] bool Init(std::string_view key) {
+    return Init(reinterpret_cast<const unsigned char*>(key.data()),
+                key.size());
+  }
+
+  // Calculates the HMAC for the message in |data| using the algorithm supplied
+  // to the constructor and the key supplied to the Init method. The HMAC is
+  // returned in |digest|, which has |digest_length| bytes of storage available.
+  [[nodiscard]] bool Sign(std::string_view data, unsigned char* digest,
+            size_t digest_length) const;
+
+  // Verifies that the HMAC for the message in |data| equals the HMAC provided
+  // in |digest|, using the algorithm supplied to the constructor and the key
+  // supplied to the Init method. Use of this method is strongly recommended
+  // over using Sign() with a manual comparison (such as memcmp), as such
+  // comparisons may result in side-channel disclosures, such as timing, that
+  // undermine the cryptographic integrity. |digest| must be exactly
+  // |DigestLength()| bytes long.
+  [[nodiscard]] bool Verify(std::string_view data,
+              std::string_view digest) const;
+
+  // Verifies a truncated HMAC, behaving identical to Verify(), except
+  // that |digest| is allowed to be smaller than |DigestLength()|.
+  [[nodiscard]] bool VerifyTruncated(
+      std::string_view data,
+      std::string_view digest) const;
+
+ private:
+  HashAlgorithm hash_alg_;
+  std::unique_ptr<HMACPlatformData> plat_;
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_HMAC_H_
diff --git a/crypto/hmac_nss.cc b/crypto/hmac_nss.cc
new file mode 100644
index 0000000..c69d6e2
--- /dev/null
+++ b/crypto/hmac_nss.cc
@@ -0,0 +1,119 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/hmac.h"
+
+#include <nss.h>
+#include <pk11pub.h>
+#include <stddef.h>
+
+#include <memory>
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace crypto {
+
+struct HMACPlatformData {
+  CK_MECHANISM_TYPE mechanism_;
+  ScopedPK11Slot slot_;
+  ScopedPK11SymKey sym_key_;
+};
+
+HMAC::HMAC(HashAlgorithm hash_alg)
+    : hash_alg_(hash_alg), plat_(new HMACPlatformData()) {
+  // Only SHA-1 and SHA-256 hash algorithms are supported.
+  switch (hash_alg_) {
+    case SHA1:
+      plat_->mechanism_ = CKM_SHA_1_HMAC;
+      break;
+    case SHA256:
+      plat_->mechanism_ = CKM_SHA256_HMAC;
+      break;
+    default:
+      NOTREACHED() << "Unsupported hash algorithm";
+      break;
+  }
+}
+
+HMAC::~HMAC() {
+}
+
+bool HMAC::Init(const unsigned char *key, size_t key_length) {
+  EnsureNSSInit();
+
+  if (plat_->slot_.get()) {
+    // Init must not be called more than twice on the same HMAC object.
+    NOTREACHED();
+    return false;
+  }
+
+  plat_->slot_.reset(PK11_GetInternalSlot());
+  if (!plat_->slot_.get()) {
+    NOTREACHED();
+    return false;
+  }
+
+  SECItem key_item;
+  key_item.type = siBuffer;
+  key_item.data = const_cast<unsigned char*>(key);  // NSS API isn't const.
+  key_item.len = key_length;
+
+  plat_->sym_key_.reset(PK11_ImportSymKey(plat_->slot_.get(),
+                                          plat_->mechanism_,
+                                          PK11_OriginUnwrap,
+                                          CKA_SIGN,
+                                          &key_item,
+                                          NULL));
+  if (!plat_->sym_key_.get()) {
+    NOTREACHED();
+    return false;
+  }
+
+  return true;
+}
+
+bool HMAC::Sign(std::string_view data,
+                unsigned char* digest,
+                size_t digest_length) const {
+  if (!plat_->sym_key_.get()) {
+    // Init has not been called before Sign.
+    NOTREACHED();
+    return false;
+  }
+
+  SECItem param = { siBuffer, NULL, 0 };
+  ScopedPK11Context context(PK11_CreateContextBySymKey(plat_->mechanism_,
+                                                       CKA_SIGN,
+                                                       plat_->sym_key_.get(),
+                                                       &param));
+  if (!context.get()) {
+    NOTREACHED();
+    return false;
+  }
+
+  if (PK11_DigestBegin(context.get()) != SECSuccess) {
+    NOTREACHED();
+    return false;
+  }
+
+  if (PK11_DigestOp(context.get(),
+                    reinterpret_cast<const unsigned char*>(data.data()),
+                    data.length()) != SECSuccess) {
+    NOTREACHED();
+    return false;
+  }
+
+  unsigned int len = 0;
+  if (PK11_DigestFinal(context.get(),
+                       digest, &len, digest_length) != SECSuccess) {
+    NOTREACHED();
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace crypto
diff --git a/crypto/hmac_unittest.cc b/crypto/hmac_unittest.cc
new file mode 100644
index 0000000..7d8fdb6
--- /dev/null
+++ b/crypto/hmac_unittest.cc
@@ -0,0 +1,297 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+
+#include <string>
+
+#include "crypto/hmac.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+static const size_t kSHA1DigestSize = 20;
+static const size_t kSHA256DigestSize = 32;
+
+static const char* kSimpleKey =
+    "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+    "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+    "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+    "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+    "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA";
+static const size_t kSimpleKeyLength = 80;
+
+static const struct {
+  const char *data;
+  const int data_len;
+  const char *digest;
+} kSimpleHmacCases[] = {
+  { "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+    "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55"
+        "\xED\x40\x21\x12" },
+  { "Test Using Larger Than Block-Size Key and Larger "
+        "Than One Block-Size Data", 73,
+    "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08"
+        "\xBB\xFF\x1A\x91" }
+};
+
+TEST(HMACTest, HmacSafeBrowsingResponseTest) {
+  const int kKeySize = 16;
+
+  // Client key.
+  const unsigned char kClientKey[kKeySize] =
+      { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd,
+        0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 };
+
+  // Expected HMAC result using kMessage and kClientKey.
+  const unsigned char kReceivedHmac[kSHA1DigestSize] =
+      { 0xb9, 0x3c, 0xd6, 0xf0, 0x49, 0x47, 0xe2, 0x52,
+        0x59, 0x7a, 0xbd, 0x1f, 0x2b, 0x4c, 0x83, 0xad,
+        0x86, 0xd2, 0x48, 0x85 };
+
+  const char kMessage[] =
+"n:1896\ni:goog-malware-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav"
+"ar_s_445-450\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_439-444\nu:s"
+".ytimg.com/safebrowsing/rd/goog-malware-shavar_s_437\nu:s.ytimg.com/safebrowsi"
+"ng/rd/goog-malware-shavar_s_436\nu:s.ytimg.com/safebrowsing/rd/goog-malware-sh"
+"avar_s_433-435\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_431\nu:s.y"
+"timg.com/safebrowsing/rd/goog-malware-shavar_s_430\nu:s.ytimg.com/safebrowsing"
+"/rd/goog-malware-shavar_s_429\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav"
+"ar_s_428\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_426\nu:s.ytimg.c"
+"om/safebrowsing/rd/goog-malware-shavar_s_424\nu:s.ytimg.com/safebrowsing/rd/go"
+"og-malware-shavar_s_423\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4"
+"22\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_420\nu:s.ytimg.com/saf"
+"ebrowsing/rd/goog-malware-shavar_s_419\nu:s.ytimg.com/safebrowsing/rd/goog-mal"
+"ware-shavar_s_414\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_409-411"
+"\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_405\nu:s.ytimg.com/safeb"
+"rowsing/rd/goog-malware-shavar_s_404\nu:s.ytimg.com/safebrowsing/rd/goog-malwa"
+"re-shavar_s_402\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_401\nu:s."
+"ytimg.com/safebrowsing/rd/goog-malware-shavar_a_973-978\nu:s.ytimg.com/safebro"
+"wsing/rd/goog-malware-shavar_a_937-972\nu:s.ytimg.com/safebrowsing/rd/goog-mal"
+"ware-shavar_a_931-936\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_925"
+"-930\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_919-924\ni:goog-phis"
+"h-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2633\nu:s.ytimg.co"
+"m/safebrowsing/rd/goog-phish-shavar_a_2632\nu:s.ytimg.com/safebrowsing/rd/goog"
+"-phish-shavar_a_2629-2631\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2"
+"626-2628\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2625\n";
+
+  std::string message_data(kMessage);
+
+  crypto::HMAC hmac(crypto::HMAC::SHA1);
+  ASSERT_TRUE(hmac.Init(kClientKey, kKeySize));
+  unsigned char calculated_hmac[kSHA1DigestSize];
+
+  EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize));
+  EXPECT_EQ(0, memcmp(kReceivedHmac, calculated_hmac, kSHA1DigestSize));
+}
+
+// Test cases from RFC 2202 section 3
+TEST(HMACTest, RFC2202TestCases) {
+  const struct {
+    const char *key;
+    const int key_len;
+    const char *data;
+    const int data_len;
+    const char *digest;
+  } cases[] = {
+    { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+          "\x0B\x0B\x0B\x0B", 20,
+      "Hi There", 8,
+      "\xB6\x17\x31\x86\x55\x05\x72\x64\xE2\x8B\xC0\xB6\xFB\x37\x8C\x8E"
+          "\xF1\x46\xBE\x00" },
+    { "Jefe", 4,
+      "what do ya want for nothing?", 28,
+      "\xEF\xFC\xDF\x6A\xE5\xEB\x2F\xA2\xD2\x74\x16\xD5\xF1\x84\xDF\x9C"
+          "\x25\x9A\x7C\x79" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+          "\xAA\xAA\xAA\xAA", 20,
+      "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+          "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+          "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+          "\xDD\xDD", 50,
+      "\x12\x5D\x73\x42\xB9\xAC\x11\xCD\x91\xA3\x9A\xF4\x8A\xA1\x7B\x4F"
+          "\x63\xF1\x75\xD3" },
+    { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+          "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
+      "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+          "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+          "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+          "\xCD\xCD", 50,
+      "\x4C\x90\x07\xF4\x02\x62\x50\xC6\xBC\x84\x14\xF9\xBF\x50\xC8\x6C"
+          "\x2D\x72\x35\xDA" },
+    { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+          "\x0C\x0C\x0C\x0C", 20,
+      "Test With Truncation", 20,
+      "\x4C\x1A\x03\x42\x4B\x55\xE0\x7F\xE7\xF2\x7B\xE1\xD5\x8B\xB9\x32"
+          "\x4A\x9A\x5A\x04" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+          "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+          "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+          "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+          "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
+      80,
+      "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+      "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55"
+          "\xED\x40\x21\x12" },
+    { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+          "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+          "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+          "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+          "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
+      80,
+      "Test Using Larger Than Block-Size Key and Larger "
+          "Than One Block-Size Data", 73,
+      "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08"
+          "\xBB\xFF\x1A\x91" }
+  };
+
+  for (size_t i = 0; i < arraysize(cases); ++i) {
+    crypto::HMAC hmac(crypto::HMAC::SHA1);
+    ASSERT_TRUE(hmac.Init(reinterpret_cast<const unsigned char*>(cases[i].key),
+                          cases[i].key_len));
+    std::string data_string(cases[i].data, cases[i].data_len);
+    unsigned char digest[kSHA1DigestSize];
+    EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize));
+    EXPECT_EQ(0, memcmp(cases[i].digest, digest, kSHA1DigestSize));
+  }
+}
+
+// TODO(wtc): add other test vectors from RFC 4231.
+TEST(HMACTest, RFC4231TestCase6) {
+  unsigned char key[131];
+  for (size_t i = 0; i < sizeof(key); ++i)
+    key[i] = 0xaa;
+
+  std::string data = "Test Using Larger Than Block-Size Key - Hash Key First";
+  ASSERT_EQ(54U, data.size());
+
+  static unsigned char kKnownHMACSHA256[] = {
+    0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
+    0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
+    0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
+    0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54
+  };
+
+  crypto::HMAC hmac(crypto::HMAC::SHA256);
+  ASSERT_TRUE(hmac.Init(key, sizeof(key)));
+  unsigned char calculated_hmac[kSHA256DigestSize];
+
+  EXPECT_EQ(kSHA256DigestSize, hmac.DigestLength());
+  EXPECT_TRUE(hmac.Sign(data, calculated_hmac, kSHA256DigestSize));
+  EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize));
+}
+
+// Based on NSS's FIPS HMAC power-up self-test.
+TEST(HMACTest, NSSFIPSPowerUpSelfTest) {
+  static const char kKnownMessage[] =
+      "The test message for the MD2, MD5, and SHA-1 hashing algorithms.";
+
+  static const unsigned char kKnownSecretKey[] = {
+    0x46, 0x69, 0x72, 0x65, 0x66, 0x6f, 0x78, 0x20,
+    0x61, 0x6e, 0x64, 0x20, 0x54, 0x68, 0x75, 0x6e,
+    0x64, 0x65, 0x72, 0x42, 0x69, 0x72, 0x64, 0x20,
+    0x61, 0x72, 0x65, 0x20, 0x61, 0x77, 0x65, 0x73,
+    0x6f, 0x6d, 0x65, 0x21, 0x00
+  };
+
+  static const size_t kKnownSecretKeySize = sizeof(kKnownSecretKey);
+
+  // HMAC-SHA-1 known answer (20 bytes).
+  static const unsigned char kKnownHMACSHA1[] = {
+    0xd5, 0x85, 0xf6, 0x5b, 0x39, 0xfa, 0xb9, 0x05,
+    0x3b, 0x57, 0x1d, 0x61, 0xe7, 0xb8, 0x84, 0x1e,
+    0x5d, 0x0e, 0x1e, 0x11
+  };
+
+  // HMAC-SHA-256 known answer (32 bytes).
+  static const unsigned char kKnownHMACSHA256[] = {
+    0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44,
+    0xe2, 0x46, 0x4b, 0x92, 0x22, 0x14, 0x22, 0xe0,
+    0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5, 0x49, 0xe9,
+    0xa7, 0x1b, 0x56, 0x7d, 0x1d, 0x29, 0x40, 0x48
+  };
+
+  std::string message_data(kKnownMessage);
+
+  crypto::HMAC hmac(crypto::HMAC::SHA1);
+  ASSERT_TRUE(hmac.Init(kKnownSecretKey, kKnownSecretKeySize));
+  unsigned char calculated_hmac[kSHA1DigestSize];
+
+  EXPECT_EQ(kSHA1DigestSize, hmac.DigestLength());
+  EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize));
+  EXPECT_EQ(0, memcmp(kKnownHMACSHA1, calculated_hmac, kSHA1DigestSize));
+  EXPECT_TRUE(hmac.Verify(
+      message_data,
+      std::string_view(reinterpret_cast<const char*>(kKnownHMACSHA1),
+                        kSHA1DigestSize)));
+  EXPECT_TRUE(hmac.VerifyTruncated(
+      message_data,
+      std::string_view(reinterpret_cast<const char*>(kKnownHMACSHA1),
+                        kSHA1DigestSize / 2)));
+
+  crypto::HMAC hmac2(crypto::HMAC::SHA256);
+  ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize));
+  unsigned char calculated_hmac2[kSHA256DigestSize];
+
+  EXPECT_TRUE(hmac2.Sign(message_data, calculated_hmac2, kSHA256DigestSize));
+  EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac2, kSHA256DigestSize));
+}
+
+TEST(HMACTest, HMACObjectReuse) {
+  crypto::HMAC hmac(crypto::HMAC::SHA1);
+  ASSERT_TRUE(
+      hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
+                kSimpleKeyLength));
+  for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) {
+    std::string data_string(kSimpleHmacCases[i].data,
+                            kSimpleHmacCases[i].data_len);
+    unsigned char digest[kSHA1DigestSize];
+    EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize));
+    EXPECT_EQ(0, memcmp(kSimpleHmacCases[i].digest, digest, kSHA1DigestSize));
+  }
+}
+
+TEST(HMACTest, Verify) {
+  crypto::HMAC hmac(crypto::HMAC::SHA1);
+  ASSERT_TRUE(
+      hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
+                kSimpleKeyLength));
+  const char empty_digest[kSHA1DigestSize] = { 0 };
+  for (size_t i = 0; i < arraysize(kSimpleHmacCases); ++i) {
+    // Expected results
+    EXPECT_TRUE(hmac.Verify(
+        std::string_view(kSimpleHmacCases[i].data,
+                          kSimpleHmacCases[i].data_len),
+        std::string_view(kSimpleHmacCases[i].digest,
+                          kSHA1DigestSize)));
+    // Mismatched size
+    EXPECT_FALSE(hmac.Verify(
+        std::string_view(kSimpleHmacCases[i].data,
+                          kSimpleHmacCases[i].data_len),
+        std::string_view(kSimpleHmacCases[i].data,
+                          kSimpleHmacCases[i].data_len)));
+
+    // Expected size, mismatched data
+    EXPECT_FALSE(hmac.Verify(
+        std::string_view(kSimpleHmacCases[i].data,
+                          kSimpleHmacCases[i].data_len),
+        std::string_view(empty_digest, kSHA1DigestSize)));
+  }
+}
+
+TEST(HMACTest, EmptyKey) {
+  // Test vector from https://en.wikipedia.org/wiki/HMAC
+  const char* kExpectedDigest =
+      "\xFB\xDB\x1D\x1B\x18\xAA\x6C\x08\x32\x4B\x7D\x64\xB7\x1F\xB7\x63"
+      "\x70\x69\x0E\x1D";
+  std::string_view data("");
+
+  crypto::HMAC hmac(crypto::HMAC::SHA1);
+  ASSERT_TRUE(hmac.Init(NULL, 0));
+
+  unsigned char digest[kSHA1DigestSize];
+  EXPECT_TRUE(hmac.Sign(data, digest, kSHA1DigestSize));
+  EXPECT_EQ(0, memcmp(kExpectedDigest, digest, kSHA1DigestSize));
+
+  EXPECT_TRUE(hmac.Verify(
+      data, std::string_view(kExpectedDigest, kSHA1DigestSize)));
+}
diff --git a/crypto/libcrypto-compat.c b/crypto/libcrypto-compat.c
new file mode 100644
index 0000000..ab6509a
--- /dev/null
+++ b/crypto/libcrypto-compat.c
@@ -0,0 +1,455 @@
+/*

+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.

+ *

+ * Licensed under the OpenSSL license (the "License").  You may not use

+ * this file except in compliance with the License.  You can obtain a copy

+ * in the file LICENSE in the source distribution or at

+ * https://www.openssl.org/source/license.html

+ */

+

+#include <openssl/opensslv.h> /* For OPENSSL_VERSION_NUMBER */

+#include "crypto/libcrypto-compat.h"

+

+#if OPENSSL_VERSION_NUMBER < 0x10100000L

+

+#include <string.h>

+#include <openssl/engine.h>

+

+const unsigned char* ASN1_STRING_get0_data(const ASN1_STRING* x)

+{

+  return x->data;

+}

+

+void BIO_set_data(BIO* a, void* ptr)

+{

+    a->ptr = ptr;

+}

+

+void* BIO_get_data(BIO* a)

+{

+    return a->ptr;

+}

+

+void BIO_set_init(BIO* a, int init)

+{

+    a->init = init;

+}

+

+int BIO_get_init(BIO* a) {

+    return a->init;

+}

+

+void BIO_set_shutdown(BIO* a, int shut)

+{

+    a->shutdown = shut;

+}

+

+static void *OPENSSL_zalloc(size_t num)

+{

+    void *ret = OPENSSL_malloc(num);

+

+    if (ret != NULL)

+        memset(ret, 0, num);

+    return ret;

+}

+

+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)

+{

+    /* If the fields n and e in r are NULL, the corresponding input

+     * parameters MUST be non-NULL for n and e.  d may be

+     * left NULL (in case only the public key is used).

+     */

+    if ((r->n == NULL && n == NULL)

+        || (r->e == NULL && e == NULL))

+        return 0;

+

+    if (n != NULL) {

+        BN_free(r->n);

+        r->n = n;

+    }

+    if (e != NULL) {

+        BN_free(r->e);

+        r->e = e;

+    }

+    if (d != NULL) {

+        BN_free(r->d);

+        r->d = d;

+    }

+

+    return 1;

+}

+

+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q)

+{

+    /* If the fields p and q in r are NULL, the corresponding input

+     * parameters MUST be non-NULL.

+     */

+    if ((r->p == NULL && p == NULL)

+        || (r->q == NULL && q == NULL))

+        return 0;

+

+    if (p != NULL) {

+        BN_free(r->p);

+        r->p = p;

+    }

+    if (q != NULL) {

+        BN_free(r->q);

+        r->q = q;

+    }

+

+    return 1;

+}

+

+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp)

+{

+    /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input

+     * parameters MUST be non-NULL.

+     */

+    if ((r->dmp1 == NULL && dmp1 == NULL)

+        || (r->dmq1 == NULL && dmq1 == NULL)

+        || (r->iqmp == NULL && iqmp == NULL))

+        return 0;

+

+    if (dmp1 != NULL) {

+        BN_free(r->dmp1);

+        r->dmp1 = dmp1;

+    }

+    if (dmq1 != NULL) {

+        BN_free(r->dmq1);

+        r->dmq1 = dmq1;

+    }

+    if (iqmp != NULL) {

+        BN_free(r->iqmp);

+        r->iqmp = iqmp;

+    }

+

+    return 1;

+}

+

+void RSA_get0_key(const RSA *r,

+                  const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)

+{

+    if (n != NULL)

+        *n = r->n;

+    if (e != NULL)

+        *e = r->e;

+    if (d != NULL)

+        *d = r->d;

+}

+

+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)

+{

+    if (p != NULL)

+        *p = r->p;

+    if (q != NULL)

+        *q = r->q;

+}

+

+void RSA_get0_crt_params(const RSA *r,

+                         const BIGNUM **dmp1, const BIGNUM **dmq1,

+                         const BIGNUM **iqmp)

+{

+    if (dmp1 != NULL)

+        *dmp1 = r->dmp1;

+    if (dmq1 != NULL)

+        *dmq1 = r->dmq1;

+    if (iqmp != NULL)

+        *iqmp = r->iqmp;

+}

+

+void DSA_get0_pqg(const DSA *d,

+                  const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)

+{

+    if (p != NULL)

+        *p = d->p;

+    if (q != NULL)

+        *q = d->q;

+    if (g != NULL)

+        *g = d->g;

+}

+

+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)

+{

+    /* If the fields p, q and g in d are NULL, the corresponding input

+     * parameters MUST be non-NULL.

+     */

+    if ((d->p == NULL && p == NULL)

+        || (d->q == NULL && q == NULL)

+        || (d->g == NULL && g == NULL))

+        return 0;

+

+    if (p != NULL) {

+        BN_free(d->p);

+        d->p = p;

+    }

+    if (q != NULL) {

+        BN_free(d->q);

+        d->q = q;

+    }

+    if (g != NULL) {

+        BN_free(d->g);

+        d->g = g;

+    }

+

+    return 1;

+}

+

+void DSA_get0_key(const DSA *d,

+                  const BIGNUM **pub_key, const BIGNUM **priv_key)

+{

+    if (pub_key != NULL)

+        *pub_key = d->pub_key;

+    if (priv_key != NULL)

+        *priv_key = d->priv_key;

+}

+

+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)

+{

+    /* If the field pub_key in d is NULL, the corresponding input

+     * parameters MUST be non-NULL.  The priv_key field may

+     * be left NULL.

+     */

+    if (d->pub_key == NULL && pub_key == NULL)

+        return 0;

+

+    if (pub_key != NULL) {

+        BN_free(d->pub_key);

+        d->pub_key = pub_key;

+    }

+    if (priv_key != NULL) {

+        BN_free(d->priv_key);

+        d->priv_key = priv_key;

+    }

+

+    return 1;

+}

+

+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)

+{

+    if (pr != NULL)

+        *pr = sig->r;

+    if (ps != NULL)

+        *ps = sig->s;

+}

+

+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)

+{

+    if (r == NULL || s == NULL)

+        return 0;

+    BN_clear_free(sig->r);

+    BN_clear_free(sig->s);

+    sig->r = r;

+    sig->s = s;

+    return 1;

+}

+

+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)

+{

+    if (pr != NULL)

+        *pr = sig->r;

+    if (ps != NULL)

+        *ps = sig->s;

+}

+

+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)

+{

+    if (r == NULL || s == NULL)

+        return 0;

+    BN_clear_free(sig->r);

+    BN_clear_free(sig->s);

+    sig->r = r;

+    sig->s = s;

+    return 1;

+}

+

+void DH_get0_pqg(const DH *dh,

+                 const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)

+{

+    if (p != NULL)

+        *p = dh->p;

+    if (q != NULL)

+        *q = dh->q;

+    if (g != NULL)

+        *g = dh->g;

+}

+

+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)

+{

+    /* If the fields p and g in d are NULL, the corresponding input

+     * parameters MUST be non-NULL.  q may remain NULL.

+     */

+    if ((dh->p == NULL && p == NULL)

+        || (dh->g == NULL && g == NULL))

+        return 0;

+

+    if (p != NULL) {

+        BN_free(dh->p);

+        dh->p = p;

+    }

+    if (q != NULL) {

+        BN_free(dh->q);

+        dh->q = q;

+    }

+    if (g != NULL) {

+        BN_free(dh->g);

+        dh->g = g;

+    }

+

+    if (q != NULL) {

+        dh->length = BN_num_bits(q);

+    }

+

+    return 1;

+}

+

+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key)

+{

+    if (pub_key != NULL)

+        *pub_key = dh->pub_key;

+    if (priv_key != NULL)

+        *priv_key = dh->priv_key;

+}

+

+int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)

+{

+    /* If the field pub_key in dh is NULL, the corresponding input

+     * parameters MUST be non-NULL.  The priv_key field may

+     * be left NULL.

+     */

+    if (dh->pub_key == NULL && pub_key == NULL)

+        return 0;

+

+    if (pub_key != NULL) {

+        BN_free(dh->pub_key);

+        dh->pub_key = pub_key;

+    }

+    if (priv_key != NULL) {

+        BN_free(dh->priv_key);

+        dh->priv_key = priv_key;

+    }

+

+    return 1;

+}

+

+int DH_set_length(DH *dh, long length)

+{

+    dh->length = length;

+    return 1;

+}

+

+const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx)

+{

+    return ctx->iv;

+}

+

+unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx)

+{

+    return ctx->iv;

+}

+

+EVP_MD_CTX *EVP_MD_CTX_new(void)

+{

+    return OPENSSL_zalloc(sizeof(EVP_MD_CTX));

+}

+

+void EVP_MD_CTX_free(EVP_MD_CTX *ctx)

+{

+    EVP_MD_CTX_cleanup(ctx);

+    OPENSSL_free(ctx);

+}

+

+HMAC_CTX *HMAC_CTX_new(void)

+{

+    HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));

+    if (ctx) {

+        HMAC_CTX_init(ctx);

+    }

+    return ctx;

+}

+

+void HMAC_CTX_free(HMAC_CTX *ctx)

+{

+    HMAC_CTX_cleanup(ctx);

+    OPENSSL_free(ctx);

+}

+

+

+RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth)

+{

+    RSA_METHOD *ret;

+

+    ret = OPENSSL_malloc(sizeof(RSA_METHOD));

+

+    if (ret != NULL) {

+        memcpy(ret, meth, sizeof(*meth));

+        ret->name = OPENSSL_strdup(meth->name);

+        if (ret->name == NULL) {

+            OPENSSL_free(ret);

+            return NULL;

+        }

+    }

+

+    return ret;

+}

+

+int RSA_meth_set1_name(RSA_METHOD *meth, const char *name)

+{

+    char *tmpname;

+

+    tmpname = OPENSSL_strdup(name);

+    if (tmpname == NULL) {

+        return 0;

+    }

+

+    OPENSSL_free((char *)meth->name);

+    meth->name = tmpname;

+

+    return 1;

+}

+

+int RSA_meth_set_priv_enc(RSA_METHOD *meth,

+                          int (*priv_enc) (int flen, const unsigned char *from,

+                                           unsigned char *to, RSA *rsa,

+                                           int padding))

+{

+    meth->rsa_priv_enc = priv_enc;

+    return 1;

+}

+

+int RSA_meth_set_priv_dec(RSA_METHOD *meth,

+                          int (*priv_dec) (int flen, const unsigned char *from,

+                                           unsigned char *to, RSA *rsa,

+                                           int padding))

+{

+    meth->rsa_priv_dec = priv_dec;

+    return 1;

+}

+

+int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa))

+{

+    meth->finish = finish;

+    return 1;

+}

+

+void RSA_meth_free(RSA_METHOD *meth)

+{

+    if (meth != NULL) {

+        OPENSSL_free((char *)meth->name);

+        OPENSSL_free(meth);

+    }

+}

+

+int RSA_bits(const RSA *r)

+{

+    return (BN_num_bits(r->n));

+}

+

+RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)

+{

+    if (pkey->type != EVP_PKEY_RSA) {

+        return NULL;

+    }

+    return pkey->pkey.rsa;

+}

+

+#endif /* OPENSSL_VERSION_NUMBER */

diff --git a/crypto/libcrypto-compat.h b/crypto/libcrypto-compat.h
new file mode 100644
index 0000000..8e5f72c
--- /dev/null
+++ b/crypto/libcrypto-compat.h
@@ -0,0 +1,96 @@
+/*

+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.

+ *

+ * Licensed under the OpenSSL license (the "License").  You may not use

+ * this file except in compliance with the License.  You can obtain a copy

+ * in the file LICENSE in the source distribution or at

+ * https://www.openssl.org/source/license.html

+ */

+

+#ifndef LIBCRYPTO_COMPAT_H

+#define LIBCRYPTO_COMPAT_H

+

+#include <openssl/opensslv.h> /* For OPENSSL_VERSION_NUMBER */

+

+#if OPENSSL_VERSION_NUMBER < 0x10100000L

+

+#include <openssl/asn1.h>

+#include <openssl/bio.h>

+#include <openssl/dh.h>

+#include <openssl/dsa.h>

+#include <openssl/ecdsa.h>

+#include <openssl/evp.h>

+#include <openssl/hmac.h>

+#include <openssl/rsa.h>

+

+#include "crypto/crypto_export.h"

+

+#ifdef __cplusplus

+extern "C"

+{

+#endif

+

+CRYPTO_EXPORT const unsigned char* ASN1_STRING_get0_data(const ASN1_STRING* x);

+

+CRYPTO_EXPORT void BIO_set_data(BIO* a, void* ptr);

+CRYPTO_EXPORT void* BIO_get_data(BIO* a);

+CRYPTO_EXPORT void BIO_set_init(BIO* a, int init);

+CRYPTO_EXPORT int BIO_get_init(BIO* a);

+CRYPTO_EXPORT void BIO_set_shutdown(BIO* a, int shut);

+

+CRYPTO_EXPORT int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);

+CRYPTO_EXPORT int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q);

+CRYPTO_EXPORT int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp);

+CRYPTO_EXPORT void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d);

+CRYPTO_EXPORT void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q);

+CRYPTO_EXPORT void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp);

+

+CRYPTO_EXPORT void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);

+CRYPTO_EXPORT int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g);

+CRYPTO_EXPORT void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key);

+CRYPTO_EXPORT int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key);

+

+CRYPTO_EXPORT void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);

+CRYPTO_EXPORT int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s);

+

+CRYPTO_EXPORT void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);

+CRYPTO_EXPORT int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);

+

+CRYPTO_EXPORT void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);

+CRYPTO_EXPORT int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g);

+CRYPTO_EXPORT void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key);

+CRYPTO_EXPORT int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key);

+CRYPTO_EXPORT int DH_set_length(DH *dh, long length);

+

+CRYPTO_EXPORT const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);

+CRYPTO_EXPORT unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);

+CRYPTO_EXPORT EVP_MD_CTX *EVP_MD_CTX_new(void);

+CRYPTO_EXPORT void EVP_MD_CTX_free(EVP_MD_CTX *ctx);

+#define EVP_CIPHER_impl_ctx_size(e) (e)->ctx_size

+#define EVP_CIPHER_CTX_get_cipher_data(ctx) (ctx)->cipher_data

+

+CRYPTO_EXPORT HMAC_CTX *HMAC_CTX_new(void);

+CRYPTO_EXPORT void HMAC_CTX_free(HMAC_CTX *ctx);

+

+#define TLS_client_method() TLSv1_2_client_method()

+

+CRYPTO_EXPORT RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth);

+CRYPTO_EXPORT int RSA_meth_set1_name(RSA_METHOD *meth, const char *name);

+#define RSA_meth_get_finish(meth) (meth)->finish

+CRYPTO_EXPORT int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));

+CRYPTO_EXPORT int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding));

+CRYPTO_EXPORT int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa));

+CRYPTO_EXPORT void RSA_meth_free(RSA_METHOD *meth);

+

+CRYPTO_EXPORT int RSA_bits(const RSA *r);

+

+CRYPTO_EXPORT RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);

+

+#ifdef __cplusplus

+} // extern "C"

+#endif

+

+

+#endif /* OPENSSL_VERSION_NUMBER */

+

+#endif /* LIBCRYPTO_COMPAT_H */

diff --git a/crypto/nss_crypto_module_delegate.h b/crypto/nss_crypto_module_delegate.h
new file mode 100644
index 0000000..83dbbc7
--- /dev/null
+++ b/crypto/nss_crypto_module_delegate.h
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_
+#define CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_
+
+#include <string>
+
+#include "base/functional/callback_forward.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace crypto {
+
+// PK11_SetPasswordFunc is a global setting.  An implementation of
+// CryptoModuleBlockingPasswordDelegate should be passed using wincx() as the
+// user data argument (|wincx|) to relevant NSS functions, which the global
+// password handler will call to do the actual work. This delegate should only
+// be used in NSS calls on worker threads due to the blocking nature.
+class CryptoModuleBlockingPasswordDelegate {
+ public:
+  virtual ~CryptoModuleBlockingPasswordDelegate() {}
+
+  // Return a value suitable for passing to the |wincx| argument of relevant NSS
+  // functions. This should be used instead of passing the object pointer
+  // directly to avoid accidentally casting a pointer to a subclass to void* and
+  // then casting back to a pointer of the base class
+  void* wincx() { return this; }
+
+  // Requests a password to unlock |slot_name|. The interface is synchronous
+  // because NSS cannot issue an asynchronous request. |retry| is true if this
+  // is a request for the retry and we previously returned the wrong password.
+  // The implementation should set |*cancelled| to true if the user cancelled
+  // instead of entering a password, otherwise it should return the password the
+  // user entered.
+  virtual std::string RequestPassword(const std::string& slot_name, bool retry,
+                                      bool* cancelled) = 0;
+
+};
+
+// Extends CryptoModuleBlockingPasswordDelegate with the ability to return a
+// slot in which to act. (Eg, which slot to store a generated key in.)
+class NSSCryptoModuleDelegate : public CryptoModuleBlockingPasswordDelegate {
+ public:
+  ~NSSCryptoModuleDelegate() override {}
+
+  // Get the slot to store the generated key.
+  virtual ScopedPK11Slot RequestSlot() = 0;
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_
diff --git a/crypto/nss_key_util.cc b/crypto/nss_key_util.cc
new file mode 100644
index 0000000..8c32dd8
--- /dev/null
+++ b/crypto/nss_key_util.cc
@@ -0,0 +1,165 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/nss_key_util.h"
+
+#include <cryptohi.h>
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+
+#if defined(USE_NSS_CERTS)
+#include <secmod.h>
+#include "crypto/nss_util_internal.h"
+#endif
+
+namespace crypto {
+
+namespace {
+
+#if defined(USE_NSS_CERTS)
+
+struct PublicKeyInfoDeleter {
+  inline void operator()(CERTSubjectPublicKeyInfo* spki) {
+    SECKEY_DestroySubjectPublicKeyInfo(spki);
+  }
+};
+
+typedef std::unique_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter>
+    ScopedPublicKeyInfo;
+
+// Decodes |input| as a SubjectPublicKeyInfo and returns a SECItem containing
+// the CKA_ID of that public key or nullptr on error.
+ScopedSECItem MakeIDFromSPKI(const std::vector<uint8_t>& input) {
+  // First, decode and save the public key.
+  SECItem key_der;
+  key_der.type = siBuffer;
+  key_der.data = const_cast<unsigned char*>(input.data());
+  key_der.len = input.size();
+
+  ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der));
+  if (!spki)
+    return nullptr;
+
+  ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get()));
+  if (!result)
+    return nullptr;
+
+  // See pk11_MakeIDFromPublicKey from NSS. For now, only RSA keys are
+  // supported.
+  if (SECKEY_GetPublicKeyType(result.get()) != rsaKey)
+    return nullptr;
+
+  return ScopedSECItem(PK11_MakeIDFromPubKey(&result->u.rsa.modulus));
+}
+
+#endif  // defined(USE_NSS_CERTS)
+
+}  // namespace
+
+bool GenerateRSAKeyPairNSS(PK11SlotInfo* slot,
+                           uint16_t num_bits,
+                           bool permanent,
+                           ScopedSECKEYPublicKey* public_key,
+                           ScopedSECKEYPrivateKey* private_key) {
+  DCHECK(slot);
+
+  PK11RSAGenParams param;
+  param.keySizeInBits = num_bits;
+  param.pe = 65537L;
+  SECKEYPublicKey* public_key_raw = nullptr;
+  private_key->reset(PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
+                                          &param, &public_key_raw, permanent,
+                                          permanent /* sensitive */, nullptr));
+  if (!*private_key)
+    return false;
+
+  public_key->reset(public_key_raw);
+  return true;
+}
+
+ScopedSECKEYPrivateKey ImportNSSKeyFromPrivateKeyInfo(
+    PK11SlotInfo* slot,
+    const std::vector<uint8_t>& input,
+    bool permanent) {
+  DCHECK(slot);
+
+  ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+  DCHECK(arena);
+
+  // Excess data is illegal, but NSS silently accepts it, so first ensure that
+  // |input| consists of a single ASN.1 element.
+  SECItem input_item;
+  input_item.data = const_cast<unsigned char*>(input.data());
+  input_item.len = input.size();
+  SECItem der_private_key_info;
+  SECStatus rv =
+      SEC_QuickDERDecodeItem(arena.get(), &der_private_key_info,
+                             SEC_ASN1_GET(SEC_AnyTemplate), &input_item);
+  if (rv != SECSuccess)
+    return nullptr;
+
+  // Allow the private key to be used for key unwrapping, data decryption,
+  // and signature generation.
+  const unsigned int key_usage =
+      KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
+  SECKEYPrivateKey* key_raw = nullptr;
+  rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
+      slot, &der_private_key_info, nullptr, nullptr, permanent,
+      permanent /* sensitive */, key_usage, &key_raw, nullptr);
+  if (rv != SECSuccess)
+    return nullptr;
+  return ScopedSECKEYPrivateKey(key_raw);
+}
+
+#if defined(USE_NSS_CERTS)
+
+ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfo(
+    const std::vector<uint8_t>& input) {
+  EnsureNSSInit();
+
+  ScopedSECItem cka_id(MakeIDFromSPKI(input));
+  if (!cka_id)
+    return nullptr;
+
+  // Search all slots in all modules for the key with the given ID.
+  AutoSECMODListReadLock auto_lock;
+  const SECMODModuleList* head = SECMOD_GetDefaultModuleList();
+  for (const SECMODModuleList* item = head; item != nullptr;
+       item = item->next) {
+    int slot_count = item->module->loaded ? item->module->slotCount : 0;
+    for (int i = 0; i < slot_count; i++) {
+      // Look for the key in slot |i|.
+      ScopedSECKEYPrivateKey key(
+          PK11_FindKeyByKeyID(item->module->slots[i], cka_id.get(), nullptr));
+      if (key)
+        return key;
+    }
+  }
+
+  // The key wasn't found in any module.
+  return nullptr;
+}
+
+ScopedSECKEYPrivateKey FindNSSKeyFromPublicKeyInfoInSlot(
+    const std::vector<uint8_t>& input,
+    PK11SlotInfo* slot) {
+  DCHECK(slot);
+
+  ScopedSECItem cka_id(MakeIDFromSPKI(input));
+  if (!cka_id)
+    return nullptr;
+
+  return ScopedSECKEYPrivateKey(
+      PK11_FindKeyByKeyID(slot, cka_id.get(), nullptr));
+}
+
+#endif  // defined(USE_NSS_CERTS)
+
+}  // namespace crypto
diff --git a/crypto/nss_key_util.h b/crypto/nss_key_util.h
new file mode 100644
index 0000000..9142609
--- /dev/null
+++ b/crypto/nss_key_util.h
@@ -0,0 +1,58 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_NSS_KEY_UTIL_H_
+#define CRYPTO_NSS_KEY_UTIL_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "build/build_config.h"
+#include "crypto/crypto_export.h"
+#include "crypto/scoped_nss_types.h"
+
+typedef struct PK11SlotInfoStr PK11SlotInfo;
+
+namespace crypto {
+
+// Generates a new RSA keypair of size |num_bits| in |slot|. Returns true on
+// success and false on failure. If |permanent| is true, the resulting key is
+// permanent and is not exportable in plaintext form.
+CRYPTO_EXPORT bool GenerateRSAKeyPairNSS(
+    PK11SlotInfo* slot,
+    uint16_t num_bits,
+    bool permanent,
+    ScopedSECKEYPublicKey* out_public_key,
+    ScopedSECKEYPrivateKey* out_private_key);
+
+// Imports a private key from |input| into |slot|. |input| is interpreted as a
+// DER-encoded PrivateKeyInfo block from PKCS #8. Returns nullptr on error. If
+// |permanent| is true, the resulting key is permanent and is not exportable in
+// plaintext form.
+CRYPTO_EXPORT ScopedSECKEYPrivateKey
+ImportNSSKeyFromPrivateKeyInfo(PK11SlotInfo* slot,
+                               const std::vector<uint8_t>& input,
+                               bool permanent);
+
+#if defined(USE_NSS_CERTS)
+
+// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for
+// the private key half in the key database. Returns the private key on success
+// or nullptr on error.
+CRYPTO_EXPORT ScopedSECKEYPrivateKey
+FindNSSKeyFromPublicKeyInfo(const std::vector<uint8_t>& input);
+
+// Decodes |input| as a DER-encoded X.509 SubjectPublicKeyInfo and searches for
+// the private key half in the slot specified by |slot|. Returns the private key
+// on success or nullptr on error.
+CRYPTO_EXPORT ScopedSECKEYPrivateKey
+FindNSSKeyFromPublicKeyInfoInSlot(const std::vector<uint8_t>& input,
+                                  PK11SlotInfo* slot);
+
+#endif  // defined(USE_NSS_CERTS)
+
+}  // namespace crypto
+
+#endif  // CRYPTO_NSS_KEY_UTIL_H_
diff --git a/crypto/nss_key_util_unittest.cc b/crypto/nss_key_util_unittest.cc
new file mode 100644
index 0000000..c507900
--- /dev/null
+++ b/crypto/nss_key_util_unittest.cc
@@ -0,0 +1,88 @@
+// Copyright 2015 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/nss_key_util.h"
+
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <stdint.h>
+
+#include <vector>
+
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace crypto {
+
+class NSSKeyUtilTest : public testing::Test {
+ public:
+  void SetUp() override {
+    EnsureNSSInit();
+
+    internal_slot_.reset(PK11_GetInternalSlot());
+    ASSERT_TRUE(internal_slot_);
+  }
+
+  PK11SlotInfo* internal_slot() { return internal_slot_.get(); }
+
+ private:
+  ScopedPK11Slot internal_slot_;
+};
+
+TEST_F(NSSKeyUtilTest, GenerateRSAKeyPairNSS) {
+  const int kKeySizeBits = 1024;
+
+  ScopedSECKEYPublicKey public_key;
+  ScopedSECKEYPrivateKey private_key;
+  ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), kKeySizeBits,
+                                    false /* not permanent */, &public_key,
+                                    &private_key));
+
+  EXPECT_EQ(rsaKey, SECKEY_GetPublicKeyType(public_key.get()));
+  EXPECT_EQ(rsaKey, SECKEY_GetPrivateKeyType(private_key.get()));
+  EXPECT_EQ((kKeySizeBits + 7) / 8,
+            PK11_GetPrivateModulusLen(private_key.get()));
+}
+
+#if defined(USE_NSS_CERTS)
+TEST_F(NSSKeyUtilTest, FindNSSKeyFromPublicKeyInfo) {
+  // Create an NSS keypair, which will put the keys in the user's NSSDB.
+  ScopedSECKEYPublicKey public_key;
+  ScopedSECKEYPrivateKey private_key;
+  ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 512,
+                                    false /* not permanent */, &public_key,
+                                    &private_key));
+
+  ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get()));
+  ASSERT_TRUE(item);
+  std::vector<uint8_t> public_key_der(item->data, item->data + item->len);
+
+  ScopedSECKEYPrivateKey private_key2 =
+      FindNSSKeyFromPublicKeyInfo(public_key_der);
+  ASSERT_TRUE(private_key2);
+  EXPECT_EQ(private_key->pkcs11ID, private_key2->pkcs11ID);
+}
+
+TEST_F(NSSKeyUtilTest, FailedFindNSSKeyFromPublicKeyInfo) {
+  // Create an NSS keypair, which will put the keys in the user's NSSDB.
+  ScopedSECKEYPublicKey public_key;
+  ScopedSECKEYPrivateKey private_key;
+  ASSERT_TRUE(GenerateRSAKeyPairNSS(internal_slot(), 512,
+                                    false /* not permanent */, &public_key,
+                                    &private_key));
+
+  ScopedSECItem item(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key.get()));
+  ASSERT_TRUE(item);
+  std::vector<uint8_t> public_key_der(item->data, item->data + item->len);
+
+  // Remove the keys from the DB, and make sure we can't find them again.
+  PK11_DestroyTokenObject(private_key->pkcs11Slot, private_key->pkcs11ID);
+  PK11_DestroyTokenObject(public_key->pkcs11Slot, public_key->pkcs11ID);
+
+  EXPECT_FALSE(FindNSSKeyFromPublicKeyInfo(public_key_der));
+}
+#endif  // defined(USE_NSS_CERTS)
+
+}  // namespace crypto
diff --git a/crypto/nss_util.cc b/crypto/nss_util.cc
new file mode 100644
index 0000000..d38036c
--- /dev/null
+++ b/crypto/nss_util.cc
@@ -0,0 +1,1033 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/nss_util.h"
+
+#include <nss.h>
+#include <pk11pub.h>
+#include <plarena.h>
+#include <prerror.h>
+#include <prinit.h>
+#include <prtime.h>
+#include <secmod.h>
+
+#include <memory>
+#include <utility>
+
+#include "crypto/nss_util_internal.h"
+
+#if defined(OS_OPENBSD)
+#include <sys/mount.h>
+#include <sys/param.h>
+#endif
+
+#if defined(OS_CHROMEOS)
+#include <dlfcn.h>
+#endif
+
+#include <map>
+#include <vector>
+
+#include "base/functional/bind.h"
+#include "base/cpu.h"
+#include "base/debug/alias.h"
+#include "base/debug/stack_trace.h"
+#include "base/environment.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/native_library.h"
+#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/task/single_thread_task_executor.h"
+#include "base/task/single_thread_task_runner.h"
+#include "base/task/thread_pool.h"
+#include "base/threading/scoped_blocking_call.h"
+#include "base/threading/thread_checker.h"
+#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
+
+#if !defined(OS_CHROMEOS)
+#include "base/base_paths.h"
+#include "base/path_service.h"
+#endif
+
+// USE_NSS_CERTS means NSS is used for certificates and platform integration.
+// This requires additional support to manage the platform certificate and key
+// stores.
+#if defined(USE_NSS_CERTS)
+#include "base/synchronization/lock.h"
+#include "crypto/nss_crypto_module_delegate.h"
+#endif  // defined(USE_NSS_CERTS)
+
+namespace crypto {
+
+namespace {
+
+#if defined(OS_CHROMEOS)
+const char kUserNSSDatabaseName[] = "UserNSSDB";
+
+// Constants for loading the Chrome OS TPM-backed PKCS #11 library.
+const char kChapsModuleName[] = "Chaps";
+const char kChapsPath[] = "libchaps.so";
+
+// Fake certificate authority database used for testing.
+static const base::FilePath::CharType kReadOnlyCertDB[] =
+    FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb");
+#endif  // defined(OS_CHROMEOS)
+
+std::string GetNSSErrorMessage() {
+  std::string result;
+  if (PR_GetErrorTextLength()) {
+    std::unique_ptr<char[]> error_text(new char[PR_GetErrorTextLength() + 1]);
+    PRInt32 copied = PR_GetErrorText(error_text.get());
+    result = std::string(error_text.get(), copied);
+  } else {
+    result = base::StringPrintf("NSS error code: %d", PR_GetError());
+  }
+  return result;
+}
+
+#if defined(USE_NSS_CERTS)
+#if !defined(OS_CHROMEOS)
+base::FilePath GetDefaultConfigDirectory() {
+  base::FilePath dir;
+  PathService::Get(base::DIR_HOME, &dir);
+  if (dir.empty()) {
+    LOG(ERROR) << "Failed to get home directory.";
+    return dir;
+  }
+  dir = dir.AppendASCII(".pki").AppendASCII("nssdb");
+  if (!base::CreateDirectory(dir)) {
+    LOG(ERROR) << "Failed to create " << dir.value() << " directory.";
+    dir.clear();
+  }
+  DVLOG(2) << "DefaultConfigDirectory: " << dir.value();
+  return dir;
+}
+#endif  // !defined(OS_CHROMEOS)
+
+// On non-Chrome OS platforms, return the default config directory. On Chrome OS
+// test images, return a read-only directory with fake root CA certs (which are
+// used by the local Google Accounts server mock we use when testing our login
+// code). On Chrome OS non-test images (where the read-only directory doesn't
+// exist), return an empty path.
+base::FilePath GetInitialConfigDirectory() {
+#if defined(OS_CHROMEOS)
+  base::FilePath database_dir = base::FilePath(kReadOnlyCertDB);
+  if (!base::PathExists(database_dir))
+    database_dir.clear();
+  return database_dir;
+#else
+  return GetDefaultConfigDirectory();
+#endif  // defined(OS_CHROMEOS)
+}
+
+// This callback for NSS forwards all requests to a caller-specified
+// CryptoModuleBlockingPasswordDelegate object.
+char* PKCS11PasswordFunc(PK11SlotInfo* slot, PRBool retry, void* arg) {
+  crypto::CryptoModuleBlockingPasswordDelegate* delegate =
+      reinterpret_cast<crypto::CryptoModuleBlockingPasswordDelegate*>(arg);
+  if (delegate) {
+    bool cancelled = false;
+    std::string password = delegate->RequestPassword(PK11_GetTokenName(slot),
+                                                     retry != PR_FALSE,
+                                                     &cancelled);
+    if (cancelled)
+      return NULL;
+    char* result = PORT_Strdup(password.c_str());
+    password.replace(0, password.size(), password.size(), 0);
+    return result;
+  }
+  DLOG(ERROR) << "PK11 password requested with NULL arg";
+  return NULL;
+}
+
+// NSS creates a local cache of the sqlite database if it detects that the
+// filesystem the database is on is much slower than the local disk.  The
+// detection doesn't work with the latest versions of sqlite, such as 3.6.22
+// (NSS bug https://bugzilla.mozilla.org/show_bug.cgi?id=578561).  So we set
+// the NSS environment variable NSS_SDB_USE_CACHE to "yes" to override NSS's
+// detection when database_dir is on NFS.  See http://crbug.com/48585.
+//
+// TODO(wtc): port this function to other USE_NSS_CERTS platforms.  It is
+// defined only for OS_LINUX and OS_OPENBSD simply because the statfs structure
+// is OS-specific.
+//
+// Because this function sets an environment variable it must be run before we
+// go multi-threaded.
+void UseLocalCacheOfNSSDatabaseIfNFS(const base::FilePath& database_dir) {
+  bool db_on_nfs = false;
+#if defined(OS_LINUX)
+  base::FileSystemType fs_type = base::FILE_SYSTEM_UNKNOWN;
+  if (base::GetFileSystemType(database_dir, &fs_type))
+    db_on_nfs = (fs_type == base::FILE_SYSTEM_NFS);
+#elif defined(OS_OPENBSD)
+  struct statfs buf;
+  if (statfs(database_dir.value().c_str(), &buf) == 0)
+    db_on_nfs = (strcmp(buf.f_fstypename, MOUNT_NFS) == 0);
+#else
+  NOTIMPLEMENTED();
+#endif
+
+  if (db_on_nfs) {
+    std::unique_ptr<base::Environment> env(base::Environment::Create());
+    static const char kUseCacheEnvVar[] = "NSS_SDB_USE_CACHE";
+    if (!env->HasVar(kUseCacheEnvVar))
+      env->SetVar(kUseCacheEnvVar, "yes");
+  }
+}
+
+#endif  // defined(USE_NSS_CERTS)
+
+// A singleton to initialize/deinitialize NSPR.
+// Separate from the NSS singleton because we initialize NSPR on the UI thread.
+// Now that we're leaking the singleton, we could merge back with the NSS
+// singleton.
+class NSPRInitSingleton {
+ private:
+ friend struct base::LazyInstanceTraitsBase<NSPRInitSingleton>;
+
+  NSPRInitSingleton() {
+    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+  }
+
+  // NOTE(willchan): We don't actually execute this code since we leak NSS to
+  // prevent non-joinable threads from using NSS after it's already been shut
+  // down.
+  ~NSPRInitSingleton() {
+    PL_ArenaFinish();
+    PRStatus prstatus = PR_Cleanup();
+    if (prstatus != PR_SUCCESS)
+      LOG(ERROR) << "PR_Cleanup failed; was NSPR initialized on wrong thread?";
+  }
+};
+
+base::LazyInstance<NSPRInitSingleton>::Leaky
+    g_nspr_singleton = LAZY_INSTANCE_INITIALIZER;
+
+// Force a crash with error info on NSS_NoDB_Init failure.
+void CrashOnNSSInitFailure() {
+  int nss_error = PR_GetError();
+  int os_error = PR_GetOSError();
+  base::debug::Alias(&nss_error);
+  base::debug::Alias(&os_error);
+  LOG(ERROR) << "Error initializing NSS without a persistent database: "
+             << GetNSSErrorMessage();
+  LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error;
+}
+
+#if defined(OS_CHROMEOS)
+class ChromeOSUserData {
+ public:
+  using SlotReadyCallback = base::OnceCallback<void(ScopedPK11Slot)>;
+  explicit ChromeOSUserData(ScopedPK11Slot public_slot)
+      : public_slot_(std::move(public_slot)) {}
+  ~ChromeOSUserData() {
+    if (public_slot_) {
+      SECStatus status = SECMOD_CloseUserDB(public_slot_.get());
+      if (status != SECSuccess)
+        PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
+    }
+  }
+
+  ScopedPK11Slot GetPublicSlot() {
+    return ScopedPK11Slot(
+        public_slot_ ? PK11_ReferenceSlot(public_slot_.get()) : NULL);
+  }
+
+  ScopedPK11Slot GetPrivateSlot(SlotReadyCallback callback) {
+    if (private_slot_)
+      return ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get()));
+    if (!callback.is_null())
+      tpm_ready_callback_list_.push_back(std::move(callback));
+    return ScopedPK11Slot();
+  }
+
+  void SetPrivateSlot(ScopedPK11Slot private_slot) {
+    DCHECK(!private_slot_);
+    private_slot_ = std::move(private_slot);
+
+    SlotReadyCallbackList callback_list;
+    callback_list.swap(tpm_ready_callback_list_);
+    for (SlotReadyCallbackList::iterator i = callback_list.begin();
+         i != callback_list.end();
+         ++i) {
+      std::move(*i).Run(ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get())));
+    }
+  }
+
+  bool private_slot_initialization_started() const {
+      return private_slot_initialization_started_;
+  }
+
+  void set_private_slot_initialization_started() {
+      private_slot_initialization_started_ = true;
+  }
+
+ private:
+  using SlotReadyCallbackList =
+      std::vector<base::OnceCallback<void(ScopedPK11Slot)>>;
+
+  ScopedPK11Slot public_slot_;
+  ScopedPK11Slot private_slot_;
+
+  bool private_slot_initialization_started_ = false;
+
+  SlotReadyCallbackList tpm_ready_callback_list_;
+};
+
+class ScopedChapsLoadFixup {
+  public:
+    ScopedChapsLoadFixup();
+    ~ScopedChapsLoadFixup();
+
+  private:
+#if defined(COMPONENT_BUILD)
+    void *chaps_handle_;
+#endif
+};
+
+#if defined(COMPONENT_BUILD)
+
+ScopedChapsLoadFixup::ScopedChapsLoadFixup() {
+  // HACK: libchaps links the system protobuf and there are symbol conflicts
+  // with the bundled copy. Load chaps with RTLD_DEEPBIND to workaround.
+  chaps_handle_ = dlopen(kChapsPath, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND);
+}
+
+ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {
+  // LoadModule() will have taken a 2nd reference.
+  if (chaps_handle_)
+    dlclose(chaps_handle_);
+}
+
+#else
+
+ScopedChapsLoadFixup::ScopedChapsLoadFixup() {}
+ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {}
+
+#endif  // defined(COMPONENT_BUILD)
+#endif  // defined(OS_CHROMEOS)
+
+class NSSInitSingleton {
+ public:
+#if defined(OS_CHROMEOS)
+  // Used with PostTaskAndReply to pass handles to worker thread and back.
+  struct TPMModuleAndSlot {
+    explicit TPMModuleAndSlot(SECMODModule* init_chaps_module)
+        : chaps_module(init_chaps_module) {}
+    SECMODModule* chaps_module;
+    crypto::ScopedPK11Slot tpm_slot;
+  };
+
+  ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name,
+                                            const base::FilePath& path) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    // NSS is allowed to do IO on the current thread since dispatching
+    // to a dedicated thread would still have the affect of blocking
+    // the current thread, due to NSS's internal locking requirements
+    ScopedAllowBlockingForNSS allow_blocking;
+
+    base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb");
+    if (!base::CreateDirectory(nssdb_path)) {
+      LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory.";
+      return ScopedPK11Slot();
+    }
+    return OpenSoftwareNSSDB(nssdb_path, db_name);
+  }
+
+  void EnableTPMTokenForNSS() {
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    // If this gets set, then we'll use the TPM for certs with
+    // private keys, otherwise we'll fall back to the software
+    // implementation.
+    tpm_token_enabled_for_nss_ = true;
+  }
+
+  bool IsTPMTokenEnabledForNSS() {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    return tpm_token_enabled_for_nss_;
+  }
+
+  void InitializeTPMTokenAndSystemSlot(
+      int system_slot_id,
+      base::OnceCallback<void(bool)> callback) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    // Should not be called while there is already an initialization in
+    // progress.
+    DCHECK(!initializing_tpm_token_);
+    // If EnableTPMTokenForNSS hasn't been called, return false.
+    if (!tpm_token_enabled_for_nss_) {
+      base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), false));
+      return;
+    }
+
+    // If everything is already initialized, then return true.
+    // Note that only |tpm_slot_| is checked, since |chaps_module_| could be
+    // NULL in tests while |tpm_slot_| has been set to the test DB.
+    if (tpm_slot_) {
+      base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+          FROM_HERE, base::BindOnce(std::move(callback), true));
+      return;
+    }
+
+    // Note that a reference is not taken to chaps_module_. This is safe since
+    // NSSInitSingleton is Leaky, so the reference it holds is never released.
+    std::unique_ptr<TPMModuleAndSlot> tpm_args(
+        new TPMModuleAndSlot(chaps_module_));
+    TPMModuleAndSlot* tpm_args_ptr = tpm_args.get();
+    base::ThreadPool::PostTaskAndReply(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::BindOnce(&NSSInitSingleton::InitializeTPMTokenInThreadPool,
+                       system_slot_id, tpm_args_ptr),
+        base::BindOnce(&NSSInitSingleton::OnInitializedTPMTokenAndSystemSlot,
+                       base::Unretained(this),  // NSSInitSingleton is leaky
+                       std::move(callback), std::move(tpm_args)));
+    initializing_tpm_token_ = true;
+  }
+
+  static void InitializeTPMTokenInThreadPool(CK_SLOT_ID token_slot_id,
+                                             TPMModuleAndSlot* tpm_args) {
+    // NSS functions may reenter //net via extension hooks. If the reentered
+    // code needs to synchronously wait for a task to run but the thread pool in
+    // which that task must run doesn't have enough threads to schedule it, a
+    // deadlock occurs. To prevent that, the base::ScopedBlockingCall below
+    // increments the thread pool capacity for the duration of the TPM
+    // initialization.
+    base::ScopedBlockingCall scoped_blocking_call(
+        FROM_HERE, base::BlockingType::WILL_BLOCK);
+
+    if (!tpm_args->chaps_module) {
+      ScopedChapsLoadFixup chaps_loader;
+
+      DVLOG(3) << "Loading chaps...";
+      tpm_args->chaps_module = LoadModule(
+          kChapsModuleName,
+          kChapsPath,
+          // For more details on these parameters, see:
+          // https://developer.mozilla.org/en/PKCS11_Module_Specs
+          // slotFlags=[PublicCerts] -- Certificates and public keys can be
+          //   read from this slot without requiring a call to C_Login.
+          // askpw=only -- Only authenticate to the token when necessary.
+          "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\"");
+    }
+    if (tpm_args->chaps_module) {
+      tpm_args->tpm_slot =
+          GetTPMSlotForIdInThreadPool(tpm_args->chaps_module, token_slot_id);
+    }
+  }
+
+  void OnInitializedTPMTokenAndSystemSlot(
+      base::OnceCallback<void(bool)> callback,
+      std::unique_ptr<TPMModuleAndSlot> tpm_args) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module
+             << ", got tpm slot: " << !!tpm_args->tpm_slot;
+
+    chaps_module_ = tpm_args->chaps_module;
+    tpm_slot_ = std::move(tpm_args->tpm_slot);
+    if (!chaps_module_ && test_system_slot_) {
+      // chromeos_unittests try to test the TPM initialization process. If we
+      // have a test DB open, pretend that it is the TPM slot.
+      tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get()));
+    }
+    initializing_tpm_token_ = false;
+
+    if (tpm_slot_)
+      RunAndClearTPMReadyCallbackList();
+
+    std::move(callback).Run(!!tpm_slot_);
+  }
+
+  void RunAndClearTPMReadyCallbackList() {
+    TPMReadyCallbackList callback_list;
+    callback_list.swap(tpm_ready_callback_list_);
+    for (TPMReadyCallbackList::iterator i = callback_list.begin();
+         i != callback_list.end();
+         ++i) {
+      std::move(*i).Run();
+    }
+  }
+
+  bool IsTPMTokenReady(base::OnceClosure callback) {
+    if (!callback.is_null()) {
+      // Cannot DCHECK in the general case yet, but since the callback is
+      // a new addition to the API, DCHECK to make sure at least the new uses
+      // don't regress.
+      DCHECK(thread_checker_.CalledOnValidThread());
+    } else if (!thread_checker_.CalledOnValidThread()) {
+      // TODO(mattm): Change to DCHECK when callers have been fixed.
+      DVLOG(1) << "Called on wrong thread.\n"
+               << base::debug::StackTrace().ToString();
+    }
+
+    if (tpm_slot_)
+      return true;
+
+    if (!callback.is_null())
+      tpm_ready_callback_list_.push_back(std::move(callback));
+
+    return false;
+  }
+
+  // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot
+  // id as an int. This should be safe since this is only used with chaps, which
+  // we also control.
+  static crypto::ScopedPK11Slot GetTPMSlotForIdInThreadPool(
+      SECMODModule* chaps_module,
+      CK_SLOT_ID slot_id) {
+    DCHECK(chaps_module);
+
+    DVLOG(3) << "Poking chaps module.";
+    SECStatus rv = SECMOD_UpdateSlotList(chaps_module);
+    if (rv != SECSuccess)
+      PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError();
+
+    PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module->moduleID, slot_id);
+    if (!slot)
+      LOG(ERROR) << "TPM slot " << slot_id << " not found.";
+    return crypto::ScopedPK11Slot(slot);
+  }
+
+  bool InitializeNSSForChromeOSUser(const std::string& username_hash,
+                                    const base::FilePath& path) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) {
+      // This user already exists in our mapping.
+      DVLOG(2) << username_hash << " already initialized.";
+      return false;
+    }
+
+    DVLOG(2) << "Opening NSS DB " << path.value();
+    std::string db_name = base::StringPrintf(
+        "%s %s", kUserNSSDatabaseName, username_hash.c_str());
+    ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path));
+    chromeos_user_map_[username_hash] =
+        std::make_unique<ChromeOSUserData>(std::move(public_slot));
+    return true;
+  }
+
+  bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+
+    return !chromeos_user_map_[username_hash]
+                ->private_slot_initialization_started();
+  }
+
+  void WillInitializeTPMForChromeOSUser(const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+
+    chromeos_user_map_[username_hash]
+        ->set_private_slot_initialization_started();
+  }
+
+  void InitializeTPMForChromeOSUser(const std::string& username_hash,
+                                    CK_SLOT_ID slot_id) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+    DCHECK(chromeos_user_map_[username_hash]->
+               private_slot_initialization_started());
+
+    if (!chaps_module_)
+      return;
+
+    // Note that a reference is not taken to chaps_module_. This is safe since
+    // NSSInitSingleton is Leaky, so the reference it holds is never released.
+    std::unique_ptr<TPMModuleAndSlot> tpm_args(
+        new TPMModuleAndSlot(chaps_module_));
+    TPMModuleAndSlot* tpm_args_ptr = tpm_args.get();
+    base::ThreadPool::PostTaskAndReply(
+        FROM_HERE,
+        {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::BindOnce(&NSSInitSingleton::InitializeTPMTokenInThreadPool,
+                       slot_id, tpm_args_ptr),
+        base::BindOnce(&NSSInitSingleton::OnInitializedTPMForChromeOSUser,
+                       base::Unretained(this),  // NSSInitSingleton is leaky
+                       username_hash, std::move(tpm_args)));
+  }
+
+  void OnInitializedTPMForChromeOSUser(
+      const std::string& username_hash,
+      std::unique_ptr<TPMModuleAndSlot> tpm_args) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    DVLOG(2) << "Got tpm slot for " << username_hash << " "
+             << !!tpm_args->tpm_slot;
+    chromeos_user_map_[username_hash]->SetPrivateSlot(
+        std::move(tpm_args->tpm_slot));
+  }
+
+  void InitializePrivateSoftwareSlotForChromeOSUser(
+      const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    VLOG(1) << "using software private slot for " << username_hash;
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+    DCHECK(chromeos_user_map_[username_hash]->
+               private_slot_initialization_started());
+
+    chromeos_user_map_[username_hash]->SetPrivateSlot(
+        chromeos_user_map_[username_hash]->GetPublicSlot());
+  }
+
+  ScopedPK11Slot GetPublicSlotForChromeOSUser(
+      const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    if (username_hash.empty()) {
+      DVLOG(2) << "empty username_hash";
+      return ScopedPK11Slot();
+    }
+
+    if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) {
+      LOG(ERROR) << username_hash << " not initialized.";
+      return ScopedPK11Slot();
+    }
+    return chromeos_user_map_[username_hash]->GetPublicSlot();
+  }
+
+  ScopedPK11Slot GetPrivateSlotForChromeOSUser(
+      const std::string& username_hash,
+      base::OnceCallback<void(ScopedPK11Slot)> callback) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    if (username_hash.empty()) {
+      DVLOG(2) << "empty username_hash";
+      if (!callback.is_null()) {
+        base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
+            FROM_HERE, base::BindOnce(std::move(callback), ScopedPK11Slot()));
+      }
+      return ScopedPK11Slot();
+    }
+
+    DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
+
+    return chromeos_user_map_[username_hash]->GetPrivateSlot(
+        std::move(callback));
+  }
+
+  void CloseChromeOSUserForTesting(const std::string& username_hash) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    ChromeOSUserMap::iterator i = chromeos_user_map_.find(username_hash);
+    DCHECK(i != chromeos_user_map_.end());
+    chromeos_user_map_.erase(i);
+  }
+
+  void SetSystemKeySlotForTesting(ScopedPK11Slot slot) {
+    // Ensure that a previous value of test_system_slot_ is not overwritten.
+    // Unsetting, i.e. setting a NULL, however is allowed.
+    DCHECK(!slot || !test_system_slot_);
+    test_system_slot_ = std::move(slot);
+    if (test_system_slot_) {
+      tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get()));
+      RunAndClearTPMReadyCallbackList();
+    } else {
+      tpm_slot_.reset();
+    }
+  }
+#endif  // defined(OS_CHROMEOS)
+
+#if !defined(OS_CHROMEOS)
+  PK11SlotInfo* GetPersistentNSSKeySlot() {
+    // TODO(mattm): Change to DCHECK when callers have been fixed.
+    if (!thread_checker_.CalledOnValidThread()) {
+      DVLOG(1) << "Called on wrong thread.\n"
+               << base::debug::StackTrace().ToString();
+    }
+
+    return PK11_GetInternalKeySlot();
+  }
+#endif
+
+#if defined(OS_CHROMEOS)
+  void GetSystemNSSKeySlotCallback(
+      base::OnceCallback<void(ScopedPK11Slot)> callback) {
+    std::move(callback).Run(
+        ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get())));
+  }
+
+  ScopedPK11Slot GetSystemNSSKeySlot(
+      base::OnceCallback<void(ScopedPK11Slot)> callback) {
+    DCHECK(thread_checker_.CalledOnValidThread());
+    // TODO(mattm): chromeos::TPMTokenloader always calls
+    // InitializeTPMTokenAndSystemSlot with slot 0.  If the system slot is
+    // disabled, tpm_slot_ will be the first user's slot instead. Can that be
+    // detected and return NULL instead?
+
+    base::OnceClosure wrapped_callback;
+    if (!callback.is_null()) {
+      wrapped_callback = base::BindOnce(
+          &NSSInitSingleton::GetSystemNSSKeySlotCallback,
+          base::Unretained(this) /* singleton is leaky */, std::move(callback));
+    }
+    if (IsTPMTokenReady(std::move(wrapped_callback)))
+      return ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get()));
+    return ScopedPK11Slot();
+  }
+#endif
+
+#if defined(USE_NSS_CERTS)
+  base::Lock* write_lock() {
+    return &write_lock_;
+  }
+#endif  // defined(USE_NSS_CERTS)
+
+ private:
+  friend struct base::LazyInstanceTraitsBase<NSSInitSingleton>;
+
+  NSSInitSingleton()
+      : tpm_token_enabled_for_nss_(false),
+        initializing_tpm_token_(false),
+        chaps_module_(NULL),
+        root_(NULL) {
+    // It's safe to construct on any thread, since LazyInstance will prevent any
+    // other threads from accessing until the constructor is done.
+    thread_checker_.DetachFromThread();
+
+    EnsureNSPRInit();
+
+    // We *must* have NSS >= 3.14.3.
+    static_assert(
+        (NSS_VMAJOR == 3 && NSS_VMINOR == 14 && NSS_VPATCH >= 3) ||
+        (NSS_VMAJOR == 3 && NSS_VMINOR > 14) ||
+        (NSS_VMAJOR > 3),
+        "nss version check failed");
+    // Also check the run-time NSS version.
+    // NSS_VersionCheck is a >= check, not strict equality.
+    if (!NSS_VersionCheck("3.14.3")) {
+      LOG(FATAL) << "NSS_VersionCheck(\"3.14.3\") failed. NSS >= 3.14.3 is "
+                    "required. Please upgrade to the latest NSS, and if you "
+                    "still get this error, contact your distribution "
+                    "maintainer.";
+    }
+
+    SECStatus status = SECFailure;
+    bool nodb_init = false;
+
+#if !defined(USE_NSS_CERTS)
+    // Use the system certificate store, so initialize NSS without database.
+    nodb_init = true;
+#endif
+
+    if (nodb_init) {
+      status = NSS_NoDB_Init(NULL);
+      if (status != SECSuccess) {
+        CrashOnNSSInitFailure();
+        return;
+      }
+#if defined(OS_IOS)
+      root_ = InitDefaultRootCerts();
+#endif  // defined(OS_IOS)
+    } else {
+#if defined(USE_NSS_CERTS)
+      base::FilePath database_dir = GetInitialConfigDirectory();
+      if (!database_dir.empty()) {
+        // This duplicates the work which should have been done in
+        // EarlySetupForNSSInit. However, this function is idempotent so
+        // there's no harm done.
+        UseLocalCacheOfNSSDatabaseIfNFS(database_dir);
+
+        // Initialize with a persistent database (likely, ~/.pki/nssdb).
+        // Use "sql:" which can be shared by multiple processes safely.
+        std::string nss_config_dir =
+            base::StringPrintf("sql:%s", database_dir.value().c_str());
+#if defined(OS_CHROMEOS)
+        status = NSS_Init(nss_config_dir.c_str());
+#else
+        status = NSS_InitReadWrite(nss_config_dir.c_str());
+#endif
+        if (status != SECSuccess) {
+          LOG(ERROR) << "Error initializing NSS with a persistent "
+                        "database (" << nss_config_dir
+                     << "): " << GetNSSErrorMessage();
+        }
+      }
+      if (status != SECSuccess) {
+        VLOG(1) << "Initializing NSS without a persistent database.";
+        status = NSS_NoDB_Init(NULL);
+        if (status != SECSuccess) {
+          CrashOnNSSInitFailure();
+          return;
+        }
+      }
+
+      PK11_SetPasswordFunc(PKCS11PasswordFunc);
+
+      // If we haven't initialized the password for the NSS databases,
+      // initialize an empty-string password so that we don't need to
+      // log in.
+      PK11SlotInfo* slot = PK11_GetInternalKeySlot();
+      if (slot) {
+        // PK11_InitPin may write to the keyDB, but no other thread can use NSS
+        // yet, so we don't need to lock.
+        if (PK11_NeedUserInit(slot))
+          PK11_InitPin(slot, NULL, NULL);
+        PK11_FreeSlot(slot);
+      }
+
+      root_ = InitDefaultRootCerts();
+#endif  // defined(USE_NSS_CERTS)
+    }
+
+    // Disable MD5 certificate signatures. (They are disabled by default in
+    // NSS 3.14.)
+    NSS_SetAlgorithmPolicy(SEC_OID_MD5, 0, NSS_USE_ALG_IN_CERT_SIGNATURE);
+    NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
+                           0, NSS_USE_ALG_IN_CERT_SIGNATURE);
+  }
+
+  // NOTE(willchan): We don't actually execute this code since we leak NSS to
+  // prevent non-joinable threads from using NSS after it's already been shut
+  // down.
+  ~NSSInitSingleton() {
+#if defined(OS_CHROMEOS)
+    chromeos_user_map_.clear();
+#endif
+    tpm_slot_.reset();
+    if (root_) {
+      SECMOD_UnloadUserModule(root_);
+      SECMOD_DestroyModule(root_);
+      root_ = NULL;
+    }
+    if (chaps_module_) {
+      SECMOD_UnloadUserModule(chaps_module_);
+      SECMOD_DestroyModule(chaps_module_);
+      chaps_module_ = NULL;
+    }
+
+    SECStatus status = NSS_Shutdown();
+    if (status != SECSuccess) {
+      // We VLOG(1) because this failure is relatively harmless (leaking, but
+      // we're shutting down anyway).
+      VLOG(1) << "NSS_Shutdown failed; see http://crbug.com/4609";
+    }
+  }
+
+  // Load nss's built-in root certs.
+  SECMODModule* InitDefaultRootCerts() {
+    SECMODModule* root = LoadModule("Root Certs", "libnssckbi.so", NULL);
+    if (root)
+      return root;
+
+    // Aw, snap.  Can't find/load root cert shared library.
+    // This will make it hard to talk to anybody via https.
+    // TODO(mattm): Re-add the NOTREACHED here when crbug.com/310972 is fixed.
+    return NULL;
+  }
+
+  // Load the given module for this NSS session.
+  static SECMODModule* LoadModule(const char* name,
+                                  const char* library_path,
+                                  const char* params) {
+    std::string modparams = base::StringPrintf(
+        "name=\"%s\" library=\"%s\" %s",
+        name, library_path, params ? params : "");
+
+    // Shouldn't need to const_cast here, but SECMOD doesn't properly
+    // declare input string arguments as const.  Bug
+    // https://bugzilla.mozilla.org/show_bug.cgi?id=642546 was filed
+    // on NSS codebase to address this.
+    SECMODModule* module = SECMOD_LoadUserModule(
+        const_cast<char*>(modparams.c_str()), NULL, PR_FALSE);
+    if (!module) {
+      LOG(ERROR) << "Error loading " << name << " module into NSS: "
+                 << GetNSSErrorMessage();
+      return NULL;
+    }
+    if (!module->loaded) {
+      LOG(ERROR) << "After loading " << name << ", loaded==false: "
+                 << GetNSSErrorMessage();
+      SECMOD_DestroyModule(module);
+      return NULL;
+    }
+    return module;
+  }
+
+  bool tpm_token_enabled_for_nss_;
+  bool initializing_tpm_token_;
+  typedef std::vector<base::OnceClosure> TPMReadyCallbackList;
+  TPMReadyCallbackList tpm_ready_callback_list_;
+  SECMODModule* chaps_module_;
+  crypto::ScopedPK11Slot tpm_slot_;
+  SECMODModule* root_;
+#if defined(OS_CHROMEOS)
+  typedef std::map<std::string, std::unique_ptr<ChromeOSUserData>> ChromeOSUserMap;
+  ChromeOSUserMap chromeos_user_map_;
+  ScopedPK11Slot test_system_slot_;
+#endif
+#if defined(USE_NSS_CERTS)
+  // TODO(davidben): When https://bugzilla.mozilla.org/show_bug.cgi?id=564011
+  // is fixed, we will no longer need the lock.
+  base::Lock write_lock_;
+#endif  // defined(USE_NSS_CERTS)
+
+  base::ThreadChecker thread_checker_;
+};
+
+base::LazyInstance<NSSInitSingleton>::Leaky
+    g_nss_singleton = LAZY_INSTANCE_INITIALIZER;
+}  // namespace
+
+#if defined(USE_NSS_CERTS)
+ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path,
+                                 const std::string& description) {
+  const std::string modspec =
+      base::StringPrintf("configDir='sql:%s' tokenDescription='%s'",
+                         path.value().c_str(),
+                         description.c_str());
+  PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str());
+  if (db_slot) {
+    if (PK11_NeedUserInit(db_slot))
+      PK11_InitPin(db_slot, NULL, NULL);
+  } else {
+    LOG(ERROR) << "Error opening persistent database (" << modspec
+               << "): " << GetNSSErrorMessage();
+  }
+  return ScopedPK11Slot(db_slot);
+}
+
+void EarlySetupForNSSInit() {
+  base::FilePath database_dir = GetInitialConfigDirectory();
+  if (!database_dir.empty())
+    UseLocalCacheOfNSSDatabaseIfNFS(database_dir);
+}
+#endif
+
+void EnsureNSPRInit() {
+  g_nspr_singleton.Get();
+}
+
+void EnsureNSSInit() {
+  // Initializing SSL causes us to do blocking IO.
+  // Temporarily allow it until we fix
+  //   http://code.google.com/p/chromium/issues/detail?id=59847
+  ScopedAllowBlockingForNSS allow_blocking;
+  g_nss_singleton.Get();
+}
+
+bool CheckNSSVersion(const char* version) {
+  return !!NSS_VersionCheck(version);
+}
+
+#if defined(USE_NSS_CERTS)
+base::Lock* GetNSSWriteLock() {
+  return g_nss_singleton.Get().write_lock();
+}
+
+AutoNSSWriteLock::AutoNSSWriteLock() : lock_(GetNSSWriteLock()) {
+  // May be NULL if the lock is not needed in our version of NSS.
+  if (lock_)
+    lock_->Acquire();
+}
+
+AutoNSSWriteLock::~AutoNSSWriteLock() {
+  if (lock_) {
+    lock_->AssertAcquired();
+    lock_->Release();
+  }
+}
+
+AutoSECMODListReadLock::AutoSECMODListReadLock()
+      : lock_(SECMOD_GetDefaultModuleListLock()) {
+    SECMOD_GetReadLock(lock_);
+  }
+
+AutoSECMODListReadLock::~AutoSECMODListReadLock() {
+  SECMOD_ReleaseReadLock(lock_);
+}
+#endif  // defined(USE_NSS_CERTS)
+
+#if defined(OS_CHROMEOS)
+ScopedPK11Slot GetSystemNSSKeySlot(
+    base::OnceCallback<void(ScopedPK11Slot)> callback) {
+  return g_nss_singleton.Get().GetSystemNSSKeySlot(std::move(callback));
+}
+
+void SetSystemKeySlotForTesting(ScopedPK11Slot slot) {
+  g_nss_singleton.Get().SetSystemKeySlotForTesting(std::move(slot));
+}
+
+void EnableTPMTokenForNSS() {
+  g_nss_singleton.Get().EnableTPMTokenForNSS();
+}
+
+bool IsTPMTokenEnabledForNSS() {
+  return g_nss_singleton.Get().IsTPMTokenEnabledForNSS();
+}
+
+bool IsTPMTokenReady(base::OnceClosure callback) {
+  return g_nss_singleton.Get().IsTPMTokenReady(std::move(callback));
+}
+
+void InitializeTPMTokenAndSystemSlot(
+    int token_slot_id, base::OnceCallback<void(bool)> callback) {
+  g_nss_singleton.Get().InitializeTPMTokenAndSystemSlot(token_slot_id,
+                                                        std::move(callback));
+}
+
+bool InitializeNSSForChromeOSUser(const std::string& username_hash,
+                                  const base::FilePath& path) {
+  return g_nss_singleton.Get().InitializeNSSForChromeOSUser(username_hash,
+                                                            path);
+}
+
+bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) {
+  return g_nss_singleton.Get().ShouldInitializeTPMForChromeOSUser(
+      username_hash);
+}
+
+void WillInitializeTPMForChromeOSUser(const std::string& username_hash) {
+  g_nss_singleton.Get().WillInitializeTPMForChromeOSUser(username_hash);
+}
+
+void InitializeTPMForChromeOSUser(
+    const std::string& username_hash,
+    CK_SLOT_ID slot_id) {
+  g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id);
+}
+
+void InitializePrivateSoftwareSlotForChromeOSUser(
+    const std::string& username_hash) {
+  g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser(
+      username_hash);
+}
+
+ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) {
+  return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash);
+}
+
+ScopedPK11Slot GetPrivateSlotForChromeOSUser(
+    const std::string& username_hash,
+    base::OnceCallback<void(ScopedPK11Slot)> callback) {
+  return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(
+      username_hash, std::move(callback));
+}
+
+void CloseChromeOSUserForTesting(const std::string& username_hash) {
+  g_nss_singleton.Get().CloseChromeOSUserForTesting(username_hash);
+}
+#endif  // defined(OS_CHROMEOS)
+
+base::Time PRTimeToBaseTime(PRTime prtime) {
+  return base::Time::FromInternalValue(
+      prtime + base::Time::UnixEpoch().ToInternalValue());
+}
+
+PRTime BaseTimeToPRTime(base::Time time) {
+  return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue();
+}
+
+#if !defined(OS_CHROMEOS)
+PK11SlotInfo* GetPersistentNSSKeySlot() {
+  return g_nss_singleton.Get().GetPersistentNSSKeySlot();
+}
+#endif
+
+}  // namespace crypto
diff --git a/crypto/nss_util.h b/crypto/nss_util.h
new file mode 100644
index 0000000..c2b5f36
--- /dev/null
+++ b/crypto/nss_util.h
@@ -0,0 +1,112 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_NSS_UTIL_H_
+#define CRYPTO_NSS_UTIL_H_
+
+#include <stdint.h>
+
+#include <string>
+#include "base/functional/callback.h"
+#include "base/threading/thread_restrictions.h"
+#include "crypto/crypto_export.h"
+
+namespace base {
+class FilePath;
+class Lock;
+class Time;
+}  // namespace base
+
+// This file specifically doesn't depend on any NSS or NSPR headers because it
+// is included by various (non-crypto) parts of chrome to call the
+// initialization functions.
+namespace crypto {
+
+class ScopedAllowBlockingForNSS : public base::ScopedAllowBlocking {};
+
+#if defined(USE_NSS_CERTS)
+// EarlySetupForNSSInit performs lightweight setup which must occur before the
+// process goes multithreaded. This does not initialise NSS. For test, see
+// EnsureNSSInit.
+CRYPTO_EXPORT void EarlySetupForNSSInit();
+#endif
+
+// Initialize NRPR if it isn't already initialized.  This function is
+// thread-safe, and NSPR will only ever be initialized once.
+CRYPTO_EXPORT void EnsureNSPRInit();
+
+// Initialize NSS if it isn't already initialized.  This must be called before
+// any other NSS functions.  This function is thread-safe, and NSS will only
+// ever be initialized once.
+CRYPTO_EXPORT void EnsureNSSInit();
+
+// Check if the current NSS version is greater than or equals to |version|.
+// A sample version string is "3.12.3".
+bool CheckNSSVersion(const char* version);
+
+#if defined(OS_CHROMEOS)
+// Indicates that NSS should use the Chaps library so that we
+// can access the TPM through NSS.  InitializeTPMTokenAndSystemSlot and
+// InitializeTPMForChromeOSUser must still be called to load the slots.
+CRYPTO_EXPORT void EnableTPMTokenForNSS();
+
+// Returns true if EnableTPMTokenForNSS has been called.
+CRYPTO_EXPORT bool IsTPMTokenEnabledForNSS();
+
+// Returns true if the TPM is owned and PKCS#11 initialized with the
+// user and security officer PINs, and has been enabled in NSS by
+// calling EnableTPMForNSS, and Chaps has been successfully
+// loaded into NSS.
+// If |callback| is non-null and the function returns false, the |callback| will
+// be run once the TPM is ready. |callback| will never be run if the function
+// returns true.
+[[nodiscard]] CRYPTO_EXPORT bool IsTPMTokenReady(base::OnceClosure callback)
+   ;
+
+// Initialize the TPM token and system slot. The |callback| will run on the same
+// thread with true if the token and slot were successfully loaded or were
+// already initialized. |callback| will be passed false if loading failed.  Once
+// called, InitializeTPMTokenAndSystemSlot must not be called again until the
+// |callback| has been run.
+CRYPTO_EXPORT void InitializeTPMTokenAndSystemSlot(
+    int system_slot_id,
+    const base::OnceCallback<void(bool)>& callback);
+#endif
+
+// Convert a NSS PRTime value into a base::Time object.
+// We use a int64_t instead of PRTime here to avoid depending on NSPR headers.
+CRYPTO_EXPORT base::Time PRTimeToBaseTime(int64_t prtime);
+
+// Convert a base::Time object into a PRTime value.
+// We use a int64_t instead of PRTime here to avoid depending on NSPR headers.
+CRYPTO_EXPORT int64_t BaseTimeToPRTime(base::Time time);
+
+#if defined(USE_NSS_CERTS)
+// NSS has a bug which can cause a deadlock or stall in some cases when writing
+// to the certDB and keyDB. It also has a bug which causes concurrent key pair
+// generations to scribble over each other. To work around this, we synchronize
+// writes to the NSS databases with a global lock. The lock is hidden beneath a
+// function for easy disabling when the bug is fixed. Callers should allow for
+// it to return NULL in the future.
+//
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=564011
+base::Lock* GetNSSWriteLock();
+
+// A helper class that acquires the NSS write Lock while the AutoNSSWriteLock
+// is in scope.
+class CRYPTO_EXPORT AutoNSSWriteLock {
+ public:
+  AutoNSSWriteLock();
+  AutoNSSWriteLock(const AutoNSSWriteLock&) = delete;
+  AutoNSSWriteLock& operator=(const AutoNSSWriteLock&) = delete;
+
+  ~AutoNSSWriteLock();
+ private:
+  base::Lock *lock_;
+};
+#endif  // defined(USE_NSS_CERTS)
+
+}  // namespace crypto
+
+#endif  // CRYPTO_NSS_UTIL_H_
diff --git a/crypto/nss_util_internal.h b/crypto/nss_util_internal.h
new file mode 100644
index 0000000..82dc060
--- /dev/null
+++ b/crypto/nss_util_internal.h
@@ -0,0 +1,113 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_NSS_UTIL_INTERNAL_H_
+#define CRYPTO_NSS_UTIL_INTERNAL_H_
+
+#include <secmodt.h>
+
+#include "base/functional/callback.h"
+#include "crypto/crypto_export.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace base {
+class FilePath;
+}
+
+// These functions return a type defined in an NSS header, and so cannot be
+// declared in nss_util.h.  Hence, they are declared here.
+
+namespace crypto {
+
+// Opens an NSS software database in folder |path|, with the (potentially)
+// user-visible description |description|. Returns the slot for the opened
+// database, or NULL if the database could not be opened.
+CRYPTO_EXPORT ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path,
+                                               const std::string& description);
+
+#if !defined(OS_CHROMEOS)
+// Returns a reference to the default NSS key slot for storing persistent data.
+// Caller must release returned reference with PK11_FreeSlot.
+[[nodiscard]] CRYPTO_EXPORT PK11SlotInfo* GetPersistentNSSKeySlot();
+#endif
+
+// A helper class that acquires the SECMOD list read lock while the
+// AutoSECMODListReadLock is in scope.
+class CRYPTO_EXPORT AutoSECMODListReadLock {
+ public:
+  AutoSECMODListReadLock();
+  AutoSECMODListReadLock(const AutoSECMODListReadLock&) = delete;
+  AutoSECMODListReadLock& operator=(const AutoSECMODListReadLock&) = delete;
+
+  ~AutoSECMODListReadLock();
+
+ private:
+  SECMODListLock* lock_;
+};
+
+#if defined(OS_CHROMEOS)
+// Returns a reference to the system-wide TPM slot if it is loaded. If it is not
+// loaded and |callback| is non-null, the |callback| will be run once the slot
+// is loaded.
+[[nodiscard]] CRYPTO_EXPORT ScopedPK11Slot GetSystemNSSKeySlot(
+    base::OnceCallback<void(ScopedPK11Slot)> callback);
+
+// Sets the test system slot to |slot|, which means that |slot| will be exposed
+// through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will return true.
+// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization,
+// does not have to be called if the test system slot is set.
+// This must must not be called consecutively with a |slot| != NULL. If |slot|
+// is NULL, the test system slot is unset.
+CRYPTO_EXPORT void SetSystemKeySlotForTesting(ScopedPK11Slot slot);
+
+// Prepare per-user NSS slot mapping. It is safe to call this function multiple
+// times. Returns true if the user was added, or false if it already existed.
+CRYPTO_EXPORT bool InitializeNSSForChromeOSUser(
+    const std::string& username_hash,
+    const base::FilePath& path);
+
+// Returns whether TPM for ChromeOS user still needs initialization. If
+// true is returned, the caller can proceed to initialize TPM slot for the
+// user, but should call |WillInitializeTPMForChromeOSUser| first.
+// |InitializeNSSForChromeOSUser| must have been called first.
+[[nodiscard]] CRYPTO_EXPORT bool ShouldInitializeTPMForChromeOSUser(
+    const std::string& username_hash);
+
+// Makes |ShouldInitializeTPMForChromeOSUser| start returning false.
+// Should be called before starting TPM initialization for the user.
+// Assumes |InitializeNSSForChromeOSUser| had already been called.
+CRYPTO_EXPORT void WillInitializeTPMForChromeOSUser(
+    const std::string& username_hash);
+
+// Use TPM slot |slot_id| for user.  InitializeNSSForChromeOSUser must have been
+// called first.
+CRYPTO_EXPORT void InitializeTPMForChromeOSUser(
+    const std::string& username_hash,
+    CK_SLOT_ID slot_id);
+
+// Use the software slot as the private slot for user.
+// InitializeNSSForChromeOSUser must have been called first.
+CRYPTO_EXPORT void InitializePrivateSoftwareSlotForChromeOSUser(
+    const std::string& username_hash);
+
+// Returns a reference to the public slot for user.
+[[nodiscard]] CRYPTO_EXPORT ScopedPK11Slot GetPublicSlotForChromeOSUser(
+    const std::string& username_hash);
+
+// Returns the private slot for |username_hash| if it is loaded. If it is not
+// loaded and |callback| is non-null, the |callback| will be run once the slot
+// is loaded.
+[[nodiscard]] CRYPTO_EXPORT ScopedPK11Slot GetPrivateSlotForChromeOSUser(
+    const std::string& username_hash,
+    base::OnceCallback<void(ScopedPK11Slot)> callback);
+
+// Closes the NSS DB for |username_hash| that was previously opened by the
+// *Initialize*ForChromeOSUser functions.
+CRYPTO_EXPORT void CloseChromeOSUserForTesting(
+    const std::string& username_hash);
+#endif  // defined(OS_CHROMEOS)
+
+}  // namespace crypto
+
+#endif  // CRYPTO_NSS_UTIL_INTERNAL_H_
diff --git a/crypto/nss_util_unittest.cc b/crypto/nss_util_unittest.cc
new file mode 100644
index 0000000..8b37034
--- /dev/null
+++ b/crypto/nss_util_unittest.cc
@@ -0,0 +1,43 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/nss_util.h"
+
+#include <prtime.h>
+
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace crypto {
+
+TEST(NSSUtilTest, PRTimeConversion) {
+  EXPECT_EQ(base::Time::UnixEpoch(), PRTimeToBaseTime(0));
+  EXPECT_EQ(0, BaseTimeToPRTime(base::Time::UnixEpoch()));
+
+  PRExplodedTime prxtime;
+  prxtime.tm_params.tp_gmt_offset = 0;
+  prxtime.tm_params.tp_dst_offset = 0;
+  base::Time::Exploded exploded;
+  exploded.year = prxtime.tm_year = 2011;
+  exploded.month = 12;
+  prxtime.tm_month = 11;
+  // PRExplodedTime::tm_wday is a smaller type than Exploded::day_of_week, so
+  // assigning the two in this order instead of the reverse avoids potential
+  // warnings about type downcasting.
+  exploded.day_of_week = prxtime.tm_wday = 0;  // Should be unused.
+  exploded.day_of_month = prxtime.tm_mday = 10;
+  exploded.hour = prxtime.tm_hour = 2;
+  exploded.minute = prxtime.tm_min = 52;
+  exploded.second = prxtime.tm_sec = 19;
+  exploded.millisecond = 342;
+  prxtime.tm_usec = 342000;
+
+  PRTime pr_time = PR_ImplodeTime(&prxtime);
+  base::Time base_time = base::Time::FromUTCExploded(exploded);
+
+  EXPECT_EQ(base_time, PRTimeToBaseTime(pr_time));
+  EXPECT_EQ(pr_time, BaseTimeToPRTime(base_time));
+}
+
+}  // namespace crypto
diff --git a/crypto/openssl_util.cc b/crypto/openssl_util.cc
new file mode 100644
index 0000000..1229b7a
--- /dev/null
+++ b/crypto/openssl_util.cc
@@ -0,0 +1,63 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/openssl_util.h"
+
+#if defined(OPENSSL_IS_BORINGSSL)
+#include <openssl/cpu.h>
+#else
+#include <openssl/ssl.h>
+#endif
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string_view>
+
+#include "base/logging.h"
+
+namespace crypto {
+
+namespace {
+
+// Callback routine for OpenSSL to print error messages. |str| is a
+// NULL-terminated string of length |len| containing diagnostic information
+// such as the library, function and reason for the error, the file and line
+// where the error originated, plus potentially any context-specific
+// information about the error. |context| contains a pointer to user-supplied
+// data, which is currently unused.
+// If this callback returns a value <= 0, OpenSSL will stop processing the
+// error queue and return, otherwise it will continue calling this function
+// until all errors have been removed from the queue.
+int OpenSSLErrorCallback(const char* str, size_t len, void* context) {
+  DVLOG(1) << "\t" << std::string_view(str, len);
+  return 1;
+}
+
+}  // namespace
+
+void EnsureOpenSSLInit() {
+#if defined(OPENSSL_IS_BORINGSSL)
+  // CRYPTO_library_init may be safely called concurrently.
+  CRYPTO_library_init();
+#else
+  SSL_library_init();
+#endif
+}
+
+void ClearOpenSSLERRStack(const base::Location& location) {
+  if (DCHECK_IS_ON() && VLOG_IS_ON(1)) {
+    uint32_t error_num = ERR_peek_error();
+    if (error_num == 0)
+      return;
+
+    DVLOG(1) << "OpenSSL ERR_get_error stack from " << location.ToString();
+    ERR_print_errors_cb(&OpenSSLErrorCallback, NULL);
+  } else {
+    ERR_clear_error();
+  }
+}
+
+}  // namespace crypto
diff --git a/crypto/openssl_util.h b/crypto/openssl_util.h
new file mode 100644
index 0000000..5ba16b6
--- /dev/null
+++ b/crypto/openssl_util.h
@@ -0,0 +1,94 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_OPENSSL_UTIL_H_
+#define CRYPTO_OPENSSL_UTIL_H_
+
+#include <stddef.h>
+
+#include "base/location.h"
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// Provides a buffer of at least MIN_SIZE bytes, for use when calling OpenSSL's
+// SHA256, HMAC, etc functions, adapting the buffer sizing rules to meet those
+// of the our base wrapper APIs.
+// This allows the library to write directly to the caller's buffer if it is of
+// sufficient size, but if not it will write to temporary |min_sized_buffer_|
+// of required size and then its content is automatically copied out on
+// destruction, with truncation as appropriate.
+template<int MIN_SIZE>
+class ScopedOpenSSLSafeSizeBuffer {
+ public:
+  ScopedOpenSSLSafeSizeBuffer(unsigned char* output, size_t output_len)
+      : output_(output),
+        output_len_(output_len) {
+  }
+
+  ScopedOpenSSLSafeSizeBuffer(const ScopedOpenSSLSafeSizeBuffer&) = delete;
+  ScopedOpenSSLSafeSizeBuffer& operator=(const ScopedOpenSSLSafeSizeBuffer&) = delete;
+
+  ~ScopedOpenSSLSafeSizeBuffer() {
+    if (output_len_ < MIN_SIZE) {
+      // Copy the temporary buffer out, truncating as needed.
+      memcpy(output_, min_sized_buffer_, output_len_);
+    }
+    // else... any writing already happened directly into |output_|.
+  }
+
+  unsigned char* safe_buffer() {
+    return output_len_ < MIN_SIZE ? min_sized_buffer_ : output_;
+  }
+
+ private:
+  // Pointer to the caller's data area and its associated size, where data
+  // written via safe_buffer() will [eventually] end up.
+  unsigned char* output_;
+  size_t output_len_;
+
+  // Temporary buffer writen into in the case where the caller's
+  // buffer is not of sufficient size.
+  unsigned char min_sized_buffer_[MIN_SIZE];
+};
+
+// Initialize OpenSSL if it isn't already initialized. This must be called
+// before any other OpenSSL functions though it is safe and cheap to call this
+// multiple times.
+// This function is thread-safe, and OpenSSL will only ever be initialized once.
+// OpenSSL will be properly shut down on program exit.
+CRYPTO_EXPORT void EnsureOpenSSLInit();
+
+// Drains the OpenSSL ERR_get_error stack. On a debug build the error codes
+// are send to VLOG(1), on a release build they are disregarded. In most
+// cases you should pass FROM_HERE as the |location|.
+CRYPTO_EXPORT void ClearOpenSSLERRStack(const base::Location& location);
+
+// Place an instance of this class on the call stack to automatically clear
+// the OpenSSL error stack on function exit.
+class OpenSSLErrStackTracer {
+ public:
+  // Pass FROM_HERE as |location|, to help track the source of OpenSSL error
+  // messages. Note any diagnostic emitted will be tagged with the location of
+  // the constructor call as it's not possible to trace a destructor's callsite.
+  explicit OpenSSLErrStackTracer(const base::Location& location)
+      : location_(location) {
+    EnsureOpenSSLInit();
+  }
+
+  OpenSSLErrStackTracer() = delete;
+  OpenSSLErrStackTracer(const OpenSSLErrStackTracer&) = delete;
+  OpenSSLErrStackTracer& operator=(const OpenSSLErrStackTracer&) = delete;
+
+  ~OpenSSLErrStackTracer() {
+    ClearOpenSSLERRStack(location_);
+  }
+
+ private:
+  const base::Location location_;
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_OPENSSL_UTIL_H_
diff --git a/crypto/p224.cc b/crypto/p224.cc
new file mode 100644
index 0000000..b12ff7b
--- /dev/null
+++ b/crypto/p224.cc
@@ -0,0 +1,747 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This is an implementation of the P224 elliptic curve group. It's written to
+// be short and simple rather than fast, although it's still constant-time.
+//
+// See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
+
+#include "crypto/p224.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "base/sys_byteorder.h"
+
+namespace {
+
+using base::HostToNet32;
+using base::NetToHost32;
+
+// Field element functions.
+//
+// The field that we're dealing with is ℤ/pℤ where p = 2**224 - 2**96 + 1.
+//
+// Field elements are represented by a FieldElement, which is a typedef to an
+// array of 8 uint32_t's. The value of a FieldElement, a, is:
+//   a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7]
+//
+// Using 28-bit limbs means that there's only 4 bits of headroom, which is less
+// than we would really like. But it has the useful feature that we hit 2**224
+// exactly, making the reflections during a reduce much nicer.
+
+using crypto::p224::FieldElement;
+
+// kP is the P224 prime.
+const FieldElement kP = {
+  1, 0, 0, 268431360,
+  268435455, 268435455, 268435455, 268435455,
+};
+
+void Contract(FieldElement* inout);
+
+// IsZero returns 0xffffffff if a == 0 mod p and 0 otherwise.
+uint32_t IsZero(const FieldElement& a) {
+  FieldElement minimal;
+  memcpy(&minimal, &a, sizeof(minimal));
+  Contract(&minimal);
+
+  uint32_t is_zero = 0, is_p = 0;
+  for (unsigned i = 0; i < 8; i++) {
+    is_zero |= minimal[i];
+    is_p |= minimal[i] - kP[i];
+  }
+
+  // If either is_zero or is_p is 0, then we should return 1.
+  is_zero |= is_zero >> 16;
+  is_zero |= is_zero >> 8;
+  is_zero |= is_zero >> 4;
+  is_zero |= is_zero >> 2;
+  is_zero |= is_zero >> 1;
+
+  is_p |= is_p >> 16;
+  is_p |= is_p >> 8;
+  is_p |= is_p >> 4;
+  is_p |= is_p >> 2;
+  is_p |= is_p >> 1;
+
+  // For is_zero and is_p, the LSB is 0 iff all the bits are zero.
+  is_zero &= is_p & 1;
+  is_zero = (~is_zero) << 31;
+  is_zero = static_cast<int32_t>(is_zero) >> 31;
+  return is_zero;
+}
+
+// Add computes *out = a+b
+//
+// a[i] + b[i] < 2**32
+void Add(FieldElement* out, const FieldElement& a, const FieldElement& b) {
+  for (int i = 0; i < 8; i++) {
+    (*out)[i] = a[i] + b[i];
+  }
+}
+
+static const uint32_t kTwo31p3 = (1u << 31) + (1u << 3);
+static const uint32_t kTwo31m3 = (1u << 31) - (1u << 3);
+static const uint32_t kTwo31m15m3 = (1u << 31) - (1u << 15) - (1u << 3);
+// kZero31ModP is 0 mod p where bit 31 is set in all limbs so that we can
+// subtract smaller amounts without underflow. See the section "Subtraction" in
+// [1] for why.
+static const FieldElement kZero31ModP = {
+  kTwo31p3, kTwo31m3, kTwo31m3, kTwo31m15m3,
+  kTwo31m3, kTwo31m3, kTwo31m3, kTwo31m3
+};
+
+// Subtract computes *out = a-b
+//
+// a[i], b[i] < 2**30
+// out[i] < 2**32
+void Subtract(FieldElement* out, const FieldElement& a, const FieldElement& b) {
+  for (int i = 0; i < 8; i++) {
+    // See the section on "Subtraction" in [1] for details.
+    (*out)[i] = a[i] + kZero31ModP[i] - b[i];
+  }
+}
+
+static const uint64_t kTwo63p35 = (1ull << 63) + (1ull << 35);
+static const uint64_t kTwo63m35 = (1ull << 63) - (1ull << 35);
+static const uint64_t kTwo63m35m19 = (1ull << 63) - (1ull << 35) - (1ull << 19);
+// kZero63ModP is 0 mod p where bit 63 is set in all limbs. See the section
+// "Subtraction" in [1] for why.
+static const uint64_t kZero63ModP[8] = {
+    kTwo63p35,    kTwo63m35, kTwo63m35, kTwo63m35,
+    kTwo63m35m19, kTwo63m35, kTwo63m35, kTwo63m35,
+};
+
+static const uint32_t kBottom28Bits = 0xfffffff;
+
+// LargeFieldElement also represents an element of the field. The limbs are
+// still spaced 28-bits apart and in little-endian order. So the limbs are at
+// 0, 28, 56, ..., 392 bits, each 64-bits wide.
+typedef uint64_t LargeFieldElement[15];
+
+// ReduceLarge converts a LargeFieldElement to a FieldElement.
+//
+// in[i] < 2**62
+void ReduceLarge(FieldElement* out, LargeFieldElement* inptr) {
+  LargeFieldElement& in(*inptr);
+
+  for (int i = 0; i < 8; i++) {
+    in[i] += kZero63ModP[i];
+  }
+
+  // Eliminate the coefficients at 2**224 and greater while maintaining the
+  // same value mod p.
+  for (int i = 14; i >= 8; i--) {
+    in[i-8] -= in[i];  // reflection off the "+1" term of p.
+    in[i-5] += (in[i] & 0xffff) << 12;  // part of the "-2**96" reflection.
+    in[i-4] += in[i] >> 16;  // the rest of the "-2**96" reflection.
+  }
+  in[8] = 0;
+  // in[0..8] < 2**64
+
+  // As the values become small enough, we start to store them in |out| and use
+  // 32-bit operations.
+  for (int i = 1; i < 8; i++) {
+    in[i+1] += in[i] >> 28;
+    (*out)[i] = static_cast<uint32_t>(in[i] & kBottom28Bits);
+  }
+  // Eliminate the term at 2*224 that we introduced while keeping the same
+  // value mod p.
+  in[0] -= in[8];  // reflection off the "+1" term of p.
+  (*out)[3] += static_cast<uint32_t>(in[8] & 0xffff) << 12;  // "-2**96" term
+  (*out)[4] += static_cast<uint32_t>(in[8] >> 16);  // rest of "-2**96" term
+  // in[0] < 2**64
+  // out[3] < 2**29
+  // out[4] < 2**29
+  // out[1,2,5..7] < 2**28
+
+  (*out)[0] = static_cast<uint32_t>(in[0] & kBottom28Bits);
+  (*out)[1] += static_cast<uint32_t>((in[0] >> 28) & kBottom28Bits);
+  (*out)[2] += static_cast<uint32_t>(in[0] >> 56);
+  // out[0] < 2**28
+  // out[1..4] < 2**29
+  // out[5..7] < 2**28
+}
+
+// Mul computes *out = a*b
+//
+// a[i] < 2**29, b[i] < 2**30 (or vice versa)
+// out[i] < 2**29
+void Mul(FieldElement* out, const FieldElement& a, const FieldElement& b) {
+  LargeFieldElement tmp;
+  memset(&tmp, 0, sizeof(tmp));
+
+  for (int i = 0; i < 8; i++) {
+    for (int j = 0; j < 8; j++) {
+      tmp[i + j] += static_cast<uint64_t>(a[i]) * static_cast<uint64_t>(b[j]);
+    }
+  }
+
+  ReduceLarge(out, &tmp);
+}
+
+// Square computes *out = a*a
+//
+// a[i] < 2**29
+// out[i] < 2**29
+void Square(FieldElement* out, const FieldElement& a) {
+  LargeFieldElement tmp;
+  memset(&tmp, 0, sizeof(tmp));
+
+  for (int i = 0; i < 8; i++) {
+    for (int j = 0; j <= i; j++) {
+      uint64_t r = static_cast<uint64_t>(a[i]) * static_cast<uint64_t>(a[j]);
+      if (i == j) {
+        tmp[i+j] += r;
+      } else {
+        tmp[i+j] += r << 1;
+      }
+    }
+  }
+
+  ReduceLarge(out, &tmp);
+}
+
+// Reduce reduces the coefficients of in_out to smaller bounds.
+//
+// On entry: a[i] < 2**31 + 2**30
+// On exit: a[i] < 2**29
+void Reduce(FieldElement* in_out) {
+  FieldElement& a = *in_out;
+
+  for (int i = 0; i < 7; i++) {
+    a[i+1] += a[i] >> 28;
+    a[i] &= kBottom28Bits;
+  }
+  uint32_t top = a[7] >> 28;
+  a[7] &= kBottom28Bits;
+
+  // top < 2**4
+  // Constant-time: mask = (top != 0) ? 0xffffffff : 0
+  uint32_t mask = top;
+  mask |= mask >> 2;
+  mask |= mask >> 1;
+  mask <<= 31;
+  mask = static_cast<uint32_t>(static_cast<int32_t>(mask) >> 31);
+
+  // Eliminate top while maintaining the same value mod p.
+  a[0] -= top;
+  a[3] += top << 12;
+
+  // We may have just made a[0] negative but, if we did, then we must
+  // have added something to a[3], thus it's > 2**12. Therefore we can
+  // carry down to a[0].
+  a[3] -= 1 & mask;
+  a[2] += mask & ((1<<28) - 1);
+  a[1] += mask & ((1<<28) - 1);
+  a[0] += mask & (1<<28);
+}
+
+// Invert calcuates *out = in**-1 by computing in**(2**224 - 2**96 - 1), i.e.
+// Fermat's little theorem.
+void Invert(FieldElement* out, const FieldElement& in) {
+  FieldElement f1, f2, f3, f4;
+
+  Square(&f1, in);                        // 2
+  Mul(&f1, f1, in);                       // 2**2 - 1
+  Square(&f1, f1);                        // 2**3 - 2
+  Mul(&f1, f1, in);                       // 2**3 - 1
+  Square(&f2, f1);                        // 2**4 - 2
+  Square(&f2, f2);                        // 2**5 - 4
+  Square(&f2, f2);                        // 2**6 - 8
+  Mul(&f1, f1, f2);                       // 2**6 - 1
+  Square(&f2, f1);                        // 2**7 - 2
+  for (int i = 0; i < 5; i++) {           // 2**12 - 2**6
+    Square(&f2, f2);
+  }
+  Mul(&f2, f2, f1);                       // 2**12 - 1
+  Square(&f3, f2);                        // 2**13 - 2
+  for (int i = 0; i < 11; i++) {          // 2**24 - 2**12
+    Square(&f3, f3);
+  }
+  Mul(&f2, f3, f2);                       // 2**24 - 1
+  Square(&f3, f2);                        // 2**25 - 2
+  for (int i = 0; i < 23; i++) {          // 2**48 - 2**24
+    Square(&f3, f3);
+  }
+  Mul(&f3, f3, f2);                       // 2**48 - 1
+  Square(&f4, f3);                        // 2**49 - 2
+  for (int i = 0; i < 47; i++) {          // 2**96 - 2**48
+    Square(&f4, f4);
+  }
+  Mul(&f3, f3, f4);                       // 2**96 - 1
+  Square(&f4, f3);                        // 2**97 - 2
+  for (int i = 0; i < 23; i++) {          // 2**120 - 2**24
+    Square(&f4, f4);
+  }
+  Mul(&f2, f4, f2);                       // 2**120 - 1
+  for (int i = 0; i < 6; i++) {           // 2**126 - 2**6
+    Square(&f2, f2);
+  }
+  Mul(&f1, f1, f2);                       // 2**126 - 1
+  Square(&f1, f1);                        // 2**127 - 2
+  Mul(&f1, f1, in);                       // 2**127 - 1
+  for (int i = 0; i < 97; i++) {          // 2**224 - 2**97
+    Square(&f1, f1);
+  }
+  Mul(out, f1, f3);                       // 2**224 - 2**96 - 1
+}
+
+// Contract converts a FieldElement to its minimal, distinguished form.
+//
+// On entry, in[i] < 2**29
+// On exit, in[i] < 2**28
+void Contract(FieldElement* inout) {
+  FieldElement& out = *inout;
+
+  // Reduce the coefficients to < 2**28.
+  for (int i = 0; i < 7; i++) {
+    out[i+1] += out[i] >> 28;
+    out[i] &= kBottom28Bits;
+  }
+  uint32_t top = out[7] >> 28;
+  out[7] &= kBottom28Bits;
+
+  // Eliminate top while maintaining the same value mod p.
+  out[0] -= top;
+  out[3] += top << 12;
+
+  // We may just have made out[0] negative. So we carry down. If we made
+  // out[0] negative then we know that out[3] is sufficiently positive
+  // because we just added to it.
+  for (int i = 0; i < 3; i++) {
+    uint32_t mask = static_cast<uint32_t>(static_cast<int32_t>(out[i]) >> 31);
+    out[i] += (1 << 28) & mask;
+    out[i+1] -= 1 & mask;
+  }
+
+  // We might have pushed out[3] over 2**28 so we perform another, partial
+  // carry chain.
+  for (int i = 3; i < 7; i++) {
+    out[i+1] += out[i] >> 28;
+    out[i] &= kBottom28Bits;
+  }
+  top = out[7] >> 28;
+  out[7] &= kBottom28Bits;
+
+  // Eliminate top while maintaining the same value mod p.
+  out[0] -= top;
+  out[3] += top << 12;
+
+  // There are two cases to consider for out[3]:
+  //   1) The first time that we eliminated top, we didn't push out[3] over
+  //      2**28. In this case, the partial carry chain didn't change any values
+  //      and top is zero.
+  //   2) We did push out[3] over 2**28 the first time that we eliminated top.
+  //      The first value of top was in [0..16), therefore, prior to eliminating
+  //      the first top, 0xfff1000 <= out[3] <= 0xfffffff. Therefore, after
+  //      overflowing and being reduced by the second carry chain, out[3] <=
+  //      0xf000. Thus it cannot have overflowed when we eliminated top for the
+  //      second time.
+
+  // Again, we may just have made out[0] negative, so do the same carry down.
+  // As before, if we made out[0] negative then we know that out[3] is
+  // sufficiently positive.
+  for (int i = 0; i < 3; i++) {
+    uint32_t mask = static_cast<uint32_t>(static_cast<int32_t>(out[i]) >> 31);
+    out[i] += (1 << 28) & mask;
+    out[i+1] -= 1 & mask;
+  }
+
+  // The value is < 2**224, but maybe greater than p. In order to reduce to a
+  // unique, minimal value we see if the value is >= p and, if so, subtract p.
+
+  // First we build a mask from the top four limbs, which must all be
+  // equal to bottom28Bits if the whole value is >= p. If top_4_all_ones
+  // ends up with any zero bits in the bottom 28 bits, then this wasn't
+  // true.
+  uint32_t top_4_all_ones = 0xffffffffu;
+  for (int i = 4; i < 8; i++) {
+    top_4_all_ones &= out[i];
+  }
+  top_4_all_ones |= 0xf0000000;
+  // Now we replicate any zero bits to all the bits in top_4_all_ones.
+  top_4_all_ones &= top_4_all_ones >> 16;
+  top_4_all_ones &= top_4_all_ones >> 8;
+  top_4_all_ones &= top_4_all_ones >> 4;
+  top_4_all_ones &= top_4_all_ones >> 2;
+  top_4_all_ones &= top_4_all_ones >> 1;
+  top_4_all_ones =
+      static_cast<uint32_t>(static_cast<int32_t>(top_4_all_ones << 31) >> 31);
+
+  // Now we test whether the bottom three limbs are non-zero.
+  uint32_t bottom_3_non_zero = out[0] | out[1] | out[2];
+  bottom_3_non_zero |= bottom_3_non_zero >> 16;
+  bottom_3_non_zero |= bottom_3_non_zero >> 8;
+  bottom_3_non_zero |= bottom_3_non_zero >> 4;
+  bottom_3_non_zero |= bottom_3_non_zero >> 2;
+  bottom_3_non_zero |= bottom_3_non_zero >> 1;
+  bottom_3_non_zero =
+      static_cast<uint32_t>(static_cast<int32_t>(bottom_3_non_zero) >> 31);
+
+  // Everything depends on the value of out[3].
+  //    If it's > 0xffff000 and top_4_all_ones != 0 then the whole value is >= p
+  //    If it's = 0xffff000 and top_4_all_ones != 0 and bottom_3_non_zero != 0,
+  //      then the whole value is >= p
+  //    If it's < 0xffff000, then the whole value is < p
+  uint32_t n = out[3] - 0xffff000;
+  uint32_t out_3_equal = n;
+  out_3_equal |= out_3_equal >> 16;
+  out_3_equal |= out_3_equal >> 8;
+  out_3_equal |= out_3_equal >> 4;
+  out_3_equal |= out_3_equal >> 2;
+  out_3_equal |= out_3_equal >> 1;
+  out_3_equal =
+      ~static_cast<uint32_t>(static_cast<int32_t>(out_3_equal << 31) >> 31);
+
+  // If out[3] > 0xffff000 then n's MSB will be zero.
+  uint32_t out_3_gt =
+      ~static_cast<uint32_t>(static_cast<int32_t>(n << 31) >> 31);
+
+  uint32_t mask =
+      top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt);
+  out[0] -= 1 & mask;
+  out[3] -= 0xffff000 & mask;
+  out[4] -= 0xfffffff & mask;
+  out[5] -= 0xfffffff & mask;
+  out[6] -= 0xfffffff & mask;
+  out[7] -= 0xfffffff & mask;
+}
+
+
+// Group element functions.
+//
+// These functions deal with group elements. The group is an elliptic curve
+// group with a = -3 defined in FIPS 186-3, section D.2.2.
+
+using crypto::p224::Point;
+
+// kB is parameter of the elliptic curve.
+const FieldElement kB = {
+  55967668, 11768882, 265861671, 185302395,
+  39211076, 180311059, 84673715, 188764328,
+};
+
+void CopyConditional(Point* out, const Point& a, uint32_t mask);
+void DoubleJacobian(Point* out, const Point& a);
+
+// AddJacobian computes *out = a+b where a != b.
+void AddJacobian(Point *out,
+                 const Point& a,
+                 const Point& b) {
+  // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl
+  FieldElement z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v;
+
+  uint32_t z1_is_zero = IsZero(a.z);
+  uint32_t z2_is_zero = IsZero(b.z);
+
+  // Z1Z1 = Z1²
+  Square(&z1z1, a.z);
+
+  // Z2Z2 = Z2²
+  Square(&z2z2, b.z);
+
+  // U1 = X1*Z2Z2
+  Mul(&u1, a.x, z2z2);
+
+  // U2 = X2*Z1Z1
+  Mul(&u2, b.x, z1z1);
+
+  // S1 = Y1*Z2*Z2Z2
+  Mul(&s1, b.z, z2z2);
+  Mul(&s1, a.y, s1);
+
+  // S2 = Y2*Z1*Z1Z1
+  Mul(&s2, a.z, z1z1);
+  Mul(&s2, b.y, s2);
+
+  // H = U2-U1
+  Subtract(&h, u2, u1);
+  Reduce(&h);
+  uint32_t x_equal = IsZero(h);
+
+  // I = (2*H)²
+  for (int k = 0; k < 8; k++) {
+    i[k] = h[k] << 1;
+  }
+  Reduce(&i);
+  Square(&i, i);
+
+  // J = H*I
+  Mul(&j, h, i);
+  // r = 2*(S2-S1)
+  Subtract(&r, s2, s1);
+  Reduce(&r);
+  uint32_t y_equal = IsZero(r);
+
+  if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) {
+    // The two input points are the same therefore we must use the dedicated
+    // doubling function as the slope of the line is undefined.
+    DoubleJacobian(out, a);
+    return;
+  }
+
+  for (int k = 0; k < 8; k++) {
+    r[k] <<= 1;
+  }
+  Reduce(&r);
+
+  // V = U1*I
+  Mul(&v, u1, i);
+
+  // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H
+  Add(&z1z1, z1z1, z2z2);
+  Add(&z2z2, a.z, b.z);
+  Reduce(&z2z2);
+  Square(&z2z2, z2z2);
+  Subtract(&out->z, z2z2, z1z1);
+  Reduce(&out->z);
+  Mul(&out->z, out->z, h);
+
+  // X3 = r²-J-2*V
+  for (int k = 0; k < 8; k++) {
+    z1z1[k] = v[k] << 1;
+  }
+  Add(&z1z1, j, z1z1);
+  Reduce(&z1z1);
+  Square(&out->x, r);
+  Subtract(&out->x, out->x, z1z1);
+  Reduce(&out->x);
+
+  // Y3 = r*(V-X3)-2*S1*J
+  for (int k = 0; k < 8; k++) {
+    s1[k] <<= 1;
+  }
+  Mul(&s1, s1, j);
+  Subtract(&z1z1, v, out->x);
+  Reduce(&z1z1);
+  Mul(&z1z1, z1z1, r);
+  Subtract(&out->y, z1z1, s1);
+  Reduce(&out->y);
+
+  CopyConditional(out, a, z2_is_zero);
+  CopyConditional(out, b, z1_is_zero);
+}
+
+// DoubleJacobian computes *out = a+a.
+void DoubleJacobian(Point* out, const Point& a) {
+  // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
+  FieldElement delta, gamma, beta, alpha, t;
+
+  Square(&delta, a.z);
+  Square(&gamma, a.y);
+  Mul(&beta, a.x, gamma);
+
+  // alpha = 3*(X1-delta)*(X1+delta)
+  Add(&t, a.x, delta);
+  for (int i = 0; i < 8; i++) {
+          t[i] += t[i] << 1;
+  }
+  Reduce(&t);
+  Subtract(&alpha, a.x, delta);
+  Reduce(&alpha);
+  Mul(&alpha, alpha, t);
+
+  // Z3 = (Y1+Z1)²-gamma-delta
+  Add(&out->z, a.y, a.z);
+  Reduce(&out->z);
+  Square(&out->z, out->z);
+  Subtract(&out->z, out->z, gamma);
+  Reduce(&out->z);
+  Subtract(&out->z, out->z, delta);
+  Reduce(&out->z);
+
+  // X3 = alpha²-8*beta
+  for (int i = 0; i < 8; i++) {
+          delta[i] = beta[i] << 3;
+  }
+  Reduce(&delta);
+  Square(&out->x, alpha);
+  Subtract(&out->x, out->x, delta);
+  Reduce(&out->x);
+
+  // Y3 = alpha*(4*beta-X3)-8*gamma²
+  for (int i = 0; i < 8; i++) {
+          beta[i] <<= 2;
+  }
+  Reduce(&beta);
+  Subtract(&beta, beta, out->x);
+  Reduce(&beta);
+  Square(&gamma, gamma);
+  for (int i = 0; i < 8; i++) {
+          gamma[i] <<= 3;
+  }
+  Reduce(&gamma);
+  Mul(&out->y, alpha, beta);
+  Subtract(&out->y, out->y, gamma);
+  Reduce(&out->y);
+}
+
+// CopyConditional sets *out=a if mask is 0xffffffff. mask must be either 0 of
+// 0xffffffff.
+void CopyConditional(Point* out, const Point& a, uint32_t mask) {
+  for (int i = 0; i < 8; i++) {
+    out->x[i] ^= mask & (a.x[i] ^ out->x[i]);
+    out->y[i] ^= mask & (a.y[i] ^ out->y[i]);
+    out->z[i] ^= mask & (a.z[i] ^ out->z[i]);
+  }
+}
+
+// ScalarMult calculates *out = a*scalar where scalar is a big-endian number of
+// length scalar_len and != 0.
+void ScalarMult(Point* out,
+                const Point& a,
+                const uint8_t* scalar,
+                size_t scalar_len) {
+  memset(out, 0, sizeof(*out));
+  Point tmp;
+
+  for (size_t i = 0; i < scalar_len; i++) {
+    for (unsigned int bit_num = 0; bit_num < 8; bit_num++) {
+      DoubleJacobian(out, *out);
+      uint32_t bit = static_cast<uint32_t>(static_cast<int32_t>(
+          (((scalar[i] >> (7 - bit_num)) & 1) << 31) >> 31));
+      AddJacobian(&tmp, a, *out);
+      CopyConditional(out, tmp, bit);
+    }
+  }
+}
+
+// Get224Bits reads 7 words from in and scatters their contents in
+// little-endian form into 8 words at out, 28 bits per output word.
+void Get224Bits(uint32_t* out, const uint32_t* in) {
+  out[0] = NetToHost32(in[6]) & kBottom28Bits;
+  out[1] = ((NetToHost32(in[5]) << 4) |
+            (NetToHost32(in[6]) >> 28)) & kBottom28Bits;
+  out[2] = ((NetToHost32(in[4]) << 8) |
+            (NetToHost32(in[5]) >> 24)) & kBottom28Bits;
+  out[3] = ((NetToHost32(in[3]) << 12) |
+            (NetToHost32(in[4]) >> 20)) & kBottom28Bits;
+  out[4] = ((NetToHost32(in[2]) << 16) |
+            (NetToHost32(in[3]) >> 16)) & kBottom28Bits;
+  out[5] = ((NetToHost32(in[1]) << 20) |
+            (NetToHost32(in[2]) >> 12)) & kBottom28Bits;
+  out[6] = ((NetToHost32(in[0]) << 24) |
+            (NetToHost32(in[1]) >> 8)) & kBottom28Bits;
+  out[7] = (NetToHost32(in[0]) >> 4) & kBottom28Bits;
+}
+
+// Put224Bits performs the inverse operation to Get224Bits: taking 28 bits from
+// each of 8 input words and writing them in big-endian order to 7 words at
+// out.
+void Put224Bits(uint32_t* out, const uint32_t* in) {
+  out[6] = HostToNet32((in[0] >> 0) | (in[1] << 28));
+  out[5] = HostToNet32((in[1] >> 4) | (in[2] << 24));
+  out[4] = HostToNet32((in[2] >> 8) | (in[3] << 20));
+  out[3] = HostToNet32((in[3] >> 12) | (in[4] << 16));
+  out[2] = HostToNet32((in[4] >> 16) | (in[5] << 12));
+  out[1] = HostToNet32((in[5] >> 20) | (in[6] << 8));
+  out[0] = HostToNet32((in[6] >> 24) | (in[7] << 4));
+}
+
+}  // anonymous namespace
+
+namespace crypto {
+
+namespace p224 {
+
+bool Point::SetFromString(std::string_view in) {
+  if (in.size() != 2*28)
+    return false;
+  const uint32_t* inwords = reinterpret_cast<const uint32_t*>(in.data());
+  Get224Bits(x, inwords);
+  Get224Bits(y, inwords + 7);
+  memset(&z, 0, sizeof(z));
+  z[0] = 1;
+
+  // Check that the point is on the curve, i.e. that y² = x³ - 3x + b.
+  FieldElement lhs;
+  Square(&lhs, y);
+  Contract(&lhs);
+
+  FieldElement rhs;
+  Square(&rhs, x);
+  Mul(&rhs, x, rhs);
+
+  FieldElement three_x;
+  for (int i = 0; i < 8; i++) {
+    three_x[i] = x[i] * 3;
+  }
+  Reduce(&three_x);
+  Subtract(&rhs, rhs, three_x);
+  Reduce(&rhs);
+
+  ::Add(&rhs, rhs, kB);
+  Contract(&rhs);
+  return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
+}
+
+std::string Point::ToString() const {
+  FieldElement zinv, zinv_sq, xx, yy;
+
+  // If this is the point at infinity we return a string of all zeros.
+  if (IsZero(this->z)) {
+    static const char zeros[56] = {0};
+    return std::string(zeros, sizeof(zeros));
+  }
+
+  Invert(&zinv, this->z);
+  Square(&zinv_sq, zinv);
+  Mul(&xx, x, zinv_sq);
+  Mul(&zinv_sq, zinv_sq, zinv);
+  Mul(&yy, y, zinv_sq);
+
+  Contract(&xx);
+  Contract(&yy);
+
+  uint32_t outwords[14];
+  Put224Bits(outwords, xx);
+  Put224Bits(outwords + 7, yy);
+  return std::string(reinterpret_cast<const char*>(outwords), sizeof(outwords));
+}
+
+void ScalarMult(const Point& in, const uint8_t* scalar, Point* out) {
+  ::ScalarMult(out, in, scalar, 28);
+}
+
+// kBasePoint is the base point (generator) of the elliptic curve group.
+static const Point kBasePoint = {
+  {22813985, 52956513, 34677300, 203240812,
+   12143107, 133374265, 225162431, 191946955},
+  {83918388, 223877528, 122119236, 123340192,
+   266784067, 263504429, 146143011, 198407736},
+  {1, 0, 0, 0, 0, 0, 0, 0},
+};
+
+void ScalarBaseMult(const uint8_t* scalar, Point* out) {
+  ::ScalarMult(out, kBasePoint, scalar, 28);
+}
+
+void Add(const Point& a, const Point& b, Point* out) {
+  AddJacobian(out, a, b);
+}
+
+void Negate(const Point& in, Point* out) {
+  // Guide to elliptic curve cryptography, page 89 suggests that (X : X+Y : Z)
+  // is the negative in Jacobian coordinates, but it doesn't actually appear to
+  // be true in testing so this performs the negation in affine coordinates.
+  FieldElement zinv, zinv_sq, y;
+  Invert(&zinv, in.z);
+  Square(&zinv_sq, zinv);
+  Mul(&out->x, in.x, zinv_sq);
+  Mul(&zinv_sq, zinv_sq, zinv);
+  Mul(&y, in.y, zinv_sq);
+
+  Subtract(&out->y, kP, y);
+  Reduce(&out->y);
+
+  memset(&out->z, 0, sizeof(out->z));
+  out->z[0] = 1;
+}
+
+}  // namespace p224
+
+}  // namespace crypto
diff --git a/crypto/p224.h b/crypto/p224.h
new file mode 100644
index 0000000..a098957
--- /dev/null
+++ b/crypto/p224.h
@@ -0,0 +1,64 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_P224_H_
+#define CRYPTO_P224_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <string_view>
+
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// P224 implements an elliptic curve group, commonly known as P224 and defined
+// in FIPS 186-3, section D.2.2.
+namespace p224 {
+
+// An element of the field (ℤ/pℤ) is represented with 8, 28-bit limbs in
+// little endian order.
+typedef uint32_t FieldElement[8];
+
+struct CRYPTO_EXPORT Point {
+  // SetFromString the value of the point from the 56 byte, external
+  // representation. The external point representation is an (x, y) pair of a
+  // point on the curve. Each field element is represented as a big-endian
+  // number < p.
+  bool SetFromString(std::string_view in);
+
+  // ToString returns an external representation of the Point.
+  std::string ToString() const;
+
+  // An Point is represented in Jacobian form (x/z², y/z³).
+  FieldElement x, y, z;
+};
+
+// kScalarBytes is the number of bytes needed to represent an element of the
+// P224 field.
+static const size_t kScalarBytes = 28;
+
+// ScalarMult computes *out = in*scalar where scalar is a 28-byte, big-endian
+// number.
+void CRYPTO_EXPORT ScalarMult(const Point& in,
+                              const uint8_t* scalar,
+                              Point* out);
+
+// ScalarBaseMult computes *out = g*scalar where g is the base point of the
+// curve and scalar is a 28-byte, big-endian number.
+void CRYPTO_EXPORT ScalarBaseMult(const uint8_t* scalar, Point* out);
+
+// Add computes *out = a+b.
+void CRYPTO_EXPORT Add(const Point& a, const Point& b, Point* out);
+
+// Negate calculates out = -a;
+void CRYPTO_EXPORT Negate(const Point& a, Point* out);
+
+}  // namespace p224
+
+}  // namespace crypto
+
+#endif  // CRYPTO_P224_H_
diff --git a/crypto/p224_spake.cc b/crypto/p224_spake.cc
new file mode 100644
index 0000000..b50a47a
--- /dev/null
+++ b/crypto/p224_spake.cc
@@ -0,0 +1,268 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This code implements SPAKE2, a variant of EKE:
+//  http://www.di.ens.fr/~pointche/pub.php?reference=AbPo04
+
+#include <crypto/p224_spake.h>
+
+#include <algorithm>
+
+#include <base/logging.h>
+#include <crypto/p224.h>
+#include <crypto/random.h>
+#include <crypto/secure_util.h>
+
+namespace {
+
+// The following two points (M and N in the protocol) are verifiable random
+// points on the curve and can be generated with the following code:
+
+// #include <stdint.h>
+// #include <stdio.h>
+// #include <string.h>
+//
+// #include <openssl/ec.h>
+// #include <openssl/obj_mac.h>
+// #include <openssl/sha.h>
+//
+// static const char kSeed1[] = "P224 point generation seed (M)";
+// static const char kSeed2[] = "P224 point generation seed (N)";
+//
+// void find_seed(const char* seed) {
+//   SHA256_CTX sha256;
+//   uint8_t digest[SHA256_DIGEST_LENGTH];
+//
+//   SHA256_Init(&sha256);
+//   SHA256_Update(&sha256, seed, strlen(seed));
+//   SHA256_Final(digest, &sha256);
+//
+//   BIGNUM x, y;
+//   EC_GROUP* p224 = EC_GROUP_new_by_curve_name(NID_secp224r1);
+//   EC_POINT* p = EC_POINT_new(p224);
+//
+//   for (unsigned i = 0;; i++) {
+//     BN_init(&x);
+//     BN_bin2bn(digest, 28, &x);
+//
+//     if (EC_POINT_set_compressed_coordinates_GFp(
+//             p224, p, &x, digest[28] & 1, NULL)) {
+//       BN_init(&y);
+//       EC_POINT_get_affine_coordinates_GFp(p224, p, &x, &y, NULL);
+//       char* x_str = BN_bn2hex(&x);
+//       char* y_str = BN_bn2hex(&y);
+//       printf("Found after %u iterations:\n%s\n%s\n", i, x_str, y_str);
+//       OPENSSL_free(x_str);
+//       OPENSSL_free(y_str);
+//       BN_free(&x);
+//       BN_free(&y);
+//       break;
+//     }
+//
+//     SHA256_Init(&sha256);
+//     SHA256_Update(&sha256, digest, sizeof(digest));
+//     SHA256_Final(digest, &sha256);
+//
+//     BN_free(&x);
+//   }
+//
+//   EC_POINT_free(p);
+//   EC_GROUP_free(p224);
+// }
+//
+// int main() {
+//   find_seed(kSeed1);
+//   find_seed(kSeed2);
+//   return 0;
+// }
+
+const crypto::p224::Point kM = {
+  {174237515, 77186811, 235213682, 33849492,
+   33188520, 48266885, 177021753, 81038478},
+  {104523827, 245682244, 266509668, 236196369,
+   28372046, 145351378, 198520366, 113345994},
+  {1, 0, 0, 0, 0, 0, 0, 0},
+};
+
+const crypto::p224::Point kN = {
+  {136176322, 263523628, 251628795, 229292285,
+   5034302, 185981975, 171998428, 11653062},
+  {197567436, 51226044, 60372156, 175772188,
+   42075930, 8083165, 160827401, 65097570},
+  {1, 0, 0, 0, 0, 0, 0, 0},
+};
+
+}  // anonymous namespace
+
+namespace crypto {
+
+P224EncryptedKeyExchange::P224EncryptedKeyExchange(
+    PeerType peer_type, std::string_view password)
+    : state_(kStateInitial),
+      is_server_(peer_type == kPeerTypeServer) {
+  memset(&x_, 0, sizeof(x_));
+  memset(&expected_authenticator_, 0, sizeof(expected_authenticator_));
+
+  // x_ is a random scalar.
+  RandBytes(x_, sizeof(x_));
+
+  // Calculate |password| hash to get SPAKE password value.
+  SHA256HashString(std::string(password.data(), password.length()),
+                   pw_, sizeof(pw_));
+
+  Init();
+}
+
+void P224EncryptedKeyExchange::Init() {
+  // X = g**x_
+  p224::Point X;
+  p224::ScalarBaseMult(x_, &X);
+
+  // The client masks the Diffie-Hellman value, X, by adding M**pw and the
+  // server uses N**pw.
+  p224::Point MNpw;
+  p224::ScalarMult(is_server_ ? kN : kM, pw_, &MNpw);
+
+  // X* = X + (N|M)**pw
+  p224::Point Xstar;
+  p224::Add(X, MNpw, &Xstar);
+
+  next_message_ = Xstar.ToString();
+}
+
+const std::string& P224EncryptedKeyExchange::GetNextMessage() {
+  if (state_ == kStateInitial) {
+    state_ = kStateRecvDH;
+    return next_message_;
+  } else if (state_ == kStateSendHash) {
+    state_ = kStateRecvHash;
+    return next_message_;
+  }
+
+  LOG(FATAL) << "P224EncryptedKeyExchange::GetNextMessage called in"
+                " bad state " << state_;
+  next_message_ = "";
+  return next_message_;
+}
+
+P224EncryptedKeyExchange::Result P224EncryptedKeyExchange::ProcessMessage(
+    std::string_view message) {
+  if (state_ == kStateRecvHash) {
+    // This is the final state of the protocol: we are reading the peer's
+    // authentication hash and checking that it matches the one that we expect.
+    if (message.size() != sizeof(expected_authenticator_)) {
+      error_ = "peer's hash had an incorrect size";
+      return kResultFailed;
+    }
+    if (!SecureMemEqual(message.data(), expected_authenticator_,
+                        message.size())) {
+      error_ = "peer's hash had incorrect value";
+      return kResultFailed;
+    }
+    state_ = kStateDone;
+    return kResultSuccess;
+  }
+
+  if (state_ != kStateRecvDH) {
+    LOG(FATAL) << "P224EncryptedKeyExchange::ProcessMessage called in"
+                  " bad state " << state_;
+    error_ = "internal error";
+    return kResultFailed;
+  }
+
+  // Y* is the other party's masked, Diffie-Hellman value.
+  p224::Point Ystar;
+  if (!Ystar.SetFromString(message)) {
+    error_ = "failed to parse peer's masked Diffie-Hellman value";
+    return kResultFailed;
+  }
+
+  // We calculate the mask value: (N|M)**pw
+  p224::Point MNpw, minus_MNpw, Y, k;
+  p224::ScalarMult(is_server_ ? kM : kN, pw_, &MNpw);
+  p224::Negate(MNpw, &minus_MNpw);
+
+  // Y = Y* - (N|M)**pw
+  p224::Add(Ystar, minus_MNpw, &Y);
+
+  // K = Y**x_
+  p224::ScalarMult(Y, x_, &k);
+
+  // If everything worked out, then K is the same for both parties.
+  key_ = k.ToString();
+
+  std::string client_masked_dh, server_masked_dh;
+  if (is_server_) {
+    client_masked_dh = std::string(message);
+    server_masked_dh = next_message_;
+  } else {
+    client_masked_dh = next_message_;
+    server_masked_dh = std::string(message);
+  }
+
+  // Now we calculate the hashes that each side will use to prove to the other
+  // that they derived the correct value for K.
+  uint8_t client_hash[kSHA256Length], server_hash[kSHA256Length];
+  CalculateHash(kPeerTypeClient, client_masked_dh, server_masked_dh, key_,
+                client_hash);
+  CalculateHash(kPeerTypeServer, client_masked_dh, server_masked_dh, key_,
+                server_hash);
+
+  const uint8_t* my_hash = is_server_ ? server_hash : client_hash;
+  const uint8_t* their_hash = is_server_ ? client_hash : server_hash;
+
+  next_message_ =
+      std::string(reinterpret_cast<const char*>(my_hash), kSHA256Length);
+  memcpy(expected_authenticator_, their_hash, kSHA256Length);
+  state_ = kStateSendHash;
+  return kResultPending;
+}
+
+void P224EncryptedKeyExchange::CalculateHash(
+    PeerType peer_type,
+    const std::string& client_masked_dh,
+    const std::string& server_masked_dh,
+    const std::string& k,
+    uint8_t* out_digest) {
+  std::string hash_contents;
+
+  if (peer_type == kPeerTypeServer) {
+    hash_contents = "server";
+  } else {
+    hash_contents = "client";
+  }
+
+  hash_contents += client_masked_dh;
+  hash_contents += server_masked_dh;
+  hash_contents +=
+      std::string(reinterpret_cast<const char *>(pw_), sizeof(pw_));
+  hash_contents += k;
+
+  SHA256HashString(hash_contents, out_digest, kSHA256Length);
+}
+
+const std::string& P224EncryptedKeyExchange::error() const {
+  return error_;
+}
+
+const std::string& P224EncryptedKeyExchange::GetKey() const {
+  DCHECK_EQ(state_, kStateDone);
+  return GetUnverifiedKey();
+}
+
+const std::string& P224EncryptedKeyExchange::GetUnverifiedKey() const {
+  // Key is already final when state is kStateSendHash. Subsequent states are
+  // used only for verification of the key. Some users may combine verification
+  // with sending verifiable data instead of |expected_authenticator_|.
+  DCHECK_GE(state_, kStateSendHash);
+  return key_;
+}
+
+void P224EncryptedKeyExchange::SetXForTesting(const std::string& x) {
+  memset(&x_, 0, sizeof(x_));
+  memcpy(&x_, x.data(), std::min(x.size(), sizeof(x_)));
+  Init();
+}
+
+}  // namespace crypto
diff --git a/crypto/p224_spake.h b/crypto/p224_spake.h
new file mode 100644
index 0000000..ee0c427
--- /dev/null
+++ b/crypto/p224_spake.h
@@ -0,0 +1,128 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_P224_SPAKE_H_
+#define CRYPTO_P224_SPAKE_H_
+
+#include <crypto/p224.h>
+#include <crypto/sha2.h>
+#include <stdint.h>
+
+#include <string_view>
+
+#include "base/gtest_prod_util.h"
+
+namespace crypto {
+
+// P224EncryptedKeyExchange implements SPAKE2, a variant of Encrypted
+// Key Exchange. It allows two parties that have a secret common
+// password to establish a common secure key by exchanging messages
+// over an insecure channel without disclosing the password.
+//
+// The password can be low entropy as authenticating with an attacker only
+// gives the attacker a one-shot password oracle. No other information about
+// the password is leaked. (However, you must be sure to limit the number of
+// permitted authentication attempts otherwise they get many one-shot oracles.)
+//
+// The protocol requires several RTTs (actually two, but you shouldn't assume
+// that.) To use the object, call GetNextMessage() and pass that message to the
+// peer. Get a message from the peer and feed it into ProcessMessage. Then
+// examine the return value of ProcessMessage:
+//   kResultPending: Another round is required. Call GetNextMessage and repeat.
+//   kResultFailed: The authentication has failed. You can get a human readable
+//       error message by calling error().
+//   kResultSuccess: The authentication was successful.
+//
+// In each exchange, each peer always sends a message.
+class CRYPTO_EXPORT P224EncryptedKeyExchange {
+ public:
+  enum Result {
+    kResultPending,
+    kResultFailed,
+    kResultSuccess,
+  };
+
+  // PeerType's values are named client and server due to convention. But
+  // they could be called "A" and "B" as far as the protocol is concerned so
+  // long as the two parties don't both get the same label.
+  enum PeerType {
+    kPeerTypeClient,
+    kPeerTypeServer,
+  };
+
+  // peer_type: the type of the local authentication party.
+  // password: secret session password. Both parties to the
+  //     authentication must pass the same value. For the case of a
+  //     TLS connection, see RFC 5705.
+  P224EncryptedKeyExchange(PeerType peer_type,
+                           std::string_view password);
+
+  // GetNextMessage returns a byte string which must be passed to the other
+  // party in the authentication.
+  const std::string& GetNextMessage();
+
+  // ProcessMessage processes a message which must have been generated by a
+  // call to GetNextMessage() by the other party.
+  Result ProcessMessage(std::string_view message);
+
+  // In the event that ProcessMessage() returns kResultFailed, error will
+  // return a human readable error message.
+  const std::string& error() const;
+
+  // The key established as result of the key exchange. Must be called
+  // at then end after ProcessMessage() returns kResultSuccess.
+  const std::string& GetKey() const;
+
+  // The key established as result of the key exchange. Can be called after
+  // the first ProcessMessage()
+  const std::string& GetUnverifiedKey() const;
+
+ private:
+  // The authentication state machine is very simple and each party proceeds
+  // through each of these states, in order.
+  enum State {
+    kStateInitial,
+    kStateRecvDH,
+    kStateSendHash,
+    kStateRecvHash,
+    kStateDone,
+  };
+
+  FRIEND_TEST_ALL_PREFIXES(MutualAuth, ExpectedValues);
+
+  void Init();
+
+  // Sets internal random scalar. Should be used by tests only.
+  void SetXForTesting(const std::string& x);
+
+  State state_;
+  const bool is_server_;
+  // next_message_ contains a value for GetNextMessage() to return.
+  std::string next_message_;
+  std::string error_;
+
+  // CalculateHash computes the verification hash for the given peer and writes
+  // |kSHA256Length| bytes at |out_digest|.
+  void CalculateHash(PeerType peer_type,
+                     const std::string& client_masked_dh,
+                     const std::string& server_masked_dh,
+                     const std::string& k,
+                     uint8_t* out_digest);
+
+  // x_ is the secret Diffie-Hellman exponent (see paper referenced in .cc
+  // file).
+  uint8_t x_[p224::kScalarBytes];
+  // pw_ is SHA256(P(password), P(session))[:28] where P() prepends a uint32_t,
+  // big-endian length prefix (see paper referenced in .cc file).
+  uint8_t pw_[p224::kScalarBytes];
+  // expected_authenticator_ is used to store the hash value expected from the
+  // other party.
+  uint8_t expected_authenticator_[kSHA256Length];
+
+  std::string key_;
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_P224_SPAKE_H_
diff --git a/crypto/p224_spake_unittest.cc b/crypto/p224_spake_unittest.cc
new file mode 100644
index 0000000..d99dfc0
--- /dev/null
+++ b/crypto/p224_spake_unittest.cc
@@ -0,0 +1,177 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/p224_spake.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace crypto {
+
+namespace {
+
+std::string HexEncodeString(const std::string& binary_data) {
+  return base::HexEncode(binary_data.c_str(), binary_data.size());
+}
+
+bool RunExchange(P224EncryptedKeyExchange* client,
+                 P224EncryptedKeyExchange* server,
+                 bool is_password_same) {
+  for (;;) {
+    std::string client_message, server_message;
+    client_message = client->GetNextMessage();
+    server_message = server->GetNextMessage();
+
+    P224EncryptedKeyExchange::Result client_result, server_result;
+    client_result = client->ProcessMessage(server_message);
+    server_result = server->ProcessMessage(client_message);
+
+    // Check that we never hit the case where only one succeeds.
+    EXPECT_EQ(client_result == P224EncryptedKeyExchange::kResultSuccess,
+              server_result == P224EncryptedKeyExchange::kResultSuccess);
+
+    if (client_result == P224EncryptedKeyExchange::kResultFailed ||
+        server_result == P224EncryptedKeyExchange::kResultFailed) {
+      return false;
+    }
+
+    EXPECT_EQ(is_password_same,
+              client->GetUnverifiedKey() == server->GetUnverifiedKey());
+
+    if (client_result == P224EncryptedKeyExchange::kResultSuccess &&
+        server_result == P224EncryptedKeyExchange::kResultSuccess) {
+      return true;
+    }
+
+    EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, client_result);
+    EXPECT_EQ(P224EncryptedKeyExchange::kResultPending, server_result);
+  }
+}
+
+const char kPassword[] = "foo";
+
+}  // namespace
+
+TEST(MutualAuth, CorrectAuth) {
+  P224EncryptedKeyExchange client(
+      P224EncryptedKeyExchange::kPeerTypeClient, kPassword);
+  P224EncryptedKeyExchange server(
+      P224EncryptedKeyExchange::kPeerTypeServer, kPassword);
+
+  EXPECT_TRUE(RunExchange(&client, &server, true));
+  EXPECT_EQ(client.GetKey(), server.GetKey());
+}
+
+TEST(MutualAuth, IncorrectPassword) {
+  P224EncryptedKeyExchange client(
+      P224EncryptedKeyExchange::kPeerTypeClient,
+      kPassword);
+  P224EncryptedKeyExchange server(
+      P224EncryptedKeyExchange::kPeerTypeServer,
+      "wrongpassword");
+
+  EXPECT_FALSE(RunExchange(&client, &server, false));
+}
+
+TEST(MutualAuth, ExpectedValues) {
+  P224EncryptedKeyExchange client(P224EncryptedKeyExchange::kPeerTypeClient,
+                                  kPassword);
+  client.SetXForTesting("Client x");
+  P224EncryptedKeyExchange server(P224EncryptedKeyExchange::kPeerTypeServer,
+                                  kPassword);
+  server.SetXForTesting("Server x");
+
+  std::string client_message = client.GetNextMessage();
+  EXPECT_EQ(
+      "3508EF7DECC8AB9F9C439FBB0154288BBECC0A82E8448F4CF29554EB"
+      "BE9D486686226255EAD1D077C635B1A41F46AC91D7F7F32CED9EC3E0",
+      HexEncodeString(client_message));
+
+  std::string server_message = server.GetNextMessage();
+  EXPECT_EQ(
+      "A3088C18B75D2C2B107105661AEC85424777475EB29F1DDFB8C14AFB"
+      "F1603D0DF38413A00F420ACF2059E7997C935F5A957A193D09A2B584",
+      HexEncodeString(server_message));
+
+  EXPECT_EQ(P224EncryptedKeyExchange::kResultPending,
+            client.ProcessMessage(server_message));
+  EXPECT_EQ(P224EncryptedKeyExchange::kResultPending,
+            server.ProcessMessage(client_message));
+
+  EXPECT_EQ(client.GetUnverifiedKey(), server.GetUnverifiedKey());
+  // Must stay the same. External implementations should be able to pair with.
+  EXPECT_EQ(
+      "CE7CCFC435CDA4F01EC8826788B1F8B82EF7D550A34696B371096E64"
+      "C487D4FE193F7D1A6FF6820BC7F807796BA3889E8F999BBDEFC32FFA",
+      HexEncodeString(server.GetUnverifiedKey()));
+
+  EXPECT_TRUE(RunExchange(&client, &server, true));
+  EXPECT_EQ(client.GetKey(), server.GetKey());
+}
+
+TEST(MutualAuth, Fuzz) {
+  static const unsigned kIterations = 40;
+
+  for (unsigned i = 0; i < kIterations; i++) {
+    P224EncryptedKeyExchange client(
+        P224EncryptedKeyExchange::kPeerTypeClient, kPassword);
+    P224EncryptedKeyExchange server(
+        P224EncryptedKeyExchange::kPeerTypeServer, kPassword);
+
+    // We'll only be testing small values of i, but we don't want that to bias
+    // the test coverage. So we disperse the value of i by multiplying by the
+    // FNV, 32-bit prime, producing a poor-man's PRNG.
+    const uint32_t rand = i * 16777619;
+
+    for (unsigned round = 0;; round++) {
+      std::string client_message, server_message;
+      client_message = client.GetNextMessage();
+      server_message = server.GetNextMessage();
+
+      if ((rand & 1) == round) {
+        const bool server_or_client = rand & 2;
+        std::string* m = server_or_client ? &server_message : &client_message;
+        if (rand & 4) {
+          // Truncate
+          *m = m->substr(0, (i >> 3) % m->size());
+        } else {
+          // Corrupt
+          const size_t bits = m->size() * 8;
+          const size_t bit_to_corrupt = (rand >> 3) % bits;
+          const_cast<char*>(m->data())[bit_to_corrupt / 8] ^=
+              1 << (bit_to_corrupt % 8);
+        }
+      }
+
+      P224EncryptedKeyExchange::Result client_result, server_result;
+      client_result = client.ProcessMessage(server_message);
+      server_result = server.ProcessMessage(client_message);
+
+      // If we have corrupted anything, we expect the authentication to fail,
+      // although one side can succeed if we happen to corrupt the second round
+      // message to the other.
+      ASSERT_FALSE(
+          client_result == P224EncryptedKeyExchange::kResultSuccess &&
+          server_result == P224EncryptedKeyExchange::kResultSuccess);
+
+      if (client_result == P224EncryptedKeyExchange::kResultFailed ||
+          server_result == P224EncryptedKeyExchange::kResultFailed) {
+        break;
+      }
+
+      ASSERT_EQ(P224EncryptedKeyExchange::kResultPending,
+                client_result);
+      ASSERT_EQ(P224EncryptedKeyExchange::kResultPending,
+                server_result);
+    }
+  }
+}
+
+}  // namespace crypto
diff --git a/crypto/p224_unittest.cc b/crypto/p224_unittest.cc
new file mode 100644
index 0000000..e7b97a3
--- /dev/null
+++ b/crypto/p224_unittest.cc
@@ -0,0 +1,824 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "crypto/p224.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace crypto {
+
+using p224::Point;
+
+// kBasePointExternal is the P224 base point in external representation.
+static const uint8_t kBasePointExternal[56] = {
+    0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f, 0x32, 0x13, 0x90, 0xb9,
+    0x4a, 0x03, 0xc1, 0xd3, 0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
+    0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb,
+    0x4c, 0x22, 0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64,
+    0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34,
+};
+
+// TestVector represents a test of scalar multiplication of the base point.
+// |scalar| is a big-endian scalar and |affine| is the external representation
+// of g*scalar.
+struct TestVector {
+  uint8_t scalar[28];
+  uint8_t affine[28 * 2];
+};
+
+static const int kNumNISTTestVectors = 52;
+
+// kNISTTestVectors are the NIST test vectors for P224.
+static const TestVector kNISTTestVectors[kNumNISTTestVectors] = {
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x01},
+    {0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f,
+     0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3,
+     0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
+     0x11, 0x5c, 0x1d, 0x21, 0xbd, 0x37, 0x63, 0x88,
+     0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
+     0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64,
+     0x44, 0xd5, 0x81, 0x99, 0x85, 0x00, 0x7e, 0x34
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x02, },
+
+    {0x70, 0x6a, 0x46, 0xdc, 0x76, 0xdc, 0xb7, 0x67,
+     0x98, 0xe6, 0x0e, 0x6d, 0x89, 0x47, 0x47, 0x88,
+     0xd1, 0x6d, 0xc1, 0x80, 0x32, 0xd2, 0x68, 0xfd,
+     0x1a, 0x70, 0x4f, 0xa6, 0x1c, 0x2b, 0x76, 0xa7,
+     0xbc, 0x25, 0xe7, 0x70, 0x2a, 0x70, 0x4f, 0xa9,
+     0x86, 0x89, 0x28, 0x49, 0xfc, 0xa6, 0x29, 0x48,
+     0x7a, 0xcf, 0x37, 0x09, 0xd2, 0xe4, 0xe8, 0xbb,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x03, },
+    {0xdf, 0x1b, 0x1d, 0x66, 0xa5, 0x51, 0xd0, 0xd3,
+     0x1e, 0xff, 0x82, 0x25, 0x58, 0xb9, 0xd2, 0xcc,
+     0x75, 0xc2, 0x18, 0x02, 0x79, 0xfe, 0x0d, 0x08,
+     0xfd, 0x89, 0x6d, 0x04, 0xa3, 0xf7, 0xf0, 0x3c,
+     0xad, 0xd0, 0xbe, 0x44, 0x4c, 0x0a, 0xa5, 0x68,
+     0x30, 0x13, 0x0d, 0xdf, 0x77, 0xd3, 0x17, 0x34,
+     0x4e, 0x1a, 0xf3, 0x59, 0x19, 0x81, 0xa9, 0x25,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x04, },
+    {0xae, 0x99, 0xfe, 0xeb, 0xb5, 0xd2, 0x69, 0x45,
+     0xb5, 0x48, 0x92, 0x09, 0x2a, 0x8a, 0xee, 0x02,
+     0x91, 0x29, 0x30, 0xfa, 0x41, 0xcd, 0x11, 0x4e,
+     0x40, 0x44, 0x73, 0x01, 0x04, 0x82, 0x58, 0x0a,
+     0x0e, 0xc5, 0xbc, 0x47, 0xe8, 0x8b, 0xc8, 0xc3,
+     0x78, 0x63, 0x2c, 0xd1, 0x96, 0xcb, 0x3f, 0xa0,
+     0x58, 0xa7, 0x11, 0x4e, 0xb0, 0x30, 0x54, 0xc9,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x05, },
+    {0x31, 0xc4, 0x9a, 0xe7, 0x5b, 0xce, 0x78, 0x07,
+     0xcd, 0xff, 0x22, 0x05, 0x5d, 0x94, 0xee, 0x90,
+     0x21, 0xfe, 0xdb, 0xb5, 0xab, 0x51, 0xc5, 0x75,
+     0x26, 0xf0, 0x11, 0xaa, 0x27, 0xe8, 0xbf, 0xf1,
+     0x74, 0x56, 0x35, 0xec, 0x5b, 0xa0, 0xc9, 0xf1,
+     0xc2, 0xed, 0xe1, 0x54, 0x14, 0xc6, 0x50, 0x7d,
+     0x29, 0xff, 0xe3, 0x7e, 0x79, 0x0a, 0x07, 0x9b,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x06, },
+    {0x1f, 0x24, 0x83, 0xf8, 0x25, 0x72, 0x25, 0x1f,
+     0xca, 0x97, 0x5f, 0xea, 0x40, 0xdb, 0x82, 0x1d,
+     0xf8, 0xad, 0x82, 0xa3, 0xc0, 0x02, 0xee, 0x6c,
+     0x57, 0x11, 0x24, 0x08, 0x89, 0xfa, 0xf0, 0xcc,
+     0xb7, 0x50, 0xd9, 0x9b, 0x55, 0x3c, 0x57, 0x4f,
+     0xad, 0x7e, 0xcf, 0xb0, 0x43, 0x85, 0x86, 0xeb,
+     0x39, 0x52, 0xaf, 0x5b, 0x4b, 0x15, 0x3c, 0x7e,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x07, },
+    {0xdb, 0x2f, 0x6b, 0xe6, 0x30, 0xe2, 0x46, 0xa5,
+     0xcf, 0x7d, 0x99, 0xb8, 0x51, 0x94, 0xb1, 0x23,
+     0xd4, 0x87, 0xe2, 0xd4, 0x66, 0xb9, 0x4b, 0x24,
+     0xa0, 0x3c, 0x3e, 0x28, 0x0f, 0x3a, 0x30, 0x08,
+     0x54, 0x97, 0xf2, 0xf6, 0x11, 0xee, 0x25, 0x17,
+     0xb1, 0x63, 0xef, 0x8c, 0x53, 0xb7, 0x15, 0xd1,
+     0x8b, 0xb4, 0xe4, 0x80, 0x8d, 0x02, 0xb9, 0x63,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x08, },
+    {0x85, 0x8e, 0x6f, 0x9c, 0xc6, 0xc1, 0x2c, 0x31,
+     0xf5, 0xdf, 0x12, 0x4a, 0xa7, 0x77, 0x67, 0xb0,
+     0x5c, 0x8b, 0xc0, 0x21, 0xbd, 0x68, 0x3d, 0x2b,
+     0x55, 0x57, 0x15, 0x50, 0x04, 0x6d, 0xcd, 0x3e,
+     0xa5, 0xc4, 0x38, 0x98, 0xc5, 0xc5, 0xfc, 0x4f,
+     0xda, 0xc7, 0xdb, 0x39, 0xc2, 0xf0, 0x2e, 0xbe,
+     0xe4, 0xe3, 0x54, 0x1d, 0x1e, 0x78, 0x04, 0x7a,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x09, },
+    {0x2f, 0xdc, 0xcc, 0xfe, 0xe7, 0x20, 0xa7, 0x7e,
+     0xf6, 0xcb, 0x3b, 0xfb, 0xb4, 0x47, 0xf9, 0x38,
+     0x31, 0x17, 0xe3, 0xda, 0xa4, 0xa0, 0x7e, 0x36,
+     0xed, 0x15, 0xf7, 0x8d, 0x37, 0x17, 0x32, 0xe4,
+     0xf4, 0x1b, 0xf4, 0xf7, 0x88, 0x30, 0x35, 0xe6,
+     0xa7, 0x9f, 0xce, 0xdc, 0x0e, 0x19, 0x6e, 0xb0,
+     0x7b, 0x48, 0x17, 0x16, 0x97, 0x51, 0x74, 0x63,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x0a, },
+    {0xae, 0xa9, 0xe1, 0x7a, 0x30, 0x65, 0x17, 0xeb,
+     0x89, 0x15, 0x2a, 0xa7, 0x09, 0x6d, 0x2c, 0x38,
+     0x1e, 0xc8, 0x13, 0xc5, 0x1a, 0xa8, 0x80, 0xe7,
+     0xbe, 0xe2, 0xc0, 0xfd, 0x39, 0xbb, 0x30, 0xea,
+     0xb3, 0x37, 0xe0, 0xa5, 0x21, 0xb6, 0xcb, 0xa1,
+     0xab, 0xe4, 0xb2, 0xb3, 0xa3, 0xe5, 0x24, 0xc1,
+     0x4a, 0x3f, 0xe3, 0xeb, 0x11, 0x6b, 0x65, 0x5f,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x0b, },
+    {0xef, 0x53, 0xb6, 0x29, 0x4a, 0xca, 0x43, 0x1f,
+     0x0f, 0x3c, 0x22, 0xdc, 0x82, 0xeb, 0x90, 0x50,
+     0x32, 0x4f, 0x1d, 0x88, 0xd3, 0x77, 0xe7, 0x16,
+     0x44, 0x8e, 0x50, 0x7c, 0x20, 0xb5, 0x10, 0x00,
+     0x40, 0x92, 0xe9, 0x66, 0x36, 0xcf, 0xb7, 0xe3,
+     0x2e, 0xfd, 0xed, 0x82, 0x65, 0xc2, 0x66, 0xdf,
+     0xb7, 0x54, 0xfa, 0x6d, 0x64, 0x91, 0xa6, 0xda,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x0c, },
+    {0x6e, 0x31, 0xee, 0x1d, 0xc1, 0x37, 0xf8, 0x1b,
+     0x05, 0x67, 0x52, 0xe4, 0xde, 0xab, 0x14, 0x43,
+     0xa4, 0x81, 0x03, 0x3e, 0x9b, 0x4c, 0x93, 0xa3,
+     0x04, 0x4f, 0x4f, 0x7a, 0x20, 0x7d, 0xdd, 0xf0,
+     0x38, 0x5b, 0xfd, 0xea, 0xb6, 0xe9, 0xac, 0xda,
+     0x8d, 0xa0, 0x6b, 0x3b, 0xbe, 0xf2, 0x24, 0xa9,
+     0x3a, 0xb1, 0xe9, 0xe0, 0x36, 0x10, 0x9d, 0x13,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x0d, },
+    {0x34, 0xe8, 0xe1, 0x7a, 0x43, 0x0e, 0x43, 0x28,
+     0x97, 0x93, 0xc3, 0x83, 0xfa, 0xc9, 0x77, 0x42,
+     0x47, 0xb4, 0x0e, 0x9e, 0xbd, 0x33, 0x66, 0x98,
+     0x1f, 0xcf, 0xae, 0xca, 0x25, 0x28, 0x19, 0xf7,
+     0x1c, 0x7f, 0xb7, 0xfb, 0xcb, 0x15, 0x9b, 0xe3,
+     0x37, 0xd3, 0x7d, 0x33, 0x36, 0xd7, 0xfe, 0xb9,
+     0x63, 0x72, 0x4f, 0xdf, 0xb0, 0xec, 0xb7, 0x67,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x0e, },
+    {0xa5, 0x36, 0x40, 0xc8, 0x3d, 0xc2, 0x08, 0x60,
+     0x3d, 0xed, 0x83, 0xe4, 0xec, 0xf7, 0x58, 0xf2,
+     0x4c, 0x35, 0x7d, 0x7c, 0xf4, 0x80, 0x88, 0xb2,
+     0xce, 0x01, 0xe9, 0xfa, 0xd5, 0x81, 0x4c, 0xd7,
+     0x24, 0x19, 0x9c, 0x4a, 0x5b, 0x97, 0x4a, 0x43,
+     0x68, 0x5f, 0xbf, 0x5b, 0x8b, 0xac, 0x69, 0x45,
+     0x9c, 0x94, 0x69, 0xbc, 0x8f, 0x23, 0xcc, 0xaf,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x0f, },
+    {0xba, 0xa4, 0xd8, 0x63, 0x55, 0x11, 0xa7, 0xd2,
+     0x88, 0xae, 0xbe, 0xed, 0xd1, 0x2c, 0xe5, 0x29,
+     0xff, 0x10, 0x2c, 0x91, 0xf9, 0x7f, 0x86, 0x7e,
+     0x21, 0x91, 0x6b, 0xf9, 0x97, 0x9a, 0x5f, 0x47,
+     0x59, 0xf8, 0x0f, 0x4f, 0xb4, 0xec, 0x2e, 0x34,
+     0xf5, 0x56, 0x6d, 0x59, 0x56, 0x80, 0xa1, 0x17,
+     0x35, 0xe7, 0xb6, 0x10, 0x46, 0x12, 0x79, 0x89,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x10, },
+    {0x0b, 0x6e, 0xc4, 0xfe, 0x17, 0x77, 0x38, 0x24,
+     0x04, 0xef, 0x67, 0x99, 0x97, 0xba, 0x8d, 0x1c,
+     0xc5, 0xcd, 0x8e, 0x85, 0x34, 0x92, 0x59, 0xf5,
+     0x90, 0xc4, 0xc6, 0x6d, 0x33, 0x99, 0xd4, 0x64,
+     0x34, 0x59, 0x06, 0xb1, 0x1b, 0x00, 0xe3, 0x63,
+     0xef, 0x42, 0x92, 0x21, 0xf2, 0xec, 0x72, 0x0d,
+     0x2f, 0x66, 0x5d, 0x7d, 0xea, 0xd5, 0xb4, 0x82,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x11, },
+    {0xb8, 0x35, 0x7c, 0x3a, 0x6c, 0xee, 0xf2, 0x88,
+     0x31, 0x0e, 0x17, 0xb8, 0xbf, 0xef, 0xf9, 0x20,
+     0x08, 0x46, 0xca, 0x8c, 0x19, 0x42, 0x49, 0x7c,
+     0x48, 0x44, 0x03, 0xbc, 0xff, 0x14, 0x9e, 0xfa,
+     0x66, 0x06, 0xa6, 0xbd, 0x20, 0xef, 0x7d, 0x1b,
+     0x06, 0xbd, 0x92, 0xf6, 0x90, 0x46, 0x39, 0xdc,
+     0xe5, 0x17, 0x4d, 0xb6, 0xcc, 0x55, 0x4a, 0x26,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x12, },
+    {0xc9, 0xff, 0x61, 0xb0, 0x40, 0x87, 0x4c, 0x05,
+     0x68, 0x47, 0x92, 0x16, 0x82, 0x4a, 0x15, 0xea,
+     0xb1, 0xa8, 0x38, 0xa7, 0x97, 0xd1, 0x89, 0x74,
+     0x62, 0x26, 0xe4, 0xcc, 0xea, 0x98, 0xd6, 0x0e,
+     0x5f, 0xfc, 0x9b, 0x8f, 0xcf, 0x99, 0x9f, 0xab,
+     0x1d, 0xf7, 0xe7, 0xef, 0x70, 0x84, 0xf2, 0x0d,
+     0xdb, 0x61, 0xbb, 0x04, 0x5a, 0x6c, 0xe0, 0x02,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x13, },
+    {0xa1, 0xe8, 0x1c, 0x04, 0xf3, 0x0c, 0xe2, 0x01,
+     0xc7, 0xc9, 0xac, 0xe7, 0x85, 0xed, 0x44, 0xcc,
+     0x33, 0xb4, 0x55, 0xa0, 0x22, 0xf2, 0xac, 0xdb,
+     0xc6, 0xca, 0xe8, 0x3c, 0xdc, 0xf1, 0xf6, 0xc3,
+     0xdb, 0x09, 0xc7, 0x0a, 0xcc, 0x25, 0x39, 0x1d,
+     0x49, 0x2f, 0xe2, 0x5b, 0x4a, 0x18, 0x0b, 0xab,
+     0xd6, 0xce, 0xa3, 0x56, 0xc0, 0x47, 0x19, 0xcd,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x14, },
+    {0xfc, 0xc7, 0xf2, 0xb4, 0x5d, 0xf1, 0xcd, 0x5a,
+     0x3c, 0x0c, 0x07, 0x31, 0xca, 0x47, 0xa8, 0xaf,
+     0x75, 0xcf, 0xb0, 0x34, 0x7e, 0x83, 0x54, 0xee,
+     0xfe, 0x78, 0x24, 0x55, 0x0d, 0x5d, 0x71, 0x10,
+     0x27, 0x4c, 0xba, 0x7c, 0xde, 0xe9, 0x0e, 0x1a,
+     0x8b, 0x0d, 0x39, 0x4c, 0x37, 0x6a, 0x55, 0x73,
+     0xdb, 0x6b, 0xe0, 0xbf, 0x27, 0x47, 0xf5, 0x30,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x01, 0x8e, 0xbb, 0xb9,
+     0x5e, 0xed, 0x0e, 0x13, },
+    {0x61, 0xf0, 0x77, 0xc6, 0xf6, 0x2e, 0xd8, 0x02,
+     0xda, 0xd7, 0xc2, 0xf3, 0x8f, 0x5c, 0x67, 0xf2,
+     0xcc, 0x45, 0x36, 0x01, 0xe6, 0x1b, 0xd0, 0x76,
+     0xbb, 0x46, 0x17, 0x9e, 0x22, 0x72, 0xf9, 0xe9,
+     0xf5, 0x93, 0x3e, 0x70, 0x38, 0x8e, 0xe6, 0x52,
+     0x51, 0x34, 0x43, 0xb5, 0xe2, 0x89, 0xdd, 0x13,
+     0x5d, 0xcc, 0x0d, 0x02, 0x99, 0xb2, 0x25, 0xe4,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x9d, 0x89,
+     0x3d, 0x4c, 0xdd, 0x74, 0x72, 0x46, 0xcd, 0xca,
+     0x43, 0x59, 0x0e, 0x13, },
+    {0x02, 0x98, 0x95, 0xf0, 0xaf, 0x49, 0x6b, 0xfc,
+     0x62, 0xb6, 0xef, 0x8d, 0x8a, 0x65, 0xc8, 0x8c,
+     0x61, 0x39, 0x49, 0xb0, 0x36, 0x68, 0xaa, 0xb4,
+     0xf0, 0x42, 0x9e, 0x35, 0x3e, 0xa6, 0xe5, 0x3f,
+     0x9a, 0x84, 0x1f, 0x20, 0x19, 0xec, 0x24, 0xbd,
+     0xe1, 0xa7, 0x56, 0x77, 0xaa, 0x9b, 0x59, 0x02,
+     0xe6, 0x10, 0x81, 0xc0, 0x10, 0x64, 0xde, 0x93,
+    },
+  },
+  {
+    {0x41, 0xff, 0xc1, 0xff, 0xff, 0xfe, 0x01, 0xff,
+     0xfc, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x07, 0xc0,
+     0x01, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xf0, 0x7f,
+     0xfe, 0x00, 0x07, 0xc0, },
+    {0xab, 0x68, 0x99, 0x30, 0xbc, 0xae, 0x4a, 0x4a,
+     0xa5, 0xf5, 0xcb, 0x08, 0x5e, 0x82, 0x3e, 0x8a,
+     0xe3, 0x0f, 0xd3, 0x65, 0xeb, 0x1d, 0xa4, 0xab,
+     0xa9, 0xcf, 0x03, 0x79, 0x33, 0x45, 0xa1, 0x21,
+     0xbb, 0xd2, 0x33, 0x54, 0x8a, 0xf0, 0xd2, 0x10,
+     0x65, 0x4e, 0xb4, 0x0b, 0xab, 0x78, 0x8a, 0x03,
+     0x66, 0x64, 0x19, 0xbe, 0x6f, 0xbd, 0x34, 0xe7,
+    },
+  },
+  {
+    {0x7f, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xc0, 0x03,
+     0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x00, 0x00,
+     0x00, 0x00, 0x07, 0x00, 0x00, 0x10, 0x00, 0x00,
+     0x00, 0x0e, 0x00, 0xff, },
+    {0xbd, 0xb6, 0xa8, 0x81, 0x7c, 0x1f, 0x89, 0xda,
+     0x1c, 0x2f, 0x3d, 0xd8, 0xe9, 0x7f, 0xeb, 0x44,
+     0x94, 0xf2, 0xed, 0x30, 0x2a, 0x4c, 0xe2, 0xbc,
+     0x7f, 0x5f, 0x40, 0x25, 0x4c, 0x70, 0x20, 0xd5,
+     0x7c, 0x00, 0x41, 0x18, 0x89, 0x46, 0x2d, 0x77,
+     0xa5, 0x43, 0x8b, 0xb4, 0xe9, 0x7d, 0x17, 0x77,
+     0x00, 0xbf, 0x72, 0x43, 0xa0, 0x7f, 0x16, 0x80,
+    },
+  },
+  {
+    {0x7f, 0xff, 0xff, 0x04, 0x00, 0x00, 0x00, 0x00,
+     0xff, 0xff, 0xf0, 0x1f, 0xff, 0xf8, 0xff, 0xff,
+     0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00,
+     0x00, 0x0f, 0xff, 0xff, },
+    {0xd5, 0x8b, 0x61, 0xaa, 0x41, 0xc3, 0x2d, 0xd5,
+     0xeb, 0xa4, 0x62, 0x64, 0x7d, 0xba, 0x75, 0xc5,
+     0xd6, 0x7c, 0x83, 0x60, 0x6c, 0x0a, 0xf2, 0xbd,
+     0x92, 0x84, 0x46, 0xa9, 0xd2, 0x4b, 0xa6, 0xa8,
+     0x37, 0xbe, 0x04, 0x60, 0xdd, 0x10, 0x7a, 0xe7,
+     0x77, 0x25, 0x69, 0x6d, 0x21, 0x14, 0x46, 0xc5,
+     0x60, 0x9b, 0x45, 0x95, 0x97, 0x6b, 0x16, 0xbd,
+    },
+  },
+  {
+    {0x7f, 0xff, 0xff, 0xc0, 0x00, 0xff, 0xfe, 0x3f,
+     0xff, 0xfc, 0x10, 0x00, 0x00, 0x20, 0x00, 0x3f,
+     0xff, 0xff, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00,
+     0x3f, 0xff, 0xff, 0xff, },
+    {0xdc, 0x9f, 0xa7, 0x79, 0x78, 0xa0, 0x05, 0x51,
+     0x09, 0x80, 0xe9, 0x29, 0xa1, 0x48, 0x5f, 0x63,
+     0x71, 0x6d, 0xf6, 0x95, 0xd7, 0xa0, 0xc1, 0x8b,
+     0xb5, 0x18, 0xdf, 0x03, 0xed, 0xe2, 0xb0, 0x16,
+     0xf2, 0xdd, 0xff, 0xc2, 0xa8, 0xc0, 0x15, 0xb1,
+     0x34, 0x92, 0x82, 0x75, 0xce, 0x09, 0xe5, 0x66,
+     0x1b, 0x7a, 0xb1, 0x4c, 0xe0, 0xd1, 0xd4, 0x03,
+    },
+  },
+  {
+    {0x70, 0x01, 0xf0, 0x00, 0x1c, 0x00, 0x01, 0xc0,
+     0x00, 0x00, 0x1f, 0xff, 0xff, 0xfc, 0x00, 0x00,
+     0x1f, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xc0, 0x00,
+     0x00, 0x01, 0xfc, 0x00, },
+    {0x49, 0x9d, 0x8b, 0x28, 0x29, 0xcf, 0xb8, 0x79,
+     0xc9, 0x01, 0xf7, 0xd8, 0x5d, 0x35, 0x70, 0x45,
+     0xed, 0xab, 0x55, 0x02, 0x88, 0x24, 0xd0, 0xf0,
+     0x5b, 0xa2, 0x79, 0xba, 0xbf, 0x92, 0x95, 0x37,
+     0xb0, 0x6e, 0x40, 0x15, 0x91, 0x96, 0x39, 0xd9,
+     0x4f, 0x57, 0x83, 0x8f, 0xa3, 0x3f, 0xc3, 0xd9,
+     0x52, 0x59, 0x8d, 0xcd, 0xbb, 0x44, 0xd6, 0x38,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00,
+     0x00, 0xff, 0xf0, 0x30, 0x00, 0x1f, 0x00, 0x00,
+     0xff, 0xff, 0xf0, 0x00, 0x00, 0x38, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x02, },
+    {0x82, 0x46, 0xc9, 0x99, 0x13, 0x71, 0x86, 0x63,
+     0x2c, 0x5f, 0x9e, 0xdd, 0xf3, 0xb1, 0xb0, 0xe1,
+     0x76, 0x4c, 0x5e, 0x8b, 0xd0, 0xe0, 0xd8, 0xa5,
+     0x54, 0xb9, 0xcb, 0x77, 0xe8, 0x0e, 0xd8, 0x66,
+     0x0b, 0xc1, 0xcb, 0x17, 0xac, 0x7d, 0x84, 0x5b,
+     0xe4, 0x0a, 0x7a, 0x02, 0x2d, 0x33, 0x06, 0xf1,
+     0x16, 0xae, 0x9f, 0x81, 0xfe, 0xa6, 0x59, 0x47,
+    },
+  },
+  {
+    {0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x07, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0xff, 0xfe, 0x08, 0x00, 0x00, 0x1f,
+     0xf0, 0x00, 0x1f, 0xff, },
+    {0x66, 0x70, 0xc2, 0x0a, 0xfc, 0xce, 0xae, 0xa6,
+     0x72, 0xc9, 0x7f, 0x75, 0xe2, 0xe9, 0xdd, 0x5c,
+     0x84, 0x60, 0xe5, 0x4b, 0xb3, 0x85, 0x38, 0xeb,
+     0xb4, 0xbd, 0x30, 0xeb, 0xf2, 0x80, 0xd8, 0x00,
+     0x8d, 0x07, 0xa4, 0xca, 0xf5, 0x42, 0x71, 0xf9,
+     0x93, 0x52, 0x7d, 0x46, 0xff, 0x3f, 0xf4, 0x6f,
+     0xd1, 0x19, 0x0a, 0x3f, 0x1f, 0xaa, 0x4f, 0x74,
+    },
+  },
+  {
+    {0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xc0, 0x00, 0x07, 0xff, 0xff, 0xe0, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xff,
+     0xff, 0xff, 0xff, 0xff, },
+    {0x00, 0x0e, 0xca, 0x93, 0x42, 0x47, 0x42, 0x5c,
+     0xfd, 0x94, 0x9b, 0x79, 0x5c, 0xb5, 0xce, 0x1e,
+     0xff, 0x40, 0x15, 0x50, 0x38, 0x6e, 0x28, 0xd1,
+     0xa4, 0xc5, 0xa8, 0xeb, 0xd4, 0xc0, 0x10, 0x40,
+     0xdb, 0xa1, 0x96, 0x28, 0x93, 0x1b, 0xc8, 0x85,
+     0x53, 0x70, 0x31, 0x7c, 0x72, 0x2c, 0xbd, 0x9c,
+     0xa6, 0x15, 0x69, 0x85, 0xf1, 0xc2, 0xe9, 0xce,
+    },
+  },
+  {
+    {0x7f, 0xff, 0xfc, 0x03, 0xff, 0x80, 0x7f, 0xff,
+     0xe0, 0x00, 0x1f, 0xff, 0xff, 0x80, 0x0f, 0xff,
+     0x80, 0x00, 0x01, 0xff, 0xff, 0x00, 0x01, 0xff,
+     0xff, 0xfe, 0x00, 0x1f, },
+    {0xef, 0x35, 0x3b, 0xf5, 0xc7, 0x3c, 0xd5, 0x51,
+     0xb9, 0x6d, 0x59, 0x6f, 0xbc, 0x9a, 0x67, 0xf1,
+     0x6d, 0x61, 0xdd, 0x9f, 0xe5, 0x6a, 0xf1, 0x9d,
+     0xe1, 0xfb, 0xa9, 0xcd, 0x21, 0x77, 0x1b, 0x9c,
+     0xdc, 0xe3, 0xe8, 0x43, 0x0c, 0x09, 0xb3, 0x83,
+     0x8b, 0xe7, 0x0b, 0x48, 0xc2, 0x1e, 0x15, 0xbc,
+     0x09, 0xee, 0x1f, 0x2d, 0x79, 0x45, 0xb9, 0x1f,
+    },
+  },
+  {
+    {0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x7f, 0xff,
+     0xff, 0xff, 0x01, 0xff, 0xfe, 0x03, 0xff, 0xfe,
+     0x40, 0x00, 0x38, 0x00, 0x07, 0xe0, 0x00, 0x3f,
+     0xfe, 0x00, 0x00, 0x00, },
+    {0x40, 0x36, 0x05, 0x2a, 0x30, 0x91, 0xeb, 0x48,
+     0x10, 0x46, 0xad, 0x32, 0x89, 0xc9, 0x5d, 0x3a,
+     0xc9, 0x05, 0xca, 0x00, 0x23, 0xde, 0x2c, 0x03,
+     0xec, 0xd4, 0x51, 0xcf, 0xd7, 0x68, 0x16, 0x5a,
+     0x38, 0xa2, 0xb9, 0x6f, 0x81, 0x25, 0x86, 0xa9,
+     0xd5, 0x9d, 0x41, 0x36, 0x03, 0x5d, 0x9c, 0x85,
+     0x3a, 0x5b, 0xf2, 0xe1, 0xc8, 0x6a, 0x49, 0x93,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x29, },
+    {0xfc, 0xc7, 0xf2, 0xb4, 0x5d, 0xf1, 0xcd, 0x5a,
+     0x3c, 0x0c, 0x07, 0x31, 0xca, 0x47, 0xa8, 0xaf,
+     0x75, 0xcf, 0xb0, 0x34, 0x7e, 0x83, 0x54, 0xee,
+     0xfe, 0x78, 0x24, 0x55, 0xf2, 0xa2, 0x8e, 0xef,
+     0xd8, 0xb3, 0x45, 0x83, 0x21, 0x16, 0xf1, 0xe5,
+     0x74, 0xf2, 0xc6, 0xb2, 0xc8, 0x95, 0xaa, 0x8c,
+     0x24, 0x94, 0x1f, 0x40, 0xd8, 0xb8, 0x0a, 0xd1,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x2a, },
+    {0xa1, 0xe8, 0x1c, 0x04, 0xf3, 0x0c, 0xe2, 0x01,
+     0xc7, 0xc9, 0xac, 0xe7, 0x85, 0xed, 0x44, 0xcc,
+     0x33, 0xb4, 0x55, 0xa0, 0x22, 0xf2, 0xac, 0xdb,
+     0xc6, 0xca, 0xe8, 0x3c, 0x23, 0x0e, 0x09, 0x3c,
+     0x24, 0xf6, 0x38, 0xf5, 0x33, 0xda, 0xc6, 0xe2,
+     0xb6, 0xd0, 0x1d, 0xa3, 0xb5, 0xe7, 0xf4, 0x54,
+     0x29, 0x31, 0x5c, 0xa9, 0x3f, 0xb8, 0xe6, 0x34,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x2b, },
+    {0xc9, 0xff, 0x61, 0xb0, 0x40, 0x87, 0x4c, 0x05,
+     0x68, 0x47, 0x92, 0x16, 0x82, 0x4a, 0x15, 0xea,
+     0xb1, 0xa8, 0x38, 0xa7, 0x97, 0xd1, 0x89, 0x74,
+     0x62, 0x26, 0xe4, 0xcc, 0x15, 0x67, 0x29, 0xf1,
+     0xa0, 0x03, 0x64, 0x70, 0x30, 0x66, 0x60, 0x54,
+     0xe2, 0x08, 0x18, 0x0f, 0x8f, 0x7b, 0x0d, 0xf2,
+     0x24, 0x9e, 0x44, 0xfb, 0xa5, 0x93, 0x1f, 0xff,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x2c, },
+    {0xb8, 0x35, 0x7c, 0x3a, 0x6c, 0xee, 0xf2, 0x88,
+     0x31, 0x0e, 0x17, 0xb8, 0xbf, 0xef, 0xf9, 0x20,
+     0x08, 0x46, 0xca, 0x8c, 0x19, 0x42, 0x49, 0x7c,
+     0x48, 0x44, 0x03, 0xbc, 0x00, 0xeb, 0x61, 0x05,
+     0x99, 0xf9, 0x59, 0x42, 0xdf, 0x10, 0x82, 0xe4,
+     0xf9, 0x42, 0x6d, 0x08, 0x6f, 0xb9, 0xc6, 0x23,
+     0x1a, 0xe8, 0xb2, 0x49, 0x33, 0xaa, 0xb5, 0xdb,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x2d, },
+    {0x0b, 0x6e, 0xc4, 0xfe, 0x17, 0x77, 0x38, 0x24,
+     0x04, 0xef, 0x67, 0x99, 0x97, 0xba, 0x8d, 0x1c,
+     0xc5, 0xcd, 0x8e, 0x85, 0x34, 0x92, 0x59, 0xf5,
+     0x90, 0xc4, 0xc6, 0x6d, 0xcc, 0x66, 0x2b, 0x9b,
+     0xcb, 0xa6, 0xf9, 0x4e, 0xe4, 0xff, 0x1c, 0x9c,
+     0x10, 0xbd, 0x6d, 0xdd, 0x0d, 0x13, 0x8d, 0xf2,
+     0xd0, 0x99, 0xa2, 0x82, 0x15, 0x2a, 0x4b, 0x7f,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x2e, },
+    {0xba, 0xa4, 0xd8, 0x63, 0x55, 0x11, 0xa7, 0xd2,
+     0x88, 0xae, 0xbe, 0xed, 0xd1, 0x2c, 0xe5, 0x29,
+     0xff, 0x10, 0x2c, 0x91, 0xf9, 0x7f, 0x86, 0x7e,
+     0x21, 0x91, 0x6b, 0xf9, 0x68, 0x65, 0xa0, 0xb8,
+     0xa6, 0x07, 0xf0, 0xb0, 0x4b, 0x13, 0xd1, 0xcb,
+     0x0a, 0xa9, 0x92, 0xa5, 0xa9, 0x7f, 0x5e, 0xe8,
+     0xca, 0x18, 0x49, 0xef, 0xb9, 0xed, 0x86, 0x78,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x2f, },
+    {0xa5, 0x36, 0x40, 0xc8, 0x3d, 0xc2, 0x08, 0x60,
+     0x3d, 0xed, 0x83, 0xe4, 0xec, 0xf7, 0x58, 0xf2,
+     0x4c, 0x35, 0x7d, 0x7c, 0xf4, 0x80, 0x88, 0xb2,
+     0xce, 0x01, 0xe9, 0xfa, 0x2a, 0x7e, 0xb3, 0x28,
+     0xdb, 0xe6, 0x63, 0xb5, 0xa4, 0x68, 0xb5, 0xbc,
+     0x97, 0xa0, 0x40, 0xa3, 0x74, 0x53, 0x96, 0xba,
+     0x63, 0x6b, 0x96, 0x43, 0x70, 0xdc, 0x33, 0x52,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x30, },
+    {0x34, 0xe8, 0xe1, 0x7a, 0x43, 0x0e, 0x43, 0x28,
+     0x97, 0x93, 0xc3, 0x83, 0xfa, 0xc9, 0x77, 0x42,
+     0x47, 0xb4, 0x0e, 0x9e, 0xbd, 0x33, 0x66, 0x98,
+     0x1f, 0xcf, 0xae, 0xca, 0xda, 0xd7, 0xe6, 0x08,
+     0xe3, 0x80, 0x48, 0x04, 0x34, 0xea, 0x64, 0x1c,
+     0xc8, 0x2c, 0x82, 0xcb, 0xc9, 0x28, 0x01, 0x46,
+     0x9c, 0x8d, 0xb0, 0x20, 0x4f, 0x13, 0x48, 0x9a,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x31, },
+    {0x6e, 0x31, 0xee, 0x1d, 0xc1, 0x37, 0xf8, 0x1b,
+     0x05, 0x67, 0x52, 0xe4, 0xde, 0xab, 0x14, 0x43,
+     0xa4, 0x81, 0x03, 0x3e, 0x9b, 0x4c, 0x93, 0xa3,
+     0x04, 0x4f, 0x4f, 0x7a, 0xdf, 0x82, 0x22, 0x0f,
+     0xc7, 0xa4, 0x02, 0x15, 0x49, 0x16, 0x53, 0x25,
+     0x72, 0x5f, 0x94, 0xc3, 0x41, 0x0d, 0xdb, 0x56,
+     0xc5, 0x4e, 0x16, 0x1f, 0xc9, 0xef, 0x62, 0xee,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x32, },
+    {0xef, 0x53, 0xb6, 0x29, 0x4a, 0xca, 0x43, 0x1f,
+     0x0f, 0x3c, 0x22, 0xdc, 0x82, 0xeb, 0x90, 0x50,
+     0x32, 0x4f, 0x1d, 0x88, 0xd3, 0x77, 0xe7, 0x16,
+     0x44, 0x8e, 0x50, 0x7c, 0xdf, 0x4a, 0xef, 0xff,
+     0xbf, 0x6d, 0x16, 0x99, 0xc9, 0x30, 0x48, 0x1c,
+     0xd1, 0x02, 0x12, 0x7c, 0x9a, 0x3d, 0x99, 0x20,
+     0x48, 0xab, 0x05, 0x92, 0x9b, 0x6e, 0x59, 0x27,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x33, },
+    {0xae, 0xa9, 0xe1, 0x7a, 0x30, 0x65, 0x17, 0xeb,
+     0x89, 0x15, 0x2a, 0xa7, 0x09, 0x6d, 0x2c, 0x38,
+     0x1e, 0xc8, 0x13, 0xc5, 0x1a, 0xa8, 0x80, 0xe7,
+     0xbe, 0xe2, 0xc0, 0xfd, 0xc6, 0x44, 0xcf, 0x15,
+     0x4c, 0xc8, 0x1f, 0x5a, 0xde, 0x49, 0x34, 0x5e,
+     0x54, 0x1b, 0x4d, 0x4b, 0x5c, 0x1a, 0xdb, 0x3e,
+     0xb5, 0xc0, 0x1c, 0x14, 0xee, 0x94, 0x9a, 0xa2,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x34, },
+    {0x2f, 0xdc, 0xcc, 0xfe, 0xe7, 0x20, 0xa7, 0x7e,
+     0xf6, 0xcb, 0x3b, 0xfb, 0xb4, 0x47, 0xf9, 0x38,
+     0x31, 0x17, 0xe3, 0xda, 0xa4, 0xa0, 0x7e, 0x36,
+     0xed, 0x15, 0xf7, 0x8d, 0xc8, 0xe8, 0xcd, 0x1b,
+     0x0b, 0xe4, 0x0b, 0x08, 0x77, 0xcf, 0xca, 0x19,
+     0x58, 0x60, 0x31, 0x22, 0xf1, 0xe6, 0x91, 0x4f,
+     0x84, 0xb7, 0xe8, 0xe9, 0x68, 0xae, 0x8b, 0x9e,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x35, },
+    {0x85, 0x8e, 0x6f, 0x9c, 0xc6, 0xc1, 0x2c, 0x31,
+     0xf5, 0xdf, 0x12, 0x4a, 0xa7, 0x77, 0x67, 0xb0,
+     0x5c, 0x8b, 0xc0, 0x21, 0xbd, 0x68, 0x3d, 0x2b,
+     0x55, 0x57, 0x15, 0x50, 0xfb, 0x92, 0x32, 0xc1,
+     0x5a, 0x3b, 0xc7, 0x67, 0x3a, 0x3a, 0x03, 0xb0,
+     0x25, 0x38, 0x24, 0xc5, 0x3d, 0x0f, 0xd1, 0x41,
+     0x1b, 0x1c, 0xab, 0xe2, 0xe1, 0x87, 0xfb, 0x87,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x36, },
+    {0xdb, 0x2f, 0x6b, 0xe6, 0x30, 0xe2, 0x46, 0xa5,
+     0xcf, 0x7d, 0x99, 0xb8, 0x51, 0x94, 0xb1, 0x23,
+     0xd4, 0x87, 0xe2, 0xd4, 0x66, 0xb9, 0x4b, 0x24,
+     0xa0, 0x3c, 0x3e, 0x28, 0xf0, 0xc5, 0xcf, 0xf7,
+     0xab, 0x68, 0x0d, 0x09, 0xee, 0x11, 0xda, 0xe8,
+     0x4e, 0x9c, 0x10, 0x72, 0xac, 0x48, 0xea, 0x2e,
+     0x74, 0x4b, 0x1b, 0x7f, 0x72, 0xfd, 0x46, 0x9e,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x37, },
+    {0x1f, 0x24, 0x83, 0xf8, 0x25, 0x72, 0x25, 0x1f,
+     0xca, 0x97, 0x5f, 0xea, 0x40, 0xdb, 0x82, 0x1d,
+     0xf8, 0xad, 0x82, 0xa3, 0xc0, 0x02, 0xee, 0x6c,
+     0x57, 0x11, 0x24, 0x08, 0x76, 0x05, 0x0f, 0x33,
+     0x48, 0xaf, 0x26, 0x64, 0xaa, 0xc3, 0xa8, 0xb0,
+     0x52, 0x81, 0x30, 0x4e, 0xbc, 0x7a, 0x79, 0x14,
+     0xc6, 0xad, 0x50, 0xa4, 0xb4, 0xea, 0xc3, 0x83,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x38, },
+    {0x31, 0xc4, 0x9a, 0xe7, 0x5b, 0xce, 0x78, 0x07,
+     0xcd, 0xff, 0x22, 0x05, 0x5d, 0x94, 0xee, 0x90,
+     0x21, 0xfe, 0xdb, 0xb5, 0xab, 0x51, 0xc5, 0x75,
+     0x26, 0xf0, 0x11, 0xaa, 0xd8, 0x17, 0x40, 0x0e,
+     0x8b, 0xa9, 0xca, 0x13, 0xa4, 0x5f, 0x36, 0x0e,
+     0x3d, 0x12, 0x1e, 0xaa, 0xeb, 0x39, 0xaf, 0x82,
+     0xd6, 0x00, 0x1c, 0x81, 0x86, 0xf5, 0xf8, 0x66,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x39, },
+    {0xae, 0x99, 0xfe, 0xeb, 0xb5, 0xd2, 0x69, 0x45,
+     0xb5, 0x48, 0x92, 0x09, 0x2a, 0x8a, 0xee, 0x02,
+     0x91, 0x29, 0x30, 0xfa, 0x41, 0xcd, 0x11, 0x4e,
+     0x40, 0x44, 0x73, 0x01, 0xfb, 0x7d, 0xa7, 0xf5,
+     0xf1, 0x3a, 0x43, 0xb8, 0x17, 0x74, 0x37, 0x3c,
+     0x87, 0x9c, 0xd3, 0x2d, 0x69, 0x34, 0xc0, 0x5f,
+     0xa7, 0x58, 0xee, 0xb1, 0x4f, 0xcf, 0xab, 0x38,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x3a, },
+    {0xdf, 0x1b, 0x1d, 0x66, 0xa5, 0x51, 0xd0, 0xd3,
+     0x1e, 0xff, 0x82, 0x25, 0x58, 0xb9, 0xd2, 0xcc,
+     0x75, 0xc2, 0x18, 0x02, 0x79, 0xfe, 0x0d, 0x08,
+     0xfd, 0x89, 0x6d, 0x04, 0x5c, 0x08, 0x0f, 0xc3,
+     0x52, 0x2f, 0x41, 0xbb, 0xb3, 0xf5, 0x5a, 0x97,
+     0xcf, 0xec, 0xf2, 0x1f, 0x88, 0x2c, 0xe8, 0xcb,
+     0xb1, 0xe5, 0x0c, 0xa6, 0xe6, 0x7e, 0x56, 0xdc,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x3b, },
+    {0x70, 0x6a, 0x46, 0xdc, 0x76, 0xdc, 0xb7, 0x67,
+     0x98, 0xe6, 0x0e, 0x6d, 0x89, 0x47, 0x47, 0x88,
+     0xd1, 0x6d, 0xc1, 0x80, 0x32, 0xd2, 0x68, 0xfd,
+     0x1a, 0x70, 0x4f, 0xa6, 0xe3, 0xd4, 0x89, 0x58,
+     0x43, 0xda, 0x18, 0x8f, 0xd5, 0x8f, 0xb0, 0x56,
+     0x79, 0x76, 0xd7, 0xb5, 0x03, 0x59, 0xd6, 0xb7,
+     0x85, 0x30, 0xc8, 0xf6, 0x2d, 0x1b, 0x17, 0x46,
+    },
+  },
+  {
+    {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x16, 0xa2,
+     0xe0, 0xb8, 0xf0, 0x3e, 0x13, 0xdd, 0x29, 0x45,
+     0x5c, 0x5c, 0x2a, 0x3c, },
+    {0xb7, 0x0e, 0x0c, 0xbd, 0x6b, 0xb4, 0xbf, 0x7f,
+     0x32, 0x13, 0x90, 0xb9, 0x4a, 0x03, 0xc1, 0xd3,
+     0x56, 0xc2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xd6,
+     0x11, 0x5c, 0x1d, 0x21, 0x42, 0xc8, 0x9c, 0x77,
+     0x4a, 0x08, 0xdc, 0x04, 0xb3, 0xdd, 0x20, 0x19,
+     0x32, 0xbc, 0x8a, 0x5e, 0xa5, 0xf8, 0xb8, 0x9b,
+     0xbb, 0x2a, 0x7e, 0x66, 0x7a, 0xff, 0x81, 0xcd,
+    },
+  },
+};
+
+TEST(P224, ExternalToInternalAndBack) {
+  Point point;
+
+  EXPECT_TRUE(point.SetFromString(std::string_view(
+      reinterpret_cast<const char *>(kBasePointExternal),
+      sizeof(kBasePointExternal))));
+
+  const std::string external = point.ToString();
+
+  ASSERT_EQ(external.size(), 56u);
+  EXPECT_TRUE(memcmp(external.data(), kBasePointExternal,
+                     sizeof(kBasePointExternal)) == 0);
+}
+
+TEST(P224, ScalarBaseMult) {
+  Point point;
+
+  for (size_t i = 0; i < arraysize(kNISTTestVectors); i++) {
+    p224::ScalarBaseMult(kNISTTestVectors[i].scalar, &point);
+    const std::string external = point.ToString();
+    ASSERT_EQ(external.size(), 56u);
+    EXPECT_TRUE(memcmp(external.data(), kNISTTestVectors[i].affine,
+                       external.size()) == 0);
+  }
+}
+
+TEST(P224, Addition) {
+  Point a, b, minus_b, sum, a_again;
+
+  ASSERT_TRUE(a.SetFromString(std::string_view(
+      reinterpret_cast<const char *>(kNISTTestVectors[10].affine), 56)));
+  ASSERT_TRUE(b.SetFromString(std::string_view(
+      reinterpret_cast<const char *>(kNISTTestVectors[11].affine), 56)));
+
+  p224::Negate(b, &minus_b);
+  p224::Add(a, b, &sum);
+  EXPECT_TRUE(memcmp(&sum, &a, sizeof(sum)) != 0);
+  p224::Add(minus_b, sum, &a_again);
+  EXPECT_TRUE(a_again.ToString() == a.ToString());
+}
+
+TEST(P224, Infinity) {
+  char zeros[56];
+  memset(zeros, 0, sizeof(zeros));
+
+  // Test that x^0 = ∞.
+  Point a;
+  p224::ScalarBaseMult(reinterpret_cast<const uint8_t*>(zeros), &a);
+  EXPECT_TRUE(memcmp(zeros, a.ToString().data(), sizeof(zeros)) == 0);
+
+  // We shouldn't allow ∞ to be imported.
+  EXPECT_FALSE(a.SetFromString(std::string(zeros, sizeof(zeros))));
+}
+
+}  // namespace crypto
diff --git a/crypto/random.cc b/crypto/random.cc
new file mode 100644
index 0000000..847d5df
--- /dev/null
+++ b/crypto/random.cc
@@ -0,0 +1,28 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/random.h"
+
+#include <stddef.h>
+
+#include <vector>
+
+#include "base/rand_util.h"
+
+namespace crypto {
+
+void RandBytes(base::span<uint8_t> bytes) {
+  // base::RandBytes() is already strongly random, so this is just an alias for
+  // it. If base needs a non-strong RNG function in the future, it will get a
+  // different name.
+  base::RandBytes(bytes);
+}
+
+std::vector<uint8_t> RandBytesAsVector(size_t length) {
+  std::vector<uint8_t> result(length);
+  RandBytes(result);
+  return result;
+}
+
+}  // namespace crypto
diff --git a/crypto/random.h b/crypto/random.h
new file mode 100644
index 0000000..a8a4056
--- /dev/null
+++ b/crypto/random.h
@@ -0,0 +1,25 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_RANDOM_H_
+#define CRYPTO_RANDOM_H_
+
+#include <stddef.h>
+
+#include <vector>
+
+#include "base/containers/span.h"
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// Fills `bytes` with cryptographically-secure random bits.
+CRYPTO_EXPORT void RandBytes(base::span<uint8_t> bytes);
+
+// Returns a vector of `length` bytes filled with cryptographically-secure
+// random bits.
+CRYPTO_EXPORT std::vector<uint8_t> RandBytesAsVector(size_t length);
+}
+
+#endif  // CRYPTO_RANDOM_H_
diff --git a/crypto/random_unittest.cc b/crypto/random_unittest.cc
new file mode 100644
index 0000000..ec93b90
--- /dev/null
+++ b/crypto/random_unittest.cc
@@ -0,0 +1,35 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/random.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Basic functionality tests. Does NOT test the security of the random data.
+
+// Ensures we don't have all trivial data, i.e. that the data is indeed random.
+// Currently, that means the bytes cannot be all the same (e.g. all zeros).
+bool IsTrivial(base::span<const uint8_t> bytes) {
+  for (size_t i = 0u; i < bytes.size(); i++) {
+    if (bytes[i] != bytes[0]) {
+      return false;
+    }
+  }
+  return true;
+}
+
+TEST(RandBytes, RandBytes) {
+  std::array<uint8_t, 16> bytes;
+  crypto::RandBytes(bytes);
+  EXPECT_FALSE(IsTrivial(bytes));
+}
+
+TEST(RandBytes, RandBytesAsVector) {
+  std::vector<uint8_t> vector = crypto::RandBytesAsVector(16);
+  EXPECT_FALSE(IsTrivial(vector));
+}
diff --git a/crypto/rsa_private_key.cc b/crypto/rsa_private_key.cc
new file mode 100644
index 0000000..08418f7
--- /dev/null
+++ b/crypto/rsa_private_key.cc
@@ -0,0 +1,387 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/rsa_private_key.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/notreached.h"
+#include "base/strings/string_util.h"
+
+// This file manually encodes and decodes RSA private keys using PrivateKeyInfo
+// from PKCS #8 and RSAPrivateKey from PKCS #1. These structures are:
+//
+// PrivateKeyInfo ::= SEQUENCE {
+//   version Version,
+//   privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+//   privateKey PrivateKey,
+//   attributes [0] IMPLICIT Attributes OPTIONAL
+// }
+//
+// RSAPrivateKey ::= SEQUENCE {
+//   version Version,
+//   modulus INTEGER,
+//   publicExponent INTEGER,
+//   privateExponent INTEGER,
+//   prime1 INTEGER,
+//   prime2 INTEGER,
+//   exponent1 INTEGER,
+//   exponent2 INTEGER,
+//   coefficient INTEGER
+// }
+
+namespace {
+// Helper for error handling during key import.
+#define READ_ASSERT(truth) \
+  if (!(truth)) { \
+    NOTREACHED(); \
+    return false; \
+  }
+}  // namespace
+
+namespace crypto {
+
+const uint8_t PrivateKeyInfoCodec::kRsaAlgorithmIdentifier[] = {
+    0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+    0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00};
+
+PrivateKeyInfoCodec::PrivateKeyInfoCodec(bool big_endian)
+    : big_endian_(big_endian) {}
+
+PrivateKeyInfoCodec::~PrivateKeyInfoCodec() {}
+
+bool PrivateKeyInfoCodec::Export(std::vector<uint8_t>* output) {
+  std::list<uint8_t> content;
+
+  // Version (always zero)
+  uint8_t version = 0;
+
+  PrependInteger(coefficient_, &content);
+  PrependInteger(exponent2_, &content);
+  PrependInteger(exponent1_, &content);
+  PrependInteger(prime2_, &content);
+  PrependInteger(prime1_, &content);
+  PrependInteger(private_exponent_, &content);
+  PrependInteger(public_exponent_, &content);
+  PrependInteger(modulus_, &content);
+  PrependInteger(&version, 1, &content);
+  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
+  PrependTypeHeaderAndLength(kOctetStringTag, content.size(), &content);
+
+  // RSA algorithm OID
+  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
+    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
+
+  PrependInteger(&version, 1, &content);
+  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
+
+  // Copy everying into the output.
+  output->reserve(content.size());
+  output->assign(content.begin(), content.end());
+
+  return true;
+}
+
+bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8_t>* output) {
+  // Create a sequence with the modulus (n) and public exponent (e).
+  std::vector<uint8_t> bit_string;
+  if (!ExportPublicKey(&bit_string))
+    return false;
+
+  // Add the sequence as the contents of a bit string.
+  std::list<uint8_t> content;
+  PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()),
+                   &content);
+
+  // Add the RSA algorithm OID.
+  for (size_t i = sizeof(kRsaAlgorithmIdentifier); i > 0; --i)
+    content.push_front(kRsaAlgorithmIdentifier[i - 1]);
+
+  // Finally, wrap everything in a sequence.
+  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
+
+  // Copy everything into the output.
+  output->reserve(content.size());
+  output->assign(content.begin(), content.end());
+
+  return true;
+}
+
+bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8_t>* output) {
+  // Create a sequence with the modulus (n) and public exponent (e).
+  std::list<uint8_t> content;
+  PrependInteger(&public_exponent_[0],
+                 static_cast<int>(public_exponent_.size()),
+                 &content);
+  PrependInteger(&modulus_[0],  static_cast<int>(modulus_.size()), &content);
+  PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content);
+
+  // Copy everything into the output.
+  output->reserve(content.size());
+  output->assign(content.begin(), content.end());
+
+  return true;
+}
+
+bool PrivateKeyInfoCodec::Import(const std::vector<uint8_t>& input) {
+  if (input.empty()) {
+    return false;
+  }
+
+  // Parse the private key info up to the public key values, ignoring
+  // the subsequent private key values.
+  uint8_t* src = const_cast<uint8_t*>(&input.front());
+  uint8_t* end = src + input.size();
+  if (!ReadSequence(&src, end) ||
+      !ReadVersion(&src, end) ||
+      !ReadAlgorithmIdentifier(&src, end) ||
+      !ReadTypeHeaderAndLength(&src, end, kOctetStringTag, NULL) ||
+      !ReadSequence(&src, end) ||
+      !ReadVersion(&src, end) ||
+      !ReadInteger(&src, end, &modulus_))
+    return false;
+
+  int mod_size = modulus_.size();
+  READ_ASSERT(mod_size % 2 == 0);
+  int primes_size = mod_size / 2;
+
+  if (!ReadIntegerWithExpectedSize(&src, end, 4, &public_exponent_) ||
+      !ReadIntegerWithExpectedSize(&src, end, mod_size, &private_exponent_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime1_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &prime2_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent1_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &exponent2_) ||
+      !ReadIntegerWithExpectedSize(&src, end, primes_size, &coefficient_))
+    return false;
+
+  READ_ASSERT(src == end);
+
+
+  return true;
+}
+
+void PrivateKeyInfoCodec::PrependInteger(const std::vector<uint8_t>& in,
+                                         std::list<uint8_t>* out) {
+  uint8_t* ptr = const_cast<uint8_t*>(&in.front());
+  PrependIntegerImpl(ptr, in.size(), out, big_endian_);
+}
+
+// Helper to prepend an ASN.1 integer.
+void PrivateKeyInfoCodec::PrependInteger(uint8_t* val,
+                                         int num_bytes,
+                                         std::list<uint8_t>* data) {
+  PrependIntegerImpl(val, num_bytes, data, big_endian_);
+}
+
+void PrivateKeyInfoCodec::PrependIntegerImpl(uint8_t* val,
+                                             int num_bytes,
+                                             std::list<uint8_t>* data,
+                                             bool big_endian) {
+ // Reverse input if little-endian.
+ std::vector<uint8_t> tmp;
+ if (!big_endian) {
+   tmp.assign(val, val + num_bytes);
+   std::reverse(tmp.begin(), tmp.end());
+   val = &tmp.front();
+ }
+
+  // ASN.1 integers are unpadded byte arrays, so skip any null padding bytes
+  // from the most-significant end of the integer.
+  int start = 0;
+  while (start < (num_bytes - 1) && val[start] == 0x00) {
+    start++;
+    num_bytes--;
+  }
+  PrependBytes(val, start, num_bytes, data);
+
+  // ASN.1 integers are signed. To encode a positive integer whose sign bit
+  // (the most significant bit) would otherwise be set and make the number
+  // negative, ASN.1 requires a leading null byte to force the integer to be
+  // positive.
+  uint8_t front = data->front();
+  if ((front & 0x80) != 0) {
+    data->push_front(0x00);
+    num_bytes++;
+  }
+
+  PrependTypeHeaderAndLength(kIntegerTag, num_bytes, data);
+}
+
+bool PrivateKeyInfoCodec::ReadInteger(uint8_t** pos,
+                                      uint8_t* end,
+                                      std::vector<uint8_t>* out) {
+  return ReadIntegerImpl(pos, end, out, big_endian_);
+}
+
+bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(
+    uint8_t** pos,
+    uint8_t* end,
+    size_t expected_size,
+    std::vector<uint8_t>* out) {
+  std::vector<uint8_t> temp;
+  if (!ReadIntegerImpl(pos, end, &temp, true))  // Big-Endian
+    return false;
+
+  int pad = expected_size - temp.size();
+  if (out->size() == expected_size + 1) {
+    READ_ASSERT(out->front() == 0x00);
+    pad++;
+  } else {
+    READ_ASSERT(out->size() <= expected_size);
+  }
+
+  out->insert(out->end(), pad, 0x00);
+  out->insert(out->end(), temp.begin(), temp.end());
+
+  // Reverse output if little-endian.
+  if (!big_endian_)
+    std::reverse(out->begin(), out->end());
+  return true;
+}
+
+bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8_t** pos,
+                                          uint8_t* end,
+                                          std::vector<uint8_t>* out,
+                                          bool big_endian) {
+  uint32_t length = 0;
+  if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length) || !length)
+    return false;
+
+  // The first byte can be zero to force positiveness. We can ignore this.
+  if (**pos == 0x00) {
+    ++(*pos);
+    --length;
+  }
+
+  if (length)
+    out->insert(out->end(), *pos, (*pos) + length);
+
+  (*pos) += length;
+
+  // Reverse output if little-endian.
+  if (!big_endian)
+    std::reverse(out->begin(), out->end());
+  return true;
+}
+
+void PrivateKeyInfoCodec::PrependBytes(uint8_t* val,
+                                       int start,
+                                       int num_bytes,
+                                       std::list<uint8_t>* data) {
+  while (num_bytes > 0) {
+    --num_bytes;
+    data->push_front(val[start + num_bytes]);
+  }
+}
+
+void PrivateKeyInfoCodec::PrependLength(size_t size, std::list<uint8_t>* data) {
+  // The high bit is used to indicate whether additional octets are needed to
+  // represent the length.
+  if (size < 0x80) {
+    data->push_front(static_cast<uint8_t>(size));
+  } else {
+    uint8_t num_bytes = 0;
+    while (size > 0) {
+      data->push_front(static_cast<uint8_t>(size & 0xFF));
+      size >>= 8;
+      num_bytes++;
+    }
+    CHECK_LE(num_bytes, 4);
+    data->push_front(0x80 | num_bytes);
+  }
+}
+
+void PrivateKeyInfoCodec::PrependTypeHeaderAndLength(
+    uint8_t type,
+    uint32_t length,
+    std::list<uint8_t>* output) {
+  PrependLength(length, output);
+  output->push_front(type);
+}
+
+void PrivateKeyInfoCodec::PrependBitString(uint8_t* val,
+                                           int num_bytes,
+                                           std::list<uint8_t>* output) {
+  // Start with the data.
+  PrependBytes(val, 0, num_bytes, output);
+  // Zero unused bits.
+  output->push_front(0);
+  // Add the length.
+  PrependLength(num_bytes + 1, output);
+  // Finally, add the bit string tag.
+  output->push_front((uint8_t)kBitStringTag);
+}
+
+bool PrivateKeyInfoCodec::ReadLength(uint8_t** pos,
+                                     uint8_t* end,
+                                     uint32_t* result) {
+  READ_ASSERT(*pos < end);
+  int length = 0;
+
+  // If the MSB is not set, the length is just the byte itself.
+  if (!(**pos & 0x80)) {
+    length = **pos;
+    (*pos)++;
+  } else {
+    // Otherwise, the lower 7 indicate the length of the length.
+    int length_of_length = **pos & 0x7F;
+    READ_ASSERT(length_of_length <= 4);
+    (*pos)++;
+    READ_ASSERT(*pos + length_of_length < end);
+
+    length = 0;
+    for (int i = 0; i < length_of_length; ++i) {
+      length <<= 8;
+      length |= **pos;
+      (*pos)++;
+    }
+  }
+
+  READ_ASSERT(*pos + length <= end);
+  if (result) *result = length;
+  return true;
+}
+
+bool PrivateKeyInfoCodec::ReadTypeHeaderAndLength(uint8_t** pos,
+                                                  uint8_t* end,
+                                                  uint8_t expected_tag,
+                                                  uint32_t* length) {
+  READ_ASSERT(*pos < end);
+  READ_ASSERT(**pos == expected_tag);
+  (*pos)++;
+
+  return ReadLength(pos, end, length);
+}
+
+bool PrivateKeyInfoCodec::ReadSequence(uint8_t** pos, uint8_t* end) {
+  return ReadTypeHeaderAndLength(pos, end, kSequenceTag, NULL);
+}
+
+bool PrivateKeyInfoCodec::ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end) {
+  READ_ASSERT(*pos + sizeof(kRsaAlgorithmIdentifier) < end);
+  READ_ASSERT(memcmp(*pos, kRsaAlgorithmIdentifier,
+                     sizeof(kRsaAlgorithmIdentifier)) == 0);
+  (*pos) += sizeof(kRsaAlgorithmIdentifier);
+  return true;
+}
+
+bool PrivateKeyInfoCodec::ReadVersion(uint8_t** pos, uint8_t* end) {
+  uint32_t length = 0;
+  if (!ReadTypeHeaderAndLength(pos, end, kIntegerTag, &length))
+    return false;
+
+  // The version should be zero.
+  for (uint32_t i = 0; i < length; ++i) {
+    READ_ASSERT(**pos == 0x00);
+    (*pos)++;
+  }
+
+  return true;
+}
+
+}  // namespace crypto
diff --git a/crypto/rsa_private_key.h b/crypto/rsa_private_key.h
new file mode 100644
index 0000000..7ffb412
--- /dev/null
+++ b/crypto/rsa_private_key.h
@@ -0,0 +1,224 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_RSA_PRIVATE_KEY_H_
+#define CRYPTO_RSA_PRIVATE_KEY_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <list>
+#include <vector>
+
+#include "build/build_config.h"
+#include "crypto/crypto_export.h"
+
+#if defined(USE_OPENSSL)
+// Forward declaration for openssl/*.h
+typedef struct evp_pkey_st EVP_PKEY;
+#else
+// Forward declaration.
+typedef struct PK11SlotInfoStr PK11SlotInfo;
+typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
+typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
+#endif
+
+
+namespace crypto {
+
+// Used internally by RSAPrivateKey for serializing and deserializing
+// PKCS #8 PrivateKeyInfo and PublicKeyInfo.
+class PrivateKeyInfoCodec {
+ public:
+  // ASN.1 encoding of the AlgorithmIdentifier from PKCS #8.
+  static const uint8_t kRsaAlgorithmIdentifier[];
+
+  // ASN.1 tags for some types we use.
+  static const uint8_t kBitStringTag = 0x03;
+  static const uint8_t kIntegerTag = 0x02;
+  static const uint8_t kNullTag = 0x05;
+  static const uint8_t kOctetStringTag = 0x04;
+  static const uint8_t kSequenceTag = 0x30;
+
+  // |big_endian| here specifies the byte-significance of the integer components
+  // that will be parsed & serialized (modulus(), etc...) during Import(),
+  // Export() and ExportPublicKeyInfo() -- not the ASN.1 DER encoding of the
+  // PrivateKeyInfo/PublicKeyInfo (which is always big-endian).
+  explicit PrivateKeyInfoCodec(bool big_endian);
+  PrivateKeyInfoCodec(const PrivateKeyInfoCodec&) = delete;
+  PrivateKeyInfoCodec& operator=(const PrivateKeyInfoCodec&) = delete;
+
+  ~PrivateKeyInfoCodec();
+
+  // Exports the contents of the integer components to the ASN.1 DER encoding
+  // of the PrivateKeyInfo structure to |output|.
+  bool Export(std::vector<uint8_t>* output);
+
+  // Exports the contents of the integer components to the ASN.1 DER encoding
+  // of the PublicKeyInfo structure to |output|.
+  bool ExportPublicKeyInfo(std::vector<uint8_t>* output);
+
+  // Exports the contents of the integer components to the ASN.1 DER encoding
+  // of the RSAPublicKey structure to |output|.
+  bool ExportPublicKey(std::vector<uint8_t>* output);
+
+  // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input|
+  // and populates the integer components with |big_endian_| byte-significance.
+  // IMPORTANT NOTE: This is currently *not* security-approved for importing
+  // keys from unstrusted sources.
+  bool Import(const std::vector<uint8_t>& input);
+
+  // Accessors to the contents of the integer components of the PrivateKeyInfo
+  // structure.
+  std::vector<uint8_t>* modulus() { return &modulus_; }
+  std::vector<uint8_t>* public_exponent() { return &public_exponent_; }
+  std::vector<uint8_t>* private_exponent() { return &private_exponent_; }
+  std::vector<uint8_t>* prime1() { return &prime1_; }
+  std::vector<uint8_t>* prime2() { return &prime2_; }
+  std::vector<uint8_t>* exponent1() { return &exponent1_; }
+  std::vector<uint8_t>* exponent2() { return &exponent2_; }
+  std::vector<uint8_t>* coefficient() { return &coefficient_; }
+
+ private:
+  // Utility wrappers for PrependIntegerImpl that use the class's |big_endian_|
+  // value.
+  void PrependInteger(const std::vector<uint8_t>& in, std::list<uint8_t>* out);
+  void PrependInteger(uint8_t* val, int num_bytes, std::list<uint8_t>* data);
+
+  // Prepends the integer stored in |val| - |val + num_bytes| with |big_endian|
+  // byte-significance into |data| as an ASN.1 integer.
+  void PrependIntegerImpl(uint8_t* val,
+                          int num_bytes,
+                          std::list<uint8_t>* data,
+                          bool big_endian);
+
+  // Utility wrappers for ReadIntegerImpl that use the class's |big_endian_|
+  // value.
+  bool ReadInteger(uint8_t** pos, uint8_t* end, std::vector<uint8_t>* out);
+  bool ReadIntegerWithExpectedSize(uint8_t** pos,
+                                   uint8_t* end,
+                                   size_t expected_size,
+                                   std::vector<uint8_t>* out);
+
+  // Reads an ASN.1 integer from |pos|, and stores the result into |out| with
+  // |big_endian| byte-significance.
+  bool ReadIntegerImpl(uint8_t** pos,
+                       uint8_t* end,
+                       std::vector<uint8_t>* out,
+                       bool big_endian);
+
+  // Prepends the integer stored in |val|, starting a index |start|, for
+  // |num_bytes| bytes onto |data|.
+  void PrependBytes(uint8_t* val,
+                    int start,
+                    int num_bytes,
+                    std::list<uint8_t>* data);
+
+  // Helper to prepend an ASN.1 length field.
+  void PrependLength(size_t size, std::list<uint8_t>* data);
+
+  // Helper to prepend an ASN.1 type header.
+  void PrependTypeHeaderAndLength(uint8_t type,
+                                  uint32_t length,
+                                  std::list<uint8_t>* output);
+
+  // Helper to prepend an ASN.1 bit string
+  void PrependBitString(uint8_t* val,
+                        int num_bytes,
+                        std::list<uint8_t>* output);
+
+  // Read an ASN.1 length field. This also checks that the length does not
+  // extend beyond |end|.
+  bool ReadLength(uint8_t** pos, uint8_t* end, uint32_t* result);
+
+  // Read an ASN.1 type header and its length.
+  bool ReadTypeHeaderAndLength(uint8_t** pos,
+                               uint8_t* end,
+                               uint8_t expected_tag,
+                               uint32_t* length);
+
+  // Read an ASN.1 sequence declaration. This consumes the type header and
+  // length field, but not the contents of the sequence.
+  bool ReadSequence(uint8_t** pos, uint8_t* end);
+
+  // Read the RSA AlgorithmIdentifier.
+  bool ReadAlgorithmIdentifier(uint8_t** pos, uint8_t* end);
+
+  // Read one of the two version fields in PrivateKeyInfo.
+  bool ReadVersion(uint8_t** pos, uint8_t* end);
+
+  // The byte-significance of the stored components (modulus, etc..).
+  bool big_endian_;
+
+  // Component integers of the PrivateKeyInfo
+  std::vector<uint8_t> modulus_;
+  std::vector<uint8_t> public_exponent_;
+  std::vector<uint8_t> private_exponent_;
+  std::vector<uint8_t> prime1_;
+  std::vector<uint8_t> prime2_;
+  std::vector<uint8_t> exponent1_;
+  std::vector<uint8_t> exponent2_;
+  std::vector<uint8_t> coefficient_;
+};
+
+// Encapsulates an RSA private key. Can be used to generate new keys, export
+// keys to other formats, or to extract a public key.
+// TODO(hclam): This class should be ref-counted so it can be reused easily.
+class CRYPTO_EXPORT RSAPrivateKey {
+ public:
+  RSAPrivateKey(const RSAPrivateKey&) = delete;
+  RSAPrivateKey& operator=(const RSAPrivateKey&) = delete;
+  ~RSAPrivateKey();
+
+  // Create a new random instance. Can return NULL if initialization fails.
+  static RSAPrivateKey* Create(uint16_t num_bits);
+
+  // Create a new instance by importing an existing private key. The format is
+  // an ASN.1-encoded PrivateKeyInfo block from PKCS #8. This can return NULL if
+  // initialization fails.
+  static RSAPrivateKey* CreateFromPrivateKeyInfo(
+      const std::vector<uint8_t>& input);
+
+#if defined(USE_OPENSSL)
+  // Create a new instance from an existing EVP_PKEY, taking a
+  // reference to it. |key| must be an RSA key. Returns NULL on
+  // failure.
+  static RSAPrivateKey* CreateFromKey(EVP_PKEY* key);
+#else
+  // Create a new instance by referencing an existing private key
+  // structure.  Does not import the key.
+  static RSAPrivateKey* CreateFromKey(SECKEYPrivateKey* key);
+#endif
+
+#if defined(USE_OPENSSL)
+  EVP_PKEY* key() { return key_; }
+#else
+  SECKEYPrivateKey* key() { return key_; }
+  SECKEYPublicKey* public_key() { return public_key_; }
+#endif
+
+  // Creates a copy of the object.
+  RSAPrivateKey* Copy() const;
+
+  // Exports the private key to a PKCS #8 PrivateKeyInfo block.
+  bool ExportPrivateKey(std::vector<uint8_t>* output) const;
+
+  // Exports the public key to an X509 SubjectPublicKeyInfo block.
+  bool ExportPublicKey(std::vector<uint8_t>* output) const;
+
+ private:
+  // Constructor is private. Use one of the Create*() methods above instead.
+  RSAPrivateKey();
+
+#if defined(USE_OPENSSL)
+  EVP_PKEY* key_;
+#else
+  SECKEYPrivateKey* key_;
+  SECKEYPublicKey* public_key_;
+#endif
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_RSA_PRIVATE_KEY_H_
diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc
new file mode 100644
index 0000000..a89e836
--- /dev/null
+++ b/crypto/rsa_private_key_nss.cc
@@ -0,0 +1,151 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/rsa_private_key.h"
+
+#include <cryptohi.h>
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <stdint.h>
+
+#include <list>
+#include <memory>
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "crypto/nss_key_util.h"
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+
+// TODO(rafaelw): Consider using NSS's ASN.1 encoder.
+namespace {
+
+static bool ReadAttribute(SECKEYPrivateKey* key,
+                          CK_ATTRIBUTE_TYPE type,
+                          std::vector<uint8_t>* output) {
+  SECItem item;
+  SECStatus rv;
+  rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item);
+  if (rv != SECSuccess) {
+    NOTREACHED();
+    return false;
+  }
+
+  output->assign(item.data, item.data + item.len);
+  SECITEM_FreeItem(&item, PR_FALSE);
+  return true;
+}
+
+}  // namespace
+
+namespace crypto {
+
+RSAPrivateKey::~RSAPrivateKey() {
+  if (key_)
+    SECKEY_DestroyPrivateKey(key_);
+  if (public_key_)
+    SECKEY_DestroyPublicKey(public_key_);
+}
+
+// static
+RSAPrivateKey* RSAPrivateKey::Create(uint16_t num_bits) {
+  EnsureNSSInit();
+
+  ScopedPK11Slot slot(PK11_GetInternalSlot());
+  if (!slot) {
+    NOTREACHED();
+    return nullptr;
+  }
+
+  ScopedSECKEYPublicKey public_key;
+  ScopedSECKEYPrivateKey private_key;
+  if (!GenerateRSAKeyPairNSS(slot.get(), num_bits, false /* not permanent */,
+                             &public_key, &private_key)) {
+    return nullptr;
+  }
+
+  RSAPrivateKey* rsa_key = new RSAPrivateKey;
+  rsa_key->public_key_ = public_key.release();
+  rsa_key->key_ = private_key.release();
+  return rsa_key;
+}
+
+// static
+RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
+    const std::vector<uint8_t>& input) {
+  EnsureNSSInit();
+
+  ScopedPK11Slot slot(PK11_GetInternalSlot());
+  if (!slot) {
+    NOTREACHED();
+    return nullptr;
+  }
+  ScopedSECKEYPrivateKey key(ImportNSSKeyFromPrivateKeyInfo(
+      slot.get(), input, false /* not permanent */));
+  if (!key || SECKEY_GetPrivateKeyType(key.get()) != rsaKey)
+    return nullptr;
+  return RSAPrivateKey::CreateFromKey(key.get());
+}
+
+// static
+RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
+  DCHECK(key);
+  if (SECKEY_GetPrivateKeyType(key) != rsaKey)
+    return NULL;
+  RSAPrivateKey* copy = new RSAPrivateKey();
+  copy->key_ = SECKEY_CopyPrivateKey(key);
+  copy->public_key_ = SECKEY_ConvertToPublicKey(key);
+  if (!copy->key_ || !copy->public_key_) {
+    NOTREACHED_IN_MIGRATION();
+    delete copy;
+    return NULL;
+  }
+  return copy;
+}
+
+RSAPrivateKey* RSAPrivateKey::Copy() const {
+  RSAPrivateKey* copy = new RSAPrivateKey();
+  copy->key_ = SECKEY_CopyPrivateKey(key_);
+  copy->public_key_ = SECKEY_CopyPublicKey(public_key_);
+  return copy;
+}
+
+bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
+  PrivateKeyInfoCodec private_key_info(true);
+
+  // Manually read the component attributes of the private key and build up
+  // the PrivateKeyInfo.
+  if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) ||
+      !ReadAttribute(key_, CKA_PUBLIC_EXPONENT,
+          private_key_info.public_exponent()) ||
+      !ReadAttribute(key_, CKA_PRIVATE_EXPONENT,
+          private_key_info.private_exponent()) ||
+      !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) ||
+      !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) ||
+      !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) ||
+      !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) ||
+      !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) {
+    NOTREACHED();
+    return false;
+  }
+
+  return private_key_info.Export(output);
+}
+
+bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
+  ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_));
+  if (!der_pubkey.get()) {
+    NOTREACHED();
+    return false;
+  }
+
+  output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len);
+  return true;
+}
+
+RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) {
+  EnsureNSSInit();
+}
+
+}  // namespace crypto
diff --git a/crypto/rsa_private_key_unittest.cc b/crypto/rsa_private_key_unittest.cc
new file mode 100644
index 0000000..db65133
--- /dev/null
+++ b/crypto/rsa_private_key_unittest.cc
@@ -0,0 +1,380 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/rsa_private_key.h"
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const uint8_t kTestPrivateKeyInfo[] = {
+    0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+    0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+    0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+    0x00, 0xb8, 0x7f, 0x2b, 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61,
+    0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, 0x55, 0x84, 0xd5, 0x3a,
+    0xbf, 0x2b, 0xa4, 0x64, 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4,
+    0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, 0xb0, 0x40, 0x53, 0x3a,
+    0xd7, 0x66, 0x09, 0x0f, 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f,
+    0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, 0xde, 0x4e, 0xb9, 0x57,
+    0x5e, 0x7e, 0x0a, 0xe5, 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff,
+    0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, 0x84, 0x32, 0x33, 0xf3,
+    0x17, 0x49, 0xbf, 0xe9, 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5,
+    0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, 0x53, 0x56, 0xa6, 0x83,
+    0xa2, 0xce, 0x93, 0x93, 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01,
+    0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89, 0x37, 0xcb, 0xf2, 0x98,
+    0xa0, 0xce, 0xb4, 0xcb, 0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7,
+    0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd, 0xed, 0xb8, 0x48, 0x8b,
+    0x16, 0x93, 0x36, 0x95, 0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6,
+    0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc, 0x43, 0x78, 0xf9, 0xfe,
+    0x1f, 0x33, 0x23, 0x1e, 0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b,
+    0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed, 0x86, 0xb2, 0xcb, 0x3c,
+    0xfe, 0x4e, 0xa1, 0xfa, 0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38,
+    0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee, 0xa3, 0xf6, 0x85, 0x6b,
+    0x84, 0x43, 0xc9, 0x1e, 0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e,
+    0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46, 0x29, 0x5c, 0xc0, 0x4f,
+    0x01, 0x02, 0x41, 0x00, 0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c,
+    0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7, 0xcc, 0x61, 0xcd, 0x38,
+    0x42, 0x20, 0xd3, 0x82, 0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89,
+    0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42, 0xba, 0x16, 0x1a, 0xea,
+    0x15, 0xc6, 0xf0, 0xb8, 0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2,
+    0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81, 0x02, 0x41, 0x00, 0xc0,
+    0x60, 0x62, 0x80, 0xe1, 0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72,
+    0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f, 0x7d, 0xd6, 0xb8, 0x31,
+    0x2b, 0x84, 0x7f, 0x62, 0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c,
+    0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c, 0x5c, 0x09, 0x3c, 0xcf,
+    0x2f, 0x44, 0x9d, 0xb6, 0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b,
+    0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04, 0xe2, 0x0e, 0x56, 0xca,
+    0x03, 0x1a, 0xc0, 0xf9, 0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda,
+    0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58, 0xda, 0x55, 0x98, 0x74,
+    0xfc, 0x28, 0x17, 0x93, 0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae,
+    0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35, 0xb8, 0x06, 0x03, 0xba,
+    0x08, 0x59, 0x2b, 0x17, 0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41,
+    0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30, 0xa0, 0x24, 0xf5, 0xdb,
+    0x2f, 0xf0, 0x2f, 0xf1, 0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0,
+    0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d, 0xb4, 0x14, 0xd4, 0x09,
+    0x91, 0x33, 0x5a, 0xfd, 0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69,
+    0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39, 0xff, 0x6e, 0xeb, 0xc6,
+    0x86, 0xf5, 0xb4, 0xc7, 0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f,
+    0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35, 0x3e, 0x70, 0x8a, 0xbf,
+    0x27, 0x49, 0xb0, 0x99, 0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6,
+    0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3, 0xc6, 0xa4, 0x92, 0xd1,
+    0xce, 0x6c, 0x72, 0xfb, 0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca,
+    0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3, 0xb1, 0xc5, 0x15, 0xf3};
+
+}  // namespace
+
+// Generate random private keys with two different sizes. Reimport, then
+// export them again. We should get back the same exact bytes.
+TEST(RSAPrivateKeyUnitTest, InitRandomTest) {
+  std::unique_ptr<crypto::RSAPrivateKey> keypair1(
+      crypto::RSAPrivateKey::Create(1024));
+  std::unique_ptr<crypto::RSAPrivateKey> keypair2(
+      crypto::RSAPrivateKey::Create(2048));
+  ASSERT_TRUE(keypair1.get());
+  ASSERT_TRUE(keypair2.get());
+
+  std::vector<uint8_t> privkey1;
+  std::vector<uint8_t> privkey2;
+  std::vector<uint8_t> pubkey1;
+  std::vector<uint8_t> pubkey2;
+
+  ASSERT_TRUE(keypair1->ExportPrivateKey(&privkey1));
+  ASSERT_TRUE(keypair2->ExportPrivateKey(&privkey2));
+  ASSERT_TRUE(keypair1->ExportPublicKey(&pubkey1));
+  ASSERT_TRUE(keypair2->ExportPublicKey(&pubkey2));
+
+  std::unique_ptr<crypto::RSAPrivateKey> keypair3(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey1));
+  std::unique_ptr<crypto::RSAPrivateKey> keypair4(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(privkey2));
+  ASSERT_TRUE(keypair3.get());
+  ASSERT_TRUE(keypair4.get());
+
+  std::vector<uint8_t> privkey3;
+  std::vector<uint8_t> privkey4;
+  ASSERT_TRUE(keypair3->ExportPrivateKey(&privkey3));
+  ASSERT_TRUE(keypair4->ExportPrivateKey(&privkey4));
+
+  ASSERT_EQ(privkey1.size(), privkey3.size());
+  ASSERT_EQ(privkey2.size(), privkey4.size());
+  ASSERT_TRUE(0 == memcmp(&privkey1.front(), &privkey3.front(),
+                          privkey1.size()));
+  ASSERT_TRUE(0 == memcmp(&privkey2.front(), &privkey4.front(),
+                          privkey2.size()));
+}
+
+// Test Copy() method.
+TEST(RSAPrivateKeyUnitTest, CopyTest) {
+  std::vector<uint8_t> input(kTestPrivateKeyInfo,
+                             kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo));
+
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
+
+  std::unique_ptr<crypto::RSAPrivateKey> key_copy(key->Copy());
+  ASSERT_TRUE(key_copy.get());
+
+  std::vector<uint8_t> privkey_copy;
+  ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy));
+  ASSERT_EQ(input, privkey_copy);
+}
+
+// Test that CreateFromPrivateKeyInfo fails if there is extra data after the RSA
+// key.
+TEST(RSAPrivateKeyUnitTest, ExtraData) {
+  std::vector<uint8_t> input(kTestPrivateKeyInfo,
+                             kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo));
+  input.push_back(0);
+
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
+
+  // Import should fail.
+  EXPECT_FALSE(key);
+}
+
+TEST(RSAPrivateKeyUnitTest, NotRsaKey) {
+  // Defines a valid P-256 private key.
+  const uint8_t kTestEcPrivateKeyInfo[] = {
+      0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
+      0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+      0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02, 0x01, 0x01, 0x04, 0x20,
+      0x1F, 0xE3, 0x39, 0x50, 0xC5, 0xF4, 0x61, 0x12, 0x4A, 0xE9, 0x92, 0xC2,
+      0xBD, 0xFD, 0xF1, 0xC7, 0x3B, 0x16, 0x15, 0xF5, 0x71, 0xBD, 0x56, 0x7E,
+      0x60, 0xD1, 0x9A, 0xA1, 0xF4, 0x8C, 0xDF, 0x42, 0xA1, 0x44, 0x03, 0x42,
+      0x00, 0x04, 0x7C, 0x11, 0x0C, 0x66, 0xDC, 0xFD, 0xA8, 0x07, 0xF6, 0xE6,
+      0x9E, 0x45, 0xDD, 0xB3, 0xC7, 0x4F, 0x69, 0xA1, 0x48, 0x4D, 0x20, 0x3E,
+      0x8D, 0xC5, 0xAD, 0xA8, 0xE9, 0xA9, 0xDD, 0x7C, 0xB3, 0xC7, 0x0D, 0xF4,
+      0x48, 0x98, 0x6E, 0x51, 0xBD, 0xE5, 0xD1, 0x57, 0x6F, 0x99, 0x90, 0x1F,
+      0x9C, 0x2C, 0x6A, 0x80, 0x6A, 0x47, 0xFD, 0x90, 0x76, 0x43, 0xA7, 0x2B,
+      0x83, 0x55, 0x97, 0xEF, 0xC8, 0xC6};
+
+  std::vector<uint8_t> input(
+      kTestEcPrivateKeyInfo,
+      kTestEcPrivateKeyInfo + sizeof(kTestEcPrivateKeyInfo));
+
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
+
+  // Import should fail as the given PKCS8 bytes were for an EC key not RSA key.
+  EXPECT_FALSE(key);
+}
+
+// Verify that generated public keys look good. This test data was generated
+// with the openssl command line tool.
+TEST(RSAPrivateKeyUnitTest, PublicKeyTest) {
+  const uint8_t expected_public_key_info[] = {
+      0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+      0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81,
+      0x89, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, 0x20, 0xdc, 0x7c, 0x9b,
+      0x0c, 0xdc, 0x51, 0x61, 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08,
+      0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, 0x85, 0x7b, 0x0c, 0x04,
+      0x13, 0x3f, 0x8d, 0xf4, 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a,
+      0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, 0x9e, 0x36, 0x74, 0x30,
+      0xda, 0x8a, 0x31, 0x4f, 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17,
+      0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, 0xb2, 0x65, 0x7a, 0x89,
+      0x4e, 0xb6, 0x47, 0xff, 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85,
+      0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, 0x96, 0xd0, 0xd6, 0x14,
+      0x6f, 0x13, 0x8d, 0xc5, 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18,
+      0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, 0xe7, 0x1f, 0x0f, 0xe6,
+      0x0f, 0x02, 0x03, 0x01, 0x00, 0x01};
+
+  std::vector<uint8_t> input(kTestPrivateKeyInfo,
+                             kTestPrivateKeyInfo + sizeof(kTestPrivateKeyInfo));
+
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input));
+  ASSERT_TRUE(key.get());
+
+  std::vector<uint8_t> output;
+  ASSERT_TRUE(key->ExportPublicKey(&output));
+
+  ASSERT_TRUE(
+      memcmp(expected_public_key_info, &output.front(), output.size()) == 0);
+}
+
+// These two test keys each contain an integer that has 0x00 for its most
+// significant byte. When encoded as ASN.1, this byte is dropped and there are
+// two interesting sub-cases. When the sign bit of the integer is set, an extra
+// null byte is added back to force the encoded value to be positive. When the
+// sign bit is not set, the encoded integer is just left shorter than usual.
+// See also: http://code.google.com/p/chromium/issues/detail?id=14877.
+//
+// Before we were handling this correctly, we would see one of two failures:
+// * RSAPrivateKey::CreateFromPrivateKeyInfo would return null because the
+//   underlying windows API failed to import the key.
+// * The import would succeed, but incorrectly interpret the data. On export,
+//   the key would contain different values.
+//
+// This test case verifies these two failures modes don't occur.
+TEST(RSAPrivateKeyUnitTest, ShortIntegers) {
+  const uint8_t short_integer_with_high_bit[] = {
+      0x30, 0x82, 0x02, 0x77, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+      0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+      0x02, 0x61, 0x30, 0x82, 0x02, 0x5d, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+      0x00, 0x92, 0x59, 0x32, 0x7d, 0x8e, 0xaf, 0x2e, 0xd5, 0xb2, 0x5c, 0x67,
+      0xc8, 0x7d, 0x48, 0xb7, 0x84, 0x12, 0xd0, 0x76, 0xda, 0xe1, 0xa3, 0x1e,
+      0x40, 0x01, 0x14, 0x5c, 0xef, 0x26, 0x6e, 0x28, 0xa2, 0xf7, 0xa5, 0xb4,
+      0x02, 0x37, 0xd0, 0x53, 0x10, 0xcb, 0x7c, 0x6a, 0xf4, 0x53, 0x9f, 0xb8,
+      0xe0, 0x83, 0x93, 0xd1, 0x19, 0xd8, 0x28, 0xd1, 0xd1, 0xd8, 0x87, 0x8f,
+      0x92, 0xfd, 0x73, 0xc0, 0x4d, 0x3e, 0x07, 0x22, 0x1f, 0xc1, 0x20, 0xb0,
+      0x70, 0xb2, 0x3b, 0xea, 0xb1, 0xe5, 0x0a, 0xfd, 0x56, 0x49, 0x5e, 0x39,
+      0x90, 0x91, 0xce, 0x04, 0x83, 0x29, 0xaa, 0xfd, 0x12, 0xa4, 0x42, 0x26,
+      0x6c, 0x6e, 0x79, 0x70, 0x77, 0x03, 0xb2, 0x07, 0x01, 0x3d, 0x85, 0x81,
+      0x95, 0x9e, 0xda, 0x5a, 0xa3, 0xf4, 0x2d, 0x38, 0x04, 0x58, 0xf5, 0x6b,
+      0xc9, 0xf1, 0xb5, 0x65, 0xfe, 0x66, 0x0d, 0xa2, 0xd5, 0x02, 0x03, 0x01,
+      0x00, 0x01, 0x02, 0x81, 0x80, 0x5e, 0x01, 0x5f, 0xb6, 0x59, 0x1d, 0xdc,
+      0x36, 0xb6, 0x60, 0x36, 0xe6, 0x08, 0xdb, 0xd9, 0xcd, 0xc3, 0x8c, 0x16,
+      0x9c, 0x98, 0x8d, 0x7f, 0xd3, 0xdb, 0x1d, 0xaa, 0x68, 0x8f, 0xc5, 0xf8,
+      0xe2, 0x5d, 0xb3, 0x19, 0xc2, 0xc6, 0xf9, 0x51, 0x32, 0x1b, 0x93, 0x6a,
+      0xdc, 0x50, 0x8e, 0xeb, 0x61, 0x84, 0x03, 0x42, 0x30, 0x98, 0xb1, 0xf7,
+      0xbd, 0x14, 0x9a, 0x57, 0x36, 0x33, 0x09, 0xd4, 0x3e, 0x90, 0xda, 0xef,
+      0x09, 0x6e, 0xef, 0x49, 0xb6, 0x60, 0x68, 0x5e, 0x54, 0x17, 0x25, 0x5b,
+      0x37, 0xe3, 0x35, 0x63, 0x5b, 0x60, 0x3c, 0xbd, 0x50, 0xdf, 0x46, 0x43,
+      0x08, 0xa4, 0x71, 0x21, 0xf1, 0x30, 0x71, 0xdc, 0xda, 0xd7, 0x6f, 0xd2,
+      0x18, 0xbd, 0x39, 0xf1, 0xe1, 0xbe, 0xa8, 0x8d, 0x62, 0xdf, 0xa2, 0x3e,
+      0xb6, 0x15, 0x26, 0xb6, 0x57, 0xbd, 0x63, 0xdb, 0xc1, 0x91, 0xec, 0xb8,
+      0x01, 0x02, 0x41, 0x00, 0xc6, 0x1a, 0x06, 0x48, 0xf2, 0x12, 0x1c, 0x9f,
+      0x74, 0x20, 0x5c, 0x85, 0xa2, 0xda, 0xe5, 0x62, 0x96, 0x8d, 0x22, 0x7b,
+      0x78, 0x73, 0xea, 0xbb, 0x9f, 0x59, 0x42, 0x13, 0x15, 0xc8, 0x11, 0x50,
+      0x6c, 0x55, 0xf6, 0xdf, 0x8b, 0xfe, 0xc7, 0xdd, 0xa8, 0xca, 0x54, 0x41,
+      0xe8, 0xce, 0xbe, 0x7d, 0xbd, 0xe2, 0x13, 0x4b, 0x5b, 0x61, 0xeb, 0x69,
+      0x6c, 0xb1, 0x9b, 0x28, 0x68, 0x5b, 0xd6, 0x01, 0x02, 0x41, 0x00, 0xbd,
+      0x1e, 0xfe, 0x51, 0x99, 0xb6, 0xe3, 0x84, 0xfe, 0xf1, 0x9e, 0xfd, 0x9c,
+      0xe7, 0x86, 0x43, 0x68, 0x7f, 0x2f, 0x6a, 0x2a, 0x4c, 0xae, 0xa6, 0x41,
+      0x1c, 0xf0, 0x10, 0x37, 0x54, 0x23, 0xba, 0x05, 0x0d, 0x18, 0x27, 0x8d,
+      0xb8, 0xe4, 0x8f, 0xf2, 0x25, 0x73, 0x8a, 0xd7, 0x05, 0x98, 0x6b, 0x3d,
+      0x55, 0xb7, 0x6f, 0x7c, 0xec, 0x77, 0x61, 0x54, 0x7b, 0xb6, 0x6b, 0x31,
+      0xec, 0x94, 0xd5, 0x02, 0x41, 0x00, 0x90, 0xa2, 0xa5, 0x9e, 0x12, 0xa7,
+      0x68, 0xa0, 0x7e, 0xdf, 0xb5, 0xcd, 0x98, 0x26, 0xab, 0xbd, 0xbc, 0x5f,
+      0xd5, 0x22, 0x42, 0xc2, 0x97, 0x4a, 0x5f, 0x40, 0x82, 0xfe, 0x7e, 0x33,
+      0xb1, 0x78, 0x7f, 0x70, 0x90, 0x2b, 0x8d, 0x01, 0xfb, 0x18, 0xfa, 0x48,
+      0xa7, 0x15, 0xec, 0x0d, 0x2e, 0x85, 0x8d, 0xe2, 0x86, 0xe5, 0xc9, 0x15,
+      0x88, 0x14, 0x53, 0xd8, 0xa4, 0x88, 0xef, 0x10, 0xc6, 0x01, 0x02, 0x41,
+      0x00, 0xba, 0xe4, 0xaf, 0x14, 0xfa, 0xdf, 0xf6, 0xd5, 0xce, 0x8f, 0xfe,
+      0xbb, 0xc8, 0x5c, 0x30, 0x9d, 0xda, 0xdd, 0x9d, 0x80, 0xc0, 0x0e, 0x89,
+      0xa5, 0xb8, 0xc1, 0x1d, 0x28, 0x19, 0x55, 0x67, 0xfd, 0x03, 0xd2, 0xdd,
+      0xe4, 0xf0, 0xb4, 0x20, 0x03, 0x74, 0x9b, 0xb8, 0x24, 0x23, 0xbb, 0xde,
+      0xd5, 0x53, 0x86, 0xaa, 0xc1, 0x5d, 0x65, 0xdd, 0xcf, 0xec, 0x8a, 0x59,
+      0x4a, 0x73, 0xca, 0xc5, 0x85, 0x02, 0x40, 0x00, 0xc4, 0x5e, 0x8d, 0xa4,
+      0xea, 0xbb, 0x6a, 0x9b, 0xe6, 0x3a, 0x4d, 0xc1, 0xdb, 0xe5, 0x52, 0x38,
+      0xf9, 0x59, 0x91, 0x2d, 0x90, 0x82, 0xe3, 0x31, 0x1b, 0x48, 0xb7, 0x42,
+      0xfa, 0x1d, 0x83, 0xd5, 0x3d, 0x02, 0xc2, 0x12, 0x71, 0x10, 0x3a, 0xbd,
+      0x92, 0x8f, 0x9b, 0xa2, 0x6b, 0x2d, 0x21, 0xa4, 0x65, 0xe9, 0xfa, 0x8c,
+      0x30, 0x2a, 0x89, 0xce, 0xd0, 0xa7, 0x67, 0xd8, 0x45, 0x84, 0xb0};
+
+  const uint8_t short_integer_without_high_bit[] = {
+      0x30, 0x82, 0x02, 0x76, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+      0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+      0x02, 0x60, 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81,
+      0x00, 0xc3, 0x9e, 0x8d, 0xc4, 0x6d, 0x38, 0xe8, 0x0e, 0x9f, 0x84, 0x03,
+      0x40, 0x8e, 0x81, 0x2e, 0x56, 0x67, 0x78, 0x11, 0x85, 0x27, 0x81, 0x52,
+      0xf2, 0x1b, 0x3e, 0x5b, 0xf8, 0xab, 0xfc, 0xaf, 0xca, 0x5c, 0x26, 0xd5,
+      0xfa, 0xd4, 0x55, 0x50, 0x38, 0xb9, 0x9d, 0x89, 0x92, 0x7e, 0x34, 0xcf,
+      0x37, 0x82, 0x48, 0x2d, 0xaa, 0xc4, 0x6a, 0x0e, 0x93, 0xea, 0xad, 0x8a,
+      0x33, 0xf0, 0x42, 0x23, 0xe0, 0x4c, 0x98, 0xbf, 0x01, 0x00, 0x1b, 0xfe,
+      0x06, 0x15, 0xc6, 0xe3, 0x80, 0x79, 0x6d, 0xfe, 0x48, 0xcd, 0x40, 0xbb,
+      0xf9, 0x58, 0xe6, 0xbf, 0xd5, 0x4c, 0x29, 0x48, 0x53, 0x78, 0x06, 0x03,
+      0x0d, 0x59, 0xf5, 0x20, 0xe0, 0xe6, 0x8c, 0xb2, 0xf5, 0xd8, 0x61, 0x52,
+      0x7e, 0x40, 0x83, 0xd7, 0x69, 0xae, 0xd7, 0x75, 0x02, 0x2d, 0x49, 0xd5,
+      0x15, 0x5b, 0xf1, 0xd9, 0x4d, 0x60, 0x7d, 0x62, 0xa5, 0x02, 0x03, 0x01,
+      0x00, 0x01, 0x02, 0x7f, 0x6d, 0x45, 0x23, 0xeb, 0x95, 0x17, 0x34, 0x88,
+      0xf6, 0x91, 0xc7, 0x3f, 0x48, 0x5a, 0xe0, 0x87, 0x63, 0x44, 0xae, 0x84,
+      0xb2, 0x8c, 0x8a, 0xc8, 0xb2, 0x6f, 0x22, 0xf0, 0xc5, 0x21, 0x61, 0x10,
+      0xa8, 0x69, 0x09, 0x1e, 0x13, 0x7d, 0x94, 0x52, 0x1b, 0x5c, 0xe4, 0x7b,
+      0xf0, 0x03, 0x8f, 0xbc, 0x72, 0x09, 0xdf, 0x78, 0x84, 0x3e, 0xb9, 0xe5,
+      0xe6, 0x31, 0x0a, 0x01, 0xf9, 0x32, 0xf8, 0xd6, 0x57, 0xa3, 0x87, 0xe6,
+      0xf5, 0x98, 0xbc, 0x8e, 0x41, 0xb9, 0x50, 0x17, 0x7b, 0xd3, 0x97, 0x5a,
+      0x44, 0x3a, 0xee, 0xff, 0x6b, 0xb3, 0x3a, 0x52, 0xe7, 0xa4, 0x96, 0x9a,
+      0xf6, 0x83, 0xc8, 0x97, 0x1c, 0x63, 0xa1, 0xd6, 0xb3, 0xa8, 0xb2, 0xc7,
+      0x73, 0x25, 0x0f, 0x58, 0x36, 0xb9, 0x7a, 0x47, 0xa7, 0x4d, 0x30, 0xfe,
+      0x4d, 0x74, 0x56, 0xe8, 0xfb, 0xd6, 0x50, 0xe5, 0xe0, 0x28, 0x15, 0x02,
+      0x41, 0x00, 0xeb, 0x15, 0x62, 0xb6, 0x37, 0x41, 0x7c, 0xc5, 0x00, 0x22,
+      0x2c, 0x5a, 0x5e, 0xe4, 0xb2, 0x11, 0x87, 0x89, 0xad, 0xf4, 0x57, 0x68,
+      0x90, 0xb7, 0x9f, 0xe2, 0x79, 0x20, 0x6b, 0x98, 0x00, 0x0d, 0x3a, 0x3b,
+      0xc1, 0xcd, 0x36, 0xf9, 0x27, 0xda, 0x40, 0x36, 0x1d, 0xb8, 0x5c, 0x96,
+      0xeb, 0x04, 0x08, 0xe1, 0x3f, 0xfa, 0x94, 0x8b, 0x0f, 0xa0, 0xff, 0xc1,
+      0x51, 0xea, 0x90, 0xad, 0x15, 0xc7, 0x02, 0x41, 0x00, 0xd5, 0x06, 0x45,
+      0xd7, 0x55, 0x63, 0x1a, 0xf0, 0x89, 0x81, 0xae, 0x87, 0x23, 0xa2, 0x39,
+      0xfe, 0x3d, 0x82, 0xc7, 0xcb, 0x15, 0xb9, 0xe3, 0xe2, 0x5b, 0xc6, 0xd2,
+      0x55, 0xdd, 0xab, 0x55, 0x29, 0x7c, 0xda, 0x0e, 0x1c, 0x09, 0xfc, 0x73,
+      0x0d, 0x01, 0xed, 0x6d, 0x2f, 0x05, 0xd0, 0xd5, 0x1d, 0xce, 0x18, 0x7f,
+      0xb0, 0xc8, 0x47, 0x77, 0xd2, 0xa9, 0x9e, 0xfc, 0x39, 0x4b, 0x3d, 0x94,
+      0x33, 0x02, 0x41, 0x00, 0x8f, 0x94, 0x09, 0x2d, 0x17, 0x44, 0x75, 0x0a,
+      0xf1, 0x10, 0xee, 0x1b, 0xe7, 0xd7, 0x2f, 0xf6, 0xca, 0xdc, 0x49, 0x15,
+      0x72, 0x09, 0x58, 0x51, 0xfe, 0x61, 0xd8, 0xee, 0xf7, 0x27, 0xe7, 0xe8,
+      0x2c, 0x47, 0xf1, 0x0f, 0x00, 0x63, 0x5e, 0x76, 0xcb, 0x3f, 0x02, 0x19,
+      0xe6, 0xda, 0xfa, 0x01, 0x05, 0xd7, 0x65, 0x37, 0x0b, 0x60, 0x7f, 0x94,
+      0x2a, 0x80, 0x8d, 0x22, 0x81, 0x68, 0x65, 0x63, 0x02, 0x41, 0x00, 0xc2,
+      0xd4, 0x18, 0xde, 0x47, 0x9e, 0xfb, 0x8d, 0x91, 0x05, 0xc5, 0x3c, 0x9d,
+      0xcf, 0x8a, 0x60, 0xc7, 0x9b, 0x2b, 0xe5, 0xc6, 0xba, 0x1b, 0xfc, 0xf3,
+      0xd9, 0x54, 0x97, 0xe9, 0xc4, 0x00, 0x80, 0x90, 0x4a, 0xd2, 0x6a, 0xbc,
+      0x8b, 0x62, 0x22, 0x3c, 0x68, 0x0c, 0xda, 0xdb, 0xe3, 0xd2, 0x76, 0x8e,
+      0xff, 0x03, 0x12, 0x09, 0x2a, 0xac, 0x21, 0x44, 0xb7, 0x3e, 0x91, 0x9c,
+      0x09, 0xf6, 0xd7, 0x02, 0x41, 0x00, 0xc0, 0xa1, 0xbb, 0x70, 0xdc, 0xf8,
+      0xeb, 0x17, 0x61, 0xd4, 0x8c, 0x7c, 0x3b, 0x82, 0x91, 0x58, 0xff, 0xf9,
+      0x19, 0xac, 0x3a, 0x73, 0xa7, 0x20, 0xe5, 0x22, 0x02, 0xc4, 0xf6, 0xb9,
+      0xb9, 0x43, 0x53, 0x35, 0x88, 0xe1, 0x05, 0xb6, 0x43, 0x9b, 0x39, 0xc8,
+      0x04, 0x4d, 0x2b, 0x01, 0xf7, 0xe6, 0x1b, 0x8d, 0x7e, 0x89, 0xe3, 0x43,
+      0xd4, 0xf3, 0xab, 0x28, 0xd4, 0x5a, 0x1f, 0x20, 0xea, 0xbe};
+
+  std::vector<uint8_t> input1;
+  std::vector<uint8_t> input2;
+
+  input1.resize(sizeof(short_integer_with_high_bit));
+  input2.resize(sizeof(short_integer_without_high_bit));
+
+  memcpy(&input1.front(), short_integer_with_high_bit,
+         sizeof(short_integer_with_high_bit));
+  memcpy(&input2.front(), short_integer_without_high_bit,
+         sizeof(short_integer_without_high_bit));
+
+  std::unique_ptr<crypto::RSAPrivateKey> keypair1(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input1));
+  std::unique_ptr<crypto::RSAPrivateKey> keypair2(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input2));
+  ASSERT_TRUE(keypair1.get());
+  ASSERT_TRUE(keypair2.get());
+
+  std::vector<uint8_t> output1;
+  std::vector<uint8_t> output2;
+  ASSERT_TRUE(keypair1->ExportPrivateKey(&output1));
+  ASSERT_TRUE(keypair2->ExportPrivateKey(&output2));
+
+  ASSERT_EQ(input1.size(), output1.size());
+  ASSERT_EQ(input2.size(), output2.size());
+  ASSERT_TRUE(0 == memcmp(&output1.front(), &input1.front(),
+                          input1.size()));
+  ASSERT_TRUE(0 == memcmp(&output2.front(), &input2.front(),
+                          input2.size()));
+}
+
+TEST(RSAPrivateKeyUnitTest, CreateFromKeyTest) {
+  std::unique_ptr<crypto::RSAPrivateKey> key_pair(
+      crypto::RSAPrivateKey::Create(512));
+  ASSERT_TRUE(key_pair.get());
+
+  std::unique_ptr<crypto::RSAPrivateKey> key_copy(
+      crypto::RSAPrivateKey::CreateFromKey(key_pair->key()));
+  ASSERT_TRUE(key_copy.get());
+
+  std::vector<uint8_t> privkey;
+  std::vector<uint8_t> pubkey;
+  ASSERT_TRUE(key_pair->ExportPrivateKey(&privkey));
+  ASSERT_TRUE(key_pair->ExportPublicKey(&pubkey));
+
+  std::vector<uint8_t> privkey_copy;
+  std::vector<uint8_t> pubkey_copy;
+  ASSERT_TRUE(key_copy->ExportPrivateKey(&privkey_copy));
+  ASSERT_TRUE(key_copy->ExportPublicKey(&pubkey_copy));
+
+  ASSERT_EQ(privkey, privkey_copy);
+  ASSERT_EQ(pubkey, pubkey_copy);
+}
+
diff --git a/crypto/scoped_capi_types.h b/crypto/scoped_capi_types.h
new file mode 100644
index 0000000..efe0d24
--- /dev/null
+++ b/crypto/scoped_capi_types.h
@@ -0,0 +1,122 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SCOPED_CAPI_TYPES_H_
+#define CRYPTO_SCOPED_CAPI_TYPES_H_
+
+#include <windows.h>
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "crypto/wincrypt_shim.h"
+
+namespace crypto {
+
+// Simple destructor for the Free family of CryptoAPI functions, such as
+// CryptDestroyHash, which take only a single argument to release.
+template <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle)>
+struct CAPIDestroyer {
+  void operator()(CAPIHandle handle) const {
+    if (handle) {
+      BOOL ok = Destroyer(handle);
+      DCHECK(ok);
+    }
+  }
+};
+
+// Destructor for the Close/Release family of CryptoAPI functions, which take
+// a second DWORD parameter indicating flags to use when closing or releasing.
+// This includes functions like CertCloseStore or CryptReleaseContext.
+template <typename CAPIHandle, BOOL (WINAPI *Destroyer)(CAPIHandle, DWORD),
+          DWORD flags>
+struct CAPIDestroyerWithFlags {
+  void operator()(CAPIHandle handle) const {
+    if (handle) {
+      BOOL ok = Destroyer(handle, flags);
+      DCHECK(ok);
+    }
+  }
+};
+
+// scoped_ptr-like class for the CryptoAPI cryptography and certificate
+// handles. Because these handles are defined as integer types, and not
+// pointers, the existing scoped classes, such as scoped_ptr, are insufficient.
+// The semantics are the same as scoped_ptr.
+template <class CAPIHandle, typename FreeProc>
+class ScopedCAPIHandle {
+ public:
+  explicit ScopedCAPIHandle(CAPIHandle handle = NULL) : handle_(handle) {}
+
+  ScopedCAPIHandle(const ScopedCAPIHandle&) = delete;
+  ScopedCAPIHandle& operator=(const ScopedCAPIHandle&) = delete;
+
+  ~ScopedCAPIHandle() {
+    reset();
+  }
+
+  void reset(CAPIHandle handle = NULL) {
+    if (handle_ != handle) {
+      FreeProc free_proc;
+      free_proc(handle_);
+      handle_ = handle;
+    }
+  }
+
+  operator CAPIHandle() const { return handle_; }
+  CAPIHandle get() const { return handle_; }
+
+  CAPIHandle* receive() {
+    CHECK(handle_ == NULL);
+    return &handle_;
+  }
+
+  bool operator==(CAPIHandle handle) const {
+    return handle_ == handle;
+  }
+
+  bool operator!=(CAPIHandle handle) const {
+    return handle_ != handle;
+  }
+
+  void swap(ScopedCAPIHandle& b) {
+    CAPIHandle tmp = b.handle_;
+    b.handle_ = handle_;
+    handle_ = tmp;
+  }
+
+  CAPIHandle release() {
+    CAPIHandle tmp = handle_;
+    handle_ = NULL;
+    return tmp;
+  }
+
+ private:
+  CAPIHandle handle_;
+};
+
+template<class CH, typename FP> inline
+bool operator==(CH h, const ScopedCAPIHandle<CH, FP>& b) {
+  return h == b.get();
+}
+
+template<class CH, typename FP> inline
+bool operator!=(CH h, const ScopedCAPIHandle<CH, FP>& b) {
+  return h != b.get();
+}
+
+typedef ScopedCAPIHandle<
+    HCRYPTPROV,
+    CAPIDestroyerWithFlags<HCRYPTPROV,
+                           CryptReleaseContext, 0> > ScopedHCRYPTPROV;
+
+typedef ScopedCAPIHandle<
+    HCRYPTKEY, CAPIDestroyer<HCRYPTKEY, CryptDestroyKey> > ScopedHCRYPTKEY;
+
+typedef ScopedCAPIHandle<
+    HCRYPTHASH, CAPIDestroyer<HCRYPTHASH, CryptDestroyHash> > ScopedHCRYPTHASH;
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_CAPI_TYPES_H_
diff --git a/crypto/scoped_nss_types.h b/crypto/scoped_nss_types.h
new file mode 100644
index 0000000..2a75113
--- /dev/null
+++ b/crypto/scoped_nss_types.h
@@ -0,0 +1,63 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SCOPED_NSS_TYPES_H_
+#define CRYPTO_SCOPED_NSS_TYPES_H_
+
+#include <keyhi.h>
+#include <nss.h>
+#include <pk11pub.h>
+#include <plarena.h>
+
+#include <memory>
+
+namespace crypto {
+
+template <typename Type, void (*Destroyer)(Type*)>
+struct NSSDestroyer {
+  void operator()(Type* ptr) const {
+    Destroyer(ptr);
+  }
+};
+
+template <typename Type, void (*Destroyer)(Type*, PRBool), PRBool freeit>
+struct NSSDestroyer1 {
+  void operator()(Type* ptr) const {
+    Destroyer(ptr, freeit);
+  }
+};
+
+// Define some convenient scopers around NSS pointers.
+typedef std::unique_ptr<
+    PK11Context,
+    NSSDestroyer1<PK11Context, PK11_DestroyContext, PR_TRUE>>
+    ScopedPK11Context;
+typedef std::unique_ptr<PK11SlotInfo, NSSDestroyer<PK11SlotInfo, PK11_FreeSlot>>
+    ScopedPK11Slot;
+typedef std::unique_ptr<PK11SlotList,
+                        NSSDestroyer<PK11SlotList, PK11_FreeSlotList>>
+    ScopedPK11SlotList;
+typedef std::unique_ptr<PK11SymKey, NSSDestroyer<PK11SymKey, PK11_FreeSymKey>>
+    ScopedPK11SymKey;
+typedef std::unique_ptr<SECKEYPublicKey,
+                        NSSDestroyer<SECKEYPublicKey, SECKEY_DestroyPublicKey>>
+    ScopedSECKEYPublicKey;
+typedef std::unique_ptr<
+    SECKEYPrivateKey,
+    NSSDestroyer<SECKEYPrivateKey, SECKEY_DestroyPrivateKey>>
+    ScopedSECKEYPrivateKey;
+typedef std::unique_ptr<
+    SECAlgorithmID,
+    NSSDestroyer1<SECAlgorithmID, SECOID_DestroyAlgorithmID, PR_TRUE>>
+    ScopedSECAlgorithmID;
+typedef std::unique_ptr<SECItem,
+                        NSSDestroyer1<SECItem, SECITEM_FreeItem, PR_TRUE>>
+    ScopedSECItem;
+typedef std::unique_ptr<PLArenaPool,
+                        NSSDestroyer1<PLArenaPool, PORT_FreeArena, PR_FALSE>>
+    ScopedPLArenaPool;
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_NSS_TYPES_H_
diff --git a/crypto/scoped_openssl_types.h b/crypto/scoped_openssl_types.h
new file mode 100644
index 0000000..e6f895b
--- /dev/null
+++ b/crypto/scoped_openssl_types.h
@@ -0,0 +1,69 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SCOPED_OPENSSL_TYPES_H_
+#define CRYPTO_SCOPED_OPENSSL_TYPES_H_
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#ifdef OPENSSL_IS_BORINGSSL
+#include <openssl/mem.h>
+#endif
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+#include <stdint.h>
+
+#include <memory>
+
+// TODO(crbug.com/984789): Remove once all of Chrome OS uses OpenSSL 1.1.
+#include "crypto/libcrypto-compat.h"
+
+namespace crypto {
+
+// Simplistic helper that wraps a call to a deleter function. In a C++11 world,
+// this would be std::function<>. An alternative would be to re-use
+// base::internal::RunnableAdapter<>, but that's far too heavy weight.
+template <typename Type, void (*Destroyer)(Type*)>
+struct OpenSSLDestroyer {
+  void operator()(Type* ptr) const { Destroyer(ptr); }
+};
+
+template <typename PointerType, void (*Destroyer)(PointerType*)>
+using ScopedOpenSSL =
+    std::unique_ptr<PointerType, OpenSSLDestroyer<PointerType, Destroyer>>;
+
+struct OpenSSLFree {
+  void operator()(uint8_t* ptr) const { OPENSSL_free(ptr); }
+};
+
+// Several typedefs are provided for crypto-specific primitives, for
+// short-hand and prevalence.
+using ScopedBIGNUM = ScopedOpenSSL<BIGNUM, BN_free>;
+using ScopedEC_Key = ScopedOpenSSL<EC_KEY, EC_KEY_free>;
+using ScopedBIO = ScopedOpenSSL<BIO, BIO_free_all>;
+using ScopedDSA = ScopedOpenSSL<DSA, DSA_free>;
+using ScopedECDSA_SIG = ScopedOpenSSL<ECDSA_SIG, ECDSA_SIG_free>;
+using ScopedEC_GROUP = ScopedOpenSSL<EC_GROUP, EC_GROUP_free>;
+using ScopedEC_KEY = ScopedOpenSSL<EC_KEY, EC_KEY_free>;
+using ScopedEC_POINT = ScopedOpenSSL<EC_POINT, EC_POINT_free>;
+using ScopedEVP_CIPHER_CTX = ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>;
+using ScopedEVP_MD_CTX = ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_free>;
+using ScopedEVP_PKEY = ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free>;
+using ScopedEVP_PKEY_CTX = ScopedOpenSSL<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
+using ScopedHMAC_CTX = ScopedOpenSSL<HMAC_CTX, HMAC_CTX_free>;
+using ScopedNETSCAPE_SPKI = ScopedOpenSSL<NETSCAPE_SPKI, NETSCAPE_SPKI_free>;
+using ScopedRSA = ScopedOpenSSL<RSA, RSA_free>;
+using ScopedX509 = ScopedOpenSSL<X509, X509_free>;
+
+// The bytes must have been allocated with OPENSSL_malloc.
+using ScopedOpenSSLBytes = std::unique_ptr<uint8_t, OpenSSLFree>;
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_OPENSSL_TYPES_H_
diff --git a/crypto/scoped_test_nss_chromeos_user.cc b/crypto/scoped_test_nss_chromeos_user.cc
new file mode 100644
index 0000000..623c509
--- /dev/null
+++ b/crypto/scoped_test_nss_chromeos_user.cc
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/scoped_test_nss_chromeos_user.h"
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
+
+namespace crypto {
+
+ScopedTestNSSChromeOSUser::ScopedTestNSSChromeOSUser(
+    const std::string& username_hash)
+    : username_hash_(username_hash), constructed_successfully_(false) {
+  if (!temp_dir_.CreateUniqueTempDir())
+    return;
+  // This opens a software DB in the given folder. In production code that is in
+  // the home folder, but for testing the temp folder is used.
+  constructed_successfully_ =
+      InitializeNSSForChromeOSUser(username_hash, temp_dir_.path());
+}
+
+ScopedTestNSSChromeOSUser::~ScopedTestNSSChromeOSUser() {
+  if (constructed_successfully_)
+    CloseChromeOSUserForTesting(username_hash_);
+}
+
+void ScopedTestNSSChromeOSUser::FinishInit() {
+  DCHECK(constructed_successfully_);
+  if (!ShouldInitializeTPMForChromeOSUser(username_hash_))
+    return;
+  WillInitializeTPMForChromeOSUser(username_hash_);
+  InitializePrivateSoftwareSlotForChromeOSUser(username_hash_);
+}
+
+}  // namespace crypto
diff --git a/crypto/scoped_test_nss_chromeos_user.h b/crypto/scoped_test_nss_chromeos_user.h
new file mode 100644
index 0000000..e1517d0
--- /dev/null
+++ b/crypto/scoped_test_nss_chromeos_user.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_
+#define CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_
+
+#include <string>
+
+#include "base/files/scoped_temp_dir.h"
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// Opens a persistent NSS software database in a temporary directory for the
+// user with |username_hash|. This database will be used for both the user's
+// public and private slot.
+class CRYPTO_EXPORT ScopedTestNSSChromeOSUser {
+ public:
+  // Opens the software database and sets the public slot for the user. The
+  // private slot will not be initialized until FinishInit() is called.
+  explicit ScopedTestNSSChromeOSUser(const std::string& username_hash);
+
+  ScopedTestNSSChromeOSUser(const ScopedTestNSSChromeOSUser&) = delete;
+  ScopedTestNSSChromeOSUser& operator=(const ScopedTestNSSChromeOSUser&) = delete;
+
+  ~ScopedTestNSSChromeOSUser();
+
+  std::string username_hash() const { return username_hash_; }
+  bool constructed_successfully() const { return constructed_successfully_; }
+
+  // Completes initialization of user. Causes any waiting private slot callbacks
+  // to run, see GetPrivateSlotForChromeOSUser().
+  void FinishInit();
+
+ private:
+  const std::string username_hash_;
+  base::ScopedTempDir temp_dir_;
+  bool constructed_successfully_;
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_TEST_NSS_CHROMEOS_USER_H_
diff --git a/crypto/scoped_test_nss_db.cc b/crypto/scoped_test_nss_db.cc
new file mode 100644
index 0000000..73614fc
--- /dev/null
+++ b/crypto/scoped_test_nss_db.cc
@@ -0,0 +1,71 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/scoped_test_nss_db.h"
+
+#include <cert.h>
+
+#include "base/logging.h"
+#include "base/threading/thread_restrictions.h"
+#include "crypto/nss_util.h"
+#include "crypto/nss_util_internal.h"
+
+namespace crypto {
+
+ScopedTestNSSDB::ScopedTestNSSDB() {
+  EnsureNSSInit();
+  // NSS is allowed to do IO on the current thread since dispatching
+  // to a dedicated thread would still have the affect of blocking
+  // the current thread, due to NSS's internal locking requirements
+  base::ScopedAllowBlockingForTesting allow_blocking;
+
+  if (!temp_dir_.CreateUniqueTempDir())
+    return;
+
+  const char kTestDescription[] = "Test DB";
+  slot_ = OpenSoftwareNSSDB(temp_dir_.GetPath(), kTestDescription);
+}
+
+ScopedTestNSSDB::~ScopedTestNSSDB() {
+  // Remove trust from any certs in the test DB before closing it. Otherwise NSS
+  // may cache verification results even after the test DB is gone.
+  if (slot_) {
+    CERTCertList* cert_list = PK11_ListCertsInSlot(slot_.get());
+    for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
+         !CERT_LIST_END(node, cert_list);
+         node = CERT_LIST_NEXT(node)) {
+      CERTCertTrust trust = {0};
+      if (CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), node->cert, &trust) !=
+          SECSuccess) {
+        LOG(ERROR) << "CERT_ChangeCertTrust failed: " << PORT_GetError();
+      }
+    }
+    CERT_DestroyCertList(cert_list);
+  }
+
+  // Don't close when NSS is < 3.15.1, because it would require an additional
+  // sleep for 1 second after closing the database, due to
+  // http://bugzil.la/875601.
+  if (!NSS_VersionCheck("3.15.1")) {
+    LOG(ERROR) << "NSS version is < 3.15.1, test DB will not be closed.";
+    temp_dir_.Take();
+    return;
+  }
+
+  // NSS is allowed to do IO on the current thread since dispatching
+  // to a dedicated thread would still have the affect of blocking
+  // the current thread, due to NSS's internal locking requirements
+  base::ScopedAllowBlockingForTesting allow_blocking;
+
+  if (slot_) {
+    SECStatus status = SECMOD_CloseUserDB(slot_.get());
+    if (status != SECSuccess)
+      PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
+  }
+
+  if (!temp_dir_.Delete())
+    LOG(ERROR) << "Could not delete temporary directory.";
+}
+
+}  // namespace crypto
diff --git a/crypto/scoped_test_nss_db.h b/crypto/scoped_test_nss_db.h
new file mode 100644
index 0000000..f9f5cbe
--- /dev/null
+++ b/crypto/scoped_test_nss_db.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SCOPED_TEST_NSS_DB_H_
+#define CRYPTO_SCOPED_TEST_NSS_DB_H_
+
+#include "base/files/scoped_temp_dir.h"
+#include "crypto/crypto_export.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace crypto {
+
+// Opens a persistent NSS database in a temporary directory.
+// Prior NSS version 3.15.1, because of http://bugzil.la/875601 , the opened DB
+// will not be closed automatically.
+class CRYPTO_EXPORT ScopedTestNSSDB {
+ public:
+  ScopedTestNSSDB();
+  ScopedTestNSSDB(const ScopedTestNSSDB&) = delete;
+  ScopedTestNSSDB& operator=(const ScopedTestNSSDB&) = delete;
+
+  ~ScopedTestNSSDB();
+
+  bool is_open() const { return !!slot_; }
+  PK11SlotInfo* slot() const { return slot_.get(); }
+
+ private:
+  base::ScopedTempDir temp_dir_;
+  ScopedPK11Slot slot_;
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_TEST_NSS_DB_H_
diff --git a/crypto/scoped_test_system_nss_key_slot.cc b/crypto/scoped_test_system_nss_key_slot.cc
new file mode 100644
index 0000000..58d5db2
--- /dev/null
+++ b/crypto/scoped_test_system_nss_key_slot.cc
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/scoped_test_system_nss_key_slot.h"
+
+#include "crypto/nss_util_internal.h"
+#include "crypto/scoped_test_nss_db.h"
+
+namespace crypto {
+
+ScopedTestSystemNSSKeySlot::ScopedTestSystemNSSKeySlot()
+    : test_db_(new ScopedTestNSSDB) {
+  if (!test_db_->is_open())
+    return;
+  SetSystemKeySlotForTesting(
+      ScopedPK11Slot(PK11_ReferenceSlot(test_db_->slot())));
+}
+
+ScopedTestSystemNSSKeySlot::~ScopedTestSystemNSSKeySlot() {
+  SetSystemKeySlotForTesting(ScopedPK11Slot());
+}
+
+bool ScopedTestSystemNSSKeySlot::ConstructedSuccessfully() const {
+  return test_db_->is_open();
+}
+
+PK11SlotInfo* ScopedTestSystemNSSKeySlot::slot() const {
+  return test_db_->slot();
+}
+
+}  // namespace crypto
diff --git a/crypto/scoped_test_system_nss_key_slot.h b/crypto/scoped_test_system_nss_key_slot.h
new file mode 100644
index 0000000..24af513
--- /dev/null
+++ b/crypto/scoped_test_system_nss_key_slot.h
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_
+#define CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_
+
+#include <memory>
+
+#include "crypto/crypto_export.h"
+
+// Forward declaration, from <pk11pub.h>
+typedef struct PK11SlotInfoStr PK11SlotInfo;
+
+namespace crypto {
+
+class ScopedTestNSSDB;
+
+// Opens a persistent NSS software database in a temporary directory and sets
+// the test system slot to the opened database. This helper should be created in
+// tests to fake the system token that is usually provided by the Chaps module.
+// |slot| is exposed through |GetSystemNSSKeySlot| and |IsTPMTokenReady| will
+// return true.
+// |InitializeTPMTokenAndSystemSlot|, which triggers the TPM initialization,
+// does not have to be called if this helper is used.
+// At most one instance of this helper must be used at a time.
+class CRYPTO_EXPORT ScopedTestSystemNSSKeySlot {
+ public:
+  explicit ScopedTestSystemNSSKeySlot();
+  ScopedTestSystemNssKeySlot(const ScopedTestSystemNssKeySlot&) = delete;
+  ScopedTestSystemNssKeySlot& operator=(const ScopedTestSystemNssKeySlot&) = delete;
+  ~ScopedTestSystemNSSKeySlot();
+
+  bool ConstructedSuccessfully() const;
+  PK11SlotInfo* slot() const;
+
+ private:
+  std::unique_ptr<ScopedTestNSSDB> test_db_;
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SCOPED_TEST_SYSTEM_NSS_KEY_SLOT_H_
diff --git a/crypto/secure_hash.cc b/crypto/secure_hash.cc
new file mode 100644
index 0000000..4b22afa
--- /dev/null
+++ b/crypto/secure_hash.cc
@@ -0,0 +1,70 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/secure_hash.h"
+
+#if defined(OPENSSL_IS_BORINGSSL)
+#include <openssl/mem.h>
+#else
+#include <openssl/crypto.h>
+#endif
+#include <openssl/sha.h>
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "base/notreached.h"
+#include "base/pickle.h"
+#include "crypto/openssl_util.h"
+
+namespace crypto {
+
+namespace {
+
+class SecureHashSHA256 : public SecureHash {
+ public:
+  SecureHashSHA256() {
+    SHA256_Init(&ctx_);
+  }
+
+  SecureHashSHA256(const SecureHashSHA256& other) : SecureHash() {
+    memcpy(&ctx_, &other.ctx_, sizeof(ctx_));
+  }
+
+  ~SecureHashSHA256() override {
+    OPENSSL_cleanse(&ctx_, sizeof(ctx_));
+  }
+
+  void Update(const void* input, size_t len) override {
+    SHA256_Update(&ctx_, static_cast<const unsigned char*>(input), len);
+  }
+
+  void Finish(void* output, size_t len) override {
+    ScopedOpenSSLSafeSizeBuffer<SHA256_DIGEST_LENGTH> result(
+        static_cast<unsigned char*>(output), len);
+    SHA256_Final(result.safe_buffer(), &ctx_);
+  }
+
+  SecureHash* Clone() const override {
+    return new SecureHashSHA256(*this);
+  }
+
+  size_t GetHashLength() const override { return SHA256_DIGEST_LENGTH; }
+
+ private:
+  SHA256_CTX ctx_;
+};
+
+}  // namespace
+
+SecureHash* SecureHash::Create(Algorithm algorithm) {
+  switch (algorithm) {
+    case SHA256:
+      return new SecureHashSHA256();
+    default:
+      NOTIMPLEMENTED();
+      return NULL;
+  }
+}
+
+}  // namespace crypto
diff --git a/crypto/secure_hash.h b/crypto/secure_hash.h
new file mode 100644
index 0000000..41ff5d0
--- /dev/null
+++ b/crypto/secure_hash.h
@@ -0,0 +1,44 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SECURE_HASH_H_
+#define CRYPTO_SECURE_HASH_H_
+
+#include <stddef.h>
+
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// A wrapper to calculate secure hashes incrementally, allowing to
+// be used when the full input is not known in advance.
+class CRYPTO_EXPORT SecureHash {
+ public:
+  enum Algorithm {
+    SHA256,
+  };
+
+  SecureHash(const SecureHash&) = delete;
+  SecureHash& operator=(const SecureHash&) = delete;
+
+  virtual ~SecureHash() {}
+
+  static SecureHash* Create(Algorithm type);
+
+  virtual void Update(const void* input, size_t len) = 0;
+  virtual void Finish(void* output, size_t len) = 0;
+  virtual size_t GetHashLength() const = 0;
+
+  // Create a clone of this SecureHash. The returned clone and this both
+  // represent the same hash state. But from this point on, calling
+  // Update()/Finish() on either doesn't affect the state of the other.
+  virtual SecureHash* Clone() const = 0;
+
+ protected:
+  SecureHash() {}
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SECURE_HASH_H_
diff --git a/crypto/secure_hash_unittest.cc b/crypto/secure_hash_unittest.cc
new file mode 100644
index 0000000..176841a
--- /dev/null
+++ b/crypto/secure_hash_unittest.cc
@@ -0,0 +1,82 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/secure_hash.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+
+#include "crypto/sha2.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(SecureHashTest, TestUpdate) {
+  // Example B.3 from FIPS 180-2: long message.
+  std::string input3(500000, 'a');  // 'a' repeated half a million times
+  const int kExpectedHashOfInput3[] = {
+      0xcd, 0xc7, 0x6e, 0x5c, 0x99, 0x14, 0xfb, 0x92, 0x81, 0xa1, 0xc7,
+      0xe2, 0x84, 0xd7, 0x3e, 0x67, 0xf1, 0x80, 0x9a, 0x48, 0xa4, 0x97,
+      0x20, 0x0e, 0x04, 0x6d, 0x39, 0xcc, 0xc7, 0x11, 0x2c, 0xd0};
+
+  uint8_t output3[crypto::kSHA256Length];
+
+  std::unique_ptr<crypto::SecureHash> ctx(
+      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+  ctx->Update(input3.data(), input3.size());
+  ctx->Update(input3.data(), input3.size());
+
+  ctx->Finish(output3, sizeof(output3));
+  for (size_t i = 0; i < crypto::kSHA256Length; i++)
+    EXPECT_EQ(kExpectedHashOfInput3[i], static_cast<int>(output3[i]));
+}
+
+TEST(SecureHashTest, TestClone) {
+  std::string input1(10001, 'a');  // 'a' repeated 10001 times
+  std::string input2(10001, 'd');  // 'd' repeated 10001 times
+
+  const uint8_t kExpectedHashOfInput1[crypto::kSHA256Length] = {
+      0x0c, 0xab, 0x99, 0xa0, 0x58, 0x60, 0x0f, 0xfa, 0xad, 0x12, 0x92,
+      0xd0, 0xc5, 0x3c, 0x05, 0x48, 0xeb, 0xaf, 0x88, 0xdd, 0x1d, 0x01,
+      0x03, 0x03, 0x45, 0x70, 0x5f, 0x01, 0x8a, 0x81, 0x39, 0x09};
+  const uint8_t kExpectedHashOfInput1And2[crypto::kSHA256Length] = {
+      0x4c, 0x8e, 0x26, 0x5a, 0xc3, 0x85, 0x1f, 0x1f, 0xa5, 0x04, 0x1c,
+      0xc7, 0x88, 0x53, 0x1c, 0xc7, 0x80, 0x47, 0x15, 0xfb, 0x47, 0xff,
+      0x72, 0xb1, 0x28, 0x37, 0xb0, 0x4d, 0x6e, 0x22, 0x2e, 0x4d};
+
+  uint8_t output1[crypto::kSHA256Length];
+  uint8_t output2[crypto::kSHA256Length];
+  uint8_t output3[crypto::kSHA256Length];
+
+  std::unique_ptr<crypto::SecureHash> ctx1(
+      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+  ctx1->Update(input1.data(), input1.size());
+
+  std::unique_ptr<crypto::SecureHash> ctx2(ctx1->Clone());
+  std::unique_ptr<crypto::SecureHash> ctx3(ctx2->Clone());
+  // At this point, ctx1, ctx2, and ctx3 are all equivalent and represent the
+  // state after hashing input1.
+
+  // Updating ctx1 and ctx2 with input2 should produce equivalent results.
+  ctx1->Update(input2.data(), input2.size());
+  ctx1->Finish(output1, sizeof(output1));
+
+  ctx2->Update(input2.data(), input2.size());
+  ctx2->Finish(output2, sizeof(output2));
+
+  EXPECT_EQ(0, memcmp(output1, output2, crypto::kSHA256Length));
+  EXPECT_EQ(0,
+            memcmp(output1, kExpectedHashOfInput1And2, crypto::kSHA256Length));
+
+  // Finish() ctx3, which should produce the hash of input1.
+  ctx3->Finish(&output3, sizeof(output3));
+  EXPECT_EQ(0, memcmp(output3, kExpectedHashOfInput1, crypto::kSHA256Length));
+}
+
+TEST(SecureHashTest, TestLength) {
+  std::unique_ptr<crypto::SecureHash> ctx(
+      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+  EXPECT_EQ(crypto::kSHA256Length, ctx->GetHashLength());
+}
diff --git a/crypto/secure_util.cc b/crypto/secure_util.cc
new file mode 100644
index 0000000..bf45091
--- /dev/null
+++ b/crypto/secure_util.cc
@@ -0,0 +1,21 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+
+#include "crypto/secure_util.h"
+
+namespace crypto {
+
+bool SecureMemEqual(const void* s1, const void* s2, size_t n) {
+  const unsigned char* s1_ptr = reinterpret_cast<const unsigned char*>(s1);
+  const unsigned char* s2_ptr = reinterpret_cast<const unsigned char*>(s2);
+  unsigned char tmp = 0;
+  for (size_t i = 0; i < n; ++i, ++s1_ptr, ++s2_ptr)
+    tmp |= *s1_ptr ^ *s2_ptr;
+  return (tmp == 0);
+}
+
+}  // namespace crypto
+
diff --git a/crypto/secure_util.h b/crypto/secure_util.h
new file mode 100644
index 0000000..70a23c6
--- /dev/null
+++ b/crypto/secure_util.h
@@ -0,0 +1,29 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SECURE_UTIL_H_
+#define CRYPTO_SECURE_UTIL_H_
+
+#include <stddef.h>
+
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// Performs a constant-time comparison of two strings, returning true if the
+// strings are equal.
+//
+// For cryptographic operations, comparison functions such as memcmp() may
+// expose side-channel information about input, allowing an attacker to
+// perform timing analysis to determine what the expected bits should be. In
+// order to avoid such attacks, the comparison must execute in constant time,
+// so as to not to reveal to the attacker where the difference(s) are.
+// For an example attack, see
+// http://groups.google.com/group/keyczar-discuss/browse_thread/thread/5571eca0948b2a13
+CRYPTO_EXPORT bool SecureMemEqual(const void* s1, const void* s2, size_t n);
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SECURE_UTIL_H_
+
diff --git a/crypto/sha2.cc b/crypto/sha2.cc
new file mode 100644
index 0000000..da207b7
--- /dev/null
+++ b/crypto/sha2.cc
@@ -0,0 +1,28 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/sha2.h"
+
+#include <stddef.h>
+
+#include <iterator>
+#include <memory>
+
+#include "crypto/secure_hash.h"
+
+namespace crypto {
+
+void SHA256HashString(std::string_view str, void* output, size_t len) {
+  std::unique_ptr<SecureHash> ctx(SecureHash::Create(SecureHash::SHA256));
+  ctx->Update(str.data(), str.length());
+  ctx->Finish(output, len);
+}
+
+std::string SHA256HashString(std::string_view str) {
+  std::string output(kSHA256Length, 0);
+  SHA256HashString(str, std::data(output), output.size());
+  return output;
+}
+
+}  // namespace crypto
diff --git a/crypto/sha2.h b/crypto/sha2.h
new file mode 100644
index 0000000..52b444e
--- /dev/null
+++ b/crypto/sha2.h
@@ -0,0 +1,35 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SHA2_H_
+#define CRYPTO_SHA2_H_
+
+#include <stddef.h>
+
+#include <string>
+#include <string_view>
+
+#include "crypto/crypto_export.h"
+
+namespace crypto {
+
+// These functions perform SHA-256 operations.
+//
+// Functions for SHA-384 and SHA-512 can be added when the need arises.
+
+static const size_t kSHA256Length = 32;  // Length in bytes of a SHA-256 hash.
+
+// Computes the SHA-256 hash of the input string 'str' and stores the first
+// 'len' bytes of the hash in the output buffer 'output'.  If 'len' > 32,
+// only 32 bytes (the full hash) are stored in the 'output' buffer.
+CRYPTO_EXPORT void SHA256HashString(std::string_view str,
+                                    void* output, size_t len);
+
+// Convenience version of the above that returns the result in a 32-byte
+// string.
+CRYPTO_EXPORT std::string SHA256HashString(std::string_view str);
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SHA2_H_
diff --git a/crypto/sha2_unittest.cc b/crypto/sha2_unittest.cc
new file mode 100644
index 0000000..dcfa27a
--- /dev/null
+++ b/crypto/sha2_unittest.cc
@@ -0,0 +1,102 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/sha2.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(Sha256Test, Test1) {
+  // Example B.1 from FIPS 180-2: one-block message.
+  std::string input1 = "abc";
+  int expected1[] = { 0xba, 0x78, 0x16, 0xbf,
+                      0x8f, 0x01, 0xcf, 0xea,
+                      0x41, 0x41, 0x40, 0xde,
+                      0x5d, 0xae, 0x22, 0x23,
+                      0xb0, 0x03, 0x61, 0xa3,
+                      0x96, 0x17, 0x7a, 0x9c,
+                      0xb4, 0x10, 0xff, 0x61,
+                      0xf2, 0x00, 0x15, 0xad };
+
+  uint8_t output1[crypto::kSHA256Length];
+  crypto::SHA256HashString(input1, output1, sizeof(output1));
+  for (size_t i = 0; i < crypto::kSHA256Length; i++)
+    EXPECT_EQ(expected1[i], static_cast<int>(output1[i]));
+
+  uint8_t output_truncated1[4];  // 4 bytes == 32 bits
+  crypto::SHA256HashString(input1,
+                           output_truncated1, sizeof(output_truncated1));
+  for (size_t i = 0; i < sizeof(output_truncated1); i++)
+    EXPECT_EQ(expected1[i], static_cast<int>(output_truncated1[i]));
+}
+
+TEST(Sha256Test, Test1_String) {
+  // Same as the above, but using the wrapper that returns a std::string.
+  // Example B.1 from FIPS 180-2: one-block message.
+  std::string input1 = "abc";
+  int expected1[] = { 0xba, 0x78, 0x16, 0xbf,
+                      0x8f, 0x01, 0xcf, 0xea,
+                      0x41, 0x41, 0x40, 0xde,
+                      0x5d, 0xae, 0x22, 0x23,
+                      0xb0, 0x03, 0x61, 0xa3,
+                      0x96, 0x17, 0x7a, 0x9c,
+                      0xb4, 0x10, 0xff, 0x61,
+                      0xf2, 0x00, 0x15, 0xad };
+
+  std::string output1 = crypto::SHA256HashString(input1);
+  ASSERT_EQ(crypto::kSHA256Length, output1.size());
+  for (size_t i = 0; i < crypto::kSHA256Length; i++)
+    EXPECT_EQ(expected1[i], static_cast<uint8_t>(output1[i]));
+}
+
+TEST(Sha256Test, Test2) {
+  // Example B.2 from FIPS 180-2: multi-block message.
+  std::string input2 =
+      "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
+  int expected2[] = { 0x24, 0x8d, 0x6a, 0x61,
+                      0xd2, 0x06, 0x38, 0xb8,
+                      0xe5, 0xc0, 0x26, 0x93,
+                      0x0c, 0x3e, 0x60, 0x39,
+                      0xa3, 0x3c, 0xe4, 0x59,
+                      0x64, 0xff, 0x21, 0x67,
+                      0xf6, 0xec, 0xed, 0xd4,
+                      0x19, 0xdb, 0x06, 0xc1 };
+
+  uint8_t output2[crypto::kSHA256Length];
+  crypto::SHA256HashString(input2, output2, sizeof(output2));
+  for (size_t i = 0; i < crypto::kSHA256Length; i++)
+    EXPECT_EQ(expected2[i], static_cast<int>(output2[i]));
+
+  uint8_t output_truncated2[6];
+  crypto::SHA256HashString(input2,
+                           output_truncated2, sizeof(output_truncated2));
+  for (size_t i = 0; i < sizeof(output_truncated2); i++)
+    EXPECT_EQ(expected2[i], static_cast<int>(output_truncated2[i]));
+}
+
+TEST(Sha256Test, Test3) {
+  // Example B.3 from FIPS 180-2: long message.
+  std::string input3(1000000, 'a');  // 'a' repeated a million times
+  int expected3[] = { 0xcd, 0xc7, 0x6e, 0x5c,
+                      0x99, 0x14, 0xfb, 0x92,
+                      0x81, 0xa1, 0xc7, 0xe2,
+                      0x84, 0xd7, 0x3e, 0x67,
+                      0xf1, 0x80, 0x9a, 0x48,
+                      0xa4, 0x97, 0x20, 0x0e,
+                      0x04, 0x6d, 0x39, 0xcc,
+                      0xc7, 0x11, 0x2c, 0xd0 };
+
+  uint8_t output3[crypto::kSHA256Length];
+  crypto::SHA256HashString(input3, output3, sizeof(output3));
+  for (size_t i = 0; i < crypto::kSHA256Length; i++)
+    EXPECT_EQ(expected3[i], static_cast<int>(output3[i]));
+
+  uint8_t output_truncated3[12];
+  crypto::SHA256HashString(input3,
+                           output_truncated3, sizeof(output_truncated3));
+  for (size_t i = 0; i < sizeof(output_truncated3); i++)
+    EXPECT_EQ(expected3[i], static_cast<int>(output_truncated3[i]));
+}
diff --git a/crypto/signature_creator.h b/crypto/signature_creator.h
new file mode 100644
index 0000000..fba3315
--- /dev/null
+++ b/crypto/signature_creator.h
@@ -0,0 +1,75 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SIGNATURE_CREATOR_H_
+#define CRYPTO_SIGNATURE_CREATOR_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "build/build_config.h"
+#include "crypto/crypto_export.h"
+
+#if defined(USE_OPENSSL)
+// Forward declaration for openssl/*.h
+typedef struct env_md_ctx_st EVP_MD_CTX;
+#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX)
+// Forward declaration.
+struct SGNContextStr;
+#endif
+
+namespace crypto {
+
+class RSAPrivateKey;
+
+// Signs data using a bare private key (as opposed to a full certificate).
+// Currently can only sign data using SHA-1 or SHA-256 with RSA PKCS#1v1.5.
+class CRYPTO_EXPORT SignatureCreator {
+ public:
+  // The set of supported hash functions. Extend as required.
+  enum HashAlgorithm {
+    SHA1,
+    SHA256,
+  };
+
+  SignatureCreator(const SignatureCreator&) = delete;
+  SignatureCreator& operator=(const SignatureCreator&) = delete;
+
+  ~SignatureCreator();
+
+  // Create an instance. The caller must ensure that the provided PrivateKey
+  // instance outlives the created SignatureCreator. Uses the HashAlgorithm
+  // specified.
+  static SignatureCreator* Create(RSAPrivateKey* key, HashAlgorithm hash_alg);
+
+
+  // Signs the precomputed |hash_alg| digest |data| using private |key| as
+  // specified in PKCS #1 v1.5.
+  static bool Sign(RSAPrivateKey* key,
+                   HashAlgorithm hash_alg,
+                   const uint8_t* data,
+                   int data_len,
+                   std::vector<uint8_t>* signature);
+
+  // Update the signature with more data.
+  bool Update(const uint8_t* data_part, int data_part_len);
+
+  // Finalize the signature.
+  bool Final(std::vector<uint8_t>* signature);
+
+ private:
+  // Private constructor. Use the Create() method instead.
+  SignatureCreator();
+
+#if defined(USE_OPENSSL)
+  EVP_MD_CTX* sign_context_;
+#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX)
+  SGNContextStr* sign_context_;
+#endif
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SIGNATURE_CREATOR_H_
diff --git a/crypto/signature_creator_nss.cc b/crypto/signature_creator_nss.cc
new file mode 100644
index 0000000..1554508
--- /dev/null
+++ b/crypto/signature_creator_nss.cc
@@ -0,0 +1,120 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/signature_creator.h"
+
+#include <cryptohi.h>
+#include <keyhi.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <memory>
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+#include "crypto/rsa_private_key.h"
+
+namespace crypto {
+
+namespace {
+
+SECOidTag ToNSSSigOid(SignatureCreator::HashAlgorithm hash_alg) {
+  switch (hash_alg) {
+    case SignatureCreator::SHA1:
+      return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+    case SignatureCreator::SHA256:
+      return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+  }
+  return SEC_OID_UNKNOWN;
+}
+
+SECOidTag ToNSSHashOid(SignatureCreator::HashAlgorithm hash_alg) {
+  switch (hash_alg) {
+    case SignatureCreator::SHA1:
+      return SEC_OID_SHA1;
+    case SignatureCreator::SHA256:
+      return SEC_OID_SHA256;
+  }
+  return SEC_OID_UNKNOWN;
+}
+
+}  // namespace
+
+SignatureCreator::~SignatureCreator() {
+  if (sign_context_) {
+    SGN_DestroyContext(sign_context_, PR_TRUE);
+    sign_context_ = NULL;
+  }
+}
+
+// static
+SignatureCreator* SignatureCreator::Create(RSAPrivateKey* key,
+                                           HashAlgorithm hash_alg) {
+  std::unique_ptr<SignatureCreator> result(new SignatureCreator);
+  result->sign_context_ = SGN_NewContext(ToNSSSigOid(hash_alg), key->key());
+  if (!result->sign_context_) {
+    NOTREACHED();
+    return NULL;
+  }
+
+  SECStatus rv = SGN_Begin(result->sign_context_);
+  if (rv != SECSuccess) {
+    NOTREACHED();
+    return NULL;
+  }
+
+  return result.release();
+}
+
+// static
+bool SignatureCreator::Sign(RSAPrivateKey* key,
+                            HashAlgorithm hash_alg,
+                            const uint8_t* data,
+                            int data_len,
+                            std::vector<uint8_t>* signature) {
+  SECItem data_item;
+  data_item.type = siBuffer;
+  data_item.data = const_cast<unsigned char*>(data);
+  data_item.len = data_len;
+
+  SECItem signature_item;
+  SECStatus rv = SGN_Digest(key->key(), ToNSSHashOid(hash_alg), &signature_item,
+                            &data_item);
+  if (rv != SECSuccess) {
+    NOTREACHED();
+    return false;
+  }
+  signature->assign(signature_item.data,
+                    signature_item.data + signature_item.len);
+  SECITEM_FreeItem(&signature_item, PR_FALSE);
+  return true;
+}
+
+bool SignatureCreator::Update(const uint8_t* data_part, int data_part_len) {
+  SECStatus rv = SGN_Update(sign_context_, data_part, data_part_len);
+  if (rv != SECSuccess) {
+    NOTREACHED();
+    return false;
+  }
+
+  return true;
+}
+
+bool SignatureCreator::Final(std::vector<uint8_t>* signature) {
+  SECItem signature_item;
+  SECStatus rv = SGN_End(sign_context_, &signature_item);
+  if (rv != SECSuccess) {
+    return false;
+  }
+  signature->assign(signature_item.data,
+                    signature_item.data + signature_item.len);
+  SECITEM_FreeItem(&signature_item, PR_FALSE);
+  return true;
+}
+
+SignatureCreator::SignatureCreator() : sign_context_(NULL) {
+  EnsureNSSInit();
+}
+
+}  // namespace crypto
diff --git a/crypto/signature_creator_unittest.cc b/crypto/signature_creator_unittest.cc
new file mode 100644
index 0000000..1c011f6
--- /dev/null
+++ b/crypto/signature_creator_unittest.cc
@@ -0,0 +1,122 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/signature_creator.h"
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/sha1.h"
+#include "crypto/rsa_private_key.h"
+#include "crypto/sha2.h"
+#include "crypto/signature_verifier.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(SignatureCreatorTest, BasicTest) {
+  // Do a verify round trip.
+  std::unique_ptr<crypto::RSAPrivateKey> key_original(
+      crypto::RSAPrivateKey::Create(1024));
+  ASSERT_TRUE(key_original.get());
+
+  std::vector<uint8_t> key_info;
+  key_original->ExportPrivateKey(&key_info);
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info));
+  ASSERT_TRUE(key.get());
+
+  std::unique_ptr<crypto::SignatureCreator> signer(
+      crypto::SignatureCreator::Create(key.get(),
+                                       crypto::SignatureCreator::SHA1));
+  ASSERT_TRUE(signer.get());
+
+  std::string data("Hello, World!");
+  ASSERT_TRUE(signer->Update(reinterpret_cast<const uint8_t*>(data.c_str()),
+                             data.size()));
+
+  std::vector<uint8_t> signature;
+  ASSERT_TRUE(signer->Final(&signature));
+
+  std::vector<uint8_t> public_key_info;
+  ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));
+
+  crypto::SignatureVerifier verifier;
+  ASSERT_TRUE(verifier.VerifyInit(
+      crypto::SignatureVerifier::RSA_PKCS1_SHA1, &signature.front(),
+      signature.size(), &public_key_info.front(), public_key_info.size()));
+
+  verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(data.c_str()),
+                        data.size());
+  ASSERT_TRUE(verifier.VerifyFinal());
+}
+
+TEST(SignatureCreatorTest, SignDigestTest) {
+  // Do a verify round trip.
+  std::unique_ptr<crypto::RSAPrivateKey> key_original(
+      crypto::RSAPrivateKey::Create(1024));
+  ASSERT_TRUE(key_original.get());
+
+  std::vector<uint8_t> key_info;
+  key_original->ExportPrivateKey(&key_info);
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info));
+  ASSERT_TRUE(key.get());
+
+  std::string data("Hello, World!");
+  std::string sha1 = base::SHA1HashString(data);
+  // Sign sha1 of the input data.
+  std::vector<uint8_t> signature;
+  ASSERT_TRUE(crypto::SignatureCreator::Sign(
+      key.get(), crypto::SignatureCreator::SHA1,
+      reinterpret_cast<const uint8_t*>(sha1.c_str()), sha1.size(), &signature));
+
+  std::vector<uint8_t> public_key_info;
+  ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));
+
+  // Verify the input data.
+  crypto::SignatureVerifier verifier;
+  ASSERT_TRUE(verifier.VerifyInit(
+      crypto::SignatureVerifier::RSA_PKCS1_SHA1, &signature.front(),
+      signature.size(), &public_key_info.front(), public_key_info.size()));
+
+  verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(data.c_str()),
+                        data.size());
+  ASSERT_TRUE(verifier.VerifyFinal());
+}
+
+TEST(SignatureCreatorTest, SignSHA256DigestTest) {
+  // Do a verify round trip.
+  std::unique_ptr<crypto::RSAPrivateKey> key_original(
+      crypto::RSAPrivateKey::Create(1024));
+  ASSERT_TRUE(key_original.get());
+
+  std::vector<uint8_t> key_info;
+  key_original->ExportPrivateKey(&key_info);
+  std::unique_ptr<crypto::RSAPrivateKey> key(
+      crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info));
+  ASSERT_TRUE(key.get());
+
+  std::string data("Hello, World!");
+  std::string sha256 = crypto::SHA256HashString(data);
+  // Sign sha256 of the input data.
+  std::vector<uint8_t> signature;
+  ASSERT_TRUE(crypto::SignatureCreator::Sign(
+      key.get(), crypto::SignatureCreator::HashAlgorithm::SHA256,
+      reinterpret_cast<const uint8_t*>(sha256.c_str()), sha256.size(),
+      &signature));
+
+  std::vector<uint8_t> public_key_info;
+  ASSERT_TRUE(key_original->ExportPublicKey(&public_key_info));
+
+  // Verify the input data.
+  crypto::SignatureVerifier verifier;
+  ASSERT_TRUE(verifier.VerifyInit(
+      crypto::SignatureVerifier::RSA_PKCS1_SHA256, &signature.front(),
+      signature.size(), &public_key_info.front(), public_key_info.size()));
+
+  verifier.VerifyUpdate(reinterpret_cast<const uint8_t*>(data.c_str()),
+                        data.size());
+  ASSERT_TRUE(verifier.VerifyFinal());
+}
diff --git a/crypto/signature_verifier.h b/crypto/signature_verifier.h
new file mode 100644
index 0000000..a02f5aa
--- /dev/null
+++ b/crypto/signature_verifier.h
@@ -0,0 +1,134 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SIGNATURE_VERIFIER_H_
+#define CRYPTO_SIGNATURE_VERIFIER_H_
+
+#include <stdint.h>
+
+#include <vector>
+
+#include "build/build_config.h"
+#include "crypto/crypto_export.h"
+
+#if defined(USE_OPENSSL)
+typedef struct env_md_st EVP_MD;
+typedef struct evp_pkey_ctx_st EVP_PKEY_CTX;
+#else
+typedef struct HASHContextStr HASHContext;
+typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
+typedef struct VFYContextStr VFYContext;
+#endif
+
+namespace crypto {
+
+// The SignatureVerifier class verifies a signature using a bare public key
+// (as opposed to a certificate).
+class CRYPTO_EXPORT SignatureVerifier {
+ public:
+  // The set of supported hash functions. Extend as required.
+  enum HashAlgorithm {
+    SHA1,
+    SHA256,
+  };
+
+  // The set of supported signature algorithms. Extend as required.
+  enum SignatureAlgorithm {
+    RSA_PKCS1_SHA1,
+    RSA_PKCS1_SHA256,
+    ECDSA_SHA256,
+  };
+
+  SignatureVerifier();
+  ~SignatureVerifier();
+
+  // Streaming interface:
+
+  // Initiates a signature verification operation.  This should be followed
+  // by one or more VerifyUpdate calls and a VerifyFinal call.
+  // NOTE: for RSA-PSS signatures, use VerifyInitRSAPSS instead.
+  //
+  // The signature is encoded according to the signature algorithm.
+  //
+  // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo
+  // structure, which contains not only the public key but also its type
+  // (algorithm):
+  //   SubjectPublicKeyInfo  ::=  SEQUENCE  {
+  //       algorithm            AlgorithmIdentifier,
+  //       subjectPublicKey     BIT STRING  }
+  bool VerifyInit(SignatureAlgorithm signature_algorithm,
+                  const uint8_t* signature,
+                  int signature_len,
+                  const uint8_t* public_key_info,
+                  int public_key_info_len);
+
+  // Initiates a RSA-PSS signature verification operation.  This should be
+  // followed by one or more VerifyUpdate calls and a VerifyFinal call.
+  //
+  // The RSA-PSS signature algorithm parameters are specified with the
+  // |hash_alg|, |mask_hash_alg|, and |salt_len| arguments.
+  //
+  // An RSA-PSS signature is a nonnegative integer encoded as a byte string
+  // (of the same length as the RSA modulus) in big-endian byte order. It
+  // must not be further encoded in an ASN.1 BIT STRING.
+  //
+  // The public key is specified as a DER encoded ASN.1 SubjectPublicKeyInfo
+  // structure, which contains not only the public key but also its type
+  // (algorithm):
+  //   SubjectPublicKeyInfo  ::=  SEQUENCE  {
+  //       algorithm            AlgorithmIdentifier,
+  //       subjectPublicKey     BIT STRING  }
+  bool VerifyInitRSAPSS(HashAlgorithm hash_alg,
+                        HashAlgorithm mask_hash_alg,
+                        int salt_len,
+                        const uint8_t* signature,
+                        int signature_len,
+                        const uint8_t* public_key_info,
+                        int public_key_info_len);
+
+  // Feeds a piece of the data to the signature verifier.
+  void VerifyUpdate(const uint8_t* data_part, int data_part_len);
+
+  // Concludes a signature verification operation.  Returns true if the
+  // signature is valid.  Returns false if the signature is invalid or an
+  // error occurred.
+  bool VerifyFinal();
+
+ private:
+#if defined(USE_OPENSSL)
+  bool CommonInit(int pkey_type,
+                  const EVP_MD* digest,
+                  const uint8_t* signature,
+                  int signature_len,
+                  const uint8_t* public_key_info,
+                  int public_key_info_len,
+                  EVP_PKEY_CTX** pkey_ctx);
+#else
+  static SECKEYPublicKey* DecodePublicKeyInfo(const uint8_t* public_key_info,
+                                              int public_key_info_len);
+#endif
+
+  void Reset();
+
+  std::vector<uint8_t> signature_;
+
+#if defined(USE_OPENSSL)
+  struct VerifyContext;
+  VerifyContext* verify_context_;
+#else
+  // Used for all signature types except RSA-PSS.
+  VFYContext* vfy_context_;
+
+  // Used for RSA-PSS signatures.
+  HashAlgorithm hash_alg_;
+  HashAlgorithm mask_hash_alg_;
+  unsigned int salt_len_;
+  SECKEYPublicKey* public_key_;
+  HASHContext* hash_context_;
+#endif
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SIGNATURE_VERIFIER_H_
diff --git a/crypto/signature_verifier_nss.cc b/crypto/signature_verifier_nss.cc
new file mode 100644
index 0000000..2a4a10c
--- /dev/null
+++ b/crypto/signature_verifier_nss.cc
@@ -0,0 +1,213 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/signature_verifier.h"
+
+#include <cryptohi.h>
+#include <keyhi.h>
+#include <pk11pub.h>
+#include <secerr.h>
+#include <sechash.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+#include "crypto/third_party/nss/chromium-nss.h"
+
+namespace crypto {
+
+namespace {
+
+HASH_HashType ToNSSHashType(SignatureVerifier::HashAlgorithm hash_alg) {
+  switch (hash_alg) {
+    case SignatureVerifier::SHA1:
+      return HASH_AlgSHA1;
+    case SignatureVerifier::SHA256:
+      return HASH_AlgSHA256;
+  }
+  return HASH_AlgNULL;
+}
+
+SECOidTag ToNSSSignatureType(SignatureVerifier::SignatureAlgorithm sig_alg) {
+  switch (sig_alg) {
+    case SignatureVerifier::RSA_PKCS1_SHA1:
+      return SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
+    case SignatureVerifier::RSA_PKCS1_SHA256:
+      return SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
+    case SignatureVerifier::ECDSA_SHA256:
+      return SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE;
+  }
+  return SEC_OID_UNKNOWN;
+}
+
+SECStatus VerifyRSAPSS_End(SECKEYPublicKey* public_key,
+                           HASHContext* hash_context,
+                           HASH_HashType mask_hash_alg,
+                           unsigned int salt_len,
+                           const unsigned char* signature,
+                           unsigned int signature_len) {
+  unsigned int hash_len = HASH_ResultLenContext(hash_context);
+  std::vector<unsigned char> hash(hash_len);
+  HASH_End(hash_context, &hash[0], &hash_len, hash.size());
+
+  unsigned int modulus_len = SECKEY_PublicKeyStrength(public_key);
+  if (signature_len != modulus_len) {
+    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+    return SECFailure;
+  }
+  std::vector<unsigned char> enc(signature_len);
+  SECStatus rv = PK11_PubEncryptRaw(public_key, &enc[0],
+                                    const_cast<unsigned char*>(signature),
+                                    signature_len, NULL);
+  if (rv != SECSuccess) {
+    LOG(WARNING) << "PK11_PubEncryptRaw failed";
+    return rv;
+  }
+  return emsa_pss_verify(&hash[0], &enc[0], enc.size(),
+                         HASH_GetType(hash_context), mask_hash_alg,
+                         salt_len);
+}
+
+}  // namespace
+
+SignatureVerifier::SignatureVerifier()
+    : vfy_context_(NULL),
+      hash_alg_(SHA1),
+      mask_hash_alg_(SHA1),
+      salt_len_(0),
+      public_key_(NULL),
+      hash_context_(NULL) {
+  EnsureNSSInit();
+}
+
+SignatureVerifier::~SignatureVerifier() {
+  Reset();
+}
+
+bool SignatureVerifier::VerifyInit(SignatureAlgorithm signature_algorithm,
+                                   const uint8_t* signature,
+                                   int signature_len,
+                                   const uint8_t* public_key_info,
+                                   int public_key_info_len) {
+  if (vfy_context_ || hash_context_)
+    return false;
+
+  signature_.assign(signature, signature + signature_len);
+
+  SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
+                                                    public_key_info_len);
+  if (!public_key)
+    return false;
+
+  SECItem sig;
+  sig.type = siBuffer;
+  sig.data = const_cast<uint8_t*>(signature);
+  sig.len = signature_len;
+  vfy_context_ = VFY_CreateContext(
+      public_key, &sig, ToNSSSignatureType(signature_algorithm), nullptr);
+  SECKEY_DestroyPublicKey(public_key);  // Done with public_key.
+  if (!vfy_context_) {
+    // A corrupted RSA signature could be detected without the data, so
+    // VFY_CreateContextWithAlgorithmID may fail with SEC_ERROR_BAD_SIGNATURE
+    // (-8182).
+    return false;
+  }
+
+  if (VFY_Begin(vfy_context_) != SECSuccess) {
+    NOTREACHED();
+    return false;
+  }
+  return true;
+}
+
+bool SignatureVerifier::VerifyInitRSAPSS(HashAlgorithm hash_alg,
+                                         HashAlgorithm mask_hash_alg,
+                                         int salt_len,
+                                         const uint8_t* signature,
+                                         int signature_len,
+                                         const uint8_t* public_key_info,
+                                         int public_key_info_len) {
+  if (vfy_context_ || hash_context_)
+    return false;
+
+  signature_.assign(signature, signature + signature_len);
+
+  SECKEYPublicKey* public_key = DecodePublicKeyInfo(public_key_info,
+                                                    public_key_info_len);
+  if (!public_key)
+    return false;
+
+  public_key_ = public_key;
+  hash_alg_ = hash_alg;
+  mask_hash_alg_ = mask_hash_alg;
+  salt_len_ = salt_len;
+  hash_context_ = HASH_Create(ToNSSHashType(hash_alg_));
+  if (!hash_context_)
+    return false;
+  HASH_Begin(hash_context_);
+  return true;
+}
+
+void SignatureVerifier::VerifyUpdate(const uint8_t* data_part,
+                                     int data_part_len) {
+  if (vfy_context_) {
+    SECStatus rv = VFY_Update(vfy_context_, data_part, data_part_len);
+    DCHECK_EQ(SECSuccess, rv);
+  } else {
+    HASH_Update(hash_context_, data_part, data_part_len);
+  }
+}
+
+bool SignatureVerifier::VerifyFinal() {
+  SECStatus rv;
+  if (vfy_context_) {
+    rv = VFY_End(vfy_context_);
+  } else {
+    rv = VerifyRSAPSS_End(public_key_, hash_context_,
+                          ToNSSHashType(mask_hash_alg_), salt_len_,
+                          signature_.data(),
+                          signature_.size());
+  }
+  Reset();
+
+  // If signature verification fails, the error code is
+  // SEC_ERROR_BAD_SIGNATURE (-8182).
+  return (rv == SECSuccess);
+}
+
+// static
+SECKEYPublicKey* SignatureVerifier::DecodePublicKeyInfo(
+    const uint8_t* public_key_info,
+    int public_key_info_len) {
+  CERTSubjectPublicKeyInfo* spki = NULL;
+  SECItem spki_der;
+  spki_der.type = siBuffer;
+  spki_der.data = const_cast<uint8_t*>(public_key_info);
+  spki_der.len = public_key_info_len;
+  spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_der);
+  if (!spki)
+    return NULL;
+  SECKEYPublicKey* public_key = SECKEY_ExtractPublicKey(spki);
+  SECKEY_DestroySubjectPublicKeyInfo(spki);  // Done with spki.
+  return public_key;
+}
+
+void SignatureVerifier::Reset() {
+  if (vfy_context_) {
+    VFY_DestroyContext(vfy_context_, PR_TRUE);
+    vfy_context_ = NULL;
+  }
+  if (hash_context_) {
+    HASH_Destroy(hash_context_);
+    hash_context_ = NULL;
+  }
+  if (public_key_) {
+    SECKEY_DestroyPublicKey(public_key_);
+    public_key_ = NULL;
+  }
+  signature_.clear();
+}
+
+}  // namespace crypto
diff --git a/crypto/signature_verifier_unittest.cc b/crypto/signature_verifier_unittest.cc
new file mode 100644
index 0000000..8ea8bfe
--- /dev/null
+++ b/crypto/signature_verifier_unittest.cc
@@ -0,0 +1,1143 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/signature_verifier.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "base/numerics/safe_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(SignatureVerifierTest, BasicTest) {
+  // The input data in this test comes from real certificates.
+  //
+  // tbs_certificate ("to-be-signed certificate", the part of a certificate that
+  // is signed), signature, and algorithm come from the certificate of
+  // bugs.webkit.org.
+  //
+  // public_key_info comes from the certificate of the issuer, Go Daddy Secure
+  // Certification Authority.
+  //
+  // The bytes in the array initializers are formatted to expose the DER
+  // encoding of the ASN.1 structures.
+
+  // The data that is signed is the following ASN.1 structure:
+  //    TBSCertificate  ::=  SEQUENCE  {
+  //        ...  -- omitted, not important
+  //        }
+  const uint8_t tbs_certificate[1017] = {
+      0x30, 0x82, 0x03, 0xf5,  // a SEQUENCE of length 1013 (0x3f5)
+      0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x43, 0xdd, 0x63, 0x30, 0x0d,
+      0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05,
+      0x00, 0x30, 0x81, 0xca, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+      0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+      0x04, 0x08, 0x13, 0x07, 0x41, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x61, 0x31,
+      0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0a, 0x53, 0x63,
+      0x6f, 0x74, 0x74, 0x73, 0x64, 0x61, 0x6c, 0x65, 0x31, 0x1a, 0x30, 0x18,
+      0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x47, 0x6f, 0x44, 0x61, 0x64,
+      0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
+      0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x68,
+      0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66,
+      0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64,
+      0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73,
+      0x69, 0x74, 0x6f, 0x72, 0x79, 0x31, 0x30, 0x30, 0x2e, 0x06, 0x03, 0x55,
+      0x04, 0x03, 0x13, 0x27, 0x47, 0x6f, 0x20, 0x44, 0x61, 0x64, 0x64, 0x79,
+      0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x43, 0x65, 0x72, 0x74,
+      0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x75,
+      0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x31, 0x11, 0x30, 0x0f, 0x06,
+      0x03, 0x55, 0x04, 0x05, 0x13, 0x08, 0x30, 0x37, 0x39, 0x36, 0x39, 0x32,
+      0x38, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x38, 0x30, 0x33, 0x31, 0x38,
+      0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x31, 0x30,
+      0x33, 0x31, 0x38, 0x32, 0x33, 0x33, 0x35, 0x31, 0x39, 0x5a, 0x30, 0x79,
+      0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+      0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
+      0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x12,
+      0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x75, 0x70,
+      0x65, 0x72, 0x74, 0x69, 0x6e, 0x6f, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
+      0x55, 0x04, 0x0a, 0x13, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x49,
+      0x6e, 0x63, 0x2e, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0b,
+      0x13, 0x0c, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x46, 0x6f, 0x72,
+      0x67, 0x65, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+      0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69, 0x74, 0x2e, 0x6f, 0x72,
+      0x67, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+      0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30,
+      0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xa7, 0x62, 0x79, 0x41, 0xda, 0x28,
+      0xf2, 0xc0, 0x4f, 0xe0, 0x25, 0xaa, 0xa1, 0x2e, 0x3b, 0x30, 0x94, 0xb5,
+      0xc9, 0x26, 0x3a, 0x1b, 0xe2, 0xd0, 0xcc, 0xa2, 0x95, 0xe2, 0x91, 0xc0,
+      0xf0, 0x40, 0x9e, 0x27, 0x6e, 0xbd, 0x6e, 0xde, 0x7c, 0xb6, 0x30, 0x5c,
+      0xb8, 0x9b, 0x01, 0x2f, 0x92, 0x04, 0xa1, 0xef, 0x4a, 0xb1, 0x6c, 0xb1,
+      0x7e, 0x8e, 0xcd, 0xa6, 0xf4, 0x40, 0x73, 0x1f, 0x2c, 0x96, 0xad, 0xff,
+      0x2a, 0x6d, 0x0e, 0xba, 0x52, 0x84, 0x83, 0xb0, 0x39, 0xee, 0xc9, 0x39,
+      0xdc, 0x1e, 0x34, 0xd0, 0xd8, 0x5d, 0x7a, 0x09, 0xac, 0xa9, 0xee, 0xca,
+      0x65, 0xf6, 0x85, 0x3a, 0x6b, 0xee, 0xe4, 0x5c, 0x5e, 0xf8, 0xda, 0xd1,
+      0xce, 0x88, 0x47, 0xcd, 0x06, 0x21, 0xe0, 0xb9, 0x4b, 0xe4, 0x07, 0xcb,
+      0x57, 0xdc, 0xca, 0x99, 0x54, 0xf7, 0x0e, 0xd5, 0x17, 0x95, 0x05, 0x2e,
+      0xe9, 0xb1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x01, 0xce, 0x30,
+      0x82, 0x01, 0xca, 0x30, 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02,
+      0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03,
+      0x02, 0x05, 0xa0, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16,
+      0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,
+      0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x57,
+      0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x50, 0x30, 0x4e, 0x30, 0x4c, 0xa0,
+      0x4a, 0xa0, 0x48, 0x86, 0x46, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f,
+      0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73,
+      0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
+      0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x2f,
+      0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79, 0x65, 0x78, 0x74, 0x65, 0x6e,
+      0x64, 0x65, 0x64, 0x69, 0x73, 0x73, 0x75, 0x69, 0x6e, 0x67, 0x33, 0x2e,
+      0x63, 0x72, 0x6c, 0x30, 0x52, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04, 0x4b,
+      0x30, 0x49, 0x30, 0x47, 0x06, 0x0b, 0x60, 0x86, 0x48, 0x01, 0x86, 0xfd,
+      0x6d, 0x01, 0x07, 0x17, 0x02, 0x30, 0x38, 0x30, 0x36, 0x06, 0x08, 0x2b,
+      0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x2a, 0x68, 0x74, 0x74,
+      0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
+      0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64, 0x79,
+      0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
+      0x6f, 0x72, 0x79, 0x30, 0x7f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+      0x07, 0x01, 0x01, 0x04, 0x73, 0x30, 0x71, 0x30, 0x23, 0x06, 0x08, 0x2b,
+      0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x17, 0x68, 0x74, 0x74,
+      0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x6f, 0x64,
+      0x61, 0x64, 0x64, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x4a, 0x06, 0x08,
+      0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3e, 0x68, 0x74,
+      0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
+      0x63, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x67, 0x6f, 0x64, 0x61, 0x64, 0x64,
+      0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69,
+      0x74, 0x6f, 0x72, 0x79, 0x2f, 0x67, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65,
+      0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x2e, 0x63, 0x72, 0x74,
+      0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x48,
+      0xdf, 0x60, 0x32, 0xcc, 0x89, 0x01, 0xb6, 0xdc, 0x2f, 0xe3, 0x73, 0xb5,
+      0x9c, 0x16, 0x58, 0x32, 0x68, 0xa9, 0xc3, 0x30, 0x1f, 0x06, 0x03, 0x55,
+      0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xfd, 0xac, 0x61, 0x32,
+      0x93, 0x6c, 0x45, 0xd6, 0xe2, 0xee, 0x85, 0x5f, 0x9a, 0xba, 0xe7, 0x76,
+      0x99, 0x68, 0xcc, 0xe7, 0x30, 0x23, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04,
+      0x1c, 0x30, 0x1a, 0x82, 0x0c, 0x2a, 0x2e, 0x77, 0x65, 0x62, 0x6b, 0x69,
+      0x74, 0x2e, 0x6f, 0x72, 0x67, 0x82, 0x0a, 0x77, 0x65, 0x62, 0x6b, 0x69,
+      0x74, 0x2e, 0x6f, 0x72, 0x67};
+
+  // RSA signature, a big integer in the big-endian byte order.
+  const uint8_t signature[256] = {
+      0x1e, 0x6a, 0xe7, 0xe0, 0x4f, 0xe7, 0x4d, 0xd0, 0x69, 0x7c, 0xf8, 0x8f,
+      0x99, 0xb4, 0x18, 0x95, 0x36, 0x24, 0x0f, 0x0e, 0xa3, 0xea, 0x34, 0x37,
+      0xf4, 0x7d, 0xd5, 0x92, 0x35, 0x53, 0x72, 0x76, 0x3f, 0x69, 0xf0, 0x82,
+      0x56, 0xe3, 0x94, 0x7a, 0x1d, 0x1a, 0x81, 0xaf, 0x9f, 0xc7, 0x43, 0x01,
+      0x64, 0xd3, 0x7c, 0x0d, 0xc8, 0x11, 0x4e, 0x4a, 0xe6, 0x1a, 0xc3, 0x01,
+      0x74, 0xe8, 0x35, 0x87, 0x5c, 0x61, 0xaa, 0x8a, 0x46, 0x06, 0xbe, 0x98,
+      0x95, 0x24, 0x9e, 0x01, 0xe3, 0xe6, 0xa0, 0x98, 0xee, 0x36, 0x44, 0x56,
+      0x8d, 0x23, 0x9c, 0x65, 0xea, 0x55, 0x6a, 0xdf, 0x66, 0xee, 0x45, 0xe8,
+      0xa0, 0xe9, 0x7d, 0x9a, 0xba, 0x94, 0xc5, 0xc8, 0xc4, 0x4b, 0x98, 0xff,
+      0x9a, 0x01, 0x31, 0x6d, 0xf9, 0x2b, 0x58, 0xe7, 0xe7, 0x2a, 0xc5, 0x4d,
+      0xbb, 0xbb, 0xcd, 0x0d, 0x70, 0xe1, 0xad, 0x03, 0xf5, 0xfe, 0xf4, 0x84,
+      0x71, 0x08, 0xd2, 0xbc, 0x04, 0x7b, 0x26, 0x1c, 0xa8, 0x0f, 0x9c, 0xd8,
+      0x12, 0x6a, 0x6f, 0x2b, 0x67, 0xa1, 0x03, 0x80, 0x9a, 0x11, 0x0b, 0xe9,
+      0xe0, 0xb5, 0xb3, 0xb8, 0x19, 0x4e, 0x0c, 0xa4, 0xd9, 0x2b, 0x3b, 0xc2,
+      0xca, 0x20, 0xd3, 0x0c, 0xa4, 0xff, 0x93, 0x13, 0x1f, 0xfc, 0xba, 0x94,
+      0x93, 0x8c, 0x64, 0x15, 0x2e, 0x28, 0xa9, 0x55, 0x8c, 0x2c, 0x48, 0xd3,
+      0xd3, 0xc1, 0x50, 0x69, 0x19, 0xe8, 0x34, 0xd3, 0xf1, 0x04, 0x9f, 0x0a,
+      0x7a, 0x21, 0x87, 0xbf, 0xb9, 0x59, 0x37, 0x2e, 0xf4, 0x71, 0xa5, 0x3e,
+      0xbe, 0xcd, 0x70, 0x83, 0x18, 0xf8, 0x8a, 0x72, 0x85, 0x45, 0x1f, 0x08,
+      0x01, 0x6f, 0x37, 0xf5, 0x2b, 0x7b, 0xea, 0xb9, 0x8b, 0xa3, 0xcc, 0xfd,
+      0x35, 0x52, 0xdd, 0x66, 0xde, 0x4f, 0x30, 0xc5, 0x73, 0x81, 0xb6, 0xe8,
+      0x3c, 0xd8, 0x48, 0x8a};
+
+  // The public key is specified as the following ASN.1 structure:
+  //   SubjectPublicKeyInfo  ::=  SEQUENCE  {
+  //       algorithm            AlgorithmIdentifier,
+  //       subjectPublicKey     BIT STRING  }
+  const uint8_t public_key_info[294] = {
+      0x30, 0x82, 0x01, 0x22,  // a SEQUENCE of length 290 (0x122)
+      // algorithm
+      0x30, 0x0d,  // a SEQUENCE of length 13
+      0x06, 0x09,  // an OBJECT IDENTIFIER of length 9
+      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+      0x00,  // a NULL of length 0
+      // subjectPublicKey
+      0x03, 0x82, 0x01, 0x0f,  // a BIT STRING of length 271 (0x10f)
+      0x00,                    // number of unused bits
+      0x30, 0x82, 0x01, 0x0a,  // a SEQUENCE of length 266 (0x10a)
+      // modulus
+      0x02, 0x82, 0x01, 0x01,  // an INTEGER of length 257 (0x101)
+      0x00, 0xc4, 0x2d, 0xd5, 0x15, 0x8c, 0x9c, 0x26, 0x4c, 0xec, 0x32, 0x35,
+      0xeb, 0x5f, 0xb8, 0x59, 0x01, 0x5a, 0xa6, 0x61, 0x81, 0x59, 0x3b, 0x70,
+      0x63, 0xab, 0xe3, 0xdc, 0x3d, 0xc7, 0x2a, 0xb8, 0xc9, 0x33, 0xd3, 0x79,
+      0xe4, 0x3a, 0xed, 0x3c, 0x30, 0x23, 0x84, 0x8e, 0xb3, 0x30, 0x14, 0xb6,
+      0xb2, 0x87, 0xc3, 0x3d, 0x95, 0x54, 0x04, 0x9e, 0xdf, 0x99, 0xdd, 0x0b,
+      0x25, 0x1e, 0x21, 0xde, 0x65, 0x29, 0x7e, 0x35, 0xa8, 0xa9, 0x54, 0xeb,
+      0xf6, 0xf7, 0x32, 0x39, 0xd4, 0x26, 0x55, 0x95, 0xad, 0xef, 0xfb, 0xfe,
+      0x58, 0x86, 0xd7, 0x9e, 0xf4, 0x00, 0x8d, 0x8c, 0x2a, 0x0c, 0xbd, 0x42,
+      0x04, 0xce, 0xa7, 0x3f, 0x04, 0xf6, 0xee, 0x80, 0xf2, 0xaa, 0xef, 0x52,
+      0xa1, 0x69, 0x66, 0xda, 0xbe, 0x1a, 0xad, 0x5d, 0xda, 0x2c, 0x66, 0xea,
+      0x1a, 0x6b, 0xbb, 0xe5, 0x1a, 0x51, 0x4a, 0x00, 0x2f, 0x48, 0xc7, 0x98,
+      0x75, 0xd8, 0xb9, 0x29, 0xc8, 0xee, 0xf8, 0x66, 0x6d, 0x0a, 0x9c, 0xb3,
+      0xf3, 0xfc, 0x78, 0x7c, 0xa2, 0xf8, 0xa3, 0xf2, 0xb5, 0xc3, 0xf3, 0xb9,
+      0x7a, 0x91, 0xc1, 0xa7, 0xe6, 0x25, 0x2e, 0x9c, 0xa8, 0xed, 0x12, 0x65,
+      0x6e, 0x6a, 0xf6, 0x12, 0x44, 0x53, 0x70, 0x30, 0x95, 0xc3, 0x9c, 0x2b,
+      0x58, 0x2b, 0x3d, 0x08, 0x74, 0x4a, 0xf2, 0xbe, 0x51, 0xb0, 0xbf, 0x87,
+      0xd0, 0x4c, 0x27, 0x58, 0x6b, 0xb5, 0x35, 0xc5, 0x9d, 0xaf, 0x17, 0x31,
+      0xf8, 0x0b, 0x8f, 0xee, 0xad, 0x81, 0x36, 0x05, 0x89, 0x08, 0x98, 0xcf,
+      0x3a, 0xaf, 0x25, 0x87, 0xc0, 0x49, 0xea, 0xa7, 0xfd, 0x67, 0xf7, 0x45,
+      0x8e, 0x97, 0xcc, 0x14, 0x39, 0xe2, 0x36, 0x85, 0xb5, 0x7e, 0x1a, 0x37,
+      0xfd, 0x16, 0xf6, 0x71, 0x11, 0x9a, 0x74, 0x30, 0x16, 0xfe, 0x13, 0x94,
+      0xa3, 0x3f, 0x84, 0x0d, 0x4f,
+      // public exponent
+      0x02, 0x03,  // an INTEGER of length 3
+      0x01, 0x00, 0x01};
+
+  // We use the signature verifier to perform four signature verification
+  // tests.
+  crypto::SignatureVerifier verifier;
+  bool ok;
+
+  // Test  1: feed all of the data to the verifier at once (a single
+  // VerifyUpdate call).
+  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature,
+                           sizeof(signature), public_key_info,
+                           sizeof(public_key_info));
+  EXPECT_TRUE(ok);
+  verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate));
+  ok = verifier.VerifyFinal();
+  EXPECT_TRUE(ok);
+
+  // Test 2: feed the data to the verifier in three parts (three VerifyUpdate
+  // calls).
+  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature,
+                           sizeof(signature), public_key_info,
+                           sizeof(public_key_info));
+  EXPECT_TRUE(ok);
+  verifier.VerifyUpdate(tbs_certificate, 256);
+  verifier.VerifyUpdate(tbs_certificate + 256, 256);
+  verifier.VerifyUpdate(tbs_certificate + 512, sizeof(tbs_certificate) - 512);
+  ok = verifier.VerifyFinal();
+  EXPECT_TRUE(ok);
+
+  // Test 3: verify the signature with incorrect data.
+  uint8_t bad_tbs_certificate[sizeof(tbs_certificate)];
+  memcpy(bad_tbs_certificate, tbs_certificate, sizeof(tbs_certificate));
+  bad_tbs_certificate[10] += 1;  // Corrupt one byte of the data.
+  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature,
+                           sizeof(signature), public_key_info,
+                           sizeof(public_key_info));
+  EXPECT_TRUE(ok);
+  verifier.VerifyUpdate(bad_tbs_certificate, sizeof(bad_tbs_certificate));
+  ok = verifier.VerifyFinal();
+  EXPECT_FALSE(ok);
+
+  // Test 4: verify a bad signature.
+  uint8_t bad_signature[sizeof(signature)];
+  memcpy(bad_signature, signature, sizeof(signature));
+  bad_signature[10] += 1;  // Corrupt one byte of the signature.
+  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1,
+                           bad_signature, sizeof(bad_signature),
+                           public_key_info, sizeof(public_key_info));
+
+  // A crypto library (e.g., NSS) may detect that the signature is corrupted
+  // and cause VerifyInit to return false, so it is fine for 'ok' to be false.
+  if (ok) {
+    verifier.VerifyUpdate(tbs_certificate, sizeof(tbs_certificate));
+    ok = verifier.VerifyFinal();
+    EXPECT_FALSE(ok);
+  }
+
+  // Test 5: import an invalid key.
+  uint8_t bad_public_key_info[sizeof(public_key_info)];
+  memcpy(bad_public_key_info, public_key_info, sizeof(public_key_info));
+  bad_public_key_info[0] += 1;  // Corrupt part of the SPKI syntax.
+  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature,
+                           sizeof(signature), bad_public_key_info,
+                           sizeof(bad_public_key_info));
+  EXPECT_FALSE(ok);
+
+  // Test 6: import a key with extra data.
+  uint8_t long_public_key_info[sizeof(public_key_info) + 5];
+  memset(long_public_key_info, 0, sizeof(long_public_key_info));
+  memcpy(long_public_key_info, public_key_info, sizeof(public_key_info));
+  ok = verifier.VerifyInit(crypto::SignatureVerifier::RSA_PKCS1_SHA1, signature,
+                           sizeof(signature), long_public_key_info,
+                           sizeof(long_public_key_info));
+  EXPECT_FALSE(ok);
+}
+
+//////////////////////////////////////////////////////////////////////
+//
+// RSA-PSS signature verification known answer test
+//
+//////////////////////////////////////////////////////////////////////
+
+// The following RSA-PSS signature test vectors come from the pss-vect.txt
+// file downloaded from
+// ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip.
+//
+// For each key, 6 random messages of length between 1 and 256 octets have
+// been RSASSA-PSS signed.
+//
+// Hash function: SHA-1
+// Mask generation function: MGF1 with SHA-1
+// Salt length: 20 octets
+
+// Example 1: A 1024-bit RSA Key Pair"
+
+// RSA modulus n:
+static const char rsa_modulus_n_1[] =
+  "a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1 "
+  "56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91 "
+  "d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3 "
+  "94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df "
+  "d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77 "
+  "c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1 "
+  "05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4 "
+  "ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37 ";
+// RSA public exponent e: "
+static const char rsa_public_exponent_e_1[] =
+  "01 00 01 ";
+
+// RSASSA-PSS Signature Example 1.1
+// Message to be signed:
+static const char message_1_1[] =
+  "cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26 "
+  "d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6 "
+  "23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15 "
+  "6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76 "
+  "97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3 "
+  "d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0 "
+  "61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29 "
+  "cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61 "
+  "93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08 "
+  "a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c "
+  "29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca "
+  "b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16 "
+  "be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed "
+  "1b 73 31 8b 75 0a 01 67 d0 ";
+// Salt:
+static const char salt_1_1[] =
+  "de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f "
+  "3e 67 76 af ";
+// Signature:
+static const char signature_1_1[] =
+  "90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71 "
+  "fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87 "
+  "e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2 "
+  "26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15 "
+  "df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9 "
+  "c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65 "
+  "98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4 "
+  "c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c ";
+
+// RSASSA-PSS Signature Example 1.2
+// Message to be signed:
+static const char message_1_2[] =
+  "85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c "
+  "f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f "
+  "71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13 "
+  "22 6b 9e ";
+// Salt:
+static const char salt_1_2[] =
+  "ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f "
+  "d5 6d f4 2d ";
+// Signature:
+static const char signature_1_2[] =
+  "3e f7 f4 6e 83 1b f9 2b 32 27 41 42 a5 85 ff ce "
+  "fb dc a7 b3 2a e9 0d 10 fb 0f 0c 72 99 84 f0 4e "
+  "f2 9a 9d f0 78 07 75 ce 43 73 9b 97 83 83 90 db "
+  "0a 55 05 e6 3d e9 27 02 8d 9d 29 b2 19 ca 2c 45 "
+  "17 83 25 58 a5 5d 69 4a 6d 25 b9 da b6 60 03 c4 "
+  "cc cd 90 78 02 19 3b e5 17 0d 26 14 7d 37 b9 35 "
+  "90 24 1b e5 1c 25 05 5f 47 ef 62 75 2c fb e2 14 "
+  "18 fa fe 98 c2 2c 4d 4d 47 72 4f db 56 69 e8 43 ";
+
+// RSASSA-PSS Signature Example 1.3
+// Message to be signed:
+static const char message_1_3[] =
+  "a4 b1 59 94 17 61 c4 0c 6a 82 f2 b8 0d 1b 94 f5 "
+  "aa 26 54 fd 17 e1 2d 58 88 64 67 9b 54 cd 04 ef "
+  "8b d0 30 12 be 8d c3 7f 4b 83 af 79 63 fa ff 0d "
+  "fa 22 54 77 43 7c 48 01 7f f2 be 81 91 cf 39 55 "
+  "fc 07 35 6e ab 3f 32 2f 7f 62 0e 21 d2 54 e5 db "
+  "43 24 27 9f e0 67 e0 91 0e 2e 81 ca 2c ab 31 c7 "
+  "45 e6 7a 54 05 8e b5 0d 99 3c db 9e d0 b4 d0 29 "
+  "c0 6d 21 a9 4c a6 61 c3 ce 27 fa e1 d6 cb 20 f4 "
+  "56 4d 66 ce 47 67 58 3d 0e 5f 06 02 15 b5 90 17 "
+  "be 85 ea 84 89 39 12 7b d8 c9 c4 d4 7b 51 05 6c "
+  "03 1c f3 36 f1 7c 99 80 f3 b8 f5 b9 b6 87 8e 8b "
+  "79 7a a4 3b 88 26 84 33 3e 17 89 3f e9 ca a6 aa "
+  "29 9f 7e d1 a1 8e e2 c5 48 64 b7 b2 b9 9b 72 61 "
+  "8f b0 25 74 d1 39 ef 50 f0 19 c9 ee f4 16 97 13 "
+  "38 e7 d4 70 ";
+// Salt:
+static const char salt_1_3[] =
+  "71 0b 9c 47 47 d8 00 d4 de 87 f1 2a fd ce 6d f1 "
+  "81 07 cc 77 ";
+// Signature:
+static const char signature_1_3[] =
+  "66 60 26 fb a7 1b d3 e7 cf 13 15 7c c2 c5 1a 8e "
+  "4a a6 84 af 97 78 f9 18 49 f3 43 35 d1 41 c0 01 "
+  "54 c4 19 76 21 f9 62 4a 67 5b 5a bc 22 ee 7d 5b "
+  "aa ff aa e1 c9 ba ca 2c c3 73 b3 f3 3e 78 e6 14 "
+  "3c 39 5a 91 aa 7f ac a6 64 eb 73 3a fd 14 d8 82 "
+  "72 59 d9 9a 75 50 fa ca 50 1e f2 b0 4e 33 c2 3a "
+  "a5 1f 4b 9e 82 82 ef db 72 8c c0 ab 09 40 5a 91 "
+  "60 7c 63 69 96 1b c8 27 0d 2d 4f 39 fc e6 12 b1 ";
+
+// RSASSA-PSS Signature Example 1.4
+// Message to be signed:
+static const char message_1_4[] =
+  "bc 65 67 47 fa 9e af b3 f0 ";
+// Salt:
+static const char salt_1_4[] =
+  "05 6f 00 98 5d e1 4d 8e f5 ce a9 e8 2f 8c 27 be "
+  "f7 20 33 5e ";
+// Signature:
+static const char signature_1_4[] =
+  "46 09 79 3b 23 e9 d0 93 62 dc 21 bb 47 da 0b 4f "
+  "3a 76 22 64 9a 47 d4 64 01 9b 9a ea fe 53 35 9c "
+  "17 8c 91 cd 58 ba 6b cb 78 be 03 46 a7 bc 63 7f "
+  "4b 87 3d 4b ab 38 ee 66 1f 19 96 34 c5 47 a1 ad "
+  "84 42 e0 3d a0 15 b1 36 e5 43 f7 ab 07 c0 c1 3e "
+  "42 25 b8 de 8c ce 25 d4 f6 eb 84 00 f8 1f 7e 18 "
+  "33 b7 ee 6e 33 4d 37 09 64 ca 79 fd b8 72 b4 d7 "
+  "52 23 b5 ee b0 81 01 59 1f b5 32 d1 55 a6 de 87 ";
+
+// RSASSA-PSS Signature Example 1.5
+// Message to be signed:
+static const char message_1_5[] =
+  "b4 55 81 54 7e 54 27 77 0c 76 8e 8b 82 b7 55 64 "
+  "e0 ea 4e 9c 32 59 4d 6b ff 70 65 44 de 0a 87 76 "
+  "c7 a8 0b 45 76 55 0e ee 1b 2a ca bc 7e 8b 7d 3e "
+  "f7 bb 5b 03 e4 62 c1 10 47 ea dd 00 62 9a e5 75 "
+  "48 0a c1 47 0f e0 46 f1 3a 2b f5 af 17 92 1d c4 "
+  "b0 aa 8b 02 be e6 33 49 11 65 1d 7f 85 25 d1 0f "
+  "32 b5 1d 33 be 52 0d 3d df 5a 70 99 55 a3 df e7 "
+  "82 83 b9 e0 ab 54 04 6d 15 0c 17 7f 03 7f dc cc "
+  "5b e4 ea 5f 68 b5 e5 a3 8c 9d 7e dc cc c4 97 5f "
+  "45 5a 69 09 b4 ";
+// Salt:
+static const char salt_1_5[] =
+  "80 e7 0f f8 6a 08 de 3e c6 09 72 b3 9b 4f bf dc "
+  "ea 67 ae 8e ";
+// Signature:
+static const char signature_1_5[] =
+  "1d 2a ad 22 1c a4 d3 1d df 13 50 92 39 01 93 98 "
+  "e3 d1 4b 32 dc 34 dc 5a f4 ae ae a3 c0 95 af 73 "
+  "47 9c f0 a4 5e 56 29 63 5a 53 a0 18 37 76 15 b1 "
+  "6c b9 b1 3b 3e 09 d6 71 eb 71 e3 87 b8 54 5c 59 "
+  "60 da 5a 64 77 6e 76 8e 82 b2 c9 35 83 bf 10 4c "
+  "3f db 23 51 2b 7b 4e 89 f6 33 dd 00 63 a5 30 db "
+  "45 24 b0 1c 3f 38 4c 09 31 0e 31 5a 79 dc d3 d6 "
+  "84 02 2a 7f 31 c8 65 a6 64 e3 16 97 8b 75 9f ad ";
+
+// RSASSA-PSS Signature Example 1.6
+// Message to be signed:
+static const char message_1_6[] =
+  "10 aa e9 a0 ab 0b 59 5d 08 41 20 7b 70 0d 48 d7 "
+  "5f ae dd e3 b7 75 cd 6b 4c c8 8a e0 6e 46 94 ec "
+  "74 ba 18 f8 52 0d 4f 5e a6 9c bb e7 cc 2b eb a4 "
+  "3e fd c1 02 15 ac 4e b3 2d c3 02 a1 f5 3d c6 c4 "
+  "35 22 67 e7 93 6c fe bf 7c 8d 67 03 57 84 a3 90 "
+  "9f a8 59 c7 b7 b5 9b 8e 39 c5 c2 34 9f 18 86 b7 "
+  "05 a3 02 67 d4 02 f7 48 6a b4 f5 8c ad 5d 69 ad "
+  "b1 7a b8 cd 0c e1 ca f5 02 5a f4 ae 24 b1 fb 87 "
+  "94 c6 07 0c c0 9a 51 e2 f9 91 13 11 e3 87 7d 00 "
+  "44 c7 1c 57 a9 93 39 50 08 80 6b 72 3a c3 83 73 "
+  "d3 95 48 18 18 52 8c 1e 70 53 73 92 82 05 35 29 "
+  "51 0e 93 5c d0 fa 77 b8 fa 53 cc 2d 47 4b d4 fb "
+  "3c c5 c6 72 d6 ff dc 90 a0 0f 98 48 71 2c 4b cf "
+  "e4 6c 60 57 36 59 b1 1e 64 57 e8 61 f0 f6 04 b6 "
+  "13 8d 14 4f 8c e4 e2 da 73 ";
+// Salt:
+static const char salt_1_6[] =
+  "a8 ab 69 dd 80 1f 00 74 c2 a1 fc 60 64 98 36 c6 "
+  "16 d9 96 81 ";
+// Signature:
+static const char signature_1_6[] =
+  "2a 34 f6 12 5e 1f 6b 0b f9 71 e8 4f bd 41 c6 32 "
+  "be 8f 2c 2a ce 7d e8 b6 92 6e 31 ff 93 e9 af 98 "
+  "7f bc 06 e5 1e 9b e1 4f 51 98 f9 1f 3f 95 3b d6 "
+  "7d a6 0a 9d f5 97 64 c3 dc 0f e0 8e 1c be f0 b7 "
+  "5f 86 8d 10 ad 3f ba 74 9f ef 59 fb 6d ac 46 a0 "
+  "d6 e5 04 36 93 31 58 6f 58 e4 62 8f 39 aa 27 89 "
+  "82 54 3b c0 ee b5 37 dc 61 95 80 19 b3 94 fb 27 "
+  "3f 21 58 58 a0 a0 1a c4 d6 50 b9 55 c6 7f 4c 58 ";
+
+// Example 9: A 1536-bit RSA Key Pair
+
+// RSA modulus n:
+static const char rsa_modulus_n_9[] =
+  "e6 bd 69 2a c9 66 45 79 04 03 fd d0 f5 be b8 b9 "
+  "bf 92 ed 10 00 7f c3 65 04 64 19 dd 06 c0 5c 5b "
+  "5b 2f 48 ec f9 89 e4 ce 26 91 09 97 9c bb 40 b4 "
+  "a0 ad 24 d2 24 83 d1 ee 31 5a d4 cc b1 53 42 68 "
+  "35 26 91 c5 24 f6 dd 8e 6c 29 d2 24 cf 24 69 73 "
+  "ae c8 6c 5b f6 b1 40 1a 85 0d 1b 9a d1 bb 8c bc "
+  "ec 47 b0 6f 0f 8c 7f 45 d3 fc 8f 31 92 99 c5 43 "
+  "3d db c2 b3 05 3b 47 de d2 ec d4 a4 ca ef d6 14 "
+  "83 3d c8 bb 62 2f 31 7e d0 76 b8 05 7f e8 de 3f "
+  "84 48 0a d5 e8 3e 4a 61 90 4a 4f 24 8f b3 97 02 "
+  "73 57 e1 d3 0e 46 31 39 81 5c 6f d4 fd 5a c5 b8 "
+  "17 2a 45 23 0e cb 63 18 a0 4f 14 55 d8 4e 5a 8b ";
+// RSA public exponent e:
+static const char rsa_public_exponent_e_9[] =
+  "01 00 01 ";
+
+// RSASSA-PSS Signature Example 9.1
+// Message to be signed:
+static const char message_9_1[] =
+  "a8 8e 26 58 55 e9 d7 ca 36 c6 87 95 f0 b3 1b 59 "
+  "1c d6 58 7c 71 d0 60 a0 b3 f7 f3 ea ef 43 79 59 "
+  "22 02 8b c2 b6 ad 46 7c fc 2d 7f 65 9c 53 85 aa "
+  "70 ba 36 72 cd de 4c fe 49 70 cc 79 04 60 1b 27 "
+  "88 72 bf 51 32 1c 4a 97 2f 3c 95 57 0f 34 45 d4 "
+  "f5 79 80 e0 f2 0d f5 48 46 e6 a5 2c 66 8f 12 88 "
+  "c0 3f 95 00 6e a3 2f 56 2d 40 d5 2a f9 fe b3 2f "
+  "0f a0 6d b6 5b 58 8a 23 7b 34 e5 92 d5 5c f9 79 "
+  "f9 03 a6 42 ef 64 d2 ed 54 2a a8 c7 7d c1 dd 76 "
+  "2f 45 a5 93 03 ed 75 e5 41 ca 27 1e 2b 60 ca 70 "
+  "9e 44 fa 06 61 13 1e 8d 5d 41 63 fd 8d 39 85 66 "
+  "ce 26 de 87 30 e7 2f 9c ca 73 76 41 c2 44 15 94 "
+  "20 63 70 28 df 0a 18 07 9d 62 08 ea 8b 47 11 a2 "
+  "c7 50 f5 ";
+// Salt:
+static const char salt_9_1[] =
+  "c0 a4 25 31 3d f8 d7 56 4b d2 43 4d 31 15 23 d5 "
+  "25 7e ed 80 ";
+// Signature:
+static const char signature_9_1[] =
+  "58 61 07 22 6c 3c e0 13 a7 c8 f0 4d 1a 6a 29 59 "
+  "bb 4b 8e 20 5b a4 3a 27 b5 0f 12 41 11 bc 35 ef "
+  "58 9b 03 9f 59 32 18 7c b6 96 d7 d9 a3 2c 0c 38 "
+  "30 0a 5c dd a4 83 4b 62 d2 eb 24 0a f3 3f 79 d1 "
+  "3d fb f0 95 bf 59 9e 0d 96 86 94 8c 19 64 74 7b "
+  "67 e8 9c 9a ba 5c d8 50 16 23 6f 56 6c c5 80 2c "
+  "b1 3e ad 51 bc 7c a6 be f3 b9 4d cb db b1 d5 70 "
+  "46 97 71 df 0e 00 b1 a8 a0 67 77 47 2d 23 16 27 "
+  "9e da e8 64 74 66 8d 4e 1e ff f9 5f 1d e6 1c 60 "
+  "20 da 32 ae 92 bb f1 65 20 fe f3 cf 4d 88 f6 11 "
+  "21 f2 4b bd 9f e9 1b 59 ca f1 23 5b 2a 93 ff 81 "
+  "fc 40 3a dd f4 eb de a8 49 34 a9 cd af 8e 1a 9e ";
+
+// RSASSA-PSS Signature Example 9.2
+// Message to be signed:
+static const char message_9_2[] =
+  "c8 c9 c6 af 04 ac da 41 4d 22 7e f2 3e 08 20 c3 "
+  "73 2c 50 0d c8 72 75 e9 5b 0d 09 54 13 99 3c 26 "
+  "58 bc 1d 98 85 81 ba 87 9c 2d 20 1f 14 cb 88 ce "
+  "d1 53 a0 19 69 a7 bf 0a 7b e7 9c 84 c1 48 6b c1 "
+  "2b 3f a6 c5 98 71 b6 82 7c 8c e2 53 ca 5f ef a8 "
+  "a8 c6 90 bf 32 6e 8e 37 cd b9 6d 90 a8 2e ba b6 "
+  "9f 86 35 0e 18 22 e8 bd 53 6a 2e ";
+// Salt:
+static const char salt_9_2[] =
+  "b3 07 c4 3b 48 50 a8 da c2 f1 5f 32 e3 78 39 ef "
+  "8c 5c 0e 91 ";
+// Signature:
+static const char signature_9_2[] =
+  "80 b6 d6 43 25 52 09 f0 a4 56 76 38 97 ac 9e d2 "
+  "59 d4 59 b4 9c 28 87 e5 88 2e cb 44 34 cf d6 6d "
+  "d7 e1 69 93 75 38 1e 51 cd 7f 55 4f 2c 27 17 04 "
+  "b3 99 d4 2b 4b e2 54 0a 0e ca 61 95 1f 55 26 7f "
+  "7c 28 78 c1 22 84 2d ad b2 8b 01 bd 5f 8c 02 5f "
+  "7e 22 84 18 a6 73 c0 3d 6b c0 c7 36 d0 a2 95 46 "
+  "bd 67 f7 86 d9 d6 92 cc ea 77 8d 71 d9 8c 20 63 "
+  "b7 a7 10 92 18 7a 4d 35 af 10 81 11 d8 3e 83 ea "
+  "e4 6c 46 aa 34 27 7e 06 04 45 89 90 37 88 f1 d5 "
+  "e7 ce e2 5f b4 85 e9 29 49 11 88 14 d6 f2 c3 ee "
+  "36 14 89 01 6f 32 7f b5 bc 51 7e b5 04 70 bf fa "
+  "1a fa 5f 4c e9 aa 0c e5 b8 ee 19 bf 55 01 b9 58 ";
+
+// RSASSA-PSS Signature Example 9.3
+// Message to be signed:
+static const char message_9_3[] =
+  "0a fa d4 2c cd 4f c6 06 54 a5 50 02 d2 28 f5 2a "
+  "4a 5f e0 3b 8b bb 08 ca 82 da ca 55 8b 44 db e1 "
+  "26 6e 50 c0 e7 45 a3 6d 9d 29 04 e3 40 8a bc d1 "
+  "fd 56 99 94 06 3f 4a 75 cc 72 f2 fe e2 a0 cd 89 "
+  "3a 43 af 1c 5b 8b 48 7d f0 a7 16 10 02 4e 4f 6d "
+  "df 9f 28 ad 08 13 c1 aa b9 1b cb 3c 90 64 d5 ff "
+  "74 2d ef fe a6 57 09 41 39 36 9e 5e a6 f4 a9 63 "
+  "19 a5 cc 82 24 14 5b 54 50 62 75 8f ef d1 fe 34 "
+  "09 ae 16 92 59 c6 cd fd 6b 5f 29 58 e3 14 fa ec "
+  "be 69 d2 ca ce 58 ee 55 17 9a b9 b3 e6 d1 ec c1 "
+  "4a 55 7c 5f eb e9 88 59 52 64 fc 5d a1 c5 71 46 "
+  "2e ca 79 8a 18 a1 a4 94 0c da b4 a3 e9 20 09 cc "
+  "d4 2e 1e 94 7b 13 14 e3 22 38 a2 de ce 7d 23 a8 "
+  "9b 5b 30 c7 51 fd 0a 4a 43 0d 2c 54 85 94 ";
+// Salt:
+static const char salt_9_3[] =
+  "9a 2b 00 7e 80 97 8b bb 19 2c 35 4e b7 da 9a ed "
+  "fc 74 db f5 ";
+// Signature:
+static const char signature_9_3[] =
+  "48 44 08 f3 89 8c d5 f5 34 83 f8 08 19 ef bf 27 "
+  "08 c3 4d 27 a8 b2 a6 fa e8 b3 22 f9 24 02 37 f9 "
+  "81 81 7a ca 18 46 f1 08 4d aa 6d 7c 07 95 f6 e5 "
+  "bf 1a f5 9c 38 e1 85 84 37 ce 1f 7e c4 19 b9 8c "
+  "87 36 ad f6 dd 9a 00 b1 80 6d 2b d3 ad 0a 73 77 "
+  "5e 05 f5 2d fe f3 a5 9a b4 b0 81 43 f0 df 05 cd "
+  "1a d9 d0 4b ec ec a6 da a4 a2 12 98 03 e2 00 cb "
+  "c7 77 87 ca f4 c1 d0 66 3a 6c 59 87 b6 05 95 20 "
+  "19 78 2c af 2e c1 42 6d 68 fb 94 ed 1d 4b e8 16 "
+  "a7 ed 08 1b 77 e6 ab 33 0b 3f fc 07 38 20 fe cd "
+  "e3 72 7f cb e2 95 ee 61 a0 50 a3 43 65 86 37 c3 "
+  "fd 65 9c fb 63 73 6d e3 2d 9f 90 d3 c2 f6 3e ca ";
+
+// RSASSA-PSS Signature Example 9.4
+// Message to be signed:
+static const char message_9_4[] =
+  "1d fd 43 b4 6c 93 db 82 62 9b da e2 bd 0a 12 b8 "
+  "82 ea 04 c3 b4 65 f5 cf 93 02 3f 01 05 96 26 db "
+  "be 99 f2 6b b1 be 94 9d dd d1 6d c7 f3 de bb 19 "
+  "a1 94 62 7f 0b 22 44 34 df 7d 87 00 e9 e9 8b 06 "
+  "e3 60 c1 2f db e3 d1 9f 51 c9 68 4e b9 08 9e cb "
+  "b0 a2 f0 45 03 99 d3 f5 9e ac 72 94 08 5d 04 4f "
+  "53 93 c6 ce 73 74 23 d8 b8 6c 41 53 70 d3 89 e3 "
+  "0b 9f 0a 3c 02 d2 5d 00 82 e8 ad 6f 3f 1e f2 4a "
+  "45 c3 cf 82 b3 83 36 70 63 a4 d4 61 3e 42 64 f0 "
+  "1b 2d ac 2e 5a a4 20 43 f8 fb 5f 69 fa 87 1d 14 "
+  "fb 27 3e 76 7a 53 1c 40 f0 2f 34 3b c2 fb 45 a0 "
+  "c7 e0 f6 be 25 61 92 3a 77 21 1d 66 a6 e2 db b4 "
+  "3c 36 63 50 be ae 22 da 3a c2 c1 f5 07 70 96 fc "
+  "b5 c4 bf 25 5f 75 74 35 1a e0 b1 e1 f0 36 32 81 "
+  "7c 08 56 d4 a8 ba 97 af bd c8 b8 58 55 40 2b c5 "
+  "69 26 fc ec 20 9f 9e a8 ";
+// Salt:
+static const char salt_9_4[] =
+  "70 f3 82 bd df 4d 5d 2d d8 8b 3b c7 b7 30 8b e6 "
+  "32 b8 40 45 ";
+// Signature:
+static const char signature_9_4[] =
+  "84 eb eb 48 1b e5 98 45 b4 64 68 ba fb 47 1c 01 "
+  "12 e0 2b 23 5d 84 b5 d9 11 cb d1 92 6e e5 07 4a "
+  "e0 42 44 95 cb 20 e8 23 08 b8 eb b6 5f 41 9a 03 "
+  "fb 40 e7 2b 78 98 1d 88 aa d1 43 05 36 85 17 2c "
+  "97 b2 9c 8b 7b f0 ae 73 b5 b2 26 3c 40 3d a0 ed "
+  "2f 80 ff 74 50 af 78 28 eb 8b 86 f0 02 8b d2 a8 "
+  "b1 76 a4 d2 28 cc ce a1 83 94 f2 38 b0 9f f7 58 "
+  "cc 00 bc 04 30 11 52 35 57 42 f2 82 b5 4e 66 3a "
+  "91 9e 70 9d 8d a2 4a de 55 00 a7 b9 aa 50 22 6e "
+  "0c a5 29 23 e6 c2 d8 60 ec 50 ff 48 0f a5 74 77 "
+  "e8 2b 05 65 f4 37 9f 79 c7 72 d5 c2 da 80 af 9f "
+  "bf 32 5e ce 6f c2 0b 00 96 16 14 be e8 9a 18 3e ";
+
+// RSASSA-PSS Signature Example 9.5
+// Message to be signed:
+static const char message_9_5[] =
+  "1b dc 6e 7c 98 fb 8c f5 4e 9b 09 7b 66 a8 31 e9 "
+  "cf e5 2d 9d 48 88 44 8e e4 b0 97 80 93 ba 1d 7d "
+  "73 ae 78 b3 a6 2b a4 ad 95 cd 28 9c cb 9e 00 52 "
+  "26 bb 3d 17 8b cc aa 82 1f b0 44 a4 e2 1e e9 76 "
+  "96 c1 4d 06 78 c9 4c 2d ae 93 b0 ad 73 92 22 18 "
+  "55 3d aa 7e 44 eb e5 77 25 a7 a4 5c c7 2b 9b 21 "
+  "38 a6 b1 7c 8d b4 11 ce 82 79 ee 12 41 af f0 a8 "
+  "be c6 f7 7f 87 ed b0 c6 9c b2 72 36 e3 43 5a 80 "
+  "0b 19 2e 4f 11 e5 19 e3 fe 30 fc 30 ea cc ca 4f "
+  "bb 41 76 90 29 bf 70 8e 81 7a 9e 68 38 05 be 67 "
+  "fa 10 09 84 68 3b 74 83 8e 3b cf fa 79 36 6e ed "
+  "1d 48 1c 76 72 91 18 83 8f 31 ba 8a 04 8a 93 c1 "
+  "be 44 24 59 8e 8d f6 32 8b 7a 77 88 0a 3f 9c 7e "
+  "2e 8d fc a8 eb 5a 26 fb 86 bd c5 56 d4 2b be 01 "
+  "d9 fa 6e d8 06 46 49 1c 93 41 ";
+// Salt:
+static const char salt_9_5[] =
+  "d6 89 25 7a 86 ef fa 68 21 2c 5e 0c 61 9e ca 29 "
+  "5f b9 1b 67 ";
+// Signature:
+static const char signature_9_5[] =
+  "82 10 2d f8 cb 91 e7 17 99 19 a0 4d 26 d3 35 d6 "
+  "4f bc 2f 87 2c 44 83 39 43 24 1d e8 45 48 10 27 "
+  "4c df 3d b5 f4 2d 42 3d b1 52 af 71 35 f7 01 42 "
+  "0e 39 b4 94 a6 7c bf d1 9f 91 19 da 23 3a 23 da "
+  "5c 64 39 b5 ba 0d 2b c3 73 ee e3 50 70 01 37 8d "
+  "4a 40 73 85 6b 7f e2 ab a0 b5 ee 93 b2 7f 4a fe "
+  "c7 d4 d1 20 92 1c 83 f6 06 76 5b 02 c1 9e 4d 6a "
+  "1a 3b 95 fa 4c 42 29 51 be 4f 52 13 10 77 ef 17 "
+  "17 97 29 cd df bd b5 69 50 db ac ee fe 78 cb 16 "
+  "64 0a 09 9e a5 6d 24 38 9e ef 10 f8 fe cb 31 ba "
+  "3e a3 b2 27 c0 a8 66 98 bb 89 e3 e9 36 39 05 bf "
+  "22 77 7b 2a 3a a5 21 b6 5b 4c ef 76 d8 3b de 4c ";
+
+// RSASSA-PSS Signature Example 9.6
+// Message to be signed:
+static const char message_9_6[] =
+  "88 c7 a9 f1 36 04 01 d9 0e 53 b1 01 b6 1c 53 25 "
+  "c3 c7 5d b1 b4 11 fb eb 8e 83 0b 75 e9 6b 56 67 "
+  "0a d2 45 40 4e 16 79 35 44 ee 35 4b c6 13 a9 0c "
+  "c9 84 87 15 a7 3d b5 89 3e 7f 6d 27 98 15 c0 c1 "
+  "de 83 ef 8e 29 56 e3 a5 6e d2 6a 88 8d 7a 9c dc "
+  "d0 42 f4 b1 6b 7f a5 1e f1 a0 57 36 62 d1 6a 30 "
+  "2d 0e c5 b2 85 d2 e0 3a d9 65 29 c8 7b 3d 37 4d "
+  "b3 72 d9 5b 24 43 d0 61 b6 b1 a3 50 ba 87 80 7e "
+  "d0 83 af d1 eb 05 c3 f5 2f 4e ba 5e d2 22 77 14 "
+  "fd b5 0b 9d 9d 9d d6 81 4f 62 f6 27 2f cd 5c db "
+  "ce 7a 9e f7 97 ";
+// Salt:
+static const char salt_9_6[] =
+  "c2 5f 13 bf 67 d0 81 67 1a 04 81 a1 f1 82 0d 61 "
+  "3b ba 22 76 ";
+// Signature:
+static const char signature_9_6[] =
+  "a7 fd b0 d2 59 16 5c a2 c8 8d 00 bb f1 02 8a 86 "
+  "7d 33 76 99 d0 61 19 3b 17 a9 64 8e 14 cc bb aa "
+  "de ac aa cd ec 81 5e 75 71 29 4e bb 8a 11 7a f2 "
+  "05 fa 07 8b 47 b0 71 2c 19 9e 3a d0 51 35 c5 04 "
+  "c2 4b 81 70 51 15 74 08 02 48 79 92 ff d5 11 d4 "
+  "af c6 b8 54 49 1e b3 f0 dd 52 31 39 54 2f f1 5c "
+  "31 01 ee 85 54 35 17 c6 a3 c7 94 17 c6 7e 2d d9 "
+  "aa 74 1e 9a 29 b0 6d cb 59 3c 23 36 b3 67 0a e3 "
+  "af ba c7 c3 e7 6e 21 54 73 e8 66 e3 38 ca 24 4d "
+  "e0 0b 62 62 4d 6b 94 26 82 2c ea e9 f8 cc 46 08 "
+  "95 f4 12 50 07 3f d4 5c 5a 1e 7b 42 5c 20 4a 42 "
+  "3a 69 91 59 f6 90 3e 71 0b 37 a7 bb 2b c8 04 9f ";
+
+// Example 10: A 2048-bit RSA Key Pair
+
+// RSA modulus n:
+static const char rsa_modulus_n_10[] =
+  "a5 dd 86 7a c4 cb 02 f9 0b 94 57 d4 8c 14 a7 70 "
+  "ef 99 1c 56 c3 9c 0e c6 5f d1 1a fa 89 37 ce a5 "
+  "7b 9b e7 ac 73 b4 5c 00 17 61 5b 82 d6 22 e3 18 "
+  "75 3b 60 27 c0 fd 15 7b e1 2f 80 90 fe e2 a7 ad "
+  "cd 0e ef 75 9f 88 ba 49 97 c7 a4 2d 58 c9 aa 12 "
+  "cb 99 ae 00 1f e5 21 c1 3b b5 43 14 45 a8 d5 ae "
+  "4f 5e 4c 7e 94 8a c2 27 d3 60 40 71 f2 0e 57 7e "
+  "90 5f be b1 5d fa f0 6d 1d e5 ae 62 53 d6 3a 6a "
+  "21 20 b3 1a 5d a5 da bc 95 50 60 0e 20 f2 7d 37 "
+  "39 e2 62 79 25 fe a3 cc 50 9f 21 df f0 4e 6e ea "
+  "45 49 c5 40 d6 80 9f f9 30 7e ed e9 1f ff 58 73 "
+  "3d 83 85 a2 37 d6 d3 70 5a 33 e3 91 90 09 92 07 "
+  "0d f7 ad f1 35 7c f7 e3 70 0c e3 66 7d e8 3f 17 "
+  "b8 df 17 78 db 38 1d ce 09 cb 4a d0 58 a5 11 00 "
+  "1a 73 81 98 ee 27 cf 55 a1 3b 75 45 39 90 65 82 "
+  "ec 8b 17 4b d5 8d 5d 1f 3d 76 7c 61 37 21 ae 05 ";
+// RSA public exponent e:
+static const char rsa_public_exponent_e_10[] =
+  "01 00 01 ";
+
+// RSASSA-PSS Signature Example 10.1
+// Message to be signed:
+static const char message_10_1[] =
+  "88 31 77 e5 12 6b 9b e2 d9 a9 68 03 27 d5 37 0c "
+  "6f 26 86 1f 58 20 c4 3d a6 7a 3a d6 09 ";
+// Salt:
+static const char salt_10_1[] =
+  "04 e2 15 ee 6f f9 34 b9 da 70 d7 73 0c 87 34 ab "
+  "fc ec de 89 ";
+// Signature:
+static const char signature_10_1[] =
+  "82 c2 b1 60 09 3b 8a a3 c0 f7 52 2b 19 f8 73 54 "
+  "06 6c 77 84 7a bf 2a 9f ce 54 2d 0e 84 e9 20 c5 "
+  "af b4 9f fd fd ac e1 65 60 ee 94 a1 36 96 01 14 "
+  "8e ba d7 a0 e1 51 cf 16 33 17 91 a5 72 7d 05 f2 "
+  "1e 74 e7 eb 81 14 40 20 69 35 d7 44 76 5a 15 e7 "
+  "9f 01 5c b6 6c 53 2c 87 a6 a0 59 61 c8 bf ad 74 "
+  "1a 9a 66 57 02 28 94 39 3e 72 23 73 97 96 c0 2a "
+  "77 45 5d 0f 55 5b 0e c0 1d df 25 9b 62 07 fd 0f "
+  "d5 76 14 ce f1 a5 57 3b aa ff 4e c0 00 69 95 16 "
+  "59 b8 5f 24 30 0a 25 16 0c a8 52 2d c6 e6 72 7e "
+  "57 d0 19 d7 e6 36 29 b8 fe 5e 89 e2 5c c1 5b eb "
+  "3a 64 75 77 55 92 99 28 0b 9b 28 f7 9b 04 09 00 "
+  "0b e2 5b bd 96 40 8b a3 b4 3c c4 86 18 4d d1 c8 "
+  "e6 25 53 fa 1a f4 04 0f 60 66 3d e7 f5 e4 9c 04 "
+  "38 8e 25 7f 1c e8 9c 95 da b4 8a 31 5d 9b 66 b1 "
+  "b7 62 82 33 87 6f f2 38 52 30 d0 70 d0 7e 16 66 ";
+
+// RSASSA-PSS Signature Example 10.2
+// Message to be signed:
+static const char message_10_2[] =
+  "dd 67 0a 01 46 58 68 ad c9 3f 26 13 19 57 a5 0c "
+  "52 fb 77 7c db aa 30 89 2c 9e 12 36 11 64 ec 13 "
+  "97 9d 43 04 81 18 e4 44 5d b8 7b ee 58 dd 98 7b "
+  "34 25 d0 20 71 d8 db ae 80 70 8b 03 9d bb 64 db "
+  "d1 de 56 57 d9 fe d0 c1 18 a5 41 43 74 2e 0f f3 "
+  "c8 7f 74 e4 58 57 64 7a f3 f7 9e b0 a1 4c 9d 75 "
+  "ea 9a 1a 04 b7 cf 47 8a 89 7a 70 8f d9 88 f4 8e "
+  "80 1e db 0b 70 39 df 8c 23 bb 3c 56 f4 e8 21 ac ";
+// Salt:
+static const char salt_10_2[] =
+  "8b 2b dd 4b 40 fa f5 45 c7 78 dd f9 bc 1a 49 cb "
+  "57 f9 b7 1b ";
+// Signature:
+static const char signature_10_2[] =
+  "14 ae 35 d9 dd 06 ba 92 f7 f3 b8 97 97 8a ed 7c "
+  "d4 bf 5f f0 b5 85 a4 0b d4 6c e1 b4 2c d2 70 30 "
+  "53 bb 90 44 d6 4e 81 3d 8f 96 db 2d d7 00 7d 10 "
+  "11 8f 6f 8f 84 96 09 7a d7 5e 1f f6 92 34 1b 28 "
+  "92 ad 55 a6 33 a1 c5 5e 7f 0a 0a d5 9a 0e 20 3a "
+  "5b 82 78 ae c5 4d d8 62 2e 28 31 d8 71 74 f8 ca "
+  "ff 43 ee 6c 46 44 53 45 d8 4a 59 65 9b fb 92 ec "
+  "d4 c8 18 66 86 95 f3 47 06 f6 68 28 a8 99 59 63 "
+  "7f 2b f3 e3 25 1c 24 bd ba 4d 4b 76 49 da 00 22 "
+  "21 8b 11 9c 84 e7 9a 65 27 ec 5b 8a 5f 86 1c 15 "
+  "99 52 e2 3e c0 5e 1e 71 73 46 fa ef e8 b1 68 68 "
+  "25 bd 2b 26 2f b2 53 10 66 c0 de 09 ac de 2e 42 "
+  "31 69 07 28 b5 d8 5e 11 5a 2f 6b 92 b7 9c 25 ab "
+  "c9 bd 93 99 ff 8b cf 82 5a 52 ea 1f 56 ea 76 dd "
+  "26 f4 3b aa fa 18 bf a9 2a 50 4c bd 35 69 9e 26 "
+  "d1 dc c5 a2 88 73 85 f3 c6 32 32 f0 6f 32 44 c3 ";
+
+// RSASSA-PSS Signature Example 10.3
+// Message to be signed:
+static const char message_10_3[] =
+  "48 b2 b6 a5 7a 63 c8 4c ea 85 9d 65 c6 68 28 4b "
+  "08 d9 6b dc aa be 25 2d b0 e4 a9 6c b1 ba c6 01 "
+  "93 41 db 6f be fb 8d 10 6b 0e 90 ed a6 bc c6 c6 "
+  "26 2f 37 e7 ea 9c 7e 5d 22 6b d7 df 85 ec 5e 71 "
+  "ef ff 2f 54 c5 db 57 7f f7 29 ff 91 b8 42 49 1d "
+  "e2 74 1d 0c 63 16 07 df 58 6b 90 5b 23 b9 1a f1 "
+  "3d a1 23 04 bf 83 ec a8 a7 3e 87 1f f9 db ";
+// Salt:
+static const char salt_10_3[] =
+  "4e 96 fc 1b 39 8f 92 b4 46 71 01 0c 0d c3 ef d6 "
+  "e2 0c 2d 73 ";
+// Signature:
+static const char signature_10_3[] =
+  "6e 3e 4d 7b 6b 15 d2 fb 46 01 3b 89 00 aa 5b bb "
+  "39 39 cf 2c 09 57 17 98 70 42 02 6e e6 2c 74 c5 "
+  "4c ff d5 d7 d5 7e fb bf 95 0a 0f 5c 57 4f a0 9d "
+  "3f c1 c9 f5 13 b0 5b 4f f5 0d d8 df 7e df a2 01 "
+  "02 85 4c 35 e5 92 18 01 19 a7 0c e5 b0 85 18 2a "
+  "a0 2d 9e a2 aa 90 d1 df 03 f2 da ae 88 5b a2 f5 "
+  "d0 5a fd ac 97 47 6f 06 b9 3b 5b c9 4a 1a 80 aa "
+  "91 16 c4 d6 15 f3 33 b0 98 89 2b 25 ff ac e2 66 "
+  "f5 db 5a 5a 3b cc 10 a8 24 ed 55 aa d3 5b 72 78 "
+  "34 fb 8c 07 da 28 fc f4 16 a5 d9 b2 22 4f 1f 8b "
+  "44 2b 36 f9 1e 45 6f de a2 d7 cf e3 36 72 68 de "
+  "03 07 a4 c7 4e 92 41 59 ed 33 39 3d 5e 06 55 53 "
+  "1c 77 32 7b 89 82 1b de df 88 01 61 c7 8c d4 19 "
+  "6b 54 19 f7 ac c3 f1 3e 5e bf 16 1b 6e 7c 67 24 "
+  "71 6c a3 3b 85 c2 e2 56 40 19 2a c2 85 96 51 d5 "
+  "0b de 7e b9 76 e5 1c ec 82 8b 98 b6 56 3b 86 bb ";
+
+// RSASSA-PSS Signature Example 10.4
+// Message to be signed:
+static const char message_10_4[] =
+  "0b 87 77 c7 f8 39 ba f0 a6 4b bb db c5 ce 79 75 "
+  "5c 57 a2 05 b8 45 c1 74 e2 d2 e9 05 46 a0 89 c4 "
+  "e6 ec 8a df fa 23 a7 ea 97 ba e6 b6 5d 78 2b 82 "
+  "db 5d 2b 5a 56 d2 2a 29 a0 5e 7c 44 33 e2 b8 2a "
+  "62 1a bb a9 0a dd 05 ce 39 3f c4 8a 84 05 42 45 "
+  "1a ";
+// Salt:
+static const char salt_10_4[] =
+  "c7 cd 69 8d 84 b6 51 28 d8 83 5e 3a 8b 1e b0 e0 "
+  "1c b5 41 ec ";
+// Signature:
+static const char signature_10_4[] =
+  "34 04 7f f9 6c 4d c0 dc 90 b2 d4 ff 59 a1 a3 61 "
+  "a4 75 4b 25 5d 2e e0 af 7d 8b f8 7c 9b c9 e7 dd "
+  "ee de 33 93 4c 63 ca 1c 0e 3d 26 2c b1 45 ef 93 "
+  "2a 1f 2c 0a 99 7a a6 a3 4f 8e ae e7 47 7d 82 cc "
+  "f0 90 95 a6 b8 ac ad 38 d4 ee c9 fb 7e ab 7a d0 "
+  "2d a1 d1 1d 8e 54 c1 82 5e 55 bf 58 c2 a2 32 34 "
+  "b9 02 be 12 4f 9e 90 38 a8 f6 8f a4 5d ab 72 f6 "
+  "6e 09 45 bf 1d 8b ac c9 04 4c 6f 07 09 8c 9f ce "
+  "c5 8a 3a ab 10 0c 80 51 78 15 5f 03 0a 12 4c 45 "
+  "0e 5a cb da 47 d0 e4 f1 0b 80 a2 3f 80 3e 77 4d "
+  "02 3b 00 15 c2 0b 9f 9b be 7c 91 29 63 38 d5 ec "
+  "b4 71 ca fb 03 20 07 b6 7a 60 be 5f 69 50 4a 9f "
+  "01 ab b3 cb 46 7b 26 0e 2b ce 86 0b e8 d9 5b f9 "
+  "2c 0c 8e 14 96 ed 1e 52 85 93 a4 ab b6 df 46 2d "
+  "de 8a 09 68 df fe 46 83 11 68 57 a2 32 f5 eb f6 "
+  "c8 5b e2 38 74 5a d0 f3 8f 76 7a 5f db f4 86 fb ";
+
+// RSASSA-PSS Signature Example 10.5
+// Message to be signed:
+static const char message_10_5[] =
+  "f1 03 6e 00 8e 71 e9 64 da dc 92 19 ed 30 e1 7f "
+  "06 b4 b6 8a 95 5c 16 b3 12 b1 ed df 02 8b 74 97 "
+  "6b ed 6b 3f 6a 63 d4 e7 78 59 24 3c 9c cc dc 98 "
+  "01 65 23 ab b0 24 83 b3 55 91 c3 3a ad 81 21 3b "
+  "b7 c7 bb 1a 47 0a ab c1 0d 44 25 6c 4d 45 59 d9 "
+  "16 ";
+// Salt:
+static const char salt_10_5[] =
+  "ef a8 bf f9 62 12 b2 f4 a3 f3 71 a1 0d 57 41 52 "
+  "65 5f 5d fb ";
+// Signature:
+static const char signature_10_5[] =
+  "7e 09 35 ea 18 f4 d6 c1 d1 7c e8 2e b2 b3 83 6c "
+  "55 b3 84 58 9c e1 9d fe 74 33 63 ac 99 48 d1 f3 "
+  "46 b7 bf dd fe 92 ef d7 8a db 21 fa ef c8 9a de "
+  "42 b1 0f 37 40 03 fe 12 2e 67 42 9a 1c b8 cb d1 "
+  "f8 d9 01 45 64 c4 4d 12 01 16 f4 99 0f 1a 6e 38 "
+  "77 4c 19 4b d1 b8 21 32 86 b0 77 b0 49 9d 2e 7b "
+  "3f 43 4a b1 22 89 c5 56 68 4d ee d7 81 31 93 4b "
+  "b3 dd 65 37 23 6f 7c 6f 3d cb 09 d4 76 be 07 72 "
+  "1e 37 e1 ce ed 9b 2f 7b 40 68 87 bd 53 15 73 05 "
+  "e1 c8 b4 f8 4d 73 3b c1 e1 86 fe 06 cc 59 b6 ed "
+  "b8 f4 bd 7f fe fd f4 f7 ba 9c fb 9d 57 06 89 b5 "
+  "a1 a4 10 9a 74 6a 69 08 93 db 37 99 25 5a 0c b9 "
+  "21 5d 2d 1c d4 90 59 0e 95 2e 8c 87 86 aa 00 11 "
+  "26 52 52 47 0c 04 1d fb c3 ee c7 c3 cb f7 1c 24 "
+  "86 9d 11 5c 0c b4 a9 56 f5 6d 53 0b 80 ab 58 9a "
+  "cf ef c6 90 75 1d df 36 e8 d3 83 f8 3c ed d2 cc ";
+
+// RSASSA-PSS Signature Example 10.6
+// Message to be signed:
+static const char message_10_6[] =
+  "25 f1 08 95 a8 77 16 c1 37 45 0b b9 51 9d fa a1 "
+  "f2 07 fa a9 42 ea 88 ab f7 1e 9c 17 98 00 85 b5 "
+  "55 ae ba b7 62 64 ae 2a 3a b9 3c 2d 12 98 11 91 "
+  "dd ac 6f b5 94 9e b3 6a ee 3c 5d a9 40 f0 07 52 "
+  "c9 16 d9 46 08 fa 7d 97 ba 6a 29 15 b6 88 f2 03 "
+  "23 d4 e9 d9 68 01 d8 9a 72 ab 58 92 dc 21 17 c0 "
+  "74 34 fc f9 72 e0 58 cf 8c 41 ca 4b 4f f5 54 f7 "
+  "d5 06 8a d3 15 5f ce d0 f3 12 5b c0 4f 91 93 37 "
+  "8a 8f 5c 4c 3b 8c b4 dd 6d 1c c6 9d 30 ec ca 6e "
+  "aa 51 e3 6a 05 73 0e 9e 34 2e 85 5b af 09 9d ef "
+  "b8 af d7 ";
+// Salt:
+static const char salt_10_6[] =
+  "ad 8b 15 23 70 36 46 22 4b 66 0b 55 08 85 91 7c "
+  "a2 d1 df 28 ";
+// Signature:
+static const char signature_10_6[] =
+  "6d 3b 5b 87 f6 7e a6 57 af 21 f7 54 41 97 7d 21 "
+  "80 f9 1b 2c 5f 69 2d e8 29 55 69 6a 68 67 30 d9 "
+  "b9 77 8d 97 07 58 cc b2 60 71 c2 20 9f fb d6 12 "
+  "5b e2 e9 6e a8 1b 67 cb 9b 93 08 23 9f da 17 f7 "
+  "b2 b6 4e cd a0 96 b6 b9 35 64 0a 5a 1c b4 2a 91 "
+  "55 b1 c9 ef 7a 63 3a 02 c5 9f 0d 6e e5 9b 85 2c "
+  "43 b3 50 29 e7 3c 94 0f f0 41 0e 8f 11 4e ed 46 "
+  "bb d0 fa e1 65 e4 2b e2 52 8a 40 1c 3b 28 fd 81 "
+  "8e f3 23 2d ca 9f 4d 2a 0f 51 66 ec 59 c4 23 96 "
+  "d6 c1 1d bc 12 15 a5 6f a1 71 69 db 95 75 34 3e "
+  "f3 4f 9d e3 2a 49 cd c3 17 49 22 f2 29 c2 3e 18 "
+  "e4 5d f9 35 31 19 ec 43 19 ce dc e7 a1 7c 64 08 "
+  "8c 1f 6f 52 be 29 63 41 00 b3 91 9d 38 f3 d1 ed "
+  "94 e6 89 1e 66 a7 3b 8f b8 49 f5 87 4d f5 94 59 "
+  "e2 98 c7 bb ce 2e ee 78 2a 19 5a a6 6f e2 d0 73 "
+  "2b 25 e5 95 f5 7d 3e 06 1b 1f c3 e4 06 3b f9 8f ";
+
+struct SignatureExample {
+  const char* message;
+  const char* salt;
+  const char* signature;
+};
+
+struct PSSTestVector {
+  const char* modulus_n;
+  const char* public_exponent_e;
+  SignatureExample example[6];
+};
+
+static const PSSTestVector pss_test[] = {
+  {
+    rsa_modulus_n_1,
+    rsa_public_exponent_e_1,
+    {
+      { message_1_1, salt_1_1, signature_1_1 },
+      { message_1_2, salt_1_2, signature_1_2 },
+      { message_1_3, salt_1_3, signature_1_3 },
+      { message_1_4, salt_1_4, signature_1_4 },
+      { message_1_5, salt_1_5, signature_1_5 },
+      { message_1_6, salt_1_6, signature_1_6 },
+    }
+  },
+  {
+    rsa_modulus_n_9,
+    rsa_public_exponent_e_9,
+    {
+      { message_9_1, salt_9_1, signature_9_1 },
+      { message_9_2, salt_9_2, signature_9_2 },
+      { message_9_3, salt_9_3, signature_9_3 },
+      { message_9_4, salt_9_4, signature_9_4 },
+      { message_9_5, salt_9_5, signature_9_5 },
+      { message_9_6, salt_9_6, signature_9_6 },
+    }
+  },
+  {
+    rsa_modulus_n_10,
+    rsa_public_exponent_e_10,
+    {
+      { message_10_1, salt_10_1, signature_10_1 },
+      { message_10_2, salt_10_2, signature_10_2 },
+      { message_10_3, salt_10_3, signature_10_3 },
+      { message_10_4, salt_10_4, signature_10_4 },
+      { message_10_5, salt_10_5, signature_10_5 },
+      { message_10_6, salt_10_6, signature_10_6 },
+    }
+  },
+};
+
+static uint8_t HexDigitValue(char digit) {
+  if ('0' <= digit && digit <= '9')
+    return digit - '0';
+  if ('a' <= digit && digit <= 'f')
+    return digit - 'a' + 10;
+  return digit - 'A' + 10;
+}
+
+static bool DecodeTestInput(const char* in, std::vector<uint8_t>* out) {
+  out->clear();
+  while (in[0] != '\0') {
+    if (!isxdigit(in[0]) || !isxdigit(in[1]) || in[2] != ' ')
+      return false;
+    uint8_t octet = HexDigitValue(in[0]) * 16 + HexDigitValue(in[1]);
+    out->push_back(octet);
+    in += 3;
+  }
+  return true;
+}
+
+// PrependASN1Length prepends an ASN.1 serialized length to the beginning of
+// |out|.
+static void PrependASN1Length(std::vector<uint8_t>* out, size_t len) {
+  if (len < 128) {
+    out->insert(out->begin(), static_cast<uint8_t>(len));
+  } else if (len < 256) {
+    out->insert(out->begin(), static_cast<uint8_t>(len));
+    out->insert(out->begin(), 0x81);
+  } else if (len < 0x10000) {
+    out->insert(out->begin(), static_cast<uint8_t>(len));
+    out->insert(out->begin(), static_cast<uint8_t>(len >> 8));
+    out->insert(out->begin(), 0x82);
+  } else {
+    CHECK(false) << "ASN.1 length not handled: " << len;
+  }
+}
+
+static bool EncodeRSAPublicKey(const std::vector<uint8_t>& modulus_n,
+                               const std::vector<uint8_t>& public_exponent_e,
+                               std::vector<uint8_t>* public_key_info) {
+  // The public key is specified as the following ASN.1 structure:
+  //   SubjectPublicKeyInfo  ::=  SEQUENCE  {
+  //       algorithm            AlgorithmIdentifier,
+  //       subjectPublicKey     BIT STRING  }
+  //
+  // The algorithm is specified as the following ASN.1 structure:
+  //    AlgorithmIdentifier  ::=  SEQUENCE  {
+  //        algorithm               OBJECT IDENTIFIER,
+  //        parameters              ANY DEFINED BY algorithm OPTIONAL  }
+  //
+  // An RSA public key is specified as the following ASN.1 structure:
+  //    RSAPublicKey ::= SEQUENCE {
+  //        modulus           INTEGER,  -- n
+  //        publicExponent    INTEGER   -- e
+  //    }
+  static const uint8_t kIntegerTag = 0x02;
+  static const uint8_t kBitStringTag = 0x03;
+  static const uint8_t kSequenceTag = 0x30;
+  public_key_info->clear();
+
+  // Encode the public exponent e as an INTEGER.
+  public_key_info->insert(public_key_info->begin(),
+                          public_exponent_e.begin(),
+                          public_exponent_e.end());
+  PrependASN1Length(public_key_info, public_exponent_e.size());
+  public_key_info->insert(public_key_info->begin(), kIntegerTag);
+
+  // Encode the modulus n as an INTEGER.
+  public_key_info->insert(public_key_info->begin(),
+                          modulus_n.begin(), modulus_n.end());
+  size_t modulus_size = modulus_n.size();
+  if (modulus_n[0] & 0x80) {
+    public_key_info->insert(public_key_info->begin(), 0x00);
+    modulus_size++;
+  }
+  PrependASN1Length(public_key_info, modulus_size);
+  public_key_info->insert(public_key_info->begin(), kIntegerTag);
+
+  // Encode the RSAPublicKey SEQUENCE.
+  PrependASN1Length(public_key_info, public_key_info->size());
+  public_key_info->insert(public_key_info->begin(), kSequenceTag);
+
+  // Encode the BIT STRING.
+  // Number of unused bits.
+  public_key_info->insert(public_key_info->begin(), 0x00);
+  PrependASN1Length(public_key_info, public_key_info->size());
+  public_key_info->insert(public_key_info->begin(), kBitStringTag);
+
+  // Encode the AlgorithmIdentifier.
+  static const uint8_t algorithm[] = {
+      0x30, 0x0d,  // a SEQUENCE of length 13
+      0x06, 0x09,  // an OBJECT IDENTIFIER of length 9
+      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00,
+  };
+  public_key_info->insert(public_key_info->begin(),
+                          algorithm, algorithm + sizeof(algorithm));
+
+  // Encode the outermost SEQUENCE.
+  PrependASN1Length(public_key_info, public_key_info->size());
+  public_key_info->insert(public_key_info->begin(), kSequenceTag);
+
+  return true;
+}
+
+TEST(SignatureVerifierTest, VerifyRSAPSS) {
+  for (unsigned int i = 0; i < arraysize(pss_test); i++) {
+    SCOPED_TRACE(i);
+    std::vector<uint8_t> modulus_n;
+    std::vector<uint8_t> public_exponent_e;
+    ASSERT_TRUE(DecodeTestInput(pss_test[i].modulus_n, &modulus_n));
+    ASSERT_TRUE(DecodeTestInput(pss_test[i].public_exponent_e,
+                                &public_exponent_e));
+    std::vector<uint8_t> public_key_info;
+    ASSERT_TRUE(EncodeRSAPublicKey(modulus_n, public_exponent_e,
+                                   &public_key_info));
+
+    for (unsigned int j = 0; j < arraysize(pss_test[i].example); j++) {
+      SCOPED_TRACE(j);
+      std::vector<uint8_t> message;
+      std::vector<uint8_t> salt;
+      std::vector<uint8_t> signature;
+      ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].message, &message));
+      ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].salt, &salt));
+      ASSERT_TRUE(DecodeTestInput(pss_test[i].example[j].signature,
+                                  &signature));
+
+      crypto::SignatureVerifier verifier;
+      bool ok;
+
+      // Positive test.
+      ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1,
+                                     crypto::SignatureVerifier::SHA1,
+                                     salt.size(),
+                                     &signature[0], signature.size(),
+                                     &public_key_info[0],
+                                     public_key_info.size());
+      ASSERT_TRUE(ok);
+      verifier.VerifyUpdate(&message[0], message.size());
+      ok = verifier.VerifyFinal();
+      EXPECT_TRUE(ok);
+
+      // Modify the first byte of the message.
+      ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1,
+                                     crypto::SignatureVerifier::SHA1,
+                                     salt.size(),
+                                     &signature[0], signature.size(),
+                                     &public_key_info[0],
+                                     public_key_info.size());
+      ASSERT_TRUE(ok);
+      message[0] += 1;
+      verifier.VerifyUpdate(&message[0], message.size());
+      message[0] -= 1;
+      ok = verifier.VerifyFinal();
+      EXPECT_FALSE(ok);
+
+      // Truncate the message.
+      ASSERT_FALSE(message.empty());
+      ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1,
+                                     crypto::SignatureVerifier::SHA1,
+                                     salt.size(),
+                                     &signature[0], signature.size(),
+                                     &public_key_info[0],
+                                     public_key_info.size());
+      ASSERT_TRUE(ok);
+      verifier.VerifyUpdate(&message[0], message.size() - 1);
+      ok = verifier.VerifyFinal();
+      EXPECT_FALSE(ok);
+
+      // Corrupt the signature.
+      signature[0] += 1;
+      ok = verifier.VerifyInitRSAPSS(crypto::SignatureVerifier::SHA1,
+                                     crypto::SignatureVerifier::SHA1,
+                                     salt.size(),
+                                     &signature[0], signature.size(),
+                                     &public_key_info[0],
+                                     public_key_info.size());
+      signature[0] -= 1;
+      ASSERT_TRUE(ok);
+      verifier.VerifyUpdate(&message[0], message.size());
+      ok = verifier.VerifyFinal();
+      EXPECT_FALSE(ok);
+    }
+  }
+}
diff --git a/crypto/symmetric_key.cc b/crypto/symmetric_key.cc
new file mode 100644
index 0000000..69283f8
--- /dev/null
+++ b/crypto/symmetric_key.cc
@@ -0,0 +1,106 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/symmetric_key.h"
+
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <memory>
+
+#include "base/logging.h"
+#include "base/strings/string_util.h"
+#include "crypto/openssl_util.h"
+
+namespace crypto {
+
+SymmetricKey::~SymmetricKey() {
+  std::fill(key_.begin(), key_.end(), '\0');  // Zero out the confidential key.
+}
+
+// static
+SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm,
+                                              size_t key_size_in_bits) {
+  DCHECK_EQ(AES, algorithm);
+
+  // Whitelist supported key sizes to avoid accidentaly relying on
+  // algorithms available in NSS but not BoringSSL and vice
+  // versa. Note that BoringSSL does not support AES-192.
+  if (key_size_in_bits != 128 && key_size_in_bits != 256)
+    return NULL;
+
+  size_t key_size_in_bytes = key_size_in_bits / 8;
+  DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
+
+  if (key_size_in_bytes == 0)
+    return NULL;
+
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  std::unique_ptr<SymmetricKey> key(new SymmetricKey);
+  uint8_t* key_data = reinterpret_cast<uint8_t*>(
+      base::WriteInto(&key->key_, key_size_in_bytes + 1));
+
+  int rv = RAND_bytes(key_data, static_cast<int>(key_size_in_bytes));
+  return rv == 1 ? key.release() : NULL;
+}
+
+// static
+SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm,
+                                                  const std::string& password,
+                                                  const std::string& salt,
+                                                  size_t iterations,
+                                                  size_t key_size_in_bits) {
+  DCHECK(algorithm == AES || algorithm == HMAC_SHA1);
+
+  if (algorithm == AES) {
+    // Whitelist supported key sizes to avoid accidentaly relying on
+    // algorithms available in NSS but not BoringSSL and vice
+    // versa. Note that BoringSSL does not support AES-192.
+    if (key_size_in_bits != 128 && key_size_in_bits != 256)
+      return NULL;
+  }
+
+  size_t key_size_in_bytes = key_size_in_bits / 8;
+  DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
+
+  if (key_size_in_bytes == 0)
+    return NULL;
+
+  OpenSSLErrStackTracer err_tracer(FROM_HERE);
+  std::unique_ptr<SymmetricKey> key(new SymmetricKey);
+  uint8_t* key_data = reinterpret_cast<uint8_t*>(
+      base::WriteInto(&key->key_, key_size_in_bytes + 1));
+  int rv = PKCS5_PBKDF2_HMAC_SHA1(
+      password.data(), password.length(),
+      reinterpret_cast<const uint8_t*>(salt.data()), salt.length(),
+      static_cast<unsigned>(iterations),
+      key_size_in_bytes, key_data);
+  return rv == 1 ? key.release() : NULL;
+}
+
+// static
+SymmetricKey* SymmetricKey::Import(Algorithm algorithm,
+                                   const std::string& raw_key) {
+  if (algorithm == AES) {
+    // Whitelist supported key sizes to avoid accidentaly relying on
+    // algorithms available in NSS but not BoringSSL and vice
+    // versa. Note that BoringSSL does not support AES-192.
+    if (raw_key.size() != 128/8 && raw_key.size() != 256/8)
+      return NULL;
+  }
+
+  std::unique_ptr<SymmetricKey> key(new SymmetricKey);
+  key->key_ = raw_key;
+  return key.release();
+}
+
+bool SymmetricKey::GetRawKey(std::string* raw_key) {
+  *raw_key = key_;
+  return true;
+}
+
+}  // namespace crypto
diff --git a/crypto/symmetric_key.h b/crypto/symmetric_key.h
new file mode 100644
index 0000000..4508619
--- /dev/null
+++ b/crypto/symmetric_key.h
@@ -0,0 +1,104 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRYPTO_SYMMETRIC_KEY_H_
+#define CRYPTO_SYMMETRIC_KEY_H_
+
+#include <stddef.h>
+
+#include <string>
+
+#include "build/build_config.h"
+#include "crypto/crypto_export.h"
+
+#if defined(NACL_WIN64)
+// See comments for crypto_nacl_win64 in crypto.gyp.
+// Must test for NACL_WIN64 before OS_WIN since former is a subset of latter.
+#include "crypto/scoped_capi_types.h"
+#elif defined(USE_NSS_CERTS) || \
+    (!defined(USE_OPENSSL) && (defined(OS_WIN) || defined(OS_MACOSX)))
+#include "crypto/scoped_nss_types.h"
+#endif
+
+namespace crypto {
+
+// Wraps a platform-specific symmetric key and allows it to be held in a
+// scoped_ptr.
+class CRYPTO_EXPORT SymmetricKey {
+ public:
+  // Defines the algorithm that a key will be used with. See also
+  // classs Encrptor.
+  enum Algorithm {
+    AES,
+    HMAC_SHA1,
+  };
+
+  SymmetricKey(const SymmetricKey&) = delete;
+  SymmetricKey& operator=(const SymmetricKey&) = delete;
+
+  virtual ~SymmetricKey();
+
+  // Generates a random key suitable to be used with |algorithm| and of
+  // |key_size_in_bits| bits. |key_size_in_bits| must be a multiple of 8.
+  // The caller is responsible for deleting the returned SymmetricKey.
+  static SymmetricKey* GenerateRandomKey(Algorithm algorithm,
+                                         size_t key_size_in_bits);
+
+  // Derives a key from the supplied password and salt using PBKDF2, suitable
+  // for use with specified |algorithm|. Note |algorithm| is not the algorithm
+  // used to derive the key from the password. |key_size_in_bits| must be a
+  // multiple of 8. The caller is responsible for deleting the returned
+  // SymmetricKey.
+  static SymmetricKey* DeriveKeyFromPassword(Algorithm algorithm,
+                                             const std::string& password,
+                                             const std::string& salt,
+                                             size_t iterations,
+                                             size_t key_size_in_bits);
+
+  // Imports an array of key bytes in |raw_key|. This key may have been
+  // generated by GenerateRandomKey or DeriveKeyFromPassword and exported with
+  // GetRawKey, or via another compatible method. The key must be of suitable
+  // size for use with |algorithm|. The caller owns the returned SymmetricKey.
+  static SymmetricKey* Import(Algorithm algorithm, const std::string& raw_key);
+
+#if defined(NACL_WIN64)
+  HCRYPTKEY key() const { return key_.get(); }
+#elif defined(USE_OPENSSL)
+  const std::string& key() { return key_; }
+#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX)
+  PK11SymKey* key() const { return key_.get(); }
+#endif
+
+  // Extracts the raw key from the platform specific data.
+  // Warning: |raw_key| holds the raw key as bytes and thus must be handled
+  // carefully.
+  bool GetRawKey(std::string* raw_key);
+
+ private:
+#if defined(NACL_WIN64)
+  SymmetricKey(HCRYPTPROV provider, HCRYPTKEY key,
+               const void* key_data, size_t key_size_in_bytes);
+
+  ScopedHCRYPTPROV provider_;
+  ScopedHCRYPTKEY key_;
+
+  // Contains the raw key, if it is known during initialization and when it
+  // is likely that the associated |provider_| will be unable to export the
+  // |key_|. This is the case of HMAC keys when the key size exceeds 16 bytes
+  // when using the default RSA provider.
+  // TODO(rsleevi): See if KP_EFFECTIVE_KEYLEN is the reason why CryptExportKey
+  // fails with NTE_BAD_KEY/NTE_BAD_LEN
+  std::string raw_key_;
+#elif defined(USE_OPENSSL)
+  SymmetricKey() {}
+  std::string key_;
+#elif defined(USE_NSS_CERTS) || defined(OS_WIN) || defined(OS_MACOSX)
+  explicit SymmetricKey(PK11SymKey* key);
+  ScopedPK11SymKey key_;
+#endif
+};
+
+}  // namespace crypto
+
+#endif  // CRYPTO_SYMMETRIC_KEY_H_
diff --git a/crypto/symmetric_key_nss.cc b/crypto/symmetric_key_nss.cc
new file mode 100644
index 0000000..ccdde5b
--- /dev/null
+++ b/crypto/symmetric_key_nss.cc
@@ -0,0 +1,151 @@
+// Copyright 2012 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/symmetric_key.h"
+
+#include <nss.h>
+#include <pk11pub.h>
+#include <stddef.h>
+
+#include "base/logging.h"
+#include "crypto/nss_util.h"
+#include "crypto/scoped_nss_types.h"
+
+namespace crypto {
+
+SymmetricKey::~SymmetricKey() {}
+
+// static
+SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm,
+                                              size_t key_size_in_bits) {
+  DCHECK_EQ(AES, algorithm);
+
+  EnsureNSSInit();
+
+  // Whitelist supported key sizes to avoid accidentaly relying on
+  // algorithms available in NSS but not BoringSSL and vice
+  // versa. Note that BoringSSL does not support AES-192.
+  if (key_size_in_bits != 128 && key_size_in_bits != 256)
+    return NULL;
+
+  ScopedPK11Slot slot(PK11_GetInternalSlot());
+  if (!slot.get())
+    return NULL;
+
+  PK11SymKey* sym_key = PK11_KeyGen(slot.get(), CKM_AES_KEY_GEN, NULL,
+                                    key_size_in_bits / 8, NULL);
+  if (!sym_key)
+    return NULL;
+
+  return new SymmetricKey(sym_key);
+}
+
+// static
+SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm,
+                                                  const std::string& password,
+                                                  const std::string& salt,
+                                                  size_t iterations,
+                                                  size_t key_size_in_bits) {
+  EnsureNSSInit();
+  if (salt.empty() || iterations == 0 || key_size_in_bits == 0)
+    return NULL;
+
+  if (algorithm == AES) {
+    // Whitelist supported key sizes to avoid accidentaly relying on
+    // algorithms available in NSS but not BoringSSL and vice
+    // versa. Note that BoringSSL does not support AES-192.
+    if (key_size_in_bits != 128 && key_size_in_bits != 256)
+      return NULL;
+  }
+
+  SECItem password_item;
+  password_item.type = siBuffer;
+  password_item.data = reinterpret_cast<unsigned char*>(
+      const_cast<char *>(password.data()));
+  password_item.len = password.size();
+
+  SECItem salt_item;
+  salt_item.type = siBuffer;
+  salt_item.data = reinterpret_cast<unsigned char*>(
+      const_cast<char *>(salt.data()));
+  salt_item.len = salt.size();
+
+  SECOidTag cipher_algorithm =
+      algorithm == AES ? SEC_OID_AES_256_CBC : SEC_OID_HMAC_SHA1;
+  ScopedSECAlgorithmID alg_id(PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2,
+                                                          cipher_algorithm,
+                                                          SEC_OID_HMAC_SHA1,
+                                                          key_size_in_bits / 8,
+                                                          iterations,
+                                                          &salt_item));
+  if (!alg_id.get())
+    return NULL;
+
+  ScopedPK11Slot slot(PK11_GetInternalSlot());
+  if (!slot.get())
+    return NULL;
+
+  PK11SymKey* sym_key = PK11_PBEKeyGen(slot.get(), alg_id.get(), &password_item,
+                                       PR_FALSE, NULL);
+  if (!sym_key)
+    return NULL;
+
+  return new SymmetricKey(sym_key);
+}
+
+// static
+SymmetricKey* SymmetricKey::Import(Algorithm algorithm,
+                                   const std::string& raw_key) {
+  EnsureNSSInit();
+
+  if (algorithm == AES) {
+    // Whitelist supported key sizes to avoid accidentaly relying on
+    // algorithms available in NSS but not BoringSSL and vice
+    // versa. Note that BoringSSL does not support AES-192.
+    if (raw_key.size() != 128/8 && raw_key.size() != 256/8)
+      return NULL;
+  }
+
+  CK_MECHANISM_TYPE cipher =
+      algorithm == AES ? CKM_AES_CBC : CKM_SHA_1_HMAC;
+
+  SECItem key_item;
+  key_item.type = siBuffer;
+  key_item.data = reinterpret_cast<unsigned char*>(
+      const_cast<char *>(raw_key.data()));
+  key_item.len = raw_key.size();
+
+  ScopedPK11Slot slot(PK11_GetInternalSlot());
+  if (!slot.get())
+    return NULL;
+
+  // The exact value of the |origin| argument doesn't matter to NSS as long as
+  // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a
+  // placeholder.
+  PK11SymKey* sym_key = PK11_ImportSymKey(slot.get(), cipher, PK11_OriginUnwrap,
+                                          CKA_ENCRYPT, &key_item, NULL);
+  if (!sym_key)
+    return NULL;
+
+  return new SymmetricKey(sym_key);
+}
+
+bool SymmetricKey::GetRawKey(std::string* raw_key) {
+  SECStatus rv = PK11_ExtractKeyValue(key_.get());
+  if (SECSuccess != rv)
+    return false;
+
+  SECItem* key_item = PK11_GetKeyData(key_.get());
+  if (!key_item)
+    return false;
+
+  raw_key->assign(reinterpret_cast<char*>(key_item->data), key_item->len);
+  return true;
+}
+
+SymmetricKey::SymmetricKey(PK11SymKey* key) : key_(key) {
+  DCHECK(key);
+}
+
+}  // namespace crypto
diff --git a/crypto/symmetric_key_unittest.cc b/crypto/symmetric_key_unittest.cc
new file mode 100644
index 0000000..4ce3f30
--- /dev/null
+++ b/crypto/symmetric_key_unittest.cc
@@ -0,0 +1,224 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "crypto/symmetric_key.h"
+
+#include <memory>
+#include <string>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+TEST(SymmetricKeyTest, GenerateRandomKey) {
+  std::unique_ptr<crypto::SymmetricKey> key(
+      crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256));
+  ASSERT_TRUE(NULL != key.get());
+  std::string raw_key;
+  EXPECT_TRUE(key->GetRawKey(&raw_key));
+  EXPECT_EQ(32U, raw_key.size());
+
+  // Do it again and check that the keys are different.
+  // (Note: this has a one-in-10^77 chance of failure!)
+  std::unique_ptr<crypto::SymmetricKey> key2(
+      crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256));
+  ASSERT_TRUE(NULL != key2.get());
+  std::string raw_key2;
+  EXPECT_TRUE(key2->GetRawKey(&raw_key2));
+  EXPECT_EQ(32U, raw_key2.size());
+  EXPECT_NE(raw_key, raw_key2);
+}
+
+TEST(SymmetricKeyTest, ImportGeneratedKey) {
+  std::unique_ptr<crypto::SymmetricKey> key1(
+      crypto::SymmetricKey::GenerateRandomKey(crypto::SymmetricKey::AES, 256));
+  ASSERT_TRUE(NULL != key1.get());
+  std::string raw_key1;
+  EXPECT_TRUE(key1->GetRawKey(&raw_key1));
+
+  std::unique_ptr<crypto::SymmetricKey> key2(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key1));
+  ASSERT_TRUE(NULL != key2.get());
+
+  std::string raw_key2;
+  EXPECT_TRUE(key2->GetRawKey(&raw_key2));
+
+  EXPECT_EQ(raw_key1, raw_key2);
+}
+
+TEST(SymmetricKeyTest, ImportDerivedKey) {
+  std::unique_ptr<crypto::SymmetricKey> key1(
+      crypto::SymmetricKey::DeriveKeyFromPassword(
+          crypto::SymmetricKey::HMAC_SHA1, "password", "somesalt", 1024, 160));
+  ASSERT_TRUE(NULL != key1.get());
+  std::string raw_key1;
+  EXPECT_TRUE(key1->GetRawKey(&raw_key1));
+
+  std::unique_ptr<crypto::SymmetricKey> key2(
+      crypto::SymmetricKey::Import(crypto::SymmetricKey::HMAC_SHA1, raw_key1));
+  ASSERT_TRUE(NULL != key2.get());
+
+  std::string raw_key2;
+  EXPECT_TRUE(key2->GetRawKey(&raw_key2));
+
+  EXPECT_EQ(raw_key1, raw_key2);
+}
+
+struct PBKDF2TestVector {
+  crypto::SymmetricKey::Algorithm algorithm;
+  const char* password;
+  const char* salt;
+  unsigned int rounds;
+  unsigned int key_size_in_bits;
+  const char* expected;  // ASCII encoded hex bytes
+};
+
+class SymmetricKeyDeriveKeyFromPasswordTest
+    : public testing::TestWithParam<PBKDF2TestVector> {
+};
+
+TEST_P(SymmetricKeyDeriveKeyFromPasswordTest, DeriveKeyFromPassword) {
+  PBKDF2TestVector test_data(GetParam());
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+  // The OS X crypto libraries have minimum salt and iteration requirements
+  // so some of the tests below will cause them to barf. Skip these.
+  if (strlen(test_data.salt) < 8 || test_data.rounds < 1000) {
+    VLOG(1) << "Skipped test vector for " << test_data.expected;
+    return;
+  }
+#endif  // OS_MACOSX
+
+  std::unique_ptr<crypto::SymmetricKey> key(
+      crypto::SymmetricKey::DeriveKeyFromPassword(
+          test_data.algorithm, test_data.password, test_data.salt,
+          test_data.rounds, test_data.key_size_in_bits));
+  ASSERT_TRUE(NULL != key.get());
+
+  std::string raw_key;
+  key->GetRawKey(&raw_key);
+  EXPECT_EQ(test_data.key_size_in_bits / 8, raw_key.size());
+  EXPECT_EQ(test_data.expected,
+            base::ToLowerASCII(base::HexEncode(raw_key.data(),
+                                               raw_key.size())));
+}
+
+static const PBKDF2TestVector kTestVectors[] = {
+  // These tests come from
+  // http://www.ietf.org/id/draft-josefsson-pbkdf2-test-vectors-00.txt
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "password",
+    "salt",
+    1,
+    160,
+    "0c60c80f961f0e71f3a9b524af6012062fe037a6",
+  },
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "password",
+    "salt",
+    2,
+    160,
+    "ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957",
+  },
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "password",
+    "salt",
+    4096,
+    160,
+    "4b007901b765489abead49d926f721d065a429c1",
+  },
+  // This test takes over 30s to run on the trybots.
+#if 0
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "password",
+    "salt",
+    16777216,
+    160,
+    "eefe3d61cd4da4e4e9945b3d6ba2158c2634e984",
+  },
+#endif
+
+  // These tests come from RFC 3962, via BSD source code at
+  // http://www.openbsd.org/cgi-bin/cvsweb/src/sbin/bioctl/pbkdf2.c?rev=HEAD&content-type=text/plain
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "password",
+    "ATHENA.MIT.EDUraeburn",
+    1,
+    160,
+    "cdedb5281bb2f801565a1122b25635150ad1f7a0",
+  },
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "password",
+    "ATHENA.MIT.EDUraeburn",
+    2,
+    160,
+    "01dbee7f4a9e243e988b62c73cda935da05378b9",
+  },
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "password",
+    "ATHENA.MIT.EDUraeburn",
+    1200,
+    160,
+    "5c08eb61fdf71e4e4ec3cf6ba1f5512ba7e52ddb",
+  },
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "password",
+    "\022" "4VxxV4\022", /* 0x1234567878563412 */
+    5,
+    160,
+    "d1daa78615f287e6a1c8b120d7062a493f98d203",
+  },
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+    "pass phrase equals block size",
+    1200,
+    160,
+    "139c30c0966bc32ba55fdbf212530ac9c5ec59f1",
+  },
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+    "pass phrase exceeds block size",
+    1200,
+    160,
+    "9ccad6d468770cd51b10e6a68721be611a8b4d28",
+  },
+  {
+    crypto::SymmetricKey::HMAC_SHA1,
+    "\360\235\204\236", /* g-clef (0xf09d849e) */
+    "EXAMPLE.COMpianist",
+    50,
+    160,
+    "6b9cf26d45455a43a5b8bb276a403b39e7fe37a0",
+  },
+
+  // Regression tests for AES keys, derived from the Linux NSS implementation.
+  {
+    crypto::SymmetricKey::AES,
+    "A test password",
+    "saltsalt",
+    1,
+    256,
+    "44899a7777f0e6e8b752f875f02044b8ac593de146de896f2e8a816e315a36de",
+  },
+  {
+    crypto::SymmetricKey::AES,
+    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+    "pass phrase exceeds block size",
+    20,
+    256,
+    "e0739745dc28b8721ba402e05214d2ac1eab54cf72bee1fba388297a09eb493c",
+  },
+};
+
+INSTANTIATE_TEST_CASE_P(, SymmetricKeyDeriveKeyFromPasswordTest,
+                        testing::ValuesIn(kTestVectors));
diff --git a/crypto/third_party/nss/chromium-blapi.h b/crypto/third_party/nss/chromium-blapi.h
new file mode 100644
index 0000000..2ca772e
--- /dev/null
+++ b/crypto/third_party/nss/chromium-blapi.h
@@ -0,0 +1,101 @@
+/*
+ * crypto.h - public data structures and prototypes for the crypto library
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/* $Id: blapi.h,v 1.27 2007/11/09 18:49:32 wtc%google.com Exp $ */
+
+#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_
+#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_
+
+#include "crypto/third_party/nss/chromium-blapit.h"
+
+/******************************************/
+
+extern SHA256Context *SHA256_NewContext(void);
+extern void SHA256_DestroyContext(SHA256Context *cx, PRBool freeit);
+extern void SHA256_Begin(SHA256Context *cx);
+extern void SHA256_Update(SHA256Context *cx, const unsigned char *input,
+			unsigned int inputLen);
+extern void SHA256_End(SHA256Context *cx, unsigned char *digest,
+		     unsigned int *digestLen, unsigned int maxDigestLen);
+extern SECStatus SHA256_HashBuf(unsigned char *dest, const unsigned char *src,
+			      unsigned int src_length);
+extern SECStatus SHA256_Hash(unsigned char *dest, const char *src);
+extern void SHA256_TraceState(SHA256Context *cx);
+extern unsigned int SHA256_FlattenSize(SHA256Context *cx);
+extern SECStatus SHA256_Flatten(SHA256Context *cx,unsigned char *space);
+extern SHA256Context * SHA256_Resurrect(unsigned char *space, void *arg);
+extern void SHA256_Clone(SHA256Context *dest, SHA256Context *src);
+
+/******************************************/
+
+extern SHA512Context *SHA512_NewContext(void);
+extern void SHA512_DestroyContext(SHA512Context *cx, PRBool freeit);
+extern void SHA512_Begin(SHA512Context *cx);
+extern void SHA512_Update(SHA512Context *cx, const unsigned char *input,
+			unsigned int inputLen);
+extern void SHA512_End(SHA512Context *cx, unsigned char *digest,
+		     unsigned int *digestLen, unsigned int maxDigestLen);
+extern SECStatus SHA512_HashBuf(unsigned char *dest, const unsigned char *src,
+			      unsigned int src_length);
+extern SECStatus SHA512_Hash(unsigned char *dest, const char *src);
+extern void SHA512_TraceState(SHA512Context *cx);
+extern unsigned int SHA512_FlattenSize(SHA512Context *cx);
+extern SECStatus SHA512_Flatten(SHA512Context *cx,unsigned char *space);
+extern SHA512Context * SHA512_Resurrect(unsigned char *space, void *arg);
+extern void SHA512_Clone(SHA512Context *dest, SHA512Context *src);
+
+/******************************************/
+
+extern SHA384Context *SHA384_NewContext(void);
+extern void SHA384_DestroyContext(SHA384Context *cx, PRBool freeit);
+extern void SHA384_Begin(SHA384Context *cx);
+extern void SHA384_Update(SHA384Context *cx, const unsigned char *input,
+			unsigned int inputLen);
+extern void SHA384_End(SHA384Context *cx, unsigned char *digest,
+		     unsigned int *digestLen, unsigned int maxDigestLen);
+extern SECStatus SHA384_HashBuf(unsigned char *dest, const unsigned char *src,
+			      unsigned int src_length);
+extern SECStatus SHA384_Hash(unsigned char *dest, const char *src);
+extern void SHA384_TraceState(SHA384Context *cx);
+extern unsigned int SHA384_FlattenSize(SHA384Context *cx);
+extern SECStatus SHA384_Flatten(SHA384Context *cx,unsigned char *space);
+extern SHA384Context * SHA384_Resurrect(unsigned char *space, void *arg);
+extern void SHA384_Clone(SHA384Context *dest, SHA384Context *src);
+
+#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPI_H_ */
diff --git a/crypto/third_party/nss/chromium-blapit.h b/crypto/third_party/nss/chromium-blapit.h
new file mode 100644
index 0000000..938547a
--- /dev/null
+++ b/crypto/third_party/nss/chromium-blapit.h
@@ -0,0 +1,91 @@
+/*
+ * blapit.h - public data structures for the crypto library
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Dr Vipul Gupta <vipul.gupta@sun.com> and
+ *   Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/* $Id: blapit.h,v 1.20 2007/02/28 19:47:37 rrelyea%redhat.com Exp $ */
+
+#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_
+#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_
+
+#include "crypto/third_party/nss/chromium-prtypes.h"
+
+/*
+** A status code. Status's are used by procedures that return status
+** values. Again the motivation is so that a compiler can generate
+** warnings when return values are wrong. Correct testing of status codes:
+**
+**      SECStatus rv;
+**      rv = some_function (some_argument);
+**      if (rv != SECSuccess)
+**              do_an_error_thing();
+**
+*/
+typedef enum _SECStatus {
+    SECWouldBlock = -2,
+    SECFailure = -1,
+    SECSuccess = 0
+} SECStatus;
+
+#define SHA256_LENGTH 		32 	/* bytes */
+#define SHA384_LENGTH 		48 	/* bytes */
+#define SHA512_LENGTH 		64 	/* bytes */
+#define HASH_LENGTH_MAX         SHA512_LENGTH
+
+/*
+ * Input block size for each hash algorithm.
+ */
+
+#define SHA256_BLOCK_LENGTH      64     /* bytes */
+#define SHA384_BLOCK_LENGTH     128     /* bytes */
+#define SHA512_BLOCK_LENGTH     128     /* bytes */
+#define HASH_BLOCK_LENGTH_MAX   SHA512_BLOCK_LENGTH
+
+/***************************************************************************
+** Opaque objects
+*/
+
+struct SHA256ContextStr     ;
+struct SHA512ContextStr     ;
+
+typedef struct SHA256ContextStr     SHA256Context;
+typedef struct SHA512ContextStr     SHA512Context;
+/* SHA384Context is really a SHA512ContextStr.  This is not a mistake. */
+typedef struct SHA512ContextStr     SHA384Context;
+
+#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_ */
diff --git a/crypto/third_party/nss/chromium-nss.h b/crypto/third_party/nss/chromium-nss.h
new file mode 100644
index 0000000..437e6bd
--- /dev/null
+++ b/crypto/third_party/nss/chromium-nss.h
@@ -0,0 +1,79 @@
+ /* ***** BEGIN LICENSE BLOCK *****
+  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+  *
+  * The contents of this file are subject to the Mozilla Public License Version
+  * 1.1 (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.mozilla.org/MPL/
+  *
+  * Software distributed under the License is distributed on an "AS IS" basis,
+  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+  * for the specific language governing rights and limitations under the
+  * License.
+  *
+  * The Original Code is the Netscape security libraries.
+  *
+  * The Initial Developer of the Original Code is
+  * Netscape Communications Corporation.
+  * Portions created by the Initial Developer are Copyright (C) 1994-2000
+  * the Initial Developer. All Rights Reserved.
+  *
+  * Contributor(s):
+  *
+  * Alternatively, the contents of this file may be used under the terms of
+  * either the GNU General Public License Version 2 or later (the "GPL"), or
+  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+  * in which case the provisions of the GPL or the LGPL are applicable instead
+  * of those above. If you wish to allow use of your version of this file only
+  * under the terms of either the GPL or the LGPL, and not to allow others to
+  * use your version of this file under the terms of the MPL, indicate your
+  * decision by deleting the provisions above and replace them with the notice
+  * and other provisions required by the GPL or the LGPL. If you do not delete
+  * the provisions above, a recipient may use your version of this file under
+  * the terms of any one of the MPL, the GPL or the LGPL.
+  *
+  * ***** END LICENSE BLOCK ***** */
+
+#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_
+#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_
+
+// This file contains some functions we borrowed from NSS.
+
+#include <prtypes.h>
+#include <hasht.h>
+#include <keyhi.h>
+#include <secmod.h>
+
+#include "crypto/crypto_export.h"
+
+extern "C" SECStatus emsa_pss_verify(const unsigned char *mHash,
+                                     const unsigned char *em,
+                                     unsigned int emLen,
+                                     HASH_HashType hashAlg,
+                                     HASH_HashType maskHashAlg,
+                                     unsigned int sLen);
+
+// Like PK11_ImportEncryptedPrivateKeyInfo, but hardcoded for EC, and returns
+// the SECKEYPrivateKey.
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=211546
+// When we use NSS 3.13.2 or later,
+// PK11_ImportEncryptedPrivateKeyInfoAndReturnKey can be used instead.
+SECStatus ImportEncryptedECPrivateKeyInfoAndReturnKey(
+    PK11SlotInfo* slot,
+    SECKEYEncryptedPrivateKeyInfo* epki,
+    SECItem* password,
+    SECItem* nickname,
+    SECItem* public_value,
+    PRBool permanent,
+    PRBool sensitive,
+    SECKEYPrivateKey** private_key,
+    void* wincx);
+
+// Like SEC_DerSignData.
+CRYPTO_EXPORT SECStatus DerSignData(PLArenaPool *arena,
+                                    SECItem *result,
+                                    SECItem *input,
+                                    SECKEYPrivateKey *key,
+                                    SECOidTag algo_id);
+
+#endif  // CRYPTO_THIRD_PARTY_NSS_CHROMIUM_NSS_H_
diff --git a/crypto/third_party/nss/chromium-prtypes.h b/crypto/third_party/nss/chromium-prtypes.h
new file mode 100644
index 0000000..d5ea8a9
--- /dev/null
+++ b/crypto/third_party/nss/chromium-prtypes.h
@@ -0,0 +1,77 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Emulates the real prtypes.h. Defines the types and macros that sha512.cc
+ * needs. */
+
+#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_
+#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_
+
+#include <limits.h>
+#include <stdint.h>
+
+#include "build/build_config.h"
+
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+#define IS_LITTLE_ENDIAN 1
+#else
+#define IS_BIG_ENDIAN 1
+#endif
+
+/*
+ * The C language requires that 'long' be at least 32 bits. 2147483647 is the
+ * largest signed 32-bit integer.
+ */
+#if LONG_MAX > 2147483647L
+#define PR_BYTES_PER_LONG 8
+#else
+#define PR_BYTES_PER_LONG 4
+#endif
+
+#define HAVE_LONG_LONG
+
+#if defined(__linux__)
+#define LINUX
+#endif
+
+typedef uint8_t PRUint8;
+typedef uint32_t PRUint32;
+
+typedef int PRBool;
+
+#define PR_MIN(x,y) ((x)<(y)?(x):(y))
+
+#endif  /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_ */
diff --git a/crypto/third_party/nss/chromium-sha256.h b/crypto/third_party/nss/chromium-sha256.h
new file mode 100644
index 0000000..52815ca
--- /dev/null
+++ b/crypto/third_party/nss/chromium-sha256.h
@@ -0,0 +1,51 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_
+#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_
+
+#include "crypto/third_party/nss/chromium-prtypes.h"
+
+struct SHA256ContextStr {
+    union {
+	PRUint32 w[64];	    /* message schedule, input buffer, plus 48 words */
+	PRUint8  b[256];
+    } u;
+    PRUint32 h[8];		/* 8 state variables */
+    PRUint32 sizeHi,sizeLo;	/* 64-bit count of hashed bytes. */
+};
+
+#endif /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_ */
diff --git a/crypto/third_party/nss/rsawrapr.c b/crypto/third_party/nss/rsawrapr.c
new file mode 100644
index 0000000..73e498f
--- /dev/null
+++ b/crypto/third_party/nss/rsawrapr.c
@@ -0,0 +1,160 @@
+/*
+ * PKCS#1 encoding and decoding functions.
+ * This file is believed to contain no code licensed from other parties.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "seccomon.h"
+#include "secerr.h"
+#include "sechash.h"
+
+/* Needed for RSA-PSS functions */
+static const unsigned char eightZeros[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+/*
+ * Mask generation function MGF1 as defined in PKCS #1 v2.1 / RFC 3447.
+ */
+static SECStatus
+MGF1(HASH_HashType hashAlg, unsigned char *mask, unsigned int maskLen,
+     const unsigned char *mgfSeed, unsigned int mgfSeedLen)
+{
+    unsigned int digestLen;
+    PRUint32 counter, rounds;
+    unsigned char *tempHash, *temp;
+    const SECHashObject *hash;
+    void *hashContext;
+    unsigned char C[4];
+
+    hash = HASH_GetHashObject(hashAlg);
+    if (hash == NULL)
+        return SECFailure;
+
+    hashContext = (*hash->create)();
+    rounds = (maskLen + hash->length - 1) / hash->length;
+    for (counter = 0; counter < rounds; counter++) {
+        C[0] = (unsigned char)((counter >> 24) & 0xff);
+        C[1] = (unsigned char)((counter >> 16) & 0xff);
+        C[2] = (unsigned char)((counter >> 8) & 0xff);
+        C[3] = (unsigned char)(counter & 0xff);
+
+        /* This could be optimized when the clone functions in
+         * rawhash.c are implemented. */
+        (*hash->begin)(hashContext);
+        (*hash->update)(hashContext, mgfSeed, mgfSeedLen); 
+        (*hash->update)(hashContext, C, sizeof C);
+
+        tempHash = mask + counter * hash->length;
+        if (counter != (rounds-1)) {
+            (*hash->end)(hashContext, tempHash, &digestLen, hash->length);
+        } else { /* we're in the last round and need to cut the hash */
+            temp = (unsigned char *)PORT_Alloc(hash->length);
+            (*hash->end)(hashContext, temp, &digestLen, hash->length);
+            PORT_Memcpy(tempHash, temp, maskLen - counter * hash->length);
+            PORT_Free(temp);
+        }
+    }
+    (*hash->destroy)(hashContext, PR_TRUE);
+
+    return SECSuccess;
+}
+
+/*
+ * Verify a RSA-PSS signature.
+ * Described in RFC 3447, section 9.1.2.
+ * We use mHash instead of M as input.
+ * emBits from the RFC is just modBits - 1, see section 8.1.2.
+ * We only support MGF1 as the MGF.
+ *
+ * NOTE: this code assumes modBits is a multiple of 8.
+ */
+SECStatus
+emsa_pss_verify(const unsigned char *mHash,
+                const unsigned char *em, unsigned int emLen,
+                HASH_HashType hashAlg, HASH_HashType maskHashAlg,
+                unsigned int sLen)
+{
+    const SECHashObject *hash;
+    void *hash_context;
+    unsigned char *db;
+    unsigned char *H_;  /* H' from the RFC */
+    unsigned int i, dbMaskLen;
+    SECStatus rv;
+
+    hash = HASH_GetHashObject(hashAlg);
+    dbMaskLen = emLen - hash->length - 1;
+
+    /* Step 3 + 4 + 6 */
+    if ((emLen < (hash->length + sLen + 2)) ||
+	(em[emLen - 1] != 0xbc) ||
+	((em[0] & 0x80) != 0)) {
+	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+	return SECFailure;
+    }
+
+    /* Step 7 */
+    db = (unsigned char *)PORT_Alloc(dbMaskLen);
+    if (db == NULL) {
+	PORT_SetError(SEC_ERROR_NO_MEMORY);
+	return SECFailure;
+    }
+    /* &em[dbMaskLen] points to H, used as mgfSeed */
+    MGF1(maskHashAlg, db, dbMaskLen, &em[dbMaskLen], hash->length);
+
+    /* Step 8 */
+    for (i = 0; i < dbMaskLen; i++) {
+	db[i] ^= em[i];
+    }
+
+    /* Step 9 */
+    db[0] &= 0x7f;
+
+    /* Step 10 */
+    for (i = 0; i < (dbMaskLen - sLen - 1); i++) {
+	if (db[i] != 0) {
+	    PORT_Free(db);
+	    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+	    return SECFailure;
+	}
+    }
+    if (db[dbMaskLen - sLen - 1] != 0x01) {
+	PORT_Free(db);
+	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+	return SECFailure;
+    }
+
+    /* Step 12 + 13 */
+    H_ = (unsigned char *)PORT_Alloc(hash->length);
+    if (H_ == NULL) {
+	PORT_Free(db);
+	PORT_SetError(SEC_ERROR_NO_MEMORY);
+	return SECFailure;
+    }
+    hash_context = (*hash->create)();
+    if (hash_context == NULL) {
+	PORT_Free(db);
+	PORT_Free(H_);
+	PORT_SetError(SEC_ERROR_NO_MEMORY);
+	return SECFailure;
+    }
+    (*hash->begin)(hash_context);
+    (*hash->update)(hash_context, eightZeros, 8);
+    (*hash->update)(hash_context, mHash, hash->length);
+    (*hash->update)(hash_context, &db[dbMaskLen - sLen], sLen);
+    (*hash->end)(hash_context, H_, &i, hash->length);
+    (*hash->destroy)(hash_context, PR_TRUE);
+
+    PORT_Free(db);
+
+    /* Step 14 */
+    if (PORT_Memcmp(H_, &em[dbMaskLen], hash->length) != 0) {
+	PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+	rv = SECFailure;
+    } else {
+	rv = SECSuccess;
+    }
+
+    PORT_Free(H_);
+    return rv;
+}
diff --git a/crypto/third_party/nss/sha512.cc b/crypto/third_party/nss/sha512.cc
new file mode 100644
index 0000000..4698bf2
--- /dev/null
+++ b/crypto/third_party/nss/sha512.cc
@@ -0,0 +1,1390 @@
+/*
+ * sha512.c - implementation of SHA256, SHA384 and SHA512
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+/* $Id: sha512.c,v 1.9 2006/10/13 16:54:04 wtchang%redhat.com Exp $ */
+
+// Prevent manual unrolling in the sha256 code, which reduces the binary code
+// size from ~10k to ~1k.  The performance should be reasonable for our use.
+#define NOUNROLL256 1
+
+#include "crypto/third_party/nss/chromium-prtypes.h"  /* for PRUintXX */
+#if defined(_X86_) || defined(SHA_NO_LONG_LONG)
+#define NOUNROLL512 1
+#undef HAVE_LONG_LONG
+#endif
+#include "crypto/third_party/nss/chromium-blapi.h"
+#include "crypto/third_party/nss/chromium-sha256.h"    /* for struct SHA256ContextStr */
+
+#include <stdlib.h>
+#include <string.h>
+#define PORT_New(type) static_cast<type*>(malloc(sizeof(type)))
+#define PORT_ZFree(ptr, len) do { memset(ptr, 0, len); free(ptr); } while (0)
+#define PORT_Strlen(s) static_cast<unsigned int>(strlen(s))
+#define PORT_Memcpy memcpy
+
+/* ============= Common constants and defines ======================= */
+
+#define W ctx->u.w
+#define B ctx->u.b
+#define H ctx->h
+
+#define SHR(x,n) (x >> n)
+#define SHL(x,n) (x << n)
+#define Ch(x,y,z)  ((x & y) ^ (~x & z))
+#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
+
+/* Padding used with all flavors of SHA */
+static const PRUint8 pad[240] = {
+0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+   /* compiler will fill the rest in with zeros */
+};
+
+/* ============= SHA256 implemenmtation ================================== */
+
+/* SHA-256 constants, K256. */
+static const PRUint32 K256[64] = {
+    0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+    0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+    0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+    0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+    0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+    0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+    0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+    0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+    0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+    0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+    0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+    0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+    0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+    0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+    0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+    0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+/* SHA-256 initial hash values */
+static const PRUint32 H256[8] = {
+    0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+    0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
+};
+
+#if defined(_MSC_VER) && defined(_X86_)
+#ifndef FORCEINLINE
+#if (_MSC_VER >= 1200)
+#define FORCEINLINE __forceinline
+#else
+#define FORCEINLINE __inline
+#endif
+#endif
+#define FASTCALL __fastcall
+
+static FORCEINLINE PRUint32 FASTCALL
+swap4b(PRUint32 dwd)
+{
+    __asm {
+    	mov   eax,dwd
+	bswap eax
+    }
+}
+
+#define SHA_HTONL(x) swap4b(x)
+#define BYTESWAP4(x)  x = SHA_HTONL(x)
+
+#elif defined(LINUX) && defined(_X86_)
+#undef  __OPTIMIZE__
+#define __OPTIMIZE__ 1
+#undef  __pentium__
+#define __pentium__ 1
+#include <byteswap.h>
+#define SHA_HTONL(x) bswap_32(x)
+#define BYTESWAP4(x)  x = SHA_HTONL(x)
+
+#else /* neither windows nor Linux PC */
+#define SWAP4MASK  0x00FF00FF
+#define SHA_HTONL(x) (t1 = (x), t1 = (t1 << 16) | (t1 >> 16), \
+                      ((t1 & SWAP4MASK) << 8) | ((t1 >> 8) & SWAP4MASK))
+#define BYTESWAP4(x)  x = SHA_HTONL(x)
+#endif
+
+#if defined(_MSC_VER) && defined(_X86_)
+#pragma intrinsic (_lrotr, _lrotl)
+#define ROTR32(x,n) _lrotr(x,n)
+#define ROTL32(x,n) _lrotl(x,n)
+#else
+#define ROTR32(x,n) ((x >> n) | (x << ((8 * sizeof x) - n)))
+#define ROTL32(x,n) ((x << n) | (x >> ((8 * sizeof x) - n)))
+#endif
+
+/* Capitol Sigma and lower case sigma functions */
+#define S0(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x,22))
+#define S1(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x,25))
+#define s0(x) (t1 = x, ROTR32(t1, 7) ^ ROTR32(t1,18) ^ SHR(t1, 3))
+#define s1(x) (t2 = x, ROTR32(t2,17) ^ ROTR32(t2,19) ^ SHR(t2,10))
+
+SHA256Context *
+SHA256_NewContext(void)
+{
+    SHA256Context *ctx = PORT_New(SHA256Context);
+    return ctx;
+}
+
+void
+SHA256_DestroyContext(SHA256Context *ctx, PRBool freeit)
+{
+    if (freeit) {
+        PORT_ZFree(ctx, sizeof *ctx);
+    }
+}
+
+void
+SHA256_Begin(SHA256Context *ctx)
+{
+    memset(ctx, 0, sizeof *ctx);
+    memcpy(H, H256, sizeof H256);
+}
+
+static void
+SHA256_Compress(SHA256Context *ctx)
+{
+  {
+    PRUint32 t1, t2;
+
+#if defined(IS_LITTLE_ENDIAN)
+    BYTESWAP4(W[0]);
+    BYTESWAP4(W[1]);
+    BYTESWAP4(W[2]);
+    BYTESWAP4(W[3]);
+    BYTESWAP4(W[4]);
+    BYTESWAP4(W[5]);
+    BYTESWAP4(W[6]);
+    BYTESWAP4(W[7]);
+    BYTESWAP4(W[8]);
+    BYTESWAP4(W[9]);
+    BYTESWAP4(W[10]);
+    BYTESWAP4(W[11]);
+    BYTESWAP4(W[12]);
+    BYTESWAP4(W[13]);
+    BYTESWAP4(W[14]);
+    BYTESWAP4(W[15]);
+#endif
+
+#define INITW(t) W[t] = (s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16])
+
+    /* prepare the "message schedule"   */
+#ifdef NOUNROLL256
+    {
+	int t;
+	for (t = 16; t < 64; ++t) {
+	    INITW(t);
+	}
+    }
+#else
+    INITW(16);
+    INITW(17);
+    INITW(18);
+    INITW(19);
+
+    INITW(20);
+    INITW(21);
+    INITW(22);
+    INITW(23);
+    INITW(24);
+    INITW(25);
+    INITW(26);
+    INITW(27);
+    INITW(28);
+    INITW(29);
+
+    INITW(30);
+    INITW(31);
+    INITW(32);
+    INITW(33);
+    INITW(34);
+    INITW(35);
+    INITW(36);
+    INITW(37);
+    INITW(38);
+    INITW(39);
+
+    INITW(40);
+    INITW(41);
+    INITW(42);
+    INITW(43);
+    INITW(44);
+    INITW(45);
+    INITW(46);
+    INITW(47);
+    INITW(48);
+    INITW(49);
+
+    INITW(50);
+    INITW(51);
+    INITW(52);
+    INITW(53);
+    INITW(54);
+    INITW(55);
+    INITW(56);
+    INITW(57);
+    INITW(58);
+    INITW(59);
+
+    INITW(60);
+    INITW(61);
+    INITW(62);
+    INITW(63);
+
+#endif
+#undef INITW
+  }
+  {
+    PRUint32 a, b, c, d, e, f, g, h;
+
+    a = H[0];
+    b = H[1];
+    c = H[2];
+    d = H[3];
+    e = H[4];
+    f = H[5];
+    g = H[6];
+    h = H[7];
+
+#define ROUND(n,a,b,c,d,e,f,g,h) \
+    h += S1(e) + Ch(e,f,g) + K256[n] + W[n]; \
+    d += h; \
+    h += S0(a) + Maj(a,b,c);
+
+#ifdef NOUNROLL256
+    {
+	int t;
+	for (t = 0; t < 64; t+= 8) {
+	    ROUND(t+0,a,b,c,d,e,f,g,h)
+	    ROUND(t+1,h,a,b,c,d,e,f,g)
+	    ROUND(t+2,g,h,a,b,c,d,e,f)
+	    ROUND(t+3,f,g,h,a,b,c,d,e)
+	    ROUND(t+4,e,f,g,h,a,b,c,d)
+	    ROUND(t+5,d,e,f,g,h,a,b,c)
+	    ROUND(t+6,c,d,e,f,g,h,a,b)
+	    ROUND(t+7,b,c,d,e,f,g,h,a)
+	}
+    }
+#else
+    ROUND( 0,a,b,c,d,e,f,g,h)
+    ROUND( 1,h,a,b,c,d,e,f,g)
+    ROUND( 2,g,h,a,b,c,d,e,f)
+    ROUND( 3,f,g,h,a,b,c,d,e)
+    ROUND( 4,e,f,g,h,a,b,c,d)
+    ROUND( 5,d,e,f,g,h,a,b,c)
+    ROUND( 6,c,d,e,f,g,h,a,b)
+    ROUND( 7,b,c,d,e,f,g,h,a)
+
+    ROUND( 8,a,b,c,d,e,f,g,h)
+    ROUND( 9,h,a,b,c,d,e,f,g)
+    ROUND(10,g,h,a,b,c,d,e,f)
+    ROUND(11,f,g,h,a,b,c,d,e)
+    ROUND(12,e,f,g,h,a,b,c,d)
+    ROUND(13,d,e,f,g,h,a,b,c)
+    ROUND(14,c,d,e,f,g,h,a,b)
+    ROUND(15,b,c,d,e,f,g,h,a)
+
+    ROUND(16,a,b,c,d,e,f,g,h)
+    ROUND(17,h,a,b,c,d,e,f,g)
+    ROUND(18,g,h,a,b,c,d,e,f)
+    ROUND(19,f,g,h,a,b,c,d,e)
+    ROUND(20,e,f,g,h,a,b,c,d)
+    ROUND(21,d,e,f,g,h,a,b,c)
+    ROUND(22,c,d,e,f,g,h,a,b)
+    ROUND(23,b,c,d,e,f,g,h,a)
+
+    ROUND(24,a,b,c,d,e,f,g,h)
+    ROUND(25,h,a,b,c,d,e,f,g)
+    ROUND(26,g,h,a,b,c,d,e,f)
+    ROUND(27,f,g,h,a,b,c,d,e)
+    ROUND(28,e,f,g,h,a,b,c,d)
+    ROUND(29,d,e,f,g,h,a,b,c)
+    ROUND(30,c,d,e,f,g,h,a,b)
+    ROUND(31,b,c,d,e,f,g,h,a)
+
+    ROUND(32,a,b,c,d,e,f,g,h)
+    ROUND(33,h,a,b,c,d,e,f,g)
+    ROUND(34,g,h,a,b,c,d,e,f)
+    ROUND(35,f,g,h,a,b,c,d,e)
+    ROUND(36,e,f,g,h,a,b,c,d)
+    ROUND(37,d,e,f,g,h,a,b,c)
+    ROUND(38,c,d,e,f,g,h,a,b)
+    ROUND(39,b,c,d,e,f,g,h,a)
+
+    ROUND(40,a,b,c,d,e,f,g,h)
+    ROUND(41,h,a,b,c,d,e,f,g)
+    ROUND(42,g,h,a,b,c,d,e,f)
+    ROUND(43,f,g,h,a,b,c,d,e)
+    ROUND(44,e,f,g,h,a,b,c,d)
+    ROUND(45,d,e,f,g,h,a,b,c)
+    ROUND(46,c,d,e,f,g,h,a,b)
+    ROUND(47,b,c,d,e,f,g,h,a)
+
+    ROUND(48,a,b,c,d,e,f,g,h)
+    ROUND(49,h,a,b,c,d,e,f,g)
+    ROUND(50,g,h,a,b,c,d,e,f)
+    ROUND(51,f,g,h,a,b,c,d,e)
+    ROUND(52,e,f,g,h,a,b,c,d)
+    ROUND(53,d,e,f,g,h,a,b,c)
+    ROUND(54,c,d,e,f,g,h,a,b)
+    ROUND(55,b,c,d,e,f,g,h,a)
+
+    ROUND(56,a,b,c,d,e,f,g,h)
+    ROUND(57,h,a,b,c,d,e,f,g)
+    ROUND(58,g,h,a,b,c,d,e,f)
+    ROUND(59,f,g,h,a,b,c,d,e)
+    ROUND(60,e,f,g,h,a,b,c,d)
+    ROUND(61,d,e,f,g,h,a,b,c)
+    ROUND(62,c,d,e,f,g,h,a,b)
+    ROUND(63,b,c,d,e,f,g,h,a)
+#endif
+
+    H[0] += a;
+    H[1] += b;
+    H[2] += c;
+    H[3] += d;
+    H[4] += e;
+    H[5] += f;
+    H[6] += g;
+    H[7] += h;
+  }
+#undef ROUND
+}
+
+#undef s0
+#undef s1
+#undef S0
+#undef S1
+
+void
+SHA256_Update(SHA256Context *ctx, const unsigned char *input,
+		    unsigned int inputLen)
+{
+    unsigned int inBuf = ctx->sizeLo & 0x3f;
+    if (!inputLen)
+    	return;
+
+    /* Add inputLen into the count of bytes processed, before processing */
+    if ((ctx->sizeLo += inputLen) < inputLen)
+    	ctx->sizeHi++;
+
+    /* if data already in buffer, attemp to fill rest of buffer */
+    if (inBuf) {
+    	unsigned int todo = SHA256_BLOCK_LENGTH - inBuf;
+	if (inputLen < todo)
+	    todo = inputLen;
+	memcpy(B + inBuf, input, todo);
+	input    += todo;
+	inputLen -= todo;
+	if (inBuf + todo == SHA256_BLOCK_LENGTH)
+	    SHA256_Compress(ctx);
+    }
+
+    /* if enough data to fill one or more whole buffers, process them. */
+    while (inputLen >= SHA256_BLOCK_LENGTH) {
+    	memcpy(B, input, SHA256_BLOCK_LENGTH);
+	input    += SHA256_BLOCK_LENGTH;
+	inputLen -= SHA256_BLOCK_LENGTH;
+	SHA256_Compress(ctx);
+    }
+    /* if data left over, fill it into buffer */
+    if (inputLen)
+    	memcpy(B, input, inputLen);
+}
+
+void
+SHA256_End(SHA256Context *ctx, unsigned char *digest,
+           unsigned int *digestLen, unsigned int maxDigestLen)
+{
+    unsigned int inBuf = ctx->sizeLo & 0x3f;
+    unsigned int padLen = (inBuf < 56) ? (56 - inBuf) : (56 + 64 - inBuf);
+    PRUint32 hi, lo;
+#ifdef SWAP4MASK
+    PRUint32 t1;
+#endif
+
+    hi = (ctx->sizeHi << 3) | (ctx->sizeLo >> 29);
+    lo = (ctx->sizeLo << 3);
+
+    SHA256_Update(ctx, pad, padLen);
+
+#if defined(IS_LITTLE_ENDIAN)
+    W[14] = SHA_HTONL(hi);
+    W[15] = SHA_HTONL(lo);
+#else
+    W[14] = hi;
+    W[15] = lo;
+#endif
+    SHA256_Compress(ctx);
+
+    /* now output the answer */
+#if defined(IS_LITTLE_ENDIAN)
+    BYTESWAP4(H[0]);
+    BYTESWAP4(H[1]);
+    BYTESWAP4(H[2]);
+    BYTESWAP4(H[3]);
+    BYTESWAP4(H[4]);
+    BYTESWAP4(H[5]);
+    BYTESWAP4(H[6]);
+    BYTESWAP4(H[7]);
+#endif
+    padLen = PR_MIN(SHA256_LENGTH, maxDigestLen);
+    memcpy(digest, H, padLen);
+    if (digestLen)
+	*digestLen = padLen;
+}
+
+void SHA256_Clone(SHA256Context* dest, SHA256Context* src)
+{
+  memcpy(dest, src, sizeof *dest);
+}
+
+/* Comment out unused code, mostly the SHA384 and SHA512 implementations. */
+#if 0
+SECStatus
+SHA256_HashBuf(unsigned char *dest, const unsigned char *src,
+               unsigned int src_length)
+{
+    SHA256Context ctx;
+    unsigned int outLen;
+
+    SHA256_Begin(&ctx);
+    SHA256_Update(&ctx, src, src_length);
+    SHA256_End(&ctx, dest, &outLen, SHA256_LENGTH);
+
+    return SECSuccess;
+}
+
+
+SECStatus
+SHA256_Hash(unsigned char *dest, const char *src)
+{
+    return SHA256_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
+}
+
+
+void SHA256_TraceState(SHA256Context *ctx) { }
+
+unsigned int
+SHA256_FlattenSize(SHA256Context *ctx)
+{
+    return sizeof *ctx;
+}
+
+SECStatus
+SHA256_Flatten(SHA256Context *ctx,unsigned char *space)
+{
+    PORT_Memcpy(space, ctx, sizeof *ctx);
+    return SECSuccess;
+}
+
+SHA256Context *
+SHA256_Resurrect(unsigned char *space, void *arg)
+{
+    SHA256Context *ctx = SHA256_NewContext();
+    if (ctx)
+	PORT_Memcpy(ctx, space, sizeof *ctx);
+    return ctx;
+}
+
+/* ======= SHA512 and SHA384 common constants and defines ================= */
+
+/* common #defines for SHA512 and SHA384 */
+#if defined(HAVE_LONG_LONG)
+#define ROTR64(x,n) ((x >> n) | (x << (64 - n)))
+#define ROTL64(x,n) ((x << n) | (x >> (64 - n)))
+
+#define S0(x) (ROTR64(x,28) ^ ROTR64(x,34) ^ ROTR64(x,39))
+#define S1(x) (ROTR64(x,14) ^ ROTR64(x,18) ^ ROTR64(x,41))
+#define s0(x) (t1 = x, ROTR64(t1, 1) ^ ROTR64(t1, 8) ^ SHR(t1,7))
+#define s1(x) (t2 = x, ROTR64(t2,19) ^ ROTR64(t2,61) ^ SHR(t2,6))
+
+#if PR_BYTES_PER_LONG == 8
+#define ULLC(hi,lo) 0x ## hi ## lo ## UL
+#elif defined(_MSC_VER)
+#define ULLC(hi,lo) 0x ## hi ## lo ## ui64
+#else
+#define ULLC(hi,lo) 0x ## hi ## lo ## ULL
+#endif
+
+#define SHA_MASK16 ULLC(0000FFFF,0000FFFF)
+#define SHA_MASK8  ULLC(00FF00FF,00FF00FF)
+#define SHA_HTONLL(x) (t1 = x, \
+  t1 = ((t1 & SHA_MASK8 ) <<  8) | ((t1 >>  8) & SHA_MASK8 ), \
+  t1 = ((t1 & SHA_MASK16) << 16) | ((t1 >> 16) & SHA_MASK16), \
+  (t1 >> 32) | (t1 << 32))
+#define BYTESWAP8(x)  x = SHA_HTONLL(x)
+
+#else /* no long long */
+
+#if defined(IS_LITTLE_ENDIAN)
+#define ULLC(hi,lo) { 0x ## lo ## U, 0x ## hi ## U }
+#else
+#define ULLC(hi,lo) { 0x ## hi ## U, 0x ## lo ## U }
+#endif
+
+#define SHA_HTONLL(x) ( BYTESWAP4(x.lo), BYTESWAP4(x.hi), \
+   x.hi ^= x.lo ^= x.hi ^= x.lo, x)
+#define BYTESWAP8(x)  do { PRUint32 tmp; BYTESWAP4(x.lo); BYTESWAP4(x.hi); \
+   tmp = x.lo; x.lo = x.hi; x.hi = tmp; } while (0)
+#endif
+
+/* SHA-384 and SHA-512 constants, K512. */
+static const PRUint64 K512[80] = {
+#if PR_BYTES_PER_LONG == 8
+     0x428a2f98d728ae22UL ,  0x7137449123ef65cdUL ,
+     0xb5c0fbcfec4d3b2fUL ,  0xe9b5dba58189dbbcUL ,
+     0x3956c25bf348b538UL ,  0x59f111f1b605d019UL ,
+     0x923f82a4af194f9bUL ,  0xab1c5ed5da6d8118UL ,
+     0xd807aa98a3030242UL ,  0x12835b0145706fbeUL ,
+     0x243185be4ee4b28cUL ,  0x550c7dc3d5ffb4e2UL ,
+     0x72be5d74f27b896fUL ,  0x80deb1fe3b1696b1UL ,
+     0x9bdc06a725c71235UL ,  0xc19bf174cf692694UL ,
+     0xe49b69c19ef14ad2UL ,  0xefbe4786384f25e3UL ,
+     0x0fc19dc68b8cd5b5UL ,  0x240ca1cc77ac9c65UL ,
+     0x2de92c6f592b0275UL ,  0x4a7484aa6ea6e483UL ,
+     0x5cb0a9dcbd41fbd4UL ,  0x76f988da831153b5UL ,
+     0x983e5152ee66dfabUL ,  0xa831c66d2db43210UL ,
+     0xb00327c898fb213fUL ,  0xbf597fc7beef0ee4UL ,
+     0xc6e00bf33da88fc2UL ,  0xd5a79147930aa725UL ,
+     0x06ca6351e003826fUL ,  0x142929670a0e6e70UL ,
+     0x27b70a8546d22ffcUL ,  0x2e1b21385c26c926UL ,
+     0x4d2c6dfc5ac42aedUL ,  0x53380d139d95b3dfUL ,
+     0x650a73548baf63deUL ,  0x766a0abb3c77b2a8UL ,
+     0x81c2c92e47edaee6UL ,  0x92722c851482353bUL ,
+     0xa2bfe8a14cf10364UL ,  0xa81a664bbc423001UL ,
+     0xc24b8b70d0f89791UL ,  0xc76c51a30654be30UL ,
+     0xd192e819d6ef5218UL ,  0xd69906245565a910UL ,
+     0xf40e35855771202aUL ,  0x106aa07032bbd1b8UL ,
+     0x19a4c116b8d2d0c8UL ,  0x1e376c085141ab53UL ,
+     0x2748774cdf8eeb99UL ,  0x34b0bcb5e19b48a8UL ,
+     0x391c0cb3c5c95a63UL ,  0x4ed8aa4ae3418acbUL ,
+     0x5b9cca4f7763e373UL ,  0x682e6ff3d6b2b8a3UL ,
+     0x748f82ee5defb2fcUL ,  0x78a5636f43172f60UL ,
+     0x84c87814a1f0ab72UL ,  0x8cc702081a6439ecUL ,
+     0x90befffa23631e28UL ,  0xa4506cebde82bde9UL ,
+     0xbef9a3f7b2c67915UL ,  0xc67178f2e372532bUL ,
+     0xca273eceea26619cUL ,  0xd186b8c721c0c207UL ,
+     0xeada7dd6cde0eb1eUL ,  0xf57d4f7fee6ed178UL ,
+     0x06f067aa72176fbaUL ,  0x0a637dc5a2c898a6UL ,
+     0x113f9804bef90daeUL ,  0x1b710b35131c471bUL ,
+     0x28db77f523047d84UL ,  0x32caab7b40c72493UL ,
+     0x3c9ebe0a15c9bebcUL ,  0x431d67c49c100d4cUL ,
+     0x4cc5d4becb3e42b6UL ,  0x597f299cfc657e2aUL ,
+     0x5fcb6fab3ad6faecUL ,  0x6c44198c4a475817UL
+#else
+    ULLC(428a2f98,d728ae22), ULLC(71374491,23ef65cd),
+    ULLC(b5c0fbcf,ec4d3b2f), ULLC(e9b5dba5,8189dbbc),
+    ULLC(3956c25b,f348b538), ULLC(59f111f1,b605d019),
+    ULLC(923f82a4,af194f9b), ULLC(ab1c5ed5,da6d8118),
+    ULLC(d807aa98,a3030242), ULLC(12835b01,45706fbe),
+    ULLC(243185be,4ee4b28c), ULLC(550c7dc3,d5ffb4e2),
+    ULLC(72be5d74,f27b896f), ULLC(80deb1fe,3b1696b1),
+    ULLC(9bdc06a7,25c71235), ULLC(c19bf174,cf692694),
+    ULLC(e49b69c1,9ef14ad2), ULLC(efbe4786,384f25e3),
+    ULLC(0fc19dc6,8b8cd5b5), ULLC(240ca1cc,77ac9c65),
+    ULLC(2de92c6f,592b0275), ULLC(4a7484aa,6ea6e483),
+    ULLC(5cb0a9dc,bd41fbd4), ULLC(76f988da,831153b5),
+    ULLC(983e5152,ee66dfab), ULLC(a831c66d,2db43210),
+    ULLC(b00327c8,98fb213f), ULLC(bf597fc7,beef0ee4),
+    ULLC(c6e00bf3,3da88fc2), ULLC(d5a79147,930aa725),
+    ULLC(06ca6351,e003826f), ULLC(14292967,0a0e6e70),
+    ULLC(27b70a85,46d22ffc), ULLC(2e1b2138,5c26c926),
+    ULLC(4d2c6dfc,5ac42aed), ULLC(53380d13,9d95b3df),
+    ULLC(650a7354,8baf63de), ULLC(766a0abb,3c77b2a8),
+    ULLC(81c2c92e,47edaee6), ULLC(92722c85,1482353b),
+    ULLC(a2bfe8a1,4cf10364), ULLC(a81a664b,bc423001),
+    ULLC(c24b8b70,d0f89791), ULLC(c76c51a3,0654be30),
+    ULLC(d192e819,d6ef5218), ULLC(d6990624,5565a910),
+    ULLC(f40e3585,5771202a), ULLC(106aa070,32bbd1b8),
+    ULLC(19a4c116,b8d2d0c8), ULLC(1e376c08,5141ab53),
+    ULLC(2748774c,df8eeb99), ULLC(34b0bcb5,e19b48a8),
+    ULLC(391c0cb3,c5c95a63), ULLC(4ed8aa4a,e3418acb),
+    ULLC(5b9cca4f,7763e373), ULLC(682e6ff3,d6b2b8a3),
+    ULLC(748f82ee,5defb2fc), ULLC(78a5636f,43172f60),
+    ULLC(84c87814,a1f0ab72), ULLC(8cc70208,1a6439ec),
+    ULLC(90befffa,23631e28), ULLC(a4506ceb,de82bde9),
+    ULLC(bef9a3f7,b2c67915), ULLC(c67178f2,e372532b),
+    ULLC(ca273ece,ea26619c), ULLC(d186b8c7,21c0c207),
+    ULLC(eada7dd6,cde0eb1e), ULLC(f57d4f7f,ee6ed178),
+    ULLC(06f067aa,72176fba), ULLC(0a637dc5,a2c898a6),
+    ULLC(113f9804,bef90dae), ULLC(1b710b35,131c471b),
+    ULLC(28db77f5,23047d84), ULLC(32caab7b,40c72493),
+    ULLC(3c9ebe0a,15c9bebc), ULLC(431d67c4,9c100d4c),
+    ULLC(4cc5d4be,cb3e42b6), ULLC(597f299c,fc657e2a),
+    ULLC(5fcb6fab,3ad6faec), ULLC(6c44198c,4a475817)
+#endif
+};
+
+struct SHA512ContextStr {
+    union {
+	PRUint64 w[80];	    /* message schedule, input buffer, plus 64 words */
+	PRUint32 l[160];
+	PRUint8  b[640];
+    } u;
+    PRUint64 h[8];	    /* 8 state variables */
+    PRUint64 sizeLo;	    /* 64-bit count of hashed bytes. */
+};
+
+/* =========== SHA512 implementation ===================================== */
+
+/* SHA-512 initial hash values */
+static const PRUint64 H512[8] = {
+#if PR_BYTES_PER_LONG == 8
+     0x6a09e667f3bcc908UL ,  0xbb67ae8584caa73bUL ,
+     0x3c6ef372fe94f82bUL ,  0xa54ff53a5f1d36f1UL ,
+     0x510e527fade682d1UL ,  0x9b05688c2b3e6c1fUL ,
+     0x1f83d9abfb41bd6bUL ,  0x5be0cd19137e2179UL
+#else
+    ULLC(6a09e667,f3bcc908), ULLC(bb67ae85,84caa73b),
+    ULLC(3c6ef372,fe94f82b), ULLC(a54ff53a,5f1d36f1),
+    ULLC(510e527f,ade682d1), ULLC(9b05688c,2b3e6c1f),
+    ULLC(1f83d9ab,fb41bd6b), ULLC(5be0cd19,137e2179)
+#endif
+};
+
+
+SHA512Context *
+SHA512_NewContext(void)
+{
+    SHA512Context *ctx = PORT_New(SHA512Context);
+    return ctx;
+}
+
+void
+SHA512_DestroyContext(SHA512Context *ctx, PRBool freeit)
+{
+    if (freeit) {
+        PORT_ZFree(ctx, sizeof *ctx);
+    }
+}
+
+void
+SHA512_Begin(SHA512Context *ctx)
+{
+    memset(ctx, 0, sizeof *ctx);
+    memcpy(H, H512, sizeof H512);
+}
+
+#if defined(SHA512_TRACE)
+#if defined(HAVE_LONG_LONG)
+#define DUMP(n,a,d,e,h) printf(" t = %2d, %s = %016lx, %s = %016lx\n", \
+			       n, #e, d, #a, h);
+#else
+#define DUMP(n,a,d,e,h) printf(" t = %2d, %s = %08x%08x, %s = %08x%08x\n", \
+			       n, #e, d.hi, d.lo, #a, h.hi, h.lo);
+#endif
+#else
+#define DUMP(n,a,d,e,h)
+#endif
+
+#if defined(HAVE_LONG_LONG)
+
+#define ADDTO(x,y) y += x
+
+#define INITW(t) W[t] = (s1(W[t-2]) + W[t-7] + s0(W[t-15]) + W[t-16])
+
+#define ROUND(n,a,b,c,d,e,f,g,h) \
+    h += S1(e) + Ch(e,f,g) + K512[n] + W[n]; \
+    d += h; \
+    h += S0(a) + Maj(a,b,c); \
+    DUMP(n,a,d,e,h)
+
+#else /* use only 32-bit variables, and don't unroll loops */
+
+#undef  NOUNROLL512
+#define NOUNROLL512 1
+
+#define ADDTO(x,y) y.lo += x.lo; y.hi += x.hi + (x.lo > y.lo)
+
+#define ROTR64a(x,n,lo,hi) (x.lo >> n | x.hi << (32-n))
+#define ROTR64A(x,n,lo,hi) (x.lo << (64-n) | x.hi >> (n-32))
+#define  SHR64a(x,n,lo,hi) (x.lo >> n | x.hi << (32-n))
+
+/* Capitol Sigma and lower case sigma functions */
+#define s0lo(x) (ROTR64a(x,1,lo,hi) ^ ROTR64a(x,8,lo,hi) ^ SHR64a(x,7,lo,hi))
+#define s0hi(x) (ROTR64a(x,1,hi,lo) ^ ROTR64a(x,8,hi,lo) ^ (x.hi >> 7))
+
+#define s1lo(x) (ROTR64a(x,19,lo,hi) ^ ROTR64A(x,61,lo,hi) ^ SHR64a(x,6,lo,hi))
+#define s1hi(x) (ROTR64a(x,19,hi,lo) ^ ROTR64A(x,61,hi,lo) ^ (x.hi >> 6))
+
+#define S0lo(x)(ROTR64a(x,28,lo,hi) ^ ROTR64A(x,34,lo,hi) ^ ROTR64A(x,39,lo,hi))
+#define S0hi(x)(ROTR64a(x,28,hi,lo) ^ ROTR64A(x,34,hi,lo) ^ ROTR64A(x,39,hi,lo))
+
+#define S1lo(x)(ROTR64a(x,14,lo,hi) ^ ROTR64a(x,18,lo,hi) ^ ROTR64A(x,41,lo,hi))
+#define S1hi(x)(ROTR64a(x,14,hi,lo) ^ ROTR64a(x,18,hi,lo) ^ ROTR64A(x,41,hi,lo))
+
+/* 32-bit versions of Ch and Maj */
+#define Chxx(x,y,z,lo) ((x.lo & y.lo) ^ (~x.lo & z.lo))
+#define Majx(x,y,z,lo) ((x.lo & y.lo) ^ (x.lo & z.lo) ^ (y.lo & z.lo))
+
+#define INITW(t) \
+    do { \
+	PRUint32 lo, tm; \
+	PRUint32 cy = 0; \
+	lo = s1lo(W[t-2]); \
+	lo += (tm = W[t-7].lo);     if (lo < tm) cy++; \
+	lo += (tm = s0lo(W[t-15])); if (lo < tm) cy++; \
+	lo += (tm = W[t-16].lo);    if (lo < tm) cy++; \
+	W[t].lo = lo; \
+	W[t].hi = cy + s1hi(W[t-2]) + W[t-7].hi + s0hi(W[t-15]) + W[t-16].hi; \
+    } while (0)
+
+#define ROUND(n,a,b,c,d,e,f,g,h) \
+    { \
+	PRUint32 lo, tm, cy; \
+	lo  = S1lo(e); \
+	lo += (tm = Chxx(e,f,g,lo));    cy = (lo < tm); \
+	lo += (tm = K512[n].lo);	if (lo < tm) cy++; \
+	lo += (tm =    W[n].lo);	if (lo < tm) cy++; \
+	h.lo += lo;			if (h.lo < lo) cy++; \
+	h.hi += cy + S1hi(e) + Chxx(e,f,g,hi) + K512[n].hi + W[n].hi; \
+	d.lo += h.lo; \
+	d.hi += h.hi + (d.lo < h.lo); \
+	lo  = S0lo(a);  \
+	lo += (tm = Majx(a,b,c,lo));	cy = (lo < tm); \
+	h.lo += lo;			if (h.lo < lo) cy++; \
+	h.hi += cy + S0hi(a) + Majx(a,b,c,hi); \
+	DUMP(n,a,d,e,h) \
+    }
+#endif
+
+static void
+SHA512_Compress(SHA512Context *ctx)
+{
+#if defined(IS_LITTLE_ENDIAN)
+  {
+#if defined(HAVE_LONG_LONG)
+    PRUint64 t1;
+#else
+    PRUint32 t1;
+#endif
+    BYTESWAP8(W[0]);
+    BYTESWAP8(W[1]);
+    BYTESWAP8(W[2]);
+    BYTESWAP8(W[3]);
+    BYTESWAP8(W[4]);
+    BYTESWAP8(W[5]);
+    BYTESWAP8(W[6]);
+    BYTESWAP8(W[7]);
+    BYTESWAP8(W[8]);
+    BYTESWAP8(W[9]);
+    BYTESWAP8(W[10]);
+    BYTESWAP8(W[11]);
+    BYTESWAP8(W[12]);
+    BYTESWAP8(W[13]);
+    BYTESWAP8(W[14]);
+    BYTESWAP8(W[15]);
+  }
+#endif
+
+  {
+    PRUint64 t1, t2;
+#ifdef NOUNROLL512
+    {
+	/* prepare the "message schedule"   */
+	int t;
+	for (t = 16; t < 80; ++t) {
+	    INITW(t);
+	}
+    }
+#else
+    INITW(16);
+    INITW(17);
+    INITW(18);
+    INITW(19);
+
+    INITW(20);
+    INITW(21);
+    INITW(22);
+    INITW(23);
+    INITW(24);
+    INITW(25);
+    INITW(26);
+    INITW(27);
+    INITW(28);
+    INITW(29);
+
+    INITW(30);
+    INITW(31);
+    INITW(32);
+    INITW(33);
+    INITW(34);
+    INITW(35);
+    INITW(36);
+    INITW(37);
+    INITW(38);
+    INITW(39);
+
+    INITW(40);
+    INITW(41);
+    INITW(42);
+    INITW(43);
+    INITW(44);
+    INITW(45);
+    INITW(46);
+    INITW(47);
+    INITW(48);
+    INITW(49);
+
+    INITW(50);
+    INITW(51);
+    INITW(52);
+    INITW(53);
+    INITW(54);
+    INITW(55);
+    INITW(56);
+    INITW(57);
+    INITW(58);
+    INITW(59);
+
+    INITW(60);
+    INITW(61);
+    INITW(62);
+    INITW(63);
+    INITW(64);
+    INITW(65);
+    INITW(66);
+    INITW(67);
+    INITW(68);
+    INITW(69);
+
+    INITW(70);
+    INITW(71);
+    INITW(72);
+    INITW(73);
+    INITW(74);
+    INITW(75);
+    INITW(76);
+    INITW(77);
+    INITW(78);
+    INITW(79);
+#endif
+  }
+#ifdef SHA512_TRACE
+  {
+    int i;
+    for (i = 0; i < 80; ++i) {
+#ifdef HAVE_LONG_LONG
+	printf("W[%2d] = %016lx\n", i, W[i]);
+#else
+	printf("W[%2d] = %08x%08x\n", i, W[i].hi, W[i].lo);
+#endif
+    }
+  }
+#endif
+  {
+    PRUint64 a, b, c, d, e, f, g, h;
+
+    a = H[0];
+    b = H[1];
+    c = H[2];
+    d = H[3];
+    e = H[4];
+    f = H[5];
+    g = H[6];
+    h = H[7];
+
+#ifdef NOUNROLL512
+    {
+	int t;
+	for (t = 0; t < 80; t+= 8) {
+	    ROUND(t+0,a,b,c,d,e,f,g,h)
+	    ROUND(t+1,h,a,b,c,d,e,f,g)
+	    ROUND(t+2,g,h,a,b,c,d,e,f)
+	    ROUND(t+3,f,g,h,a,b,c,d,e)
+	    ROUND(t+4,e,f,g,h,a,b,c,d)
+	    ROUND(t+5,d,e,f,g,h,a,b,c)
+	    ROUND(t+6,c,d,e,f,g,h,a,b)
+	    ROUND(t+7,b,c,d,e,f,g,h,a)
+	}
+    }
+#else
+    ROUND( 0,a,b,c,d,e,f,g,h)
+    ROUND( 1,h,a,b,c,d,e,f,g)
+    ROUND( 2,g,h,a,b,c,d,e,f)
+    ROUND( 3,f,g,h,a,b,c,d,e)
+    ROUND( 4,e,f,g,h,a,b,c,d)
+    ROUND( 5,d,e,f,g,h,a,b,c)
+    ROUND( 6,c,d,e,f,g,h,a,b)
+    ROUND( 7,b,c,d,e,f,g,h,a)
+
+    ROUND( 8,a,b,c,d,e,f,g,h)
+    ROUND( 9,h,a,b,c,d,e,f,g)
+    ROUND(10,g,h,a,b,c,d,e,f)
+    ROUND(11,f,g,h,a,b,c,d,e)
+    ROUND(12,e,f,g,h,a,b,c,d)
+    ROUND(13,d,e,f,g,h,a,b,c)
+    ROUND(14,c,d,e,f,g,h,a,b)
+    ROUND(15,b,c,d,e,f,g,h,a)
+
+    ROUND(16,a,b,c,d,e,f,g,h)
+    ROUND(17,h,a,b,c,d,e,f,g)
+    ROUND(18,g,h,a,b,c,d,e,f)
+    ROUND(19,f,g,h,a,b,c,d,e)
+    ROUND(20,e,f,g,h,a,b,c,d)
+    ROUND(21,d,e,f,g,h,a,b,c)
+    ROUND(22,c,d,e,f,g,h,a,b)
+    ROUND(23,b,c,d,e,f,g,h,a)
+
+    ROUND(24,a,b,c,d,e,f,g,h)
+    ROUND(25,h,a,b,c,d,e,f,g)
+    ROUND(26,g,h,a,b,c,d,e,f)
+    ROUND(27,f,g,h,a,b,c,d,e)
+    ROUND(28,e,f,g,h,a,b,c,d)
+    ROUND(29,d,e,f,g,h,a,b,c)
+    ROUND(30,c,d,e,f,g,h,a,b)
+    ROUND(31,b,c,d,e,f,g,h,a)
+
+    ROUND(32,a,b,c,d,e,f,g,h)
+    ROUND(33,h,a,b,c,d,e,f,g)
+    ROUND(34,g,h,a,b,c,d,e,f)
+    ROUND(35,f,g,h,a,b,c,d,e)
+    ROUND(36,e,f,g,h,a,b,c,d)
+    ROUND(37,d,e,f,g,h,a,b,c)
+    ROUND(38,c,d,e,f,g,h,a,b)
+    ROUND(39,b,c,d,e,f,g,h,a)
+
+    ROUND(40,a,b,c,d,e,f,g,h)
+    ROUND(41,h,a,b,c,d,e,f,g)
+    ROUND(42,g,h,a,b,c,d,e,f)
+    ROUND(43,f,g,h,a,b,c,d,e)
+    ROUND(44,e,f,g,h,a,b,c,d)
+    ROUND(45,d,e,f,g,h,a,b,c)
+    ROUND(46,c,d,e,f,g,h,a,b)
+    ROUND(47,b,c,d,e,f,g,h,a)
+
+    ROUND(48,a,b,c,d,e,f,g,h)
+    ROUND(49,h,a,b,c,d,e,f,g)
+    ROUND(50,g,h,a,b,c,d,e,f)
+    ROUND(51,f,g,h,a,b,c,d,e)
+    ROUND(52,e,f,g,h,a,b,c,d)
+    ROUND(53,d,e,f,g,h,a,b,c)
+    ROUND(54,c,d,e,f,g,h,a,b)
+    ROUND(55,b,c,d,e,f,g,h,a)
+
+    ROUND(56,a,b,c,d,e,f,g,h)
+    ROUND(57,h,a,b,c,d,e,f,g)
+    ROUND(58,g,h,a,b,c,d,e,f)
+    ROUND(59,f,g,h,a,b,c,d,e)
+    ROUND(60,e,f,g,h,a,b,c,d)
+    ROUND(61,d,e,f,g,h,a,b,c)
+    ROUND(62,c,d,e,f,g,h,a,b)
+    ROUND(63,b,c,d,e,f,g,h,a)
+
+    ROUND(64,a,b,c,d,e,f,g,h)
+    ROUND(65,h,a,b,c,d,e,f,g)
+    ROUND(66,g,h,a,b,c,d,e,f)
+    ROUND(67,f,g,h,a,b,c,d,e)
+    ROUND(68,e,f,g,h,a,b,c,d)
+    ROUND(69,d,e,f,g,h,a,b,c)
+    ROUND(70,c,d,e,f,g,h,a,b)
+    ROUND(71,b,c,d,e,f,g,h,a)
+
+    ROUND(72,a,b,c,d,e,f,g,h)
+    ROUND(73,h,a,b,c,d,e,f,g)
+    ROUND(74,g,h,a,b,c,d,e,f)
+    ROUND(75,f,g,h,a,b,c,d,e)
+    ROUND(76,e,f,g,h,a,b,c,d)
+    ROUND(77,d,e,f,g,h,a,b,c)
+    ROUND(78,c,d,e,f,g,h,a,b)
+    ROUND(79,b,c,d,e,f,g,h,a)
+#endif
+
+    ADDTO(a,H[0]);
+    ADDTO(b,H[1]);
+    ADDTO(c,H[2]);
+    ADDTO(d,H[3]);
+    ADDTO(e,H[4]);
+    ADDTO(f,H[5]);
+    ADDTO(g,H[6]);
+    ADDTO(h,H[7]);
+  }
+}
+
+void
+SHA512_Update(SHA512Context *ctx, const unsigned char *input,
+              unsigned int inputLen)
+{
+    unsigned int inBuf;
+    if (!inputLen)
+    	return;
+
+#if defined(HAVE_LONG_LONG)
+    inBuf = (unsigned int)ctx->sizeLo & 0x7f;
+    /* Add inputLen into the count of bytes processed, before processing */
+    ctx->sizeLo += inputLen;
+#else
+    inBuf = (unsigned int)ctx->sizeLo.lo & 0x7f;
+    ctx->sizeLo.lo += inputLen;
+    if (ctx->sizeLo.lo < inputLen) ctx->sizeLo.hi++;
+#endif
+
+    /* if data already in buffer, attemp to fill rest of buffer */
+    if (inBuf) {
+    	unsigned int todo = SHA512_BLOCK_LENGTH - inBuf;
+	if (inputLen < todo)
+	    todo = inputLen;
+	memcpy(B + inBuf, input, todo);
+	input    += todo;
+	inputLen -= todo;
+	if (inBuf + todo == SHA512_BLOCK_LENGTH)
+	    SHA512_Compress(ctx);
+    }
+
+    /* if enough data to fill one or more whole buffers, process them. */
+    while (inputLen >= SHA512_BLOCK_LENGTH) {
+    	memcpy(B, input, SHA512_BLOCK_LENGTH);
+	input    += SHA512_BLOCK_LENGTH;
+	inputLen -= SHA512_BLOCK_LENGTH;
+	SHA512_Compress(ctx);
+    }
+    /* if data left over, fill it into buffer */
+    if (inputLen)
+    	memcpy(B, input, inputLen);
+}
+
+void
+SHA512_End(SHA512Context *ctx, unsigned char *digest,
+           unsigned int *digestLen, unsigned int maxDigestLen)
+{
+#if defined(HAVE_LONG_LONG)
+    unsigned int inBuf  = (unsigned int)ctx->sizeLo & 0x7f;
+    unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf);
+    PRUint64 lo, t1;
+    lo = (ctx->sizeLo << 3);
+#else
+    unsigned int inBuf  = (unsigned int)ctx->sizeLo.lo & 0x7f;
+    unsigned int padLen = (inBuf < 112) ? (112 - inBuf) : (112 + 128 - inBuf);
+    PRUint64 lo = ctx->sizeLo;
+    PRUint32 t1;
+    lo.lo <<= 3;
+#endif
+
+    SHA512_Update(ctx, pad, padLen);
+
+#if defined(HAVE_LONG_LONG)
+    W[14] = 0;
+#else
+    W[14].lo = 0;
+    W[14].hi = 0;
+#endif
+
+    W[15] = lo;
+#if defined(IS_LITTLE_ENDIAN)
+    BYTESWAP8(W[15]);
+#endif
+    SHA512_Compress(ctx);
+
+    /* now output the answer */
+#if defined(IS_LITTLE_ENDIAN)
+    BYTESWAP8(H[0]);
+    BYTESWAP8(H[1]);
+    BYTESWAP8(H[2]);
+    BYTESWAP8(H[3]);
+    BYTESWAP8(H[4]);
+    BYTESWAP8(H[5]);
+    BYTESWAP8(H[6]);
+    BYTESWAP8(H[7]);
+#endif
+    padLen = PR_MIN(SHA512_LENGTH, maxDigestLen);
+    memcpy(digest, H, padLen);
+    if (digestLen)
+	*digestLen = padLen;
+}
+
+SECStatus
+SHA512_HashBuf(unsigned char *dest, const unsigned char *src,
+               unsigned int src_length)
+{
+    SHA512Context ctx;
+    unsigned int outLen;
+
+    SHA512_Begin(&ctx);
+    SHA512_Update(&ctx, src, src_length);
+    SHA512_End(&ctx, dest, &outLen, SHA512_LENGTH);
+
+    return SECSuccess;
+}
+
+
+SECStatus
+SHA512_Hash(unsigned char *dest, const char *src)
+{
+    return SHA512_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
+}
+
+
+void SHA512_TraceState(SHA512Context *ctx) { }
+
+unsigned int
+SHA512_FlattenSize(SHA512Context *ctx)
+{
+    return sizeof *ctx;
+}
+
+SECStatus
+SHA512_Flatten(SHA512Context *ctx,unsigned char *space)
+{
+    PORT_Memcpy(space, ctx, sizeof *ctx);
+    return SECSuccess;
+}
+
+SHA512Context *
+SHA512_Resurrect(unsigned char *space, void *arg)
+{
+    SHA512Context *ctx = SHA512_NewContext();
+    if (ctx)
+	PORT_Memcpy(ctx, space, sizeof *ctx);
+    return ctx;
+}
+
+void SHA512_Clone(SHA512Context *dest, SHA512Context *src)
+{
+    memcpy(dest, src, sizeof *dest);
+}
+
+/* ======================================================================= */
+/* SHA384 uses a SHA512Context as the real context.
+** The only differences between SHA384 an SHA512 are:
+** a) the intialization values for the context, and
+** b) the number of bytes of data produced as output.
+*/
+
+/* SHA-384 initial hash values */
+static const PRUint64 H384[8] = {
+#if PR_BYTES_PER_LONG == 8
+     0xcbbb9d5dc1059ed8UL ,  0x629a292a367cd507UL ,
+     0x9159015a3070dd17UL ,  0x152fecd8f70e5939UL ,
+     0x67332667ffc00b31UL ,  0x8eb44a8768581511UL ,
+     0xdb0c2e0d64f98fa7UL ,  0x47b5481dbefa4fa4UL
+#else
+    ULLC(cbbb9d5d,c1059ed8), ULLC(629a292a,367cd507),
+    ULLC(9159015a,3070dd17), ULLC(152fecd8,f70e5939),
+    ULLC(67332667,ffc00b31), ULLC(8eb44a87,68581511),
+    ULLC(db0c2e0d,64f98fa7), ULLC(47b5481d,befa4fa4)
+#endif
+};
+
+SHA384Context *
+SHA384_NewContext(void)
+{
+    return SHA512_NewContext();
+}
+
+void
+SHA384_DestroyContext(SHA384Context *ctx, PRBool freeit)
+{
+    SHA512_DestroyContext(ctx, freeit);
+}
+
+void
+SHA384_Begin(SHA384Context *ctx)
+{
+    memset(ctx, 0, sizeof *ctx);
+    memcpy(H, H384, sizeof H384);
+}
+
+void
+SHA384_Update(SHA384Context *ctx, const unsigned char *input,
+		    unsigned int inputLen)
+{
+    SHA512_Update(ctx, input, inputLen);
+}
+
+void
+SHA384_End(SHA384Context *ctx, unsigned char *digest,
+		 unsigned int *digestLen, unsigned int maxDigestLen)
+{
+#define SHA_MIN(a,b) (a < b ? a : b)
+    unsigned int maxLen = SHA_MIN(maxDigestLen, SHA384_LENGTH);
+    SHA512_End(ctx, digest, digestLen, maxLen);
+}
+
+SECStatus
+SHA384_HashBuf(unsigned char *dest, const unsigned char *src,
+			  unsigned int src_length)
+{
+    SHA512Context ctx;
+    unsigned int outLen;
+
+    SHA384_Begin(&ctx);
+    SHA512_Update(&ctx, src, src_length);
+    SHA512_End(&ctx, dest, &outLen, SHA384_LENGTH);
+
+    return SECSuccess;
+}
+
+SECStatus
+SHA384_Hash(unsigned char *dest, const char *src)
+{
+    return SHA384_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
+}
+
+void SHA384_TraceState(SHA384Context *ctx) { }
+
+unsigned int
+SHA384_FlattenSize(SHA384Context *ctx)
+{
+    return sizeof(SHA384Context);
+}
+
+SECStatus
+SHA384_Flatten(SHA384Context *ctx,unsigned char *space)
+{
+    return SHA512_Flatten(ctx, space);
+}
+
+SHA384Context *
+SHA384_Resurrect(unsigned char *space, void *arg)
+{
+    return SHA512_Resurrect(space, arg);
+}
+
+void SHA384_Clone(SHA384Context *dest, SHA384Context *src)
+{
+    memcpy(dest, src, sizeof *dest);
+}
+#endif  /* Comment out unused code. */
+
+/* ======================================================================= */
+#ifdef SELFTEST
+#include <stdio.h>
+
+static const char abc[] = { "abc" };
+static const char abcdbc[] = {
+    "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+};
+static const char abcdef[] = {
+    "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
+    "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+};
+
+void
+dumpHash32(const unsigned char *buf, unsigned int bufLen)
+{
+    unsigned int i;
+    for (i = 0; i < bufLen; i += 4) {
+	printf(" %02x%02x%02x%02x", buf[i], buf[i+1], buf[i+2], buf[i+3]);
+    }
+    printf("\n");
+}
+
+void test256(void)
+{
+    unsigned char outBuf[SHA256_LENGTH];
+
+    printf("SHA256, input = %s\n", abc);
+    SHA256_Hash(outBuf, abc);
+    dumpHash32(outBuf, sizeof outBuf);
+
+    printf("SHA256, input = %s\n", abcdbc);
+    SHA256_Hash(outBuf, abcdbc);
+    dumpHash32(outBuf, sizeof outBuf);
+}
+
+void
+dumpHash64(const unsigned char *buf, unsigned int bufLen)
+{
+    unsigned int i;
+    for (i = 0; i < bufLen; i += 8) {
+    	if (i % 32 == 0)
+	    printf("\n");
+	printf(" %02x%02x%02x%02x%02x%02x%02x%02x",
+	       buf[i  ], buf[i+1], buf[i+2], buf[i+3],
+	       buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
+    }
+    printf("\n");
+}
+
+void test512(void)
+{
+    unsigned char outBuf[SHA512_LENGTH];
+
+    printf("SHA512, input = %s\n", abc);
+    SHA512_Hash(outBuf, abc);
+    dumpHash64(outBuf, sizeof outBuf);
+
+    printf("SHA512, input = %s\n", abcdef);
+    SHA512_Hash(outBuf, abcdef);
+    dumpHash64(outBuf, sizeof outBuf);
+}
+
+void time512(void)
+{
+    unsigned char outBuf[SHA512_LENGTH];
+
+    SHA512_Hash(outBuf, abc);
+    SHA512_Hash(outBuf, abcdef);
+}
+
+void test384(void)
+{
+    unsigned char outBuf[SHA384_LENGTH];
+
+    printf("SHA384, input = %s\n", abc);
+    SHA384_Hash(outBuf, abc);
+    dumpHash64(outBuf, sizeof outBuf);
+
+    printf("SHA384, input = %s\n", abcdef);
+    SHA384_Hash(outBuf, abcdef);
+    dumpHash64(outBuf, sizeof outBuf);
+}
+
+int main (int argc, char *argv[], char *envp[])
+{
+    int i = 1;
+    if (argc > 1) {
+    	i = atoi(argv[1]);
+    }
+    if (i < 2) {
+	test256();
+	test512();
+	test384();
+    } else {
+    	while (i-- > 0) {
+	    time512();
+	}
+	printf("done\n");
+    }
+    return 0;
+}
+
+#endif
diff --git a/dump_without_crashing.cc b/dump_without_crashing.cc
new file mode 100644
index 0000000..8435a91
--- /dev/null
+++ b/dump_without_crashing.cc
@@ -0,0 +1,34 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <dump_without_crashing.h>
+
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <base/check.h>
+#include <base/logging.h>
+#include <base/posix/eintr_wrapper.h>
+
+namespace libchrome_internal {
+
+void DumpWithoutCrashing() {
+    // Create a child process and crash it immediately.
+    pid_t pid = fork();
+    if (pid == 0) {
+        logging::RawCheckFailure(
+            "Crashing the child process for DumpWithoutCrashing().");
+    }
+    if (pid == -1) {
+        PLOG(ERROR) << "fork() failed";
+        return;
+    }
+    // Wait for the child process.
+    auto ret = HANDLE_EINTR(waitpid(pid, nullptr, 0));
+    if (ret == -1) {
+      PLOG(ERROR) << "waitpid() failed for pid = " << pid;
+    }
+}
+
+}  // namespace libchrome_internal
diff --git a/dump_without_crashing.h b/dump_without_crashing.h
new file mode 100644
index 0000000..93a3f76
--- /dev/null
+++ b/dump_without_crashing.h
@@ -0,0 +1,15 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef DUMP_WITHOUT_CRASHING_H_
+#define DUMP_WITHOUT_CRASHING_H_
+
+namespace libchrome_internal {
+
+// Creates a crash dump without crashing the current process.
+void DumpWithoutCrashing();
+
+}  // namespace libchrome_internal
+
+#endif  // DUMP_WITHOUT_CRASHING_H_
diff --git a/libchrome_tools/apply_patches.py b/libchrome_tools/apply_patches.py
new file mode 100755
index 0000000..90aa8bf
--- /dev/null
+++ b/libchrome_tools/apply_patches.py
@@ -0,0 +1,650 @@
+#!/usr/bin/env python3
+# Copyright 2023 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Tool to apply libchrome patches.
+"""
+
+import argparse
+import datetime
+import logging
+import os
+from pathlib import Path
+import re
+import stat
+import subprocess
+from typing import NamedTuple, Optional, Sequence
+
+PREFIXES = [
+    "long-term",
+    "cherry-pick",
+    "backward-compatibility",
+    "forward-compatibility",
+]
+_PATCH_BASENAME_PATTERN = r"(" + "|".join(PREFIXES) + r")-(\d{4})-(.+)\.[^.]+$"
+# A matched result has group (1) prefix, (2) number in the prefix group, (3)
+# descriptive name of patch.
+PATCH_BASENAME_RE = re.compile(_PATCH_BASENAME_PATTERN)
+
+TAG = "HEAD-before-patching"
+
+
+def apply_patch_order_key_fn(patch_name) -> (int, int):
+    """Return key for sorting patches in apply order at build time.
+
+    First number is prefix order, e.g. "long-term" is 0 and "cherry-pick"
+    is 1 and so on.
+    Second is the 4-digit number for the patch within that patch group.
+    """
+    m = PATCH_BASENAME_RE.match(patch_name)
+    assert m, f"Patch name is invalid: should match {_PATCH_BASENAME_PATTERN}."
+    return PREFIXES.index(m.group(1)), m.group(2)
+
+
+class PatchCommit(NamedTuple):
+    """Hash of a patch commit and the corresponding patch file basename."""
+    hash: str
+    patch_name: str
+    is_script: bool
+
+
+class PotentialPatchCommit(NamedTuple):
+    """Commit that is potentially a patch commit."""
+    hash: str
+    patch_name_trailers: Sequence[str]
+    is_script: bool
+
+    def is_patch_commit(self) -> bool:
+        return (len(self.patch_name_trailers) == 1
+                and PATCH_BASENAME_RE.match(self.patch_name_trailers[0]))
+
+    def to_patch_commit(self) -> PatchCommit:
+        assert self.is_patch_commit()
+        return PatchCommit(self.hash, self.patch_name_trailers[0],
+                           self.is_script)
+
+
+class CommandResult(NamedTuple):
+    retcode: int
+    stdout: str
+    stderr: str
+
+
+def _run_or_log_cmd(cmd: Sequence[str],
+                    fatal: bool = True,
+                    dry_run: bool = False) -> CommandResult:
+    logging.debug("$ %s", " ".join(cmd))
+    if dry_run:
+        return CommandResult(0, "", "")
+    completed_process = subprocess.run(cmd,
+                                       check=fatal,
+                                       capture_output=True,
+                                       universal_newlines=True)
+    return CommandResult(completed_process.returncode,
+                         completed_process.stdout.strip(),
+                         completed_process.stderr.strip())
+
+
+def _commit_script_patch(patch: str, dry_run: bool) -> None:
+    _run_or_log_cmd(["git", "add", "."], True, dry_run)
+    _run_or_log_cmd(
+        [
+            "git",
+            "commit",
+            "-m",
+            "Temporary commit for script-based patch",
+            "-m",
+            f"patch-name: {os.path.basename(patch)}\nis-script: true",
+        ],
+        True,
+        dry_run,
+    )
+
+
+def get_all_patches(libchrome_path: str) -> Sequence[str]:
+    """Return list of patches in given libchrome repo in correct apply order."""
+    patches = [
+        p for p in os.listdir(
+            os.path.join(libchrome_path, "libchrome_tools", "patches"))
+        if PATCH_BASENAME_RE.match(p)
+    ]
+    return sorted(patches, key=apply_patch_order_key_fn)
+
+
+def _git_apply_patch(patch: str, use_git_apply: bool, threeway: bool,
+                     fatal: bool, dry_run: bool) -> int:
+    # "-C1" to be compatible with `patch` and to be more robust against upstream
+    # changes.
+    git_apply_cmd = ["git", "apply" if use_git_apply else "am", "-C1", patch]
+    if threeway:
+        git_apply_cmd.append("--3way")
+    return _run_or_log_cmd(git_apply_cmd, fatal, dry_run).retcode
+
+
+def apply_patch(patch_name: str, libchrome_path: str, ebuild: bool,
+                use_git_apply: bool, dry_run: bool) -> None:
+    """Apply given patch.
+
+    Args:
+        patch_name: Basename of patch to apply. Must exist in the patches directory.
+        libchrome_path: Absolute real path to libchrome repository.
+        ebuild: In ebuild mode (not a git repository).
+        use_git_apply: Use git apply (instead of git am).
+        dry_run: In dry run mode (commands are logged not run).
+    """
+    assert not ebuild or use_git_apply, (
+        "--ebuild mode must be run with no_commit = True.")
+    patch_path = os.path.join(libchrome_path, "libchrome_tools", "patches",
+                              patch_name)
+    if patch_path.endswith(".patch"):
+        # git apply/ am is fatal (exit immediately if fail) if in ebuild mode.
+        # Otherwise, if fail (return code is non-zero), rerun to leave a 3-way
+        # merge marker.
+        if _git_apply_patch(patch_path,
+                            use_git_apply,
+                            threeway=False,
+                            fatal=ebuild,
+                            dry_run=dry_run):
+            # Failed `git am` will leave rebase directory even without --3way.
+            if not use_git_apply:
+                _run_or_log_cmd(['git', 'am', '--abort'], True, dry_run)
+            if _git_apply_patch(patch_path,
+                                use_git_apply,
+                                threeway=True,
+                                fatal=False,
+                                dry_run=dry_run):
+                raise RuntimeError(
+                    f"Failed to git {'apply' if use_git_apply else 'am'} patch "
+                    f"{patch_name}; please check 3-way merge markers and "
+                    "resolve conflicts.")
+        # Record patch name in created commit for future formatting patches.
+        if not use_git_apply:
+            patch_name_trailers = _run_or_log_cmd([
+                "git", "log", "-n1",
+                '--format=%(trailers:key=patch-name,valueonly)'
+            ], True, dry_run).stdout.splitlines()
+            if patch_name_trailers and patch_name not in patch_name_trailers:
+                logging.warning(
+                    "Applied patch contains patch-name trailers (%s) different "
+                    "from filename (%s). Overwriting with filename.",
+                    patch_name_trailers, patch_name)
+            _run_or_log_cmd([
+                "git", "-c", "trailer.ifexists=replace", "commit", "--amend",
+                "--no-edit", "--trailer", f"patch-name: {patch_name}"
+            ], True, dry_run)
+    elif os.stat(patch_path).st_mode & stat.S_IXUSR != 0:
+        if _run_or_log_cmd([patch_path], ebuild, dry_run).retcode:
+            raise RuntimeError(
+                f"Patch script {patch_name} failed. Please fix.")
+        # Commit local changes made by script as a temporary commit unless in
+        # no-commit mode.
+        if not use_git_apply:
+            _commit_script_patch(patch_path, dry_run)
+    else:
+        raise RuntimeError(f"Invalid patch file {patch_name}.")
+
+
+def assert_git_repo_state_and_get_current_branch(dry_run: bool = False) -> str:
+    """Assert git repo is in the right state (clean and at a branch)."""
+    # Abort if git repository is dirty.
+    if _run_or_log_cmd(["git", "diff", "--quiet"], False, dry_run).retcode:
+        raise RuntimeError("Git working directory is dirty. Abort script.")
+    current_branch = _run_or_log_cmd(["git", "branch", "--show-current"],
+                                     True, dry_run).stdout
+    if not dry_run and not current_branch:
+        raise RuntimeError("Not on a branch. Abort script.")
+    return current_branch
+
+
+def sanitize_patch_args(arg_name: str, arg_value: Optional[str],
+                         libchrome_path: str) -> Optional[str]:
+    """Assert the patch argument is valid.
+
+    It should be either not provided, basename-only, or a path in the right
+    directory (<libchrome_path>/libchrome_tools/patches/).
+
+    Args:
+        arg_name: name of argument sanitized ("first" or "last").
+        arg_value: value of the patch argument.
+        libchrome_path: absolute real path of the target libchrome directory.
+
+    Returns:
+        Basename of patch, or None if not provided.
+    """
+    if not arg_value:
+        return None
+
+    patch_dir = os.path.join(libchrome_path, 'libchrome_tools', 'patches')
+
+    # If provided as a path, assert parent directory is the target patch_dir.
+    if os.path.dirname(arg_value):
+        # Expand and resolve path as an absolute real path.
+        arg_value = Path(arg_value).expanduser().resolve()
+        if os.path.dirname(arg_value) != patch_dir:
+            raise ValueError(
+                f"--{arg_name} ({arg_value})) is given as a path but its "
+                f"parent directory is not {patch_dir}. You can specify target "
+                "libchrome repository with --libchrome_path.")
+
+    basename = os.path.basename(arg_value)
+    # Assert basename of patch has a valid patch name.
+    if not PATCH_BASENAME_RE.match(basename):
+        raise ValueError(
+            f"--{arg_name} ({arg_value}) is not a valid patch: patch name must "
+            f"start with prefixes in {', '.join(PREFIXES)}.")
+
+    # Only the basename matters after verifying parent directory is patch_dir,
+    # if given as a path.
+    # Assert patch exists in the target patch_dir.
+    if not os.path.exists(os.path.join(patch_dir, basename)):
+        raise ValueError(
+            f"--{arg_name} ({arg_value})) does not exist in {patch_dir}.")
+    return basename
+
+
+def clamp_patches(patches: Sequence[str],
+                  applied_patch_commits: Sequence[PatchCommit],
+                  first: Optional[str], last: Optional[str]) -> Sequence[str]:
+    """Return patches between first (or real first) and last (or real last).
+
+    Args:
+        patches: Basename of all patches in the patch directory, sorted in
+        apply order.
+        applied_patch_commits: Sequence of PatchCommit applied in the repo.
+        first: Basename of first patch to apply. Must exist in patches if given.
+        last: Basename of last patch to apply. Must exist in patches if given.
+
+    Returns:
+        The clamped sequence of patches.
+    """
+    # Find the last patch commit applied from patch in libchrome_tools/patches/.
+    last_applied_index = -1
+    for commit in reversed(applied_patch_commits):
+        try:
+            last_applied_index = patches.index(commit.patch_name)
+            break
+        # User may have committed new patch commits so they do not need to
+        # exist in the directory.
+        except ValueError:
+            pass
+
+    if first:
+        first_index = patches.index(first)
+        # Abort if --first is given but comes before the last applied patch.
+        if first_index <= last_applied_index:
+            raise RuntimeError(
+                f"Invalid input --first {first}: first patch to apply should "
+                "be applied after the last patch commit ("
+                f"{patches[last_applied_index]}) in history.")
+    else: # Default to apply from the first patch that has not been applied yet.
+        first_index = last_applied_index + 1
+        logging.info(
+            "Last patch commit in git history also in libchrome_tools/patches/ "
+            "is %s. The first patch to apply was not given and determined "
+            "automatically to be %s.", patches[last_applied_index],
+            patches[first_index])
+
+    if last:
+        last_index = patches.index(last) + 1
+        # Abort if --last is given but comes before the first patch to be
+        # applied.
+        if last_index <= first_index:
+            raise RuntimeError(
+                f"Invalid input --last {last}: last patch to apply should not "
+                f"be applied before the first one ({patches[first_index]}).")
+    else:
+        last_index = len(patches)
+
+    logging.info("Apply patches %s to %s.", patches[first_index],
+                 patches[last_index - 1])
+    return patches[first_index:last_index]
+
+
+def get_patch_head_commit(dry_run: bool = False) -> Optional[str]:
+    """Return oneline log of commit tagged HEAD-before-patching, if exists."""
+    _, tags, _ = _run_or_log_cmd(["git", "tag"], True, dry_run)
+    tags = tags.splitlines() if tags else []
+    if TAG in tags:
+        return _run_or_log_cmd(["git", "log", TAG, "-1", "--oneline"], True,
+                               dry_run).stdout
+    return None
+
+
+def _potential_patch_commits_since_hash(
+        commit_hash: str,
+        dry_run: bool = False) -> Sequence[PotentialPatchCommit]:
+    "Return the list of PotentialPatchCommit since given commit."
+    # Each line from output is "<hash>:" followed by a ","-separated list of
+    # values of the patch-name trailer, sorted from HEAD to given commit hash.
+    # It may contain empty line.
+    output = _run_or_log_cmd([
+        "git",
+        "log",
+        "--format=%H:%(trailers:key=patch-name,valueonly,separator=%x2C):%(trailers:key=is-script,keyonly)",
+        f"{commit_hash}..",
+    ], True, dry_run).stdout.split('\n')
+    # Reverse output so that it is sorted from commit hash to HEAD.
+    output.reverse()
+    # Parse output by line so each entry is a tuple (hash: str, unparsed string
+    # of ','-separated trailers: str).
+    output = [line.split(':', maxsplit=3) for line in output if line]
+    return [
+        PotentialPatchCommit(
+            line[0],  # hash
+            line[1].split(',') if line[1] else [],  # trailers: list of str
+            line[2] == 'is-script' if line[2] else False,  # script-based patch
+        ) for line in output
+    ]
+
+
+def get_patch_commits_since_tag(current_branch: str,
+                                allow_tag_not_exist: bool = True,
+                                dry_run: bool = False) -> Sequence[PatchCommit]:
+    """Get list of patch commits since commit tagged as HEAD-before-patching.
+
+    This would assert that the tag is on current branch and patch commits are
+    in the right order.
+    If tag does not exist, abort or tag current HEAD depending on value of
+    allow_tag_not_exist flag.
+
+    Args:
+        current_branch: Name of branch currently on.
+        allow_tag_not_exist: If False, abort if tag does not exist; otherwise
+            tag current HEAD (and return an empty list).
+        dry_run: In dry run mode or not.
+
+    Returns:
+        List of patch commits applied since patch-head (sorted from
+        HEAD-before-patching to HEAD).
+    """
+    # Get one-line description of the current HEAD-before-patching commit, if
+    # exists.
+    patch_head = get_patch_head_commit(dry_run)
+    if patch_head:
+        logging.info("Tag %s already exists: %s.", TAG, patch_head)
+        patch_head_branches = _run_or_log_cmd(
+            ["git", "branch", "--contains", TAG, "--format=%(refname:short)"],
+            True,
+            dry_run,
+        ).stdout.splitlines()
+        if not dry_run and current_branch not in patch_head_branches:
+            raise RuntimeError(
+                f"Tag '{TAG}' is on branches "
+                f"({', '.join(patch_head_branches)}) which does not include "
+                f"current branch {current_branch}. "
+                "Please confirm you are on the right branch, or delete "
+                f"the obsolete tag by `git tag -d {TAG}`.")
+
+        # Assume the tag is still valid if all commits from HEAD-before-patching
+        # to HEAD is generated from a patch and skip re-tagging.
+        patch_head_commit_hash = patch_head.split(maxsplit=1)[0]
+        commits = _potential_patch_commits_since_hash(patch_head_commit_hash,
+                                                      dry_run)
+        if all(c.is_patch_commit() for c in commits):
+            logging.info("Confirmed only patch commits from %s to HEAD.", TAG)
+
+            commits = [c.to_patch_commit() for c in commits]
+            applied_patches = [c.patch_name for c in commits]
+            logging.info("%d commits since %s.", len(applied_patches), TAG)
+            applied_patches_sorted = sorted(applied_patches,
+                                            key=apply_patch_order_key_fn)
+            if applied_patches_sorted != applied_patches:
+                raise RuntimeError(
+                    "Applied patches in git log are not in correct application "
+                    "order. This may cause unexpected apply failure when `emerge "
+                    "libchrome` with the generated patches. "
+                    "Please resort them using `git rebase -i`, correct order:\n",
+                    ','.join(applied_patches_sorted))
+
+            return commits
+
+        # Abort if there is non-patch commit and suggest actions.
+        non_patch_commits_summary = "\n".join([
+            f"{commit.hash}: {len(commit.patch_name_trailers)} patch-name "
+            "trailer(s)." for commit in commits
+            if not commit.is_patch_commit()
+        ])
+        raise RuntimeError(
+            f"There is non-patch commit from {TAG} to HEAD:\n"
+            f"{non_patch_commits_summary}\n"
+            "If the tag is obsolete (you would like to return to current HEAD "
+            f"after modifying patches), run `git tag -d {TAG}` to remove the "
+            "tag and rerun the script.\n"
+            "Otherwise, run `git rebase -i` with (r)eword option to add or "
+            "remove patch-name trailer to/ from the commit message so that "
+            "there is exactly one per commit.", )
+
+    if allow_tag_not_exist:
+        # Tag current HEAD; no patch commit since then by definition.
+        _run_or_log_cmd(["git", "tag", TAG], True, dry_run)
+        logging.info("Tagged current HEAD as HEAD-before-patching.")
+        return []
+
+    raise RuntimeError(
+        f"Tag {TAG} does not exist. Please run `git tag <hash> {TAG}` with "
+        "hash being commit to reset to if you have applied patches manually.")
+
+
+def apply_patches(libchrome_path: str,
+                  ebuild: bool,
+                  no_commit: bool,
+                  first: Optional[str] = None,
+                  last: Optional[str] = None,
+                  dry_run: bool = False) -> None:
+    """Apply patches in libchrome_tools/patches/ to the target libchrome.
+
+    Args:
+        libchrome_path: Absolute real path to the target libchrome.
+        ebuild: Flag to apply patches in ebuild mode (not a git repo).
+        no_commit: Flag to not commit changes made by each patch.
+        first: First patch to apply (basename), must be in patch directory.
+        last: Last patch to apply (basename), must be in patch directory.
+        dry_run: Flag for dry run mode (commands are logged without running).
+    """
+    # Change to the target libchrome directory (after resolving paths above).
+    os.chdir(libchrome_path)
+
+    patch_commits = []
+    if not ebuild:
+        # Make sure git repo is in good state.
+        current_branch = assert_git_repo_state_and_get_current_branch(
+            dry_run=dry_run)
+        # Make sure either HEAD-before-patching tag does not exist (and tag
+        # HEAD), or all commits from the tagged commit to HEAD are patch
+        # commits sorted in application order.
+        patch_commits = get_patch_commits_since_tag(current_branch,
+                                                    allow_tag_not_exist=True,
+                                                    dry_run=dry_run)
+
+    # Get the list of all patches in the libchrome_tools/patches/ directory and
+    # clamp to range as specified.
+    patches = clamp_patches(get_all_patches(libchrome_path), patch_commits,
+                            first, last)
+
+    for patch in patches:
+        logging.info("Applying %s...", patch)
+        apply_patch(patch, libchrome_path, ebuild, no_commit, dry_run)
+
+
+def format_patches(libchrome_path: str,
+                   backup_branch: bool = False,
+                   dry_run: bool = False) -> None:
+    """Format all commits from HEAD-before-patching to HEAD as patches.
+
+    Args:
+        libchrome_path: Absolute real path to libchrome repository.
+        backup_branch: Whether or not to back up current state with patch
+            commits as a branch before resetting.
+        dry_run: Flag in dry run mode.
+    """
+    # Change to the target libchrome directory (after resolving paths above).
+    os.chdir(libchrome_path)
+
+    # Make sure git repo is in good state.
+    current_branch = assert_git_repo_state_and_get_current_branch(
+        dry_run=dry_run)
+    # Make sure HEAD-before-patching tag exists, and all commits from the
+    # tagged commit to HEAD are patch commits sorted in application order.
+    commits = get_patch_commits_since_tag(current_branch,
+                                          allow_tag_not_exist=True,
+                                          dry_run=dry_run)
+
+    # If requested, checkout to a new branch now to save a copy of the current
+    # git history before resetting to HEAD-before-patching.
+    if backup_branch:
+        now_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
+        branch_name = f"apply-patch-backup-{now_str}"
+        # Retry with a new branch name at a new time if branch name already in
+        # use (unlikely).
+        try:
+            _run_or_log_cmd(["git", "checkout", "-b", branch_name])
+        except subprocess.CalledProcessError:
+            now_str = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
+            branch_name = f"apply-patch-backup-{now_str}"
+            _run_or_log_cmd(["git", "checkout", "-b", branch_name])
+        logging.info("Backed up git history to branch %s.", branch_name)
+        _run_or_log_cmd(["git", "checkout", current_branch])
+
+    # Format commits as patches, without numbering (-N). Result is ordered in
+    # commit order (HEAD-before-patching to HEAD).
+    formatted_patches = _run_or_log_cmd(["git", "format-patch", TAG, "-N"],
+                                        dry_run=dry_run).stdout.splitlines()
+    commit_count = len(formatted_patches)
+    script_generated_commit_count = len(
+        [c for c in commits if c.is_script])
+    logging.info(
+        "Formatted %d commits since %s as patches: "
+        "%d is/are generated from script (and will be discarded), "
+        "remaining %d will be moved to libchrome_tools/patches/.",
+        commit_count, TAG, script_generated_commit_count,
+        commit_count - script_generated_commit_count)
+
+    # Reset to tagged commit.
+    _run_or_log_cmd(["git", "reset", "--hard", TAG], dry_run=dry_run)
+    logging.info("Reset to %s.", TAG)
+
+    # Move and rename files to <libchrome>/libchrome_tools/patches/ with name
+    # specified by the patch-name trailer; unless it is generated from a script-
+    # based patch, in which case remove it.
+    patch_dir = os.path.join(libchrome_path, "libchrome_tools", "patches")
+    for (formatted_patch_file, commit) in zip(formatted_patches, commits):
+        if commit.is_script:
+            os.remove(formatted_patch_file)
+        else:
+            os.rename(formatted_patch_file,
+                      os.path.join(patch_dir, commit.patch_name))
+    logging.info("Moved and renamed formatted patches, please check %s.",
+                 patch_dir)
+
+    # Delete tag.
+    _run_or_log_cmd(["git", "tag", "-d", TAG], dry_run=dry_run)
+
+
+def main() -> None:
+    parser = argparse.ArgumentParser(description="Apply libchrome patches.")
+    parser.add_argument(
+        "--libchrome-path",
+        default=Path(__file__).resolve().parent.parent,
+        required=False,
+        help=("Path of libchrome to apply patches. "
+              "Defaults to parent of this file's directory."),
+    )
+    parser.add_argument(
+        "--ebuild",
+        default=False,
+        required=False,
+        action="store_true",
+        help=("Run from ebuild where the libchrome directory is not a git "
+              "repository. Defaults to False."),
+    )
+    parser.add_argument(
+        "--no-commit",
+        default=False,
+        required=False,
+        action="store_true",
+        help=("Do not commit changes made by each patch."
+              "Defaults to False except in --ebuild mode (always True)."),
+    )
+    parser.add_argument(
+        "--first",
+        required=False,
+        help=("The basename or path of the first patch to apply (inclusive)."
+              "Defaults to apply from the first patch in directory."))
+    parser.add_argument(
+        "--last",
+        required=False,
+        help=("The basename or path of the last patch to apply (inclusive)."
+              "Defaults to apply til the last patch in directory."))
+    parser.add_argument(
+        "--format-patches",
+        "-f",
+        default=False,
+        required=False,
+        action="store_true",
+        help=(
+            f"Format all commits from commit tagged {TAG} to HEAD as patches "
+            f"and reset to {TAG}."),
+    )
+    parser.add_argument(
+        "--backup-branch",
+        "-b",
+        required=False,
+        action="store_true",
+        help=("Back up the current state with patch commits as a new branch "
+              "before resetting. Only with --format-patches."))
+    parser.add_argument(
+        "--dry-run",
+        default=False,
+        required=False,
+        action="store_true",
+        help=(
+            "dry run mode where patches are not really applied. Log as debug "
+            "statements instead. Defaults to False."),
+    )
+    args = parser.parse_args()
+
+    logging.basicConfig(level=logging.INFO)
+
+    # In format patches mode, do not allow flags for applying patches.
+    if args.format_patches:
+        if args.ebuild or args.no_commit or args.first or args.last:
+            raise ValueError(
+                "In --format-patches mode, do not accept flags for applying "
+                "patches: --ebuild, --no-commit, --first, --last.")
+    else:
+        if args.backup_branch:
+            raise ValueError(
+                "--backup-branch only available in --format-patches mode.")
+
+    # In non-ebuild mode, change to libchrome directory which should be a git
+    # repository for git commands like am and commit at the right repository.
+    if not args.ebuild:
+        if not os.path.exists(os.path.join(args.libchrome_path, ".git")):
+            raise AttributeError(
+                f"Libchrome path {args.libchrome_path} is not a git repository "
+                "but not running in --ebuild mode.")
+    # Never commit changes from patches in ebuild mode.
+    else:
+        logging.info('In --ebuild mode, --no-commit is always set to True.')
+        args.no_commit = True
+
+    # Expand and resolve path as an absolute real path.
+    libchrome_path = Path(args.libchrome_path).expanduser().resolve()
+
+    # Assert first or last exists in <libchrome_path>/libchrome_tools/patches/,
+    # and is a valid patch.
+    # Crop to basename (the only relevant part) after passing the check.
+    first = sanitize_patch_args('first', args.first, libchrome_path)
+    last = sanitize_patch_args('last', args.last, libchrome_path)
+
+    if args.format_patches:
+        format_patches(libchrome_path, args.backup_branch, args.dry_run)
+    else:
+        apply_patches(libchrome_path, args.ebuild, args.no_commit, first, last,
+                      args.dry_run)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/libchrome_tools/check-libchrome.py b/libchrome_tools/check-libchrome.py
new file mode 120000
index 0000000..a6fb320
--- /dev/null
+++ b/libchrome_tools/check-libchrome.py
@@ -0,0 +1 @@
+developer-tools/presubmit/check-libchrome.py
\ No newline at end of file
diff --git a/libchrome_tools/check_libchrome_test.py b/libchrome_tools/check_libchrome_test.py
new file mode 100755
index 0000000..82eb708
--- /dev/null
+++ b/libchrome_tools/check_libchrome_test.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import random
+import subprocess
+import shutil
+import tempfile
+import unittest
+
+import check_libchrome_utils
+
+BAD_FILE = 'testdata/check-libchrome-test.cc'
+
+TEST_BAD_KEYWORDS = {
+    r'DO_NOT_USE_IN_LIBCHROME': 'TEST_PURPOSE',
+}
+
+
+class TestCheckLibchrome(unittest.TestCase):
+
+    def setUp(self):
+        self.repo_dir = tempfile.TemporaryDirectory()
+        self.orig_dir = os.getcwd()
+        os.chdir(self.repo_dir.name)
+        subprocess.check_call(['git', 'init'])
+        subprocess.check_call(['git', 'config', 'user.name', 'Test'])
+        subprocess.check_call(
+            ['git', 'config', 'user.email', 'test@chromium.org'])
+        subprocess.check_call(
+            ['git', 'commit', '-m', 'initial commit', '--allow-empty'])
+        os.makedirs(os.path.join(self.repo_dir.name, os.path.dirname(BAD_FILE)))
+        shutil.copyfile(os.path.join(self.orig_dir, BAD_FILE),
+                        os.path.join(self.repo_dir.name, BAD_FILE))
+        subprocess.check_call(['git', 'add', BAD_FILE])
+        subprocess.check_call(['git', 'commit', '-m', 'bad commit'])
+        self.commit = subprocess.check_output(
+            ['git', 'rev-parse', '--verify', 'HEAD']).strip()
+        os.chdir(self.orig_dir)
+
+    def tearDown(self):
+        os.chdir(self.orig_dir)
+        name = self.repo_dir.name
+        self.repo_dir.cleanup()
+
+    def test_check_commit_fail(self):
+        os.chdir(self.repo_dir.name)
+        self.assertEqual(
+            check_libchrome_utils.checkFiles(
+                [BAD_FILE], self.commit, TEST_BAD_KEYWORDS),
+            [
+                'In File testdata/check-libchrome-test.cc line 1 col 4, found '
+                'DO_NOT_USE_IN_LIBCHROME (pattern: DO_NOT_USE_IN_LIBCHROME), '
+                'TEST_PURPOSE'
+            ])
+
+    def test_check_file_fail(self):
+        os.chdir(self.repo_dir.name)
+        self.assertEqual(
+            check_libchrome_utils.checkFiles(
+                [BAD_FILE], None, TEST_BAD_KEYWORDS),
+            [
+                'In File testdata/check-libchrome-test.cc line 1 col 4, found '
+                'DO_NOT_USE_IN_LIBCHROME (pattern: DO_NOT_USE_IN_LIBCHROME), '
+                'TEST_PURPOSE'
+            ])
+
+    def test_check_commit_pass(self):
+        os.chdir(self.repo_dir.name)
+        self.assertEqual(
+            check_libchrome_utils.checkFiles(
+                [BAD_FILE], self.commit, check_libchrome_utils.BAD_KEYWORDS),
+            [])
+
+    def test_check_file_pass(self):
+        os.chdir(self.repo_dir.name)
+        self.assertEqual(
+            check_libchrome_utils.checkFiles(
+                [BAD_FILE], None, check_libchrome_utils.BAD_KEYWORDS),
+            [])
diff --git a/libchrome_tools/check_libchrome_utils.py b/libchrome_tools/check_libchrome_utils.py
new file mode 120000
index 0000000..f155c96
--- /dev/null
+++ b/libchrome_tools/check_libchrome_utils.py
@@ -0,0 +1 @@
+check-libchrome.py
\ No newline at end of file
diff --git a/libchrome_tools/developer-tools/README b/libchrome_tools/developer-tools/README
new file mode 100644
index 0000000..f8a52bb
--- /dev/null
+++ b/libchrome_tools/developer-tools/README
@@ -0,0 +1,7 @@
+Tools here are for developers in libchrome team to use.
+
+It's used to help libchrome team to do each uprev.
+
+Any changes in this directory shouldn't affect actual Chrome OS image directly.
+
+Infra doesn't need to run hwtests or vmtests on changes in this CL.
diff --git a/libchrome_tools/developer-tools/change_header.py b/libchrome_tools/developer-tools/change_header.py
new file mode 100755
index 0000000..94ae8bc
--- /dev/null
+++ b/libchrome_tools/developer-tools/change_header.py
@@ -0,0 +1,742 @@
+#!/usr/bin/env python3
+# Copyright 2022 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Helper for adding, removing, or replacing an include to/from source file(s).
+
+This is adapted from Chromium's tools/add_header.py with tweaks, such as the
+logic that classifies header according to ChromeOS convention (e.g. libchrome
+headers are often decorated by <> instead of "").
+
+This code does NOT aggressively re-sort includes. It tries to add/ remove header
+with minimal change to the original code.
+
+It inserts includes using some heuristics and might not be always accurate.
+Review before submission.
+
+Usage:
+change_header.py --add "<utility>" foo/bar.cc foo/baz.cc foo/baz.h
+    Add <utility> to the three files
+
+change_header.py --remove "<base/optional.h>" foo/bar.cc foo/baz.cc foo/baz.h
+change_header.py --remove '"base/optional.h"' foo/bar.cc foo/baz.cc foo/baz.h
+change_header.py --remove 'base/optional.h' foo/bar.cc foo/baz.cc foo/baz.h
+    All three remove any include of base/optional.h, if exists with matching or
+    non-matching decorator, from the three files
+
+change_header.py --replace 'base/optional.h' '<optional>' foo/bar.cc foo/baz.cc foo/baz.h
+    Replace base/optional.h (regardless of decorator) by <optional>, from the
+    three files
+change_header.py --replace 'base/bind_post_task.h' 'base/task/bind_post_task.h'
+              --same_decorator foo/bar.cc foo/baz.cc foo/baz.h
+    Replace base/bind_post_task.h (regardless of decorator) by
+    base/task/bind_post_task.h with same decorator as removed header, from the
+    three files
+change_header.py --replace 'base/bind_post_task.h' 'base/task/bind_post_task.h'
+              --same_decorator --sort_only_prefix base/ foo/bar.cc
+    Replace base/bind_post_task.h (regardless of decorator) by
+    base/task/bind_post_task.h with same decorator as removed header, from the
+    file. Only sort the headers immediately next to the replaced header that
+    start with base/. Only applicable when the old and new headers both start
+    with this prefix.
+"""
+
+import argparse
+import os.path
+import re
+import sys
+import logging
+
+# The specific values of these constants are also used as a sort key for
+# ordering different header types in the correct relative order.
+HEADER_TYPE_PRIMARY = 0
+HEADER_TYPE_C_SYSTEM = 1
+HEADER_TYPE_CXX_SYSTEM = 2
+HEADER_TYPE_CROS = 3
+HEADER_TYPE_USER = 4
+BODY = 5
+
+HEADER_TYPE_INVALID = -1
+
+def IsDecorated(name):
+    """Returns whether the name is decorated with "" or <>."""
+    return IsSystemHeader(name) or IsUserHeader(name)
+
+
+def ClassifyHeader(decorated_name):
+    assert IsDecorated(decorated_name), \
+        f'{decorated_name} is not decorated properly'
+    if IsCrOSHeader(decorated_name):
+        return HEADER_TYPE_CROS
+    elif IsCSystemHeader(decorated_name):
+        return HEADER_TYPE_C_SYSTEM
+    elif IsCXXSystemHeader(decorated_name):
+        return HEADER_TYPE_CXX_SYSTEM
+    elif IsUserHeader(decorated_name):
+        return HEADER_TYPE_USER
+    else:
+        return HEADER_TYPE_INVALID
+
+
+def UndecorateName(name):
+    """Remove "" or <> if name is decorated, or return as is."""
+    return name[1:-1] if IsDecorated(name) else name
+
+
+def CopyDecoratorTo(name, decorated_name_src):
+    """(Re)decorate name with same decorator as decorator source."""
+    name = UndecorateName(name) if IsDecorated(name) else name
+    assert IsDecorated(decorated_name_src), \
+        f'Decorator source {from_decorated_name} is not decorated properly'
+    return decorated_name_src[0] + UndecorateName(
+        name) + decorated_name_src[-1]
+
+
+def IsCrOSHeader(decorated_name):
+    """
+    Returns true if decorated_name looks like a CrOS header, e.g. libchrome or
+    libbrillo.
+    Depends only on top directory and decorator does not matter.
+    """
+    return (UndecorateName(decorated_name).split('/')[0] in [
+        'base', 'ipc', 'mojo', 'dbus', 'gtest', 'brillo'
+    ] and UndecorateName(decorated_name).endswith('.h'))
+
+
+def IsSystemHeader(decorated_name):
+    """Returns true if decorated_name looks like a system header."""
+    return decorated_name[0] == '<' and decorated_name[-1] == '>'
+
+
+def IsCSystemHeader(decorated_name):
+    """Returns true if decoraed_name looks like a C system header."""
+    return IsSystemHeader(decorated_name) and UndecorateName(
+        decorated_name).endswith('.h')
+
+
+def IsCXXSystemHeader(decorated_name):
+    """Returns true if decoraed_name looks like a C++ system header."""
+    return (IsSystemHeader(decorated_name)
+            and not UndecorateName(decorated_name).endswith('.h'))
+
+
+def IsUserHeader(decorated_name):
+    """Returns true if decoraed_name looks like a user header."""
+    return decorated_name[0] == '"' and decorated_name[-1] == '"'
+
+
+# Regular expression for matching types of lines
+EMPTY_LINE_RE = re.compile(r'\s*$')
+COMMENT_RE = re.compile(r'\s*(//|/\*)')
+COMMENT_END_RE = re.compile(r'.*\*/$')
+INCLUDE_RE = re.compile(r'\s*#(import|include)\s+([<"].+?[">])(\s*(//.*))?$')
+MACRO_RE = re.compile(r'\s*#(.*)$')
+EXTERN_C_RE = re.compile(r'\s*extern "C"(.*){$')
+EXTERN_C_END_RE = re.compile(r'\s*}(\s*//.*)?$')
+
+
+def _DecomposePath(filename):
+    """Decomposes a filename into a list of directories and the basename.
+
+    Args:
+      filename: A filename!
+
+    Returns:
+      A tuple of a list of directories and a string basename.
+    """
+    dirs = []
+    dirname, basename = os.path.split(filename)
+    while dirname:
+        dirname, last = os.path.split(dirname)
+        dirs.append(last)
+    dirs.reverse()
+    # Remove the extension from the basename.
+    basename = os.path.splitext(basename)[0]
+    return dirs, basename
+
+
+_PLATFORM_SUFFIX = (
+        r'(?:_(?:android|aura|chromeos|ios|linux|mac|ozone|posix|win|x11))?')
+_TEST_SUFFIX = r'(?:_(?:browser|interactive_ui|ui|unit)?test)?'
+
+
+def IsPrimaryInclude(decorated_name, filename):
+    """Return if this decorated include is a primary include.
+
+    Per the style guide, if moo.cc's main purpose is to implement or test the
+    functionality in moo.h, moo.h should be ordered first in the includes.
+
+    Args:
+      decorated_name: A decorated name of an include.
+      filename: The filename to use as the basis for finding the primary header.
+    """
+    # Header files never have a primary include.
+    if filename.endswith('.h'):
+        return False
+
+    basis = _DecomposePath(filename)
+
+    # The list of includes is searched in reverse order of length. Even though
+    # matching is fuzzy, moo_posix.h should take precedence over moo.h when
+    # considering moo_posix.cc.
+    header_type = ClassifyHeader(decorated_name)
+    if header_type != HEADER_TYPE_USER:
+        return False
+    to_test = _DecomposePath(UndecorateName(decorated_name))
+
+    # If the basename to test is longer than the basis, just skip it and
+    # continue. moo.c should never match against moo_posix.h.
+    if len(to_test[1]) > len(basis[1]):
+        return False
+
+    # The basename in the two paths being compared need to fuzzily match.
+    # This allows for situations where moo_posix.cc implements the interfaces
+    # defined in moo.h.
+    escaped_basename = re.escape(to_test[1])
+    if not (re.match(escaped_basename + _PLATFORM_SUFFIX + _TEST_SUFFIX + '$',
+                     basis[1]) or
+            re.match(escaped_basename + _TEST_SUFFIX + _PLATFORM_SUFFIX + '$',
+                     basis[1])):
+        return False
+
+    return True
+
+
+def GuessBlockToInsert(include_blocks, header_type):
+    """Guess position to insert a header of given type.
+
+    Args:
+      include_blocks: Blocks of includes in the original file
+      header_type: type of header to be inserted
+
+    Returns:
+      A tuple of (begin, end) indices which are:
+        * if there is a block of same type in the original file, the same as the
+          (begin, end) of that block,
+        * otherwise both the index of the empty line where the new header should
+          be inserted
+    """
+    logging.debug(f'Guessing where to include {header_type} header...')
+    logging.debug(f'Blocks are {include_blocks}')
+    # Experiment shows more likely to be found from bottom.
+    for begin, end, block_type in reversed(include_blocks):
+        # Insert to this block if its type is "close enough" to target header type.
+        if header_type - 0.5 <= block_type and block_type <= header_type + 0.5:
+            logging.debug(
+                f'\tInsert into block ({block_type}, {begin+1}, {end+1})')
+            return (begin, end)
+
+        # Target header belongs to a type between the type of this block and the
+        # block below, but not "close enough" to any of them, create a new block
+        # between them.
+        if block_type < header_type - 0.5:
+            logging.debug(
+                f'\tInsert after block ({block_type}, {begin+1}, {end+1})')
+            return (end + 1, end + 1)
+
+    # No appropriate block found from list. Insert to right before the first block
+    # (there is always a body block).
+    logging.debug(f'\tInsert before block ({include_blocks[0][2]}, ' \
+                  f'{include_blocks[0][0]+1}, {include_blocks[0][1]+1})')
+    return (begin, begin)
+
+
+def IsCommentThisAndNext(line, in_comment_block):
+    """Determine if this and next lines are comment, respectively.
+
+    Args:
+      line: This line.
+      in_comment_block: Whether or not this is in a comment block, from previous
+      lines.
+
+    Returns:
+      is_comment: whether this line is a comment, could be a single-line
+      comment, start/ middle/ end of a comment block.
+      in_comment_block_next: whether the next line is in a comment block
+    """
+    comment_line = COMMENT_RE.match(line)
+    comment_start = comment_line.group(1) == '/*' if comment_line else False
+    comment_end = COMMENT_END_RE.match(line)
+
+    is_comment = comment_line or in_comment_block
+    in_comment_block_next = ((comment_start or in_comment_block)
+                             and not comment_end)
+
+    return is_comment, in_comment_block_next
+
+
+def InsertAt(filename, source, decorated_name, target_header_type):
+    """Find indices of block to insert new header with heuristics.
+    If there is already a block containing header of same type, insert into it.
+    Otherwise, assign a type value to block (average of all its headers), and
+    insert to one close enough or create a new block.
+
+    Args:
+      filename: The name of the source file, for determining primary include.
+      source: The contents of the source file in list of lines.
+      decorated_name: The decorated name of the header to add.
+      target_header_type: The type of header to be added.
+
+    Returns:
+      None if source already contains target header (no change is needed),
+      otherwise the (begin, end) indices of range to insert header where begin is
+      inclusive and end is exclusive.
+      begin == end if new block should be created.
+    """
+    undecorated_name = UndecorateName(decorated_name)
+
+    blocks = []
+    begin = -1
+    candidate_block = False
+    type_total = 0
+    in_comment_block = False
+    in_extern_c_block = False
+
+    for idx, line in enumerate(source):
+        logging.debug(f'({idx+1}): {line}')
+
+        is_comment, in_comment_block = IsCommentThisAndNext(
+            line, in_comment_block)
+        if is_comment or in_comment_block:
+            continue
+
+        # Aassume a new include should not be inserted inside an extern C block,
+        # so ignore everyting inside that block.
+        if EXTERN_C_RE.match(line):
+            logging.debug(f'({idx+1}): {line} extern c begin - skip this line')
+            in_extern_c_block = True
+            continue
+        if in_extern_c_block and EXTERN_C_END_RE.match(line):
+            logging.debug(f'({idx+1}): {line} extern c end - skip this line')
+            in_extern_c_block = False
+            continue
+        if in_extern_c_block:
+            logging.debug(f'({idx+1}): {line} extern c block - skip this line')
+            continue
+
+        m = INCLUDE_RE.match(line)
+        if m:
+            # Update begin index of the include block.
+            if begin < 0:
+                begin = idx
+
+            header_name = m.group(2)
+            # Original source already contains target header (ignore decorator), no
+            # change is needed.
+            if UndecorateName(header_name) == undecorated_name:
+                return None, None
+            header_type = ClassifyHeader(header_name)
+
+            if header_type == HEADER_TYPE_INVALID:
+                logging.warning(f'{filename} ({idx+1}): include {m.group(2)} found ' \
+                                f'but cannot be classified.')
+                continue
+
+            # Override result of ClassifyHeader if it is primary include.
+            if len(blocks) == 0 and IsPrimaryInclude(header_name, filename):
+                logging.debug(f'Found primary header.')
+                header_type = HEADER_TYPE_PRIMARY
+
+            # A block containing header of same type found, mark it as candidate.
+            if header_type == target_header_type:
+                candidate_block = True
+
+            # For guessing type of this block of includes.
+            type_total += header_type
+            continue
+
+        # Not an include line.
+
+        # Finished parsing one block
+        if begin >= 0:
+            # Return this block directly if it is a candidate block.
+            if candidate_block:
+                logging.debug(
+                    f'Found candidate block from line {begin+1} to {idx}')
+                return (begin, idx)
+
+            # Add block to list, reset state, and continue reading.
+            type_avg = type_total / (idx - begin)
+            blocks.append((begin, idx, type_avg))
+            begin = -1
+            type_total = 0
+            continue
+
+        # Hit real code, add body block (for inserting a new block of include when
+        # there is no include at all).
+        if (not EMPTY_LINE_RE.match(line) and not MACRO_RE.match(line)):
+            logging.debug(f'Hit real code, finished parsing includes.')
+            blocks.append((idx, -1, BODY))
+            break
+
+    # Candidate block not found, guess where to insert from the list of blocks.
+    logging.debug(f'No candidate block found, guess from list.')
+    return GuessBlockToInsert(blocks, target_header_type)
+
+
+def AddHeaderToSource(filename,
+                      source,
+                      decorated_name,
+                      header_type,
+                      comment=''):
+    """Adds the specified header into the source text with minimal changes.
+
+    Args:
+      filename: The name of the source file.
+      source: The contents of the source file in list of lines.
+      decorated_name: The decorated name of the header to add.
+      header_type: The type of header to be added.
+      comment: In-line comment following the include header.
+
+    Returns:
+      None if no changes are needed or the modified source text otherwise.
+    """
+    logging.debug(f'Trying to add {decorated_name} to file.')
+    # Begin (inclusive) and end (exclusive) indices of the block to insert the new
+    # header to; or both None if no change (header already included).
+    begin, end = InsertAt(filename, source, decorated_name, header_type)
+    logging.debug(f'begin, end = {begin}, {end}')
+
+    if not begin:
+        return None
+
+    # Add include to end of block, i.e. at index end.
+    source.insert(end, '#include %s%s' % (decorated_name, comment))
+
+    # There is no block in original file of the same type, insert extra empty line
+    # after this include statement. No need to sort since it has one line only.
+    if begin == end:
+        source.insert(end + 1, '')
+    # Sort the block. Length increased by one after inserting new include.
+    else:
+        source[begin:end + 1] = sorted(source[begin:end + 1])
+
+    return source
+
+
+def RemoveHeaderFromSource(source, name):
+    """Removes the specified header from the source text.
+
+    Args:
+      source: The contents of the source file in list of lines.
+      name: The decorated or undecorated name of the header to remove.
+
+    Returns:
+      The modified source text in list of lines, removed header (for
+      --same-decorator option with replace operation), in-line comments
+      or (None, None) if nothing to remove.
+    """
+    logging.debug(f'Trying to remove {name} from file.')
+    undecorated_name = UndecorateName(name)
+
+    file_length = len(source)
+    in_comment_block = False
+    in_extern_c_block = False
+
+    for idx, line in enumerate(source):
+        logging.debug(f'({idx}): {line}')
+
+        is_comment, in_comment_block = IsCommentThisAndNext(
+            line, in_comment_block)
+        if is_comment or in_comment_block:
+            continue
+
+        # Sometimes extern C blocks are in the include section.  Ignore the
+        # lines for extern C but still check the includes inside extern C for in
+        # case that is the file to be removed.
+        if EXTERN_C_RE.match(line):
+            logging.debug(f'({idx}): {line} extern c begin - skip this line')
+            in_extern_c_block = True
+            continue
+        if in_extern_c_block and EXTERN_C_END_RE.match(line):
+            logging.debug(f'({idx}): {line} extern c end - skip this line')
+            in_extern_c_block = False
+            continue
+
+        m = INCLUDE_RE.match(line)
+        if m:
+            # This include's filepath matches target header filepath, and
+            # decorator also matches if input is decorated.
+            if UndecorateName(m.group(2)) == undecorated_name:
+                # Delete empty line after if it belongs to a single-line block.
+                if ((idx > 0 and source[idx - 1] == '')
+                        and (idx + 1 < file_length and source[idx + 1] == '')):
+                    del source[idx + 1]
+                del source[idx]
+                logging.debug(
+                    f'Header {m.group(2)} found, removing from file.')
+                return source, m.group(2), m.group(3)
+
+        # Hitting body of code, stop looking.
+        if (not EMPTY_LINE_RE.match(line) and not MACRO_RE.match(line)):
+            break
+
+    return None, None, None
+
+
+def ReplaceHeaderWithMinimumSorting(source, old_header, new_header, prefix,
+                                    same_decorator):
+    """Replaces the old header by the new one from the source text.
+       If old header doesn't exist, do nothing.
+       If new header (regardless of decorators) already exists, only delete the
+       old one without sorting.
+
+    Args:
+      source: The contents of the source file in list of lines.
+      old_header: The decorated or undecorated name of the header to remove; in
+      both cases match only by the path (decorator will be removed).
+      new_header: The decorated or undecorated name of the header to remove; if
+      same_decorator is False it must be decorated.
+      prefix: indicates sorting range (only the includes surrounding the replaced
+      header AND starting with sort_only_prefix will be sorted).
+      same_decorator: Whether or not to use the decorator of replaced header for
+      the replacement.
+
+    Returns:
+      The modified source text in list of lines, or None if old header not found.
+    """
+    old_header_idx = -1
+    new_header_idx = -1
+    in_comment_block = False
+    in_extern_c_block = False
+
+    # Look for old header (to replace) and check new header does not already
+    # exist.
+    for idx, line in enumerate(source):
+        logging.debug(f'({idx}): {line}')
+        # Skip empty line.
+        if not line:
+            continue
+        # Skip comment.
+        is_comment, in_comment_block = IsCommentThisAndNext(
+            line, in_comment_block)
+        if is_comment or in_comment_block:
+            continue
+
+        # Sometimes extern C blocks are in the include section.  Ignore the
+        # lines for extern C but still check the includes inside extern C.
+        if EXTERN_C_RE.match(line):
+            logging.debug(f'({idx}): {line} extern c begin - skip this line')
+            in_extern_c_block = True
+            continue
+        if in_extern_c_block and EXTERN_C_END_RE.match(line):
+            logging.debug(f'({idx}): {line} extern c end - skip this line')
+            in_extern_c_block = False
+            continue
+
+        m = INCLUDE_RE.match(line)
+        if m:
+            if m.group(2)[1:-1] == UndecorateName(old_header):
+                logging.debug(f'Found old header.')
+                if new_header_idx > -1:  # Delete the line if new header exists.
+                    del source[idx]
+                    return source
+                old_header_idx = idx
+            elif m.group(2)[1:-1] == UndecorateName(new_header):
+                logging.debug(f'Found new header.')
+                if old_header_idx > -1:  # Delete the old header line if exists.
+                    del source[old_header_idx]
+                    return source
+                new_header_idx = idx
+
+        # Hitting body of code, stop looking.
+        if not MACRO_RE.match(line):
+            break
+
+    if old_header_idx < 0:  # If old header is not found, do nothing.
+        return None
+
+    # Only the old header exists but not the new header.
+    # Replace the include header path.
+    OLD_HEADER_RE = re.compile('([<"])' + UndecorateName(old_header) +
+                               '([>"])')
+    if same_decorator:
+        # (Re)decorate new header by those of the old header (retrieved from
+        # pattern).
+        source[old_header_idx] = OLD_HEADER_RE.sub(
+            r'\1{}\2'.format(UndecorateName(new_header)),
+            source[old_header_idx])
+    else:
+        # New header is guaranteed to be decorated.
+        source[old_header_idx] = OLD_HEADER_RE.sub(r'{}'.format(new_header),
+                                                   source[old_header_idx])
+    logging.debug(
+        f'Replaced old header include line with new path: {source[old_header_idx]}'
+    )
+
+    # Look at includes before and after the modified include for those with
+    # matching prefix.
+    for i_delta, line in enumerate(reversed(source[:old_header_idx])):
+        m = INCLUDE_RE.match(line)
+        if not m or not UndecorateName(m.group(2)).startswith(prefix):
+            start = old_header_idx - i_delta
+            break
+    for i_delta, line in enumerate(source[old_header_idx:]):
+        m = INCLUDE_RE.match(line)
+        if not m or not UndecorateName(m.group(2)).startswith(prefix):
+            end = old_header_idx + i_delta
+            break
+    logging.debug(
+        f'Resorting lines [{start}, {end}) surrounding replaced header line at {old_header_idx}.'
+    )
+    # Overwrite the range with itself sorted.
+    source[start:end] = sorted(source[start:end])
+    return source
+
+
+def ReplaceHeader(source, old_header, new_header, same_decorator, filename):
+    """Replaces the old header by the new one from the source text.
+       If old header doesn't exist, do nothing.
+       Resort blocks touched.
+
+    Args:
+      source: The contents of the source file in list of lines.
+      old_header: The decorated or undecorated name of the header to remove; in
+      both cases match only by the path (decorator will be removed).
+      new_header: The decorated or undecorated name of the header to remove; if
+      same_decorator is False it must be decorated.
+      same_decorator: Whether or not to use the decorator of replaced header for
+      the replacement.
+      filename: Filename of the file being modified.
+
+    Returns:
+      The modified source text in list of lines, or None if old header not found.
+    """
+    source, removed_header, comment = RemoveHeaderFromSource(
+        source, old_header)
+    if not source:
+        return None
+    new_header = (CopyDecoratorTo(new_header, removed_header)
+                  if same_decorator else new_header)
+    new_source = AddHeaderToSource(os.path.normpath(filename), source,
+                                   new_header, ClassifyHeader(new_header),
+                                   comment if comment else '')
+    # new_source is None if new header already exists, but source has been
+    # modified by removing the old header.
+    return new_source if new_source else source
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description='Mass change include header of files.')
+
+    # Add, remove, or replace a header by a new one; perform exactly one of the
+    # operators.
+    group = parser.add_mutually_exclusive_group()
+    group.add_argument(
+        '--add',
+        help='The decorated filename of the header to insert (e.g. "a" or <a>).'
+    )
+    group.add_argument(
+        '--remove',
+        help='The decorated or undecorated filename of the header to delete '   \
+            '(e.g. "a" or <a>). If decorated, an include will be removed only ' \
+            'if decorator also matches, otherwise, an include with same '       \
+            'filename will be removed regardless of decorator. '                \
+            'No change to file if no match is found.')
+    group.add_argument(
+        '--replace',
+        nargs=2,
+        metavar=('OLD', 'NEW'),
+        help='Equivalent to --remove OLD and --add NEW if OLD is found.')
+
+    parser.add_argument(
+        '--same_decorator',
+        help='Use same decorator found in removed header OLD when adding new; ' \
+            'for replace operation only.',
+        action='store_true')
+    parser.add_argument(
+        '--sort_only_prefix',
+        help='Prefix of blocks of include headers to be reordered after '       \
+            'replacing header in-place, it should match both the replaced and ' \
+            'replacement headers; for replace operation only.'                  \
+    )
+
+    parser.add_argument(
+        '--verbosity', type=str,
+        help='Verbosity level of logs; one of DEBUG, INFO, WARNING, ERROR. ' \
+            'Default is INFO.',
+        default='INFO')
+
+    parser.add_argument(
+        '--dryrun',
+        help='Run the script but do not change the actual file. For debugging.',
+        default=False,
+        action='store_true')
+
+    parser.add_argument('files', nargs='+')
+    args = parser.parse_args()
+
+    assert args.add or args.remove or args.replace, \
+           f'Exactly one action out of add, remove, or replace is required.'
+
+    assert args.replace or not args.same_decorator, \
+           f'--same_decorator option is only applicable to replace operation.'
+    assert args.replace or not args.sort_only_prefix, \
+           f'--sort_only_prefix option is only applicable to replace operation.'
+
+    if args.replace:
+        assert args.same_decorator or IsDecorated(args.replace[1]), \
+               f'Provide decorated new header or use --same-decorator option.'
+
+    if args.sort_only_prefix:
+        SORT_ONLY_PREFIX_RE = re.compile(r'[<"]?{}'.format(
+            args.sort_only_prefix))
+        assert (SORT_ONLY_PREFIX_RE.match(args.replace[0]) and
+                SORT_ONLY_PREFIX_RE.match(args.replace[1])), \
+               f'--sort_only_prefix should be prefix to both replaced and replacement headers.'
+
+    assert args.verbosity in ['DEBUG', 'INFO', 'WARNING', 'ERROR'], \
+        f'Verbosity level should be one of DEBUG, INFO, WARNING, ERROR.'
+    logging.getLogger().setLevel(args.verbosity)
+
+    if args.add:
+        logging.info(f'Adding {args.add} to files.')
+    elif args.remove:
+        logging.info(f'Removing {args.remove} from files.')
+    else:  # args.replace
+        decorator_log = ' with same decorator.' if args.same_decorator else "."
+        logging.info(f'Replacing {args.replace[0]} with {args.replace[1]} from ' \
+                     f'files{decorator_log}' + '\n')
+
+    for filename in args.files:
+        if not filename.endswith('cc') and not filename.endswith(
+                'h') and not filename.endswith('cpp'):
+            logging.info(f'Skip non-c++ file {filename}...')
+            continue
+        with open(filename, 'r') as f:
+            logging.info(f'Processing {filename}...')
+            source = f.read().splitlines()
+            if args.remove:
+                source, _, _ = RemoveHeaderFromSource(source, args.remove)
+                if not source:
+                    logging.info(
+                        f'To be removed header {args.remove} not found, skipping file.'
+                    )
+            elif args.replace:
+                if args.sort_only_prefix:
+                    source = ReplaceHeaderWithMinimumSorting(
+                        source, args.replace[0], args.replace[1],
+                        args.sort_only_prefix, args.same_decorator)
+                else:
+                    source = ReplaceHeader(source, args.replace[0],
+                                           args.replace[1],
+                                           args.same_decorator, filename)
+                if not source:
+                    logging.info(
+                        f'To be replaced header {args.replace[0]} not found, skipping file.'
+                    )
+            else:  # args.add
+                source = AddHeaderToSource(os.path.normpath(filename), source,
+                                           args.add, ClassifyHeader(args.add))
+
+        if not source or args.dryrun:
+            continue
+        with open(filename, 'w', newline='\n') as f:
+            source.append(
+                '')  # To avoid eating the newline at the end of the file.
+            f.write('\n'.join(source))
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/libchrome_tools/developer-tools/elftools/crosimage.py b/libchrome_tools/developer-tools/elftools/crosimage.py
new file mode 100644
index 0000000..7079c08
--- /dev/null
+++ b/libchrome_tools/developer-tools/elftools/crosimage.py
@@ -0,0 +1,157 @@
+#!/usr/bin/env python
+# Copyright 2022 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import glob
+import os
+import shutil
+import subprocess
+
+TEST_IMAGE_FILE_NAME = 'chromiumos_test_image'
+
+
+def _get_latest_release(board):
+    """
+    Returns the latest release build version.
+
+    Args:
+      board: board name in str.
+    """
+    return subprocess.check_output([
+        'gsutil', 'cat',
+        'gs://chromeos-image-archive/%s-release/LATEST-main' % (board)
+    ]).decode('ascii').strip()
+
+
+def download_test_image(board, version, output):
+    """
+    Downloads the test image to given path.
+
+    Args:
+      board: board name in str.
+      version: build version in str.
+      output: location to store the downloaded file.
+    """
+    subprocess.check_call([
+        'gsutil', 'cp',
+        'gs://chromeos-image-archive/%s-release/%s/%s.tar.xz' %
+        (board, version, TEST_IMAGE_FILE_NAME), output
+    ])
+
+
+class MountedReleaseImage:
+    """Stateful class to maintain image downloads and mounts."""
+
+    def __init__(self, board, basedir):
+        """
+        Initializes MountedReleaseImage
+
+        Args:
+          board: board name in str.
+          basedir: a temporary dir for the class to work on.
+        """
+        self.board = board
+        self.basedir = basedir
+        self.version = _get_latest_release(board)
+        self.imagetarball = os.path.join(self.basedir,
+                                         '%s-image.tar.xz' % (self.board))
+        self.imagedir = os.path.join(self.basedir, '%s-image' % (self.board))
+        self.rootfs = os.path.join(self.imagedir, 'rootfs')
+        self.stateful = os.path.join(self.imagedir, 'stateful')
+
+    def _download_latest_release_image(self):
+        """Downloads and extracts the latest release build test image."""
+        os.makedirs(self.imagedir, exist_ok=True)
+        download_test_image(self.board, self.version, self.imagetarball)
+        subprocess.check_call(
+            ['tar', 'xf', self.imagetarball, '-C', self.imagedir])
+
+    def _mount_latest_release_image(self, umount=False):
+        """
+        Mounts the latest test image.
+
+        Args:
+          umount: umount instead of mount.
+        """
+        commands = [
+            os.path.join(os.environ.get('HOME'),
+                         'trunk/src/scripts/mount_gpt_image.sh'), '-i',
+            '%s.bin' % (TEST_IMAGE_FILE_NAME), '-f', self.imagedir,
+            '--rootfs_mountpt', self.rootfs, '--stateful_mountpt', self.stateful
+        ]
+        if umount:
+            commands.append('-u')
+        subprocess.check_call(commands),
+
+    def _umount_image(self, fromerror=False):
+        """Unmounts the test image."""
+        try:
+            self._mount_latest_release_image(umount=True)
+        except subprocess.CalledProcessError as e:
+            if not fromerror:
+                raise e
+
+    def _prepare_rootfs_dir(self):
+        """Prepares mounted rootfs for latest test image."""
+        # self.basedir must not exist to prevent accidental deletion at cleanup.
+        os.makedirs(self.basedir)
+        self._download_latest_release_image()
+        self._mount_latest_release_image()
+
+    def _cleanup(self, fromerror=False):
+        """Cleans up basedir."""
+        self._umount_image(fromerror)
+        shutil.rmtree(self.basedir)
+
+    def __enter__(self):
+        """Prepares rootfs dir for latest image and enters with block."""
+        try:
+            self._prepare_rootfs_dir()
+        except Exception as e:
+            self._cleanup(fromerror=True)
+            raise e
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        """Cleans up basedir and exits with block."""
+        self._cleanup()
+
+    def path(self, path):
+        """
+        Returns path prepended by rootfs path.
+
+        Args:
+          path: relative path to image rootfs.
+        """
+        return os.path.join(self.rootfs, path)
+
+
+class FakeMountedReleaseImage:
+    """
+    A fake provider for MountedReleaseImage.
+
+    To use the fake, test image but be mounted to /tmp/m by mount_gpt_image.sh
+    manually.
+    """
+
+    def __init__(self, board, basedir):
+        """Initializes FakeMountedReleaseImage. All args are dropped"""
+        self.rootfs = '/tmp/m'
+
+    def __enter__(self):
+        """Enters with block."""
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        """Exits with block."""
+        pass
+
+    def path(self, path):
+        """
+        Returns path prepended by rootfs path.
+
+        Args:
+          path: relative path to image rootfs.
+        """
+        return os.path.join(self.rootfs, path)
diff --git a/libchrome_tools/developer-tools/elftools/dependency_graph.py b/libchrome_tools/developer-tools/elftools/dependency_graph.py
new file mode 100644
index 0000000..5ce0a4e
--- /dev/null
+++ b/libchrome_tools/developer-tools/elftools/dependency_graph.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+# Copyright 2022 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+
+
+class DependencyGraph:
+    """Structure to maintain object dependencies by used/wanted symbols."""
+
+    def __init__(self):
+        """Initializes."""
+        self.provides = {}
+        self.wants = {}
+        self.symbol_provided = collections.defaultdict(list)
+        self.symbol_used = collections.defaultdict(list)
+
+    def add_object(self,
+                   object_name,
+                   provides,
+                   wants,
+                   ignore_duplicate_symbol_error=False):
+        """
+        Adds an object into the graph.
+
+        Args:
+          object_name: name or path (a unique identifier) of the object.
+          provides: list of symbols it provides.
+          wants: list of symbols it wants.
+          ignore_duplicate_symbol_error: do not assert if two objects provides
+            the same symbol.
+        """
+        assert object_name not in self.provides, object_name
+        assert object_name not in self.wants, object_name
+        self.provides[object_name] = provides
+        self.wants[object_name] = wants
+
+        for symbol in provides:
+            if not ignore_duplicate_symbol_error:
+                assert symbol not in self.symbol_provided, 'Object %s provides %s but already provided by %s' % (
+                    object_name, symbol, self.symbol_provided[symbol])
+                self.symbol_provided[symbol].append(object_name)
+
+        for symbol in wants:
+            self.symbol_used[symbol].append(object_name)
+
+    def get_reverse_dependencies(self, object_name):
+        """
+        Gets list of objects that depends on object_name.
+
+        Args:
+          object_name: name or path (a unique identifier) of the object.
+        """
+        symbols_provided = self.provides[object_name]
+        ret = set()
+        for symbol in symbols_provided:
+            ret |= set(self.symbol_used[symbol])
+
+        return list(ret)
+
+    def get_dependencies(self, object_name):
+        """
+        Gets list of objects that object_name depends on.
+
+        Args:
+          object_name: name or path (a unique identifier) of the object.
+        """
+        symbols_used = self.wants[object_name]
+        ret = set()
+        for symbol in symbols_used:
+            ret |= set(self.symbol_provided[symbol])
+
+        return list(ret)
+
+    def get_all_dependencies(self, object_name, reverse=False):
+        """
+        Gets list of objects that object_name depends on, recursively.
+
+        Args:
+          object_name: name or path (a unique identifier) of the object.
+          reverse: set to True to get reverse dependency recursively.
+        """
+        ret = set()
+        pending_queue = collections.deque()
+        processed = set()
+
+        ret.add(object_name)
+        pending_queue.append(object_name)
+
+        while pending_queue:
+            item = pending_queue.popleft()
+            processed.add(item)
+            if reverse:
+                dependencies = self.get_reverse_dependencies(item)
+            else:
+                dependencies = self.get_dependencies(item)
+            ret |= set(dependencies)
+            for dependency in dependencies:
+                if dependency in processed:
+                    continue
+                if dependency in pending_queue:
+                    continue
+                pending_queue.append(dependency)
+
+        return list(ret)
diff --git a/libchrome_tools/developer-tools/elftools/elf.py b/libchrome_tools/developer-tools/elftools/elf.py
new file mode 100644
index 0000000..d962c04
--- /dev/null
+++ b/libchrome_tools/developer-tools/elftools/elf.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# Copyright 2022 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import collections
+import elftools.elf.elffile
+import subprocess
+import re
+
+
+def read_symbol(elfpath, dynamic=False):
+    """
+    Reads global symbols provided or wanted by given binary.
+
+    Args:
+      elfpath: path to the binary.
+      dynamic: reads .dynsym rather than .symtab.
+    """
+    provides = []
+    wants = []
+
+    with open(elfpath, 'rb') as file:
+        elf = elftools.elf.elffile.ELFFile(file)
+        symtab = elf.get_section_by_name('.dynsym' if dynamic else '.symtab')
+        assert symtab, elfpath
+        symbols = collections.defaultdict(list)
+        for symbol in symtab.iter_symbols():
+            if not symbol.name:
+                continue
+            # Weak symbols don't provide actual implementations. Use STB_GLOBAL
+            # only.
+            if symbol.entry.st_info.bind != 'STB_GLOBAL':
+                continue
+            assert symbol.entry.st_info.type in [
+                'STT_FUNC', 'STT_NOTYPE', 'STT_OBJECT'
+            ], (elfpath, symbol.name, symbol.entry)
+            idx = symbol.entry.st_shndx
+            if idx == 'SHN_UNDEF':
+                wants.append(symbol.name)
+            else:
+                assert symbol.entry.st_info.type != 'STT_NOTYPE', symbol
+                provides.append(symbol.name)
+
+    return provides, wants
diff --git a/libchrome_tools/developer-tools/elftools/usagechecker.py b/libchrome_tools/developer-tools/elftools/usagechecker.py
new file mode 100755
index 0000000..cdab3cb
--- /dev/null
+++ b/libchrome_tools/developer-tools/elftools/usagechecker.py
@@ -0,0 +1,249 @@
+#!/usr/bin/env python
+# Copyright 2022 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+Identify unused libchrome cc files, by
+analyzing binary symbol from libchrome .o(s) and image ELF executable/.so(s).
+
+Usage:
+
+1)
+  $ export LIBCHROME_BOARD=<some board>
+  $ FEATURES=noclean emerge-$LIBCHROME_BOARD libchrome
+2)
+  ./usagechecker.py --libchrome-reference-board $LIBCHROME_BOARD --test-board
+  <board1> --test-board <board2>
+"""
+
+import argparse
+import collections
+import glob
+import os
+import subprocess
+import sys
+
+import elf
+import dependency_graph
+import crosimage
+
+TMPDIR = 'tmpdir'
+
+
+def get_libchrome_graph(board):
+    """Returns a DependencyGraph for libchrome intermediate .o
+
+    Args:
+      board: board to use. requires a board with uncleaned libchrome temporary
+        portage directory.
+    """
+    libchrome_build_dir = glob.glob(
+        '/build/%s/tmp/portage/chromeos-base/libchrome-0.0.1-r*/work/build/out/Default'
+        % (board))
+    assert len(libchrome_build_dir
+              ) == 1, 'Please do FEATURES=noclean emerge-$BOARD libchrome'
+    libchrome_build_dir = libchrome_build_dir[0]
+    objects_dir = os.path.join(libchrome_build_dir, 'obj/libchrome')
+    objects = glob.iglob(os.path.join(objects_dir, '**/*.o'), recursive=True)
+
+    object_symbols = {}
+    for o in objects:
+        # test_support .o(s) only compiles to .a static library. It is not
+        # supposed to be used by any production binary from the image. The
+        # image doesn't have unittest which uses test_support, either. Besides,
+        # the .a doesn't consume any final image size.
+        # Thus, ignore any test_support objects.
+        if 'test_support.' in o:
+            continue
+        object_symbols[o[len(objects_dir) + 1:]] = elf.read_symbol(o)
+
+    graph = dependency_graph.DependencyGraph()
+    for o, symbols in object_symbols.items():
+        provides, wants = symbols
+        graph.add_object(o, provides, wants)
+
+    return graph
+
+
+def get_target_file(path):
+    """Gets list of files that is potentially dynamically linked.
+
+    Args:
+      path: search path root begins here.
+    """
+    wanted = []
+    for dirpath, _, files in os.walk(path):
+        for filename in files:
+            # If we found libchrome itself, ignoring.
+            if 'libbase-' in filename or 'libmojo.so' == filename:
+                continue
+            filepath = os.path.join(dirpath, filename)
+            # We only want ELF executables or shared libaries. Both should have
+            # executable permissions.
+            if not os.access(filepath, os.X_OK):
+                continue
+            deps = subprocess.run(
+                ['readelf', '-d', filepath],
+                stdout=subprocess.PIPE,
+                stderr=subprocess.DEVNULL).stdout.decode('utf-8')
+            if 'libbase-' in deps or 'libmojo.so' in deps:
+                wanted.append(filepath)
+    return wanted
+
+
+def get_image_graph(board):
+    """Returns a DependencyGraph for dynamically linked binaries in board image.
+
+    Args:
+      board: board to scan image for.
+    """
+    graph = dependency_graph.DependencyGraph()
+    with crosimage.MountedReleaseImage(board, "testdir") as image:
+        # with crosimage.MountedReleaseImage(board, TMPDIR) as image:
+        files_to_scan = get_target_file(image.rootfs)
+        for f in files_to_scan:
+            provides, wants = elf.read_symbol(f, dynamic=True)
+            graph.add_object(f[len(image.rootfs) + 1:],
+                             provides,
+                             wants,
+                             ignore_duplicate_symbol_error=True)
+
+    return graph
+
+
+def get_boards_used_symbols(boards):
+    """Gets a set of used symbols for given boards.
+
+    Args:
+      boards: list of str, each str represents a board name.
+    """
+    symbols = set()
+    for board in boards:
+        graph = get_image_graph(board)
+        symbols |= set(graph.symbol_used.keys())
+
+    return symbols
+
+
+def dive_symbol(symbol, graph, cache):
+    """Gets the set of needed objects in graph, recursively, based on given symbol to use.
+
+    Args:
+      symbol: a needed symbol.
+      graph: a DependencyGraph that one object provide neede symbol.
+      cache: a set used in previous calls to dive_symbol with the same graph to
+        reduce recursive lookups.
+    """
+    if symbol not in graph.symbol_provided:
+        return set()
+
+    if symbol in cache:
+        return cache[symbol]
+
+    # Prevent infinite recursion lookup.
+    cache[symbol] = set()
+
+    objects = set()
+    provided_by_list = graph.symbol_provided[symbol]
+
+    for provided_by in provided_by_list:
+        objects.add(provided_by)
+
+        for want_symbol in graph.wants[provided_by]:
+            objects |= dive_symbol(want_symbol, graph, cache)
+
+    cache[symbol] = objects
+    return objects
+
+
+def make_group(files_unused, graph):
+    """
+    Returns groups where object should be included/excluded atomically.
+
+    With files_unused, usually developers may not want to remove all files at
+    once to reduce unexpected errors/regressions, make_group will analyze the
+    object dependency in graph to provide all possible groups that files should
+    be included/excluded atomically.
+
+    This is not a strongly connected components.
+    For example,
+     A -> B <-> C
+     |
+    \|/
+     D -> E  <- F
+    Objects dependency may look like above.
+    With strongly connected components, A / BC / D / E / F are the groups,
+    which is not correct. e.g. we cannot remove E-only.
+    Instead, groups are:
+    A / ABC / F / ADEF / AD / ABCDEF / etc.
+    Each group can be removed together and all objects remaining can still have
+    their dependency available.
+
+    Args:
+      files_unused: list of object to analyze.
+      graph: a DependencyGraph containing original objects where files_unused is
+        calculated.
+    """
+    groups = {}
+    for file in files_unused:
+        groups[file] = frozenset([file] +
+                                 graph.get_all_dependencies(file, reverse=True))
+
+    return sorted(list(set(groups.values())), key=len)
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description=
+        'Check libchrome and board images to identify unused libchrome objects.'
+    )
+
+    parser.add_argument('--libchrome-reference-board',
+                        type=str,
+                        required=True,
+                        help='Board where libchrome objects is located.')
+    parser.add_argument(
+        '--test-board',
+        action='append',
+        type=str,
+        required=True,
+        help=
+        'Board name that test image will be used. should be the same architecture as libchrome reference board.'
+    )
+    parser.add_argument(
+        '--print-groups',
+        help=
+        'Print unused objects in groups based on their inter-dependency. Note: very long output.',
+        action='store_const',
+        const=True,
+        default=False)
+
+    arg = parser.parse_args(sys.argv[1:])
+    print(arg)
+
+    graph_libchrome = get_libchrome_graph(arg.libchrome_reference_board)
+    wanted_symbols = get_boards_used_symbols(arg.test_board)
+    files_unused = graph_libchrome.provides.keys()
+    cache = {}
+    for used_symbol in wanted_symbols:
+        needed_objects = dive_symbol(used_symbol, graph_libchrome, cache)
+        files_unused -= needed_objects
+
+    files_unused = sorted(files_unused)
+    print('\n'.join(files_unused))
+    print()
+
+    if arg.print_groups:
+        files_unused_grouped = make_group(files_unused, graph_libchrome)
+        for groupid, group in enumerate(files_unused_grouped, start=1):
+            group = sorted(group)
+            for item in group:
+                print('%03d %03d %s' % (groupid, len(group), item))
+
+        print()
+
+    print(len(files_unused))
+
+
+if __name__ == '__main__':
+    main()
diff --git a/libchrome_tools/developer-tools/parallel-packages-checker/config.py b/libchrome_tools/developer-tools/parallel-packages-checker/config.py
new file mode 100644
index 0000000..9d46905
--- /dev/null
+++ b/libchrome_tools/developer-tools/parallel-packages-checker/config.py
@@ -0,0 +1,7993 @@
+# THIS FILE IS GENERATED. DO NOT EDIT MANUALLY.
+
+ALL_BOARDS = [
+    'amd64-generic', 'arm-generic', 'arm64-generic', 'asuka', 'asurada',
+    'atlas', 'beaglebone', 'betty', 'betty-arc-r', 'betty-arc-t',
+    'betty-pi-arc', 'bob', 'brask', 'brya', 'brya-arc-t', 'brya-debug-kernel',
+    'brya-faceauth', 'brya-zephyr', 'bubs', 'caroline', 'cave', 'chell',
+    'cherry', 'cherry64', 'coral', 'corsola', 'dedede', 'dedede-debug-kernel',
+    'draco', 'drallion', 'elm', 'endeavour', 'eve', 'eve-arc-r', 'excelsior',
+    'fizz', 'fizz-labstation', 'glados', 'grunt', 'grunt-arc-r', 'guybrush',
+    'guybrush-debug-kernel', 'hana', 'hatch', 'hatch-arc-r', 'hatch-arc-t',
+    'herobrine', 'jacuzzi', 'kalista', 'keeby', 'kevin', 'kevin64', 'kukui',
+    'kukui-arc-r', 'kukui-debug-kernel', 'lars', 'majolica', 'nami', 'nautilus',
+    'nissa', 'nocturne', 'novato', 'novato-arc64', 'octopus',
+    'octopus-chrome-dcheck', 'octopus-debug-kernel', 'puff', 'pyro', 'rammus',
+    'rammus-arc-r', 'reef', 'reven', 'reven-kernelnext', 'reven-vmtest', 'sand',
+    'sarien', 'scarlet', 'sentry', 'skyrim', 'sludge', 'snappy', 'soraka',
+    'strongbad', 'strongbad-kernelnext', 'tael', 'tatl', 'trogdor',
+    'trogdor-debug-kernel', 'trogdor-kernelnext',
+    'trogdor-kernelnext-debug-kernel', 'trogdor-zephyr', 'trogdor64', 'viking',
+    'volteer', 'zork', 'zork-arc-r', 'zork-floss', 'zork-mandolin'
+]
+DEFAULT_BOARDS = [
+    'brya-faceauth', 'endeavour', 'betty', 'sludge', 'nocturne', 'kevin', 'eve',
+    'herobrine', 'kukui', 'nissa', 'novato', 'octopus', 'reven', 'scarlet',
+    'snappy', 'tael'
+]
+
+# Not used. For reference only.
+BOARD_PACKAGES = {
+    'amd64-generic': [
+        'chromeos-base/aosp-frameworks-ml-nn',
+        'chromeos-base/aosp-frameworks-ml-nn-vts', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/factory_runtime_probe',
+        'chromeos-base/featured', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hps-tool',
+        'chromeos-base/hpsd', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test', 'chromeos-base/mtpd',
+        'chromeos-base/nnapi', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/tpm2-simulator', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'arm-generic': [
+        'app-crypt/trousers', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/croslog',
+        'chromeos-base/cryptohome', 'chromeos-base/cryptohome-client',
+        'chromeos-base/cryptohome-dev-utils', 'chromeos-base/debugd',
+        'chromeos-base/dev-install', 'chromeos-base/diagnostics',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hps-tool',
+        'chromeos-base/hpsd', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/u2fd', 'chromeos-base/u2fd-client',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-usb-printer',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'arm64-generic': [
+        'app-crypt/trousers', 'chromeos-base/aosp-frameworks-ml-nn',
+        'chromeos-base/aosp-frameworks-ml-nn-vts', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/croslog',
+        'chromeos-base/cryptohome', 'chromeos-base/cryptohome-client',
+        'chromeos-base/cryptohome-dev-utils', 'chromeos-base/debugd',
+        'chromeos-base/dev-install', 'chromeos-base/diagnostics',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hps-tool',
+        'chromeos-base/hpsd', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test', 'chromeos-base/mtpd',
+        'chromeos-base/nnapi', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/u2fd', 'chromeos-base/u2fd-client',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-usb-printer',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'asuka': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'asurada': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'atlas': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu3',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'beaglebone': [
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/croslog',
+        'chromeos-base/cryptohome-dev-utils', 'chromeos-base/dev-install',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libipp', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/metrics',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/policy_utils', 'chromeos-base/secure-erase-file',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-net', 'chromeos-base/syslog-cat',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/update_engine', 'chromeos-base/verity',
+        'chromeos-base/virtual-usb-printer', 'dev-util/bsdiff',
+        'dev-util/puffin'
+    ],
+    'betty': [
+        'chromeos-base/aosp-frameworks-ml-nn',
+        'chromeos-base/aosp-frameworks-ml-nn-vts', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/federated-service', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hps-tool',
+        'chromeos-base/hpsd', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/nnapi', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/tpm2-simulator', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'betty-arc-r': [
+        'chromeos-base/aosp-frameworks-ml-nn',
+        'chromeos-base/aosp-frameworks-ml-nn-vts', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/federated-service', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hps-tool',
+        'chromeos-base/hpsd', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/nnapi', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/tpm2-simulator', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'betty-arc-t': [
+        'chromeos-base/aosp-frameworks-ml-nn',
+        'chromeos-base/aosp-frameworks-ml-nn-vts', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/federated-service', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hps-tool',
+        'chromeos-base/hpsd', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/nnapi', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/tpm2-simulator', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'betty-pi-arc': [
+        'chromeos-base/aosp-frameworks-ml-nn',
+        'chromeos-base/aosp-frameworks-ml-nn-vts', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/federated-service', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hps-tool',
+        'chromeos-base/hpsd', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/nnapi', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/tpm2-simulator', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'bob': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'brask': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/lvmd',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/minios', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'brya': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hps-tool', 'chromeos-base/hpsd',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/lvmd',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/minios', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-auto-framing-tests',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb', 'media-libs/cros-camera-hdrnet-tests',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'brya-arc-t': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hps-tool', 'chromeos-base/hpsd',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/lvmd',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/minios', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-auto-framing-tests',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb', 'media-libs/cros-camera-hdrnet-tests',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'brya-debug-kernel': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hps-tool', 'chromeos-base/hpsd',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/lvmd',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/minios', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-auto-framing-tests',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb', 'media-libs/cros-camera-hdrnet-tests',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'brya-faceauth': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto', 'chromeos-base/face-cli',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hps-tool', 'chromeos-base/hpsd',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/lvmd',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/minios', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-auto-framing-tests',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb', 'media-libs/cros-camera-hdrnet-tests',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'brya-zephyr': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hps-tool', 'chromeos-base/hpsd',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/lvmd',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/minios', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-auto-framing-tests',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb', 'media-libs/cros-camera-hdrnet-tests',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'bubs': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/tpm2-simulator', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'caroline': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'cave': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'chell': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'cherry': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/minios',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'cherry64': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/minios',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'coral': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'corsola': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/lvmd', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/minios',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/modemfwd',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'dedede': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'dedede-debug-kernel': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'draco': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/lvmd',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/minios', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'drallion': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'elm': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'endeavour': [
+        'chromeos-base/atrusctl', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cfm-dfu-notification',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/ip-peripheral',
+        'chromeos-base/ipaudio-alsa-plugin', 'chromeos-base/kerberos',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mtpd', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/trunks',
+        'chromeos-base/u2fd', 'chromeos-base/u2fd-client',
+        'chromeos-base/u2fd-corp', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/viking-hid', 'chromeos-base/virtual-usb-printer',
+        'chromeos-base/vm_host_tools', 'chromeos-base/vtpm',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-ip', 'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-wireless/bluez', 'net-wireless/floss',
+        'sys-apps/aver-updater', 'sys-apps/bizlink-updater',
+        'sys-apps/cecservice', 'sys-apps/cfm-dlc-installer', 'sys-apps/hotline',
+        'sys-apps/hotlog', 'sys-apps/huddly-falcon-updater',
+        'sys-apps/huddly-monitor', 'sys-apps/huddly-updater',
+        'sys-apps/logitech-updater', 'sys-apps/mimo-mcu-updater',
+        'sys-apps/mimo-monitor', 'sys-apps/mimo-updater', 'sys-apps/sis-updater'
+    ],
+    'eve': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/st_flash', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/trunks',
+        'chromeos-base/u2fd', 'chromeos-base/u2fd-client',
+        'chromeos-base/u2fd-corp', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'eve-arc-r': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/st_flash', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/trunks',
+        'chromeos-base/u2fd', 'chromeos-base/u2fd-client',
+        'chromeos-base/u2fd-corp', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'excelsior': [
+        'chromeos-base/atrusctl', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cfm-dfu-notification',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mtpd', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/trunks',
+        'chromeos-base/u2fd', 'chromeos-base/u2fd-client',
+        'chromeos-base/u2fd-corp', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-wireless/bluez', 'net-wireless/floss',
+        'sys-apps/aver-updater', 'sys-apps/bizlink-updater',
+        'sys-apps/cecservice', 'sys-apps/cfm-dlc-installer', 'sys-apps/hotline',
+        'sys-apps/hotlog', 'sys-apps/huddly-monitor', 'sys-apps/huddly-updater',
+        'sys-apps/logitech-updater', 'sys-apps/mimo-mcu-updater',
+        'sys-apps/mimo-monitor', 'sys-apps/mimo-updater', 'sys-apps/sis-updater'
+    ],
+    'fizz': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'fizz-labstation': [
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/croslog',
+        'chromeos-base/cryptohome', 'chromeos-base/cryptohome-client',
+        'chromeos-base/cryptohome-dev-utils', 'chromeos-base/debugd',
+        'chromeos-base/dev-install', 'chromeos-base/diagnostics',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/factory_runtime_probe',
+        'chromeos-base/featured', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/missive', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vtpm',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'glados': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'grunt': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'grunt-arc-r': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'guybrush': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/lvmd', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/minios',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/modemfwd',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'guybrush-debug-kernel': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/lvmd', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/minios',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/modemfwd',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'hana': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'hatch': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'hatch-arc-r': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'hatch-arc-t': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'herobrine': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/lvmd',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/minios', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/qc-modemfwd-helper', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/trunks',
+        'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'jacuzzi': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'kalista': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'keeby': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'kevin': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/touch_firmware_calibration', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/u2fd', 'chromeos-base/u2fd-client',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'kevin64': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/touch_firmware_calibration', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/u2fd', 'chromeos-base/u2fd-client',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'kukui': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hammerd',
+        'chromeos-base/hammerd-test-utils', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-mtk', 'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'kukui-arc-r': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hammerd',
+        'chromeos-base/hammerd-test-utils', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-mtk', 'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'kukui-debug-kernel': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hammerd',
+        'chromeos-base/hammerd-test-utils', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-mtk', 'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'lars': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'majolica': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/cdm-oemcrypto-hw-test', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm2-simulator',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/trunks',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'nami': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'nautilus': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu3',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'nissa': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/discod',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/lvmd', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/minios',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/modemfwd',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'nocturne': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hammerd',
+        'chromeos-base/hammerd-test-utils', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu3',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'novato': [
+        'chromeos-base/aosp-frameworks-ml-nn',
+        'chromeos-base/aosp-frameworks-ml-nn-vts', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/croslog',
+        'chromeos-base/cryptohome', 'chromeos-base/cryptohome-client',
+        'chromeos-base/cryptohome-dev-utils', 'chromeos-base/debugd',
+        'chromeos-base/dev-install', 'chromeos-base/diagnostics',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/goldfishd',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hps-tool',
+        'chromeos-base/hpsd', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/nnapi', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/tpm2-simulator', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vtpm',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'novato-arc64': [
+        'chromeos-base/aosp-frameworks-ml-nn',
+        'chromeos-base/aosp-frameworks-ml-nn-vts', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/goldfishd',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hps-tool',
+        'chromeos-base/hpsd', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/nnapi', 'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/tpm2-simulator', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'octopus': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd', 'chromeos-base/rmad',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'octopus-chrome-dcheck': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd', 'chromeos-base/rmad',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'octopus-debug-kernel': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd', 'chromeos-base/rmad',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'puff': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'pyro': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'rammus': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'rammus-arc-r': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'reef': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'reven': [
+        'app-crypt/trousers', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/flex_id', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'reven-kernelnext': [
+        'app-crypt/trousers', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/flex_id', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'reven-vmtest': [
+        'app-crypt/trousers', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/flex_id', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/missive', 'chromeos-base/mist', 'chromeos-base/ml',
+        'chromeos-base/ml-benchmark', 'chromeos-base/ml-benchmark-drivers',
+        'chromeos-base/ml-client', 'chromeos-base/ml-cmdline',
+        'chromeos-base/modem-utilities', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/tpm2-simulator',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/trunks',
+        'chromeos-base/u2fd', 'chromeos-base/u2fd-client',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-usb-printer',
+        'chromeos-base/vm_host_tools', 'chromeos-base/vtpm',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'sand': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'sarien': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'scarlet': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-hal-rockchip-isp1',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'sentry': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'skyrim': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'sludge': [
+        'chromeos-base/diagnostics-dpsl-test', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/mcastd',
+        'chromeos-base/ndproxyd', 'chromeos-base/sommelier',
+        'chromeos-base/vm_guest_tools'
+    ],
+    'snappy': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/disk_updater',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/arc-camera-profile',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez'
+    ],
+    'soraka': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hammerd',
+        'chromeos-base/hammerd-test-utils', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu3',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'strongbad': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hammerd', 'chromeos-base/hammerd-test-utils',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'strongbad-kernelnext': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hammerd', 'chromeos-base/hammerd-test-utils',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'tael': [
+        'chromeos-base/crash-reporter', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libcrossystem',
+        'chromeos-base/mcastd', 'chromeos-base/metrics',
+        'chromeos-base/ndproxyd', 'chromeos-base/sommelier',
+        'chromeos-base/termina_container_tools', 'chromeos-base/vm_guest_tools'
+    ],
+    'tatl': [
+        'chromeos-base/crash-reporter', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libcrossystem',
+        'chromeos-base/mcastd', 'chromeos-base/metrics',
+        'chromeos-base/ndproxyd', 'chromeos-base/sommelier',
+        'chromeos-base/termina_container_tools', 'chromeos-base/vm_guest_tools'
+    ],
+    'trogdor': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'trogdor-debug-kernel': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'trogdor-kernelnext': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'trogdor-kernelnext-debug-kernel': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'trogdor-zephyr': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'trogdor64': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'viking': [
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-trim',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/dev-install', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libipp', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/metrics', 'chromeos-base/policy_utils',
+        'chromeos-base/secure-erase-file', 'chromeos-base/shill-client',
+        'chromeos-base/syslog-cat', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/update_engine',
+        'chromeos-base/verity', 'chromeos-base/virtual-usb-printer',
+        'dev-util/bsdiff', 'dev-util/puffin'
+    ],
+    'volteer': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/foomatic_shell', 'chromeos-base/fusebox',
+        'chromeos-base/g2f_tools', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'zork': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'zork-arc-r': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda', 'chromeos-base/libvda-gpu-tests',
+        'chromeos-base/lorgnette', 'chromeos-base/lorgnette_cli',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/missive', 'chromeos-base/mist',
+        'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'zork-floss': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-appfuse', 'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-keymaster', 'chromeos-base/arc-obb-mounter',
+        'chromeos-base/arc-sdcard', 'chromeos-base/arc-setup',
+        'chromeos-base/attestation', 'chromeos-base/attestation-client',
+        'chromeos-base/authpolicy', 'chromeos-base/biod',
+        'chromeos-base/biod_proxy', 'chromeos-base/bootid-logger',
+        'chromeos-base/bootlockbox-client', 'chromeos-base/bootstat',
+        'chromeos-base/cbor', 'chromeos-base/cdm-oemcrypto',
+        'chromeos-base/chaps', 'chromeos-base/chaps-client',
+        'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/croslog',
+        'chromeos-base/cryptohome', 'chromeos-base/cryptohome-client',
+        'chromeos-base/cryptohome-dev-utils', 'chromeos-base/debugd',
+        'chromeos-base/dev-install', 'chromeos-base/diagnostics',
+        'chromeos-base/dlcservice', 'chromeos-base/dlcservice-client',
+        'chromeos-base/dlp', 'chromeos-base/dns-proxy',
+        'chromeos-base/easy-unlock', 'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hwsec-test-utils',
+        'chromeos-base/iioservice', 'chromeos-base/iioservice_simpleclient',
+        'chromeos-base/imageloader', 'chromeos-base/kerberos',
+        'chromeos-base/lexmark-fax-pnh', 'chromeos-base/libbrillo',
+        'chromeos-base/libchrome', 'chromeos-base/libchromeos-ui',
+        'chromeos-base/libcontainer', 'chromeos-base/libcrossystem',
+        'chromeos-base/libec', 'chromeos-base/libhwsec',
+        'chromeos-base/libhwsec-foundation', 'chromeos-base/libiioservice_ipc',
+        'chromeos-base/libipp', 'chromeos-base/libmems',
+        'chromeos-base/libpasswordprovider', 'chromeos-base/libtpmcrypto',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/usb_bouncer',
+        'chromeos-base/verity', 'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vtpm',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-wireless/bluez',
+        'net-wireless/floss'
+    ],
+    'zork-mandolin': [
+        'app-crypt/trousers', 'chromeos-base/arc-adbd',
+        'chromeos-base/arc-apk-cache', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-data-snapshotd', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/arc-setup', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/gemalto-firmware',
+        'chromeos-base/glib-bridge', 'chromeos-base/google-lpa',
+        'chromeos-base/hardware_verifier', 'chromeos-base/hermes',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/mems_setup',
+        'chromeos-base/metrics', 'chromeos-base/midis', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/policy_utils',
+        'chromeos-base/power_manager', 'chromeos-base/power_manager-client',
+        'chromeos-base/print_tools', 'chromeos-base/quipper',
+        'chromeos-base/rgbkbd', 'chromeos-base/run_oci',
+        'chromeos-base/runtime_probe', 'chromeos-base/screen-capture-utils',
+        'chromeos-base/secanomalyd', 'chromeos-base/secure-erase-file',
+        'chromeos-base/secure-wipe', 'chromeos-base/session_manager-client',
+        'chromeos-base/shill', 'chromeos-base/shill-client',
+        'chromeos-base/shill-dbus-client', 'chromeos-base/shill-net',
+        'chromeos-base/smbfs', 'chromeos-base/smbprovider',
+        'chromeos-base/spaced', 'chromeos-base/syslog-cat',
+        'chromeos-base/system-proxy', 'chromeos-base/system_api',
+        'chromeos-base/tast-local-helpers-cros', 'chromeos-base/timberslide',
+        'chromeos-base/tpm_manager', 'chromeos-base/tpm_manager-client',
+        'chromeos-base/tpm_softclear_utils', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/update_engine',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'dev-libs/libtextclassifier', 'dev-util/bsdiff', 'dev-util/puffin',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-usb',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ]
+}
+
+BOARDS_MAPPING = {
+    'all': ALL_BOARDS,
+    'default': DEFAULT_BOARDS,
+}
+
+# Not used. For reference only.
+DEFAULT_BOARDS_REASON = {
+    'brya-faceauth': [
+        'chromeos-base/arc-adbd', 'chromeos-base/arc-apk-cache',
+        'chromeos-base/arc-data-snapshotd',
+        'chromeos-base/arc-host-clock-service', 'chromeos-base/arc-keymaster',
+        'chromeos-base/arc-setup',
+        'chromeos-base/arcvm-boot-notification-server',
+        'chromeos-base/arcvm-mojo-proxy', 'chromeos-base/attestation',
+        'chromeos-base/attestation-client', 'chromeos-base/authpolicy',
+        'chromeos-base/biod', 'chromeos-base/biod_proxy',
+        'chromeos-base/bootid-logger', 'chromeos-base/bootlockbox-client',
+        'chromeos-base/bootstat', 'chromeos-base/cbor',
+        'chromeos-base/cdm-oemcrypto', 'chromeos-base/cdm-oemcrypto-hw-test',
+        'chromeos-base/cdm-oemcrypto-hw-test-wv14',
+        'chromeos-base/cdm-oemcrypto-wv14', 'chromeos-base/chaps',
+        'chromeos-base/chaps-client', 'chromeos-base/chromeos-common-script',
+        'chromeos-base/chromeos-config-tools',
+        'chromeos-base/chromeos-imageburner', 'chromeos-base/chromeos-init',
+        'chromeos-base/chromeos-installer', 'chromeos-base/chromeos-login',
+        'chromeos-base/chromeos-storage-info', 'chromeos-base/chromeos-trim',
+        'chromeos-base/crash-reporter', 'chromeos-base/cros-camera',
+        'chromeos-base/cros-camera-android-deps',
+        'chromeos-base/cros-camera-libs', 'chromeos-base/cros-camera-tool',
+        'chromeos-base/cros-disks', 'chromeos-base/crosdns',
+        'chromeos-base/croslog', 'chromeos-base/cryptohome',
+        'chromeos-base/cryptohome-client', 'chromeos-base/cryptohome-dev-utils',
+        'chromeos-base/debugd', 'chromeos-base/dev-install',
+        'chromeos-base/diagnostics', 'chromeos-base/dlcservice',
+        'chromeos-base/dlcservice-client', 'chromeos-base/dlp',
+        'chromeos-base/dns-proxy', 'chromeos-base/easy-unlock',
+        'chromeos-base/easy-unlock-crypto', 'chromeos-base/face-cli',
+        'chromeos-base/factory_runtime_probe', 'chromeos-base/featured',
+        'chromeos-base/fibocom-firmware', 'chromeos-base/foomatic_shell',
+        'chromeos-base/fusebox', 'chromeos-base/g2f_tools',
+        'chromeos-base/gemalto-firmware', 'chromeos-base/glib-bridge',
+        'chromeos-base/google-lpa', 'chromeos-base/hardware_verifier',
+        'chromeos-base/hermes', 'chromeos-base/hps-tool', 'chromeos-base/hpsd',
+        'chromeos-base/hwsec-test-utils', 'chromeos-base/iioservice',
+        'chromeos-base/iioservice_simpleclient', 'chromeos-base/imageloader',
+        'chromeos-base/kerberos', 'chromeos-base/lexmark-fax-pnh',
+        'chromeos-base/libbrillo', 'chromeos-base/libchrome',
+        'chromeos-base/libchromeos-ui', 'chromeos-base/libcontainer',
+        'chromeos-base/libcrossystem', 'chromeos-base/libec',
+        'chromeos-base/libhwsec', 'chromeos-base/libhwsec-foundation',
+        'chromeos-base/libiioservice_ipc', 'chromeos-base/libipp',
+        'chromeos-base/libmems', 'chromeos-base/libpasswordprovider',
+        'chromeos-base/libtpmcrypto', 'chromeos-base/libvda',
+        'chromeos-base/libvda-gpu-tests', 'chromeos-base/lorgnette',
+        'chromeos-base/lorgnette_cli', 'chromeos-base/lvmd',
+        'chromeos-base/mems_setup', 'chromeos-base/metrics',
+        'chromeos-base/midis', 'chromeos-base/minios', 'chromeos-base/missive',
+        'chromeos-base/mist', 'chromeos-base/ml', 'chromeos-base/ml-benchmark',
+        'chromeos-base/ml-benchmark-drivers', 'chromeos-base/ml-client',
+        'chromeos-base/ml-cmdline', 'chromeos-base/modem-utilities',
+        'chromeos-base/modemfwd', 'chromeos-base/mojo_service_manager',
+        'chromeos-base/mojo_service_manager-test',
+        'chromeos-base/mount-passthrough', 'chromeos-base/mtpd',
+        'chromeos-base/oobe_config', 'chromeos-base/p2p',
+        'chromeos-base/patchpanel', 'chromeos-base/patchpanel-client',
+        'chromeos-base/pciguard', 'chromeos-base/perfetto_simple_producer',
+        'chromeos-base/permission_broker', 'chromeos-base/pinweaver',
+        'chromeos-base/policy_utils', 'chromeos-base/power_manager',
+        'chromeos-base/power_manager-client', 'chromeos-base/print_tools',
+        'chromeos-base/quipper', 'chromeos-base/rgbkbd',
+        'chromeos-base/run_oci', 'chromeos-base/runtime_probe',
+        'chromeos-base/screen-capture-utils', 'chromeos-base/secanomalyd',
+        'chromeos-base/secure-erase-file', 'chromeos-base/secure-wipe',
+        'chromeos-base/session_manager-client', 'chromeos-base/shill',
+        'chromeos-base/shill-client', 'chromeos-base/shill-dbus-client',
+        'chromeos-base/shill-net', 'chromeos-base/smbfs',
+        'chromeos-base/smbprovider', 'chromeos-base/spaced',
+        'chromeos-base/syslog-cat', 'chromeos-base/system-proxy',
+        'chromeos-base/system_api', 'chromeos-base/tast-local-helpers-cros',
+        'chromeos-base/timberslide', 'chromeos-base/tpm_manager',
+        'chromeos-base/tpm_manager-client', 'chromeos-base/tpm_softclear_utils',
+        'chromeos-base/trunks', 'chromeos-base/typecd', 'chromeos-base/u2fd',
+        'chromeos-base/u2fd-client', 'chromeos-base/u2fd-corp',
+        'chromeos-base/update_engine', 'chromeos-base/update_engine-client',
+        'chromeos-base/usb_bouncer', 'chromeos-base/verity',
+        'chromeos-base/virtual-file-provider',
+        'chromeos-base/virtual-usb-printer', 'chromeos-base/vm_host_tools',
+        'chromeos-base/vtpm', 'dev-libs/libtextclassifier', 'dev-util/bsdiff',
+        'dev-util/puffin', 'media-libs/cros-camera-auto-framing-tests',
+        'media-libs/cros-camera-document-scanning-test',
+        'media-libs/cros-camera-frame-annotator',
+        'media-libs/cros-camera-hal-intel-ipu6',
+        'media-libs/cros-camera-hal-usb', 'media-libs/cros-camera-hdrnet-tests',
+        'media-libs/cros-camera-libcamera_connector_test',
+        'media-libs/cros-camera-libfs', 'media-libs/cros-camera-libjea_test',
+        'media-libs/cros-camera-sw-privacy-switch-test',
+        'media-libs/cros-camera-test', 'media-libs/cros-camera-usb-tests',
+        'media-libs/dlm', 'net-print/brother_mlaser', 'net-print/cups_proxy',
+        'net-wireless/bluez', 'net-wireless/floss'
+    ],
+    'endeavour': [
+        'chromeos-base/atrusctl', 'chromeos-base/cfm-dfu-notification',
+        'chromeos-base/ip-peripheral', 'chromeos-base/ipaudio-alsa-plugin',
+        'chromeos-base/viking-hid',
+        'media-libs/cros-camera-hal-ip', 'sys-apps/aver-updater',
+        'sys-apps/bizlink-updater', 'sys-apps/cecservice',
+        'sys-apps/cfm-dlc-installer', 'sys-apps/hotline', 'sys-apps/hotlog',
+        'sys-apps/huddly-falcon-updater', 'sys-apps/huddly-monitor',
+        'sys-apps/huddly-updater', 'sys-apps/logitech-updater',
+        'sys-apps/mimo-mcu-updater', 'sys-apps/mimo-monitor',
+        'sys-apps/mimo-updater', 'sys-apps/sis-updater'
+    ],
+    'betty': [
+        'chromeos-base/aosp-frameworks-ml-nn',
+        'chromeos-base/aosp-frameworks-ml-nn-vts', 'chromeos-base/arc-appfuse',
+        'chromeos-base/arc-obb-mounter', 'chromeos-base/arc-sdcard',
+        'chromeos-base/federated-service', 'chromeos-base/nnapi',
+        'chromeos-base/tpm2-simulator'
+    ],
+    'sludge': [
+        'chromeos-base/diagnostics-dpsl-test', 'chromeos-base/mcastd',
+        'chromeos-base/ndproxyd', 'chromeos-base/sommelier',
+        'chromeos-base/vm_guest_tools'
+    ],
+    'nocturne': [
+        'chromeos-base/disk_updater', 'chromeos-base/hammerd',
+        'chromeos-base/hammerd-test-utils',
+        'media-libs/cros-camera-hal-intel-ipu3'
+    ],
+    'kevin': ['app-crypt/trousers', 'chromeos-base/touch_firmware_calibration'],
+    'eve': ['chromeos-base/st_flash'],
+    'herobrine': ['chromeos-base/qc-modemfwd-helper'],
+    'kukui': ['media-libs/cros-camera-hal-mtk'],
+    'nissa': ['chromeos-base/discod'],
+    'novato': ['chromeos-base/goldfishd'],
+    'octopus': ['chromeos-base/rmad'],
+    'reven': ['chromeos-base/flex_id'],
+    'scarlet': ['media-libs/cros-camera-hal-rockchip-isp1'],
+    'snappy': ['media-libs/arc-camera-profile'],
+    'tael': ['chromeos-base/termina_container_tools']
+}
diff --git a/libchrome_tools/developer-tools/parallel-packages-checker/gen_config.py b/libchrome_tools/developer-tools/parallel-packages-checker/gen_config.py
new file mode 100755
index 0000000..032468f
--- /dev/null
+++ b/libchrome_tools/developer-tools/parallel-packages-checker/gen_config.py
@@ -0,0 +1,231 @@
+#!/usr/bin/env python3
+# Copyright 2021 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import contextlib
+import multiprocessing
+import os
+import re
+import subprocess
+import sys
+import tempfile
+
+TEMPLATE = '''
+# THIS FILE IS GENERATED. DO NOT EDIT MANUALLY.
+
+
+ALL_BOARDS = %s
+DEFAULT_BOARDS = %s
+
+# Not used. For reference only.
+BOARD_PACKAGES = %s
+
+BOARDS_MAPPING = {
+    'all': ALL_BOARDS,
+    'default': DEFAULT_BOARDS,
+}
+
+# Not used. For reference only.
+DEFAULT_BOARDS_REASON = %s
+'''
+
+_BUILDER_CONFIG_PATH = '/mnt/host/source/infra/config/generated/builder_configs.cfg'
+_VERSION_REMOVE_RE = re.compile('(.*?)(-[0-9.]+)?(-r[0-9]+)?$')
+
+
+def get_gs_file(board, latest_release, latest_milestone, filename):
+    try:
+        pattern_to_ls = 'gs://chromeos-image-archive/%s-postsubmit/%s*/%s' % (
+            board, latest_release, filename)
+        # -1 is empty str after split '\n', -2 is the last item.
+        recent_postsubmit = subprocess.check_output(
+            ['gsutil', 'ls', pattern_to_ls]).decode('ascii').split('\n')[-2]
+    except subprocess.CalledProcessError:
+        pattern_to_ls = 'gs://chromeos-image-archive/%s-postsubmit/R%d-*/%s' % (
+            board, latest_milestone, filename)
+        try:
+            recent_postsubmit = subprocess.check_output(
+                ['gsutil', 'ls', pattern_to_ls]).decode('ascii').split('\n')[-2]
+        except subprocess.CalledProcessError:
+            return None
+    return recent_postsubmit
+
+
+def get_pkg_from_db(path):
+    dirs = set()
+    for dirpath, dirnames, filenames in os.walk(path):
+        for filename in filenames:
+            if filename == 'DEPEND' or filename == 'RDEPEND':
+                filepath = os.path.join(dirpath, filename)
+                with open(filepath, 'r') as f:
+                    if 'chromeos-base/libchrome' in f.read():
+                        dirs.add(dirpath)
+    pkg_names_with_ver = [
+        # x has format like
+        # /tmp/xxxx/var_new/db/pkg/chromeos-base/libbrillo-0.0.1-r11111
+        '/'.join(x.split('/')[-2:]) for x in dirs
+    ]
+    pkg_names = [
+        _VERSION_REMOVE_RE.match(x).group(1) for x in pkg_names_with_ver
+    ]
+    return sorted(pkg_names)
+
+
+@contextlib.contextmanager
+def managed_mounted_fs(image_dir):
+    subprocess.check_call(['./mount_image.sh', 'chromiumos_test_image.bin'],
+                          cwd=image_dir)
+    try:
+        yield
+    finally:
+        subprocess.check_call(
+            ['./umount_image.sh', 'chromiumos_test_image.bin'], cwd=image_dir)
+        print(image_dir, 'umounted')
+
+
+def get_board_packages(args):
+    idx, board, latest_release, latest_milestone = args
+    print('Started', idx, board)
+    with tempfile.TemporaryDirectory() as tmpdir:
+        packages_with_libchrome_deps = set()
+        recent_postsubmit = get_gs_file(board, latest_release, latest_milestone,
+                                        'stateful.tgz')
+        if recent_postsubmit:
+            subprocess.check_call([
+                'gsutil', 'cp', recent_postsubmit,
+                os.path.join(tmpdir, 'stateful.tgz')
+            ],
+                                  stderr=subprocess.DEVNULL)
+            subprocess.check_call([
+                'tar', 'xf',
+                os.path.join(tmpdir, 'stateful.tgz'), '-C', tmpdir
+            ])
+
+            pkgs = get_pkg_from_db(os.path.join(tmpdir, 'var_new/db/pkg'))
+        else:
+            image_zip = get_gs_file(board, latest_release, latest_milestone,
+                                    'image.zip')
+            if not image_zip:
+                print('Skipped', idx, board)
+                return (board, set())
+
+            print('Use image.zip', idx, board)
+
+            subprocess.check_call(
+                ['gsutil', 'cp', image_zip,
+                 os.path.join(tmpdir, 'image.zip')],
+                stderr=subprocess.DEVNULL)
+            subprocess.check_call(
+                ['unzip',
+                 os.path.join(tmpdir, 'image.zip'), '-d', tmpdir])
+
+            with managed_mounted_fs(image_dir=tmpdir):
+                pkgs = get_pkg_from_db(
+                    os.path.join(tmpdir, 'dir_1/var_overlay/db/pkg'))
+
+        packages_with_libchrome_deps.update(pkgs)
+        print('Done', idx, board, len(packages_with_libchrome_deps), 'packages')
+        return (board, packages_with_libchrome_deps)
+
+
+def main():
+    srcdir = os.path.dirname(__file__)
+
+    all_postsubmit = subprocess.check_output([
+        'jq',
+        '.[][] | select (.id.name == "postsubmit-orchestrator") | .orchestrator.childSpecs[].name',
+        '-r',
+        _BUILDER_CONFIG_PATH,
+    ])
+    all_postsubmit = all_postsubmit.split(b'\n')
+    all_criticals = subprocess.check_output([
+        'jq', '.[][] | select (.general.critical == true) | .id.name', '-r',
+        _BUILDER_CONFIG_PATH
+    ])
+    all_criticals = all_criticals.split(b'\n')
+    critical_postsubmit = set(all_postsubmit).intersection(set(all_criticals))
+    all_boards = []
+    for postsubmit in critical_postsubmit:
+        postsubmit = postsubmit.strip()
+        if not postsubmit:
+            continue
+        postsubmit = postsubmit.decode('ascii')
+        assert postsubmit.endswith('-postsubmit')
+        board = postsubmit[:-len('-postsubmit')]
+        # In builder_configs, generic boards has asan builders, which we don't
+        # need.
+        if re.match('(amd64|arm|arm64)-generic.+', board):
+            continue
+        # chromite is not a board.
+        if board == 'chromite':
+            continue
+        # kernel_checkconfig-* is not a board.
+        if board.startswith('kernel_checkconfig-'):
+            continue
+        all_boards.append(board)
+    all_boards = sorted(all_boards)
+    print('%d boards found %s' % (len(all_boards), all_boards))
+
+    default_boards = []
+    libchrome_users = set()
+    libchrome_users_by_board = {}
+
+    latest_release = subprocess.check_output([
+        'gsutil', 'cat',
+        'gs://chromeos-image-archive/%s-release/LATEST-main' % (all_boards[10])
+    ]).decode('ascii')
+    latest_milestone = int(latest_release.split('-')[0][1:])
+    print('Latest release %s, R%d' % (latest_release, latest_milestone))
+
+    with multiprocessing.Pool(processes=10) as pool:
+        all_board_pkgs = pool.map(
+            get_board_packages,
+            [(idx, board, latest_release, latest_milestone)
+             for idx, board in enumerate(all_boards, start=1)],
+            chunksize=1)
+
+    for board, pkgs in all_board_pkgs:
+        assert len(pkgs) > 0, 'board %s must have packages' % (board)
+        libchrome_users = libchrome_users | pkgs
+        libchrome_users_by_board[board] = pkgs
+
+    print('Total of %d packages depending on libchrome' %
+          (len(libchrome_users)))
+
+    # Deep copy.
+    libchrome_users_by_board_copy = {}
+    for board, pkg_by_board in libchrome_users_by_board.items():
+        libchrome_users_by_board_copy[board] = sorted(list(pkg_by_board))
+
+    # Use greedy algorithm to find a sub-optimal minimum boards coverage.
+    boards_reason = {}
+    while libchrome_users:
+        max_board, max_board_cnt = None, 0
+        for board in libchrome_users_by_board:
+            libchrome_users_by_board[board] = libchrome_users_by_board[
+                board].intersection(libchrome_users)
+            if len(libchrome_users_by_board[board]) > max_board_cnt:
+                max_board, max_board_cnt = board, len(
+                    libchrome_users_by_board[board])
+        assert max_board
+        default_boards.append(max_board)
+        libchrome_users.difference_update(libchrome_users_by_board[max_board])
+        boards_reason[max_board] = sorted(
+            list(libchrome_users_by_board[max_board]))
+        del libchrome_users_by_board[max_board]
+    print('Recommended coverage: %s' % (default_boards))
+
+    with open(os.path.join(srcdir, 'config.py'), 'w') as f:
+        f.write(TEMPLATE %
+                (repr(all_boards), repr(default_boards),
+                 repr(libchrome_users_by_board_copy), repr(boards_reason)))
+
+    subprocess.check_call([
+        '/mnt/host/depot_tools/yapf', '-i',
+        os.path.join(srcdir, 'config.py'), '--style=google'
+    ])
+
+
+if __name__ == '__main__':
+    main()
diff --git a/libchrome_tools/developer-tools/parallel-packages-checker/parallel_packages_checker.py b/libchrome_tools/developer-tools/parallel-packages-checker/parallel_packages_checker.py
new file mode 100755
index 0000000..9c09d41
--- /dev/null
+++ b/libchrome_tools/developer-tools/parallel-packages-checker/parallel_packages_checker.py
@@ -0,0 +1,772 @@
+#!/usr/bin/env python3
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import collections
+import concurrent
+import concurrent.futures
+import datetime
+import io
+import os
+import re
+import shutil
+import subprocess
+import sys
+import threading
+import time
+import traceback
+
+try:
+    import config
+    BOARDS_MAPPING = config.BOARDS_MAPPING
+except ImportError:
+    BOARDS_MAPPING = {}
+
+_MAX_EMERGES = 32
+_MAX_EMERGES_WITHOUT_UNITTEST = 50
+
+_MAX_BUILD_PACKAGES = 3
+
+
+class State(threading.Thread):
+    """Describes states for the running checker."""
+
+    def __init__(self, update_internval):
+        """Initializes State"""
+        super(State, self).__init__()
+        # A lock to modify states/msgs.
+        self.in_use = threading.Lock()
+        # A map from board name to state name.
+        self.states = {}
+        # A map from board name to detail messages.
+        self.msgs = {}
+        # Time when State is created.
+        self.initialized_time = datetime.datetime.now().replace(microsecond=0)
+        # Map from board name to list of failed boards.
+        self.failed = {}
+        # A event to stop the thread.
+        self.stop_print_event = threading.Event()
+        # Update interval.
+        self.update_internval = update_internval
+
+    def set_failed(self, board, packages):
+        """
+        Sets failed packages for a board.
+
+        Args:
+            board: board to set.
+            packages: failed packages.
+        """
+        with self.in_use:
+            self.failed[board] = packages
+
+    def failed_matrix(self, delimiter=' ', align=True):
+        """
+        Returns a failed matrix in string.
+
+        Failed matrix is a string containing multiple lines.
+
+        The first line is header.
+        From the 2nd line, each line contains information for a board. delimited
+        by the delimiter parameter.
+
+        For the information line, the first element is the board name. From the
+        second element, it is either empty or an 'X' meaning the corresponding
+        packages failed on this board.
+
+        Args:
+            delimiter: delimiter to separate.
+            align: should add extra space to make it aligned.
+        """
+        packages = set()
+        for failed in self.failed.values():
+            packages.update(failed)
+        max_packages_len = max(
+            len(p) for p in packages) if align and packages else 0
+        header = ' ' * max_packages_len + delimiter + delimiter.join(
+            sorted(self.failed.keys())) + '\n'
+        data = []
+        for package in packages:
+            line = []
+            package_format = '%%%ds' % (max_packages_len)
+            line.append(package_format % (package))
+            for board, failed in sorted(self.failed.items()):
+                line.append(delimiter)
+                if align:
+                    line.append(' ' * (len(board) - 1))
+                if package in failed:
+                    line.append('X')
+                else:
+                    line.append(' ')
+            line.append('\n')
+            data.append(''.join(line))
+        return ''.join([header] + data)
+
+    def update(self, board, board_state, board_msg=''):
+        """
+        Updates state.
+
+        Args:
+            board: board to update.
+            board_state: new state of the board.
+            board_msg: message to display for the board.
+        """
+        with self.in_use:
+            self.states[board] = board_state
+            self.msgs[board] = board_msg
+
+    def run(self):
+        """Runs the thread to print status"""
+        while not self.stop_print_event.is_set():
+            with self.in_use:
+                self.print()
+            time.sleep(self.update_internval)
+
+    def stop(self):
+        """Stops printing status to screen"""
+        self.stop_print_event.set()
+
+    def print(self):
+        """Prints current state to a new shell screen"""
+        now = datetime.datetime.now().replace(microsecond=0)
+        print("\033c            PARALLEL PACKAGES CHECKER")
+        print('                           duration: %s, load: %s' %
+              (now - self.initialized_time, os.getloadavg()))
+        print()
+        max_board_len = max(
+            len(board_name) for board_name in self.states.keys())
+        max_state_len = max(len(state) for state in self.states.values())
+        for board in self.states.keys():
+            board_state = self.states[board]
+            board_msg = self.msgs[board]
+            board_format = "%%%ds " % (max_board_len + 5,)
+            state_format = "%%%ds " % (max_state_len + 5,)
+            print(board_format % (board,), state_format % (board_state,),
+                  '     ', board_msg)
+        print()
+        print('                              ', now)
+        print()
+
+
+class CheckOneBoard:
+    """Threads for one board checker"""
+
+    def __init__(self, board, state, log_dir, run_unittest):
+        """
+        Initializes CheckOneBoard.
+
+        Args:
+            board: name of the board.
+            state: global state object.
+            log_dir: log_dir of the the board.
+            run_unittest: whether to run unittest.
+        """
+        self.board = board
+        self.state = state
+        self.state.update(board, 'pending')
+        self.log_dir = log_dir
+        self.run_unittest = run_unittest
+
+        self.dependency_graph = None
+        self.packages_to_verify = None
+
+        self.scheduled_emerge = set()
+        self.completed_emerge = set()
+        self.passing_emerge = set()
+        self.failed_emerge = set()
+
+    def setup_board(self):
+        """Runs setup_board, and update state."""
+        self.state.update(self.board, 'setup_board')
+        proc = subprocess.Popen(['setup_board', '--board', self.board],
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.STDOUT)
+        for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
+            line = line.strip()
+            if line:
+                self.state.update(self.board, 'setup_board', line)
+        proc.wait()
+        if proc.returncode != 0:
+            self.state.update(self.board, 'failed',
+                              'setup_board failed. further steps skipped.')
+            return
+        self.state.update(self.board, 'setup_board', 'setup_board completed.')
+
+    def cros_workon_start(self, packages):
+        """
+        Runs cros_workon start for selected client packages.
+        Ignore any failing messsage since the package might not be used on all
+        the boards.
+        """
+        self.state.update(self.board, 'cros workon start', packages)
+        for package in packages.split():
+            self._cros_workon('start', package, fail_silent=True)
+
+    def build_packages(self):
+        """Runs build_packages"""
+        # cros_workon stop libchrome
+        if not self._cros_workon('stop', 'libchrome'):
+            return
+
+        # build_packages
+        # build_packages fails somtimes under high system load, allow maximum 3
+        # times of retry.
+        build_succeeded = False
+        for trial in range(3):
+            if self._build_packages():
+                build_succeeded = True
+                break
+        if not build_succeeded:
+            self.state.update(self.board, 'failed',
+                              'build_packages failed. further steps skipped.')
+            return
+        self.state.update(self.board, 'build_packages',
+                          'build_packages completed.')
+
+    def emerge_libchrome(self):
+        """Emerges libchrome"""
+        # cros_workon start libchrome
+        if not self._cros_workon('start', 'libchrome'):
+            return
+
+        # Emerge new libchrome.
+        if not self._emerge_blocking('libchrome'):
+            return
+
+    def set_emerge_scheduled(self, package):
+        """
+        Sets emerge state for one package to scheduled.
+
+        Args:
+            package: package name.
+        """
+        self.scheduled_emerge.add(package)
+        self._update_emerge_state()
+
+    def handle_emerge_result_fn(self, package):
+        """
+        Handles emerge result.
+
+        Args:
+            package: package name.
+        """
+
+        def _handle_emerge_result(future):
+            ret = False
+            try:
+                ret = future.result()
+            finally:
+                # TODO: distinguish failure and exception.
+                if ret:
+                    self.set_emerge_pass(package)
+                else:
+                    self.set_emerge_failed(package)
+
+        return _handle_emerge_result
+
+    def set_emerge_pass(self, package):
+        """
+        Sets emerge state for one package to passing
+
+        Args:
+            package: package name.
+        """
+        self.completed_emerge.add(package)
+        self.passing_emerge.add(package)
+        self.scheduled_emerge.remove(package)
+        self._update_emerge_state()
+
+    def set_emerge_failed(self, package):
+        """
+        Sets emerge state for one package to failed.
+
+        Args:
+            package: package name.
+        """
+        self.completed_emerge.add(package)
+        self.failed_emerge.add(package)
+        self.scheduled_emerge.remove(package)
+        self._update_emerge_state()
+
+    def emerge(self, package):
+        """
+        Emerge a single package.
+
+        Args:
+            package: package name.
+        """
+        log_dir = os.path.join(self.log_dir, package)
+        os.makedirs(log_dir, exist_ok=True)
+        with open(os.path.join(log_dir, 'emerge_log'), 'w') as f:
+            build_success = self._emerge_blocking(package,
+                                                  out=f,
+                                                  update_state=False)
+        if build_success:
+            shutil.rmtree(log_dir)
+            return True
+        return False
+
+    def build_dependency_graph(self):
+        """Build and save the dependency graph for libchrome-related packages."""
+        self.packages_to_verify = self._list_depended_by('libchrome')
+        self.dependency_graph = self._build_dependency_graph(
+            self.packages_to_verify)
+
+    def buildable_packages(self):
+        """
+        Returns list of buildable packages
+
+        Packages that are already scheduled, started, or completed, are excluded.
+        """
+        newly_buildable_packages = []
+        pending_packages = []
+        for package in self.packages_to_verify:
+            if package in self.scheduled_emerge | self.completed_emerge:
+                continue
+            pending_packages.append(package)
+            dependency_satisfied = True
+            for dependency in self.dependency_graph[package]:
+                if dependency not in self.packages_to_verify:
+                    continue
+                if dependency not in self.completed_emerge:
+                    dependency_satisfied = False
+                    break
+            if dependency_satisfied:
+                newly_buildable_packages.append(package)
+
+        # Has buildable packages.
+        if newly_buildable_packages:
+            return newly_buildable_packages
+        # Wait for packages not yet completed.
+        if self.scheduled_emerge:
+            return []
+        # Return any pending_packages to restart build with cyclced dependency.
+        if pending_packages:
+            return pending_packages[0:1]
+        # Build complete.
+        return []
+
+    def _update_emerge_state(self):
+        """Updates state for emerge stage."""
+        self.state.update(
+            self.board,
+            'FEATURES=test emerge' if self.run_unittest else 'emerge',
+            'Queued/Running:%d, Completed:%d (Passing:%d, Failed:%d), Total:%d'
+            % (len(self.scheduled_emerge), len(self.completed_emerge),
+               len(self.passing_emerge), len(
+                   self.failed_emerge), len(self.packages_to_verify)))
+
+    def _cros_workon(self, action, package, fail_silent=False):
+        """
+        Runs cros_workon-$BOARD, and update state.
+
+        Returns True on sucess, False otherwise.
+        """
+        assert action in ['start', 'stop']
+        self.state.update(self.board, 'cros workon ' + action,
+                          'cros workon ' + action + ' ' + package)
+        proc = subprocess.run(['cros', 'workon', '--board=' + self.board,
+                               action, package],
+                              stdout=subprocess.DEVNULL,
+                              stderr=subprocess.DEVNULL)
+        if proc.returncode != 0 and not fail_silent:
+            self.state.update(
+                self.board, 'failed',
+                'cros workon --board=$BOARD %s %s failed. ' %
+                (action, package) + 'further steps skipped.')
+            return False
+        return True
+
+    def _build_packages(
+            self,
+            params=[],
+    ):
+        """
+        Runs build_packages, and update state.
+
+        Return True on sucess, False otherwise.
+
+        Args:
+            params: extra params for build_packages command.
+        """
+        self.state.update(self.board, 'build_packages')
+
+        proc = subprocess.Popen([
+            'cros',
+            'build-packages',
+            '--board',
+            self.board,
+            '--withdev',
+            '--skip-setup-board',
+        ] + params,
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.STDOUT)
+        log = []
+        for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
+            log.append(line)
+            line = line.strip()
+            if line:
+                self.state.update(self.board, 'build_packages', line)
+        proc.wait()
+
+        if proc.returncode != 0:
+            # Only write log at build_packages failure
+            with open(os.path.join(self.log_dir, 'build_packages'), 'w') as f:
+                f.writelines(log)
+            self.state.update(self.board, 'failed',
+                              'build_packages failed. further steps skipped.')
+            return False
+        # Ensure build_packages deleted on success without error handling.
+        shutil.rmtree(os.path.join(self.log_dir, 'build_packages'),
+                      ignore_errors=True)
+        return True
+
+    def _emerge_blocking(self,
+                         package,
+                         out=subprocess.DEVNULL,
+                         update_state=True):
+        """
+        Emerges a package, and update state.
+        Run unittests (prepending FEATURES=test) if user requested. Note
+        packages without test will be emerged normally.
+
+        Returns True on sucess, False otherwise.
+
+        Args:
+            package: package to emerge.
+        """
+        if update_state:
+            self.state.update(self.board, 'emerge_' + package)
+        env = dict(os.environ)
+        if self.run_unittest:
+            env['FEATURES'] = 'test'
+        proc = subprocess.run(
+            ['emerge-' + self.board, package],
+            stdout=out,
+            stderr=out,
+            env=env,
+        )
+        if proc.returncode != 0:
+            if update_state:
+                self.state.update(
+                    self.board, 'failed',
+                    ('FEATURES=test ' if self.run_unittest else '') +
+                    'emerge-$BOARD ' + package +
+                    ' failed. further steps skipped.')
+            return False
+        if update_state:
+            self.state.update(self.board, 'emerge_' + package,
+                              ('FEATURES=test ' if self.run_unittest else '') +
+                              'emerge-$BOARD ' + package + ' completed.')
+        return True
+
+    def _build_dependency_graph(self, packages):
+        """
+        Builds dependency graph between packages
+
+        Returns a dict from packages to list of dependencies.
+
+        Args:
+            packages: packages to build dependency graph.
+        """
+        depended_by = dict((p, self._list_depended_by(p)) for p in packages)
+        dependency_graph = collections.defaultdict(list)
+        for p, depend_on_p_packages in depended_by.items():
+            for depend_on_p in depend_on_p_packages:
+                if depend_on_p in packages:
+                    dependency_graph[depend_on_p].append(p)
+        return dependency_graph
+
+    def _list_depended_by(self, package):
+        """
+        Lists packages depended by <package>.
+
+        Returns a list of packages.
+
+        Args:
+            package: package to check.
+        """
+        self.state.update(self.board, 'enumerate_dependencies',
+                          'Enumerating packages depending on ' + package)
+        depended_by = []
+        version_remove_re = re.compile('(.*?)(-[0-9.]+)?(-r[0-9]+)?$')
+        proc = subprocess.Popen(['equery-' + self.board, 'd', package],
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.DEVNULL)
+        outs, _ = proc.communicate()
+        outs = outs.decode('utf-8').split('\n')
+        # Line format
+        # $group/$pkg-$ver-r$r (>=chromeos-base/libchrome-0.0.1-r$r:0/9999[cros-debug])
+        # Example:
+        # media-libs/cros-camera-v4l2_test-0.0.1-r399 (>=chromeos-base/libchrome-0.0.1-r117:0/9999[cros-debug])
+        for line in outs:
+            if not line:
+                continue
+            if line[0] == ' ':
+                continue
+            depended_by.append(
+                version_remove_re.match(line.split(' ')[0]).group(1))
+        return depended_by
+
+
+def handle_exception(board, state, stage):
+    """
+    Handles exception caused in future.
+
+    Returns a function to use as add_done_callback.
+
+    Args:
+        board: board name.
+        state: the global variable that stores per-board states.
+        stage: a stage name.
+    """
+
+    def _handle(future):
+        try:
+            future.result()
+        except Exception as e:
+            state.update(
+                board, 'bug',
+                "A bug occurred. Semephores may have not been released.\n" +
+                traceback.format_exc())
+
+    return _handle
+
+
+def already_failed(state, work):
+    """
+    Checks if work is already failed.
+
+    Args:
+        state: the global variable that stores per board states.
+        work: a CheckOneBoard instance.
+    """
+    return state.states[work.board] in ['bug', 'failed']
+
+
+def main():
+    assert os.getcwd(
+    ) == '/mnt/host/source/src/scripts', 'Please run under Chrome OS chroot ~/trunk/src/scripts'
+    parser = argparse.ArgumentParser(description='Build packages checker')
+    parser.add_argument('-b',
+                        '--boards',
+                        metavar='boards',
+                        action='append',
+                        type=str,
+                        help='Boards to check',
+                        required=True)
+    parser.add_argument('-d',
+                        '--output-directory',
+                        metavar='output_directory',
+                        type=str,
+                        help='Output directory of failed logs',
+                        required=True)
+    parser.add_argument('--allow-output-directory-exists',
+                        metavar='allow_output_directory_exists',
+                        action='store_const',
+                        help="Dont't error if output directory exists",
+                        const=True,
+                        default=False)
+    parser.add_argument('--unittest',
+                        metavar='unittest',
+                        action='store_const',
+                        help='Run unittest',
+                        const=True,
+                        default=False)
+    parser.add_argument('--skip-setup-board',
+                        metavar='skip_setup_board',
+                        help='Skip setup_board phase',
+                        action='store_const',
+                        const=True,
+                        default=False)
+    parser.add_argument('--skip-first-pass-build-packages',
+                        metavar='skip_first_pass_build_packages',
+                        help='Skip build_packages with stable libchrome',
+                        action='store_const',
+                        const=True,
+                        default=False)
+    parser.add_argument('--force-clean-buildroot',
+                        metavar='force_clean_buildroot',
+                        help='Force clean /build/$BOARD directory',
+                        action='store_const',
+                        const=True,
+                        default=False)
+    parser.add_argument('--max-build-packages',
+                        metavar='max_build_packages',
+                        help='Maximum parallization for build_packages',
+                        type=int)
+    parser.add_argument(
+        '--max-emerges',
+        metavar='max_emerges',
+        help=
+        'Maximum parallization for emerge(s). Default to %d (or %d when --unittest)'
+        % (_MAX_EMERGES_WITHOUT_UNITTEST, _MAX_EMERGES),
+        type=int)
+    parser.add_argument(
+        '-p',
+        '--cros-workon-packages',
+        metavar='cros_workon_packages',
+        help=
+        'Packages to use 9999 ebuild. A string of list of packages space-separated. Default to None (libchrome only).',
+        type=str,
+        default='')
+    parser.add_argument(
+        '--status-update-interval',
+        metavar='status_update_interval',
+        help='Interval for updating current status. every (f) seconds',
+        type=int,
+        default=1)
+
+    arg = parser.parse_args(sys.argv[1:])
+
+    max_build_packages = _MAX_BUILD_PACKAGES
+    if arg.max_build_packages:
+        max_build_packages = arg.max_build_packages
+
+    max_emerges = _MAX_EMERGES if arg.unittest else _MAX_EMERGES_WITHOUT_UNITTEST
+    if arg.max_emerges:
+        max_emerges = arg.max_emerges
+
+    if arg.skip_first_pass_build_packages:
+        assert arg.skip_setup_board, '--skip-setup-board must be set for --skip-first-pass-build-packages'
+    if arg.force_clean_buildroot:
+        assert not arg.skip_setup_board, '--skip-setup-board cannot be set for --force-clean-buildroot'
+        assert not arg.skip_first_pass_build_packages, '--skip-first-pass-build-packages cannot be set for --force-clean-buildroot'
+
+    boards = []
+    for board in arg.boards:
+        if board in BOARDS_MAPPING:
+            boards += BOARDS_MAPPING[board]
+        else:
+            boards.append(board)
+
+    state = State(arg.status_update_interval)
+
+    os.makedirs(arg.output_directory,
+                exist_ok=arg.allow_output_directory_exists)
+
+    if arg.force_clean_buildroot:
+        subprocess.check_output(
+            ['sudo', 'rm', '-rf'] +
+            [os.path.join('/build', board) for board in boards])
+
+    work_list = []
+    for board in boards:
+        log_dir = os.path.join(arg.output_directory, 'by-board', board)
+        os.makedirs(log_dir, exist_ok=arg.allow_output_directory_exists)
+        work = CheckOneBoard(board, state, log_dir, arg.unittest)
+        work_list.append(work)
+
+    state.start()
+
+    if not arg.skip_setup_board:
+        with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
+            for work in work_list:
+                if already_failed(state, work):
+                    continue
+                task = executor.submit(work.setup_board)
+                task.add_done_callback(
+                    handle_exception(work.board, state, 'setup_board'))
+
+    if arg.cros_workon_packages:
+        with concurrent.futures.ThreadPoolExecutor(
+                max_workers=max_build_packages) as executor:
+            for work in work_list:
+                task = executor.submit(work.cros_workon_start,
+                                       arg.cros_workon_packages)
+
+    if not arg.skip_first_pass_build_packages:
+        with concurrent.futures.ThreadPoolExecutor(
+                max_workers=max_build_packages) as executor:
+            for work in work_list:
+                if already_failed(state, work):
+                    continue
+                state.update(work.board, 'waiting',
+                             'waiting for build_packages to start.')
+                task = executor.submit(work.build_packages)
+                task.add_done_callback(
+                    handle_exception(work.board, state, 'build_packages'))
+
+    with concurrent.futures.ThreadPoolExecutor(
+            max_workers=max_emerges) as executor:
+        for work in work_list:
+            if already_failed(state, work):
+                continue
+            state.update(work.board, 'waiting',
+                         'waiting for emerge_libchrome to start.')
+            task = executor.submit(work.emerge_libchrome)
+            task.add_done_callback(
+                handle_exception(work.board, state, 'emerge_libchrome'))
+
+    with concurrent.futures.ThreadPoolExecutor(
+            max_workers=max_emerges) as executor:
+        for work in work_list:
+            if already_failed(state, work):
+                continue
+            task = executor.submit(work.build_dependency_graph)
+            task.add_done_callback(
+                handle_exception(work.board, state, 'enumerate_dependencies'))
+
+    with concurrent.futures.ThreadPoolExecutor(
+            max_workers=max_emerges) as executor:
+        unfinished_emerges = set()
+        while True:
+            if unfinished_emerges:
+                done, not_done = concurrent.futures.wait(
+                    unfinished_emerges,
+                    return_when=concurrent.futures.FIRST_COMPLETED)
+                unfinished_emerges = not_done
+
+            for work in work_list:
+                if already_failed(state, work):
+                    continue
+                for package in work.buildable_packages():
+                    work.set_emerge_scheduled(package)
+                    task = executor.submit(work.emerge, package)
+                    task.add_done_callback(
+                        work.handle_emerge_result_fn(package))
+                    unfinished_emerges.add(task)
+
+            if not unfinished_emerges:
+                break
+
+    for work in work_list:
+        if already_failed(state, work):
+            state.set_failed(work.board, set(['SYSTEM']))
+        else:
+            state.set_failed(work.board, work.failed_emerge)
+
+    state.stop()
+    state.join()
+    state.print()
+
+    if state.failed:
+        for board, packages in state.failed.items():
+            for package in packages:
+                # SYSTEM is a placeholder pacakge indicating something wrong
+                # with this checker when running task for some board.
+                # SYSTEM placeholder package doesn't have any fail log to copy.
+                # Skipping.
+                if package == 'SYSTEM':
+                    continue
+                os.makedirs(os.path.join(arg.output_directory, 'by-packages',
+                                         package),
+                            exist_ok=True)
+                shutil.copy(
+                    os.path.join(arg.output_directory, 'by-board', board,
+                                 package, 'emerge_log'),
+                    os.path.join(arg.output_directory, 'by-packages', package,
+                                 board))
+        print(state.failed_matrix(delimiter='     '))
+        with open(os.path.join(arg.output_directory, 'matrix.txt'), 'w') as f:
+            f.write(state.failed_matrix(delimiter='     '))
+        with open(os.path.join(arg.output_directory, 'matrix.csv'), 'w') as f:
+            f.write(state.failed_matrix(delimiter=','))
+
+    print("Completed. See logs at ", arg.output_directory)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/libchrome_tools/developer-tools/presubmit/check-libchrome.py b/libchrome_tools/developer-tools/presubmit/check-libchrome.py
new file mode 100755
index 0000000..d8c4b20
--- /dev/null
+++ b/libchrome_tools/developer-tools/presubmit/check-libchrome.py
@@ -0,0 +1,145 @@
+#!/usr/bin/env python3
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+Utility to check if deprecated libchrome calls are introduced.
+"""
+
+from __future__ import print_function
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+
+# BAD_KEYWORDS are mapping from bad_keyword_in_regex to
+# error_msg_if_match_found.
+BAD_KEYWORDS = {
+    # removal of deprecated base::Bind APIs
+    r'base::(Bind|Closure|Callback|CancelableCallback|CancelableClosure)(\(|<)':
+    'Deprecated base::Bind APIs. Please use the Once or Repeating variants. See crbug/714018.',
+    # unify *::optionals to std::optional
+    r'(include.*absl/types/optional.h|absl::(optional|make_optional|nullopt))':
+    'Use std::optional. absl::optional is an alias of std::optional. See go/use-std-optional-in-cros for discussion.',
+    # Migrate base::Delete* to brillo::Delete* to fix security bugs
+    r'base::Delete(File|PathRecursively)\(':
+    'Deprecated base::Delete* APIs. Use brillo::Delete* instead. See b/272503861',
+    # removal of deprecated base::ThreadLocal(Pointer|Boolean) APIs
+    r'base::(ThreadLocalBoolean|ThreadLocalPointer)':
+    'Use `thread_local bool|T*` instead. See https://chromium.googlesource.com/chromium/src/+/main/styleguide/c++/c++.md#thread_local-variables for discussion. (b/274724518)',
+    # base::StringPiece will be deprecated and replaced by std:string_view.
+    r'(include.*base/strings/string_piece.h|base::StringPiece)':
+    'Use the now equivalent std::string_view (crrev.com/c/4294483). See upstream bug crbug.com/691162 for details.',
+    # UMA_HISTOGRAM macros send their metrics into the void on CrOS.
+    r'UMA_(?:STABILITY_){0,1}HISTOGRAM[_A-Z0-9]*\(': 'Chromium UMA macros don\'t work on CrOS. See crsrc.org/o/src/platform2/metrics/metrics_library.h if you want to collect metrics on CrOS.',
+    # UmaHistogram functions send their metrics into the void on CrOS.
+    r'(?:base::){0,1}UmaHistogram[a-zA-Z0-9]*\(': 'Chromium UmaHistogram functions don\'t work on CrOS. See crsrc.org/o/src/platform2/metrics/metrics_library.h if you want to collect metrics on CrOS.',
+    # base::SupportsWeakPtr will be deprecated
+    r'base::SupportsWeakPtr': 'Deprecated base::SupportsWeakPtr.  See crbug.com/40485134 for details.',
+    # base::WriteFile (3-arg version) is deprecated
+    r'base::WriteFile\(.*,.*,.*\)': '3-arg version of base::WriteFile is deprecated - please use 2-arg version.  See crbug.com/41134632 for details.',
+    r'NOTREACHED_IN_MIGRATION\(':
+    'CrOS libchrome NOTREACHED migration, do NOT use NOTREACHED_IN_MIGRATION. Use NOTREACHED which is now fatal and [[noreturn]]. See b/356312475',
+    r'HistogramBase::Sample[^3]': 'base::HistogramBase::Sample is deprecated. Use base::HistogramBase::Sample32.',
+}
+
+LINE_NUMBER_RE=re.compile(r'^@@ [0-9\,\+\-]+ \+([0-9]+)[ \,][0-9 ]*@@')
+
+def addedLinesFromCommit(filename, commit):
+  '''Return list of (line number, line) pairs added to file by the given commit.
+  '''
+  diff = subprocess.check_output(
+      ['git', 'show', '--oneline', commit, '--', filename]).decode(
+          sys.stdout.encoding).split('\n')
+  line_number = -1
+  lines = []
+  for line in diff:
+    m = LINE_NUMBER_RE.match(line)
+    if m:
+      line_number = int(m.groups(1)[0])-1
+      continue
+    if not line.startswith('-'):
+      line_number += 1
+    if line.startswith('+++') or not line.startswith('+'):
+      continue
+    lines.append((line_number, line[1:]))
+
+  return lines
+
+def checkFileLines(filename, lines, keywords):
+  '''Check for forbidden patterns in given lines of a file.
+
+  Args:
+    filename: of the source file.
+    lines: a list of (line number, line) pairs to be checked.
+    keywords: a list of (regex, description) pairs of forbidden patterns
+
+  Returns:
+    A list of error messages reporting forbidden patterns found.
+  '''
+  errors = []
+  for line_number, line in lines:
+    for bad_pattern, error_message in keywords.items():
+      m = re.search(bad_pattern, line)
+      if m:
+        errors.append('In File %s line %s col %s, found %s (pattern: %s), %s' %
+                      (filename, line_number, m.span()[0]+1, m.group(0),
+                       bad_pattern, error_message))
+        break
+
+  return errors
+
+
+def checkFiles(files, commit, keywords=BAD_KEYWORDS):
+  '''Check for forbidden patterns from given list of files.
+
+  Args:
+    files: a list of filenames.
+    commit: hash of a commit. If given, only lines added to this commit will be
+    checked; otherwise check all lines.
+    keywords: a list of (regex, description) pairs of forbidden patterns
+
+  Returns:
+    A list of error messages reporting forbidden patterns found.
+  '''
+  errors = []
+
+  for filename in files:
+    if not (filename.endswith('.h') or filename.endswith('.cc')):
+        continue
+    if commit:
+      lines = addedLinesFromCommit(filename, commit)
+    else:
+      with open(filename) as f:
+        lines = [(i+1, line) for i, line in enumerate(f.readlines())]
+    errors += checkFileLines(filename, lines, keywords)
+
+  return errors
+
+
+def main():
+  parser = argparse.ArgumentParser(
+      description='Check no forbidden libchrome features are used.')
+
+  parser.add_argument('--commit',
+                      help='Hash of commit to check. Only show errors on ' \
+                           'lines added in the commit if set.')
+  parser.add_argument('files', nargs='*')
+  args = parser.parse_args()
+
+  errors = checkFiles(args.files, args.commit)
+
+  if errors:
+      print('\n'.join(errors), file=sys.stderr)
+      print('\n**Note the regex checks can sometimes return false positives, ' \
+            'for example the base::WriteFile\(.*,.*,.*\) check fails if the ' \
+            'second arg has a string_view ctor that contains a comma.  If ' \
+            'you are certain you didn\'t use deprecated APIs, --no-verify ' \
+            'may be appropriate.', file=sys.stderr)
+      sys.exit(1)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/libchrome_tools/developer-tools/presubmit/check-patches.py b/libchrome_tools/developer-tools/presubmit/check-patches.py
new file mode 100755
index 0000000..0c51084
--- /dev/null
+++ b/libchrome_tools/developer-tools/presubmit/check-patches.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python3
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+Utility to check if libchrome_tools/patches/patches follow the convention.
+"""
+
+from __future__ import print_function
+
+import argparse
+import os
+import re
+import subprocess
+import sys
+
+ORIGINAL_COMMIT_RE = re.compile(r'"CrOS-Libchrome-Original-Commit: (\w+)\n"')
+
+PATCH_NAME_RE = re.compile(r'(long-term|cherry-pick|backward-compatibility|forward-compatibility)-[0-9]{4}-(.+)\.\w+')
+
+def isUpstreamCommit(commit):
+    '''Check if this is a commit from cros/upstream.
+    '''
+    output = subprocess.check_output(
+        ['git', 'log', commit, '-n1',
+         '--pretty="%(trailers:key=CrOS-Libchrome-Original-Commit)"'],
+        universal_newlines=True,
+    ).strip()
+
+    # libchrome non-upstream commit will return non-empty string '""' as output.
+    m = ORIGINAL_COMMIT_RE.match(output)
+
+    if m:
+      return True
+    return False
+
+
+def getPatchesForChecking(commit = None):
+    '''Return list of patches for checking.
+
+    Args:
+      commit: hash of a commit. If given, only patches added to this commit will
+      be checked
+
+    Returns:
+      A list of patches in their basename.
+    '''
+    patches = []
+    if commit:
+      output = subprocess.check_output(
+          ['git', 'diff', '%s^' % (commit), commit, '--name-status'],
+      ).decode('utf-8').splitlines()
+      for line in output:
+        # The file is "A"dded or "R"enamed.
+        if line[0] == 'A' or line[0] == 'R':
+          filename = line.split()[-1]
+          if os.path.dirname(filename) == 'libchrome_tools/patches':
+            patches.append(os.path.basename(filename))
+    else:
+      patches = [f for f in os.listdir('libchrome_tools/patches')]
+
+    return [f for f in patches if (f != 'patches' and f!= 'patches.config')]
+
+
+def checkPatchesFileNameConvention(patches):
+    '''Check if patches follow the naming conventions.
+
+    Args:
+      patches: list of basename of patches to be checked.
+
+    Returns:
+      A list of error messages reporting bad patches settings.
+    '''
+    errors = []
+    for patch in patches:
+      print('checking "%s"'% patch)
+      m = PATCH_NAME_RE.match(patch)
+      if not m:
+        errors.append(
+            'Patch must in format type-dddd-name.ext, where '
+            'type is type of patch (one of long-term, cherry-pick, '
+            'backward compatibility, or forward compatibility), '
+            'and dddd is a four-digit patch number. Found %s.' % (patch))
+        continue
+
+      patch_type = m.group(1)
+      name = m.group(2)
+      if patch_type == 'cherry-pick':
+        if not re.match('^r[0-9]+-', name):
+          errors.append(
+              'Cherry pick patch name must include revision number of the '
+              'cherry-picked change, i.e. start with cherry-pick-dddd-rXXXX, '
+              'Found %s.' % (patch))
+
+    return errors
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description='Check libchrome patches in good shape.')
+
+    parser.add_argument('--commit',
+                        help='Hash of commit to check. Only show errors on ' \
+                             'lines added in the commit if set.')
+    parser.add_argument('files', nargs='*')
+
+    args = parser.parse_args(sys.argv)
+
+    if args.commit and isUpstreamCommit(args.commit):
+      sys.exit(0)
+
+    patches = getPatchesForChecking(args.commit)
+
+    errors = checkPatchesFileNameConvention(patches)
+
+    if errors:
+        print('\n'.join(errors), file=sys.stderr)
+        sys.exit(1)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/libchrome_tools/developer-tools/test_change_header.py b/libchrome_tools/developer-tools/test_change_header.py
new file mode 100755
index 0000000..fb3d569
--- /dev/null
+++ b/libchrome_tools/developer-tools/test_change_header.py
@@ -0,0 +1,560 @@
+#!/usr/bin/env python3
+# Copyright 2022 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import re
+import subprocess
+import tempfile
+import unittest
+from change_header import *
+
+class TestClassifyHeader(unittest.TestCase):
+    def test_is_system_header(self):
+        self.assertTrue(IsSystemHeader('<sys/time.h>'))
+        self.assertTrue(IsSystemHeader('<memory>'))
+
+        self.assertFalse(IsSystemHeader('"foo.h"'))
+
+    def test_is_c_system_header(self):
+        self.assertTrue(IsCSystemHeader('<unistd.h>'))
+
+        self.assertFalse(IsCSystemHeader('<tuple>'))
+        self.assertFalse(IsCSystemHeader('"bar.h"'))
+
+    def test_is_cxx_system_header(self):
+        self.assertTrue(IsCXXSystemHeader('<optional>'))
+
+        self.assertFalse(IsCXXSystemHeader('<signal.h>'))
+        self.assertFalse(IsCXXSystemHeader('"baz.h"'))
+
+    def test_is_cros_header(self):
+        self.assertTrue(IsCrOSHeader('<base/macros.h>'))
+        self.assertTrue(
+            IsCrOSHeader('"base/strings/string_number_conversions.h"'))
+        self.assertTrue(IsCrOSHeader('<ipc/ipc.h>'))
+        self.assertTrue(IsCrOSHeader('<mojo/core/core.h>'))
+        self.assertTrue(IsCrOSHeader('"dbus/message.h"'))
+        self.assertTrue(IsCrOSHeader('"gtest/gtest.h"'))
+        self.assertTrue(
+            IsCrOSHeader('"brillo/dbus/exported_object_manager.h"'))
+
+        self.assertFalse(IsCrOSHeader('<stdlib.h>'))
+        self.assertFalse(IsCrOSHeader('<utility>'))
+
+    def test_is_decorated_true(self):
+        self.assertTrue(IsDecorated('<foo>'))
+        self.assertTrue(IsDecorated('<foo.h>'))
+        self.assertTrue(IsDecorated('"foo.h"'))
+
+        self.assertFalse(IsDecorated('foo.h'))
+        self.assertFalse(IsDecorated('foo'))
+        self.assertFalse(IsDecorated('"foo.h'))
+        self.assertFalse(IsDecorated('foo.h"'))
+        self.assertFalse(IsDecorated('<foo.h"'))
+        self.assertFalse(IsDecorated('foo.h>'))
+
+    def test_classify_header(self):
+        self.assertEqual(ClassifyHeader('<sys/socket.h>'),
+                         HEADER_TYPE_C_SYSTEM)
+        self.assertEqual(ClassifyHeader('<iostream>'), HEADER_TYPE_CXX_SYSTEM)
+        self.assertEqual(ClassifyHeader('<base/notrrached.h>'),
+                         HEADER_TYPE_CROS)
+        self.assertEqual(ClassifyHeader('"base/logging.h"'), HEADER_TYPE_CROS)
+        self.assertEqual(
+            ClassifyHeader('<mojo/core/embedder/scoped_ipc_support.h>'),
+            HEADER_TYPE_CROS)
+        self.assertEqual(ClassifyHeader('<dbus/object_proxy.h>'),
+                         HEADER_TYPE_CROS)
+        self.assertEqual(ClassifyHeader('"brillo/variant_dictionary.h"'),
+                         HEADER_TYPE_CROS)
+        self.assertEqual(ClassifyHeader('"vm_tools/vsh/scoped_termios.h"'),
+                         HEADER_TYPE_USER)
+
+    def test_is_primary_include(self):
+        # when called in repository root, e.g. platform2/
+        self.assertTrue(
+            IsPrimaryInclude('"vm_tools/vsh/vsh_client.h"',
+                             "vm_tools/vsh/vsh_client.cc"))
+        # when called in inidividual package directory, e.g. vm_tools/
+        self.assertTrue(
+            IsPrimaryInclude('"vm_tools/vsh/vsh_client.h"',
+                             "vsh/vsh_client.cc"))
+
+        self.assertFalse(
+            IsPrimaryInclude('"vm_tools/vsh/vsh_client.h"',
+                             "vm_toost/vsh/vsh.cc"))
+        self.assertFalse(
+            IsPrimaryInclude('"vm_tools/vsh/vsh_client.h"',
+                             "vm_toost/vsh/vsh.h"))
+        self.assertFalse(
+            IsPrimaryInclude('"vm_tools/vsh/vsh.cc"',
+                             "vm_toost/vsh/vsh_client.h"))
+        self.assertFalse(
+            IsPrimaryInclude('"vm_tools/vsh/vsh.cc"',
+                             "vm_toost/vsh/vsh_client.h"))
+
+
+class TestRegularExpressions(unittest.TestCase):
+    def test_empty_line(self):
+        self.assertTrue(EMPTY_LINE_RE.match(''))
+
+        self.assertFalse(EMPTY_LINE_RE.match('foo'))
+        self.assertFalse(EMPTY_LINE_RE.match('// foo'))
+
+    def test_comment(self):
+        m = COMMENT_RE.match('/* foo')
+        self.assertTrue(m)
+        self.assertEqual(m.group(1), '/*')
+
+        m = COMMENT_RE.match('/* foo */')
+        self.assertTrue(m)
+        self.assertEqual(m.group(1), '/*')
+
+        m = COMMENT_RE.match('// foo')
+        self.assertTrue(m)
+        self.assertEqual(m.group(1), '//')
+
+        self.assertFalse(COMMENT_RE.match(' * foo'))
+        self.assertFalse(COMMENT_RE.match(' * foo */'))
+        self.assertFalse(COMMENT_RE.match('#include <vector>'))
+        self.assertFalse(COMMENT_RE.match(''))
+        self.assertFalse(COMMENT_RE.match('namespace base {'))
+
+    def test_comment_end(self):
+        self.assertTrue(COMMENT_END_RE.match('/* foo */'))
+        self.assertTrue(COMMENT_END_RE.match(' * foo */'))
+
+        self.assertFalse(COMMENT_END_RE.match('/* foo'))
+        self.assertFalse(COMMENT_END_RE.match('// foo'))
+        self.assertFalse(COMMENT_RE.match('#include <vector>'))
+        self.assertFalse(COMMENT_RE.match(''))
+        self.assertFalse(COMMENT_RE.match('namespace base {'))
+
+    def test_include(self):
+        self.assertTrue(INCLUDE_RE.match('#include <vector>'))
+        self.assertTrue(INCLUDE_RE.match('#include <time.h>'))
+        self.assertTrue(INCLUDE_RE.match('#include "base/time/time.h"'))
+
+        self.assertFalse(INCLUDE_RE.match('// #include <vector>'))
+        self.assertFalse(INCLUDE_RE.match('using ::testing::_;'))
+        self.assertFalse(INCLUDE_RE.match('class Foo {'))
+
+    def test_macro(self):
+        self.assertTrue(MACRO_RE.match('#include <vector>'))
+        self.assertTrue(MACRO_RE.match('#ifdef __GNUG'))
+        self.assertTrue(
+            MACRO_RE.match('#define TRUNKS_SCOPED_GLOBAL_SESSION_H_'))
+        self.assertTrue(MACRO_RE.match('#if BASE_VER > 12345'))
+        self.assertTrue(MACRO_RE.match('#endif'))
+
+        self.assertFalse(MACRO_RE.match('// #include <vector>'))
+        self.assertFalse(MACRO_RE.match('using ::testing::_;'))
+        self.assertFalse(MACRO_RE.match('class Foo {'))
+
+    def test_extern(self):
+        self.assertTrue(EXTERN_C_RE.match('extern "C" {'))
+
+        self.assertFalse(EXTERN_C_RE.match('// extern "C" {'))
+        self.assertFalse(EXTERN_C_RE.match('extern "C"'))
+        self.assertFalse(EXTERN_C_RE.match('#include <vector>'))
+
+    def test_extern_end(self):
+        self.assertTrue(EXTERN_C_END_RE.match('}'))
+        self.assertTrue(EXTERN_C_END_RE.match('  }'))
+        self.assertTrue(EXTERN_C_END_RE.match('}  // Comment'))
+
+        self.assertFalse(EXTERN_C_RE.match('#include <vector>'))
+        self.assertFalse(EXTERN_C_END_RE.match('// }'))
+
+class TestIsCommentThisAndNext(unittest.TestCase):
+    def test_not_comment(self):
+        is_comment, in_comment_block = IsCommentThisAndNext(
+            '#include "foo.h"', False)
+        self.assertFalse(is_comment)
+        self.assertFalse(in_comment_block)
+
+    def test_comment_line(self):
+        is_comment, in_comment_block = IsCommentThisAndNext('// foo', False)
+        self.assertTrue(is_comment)
+        self.assertFalse(in_comment_block)
+
+        is_comment, in_comment_block = IsCommentThisAndNext('// foo', True)
+        self.assertTrue(is_comment)
+        self.assertTrue(in_comment_block)
+
+    def test_comment_block_start(self):
+        is_comment, in_comment_block = IsCommentThisAndNext('/* foo', False)
+        self.assertTrue(is_comment)
+        self.assertTrue(in_comment_block)
+
+        is_comment, in_comment_block = IsCommentThisAndNext('/* foo', True)
+        self.assertTrue(is_comment)
+        self.assertTrue(in_comment_block)
+
+    def test_comment_block_middle(self):
+        is_comment, in_comment_block = IsCommentThisAndNext(' public:', True)
+        self.assertTrue(is_comment)
+        self.assertTrue(in_comment_block)
+
+    def test_comment_block_end(self):
+        is_comment, in_comment_block = IsCommentThisAndNext(' * foo */', True)
+        self.assertTrue(is_comment)
+        self.assertFalse(in_comment_block)
+
+    def test_comment_block_single_line(self):
+        is_comment, in_comment_block = IsCommentThisAndNext('/* foo */', False)
+        self.assertTrue(is_comment)
+        self.assertFalse(in_comment_block)
+
+
+class TestCommandArguments(unittest.TestCase):
+    def test_not_one_operation(self):
+        output = subprocess.run('./change_header.py'.split(),
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+
+        output = subprocess.run(
+            './change_header.py --add foo --remove bar'.split(),
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+        self.assertIn('not allowed with argument', str(output.stderr))
+
+    def test_missing_header_param(self):
+        output = subprocess.run('./change_header.py --add'.split(),
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+        self.assertIn('--add: expected one argument', str(output.stderr))
+        output = subprocess.run('./change_header.py --remove'.split(),
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+        self.assertIn('--remove: expected one argument', str(output.stderr))
+        output = subprocess.run('./change_header.py --replace'.split(),
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+        self.assertIn('--replace: expected 2 arguments', str(output.stderr))
+        output = subprocess.run('./change_header.py --replace foo'.split(),
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+        self.assertIn('--replace: expected 2 arguments', str(output.stderr))
+
+    def test_missing_file(self):
+        output = subprocess.run('./change_header.py --add foo'.split(),
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+        self.assertIn('the following arguments are required: files',
+                      str(output.stderr))
+        output = subprocess.run('./change_header.py --remove foo'.split(),
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+        self.assertIn('the following arguments are required: files',
+                      str(output.stderr))
+        output = subprocess.run('./change_header.py --replace foo bar'.split(),
+                                stdout=subprocess.PIPE,
+                                stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+        self.assertIn('the following arguments are required: files',
+                      str(output.stderr))
+
+    def test_unknown_verbosity(self):
+        output = subprocess.run(
+            './change_header.py --add foo --verbosity info bar.cc'.split(),
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE)
+        self.assertNotEqual(output.returncode, 0)
+        self.assertIn(
+            'Verbosity level should be one of DEBUG, INFO, WARNING, ERROR',
+            str(output.stderr))
+
+
+class TestRemoveHeader(unittest.TestCase):
+    def setUp(self):
+        self.filename = '../testdata/change_header_test.cc'
+        with open(self.filename, 'r') as f:
+            self.source = f.read().splitlines()
+
+    def test_remove_header_not_there(self):
+        header = '<utility>'
+        source, removed_header, _ = RemoveHeaderFromSource(self.source, header)
+        self.assertIsNone(source)
+        self.assertIsNone(removed_header)
+
+    def test_remove_header_different_decorator(self):
+        header = 'base/logging.h'
+        quote_header = '"' + header + '"'
+        arrow_header = '<' + header + '>'
+        expected_source = self.source.copy()
+        del expected_source[expected_source.index(f'#include {arrow_header}')]
+
+        source, removed_header, _ = RemoveHeaderFromSource(
+            self.source, quote_header)
+        self.assertIsNotNone(source)
+        self.assertIsNotNone(removed_header)
+
+        self.assertEqual(source, expected_source)
+        self.assertEqual(arrow_header, removed_header)
+
+    def test_remove_header_same_decorator(self):
+        header = '<base/strings/string_util.h>'
+        expected_source = self.source.copy()
+        del expected_source[expected_source.index(f'#include {header}')]
+
+        source, removed_header, _ = RemoveHeaderFromSource(self.source, header)
+        self.assertIsNotNone(source)
+        self.assertIsNotNone(removed_header)
+
+        self.assertEqual(source, expected_source)
+        self.assertEqual(header, removed_header)
+
+    def test_remove_header_any_decorator(self):
+        header = 'brillo/flag_helper.h'
+        expected_source = self.source.copy()
+        del expected_source[expected_source.index(f'#include <{header}>')]
+
+        source, removed_header, _ = RemoveHeaderFromSource(self.source, header)
+        self.assertIsNotNone(source)
+        self.assertIsNotNone(removed_header)
+
+        self.assertEqual(source, expected_source)
+        self.assertEqual(f'<{header}>', removed_header)
+
+    def test_remove_header_with_line_break(self):
+        header = '<memory>'
+        expected_source = self.source.copy()
+        idx = expected_source.index(f'#include {header}')
+        del expected_source[idx]
+        del expected_source[idx]
+
+        source, removed_header, _ = RemoveHeaderFromSource(self.source, header)
+        self.assertIsNotNone(source)
+        self.assertIsNotNone(removed_header)
+
+        self.assertEqual(source, expected_source)
+        self.assertEqual(header, removed_header)
+
+    def test_remove_header_in_extern_c(self):
+        header = '<vboot/vboot_host.h>'
+        expected_source = self.source.copy()
+        idx = expected_source.index(f'#include {header}')
+        del expected_source[idx]
+
+        source, removed_header, _ = RemoveHeaderFromSource(self.source, header)
+        self.assertIsNotNone(source)
+        self.assertIsNotNone(removed_header)
+
+        self.assertEqual(source, expected_source)
+        self.assertEqual(header, removed_header)
+
+class TestAddHeader(unittest.TestCase):
+    def setUp(self):
+        self.filename = '../testdata/change_header_test.cc'
+        with open(self.filename, 'r') as f:
+            self.source = f.read().splitlines()
+
+    def test_add_c_system_header_new_block(self):
+        header = '<stdio.h>'
+        expected_source = self.source.copy()
+        expected_source.insert(5, f'#include {header}')
+        expected_source.insert(5, f'')
+
+        source = AddHeaderToSource(os.path.normpath(self.filename),
+                                   self.source, header, ClassifyHeader(header))
+
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_add_cpp_system_header(self):
+        header = '<utility>'
+        expected_source = self.source.copy()
+        expected_source.insert(7, f'#include {header}')
+
+        source = AddHeaderToSource(os.path.normpath(self.filename),
+                                   self.source, header, ClassifyHeader(header))
+
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_add_libchrome_header(self):
+        header = '<base/check.h>'
+        expected_source = self.source.copy()
+        expected_source.insert(12, f'#include {header}')
+
+        source = AddHeaderToSource(os.path.normpath(self.filename),
+                                   self.source, header, ClassifyHeader(header))
+
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_add_header_already_there(self):
+        header = '<base/strings/string_number_conversions.h>'
+
+        source = AddHeaderToSource(os.path.normpath(self.filename),
+                                   self.source, header, ClassifyHeader(header))
+
+        self.assertIsNone(source)
+
+
+class TestReplaceHeader(unittest.TestCase):
+    def setUp(self):
+        self.filename = '../testdata/change_header_test.cc'
+        with open(self.filename, 'r') as f:
+            self.source = f.read().splitlines()
+
+    def test_old_header_does_not_exist(self):
+        new_header = '<base/foo.h>'
+        old_header = '<base/bar.h>'
+        source = ReplaceHeader(self.source, old_header, new_header, True,
+                               os.path.normpath(self.filename))
+        self.assertIsNone(source)
+
+    def test_new_header_exists(self):
+        new_header = '<base/strings/string_number_conversions.h>'
+        old_header = '<base/strings/string_util.h>'
+
+        expected_source = self.source.copy()
+        idx = expected_source.index(f'#include {old_header}')
+        del expected_source[idx]
+
+        source = ReplaceHeader(self.source, old_header, new_header, True,
+                               os.path.normpath(self.filename))
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_old_header_in_extern_c(self):
+        new_header = '<base/foo.h>'
+        old_header = '<vboot/vboot_host.h>'
+
+        expected_source = self.source.copy()
+        expected_source.insert(12, f'#include {new_header}')
+        idx = expected_source.index(f'#include {old_header}')
+        del expected_source[idx]
+
+        source = ReplaceHeader(self.source, old_header, new_header, True,
+                               os.path.normpath(self.filename))
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_replace_header_with_decorator(self):
+        new_header = '"base/foo.h"'
+        old_header = '<base/logging.h>'
+
+        expected_source = self.source.copy()
+        idx = expected_source.index(f'#include {old_header}')
+        expected_source[idx] = '#include {}'.format(new_header)
+
+        source = ReplaceHeader(self.source, old_header, new_header, False,
+                               os.path.normpath(self.filename))
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_change_decorator_to_match(self):
+        new_header = '"base/foo.h"'
+        old_header = '<base/logging.h>'
+
+        expected_source = self.source.copy()
+        idx = expected_source.index(f'#include {old_header}')
+        expected_source[idx] = '#include <{}>'.format(new_header[1:-1])
+
+        source = ReplaceHeader(self.source, old_header, new_header, True,
+                               os.path.normpath(self.filename))
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_replace_with_comment(self):
+        comment = ' // for base::Foo'
+        new_header = '<base/foo.h>'
+        old_header = '<base/logging.h>'
+
+        idx = self.source.index(f'#include {old_header}')
+        self.source[idx] = self.source[idx] + comment
+
+        expected_source = self.source.copy()
+        expected_source[idx] = '#include {}{}'.format(new_header, comment)
+
+        source = ReplaceHeader(self.source, old_header, new_header, True,
+                               os.path.normpath(self.filename))
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+
+class TestReplaceHeaderMinimum(unittest.TestCase):
+    def setUp(self):
+        self.filename = '../testdata/change_header_test.cc'
+        with open(self.filename, 'r') as f:
+            self.source = f.read().splitlines()
+
+    def test_old_header_does_not_exist(self):
+        new_header = '<base/foo.h>'
+        old_header = '<base/bar.h>'
+        source = ReplaceHeaderWithMinimumSorting(self.source, old_header,
+                                                 new_header, 'base/', True)
+        self.assertIsNone(source)
+
+    def test_new_header_exists(self):
+        new_header = '<base/strings/string_number_conversions.h>'
+        old_header = '<base/strings/string_util.h>'
+
+        expected_source = self.source.copy()
+        idx = expected_source.index(f'#include {old_header}')
+        del expected_source[idx]
+
+        source = ReplaceHeaderWithMinimumSorting(self.source, old_header,
+                                                 new_header, 'base/', True)
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_old_header_in_extern_c(self):
+        new_header = '<foo.h>'
+        old_header = '<vboot/vboot_host.h>'
+
+        expected_source = self.source.copy()
+        idx = expected_source.index(f'#include {old_header}')
+        expected_source[idx] = f'#include {new_header}'
+
+        source = ReplaceHeaderWithMinimumSorting(self.source, old_header,
+                                                 new_header, 'base/', True)
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_change_decorator_to_match(self):
+        new_header = '"base/foo.h"'
+        old_header = '<base/logging.h>'
+
+        expected_source = self.source.copy()
+        idx = expected_source.index(f'#include {old_header}')
+        expected_source[idx] = '#include <{}>'.format(new_header[1:-1])
+
+        source = ReplaceHeaderWithMinimumSorting(self.source, old_header,
+                                                 new_header, 'base/', True)
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+    def test_sort_matching_prefix_block_only(self):
+        new_header = '<base/foo.h>'
+        old_header = '<base/logging.h>'
+
+        # Remove the empty line between system and libchrome headers.
+        idx = self.source.index(f'#include <memory>')
+        del self.source[idx + 1]
+
+        expected_source = self.source.copy()
+        idx = expected_source.index(f'#include {old_header}')
+        expected_source[idx] = '#include {}'.format(new_header)
+
+        source = ReplaceHeaderWithMinimumSorting(self.source, old_header,
+                                                 new_header, 'base/', True)
+        self.assertIsNotNone(source)
+        self.assertEqual(source, expected_source)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/libchrome_tools/developer-tools/uprev/automated_uprev.py b/libchrome_tools/developer-tools/uprev/automated_uprev.py
new file mode 100755
index 0000000..99755c4
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/automated_uprev.py
@@ -0,0 +1,868 @@
+#!/usr/bin/env python3
+# Copyright 2022 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Script to generate and upload libchrome uprev commit.
+
+Given uprev target, generate the uprev commit and upload to gerrit for review.
+
+This should be run inside chroot (for emerge command) from
+CHROMIUM_SRC/src/platform/libchrome/ directory.
+
+For a typical automated daily uprev to cros/upstream HEAD (run locally):
+  libchrome_tools/developer-tools/uprev/automated_uprev.py
+This is equivalent to:
+  libchrome_tools/developer-tools/uprev/automated_uprev.py --head
+
+Provide the hash of target commit directly:
+  libchrome_tools/developer-tools/uprev/automated_uprev.py --hash <hash>
+
+For incremental uprev, use:
+  libchrome_tools/developer-tools/uprev/automated_uprev.py --days <n>
+to uprev up to the commit submitted n days after current latest on tracked
+branch (default cros/main).
+Or provide the target date manually (anything git log takes as --before arg):
+  libchrome_tools/developer-tools/uprev/automated_uprev.py --datetime <datetime>
+Format could be e.g. "yyyy-MM-dd" or "yyyy-MM-dd'T'HH:mm:ssZ".
+
+For aid to manual uprev:
+  libchrome_tools/developer-tools/uprev/automated_uprev.py
+    --before_revision <revision target>
+If creating for local experiment on top of local (or remote) branch:
+  libchrome_tools/developer-tools/uprev/automated_uprev.py
+    --before_revision <revision target>
+    --track_branch <on-going uprev branch>
+Use --track_active option to find the most recent active uprev commit on gerrit:
+  libchrome_tools/developer-tools/uprev/automated_uprev.py
+    --before_revision <revision target>
+    --track_active
+Run with --no_upload option to skip uploading the created change to Gerrit.
+"""
+
+import argparse
+import datetime
+import logging
+import os
+import re
+import subprocess
+import sys
+import typing
+from pathlib import Path
+
+# Path to the libchrome dir.
+LIBCHROME_DIR = Path(__file__).resolve().parent.parent.parent.parent
+# Find chromite relative to $CHROMEOS_CHECKOUT/src/platform/libchrome/, so
+# go up four dirs. For importing following the chromite libraries.
+sys.path.insert(0, str(LIBCHROME_DIR.parent.parent.parent))
+
+# pylint: disable=wrong-import-position
+from chromite.lib import gerrit
+from chromite.lib import gob_util
+
+chromium_helper = gerrit.GetGerritHelper(gob="chromium", print_cmd=False)
+
+BASE_VER_FILE = "BASE_VER"
+BUILD_GN_FILE = "BUILD.gn"
+PATCHES_DIRECTORY = "libchrome_tools/patches"
+PATCHES_CONFIG_FILE = os.path.join(PATCHES_DIRECTORY, "patches.config")
+
+COMMIT_REVISION_RE = re.compile(
+    r"\s*Cr-Commit-Position: refs\/heads\/\w+@\{#([0-9]+)\}$"
+)
+PATCH_RE = re.compile(r"^.+\.patch$")
+SECTION_HEADER_RE = re.compile(r"^# ={5}=* .* ={5}=*$")
+CHERRY_PICK_PATCH_RE = re.compile(r"^cherry-pick-[0-9]{4}-r([0-9]+)-.+\.patch$")
+BUILD_GN_SOURCE_FILE_LINE_RE = re.compile(r"\s*([\"\'])(.*)\1,")
+EMERGE_LIBCHROME_LOG_FILE_RE = re.compile(r" \* Build log: (.+)")
+
+MergeResult = typing.NamedTuple(
+    "MergeResult", [("succeed", bool), ("message", typing.List[str])]
+)
+Commit = typing.NamedTuple("Commit", [("hash", str), ("revision", int)])
+GitMergeSummary = typing.NamedTuple(
+    "GitMergeSummary",
+    [("files_added", typing.List[str]), ("files_removed", typing.List[str])],
+)
+
+
+def ChangeDirectoryToLibchrome() -> str:
+    """Change directory to libchrome for running git commands. Return cwd before changing."""
+    cwd = os.getcwd()
+    libchrome_directory = Path(
+        os.path.realpath(__file__)
+    ).parent.parent.parent.parent
+    os.chdir(libchrome_directory)
+    return cwd
+
+
+def IsInsideChroot() -> bool:
+    """Checks that the script is run inside chroot. Copied from chromite/lib/cros_build_lib.py"""
+    return os.path.exists("/etc/cros_chroot_version")
+
+
+def GetRevisionFromHash(commit_hash: str) -> int:
+    """Parses trailer of upstream commit (by hash) and returns revision number."""
+    try:
+        # `git log <commit>` shows history before <commit>. Use `-1` to restrict it
+        # to output the most recent commit only i.e. the specified one.
+        commit_log = subprocess.check_output(
+            ["git", "log", commit_hash, "-1"], universal_newlines=True
+        ).splitlines()
+    except subprocess.CalledProcessError as e:
+        raise ValueError(
+            f"Commit hash {commit_hash} not found on cros/upstream.\n"
+            f"Error: {e.output}"
+        )
+
+    for line in commit_log:
+        m = COMMIT_REVISION_RE.match(line)
+        if m:
+            return int(m.group(1))
+
+    raise Exception(
+        "Cannot find revision number from commit message of " f"{commit_hash}"
+    )
+
+
+def GetLatestCommitHashBeforeRevision(revision: int) -> str:
+    """Returns hash of commit with revision number <= the given number.
+
+    git's --grep option provides the most efficient way of filtering commits by
+    matching for pattern in commit message. (Compared to e.g. output the entire
+    history each with a complete commit message and then search in python.)
+    Unfortunately, it does not support printing only the matched pattern. So it
+    is not possible to e.g. print the Cr-Commit-Position information (and commit
+    hash) for all commits on cros/upstream and search on that concise output
+    here.
+
+    The compromised solution is to run git rev-list with grep in rounds with
+    a matching pattern decreasing in accuracy, so that once some match is found,
+    the first result will be the one closest to the target revision and we can
+    terminate the loop.
+
+    Starts from the pattern exactly the same as the given revison, then at each
+    iteration gets rid of the rightmost digit and replaces it with the list
+    numbers 0 up to the one before it, and padding [0-9] for correct number of
+    digits.
+    Special handling when the last digit is 0.
+    Only the beginning part of this numerical sequence is matched as the full
+    pattern contains the trailer header ("Cr-Commit-Position...").
+
+    E.g. if it is looking for 98706, first searches for revision number starting
+    with 98706, followed by that (starting with) 9870[0-5], 986[0-9][0-9],
+    98[0-5][0-9][0-9], and so on.
+    (Note we cannot just search directly with the patterning matching all
+    revision numbers that starts with 9 since the first result returned could be
+    99xxxx which is after the target.)
+    """
+    # Beginning part of pattern for revision number, kept as int for performing
+    # arithmetic operations when updating at each iteration(//10 and -1).
+    revision_prefix = revision
+    # Ending part of pattern for revision number, consists of [0-n][0-9]*.
+    pattern = ""
+
+    # l is the number of [0-9] for padding in the pattern, goes from 0 (search
+    # for exact match of target revision) to
+    # (# number of digit in target revision - 1).
+    for l in range(len(str(revision))):
+        grep_pattern = (
+            r"^\s*Cr-Commit-Position: refs\/heads\/\w\+@{#"
+            + str(revision_prefix)
+            + pattern
+            + "}"
+        )
+        try:
+            commit_hash = subprocess.check_output(
+                [
+                    "git",
+                    "rev-list",
+                    "cros/upstream",
+                    "--grep",
+                    grep_pattern,
+                    "-n1",
+                ],
+                universal_newlines=True,
+            ).strip()
+        except subprocess.CalledProcessError as e:
+            raise ValueError(
+                "Failed to format git rev-list query for revision "
+                f"matching pattern {revision_prefix}{pattern}.\n"
+                f"Error: {e.output}"
+            )
+
+        if commit_hash:
+            return commit_hash
+
+        last_digit = revision_prefix % 10
+        if last_digit:
+            pattern = r"[0-%d][0-9]\{%d\}" % (last_digit - 1, l)
+            revision_prefix //= 10
+        else:
+            pattern = r"[0-9]\{%d\}" % (l + 1)
+            revision_prefix = revision_prefix // 10 - 1
+
+    # No commit has revision number with the same number of digits as the target
+    # revision number.
+    l = len(str(revision)) - 1
+    grep_pattern = r"^\s*Cr-Commit-Position: refs\/heads\/\w\+@{#[0-9]\{,l\}}"
+    try:
+        commit_hash = subprocess.check_output(
+            [
+                "git",
+                "rev-list",
+                "cros/upstream",
+                "--grep",
+                grep_pattern,
+                "-n1",
+            ],
+            universal_newlines=True,
+        ).strip()
+    except subprocess.CalledProcessError as e:
+        raise ValueError(
+            "Failed to format git rev-list query for revision "
+            f"matching pattern {revision_prefix}{pattern}.\n"
+            f"Error: {e.output}"
+        )
+
+    if commit_hash:
+        return commit_hash
+
+    raise ValueError(
+        f"No commit with revision number <= {revision} found on "
+        "cros/upstream."
+    )
+
+
+def GetTargetCommitFromDateTime(end_date: str) -> Commit:
+    """Returns the last commit up to end_date (in any format accepted by git)."""
+    try:
+        commit_hash = subprocess.check_output(
+            ["git", "rev-list", "cros/upstream", "--before", end_date, "-n1"],
+            universal_newlines=True,
+        ).strip()
+    except subprocess.CalledProcessError as e:
+        raise ValueError(
+            f"git rev-list getting commit submitted before {end_date} "
+            f"on cros/upstream failed.\n"
+            f"Error: {e.output}"
+        )
+
+    if not commit_hash:
+        raise ValueError(
+            f"Invalid date or no commit submitted before {end_date} "
+            "found on cros/upstream.\n"
+        )
+
+    return commit_hash, GetRevisionFromHash(commit_hash)
+
+
+def GetLibchromeDate(track_branch: str = "cros/main") -> datetime.datetime:
+    """Returns libchrome date.
+
+    I.e. submission date (to upstream chromium) of the commit at r<BASE_VER> at
+    branch track_branch (default is cros/main).
+    """
+    revision = GetLibchromeRevision(track_branch)
+    grep_pattern = "^\s*Cr-Commit-Position: refs\/heads\/\w\+@{#%d}" % revision
+    try:
+        current_date = subprocess.check_output(
+            [
+                "git",
+                "log",
+                track_branch,
+                "--grep",
+                grep_pattern,
+                "-n1",
+                '--pretty="%cs"',
+            ],
+            universal_newlines=True,
+        ).strip()
+        logging.info(
+            f"Tracked branch {track_branch} at revision r{revision} was "
+            f"submitted on {current_date}."
+        )
+    except subprocess.CalledProcessError as e:
+        raise ValueError(
+            "Cannot find upstream commit with version BASE_VER "
+            f"{base_ver} on cros/main. \n"
+            f"Error: {e.output}"
+        )
+
+    return datetime.datetime.strptime(current_date, '"%Y-%m-%d"')
+
+
+def GetLatestUpstreamCommit() -> Commit:
+    """Returns latest commit on cros/upstream."""
+    try:
+        commit_hash = subprocess.check_output(
+            ["git", "rev-list", "cros/upstream", "-n1"], universal_newlines=True
+        ).strip()
+    except subprocess.CalledProcessError as e:
+        raise ValueError(
+            f"Cannot find latest commit on cros/upstream.\n"
+            f"Error: {e.output}"
+        )
+
+    return commit_hash, GetRevisionFromHash(commit_hash)
+
+
+def GetTargetCommit(args, track_branch: str) -> Commit:
+    """Returns hash and revision number of uprev target commit on cros/upstream
+    based on input argument.
+    """
+    if args.hash:
+        logging.info(f"Target option: use hash {args.hash}")
+        return args.hash, GetRevisionFromHash(args.hash)
+    if args.before_revision:
+        logging.info(
+            f"Target option: use latest commit before revision {args.before_revision}"
+        )
+        commit_hash = GetLatestCommitHashBeforeRevision(args.before_revision)
+        return commit_hash, GetRevisionFromHash(commit_hash)
+    if args.datetime:
+        logging.info(f"Target option: use latest commit before {args.datetime}")
+        return GetTargetCommitFromDateTime(args.datetime)
+    if args.days:
+        logging.info(
+            f"Target option: use latest commit {args.days} after HEAD of branch {track_branch}"
+        )
+        assert args.days >= 0, "Invalid args for --days; must be non-negative."
+        target_date = GetLibchromeDate(track_branch) + datetime.timedelta(
+            days=args.days
+        )
+        return GetTargetCommitFromDateTime(str(target_date))
+    # default option --head
+    logging.info(f"Target default: use latest commit on cros/upstream")
+    return GetLatestUpstreamCommit()
+
+
+def CreateNewBranchFromGerritCommit(ref: str, commit_number: str) -> str:
+    """Create new branch by downloading given commit ref and return its name."""
+    branch_name = f"change-{commit_number}"
+    subprocess.run(
+        [
+            "git",
+            "fetch",
+            "https://chromium.googlesource.com/chromiumos/platform/libchrome",
+            ref,
+            "--quiet",
+        ]
+    )
+    subprocess.run(
+        ["git", "checkout", "-B", branch_name, "FETCH_HEAD", "--quiet"]
+    )
+    logging.info(f"Created new branch {branch_name} for tracking")
+    return branch_name
+
+
+def GetTrackingBranch(args) -> str:
+    """Returns name of branch to track when creating the new uprev commit.
+    Create new branch by downloading from gerrit if in track_active mode.
+    """
+    if args.track_active:
+        logging.info(
+            f"Tracking option: track active commit on gerrit, fetching..."
+        )
+        # Get a list of all open libchrome uprev CLs on gerrit.
+        open_uprev_cls = gob_util.QueryChanges(
+            chromium_helper.host,
+            {
+                "repo": "chromiumos/platform/libchrome",
+                "status": "open",
+                "topic": "libchrome-automated-uprev",
+            },
+            o_params=["CURRENT_REVISION", "DOWNLOAD_COMMANDS"],
+        )
+        if open_uprev_cls:
+            # Create a local branch using the most recently updated uprev commit
+            # (gerrit query result is sorted).
+            try:
+                current_revision = open_uprev_cls[0]["current_revision"]
+                commit_number = open_uprev_cls[0]["_number"]
+                ref = open_uprev_cls[0]["revisions"][current_revision]["ref"]
+                logging.info(
+                    f"Found most recent active uprev commit: crrev.com/c/{commit_number}"
+                )
+                return CreateNewBranchFromGerritCommit(ref, commit_number)
+            except subprocess.CalledProcessError as e:
+                logging.warning(
+                    f"Failed to create new branch from active uprev commit crrev.com/c/{commit_number}: {e.output}, fallback to cros/main."
+                )
+        else:
+            logging.info(
+                f"No active uprev commit on gerrit, fallback to cros/main"
+            )
+    if args.track_branch:
+        logging.info(f"Tracking option: track branch {args.track_branch}")
+        branches = subprocess.run(
+            ["git", "rev-parse", "--verify", args.track_branch],
+            stdout=subprocess.DEVNULL,
+            stderr=subprocess.DEVNULL,
+        )
+        if not branches.retcode:
+            logging.info(f"Tracking branch {args.track_branch}")
+            return args.track_branch
+        else:
+            logging.info(
+                f"Cannot find {args.track_branch}, fallback to cros/main"
+            )
+    return "cros/main"
+
+
+def GetLibchromeRevision(track_branch: str = "cros/main") -> int:
+    """Reads BASE_VER to return current revision number on cros/main (or any other
+    specified) branch.
+    """
+    try:
+        base_ver = subprocess.check_output(
+            ["git", "show", f"{track_branch}:{BASE_VER_FILE}"],
+            universal_newlines=True,
+        ).strip()
+    except subprocess.CalledProcessError as e:
+        raise ValueError(
+            f"Cannot get BASE_VER on given branch {track_branch}.\n"
+            f"Error: {e.output}"
+        )
+    return int(base_ver)
+
+
+def UpdateBaseVer(revision: int) -> None:
+    """Overwrites BASE_VER with uprev target revision number."""
+    with open(BASE_VER_FILE, "w") as f:
+        f.write(f"{revision}\n")
+
+
+def OutdatedPatches(revision: int, directory: str = PATCHES_DIRECTORY):
+    """Return list of otudated patches in libchrome_tools/patches/."""
+    obsolete_patches = []
+    for patch in os.listdir(directory):
+        m = CHERRY_PICK_PATCH_RE.match(patch)
+        # Remove cherry-pick patch if uprev passed its revision.
+        if m and revision >= int(m.group(1)):
+            obsolete_patches.append(patch)
+    return obsolete_patches
+
+
+def UpdatePatches(revision: int) -> (typing.List[str]):
+    """Removes outdated patches and updates the list in
+    libchrome_tools/patches/patches.config.
+
+    Returns list of removed patches.
+    """
+    obsolete_patches = OutdatedPatches(revision)
+
+    if not obsolete_patches:  # Return early if no patch should be removed.
+        return []
+
+    for patch in obsolete_patches:
+        os.remove(os.path.join(PATCHES_DIRECTORY, patch))
+
+    with open(PATCHES_CONFIG_FILE, "r+") as f:
+        sources = f.read().splitlines()
+
+    # Check if config file contains any of the removed patches.
+    deleted_lines = []
+    for idx, line in enumerate(sources):
+        if not line or line.startswith("#"):  # Ignore empty line and comments.
+            continue
+        if line.split()[0] in obsolete_patches:
+            deleted_lines.append(idx)
+            if sources[idx - 1] == "":  # Remove leading empty line as well.
+                deleted_lines.append(idx - 1)
+
+    if deleted_lines:
+        # Delete lines from config file, if any, in reverse order to avoid
+        # reindexing.
+        deleted_lines.sort(reverse=True)
+        for idx in deleted_lines:
+            del sources[idx]
+
+        # To avoid eating the newline at the end of the file.
+        sources.append("")
+        # Write new patches config file.
+        with open(PATCHES_CONFIG_FILE, "w") as f:
+            f.write("\n".join(sources))
+
+    return obsolete_patches
+
+
+def ParseGitMergeSummary(merge_summary: typing.List[str]) -> GitMergeSummary:
+    """Returns list of non-test .cc source files added and deleted according to
+    git merge command output.
+    """
+    # Each of the added files and deleted files will be shown in a line in form
+    # 'create mode <permission> foo.cc' or 'delete mode <permission> foo.cc'.
+    added_files = []
+    deleted_files = []
+    for line in merge_summary:
+        line = line.strip()
+        if not line.startswith("create") and not line.startswith("delete"):
+            continue
+
+        file = line.split()[-1]
+        if file.endswith(".cc") and "unittest" not in file:
+            if line.startswith("create"):
+                added_files.append(file)
+            else:  # The line starts with "delete".
+                deleted_files.append(file)
+    return added_files, deleted_files
+
+
+def UpdateBuildGn(deleted_files: typing.List[str]) -> typing.List[str]:
+    """Removes deleted .cc files from BUILD.gn sources lists.
+
+    Returns the list of deleted files.
+    """
+    with open(BUILD_GN_FILE, "r") as f:
+        source = f.read().splitlines()
+
+    delete_idx = []
+    build_gn_deleted_files = []
+    for idx, line in enumerate(source):
+        m = BUILD_GN_SOURCE_FILE_LINE_RE.match(line)
+        if m and m.group(2) in deleted_files:
+            delete_idx.append(idx)
+            deleted_files.remove(m.group(2))
+            build_gn_deleted_files.append(m.group(2))
+
+    if delete_idx:
+        for idx in reversed(delete_idx):
+            del source[idx]
+
+        with open(BUILD_GN_FILE, "w") as f:
+            source.append(
+                ""
+            )  # To avoid eating the newline at the end of the file.
+            f.write("\n".join(source))
+
+    return build_gn_deleted_files
+
+
+def EmergeLibchrome() -> typing.Optional[bool]:
+    """Run `emerge libchrome` and returns whether or not it succeeded.
+    """
+    try:
+        process = subprocess.Popen(
+            ["sudo", "cros-workon", "--host", "start", "libchrome"],
+            universal_newlines=True,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.STDOUT,
+        )
+        process_output, _ = process.communicate()
+    except (OSError, subprocess.CalledProcessError) as e:
+        logging.warning('! `cros-workon --host start libchrome` failed, see log below:')
+        logging.warning(e.stderr)
+        return None
+
+    logging.info("`sudo emerge libchrome` running...")
+    try:
+        process = subprocess.Popen(
+            ["sudo", "emerge", "libchrome"],
+            universal_newlines=True,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.STDOUT,
+        )
+        process_output, _ = process.communicate()
+    except (OSError, subprocess.CalledProcessError) as e:
+        logging.warning('! `emerge libchrome` failed, see log below:')
+        logging.warning(e.stderr)
+        return False
+    else:
+        if process.returncode == 0:
+            logging.info(process_output)
+        else:
+            logging.warning('! `emerge libchrome` failed, see log below:')
+            logging.warning(process_output)
+        return process.returncode == 0
+
+
+def CreateUprevCommit(
+    commit_hash: str,
+    revision: int,
+    track_branch: str,
+) -> MergeResult:
+    """Runs git merge and conduct typical changes (update BASE_VER, etc).
+
+    Returns whether the merge succeeds, and the final commit message as list of strings (each str is one line).
+    """
+    subprocess.run(
+        [
+            "git",
+            "checkout",
+            "-B",
+            f"r{revision}-uprev",
+            "--track",
+            track_branch,
+            "--quiet",
+        ],
+        check=True,
+    )
+
+    message = [
+        f"Automated commit: libchrome r{revision} uprev\n",
+        f"Merge with upstream commit {commit_hash}",
+    ]
+
+    try:
+        merge_summary = subprocess.check_output(
+            ["git", "merge", commit_hash, "-m", "\n".join(message)],
+            universal_newlines=True,
+        ).splitlines()
+    except subprocess.CalledProcessError as e:
+        # Provide target hash in an empty commit for further local debugging.
+        subprocess.run(["git", "merge", "--abort"])
+        message.insert(2, "GIT MERGE FAILED")
+        subprocess.run(
+            [
+                "git",
+                "commit",
+                "--allow-empty",
+                "--quiet",
+                "-m",
+                "\n".join(message),
+            ],
+            check=True,
+        )
+        logging.error("Failed to `git merge` and create uprev commit")
+        return False, message
+
+    UpdateBaseVer(revision)
+
+    _, removed_files = ParseGitMergeSummary(merge_summary)
+    removed_from_gn_files = UpdateBuildGn(removed_files)
+    if removed_from_gn_files:
+        message.append(f"Update to {BUILD_GN_FILE} sources:")
+        message.extend(["  * remove " + f for f in removed_from_gn_files])
+
+    removed_patches = UpdatePatches(revision)
+    if removed_patches:
+        message.append(f"Remove following patches:")
+        message.extend(["  * " + f for f in removed_patches])
+
+    message.append(f"\nBUG=None")
+    message.append(f"TEST=sudo emerge libchrome")
+
+    subprocess.run(
+        [
+            "git",
+            "add",
+            "BASE_VER",
+            "BUILD.gn",
+            "libchrome_tools/patches/",
+        ],
+        check=True,
+    )
+    subprocess.run(
+        [
+            "git",
+            "commit",
+            "--amend",
+            "--quiet",
+            "--allow-empty",
+            "-m",
+            "\n".join(message),
+        ],
+        check=True,
+    )
+
+    logging.info("Created uprev commit")
+    return True, message
+
+
+def PushOptions(git_merge_success, emerge_success, recipe: bool) -> str:
+    """
+    Returns options to be used with `git push`.
+
+    Args:
+      git_merge_success: bool
+      emerge_success: bool or None (not run)
+      recipe: in recipe mode
+    """
+    push_options = (
+        "%"
+        +
+        # Add libchrome team to cc
+        "cc=chromeos-libchrome@google.com,"
+        +
+        # Set topic for easy searching of commits on gerrit
+        "topic=libchrome-automated-uprev,"
+    )
+    # Add votes according to `sudo emerge libchrome` result.
+    # Note bot submit votes will be added in the recipe after verifying
+    # `emerge libchrome` succeeded (or not).
+    if emerge_success and not recipe:
+        push_options += "l=Verified+1,"
+    # Flag git merge and emerge failure by Verified-1 in both modes.
+    elif not git_merge_success or emerge_success == False:
+        push_options += "l=Verified-1,"
+
+    # Submit CL to CQ automatically after approval
+    if not recipe:
+        push_options += "l=Auto-Submit+1,"
+
+    return push_options
+
+
+def UploadUprevCommit(push_options: str) -> None:
+    subprocess.run(
+        ["git", "push", "cros", "HEAD:refs/for/main" + push_options],
+        check=True,
+    )
+
+
+def main():
+    parser = argparse.ArgumentParser(
+        description="Generate and upload libchrome uprev commit."
+    )
+
+    parser_target_group = parser.add_mutually_exclusive_group()
+    parser_target_group.add_argument(
+        "--hash",
+        type=str,
+        help="Uprev to the given hash, exit with error if not found.",
+    )
+    parser_target_group.add_argument(
+        "--before_revision",
+        type=int,
+        help="Uprev to the latest commit on or before the given revision number.",
+    )
+    parser_target_group.add_argument(
+        "--datetime",
+        type=str,
+        help="Uprev to the latest commit on or before the given date time.",
+    )
+    parser_target_group.add_argument(
+        "--days",
+        type=int,
+        help="Uprev to the latest commit submitted n days after current latest on"
+        " cros/main.",
+    )
+    parser_target_group.add_argument(
+        "--head",
+        action="store_true",
+        help="Uprev to (latest commit) HEAD on cros/upstream.",
+    )
+
+    parser_track_group = parser.add_mutually_exclusive_group()
+    parser_track_group.add_argument(
+        "--track_branch",
+        type=str,
+        help="(Local or remote) branch to be tracked by the uprev commit.",
+        default="",
+    )
+    parser_track_group.add_argument(
+        "--track_active",
+        action="store_true",
+        help="Track most recent active uprev commit on gerrit.",
+        default=False,
+    )
+
+    parser.add_argument(
+        "--query_commit",
+        action="store_true",
+        help="Only output hash and revision number and do not perform merge.",
+        default=False,
+    )
+
+    parser.add_argument(
+        "--no_upload",
+        action="store_true",
+        help="Do not upload uprev commit to gerrit.",
+        default=False,
+    )
+
+    parser.add_argument(
+        "--recipe",
+        action="store_true",
+        help="The command is running as a recipe, i.e. not running manually."
+        "Output git push options instead of running git push directly.",
+        default=False,
+    )
+
+    args = parser.parse_args()
+
+    logging.getLogger().setLevel("INFO")
+
+    initial_directory = ChangeDirectoryToLibchrome()
+
+    # Ensure upstream branch is up-to-date.
+    logging.info("Git fetch cros to ensure cros/upstream is up-to-date")
+    subprocess.run(
+        [
+            "git",
+            "fetch",
+            "cros"
+        ],
+        check=True,
+    )
+
+    track_branch = GetTrackingBranch(args)
+    logging.info(f"Uprev commit will track {track_branch}")
+
+    target_commit_hash, target_commit_revision = GetTargetCommit(
+        args, track_branch
+    )
+    logging.info(
+        f"Uprev to revision {target_commit_revision} with hash "
+        f"{target_commit_hash}"
+    )
+    if args.query_commit:
+        exit()
+
+    if target_commit_revision <= GetLibchromeRevision(track_branch):
+        raise Exception(
+            f"Target revision {target_commit_revision} has been reached already: "
+            f"libchrome is currently at {GetLibchromeRevision(args.track_branch)}."
+        )
+
+    if subprocess.run(["git", "diff", "--quiet"]).returncode:  # if git dirty
+        raise Exception(
+            "Git working directory is dirty. Abort creating uprev commit."
+        )
+
+    merge_success, commit_message = CreateUprevCommit(
+        target_commit_hash, target_commit_revision, track_branch
+    )
+
+    emerge_success = None
+    if args.recipe:
+        logging.info(f"In --recipe mode; emerge libchrome is not run.")
+    elif merge_success and IsInsideChroot():
+        emerge_success = EmergeLibchrome()
+        if emerge_success == False:
+            logging.warning(f"emerge libchrome failed.")
+            commit_message.insert(2, "EMERGE LIBCHROME IS FAILING\n")
+        elif emerge_success == None:
+            commit_message.insert(2, "DID NOT EMERGE LIBCHROME\n")
+    else:
+        reason = (
+            "git merge failed" if not merge_success else "Not inside chroot"
+        )
+        logging.warning(f"{reason}, emerge libchrome is not run.")
+        commit_message.insert(2, "DID NOT EMERGE LIBCHROME\n")
+    subprocess.run(
+        [
+            "git",
+            "commit",
+            "--amend",
+            "--quiet",
+            "--allow-empty",
+            "-m",
+            "\n".join(commit_message),
+        ],
+        check=True,
+    )
+
+    push_options = PushOptions(merge_success, emerge_success, args.recipe)
+    if args.recipe:
+        print(push_options)
+        return
+
+    if not args.no_upload:
+        UploadUprevCommit(push_options)
+
+    os.chdir(initial_directory)
+
+
+if __name__ == "__main__":
+    sys.exit(main())
diff --git a/libchrome_tools/developer-tools/uprev/automated_uprev_test.py b/libchrome_tools/developer-tools/uprev/automated_uprev_test.py
new file mode 100644
index 0000000..352c871
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/automated_uprev_test.py
@@ -0,0 +1,221 @@
+#!/usr/bin/env python
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import subprocess
+import tempfile
+import unittest
+from pathlib import Path
+from shutil import copy
+
+from automated_uprev import *
+
+
+class TestGetRevisionFromHash(unittest.TestCase):
+    def test_simple_commit(self):
+        self.assertEqual(
+            GetRevisionFromHash("6871907594466edadc668dfeb951b456954c1336"),
+            1044017,
+        )
+
+    def test_revert_commit(self):
+        self.assertEqual(
+            GetRevisionFromHash("92f9f98919b98120af01cc367443a9e035d4fe17"),
+            1043792,
+        )
+
+    def test_reland_commit(self):
+        self.assertEqual(
+            GetRevisionFromHash("1fa681a83e9f86cff2f46931886b255f4fed58df"),
+            1035760,
+        )
+
+    def test_invalid_commit_hash(self):
+        with self.assertRaises(Exception) as context:
+            GetRevisionFromHash("foobar")
+        self.assertTrue(
+            "Commit hash foobar not found on cros/upstream."
+            in str(context.exception)
+        )
+
+    def test_bot_commit(self):
+        with self.assertRaises(Exception) as context:
+            GetRevisionFromHash("6a63e55d715595d77b9565e07d921c71835b0854")
+        self.assertTrue(
+            "Cannot find revision number from commit message"
+            in str(context.exception)
+        )
+
+
+class TestGetLatestCommitHashBeforeRevision(unittest.TestCase):
+    def test_exact_equal(self):
+        self.assertEqual(
+            GetLatestCommitHashBeforeRevision(998985),
+            "7de51b4212c6c5801f8ef6d1f77d91d5ab55516c", # r998985
+        )
+
+    def test_target_no_zero(self):
+        self.assertEqual(
+            GetLatestCommitHashBeforeRevision(998965),
+            "9e12f276bc064d1d8b951ca25a23cd6e0f41480d", # r998960
+        )
+
+    def test_target_some_zeros(self):
+        self.assertEqual(
+            GetLatestCommitHashBeforeRevision(1005160),
+            "19b05f75d1839fba3a511e44c2b89c5043577018", # r1005098
+        )
+
+    def test_result_less_digits_than_target(self):
+        self.assertEqual(
+            GetLatestCommitHashBeforeRevision(1000000),
+            "b2330d97c31cb6006ecc133625e9a40c8d56cfc8", # r999946
+        )
+
+
+class TestGetTargetCommitFromDateTime(unittest.TestCase):
+    def test_valid_datetime(self):
+        self.assertEqual(
+            GetTargetCommitFromDateTime("2022-05-10T00:00:00+0000"),
+            ("760c45a4f789e395a430455e9c476803f1199641", 1001216),
+        )
+
+    def test_no_commit(self):
+        with self.assertRaises(Exception) as context:
+            GetTargetCommitFromDateTime("2001-01-01"),
+        self.assertTrue(
+            "Invalid date or no commit submitted before 2001-01-01"
+            in str(context.exception)
+        )
+
+
+class TestGetLibchromeDate(unittest.TestCase):
+    def test_valid_libchrome_commit(self):
+        self.assertEqual(
+            GetLibchromeDate("921d6b1ae10abb974230a6399c2af4bf7a2d2f9a"),
+            datetime.datetime.strptime("2022-05-28", "%Y-%m-%d"),
+        )
+
+    def test_invalid_chromium_commit(self):
+        with self.assertRaises(Exception) as context:
+            GetLibchromeDate("eadc2d77660dbbee054646def03415aed4db9fbf"),
+        self.assertTrue(
+            "Cannot get BASE_VER on given branch" in str(context.exception)
+        )
+
+
+class TestGetLibchromeRevision(unittest.TestCase):
+    def test_valid_libchrome_commit(self):
+        self.assertEqual(
+            GetLibchromeRevision("921d6b1ae10abb974230a6399c2af4bf7a2d2f9a"),
+            1008611,
+        )
+
+    def test_invalid_chromium_commit(self):
+        with self.assertRaises(Exception) as context:
+            GetLibchromeDate("eadc2d77660dbbee054646def03415aed4db9fbf"),
+        self.assertTrue(
+            "Cannot get BASE_VER on given branch" in str(context.exception)
+        )
+
+
+class TestOutdatedPatches(unittest.TestCase):
+    def setUp(self):
+        self.repo_dir = tempfile.TemporaryDirectory()
+        self.orig_dir = os.getcwd()
+        os.chdir(self.repo_dir.name)
+        Path(os.path.join(self.repo_dir.name, "cherry-pick-0000-r201-bar.patch")).touch()
+        Path(os.path.join(self.repo_dir.name, "cherry-pick-0100-r101-foo.patch")).touch()
+        Path(os.path.join(self.repo_dir.name, "cherry-pick-0200-r876-baz.patch")).touch()
+
+    def tearDown(self):
+        os.chdir(self.orig_dir)
+        self.repo_dir.cleanup()
+
+    def test_no_update(self):
+        self.assertEqual(OutdatedPatches(100, self.repo_dir.name), [])
+
+    def test_remove_after_another_patch(self):
+        self.assertEqual(
+            OutdatedPatches(105, self.repo_dir.name),
+            ["cherry-pick-0100-r101-foo.patch"]
+        )
+
+    def test_remove_after_section_header(self):
+        self.assertEqual(
+            set(OutdatedPatches(250, self.repo_dir.name)),
+            set(["cherry-pick-0000-r201-bar.patch",
+                 "cherry-pick-0100-r101-foo.patch",])
+        )
+
+    def test_remove_after_empty_line(self):
+        self.assertEqual(
+            set(OutdatedPatches(900, self.repo_dir.name)),
+            set(["cherry-pick-0000-r201-bar.patch",
+                 "cherry-pick-0100-r101-foo.patch",
+                 "cherry-pick-0200-r876-baz.patch",],)
+        )
+
+
+class TestParseGitMergeSummary(unittest.TestCase):
+    def setUp(self):
+        self.repo_dir = tempfile.TemporaryDirectory()
+        self.orig_dir = os.getcwd()
+        os.chdir(self.repo_dir.name)
+        subprocess.check_call(["git", "init"])
+        with open(os.path.join(self.repo_dir.name, "init_file.cc"), "w+") as f:
+            f.write("// foo")
+        subprocess.check_call(["git", "add", "init_file.cc"])
+        subprocess.check_call(["git", "commit", "-m", "initial commit"])
+        subprocess.check_call(["git", "checkout", "-b", "new-branch"])
+
+    def tearDown(self):
+        os.chdir(self.orig_dir)
+        self.repo_dir.cleanup()
+
+    def test_modified_only(self):
+        os.chdir(self.repo_dir.name)
+        with open(os.path.join(self.repo_dir.name, "init_file.cc"), "w+") as f:
+            f.write("// bar")
+        subprocess.check_call(
+            ["git", "commit", "-a", "-m", "modified init_file.cc"]
+        )
+        subprocess.check_call(["git", "checkout", "main"])
+        merge_summary = subprocess.check_output(
+            ["git", "merge", "new-branch", "-m", "merging"],
+            universal_newlines=True,
+        ).splitlines()
+        added_files, removed_files = ParseGitMergeSummary(merge_summary)
+        self.assertEqual(added_files, [])
+        self.assertEqual(removed_files, [])
+
+    def test_added_files(self):
+        os.chdir(self.repo_dir.name)
+        with open(os.path.join(self.repo_dir.name, "new_file.cc"), "w+") as f:
+            f.write("// this is a new file")
+        subprocess.check_call(["git", "add", "new_file.cc"])
+        subprocess.check_call(["git", "commit", "-m", "added new_file.cc"])
+        subprocess.check_call(["git", "checkout", "main"])
+        merge_summary = subprocess.check_output(
+            ["git", "merge", "new-branch", "-m", "merging"],
+            universal_newlines=True,
+        ).splitlines()
+        added_files, removed_files = ParseGitMergeSummary(merge_summary)
+        self.assertEqual(added_files, ["new_file.cc"])
+        self.assertEqual(removed_files, [])
+
+    def test_deleted_files(self):
+        os.chdir(self.repo_dir.name)
+        os.remove(os.path.join(self.repo_dir.name, "init_file.cc"))
+        subprocess.check_call(
+            ["git", "commit", "-a", "-m", "removed init_file.cc"]
+        )
+        subprocess.check_call(["git", "checkout", "main"])
+        merge_summary = subprocess.check_output(
+            ["git", "merge", "new-branch", "-m", "merging"],
+            universal_newlines=True,
+        ).splitlines()
+        added_files, removed_files = ParseGitMergeSummary(merge_summary)
+        self.assertEqual(added_files, [])
+        self.assertEqual(removed_files, ["init_file.cc"])
diff --git a/libchrome_tools/developer-tools/uprev/filter_config.py b/libchrome_tools/developer-tools/uprev/filter_config.py
new file mode 100644
index 0000000..5193cf5
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/filter_config.py
@@ -0,0 +1,48 @@
+# Copyright 2021 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Provide filter rules for libchrome tools."""
+
+import re
+
+# Libchrome wants WANT but mot WANT_EXCLUDE
+# aka files matching WANT will be copied from upstream_files
+WANT = [
+    re.compile(rb'base/((?!(third_party)/).*$)'),
+    re.compile(rb'base/third_party/(dynamic_annotation|icu|nspr|valgrind|cityhash|superfasthash)'),
+    re.compile(
+        rb'build/(android/(gyp/util|pylib/([^/]*$|constants))|[^/]*\.(h|py)$|buildflag_header.gni)'),
+    re.compile(rb'mojo/'),
+    re.compile(rb'dbus/'),
+    re.compile(rb'ipc/.*(\.cc|\.h|\.mojom)$'),
+    re.compile(rb'ui/gfx/(gfx_export.h|geometry|range)'),
+    re.compile(rb'testing/[^/]*\.(cc|h)$'),
+    re.compile(rb'third_party/(ipcz|jinja2|markupsafe|ply)'),
+    re.compile(
+        rb'components/(json_schema|policy/core/common/[^/]*$|policy/policy_export.h|timers)'
+    ),
+    re.compile(
+        rb'device/bluetooth/bluetooth_(common|advertisement|uuid|export)\.*(h|cc)'
+    ),
+    re.compile(
+        rb'device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.(h|cc)'
+    ),
+]
+
+# WANT_EXCLUDE will be excluded from WANT
+WANT_EXCLUDE = [
+    re.compile(rb'(.*/)?BUILD.gn$'),
+    re.compile(rb'(.*/)?PRESUBMIT.py$'),
+    re.compile(rb'(.*/)?OWNERS$'),
+    re.compile(rb'(.*/)?SECURITY_OWNERS$'),
+    re.compile(rb'(.*/)?DEPS$'),
+    re.compile(rb'(.*/)?DIR_METADATA$'),
+    re.compile(rb'base/android/java/src/org/chromium/base/BuildConfig.java'),
+    re.compile(rb'base/(.*/)?(ios|win|fuchsia|mac|openbsd|freebsd|nacl)/.*'),
+    re.compile(rb'.*_(ios|win|mac|fuchsia|openbsd|freebsd|nacl)[_./]'),
+    re.compile(rb'.*/(ios|win|mac|fuchsia|openbsd|freebsd|nacl)_'),
+    re.compile(rb'dbus/(test_serv(er|ice)\.cc|test_service\.h)$')
+]
+
+# ALWAYS_WANT is a WANT, but not excluded by WANT_EXCLUDE
+ALWAYS_WANT = [re.compile(rb'base/hash/(md5|sha1)_nacl\.(h|cc)$')]
diff --git a/libchrome_tools/developer-tools/uprev/filtered_utils.py b/libchrome_tools/developer-tools/uprev/filtered_utils.py
new file mode 100644
index 0000000..bdf3f55
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/filtered_utils.py
@@ -0,0 +1,119 @@
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+""" Provides utilities for filtered branch handling. """
+
+import collections
+import re
+import subprocess
+
+import utils
+
+# Keyword to uniquely identify the beginning of upstream history.
+CROS_LIBCHROME_INITIAL_COMMIT = b'CrOS-Libchrome-History-Initial-Commit'
+# Keyword to identify original commit in Chromium browser repository.
+CROS_LIBCHROME_ORIGINAL_COMMIT = b'CrOS-Libchrome-Original-Commit'
+# Keyword to identify current commit for deleting files or merge add files
+# branch.
+CROS_LIBCHROME_CURRENT_COMMIT = b'CrOS-Libchrome-Current-Commit'
+
+# Stores metadata required for a git commit.
+GitCommitMetadata = collections.namedtuple('GitCommitMetadata', [
+    'parents',
+    'original_commits',
+    'original_commit_cursor',
+    'tree',
+    'authorship',
+    'title',
+    'message',
+    'is_root',
+])
+
+# Stores information for a commit authorship.
+GitCommitAuthorship = collections.namedtuple('GitCommitAuthorship', [
+    'name',
+    'email',
+    'time',
+    'timezone',
+])
+
+
+def get_metadata(commit_hash):
+    """Returns the metadata of the commit specified by the commit_hash.
+
+    This function parses the commit message of the commit specified by the
+    commit_hash, then returns its GitCommitMetadata instance.
+    The commit must be on the filtered branch, otherwise some metadata may be
+    omitted.
+    Returns metadata from the commit message about commit_hash on the filtered
+    branch.
+
+    Args:
+        commit_hash: the commit hash on the filtered branch.
+    """
+
+    ret = subprocess.check_output(['git', 'cat-file', 'commit',
+                                   commit_hash]).split(b'\n')
+    parents = []
+    tree_hash = None
+    authorship = None
+    author_re = re.compile(rb'^(.*) <(.*)> ([0-9]+) ([^ ])+$')
+    while ret:
+        line = ret[0]
+        ret = ret[1:]
+        if not line.strip():
+            # End of header. break.
+            break
+        tag, reminder = line.split(b' ', 1)
+        if tag == b'tree':
+            tree_hash = reminder
+        elif tag == b'author':
+            m = author_re.match(reminder)
+            assert m, (line, commit_hash)
+            authorship = GitCommitAuthorship(m.group(1), m.group(2), m.group(3),
+                                             m.group(4))
+        elif tag == b'parent':
+            parents.append(reminder)
+
+    title = ret[0] if ret else None
+
+    original_commits = []
+    original_commit_cursor = None
+    is_root = False
+    for line in ret:
+        if line.startswith(CROS_LIBCHROME_ORIGINAL_COMMIT):
+            original_commits.append(line.split(b':')[1].strip())
+        if line.startswith(CROS_LIBCHROME_ORIGINAL_COMMIT) or line.startswith(
+                CROS_LIBCHROME_CURRENT_COMMIT):
+            original_commit_cursor = line.split(b':')[1].strip()
+        if line == CROS_LIBCHROME_INITIAL_COMMIT:
+            is_root = True
+    msg = b'\n'.join(ret)
+    return GitCommitMetadata(parents, original_commits, original_commit_cursor,
+                             tree_hash, authorship, title, msg, is_root)
+
+
+def get_commits_map(commit_hash, progress_callback):
+    """Returns a map from original commit hashes to filtered commit hashes.
+
+    This function traverses the filtered branch from the commit specified by
+    commit_hash to its root, then parses each commit message and constructs the
+    map of those commits.
+
+    Args:
+        commit_hash: the commit hash on the filtered branch.
+        progress_callback: called every commit is being read. Parameters taken
+            are (idx, total_commits, current_commit)
+    """
+    commits_map = {}
+    commits_filtered_tree = utils.git_revlist(None, commit_hash)
+    for index, commit in enumerate(commits_filtered_tree, start=1):
+        if progress_callback:
+            progress_callback(index, len(commits_filtered_tree), commit[0])
+        meta = get_metadata(commit[0])
+        for original_commit in meta.original_commits:
+            commits_map[original_commit] = commit[0]
+        if meta.is_root:
+            assert 'ROOT' not in commits_map
+            commits_map['ROOT'] = commit[0]
+    return commits_map
diff --git a/libchrome_tools/developer-tools/uprev/filters.py b/libchrome_tools/developer-tools/uprev/filters.py
new file mode 100644
index 0000000..ab2bac1
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/filters.py
@@ -0,0 +1,83 @@
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Provide filters for libchrome tools."""
+
+
+class PathFilter:
+    """Provides a _sre.SRE_Pattern like class that matches a list of paths."""
+
+    def __init__(self, paths):
+        """Initializes an instance to match with the given paths.
+
+        Args:
+            paths: paths to match, must be list of bytes.
+        """
+        self.paths = paths
+
+    def match(self, what):
+        """Returns if what matches any files.
+
+        Args:
+            what: paths to look for, must be bytes.
+        """
+        return what in self.paths
+
+
+class Filter:
+    """
+    Provide filter functions for libchrome uprev tools
+    """
+
+    def __init__(self, want, want_excluded, always_want):
+        """
+        Initialize filters with given filter rules.
+        """
+        self.want = want
+        self.want_excluded = want_excluded
+        self.always_want = always_want
+
+    def want_file(self, path):
+        """Returns whether the path wants to be a new file."""
+        wanted = False
+        for want_file_regex in self.want:
+            if want_file_regex.match(path):
+                wanted = True
+                break
+        for exclude_file_regex in self.want_excluded:
+            if exclude_file_regex.match(path):
+                wanted = False
+                break
+        for always_want_file_regex in self.always_want:
+            if always_want_file_regex.match(path):
+                wanted = True
+                break
+        return wanted
+
+    def filter_files(self, upstream_files):
+        """Generates a list of files we want based on hard-coded rules.
+
+        File list must be a list of GitFile.
+
+        Args:
+            upstream_files: files in Chromium browser repository.
+        """
+
+        files = []
+        for upstream_file in upstream_files:
+            if self.want_file(upstream_file.path):
+                files.append(upstream_file)
+        return files
+
+    def filter_diff(self, diff):
+        """Returns a subset of diff, after running filters.
+
+        Args:
+            diff: diff to filter. diff contains list of utils.GitDiffTree
+        """
+        filtered = []
+        for change in diff:
+            path = change.file.path
+            if self.want_file(path):
+                filtered.append(change)
+        return filtered
diff --git a/libchrome_tools/developer-tools/uprev/generate_filtered_tree.py b/libchrome_tools/developer-tools/uprev/generate_filtered_tree.py
new file mode 100755
index 0000000..6aa33ae
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/generate_filtered_tree.py
@@ -0,0 +1,438 @@
+#!/usr/bin/env python3
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import collections
+import datetime
+import os
+import subprocess
+import sys
+import time
+
+import filter_config
+import filtered_utils
+import filters
+import lazytree
+import utils
+
+# Indicating information for look forward.
+# look_forward_until_index indicating a 1-based idx in pending_commits that
+# there's no changes we care about until look_forward_until_index.
+# parent_commit_hash indicating the parent previously made commit we cared
+# about.
+LookForwardInformation = collections.namedtuple(
+    'LookForwardInformation',
+    ['look_forward_until_index', 'parent_commit_hash'])
+
+# Use avg speed of last TIMING_DISTANCE commits.
+_TIMING_DISTANCE = 100
+# Verify the tree is consistent (diff-based, and actual) when a commit is made
+# after every _VERIFY_INTEGRITY_DISTANCE in browser repository.
+# Merge commits are always verified.
+_VERIFY_INTEGRITY_DISTANCE = 1000
+
+
+def timing(timing_deque, update=True):
+    """Returns a speed (c/s), and updates timing_deque.
+
+    Args:
+        timing_deque: a deque to store the timing of past _TIMING_DISTANCE.
+        update: adds current timestamp to timing_deque if True. It needs to set
+            to False, if it wants to be called multiple times with the current
+            timestamp.
+    """
+    first = timing_deque[0]
+    now = time.time()
+    if update:
+        timing_deque.append(now)
+        if len(timing_deque) > _TIMING_DISTANCE:
+            timing_deque.popleft()
+    return _TIMING_DISTANCE / (now - first)
+
+
+def get_start_commit_of_browser_tree(parent_filtered):
+    """Returns the last commit committed in bytes by the script, and its metadata.
+
+    Args:
+        parent_filtered: the commit hash of the tip of the filtered branch.
+    """
+    assert isinstance(parent_filtered, bytes)
+    current = parent_filtered
+    while True:
+        meta = filtered_utils.get_metadata(current)
+        if meta.original_commits:
+            return current, meta
+        if not meta.parents:
+            return None, None
+        # Follow main line only
+        current = meta.parents[0]
+
+
+def find_filtered_commit(commit, commits_map):
+    """Finds the corresponding parent of a browser commit in filtered branch.
+
+    If not found, the corresponding commit of its least ancestor is used.
+
+    Args:
+        commit: commit hash in browser repository.
+        commits_map: commit hash mapping from original commit to the one in the
+            filtered branch. commits_map may be altered.
+    """
+    look_for = commit
+    while look_for not in commits_map:
+        meta = filtered_utils.get_metadata(look_for)
+        assert len(meta.parents) <= 1
+        if len(meta.parents) == 1:
+            look_for = meta.parents[0]
+        else:
+            look_for = 'ROOT'
+    commits_map[commit] = commits_map[look_for]
+    return commits_map[look_for]
+
+
+def do_commit(treehash, commithash, meta, commits_map, commit_hash_meta_name):
+    """Makes a commit with the given arguments.
+
+    This creates a commit on the filtered branch with preserving the original
+    commiter name, email, authored timestamp and the message.
+    Also, the special annotation `CrOS-Libchrome-Original-Commit:
+    <original-commit-hash>' is appended at the end of commit message.
+    The parent commits are identified by the parents of the original commit and
+    commits_map.
+
+    Args:
+        treehash: tree object id for this commit.
+        commithash: original commit hash, used to append to commit message.
+        meta: meta data of the original commit.
+        commits_map: current known commit mapping. commits_map may be altered.
+    """
+    parents_parameters = []
+    for parent in meta.parents:
+        parents_parameters.append('-p')
+        parents_parameters.append(find_filtered_commit(parent, commits_map))
+    msg = (meta.message + b'\n\n' + commit_hash_meta_name + b': ' + commithash +
+           b'\n')
+    return subprocess.check_output(
+        ['git', 'commit-tree'] + parents_parameters + [treehash],
+        env=dict(os.environ,
+                 GIT_AUTHOR_NAME=meta.authorship.name,
+                 GIT_AUTHOR_EMAIL=meta.authorship.email,
+                 GIT_AUTHOR_DATE=b' '.join(
+                     [meta.authorship.time, meta.authorship.timezone])),
+        input=msg).strip(b'\n')
+
+
+def verify_commit(libchrome_filter, original_commit, new_tree):
+    """Verifies if new_tree is exactly original_commit after filters.
+
+    Args:
+        original_commit: commit hash in Chromium browser tree.
+        new_tree: tree hash created for upstream branch commit.
+    """
+    expected_file_list = libchrome_filter.filter_files(
+        utils.get_file_list(original_commit))
+    assert utils.git_mktree(expected_file_list) == new_tree
+
+
+def check_look_forward(pending_commits, base_commit, base_commit_meta,
+                       look_forward_from, look_forward_cnt,
+                       ignore_look_forward_until, commits_map,
+                       libchrome_filter):
+    """
+    Checks if we can look forward a few commits.
+
+    Returns (look_forward_until, ignore_look_forward_until) indicating we can
+    either look forward until look_forward_until[0], or skip checking again until
+    ignore_look_forward_until.
+
+    look_forward_until is LookForwardInformation or None.
+
+    ignore_look_forward_until is a number, which indicate we don't need to call
+    check_look_forward until ignore_look_forward_until.
+
+    Args:
+        pending_commits: list of GitCommitInRevList to process, in topological
+            order.
+        base_commit: an element in pending_commits.
+        base_commit_meta: a GitCommitMetadata for base_commit.
+        look_forward_from: the first commit after base_commit to check.
+        look_forward_cnt: total count of commits to scan for look-forward.
+        ignore_look_forward_until: do not look forward until look_forward_from
+            reaching ignore_look_forward_until.
+        commits_map: commits_map: current known commit mapping. may be altered.
+        libchrome_filter: the filter to use after diff commits.
+    """
+    # Not to look forward if feature disabled.
+    if not look_forward_cnt:
+        return None, 0
+    # Not to look forward until ignore_look_forward_until.
+    if look_forward_from < ignore_look_forward_until:
+        return None, ignore_look_forward_until
+    # Not to look forward at last few commits.
+    if look_forward_from + look_forward_cnt >= len(pending_commits):
+        return None, ignore_look_forward_until
+
+    look_forward_until = LookForwardInformation(look_forward_from - 1, None)
+    ignore_look_forward_until = look_forward_from - 1
+    merge_commit_count = sum(
+        len(commit.parent_hashes) != 1
+        for commit in pending_commits[look_forward_from:look_forward_from +
+                                      look_forward_cnt])
+    future_diff = libchrome_filter.filter_diff(
+        utils.git_difftree(
+            pending_commits[look_forward_from + look_forward_cnt -
+                            1].commit_hash, base_commit.commit_hash))
+    if len(future_diff) == 0 and merge_commit_count == 0:
+        look_forward_until = LookForwardInformation(
+            look_forward_from + look_forward_cnt,
+            commits_map[base_commit_meta.parents[0]])
+    else:
+        # It has changes, do not check again at next iteration.
+        ignore_look_forward_until = look_forward_from + look_forward_cnt
+    return look_forward_until, ignore_look_forward_until
+
+
+def process_commits(libchrome_filter, pending_commits, commits_map,
+                    look_forward, commit_hash_meta_name, progress_callback,
+                    commit_callback):
+    """Processes new commits in browser repository.
+
+    Returns the commit hash of the last commit made.
+
+    Args:
+        libchrome_filter: the filter to use after diff commits.
+        pending_commits: list of GitCommitInRevList to process, in topological
+            order.
+        commits_map: current known commit mapping. may be altered.
+            progress_callback: callback for every commit in pending_commits. It
+            should take (idx, total, orig_commit_hash, meta) as parameters.
+        look_forward: look at next look_forward commits and skip all of them if
+            next look_forward combined doesn't have any diff (submit + revert
+            will be ignored), and has no merge commit.
+        progress_callback: callback when a commit in Chromium upstream has been
+            read. It should take (idx, tot, original_commit_hash, meta) as
+            parameters.
+        commit_callback: callback when a commit is made to filtered branch. It
+            should take (orig_commit_hash, new_commit_hash, meta) as parameters.
+    """
+    last_commit = None
+    last_verified = -1
+    look_forward_until = None
+    ignore_look_forward_until = 0
+    for i, commit in enumerate(pending_commits, start=1):
+        # [i, look_forward_until.look_forward_until_index] has no changes. Skip
+        # CLs are ignored if it's submitted and reverted. Since it brings no
+        # change, and a Reland can bring back the correct history (and usually
+        # contains the correct commit message).
+        if look_forward_until and i < look_forward_until.look_forward_until_index:
+            commits_map[
+                commit.commit_hash] = look_forward_until.parent_commit_hash
+            if progress_callback:
+                progress_callback(i, len(pending_commits), commit.commit_hash,
+                                  None)
+            continue
+
+        meta = filtered_utils.get_metadata(commit.commit_hash)
+        if progress_callback:
+            progress_callback(i, len(pending_commits), commit.commit_hash, meta)
+
+        # Read diff and parent tree.
+        diff_with_parent = libchrome_filter.filter_diff(
+            utils.git_difftree(meta.parents[0] if meta.parents else None,
+                               commit.commit_hash))
+        git_lazytree = lazytree.LazyTree(
+            filtered_utils.
+            get_metadata(find_filtered_commit(meta.parents[0], commits_map)
+                        ).tree if meta.parents else None)
+
+        if len(meta.parents) <= 1 and len(diff_with_parent) == 0:
+            # not merge commit    AND no diff
+            if len(meta.parents) == 1 and meta.parents[0] in commits_map:
+                commits_map[commit.commit_hash] = commits_map[meta.parents[0]]
+                # Check if [i, i+look_forward] has no changes.
+                look_forward_until, ignore_look_forward_until = check_look_forward(
+                    pending_commits, commit, meta, i, look_forward,
+                    ignore_look_forward_until, commits_map, libchrome_filter)
+            continue
+
+        # Apply diff and commit.
+        for op, f in diff_with_parent:
+            if op == utils.DiffOperations.ADD or op == utils.DiffOperations.REP:
+                git_lazytree[f.path] = f
+            elif op == utils.DiffOperations.DEL:
+                del git_lazytree[f.path]
+        treehash_after_diff_applied = git_lazytree.hash()
+        filtered_commit = do_commit(treehash_after_diff_applied,
+                                    commit.commit_hash, meta, commits_map,
+                                    commit_hash_meta_name)
+        if commit_callback:
+            commit_callback(commit.commit_hash, filtered_commit, meta)
+        commits_map[commit.commit_hash] = filtered_commit
+        last_commit = filtered_commit
+        if len(meta.parents) > 1 or (i - last_verified >=
+                                     _VERIFY_INTEGRITY_DISTANCE):
+            # merge commit    OR  every _VERIFY_INTEGRITY_DISTANCE
+            last_verified = i
+            verify_commit(libchrome_filter, commit.commit_hash,
+                          treehash_after_diff_applied)
+    # Verify last commit
+    if last_commit:
+        verify_commit(libchrome_filter, pending_commits[-1].commit_hash,
+                      filtered_utils.get_metadata(last_commit).tree)
+    return last_commit
+
+
+def main():
+    # Init args
+    parser = argparse.ArgumentParser(description='Copy file from given commits')
+    parser.add_argument(
+        'parent_filtered',
+        metavar='parent_filtered',
+        type=str,
+        nargs=1,
+        help=
+        'commit hash in filtered branch to continue from. usually HEAD of that branch.'
+    )
+    parser.add_argument('goal_browser',
+                        metavar='goal_browser',
+                        type=str,
+                        nargs=1,
+                        help='commit hash in browser master branch.')
+    parser.add_argument(
+        '--filter_files',
+        metavar='filter_files',
+        type=str,
+        help=
+        'Path a file which should contain file paths to be checked in each line. This overwrites the default file filtering rules, if given.',
+        nargs='?')
+    parser.add_argument(
+        '--commit_hash_meta_name',
+        metavar='commit_hash_meta_name',
+        type=str,
+        default=filtered_utils.CROS_LIBCHROME_ORIGINAL_COMMIT.decode('utf-8'),
+        help=
+        'Machine-and-people redable metadata key for original commit hash. This overwrites the default value, if given.',
+        nargs='?')
+
+    parser.add_argument('--dry_run',
+                        dest='dry_run',
+                        action='store_const',
+                        const=True,
+                        default=False)
+    parser.add_argument('--verbose',
+                        dest='verbose',
+                        action='store_const',
+                        const=True,
+                        default=False)
+    parser.add_argument('--quiet',
+                        dest='quiet',
+                        action='store_const',
+                        const=True,
+                        default=False)
+
+    arg = parser.parse_args(sys.argv[1:])
+
+    if arg.quiet:
+        INFO = VERBOSE = open(os.devnull, 'w')
+    elif arg.verbose:
+        INFO = sys.stderr
+        VERBOSE = sys.stderr
+    else:
+        INFO = sys.stderr
+        VERBOSE = open(os.devnull, 'w')
+
+    # Init filters
+    if arg.filter_files:
+        with open(arg.filter_files) as f:
+            lines = [line.strip().encode('utf-8') for line in f]
+        libchrome_filter = filters.Filter([filters.PathFilter(lines)], [], [])
+        print('Filter loaded', file=INFO)
+    else:
+        libchrome_filter = filters.Filter(filter_config.WANT,
+                                          filter_config.WANT_EXCLUDE,
+                                          filter_config.ALWAYS_WANT)
+
+    # Look for last known commit made by the script in filtered branch.
+    print('Looking for last known commit from',
+          arg.parent_filtered[0],
+          file=INFO)
+    last_known, meta_last_known = get_start_commit_of_browser_tree(
+        arg.parent_filtered[0].encode('utf-8'))
+    if last_known:
+        print('Continuing from', last_known, meta_last_known, file=INFO)
+    else:
+        print('No known last commit', file=INFO)
+    print('parent on filter branch', arg.parent_filtered[0], file=INFO)
+
+    # Get a mapping between browser repository and filtered branch for commits
+    # in filtered branch.
+    print('reading commits details for commits mapping', file=INFO)
+    timing_deque = collections.deque([time.time()])
+    commits_map = filtered_utils.get_commits_map(
+        arg.parent_filtered[0], lambda cur_idx, tot_cnt, cur_hash:
+        (print('Reading',
+               cur_hash,
+               '%d/%d' % (cur_idx, tot_cnt),
+               '%f c/s' % timing(timing_deque),
+               end='\r',
+               file=VERBOSE,
+               flush=True),))
+    if not 'ROOT' in commits_map:
+        commits_map['ROOT'] = subprocess.check_output(
+            [
+                'git', 'commit-tree', '-p', arg.parent_filtered[0],
+                utils.git_mktree([])
+            ],
+            input=filtered_utils.CROS_LIBCHROME_INITIAL_COMMIT).strip(b'\n')
+    print(file=VERBOSE)
+    print('loaded commit mapping of', len(commits_map), 'commit', file=INFO)
+
+    # If last_known is not parent_filtered, which means some other commits are
+    # made after last_known, use parent_filtered as HEAD to connect.
+    if last_known and last_known != arg.parent_filtered[0].encode('utf-8'):
+        assert meta_last_known.original_commits[0] in commits_map
+        commits_map[meta_last_known.original_commits[0]] = arg.parent_filtered[
+            0].encode('ascii')
+
+    # Process newer commits in browser repository from
+    # last_known.original_commits
+    print('search for commits to filter', file=INFO)
+    timing_deque = collections.deque([time.time()])
+    pending_commits = utils.git_revlist(
+        meta_last_known.original_commits[0] if meta_last_known else None,
+        arg.goal_browser[0])
+    print(len(pending_commits), 'commits to process', file=INFO)
+    new_head = process_commits(
+        libchrome_filter,
+        pending_commits,
+        commits_map,
+        # Use look_forward=1000 if filter_files is set.
+        # This is used to generate a small sets of newly wanted files.
+        1000 if arg.filter_files else None,
+        arg.commit_hash_meta_name.encode('utf-8'),
+        # Print progress
+        lambda cur_idx, tot_cnt, cur_hash, cur_meta:
+        (print('Processing',
+               cur_hash,
+               '%d/%d' % (cur_idx, tot_cnt),
+               '%f c/s' % timing(timing_deque, update=False),
+               'eta %s' % (datetime.timedelta(seconds=int(
+                   (tot_cnt - cur_idx) / timing(timing_deque)))),
+               cur_meta.title[:50] if cur_meta else '',
+               end='\r',
+               file=VERBOSE,
+               flush=True),),
+        # Print new commits
+        lambda orig_hash, new_hash, commit_meta: print(
+            b'%s is commited as %s: %s' %
+            (orig_hash, new_hash, commit_meta.title[:50]),
+            file=INFO))
+    print(file=VERBOSE)
+    if new_head:
+        print(new_head.decode('ascii'))
+
+
+if __name__ == '__main__':
+    main()
diff --git a/libchrome_tools/developer-tools/uprev/lazytree.py b/libchrome_tools/developer-tools/uprev/lazytree.py
new file mode 100644
index 0000000..819e9af
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/lazytree.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import subprocess
+
+import utils
+
+GIT_LSTREE_RE_LINE = re.compile(rb'^([^ ]*) ([^ ]*) ([^ ]*)\t(.*)$')
+
+
+class LazyTree:
+    """LazyTree does git mktree lazily."""
+
+    def __init__(self, treehash=None):
+        """Initializes a LazyTree.
+
+        If treehash is not None, it initializes as the tree object.
+
+        Args:
+            treehash: tree object id. please do not use a treeish, it will fail
+                later.
+        """
+        if treehash:
+            self._treehash = treehash  # tree object id of current tree
+            self._subtrees = None  # map from directory name to sub LazyTree
+            self._files = None  # map from file naem to utils.GitFile
+            return
+        # Initialize an empty LazyTree
+        self._treehash = None
+        self._subtrees = {}
+        self._files = {}
+
+    def _loadtree(self):
+        """Loads _treehash into _subtrees and _files."""
+        if self._files is not None:  # _subtrees is also not None too here.
+            return
+        output = subprocess.check_output(['git', 'ls-tree',
+                                          self._treehash]).split(b'\n')
+        self._files = {}
+        self._subtrees = {}
+        for line in output:
+            if not line:
+                continue
+            m = GIT_LSTREE_RE_LINE.match(line)
+            mode, gittype, objecthash, name = m.groups()
+            assert gittype == b'blob' or gittype == b'tree'
+            assert name not in self._files and name not in self._subtrees
+            if gittype == b'blob':
+                self._files[name] = utils.GitFile(None, mode, objecthash)
+            elif gittype == b'tree':
+                self._subtrees[name] = LazyTree(objecthash)
+
+    def _remove(self, components):
+        """Removes components from self tree.
+
+        Args:
+            components: the path to remove, relative to self. Each element means
+                one level of directory tree.
+        """
+        self._loadtree()
+        self._treehash = None
+        if len(components) == 1:
+            del self._files[components[0]]
+            return
+
+        # Remove from subdirectory
+        dirname, components = components[0], components[1:]
+        subdir = self._subtrees[dirname]
+        subdir._remove(components)
+        if subdir.is_empty():
+            del self._subtrees[dirname]
+
+    def __delitem__(self, path):
+        """Removes path from self tree.
+
+        Args:
+            path: the path to remove, relative to self.
+        """
+        components = path.split(b'/')
+        self._remove(components)
+
+    def _get(self, components):
+        """Returns a file at components in utils.GitFile from self tree.
+
+        Args:
+            components: path in list instead of separated by /.
+        """
+        self._loadtree()
+        if len(components) == 1:
+            return self._files[components[0]]
+
+        dirname, components = components[0], components[1:]
+        return self._subtrees[dirname]._get(components)
+
+    def __getitem__(self, path):
+        """Returns a file at path in utils.GitFile from tree.
+
+        Args:
+            path: path of the file to read.
+        """
+        components = path.split(b'/')
+        return self._get(components)
+
+    def _set(self, components, f):
+        """Adds or replace a file.
+
+        Args:
+            components: the path to set, relative to self. Each element means
+                one level of directory tree.
+            f: a utils.GitFile object.
+        """
+
+        self._loadtree()
+        self._treehash = None
+        if len(components) == 1:
+            self._files[components[0]] = f
+            return
+
+        # Add to subdirectory
+        dirname, components = components[0], components[1:]
+        if dirname not in self._subtrees:
+            self._subtrees[dirname] = LazyTree()
+        self._subtrees[dirname]._set(components, f)
+
+    def __setitem__(self, path, f):
+        """Adds or replaces a file.
+
+        Args:
+            path: the path to set, relative to self
+            f: a utils.GitFile object
+        """
+        assert f.path.endswith(path)
+        components = path.split(b'/')
+        self._set(components, f)
+
+    def is_empty(self):
+        """Returns if self is an empty tree."""
+        return not self._subtrees and not self._files
+
+    def hash(self):
+        """Returns the hash of current tree object.
+
+        If the object doesn't exist, create it.
+        """
+        if not self._treehash:
+            self._treehash = self._mktree()
+        return self._treehash
+
+    def _mktree(self):
+        """Recreates a tree object recursively.
+
+        Lazily if subtree is unchanged.
+        """
+        keys = list(self._files.keys()) + list(self._subtrees.keys())
+        mktree_input = []
+        for name in sorted(keys):
+            file = self._files.get(name)
+            if file:
+                mktree_input.append(b'%s blob %s\t%s' %
+                                    (file.mode, file.id, name))
+            else:
+                mktree_input.append(b'040000 tree %s\t%s' %
+                                    (self._subtrees[name].hash(), name))
+        return subprocess.check_output(
+            ['git', 'mktree'], input=b'\n'.join(mktree_input)).strip(b'\n')
diff --git a/libchrome_tools/developer-tools/uprev/merge_main b/libchrome_tools/developer-tools/uprev/merge_main
new file mode 100755
index 0000000..44224fc
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/merge_main
@@ -0,0 +1,24 @@
+#!/bin/bash
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# ./merge_main
+# Merge m/main to current workspace, and reset the merged result as
+# (p1=m/main, p2=current:p2) with the same commit message.
+# This can be used to update the current commit when m/main has new changes
+# during uprev work period.
+PARENT=$(git cat-file commit HEAD | egrep '^parent' | tail -n 1 | cut -d' ' -f2)
+MSG="$(git cat-file commit HEAD | tail -n +7)"
+# Extract author from the commit message with reformatting as follows:
+#  author First Last <user@chromium.org> 1622110244 +0900 => First Last <user@chromium.org>
+AUTHOR="$(git cat-file commit HEAD | grep '^author' | head -n 1 | sed -e 's/^author \(.*\) [0-9]* [-+][0-9]*/\1/g')"
+AUTHOR_NAME="$(echo "$AUTHOR" | sed -e 's/ <.*>//g')"
+AUTHOR_EMAIL="$(echo "$AUTHOR" | sed -e 's/.*<\(.*\)>/\1/g')"
+
+git merge m/main
+(source ~/.bashrc; env PS1="change >" bash --norc)
+
+TREE=$(git cat-file commit HEAD | egrep '^tree' | cut -d' ' -f2)
+NEW=$(GIT_AUTHOR_NAME="$AUTHOR_NAME" GIT_AUTHOR_EMAIL="$AUTHOR_EMAIL" git commit-tree "$TREE" -p m/main -p "$PARENT" < <(echo "$MSG"))
+git reset --hard "$NEW"
diff --git a/libchrome_tools/developer-tools/uprev/reconnect_history.py b/libchrome_tools/developer-tools/uprev/reconnect_history.py
new file mode 100755
index 0000000..fabdd84
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/reconnect_history.py
@@ -0,0 +1,327 @@
+#!/usr/bin/env python3
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+Utility to disconnect history of files from a branch, and reconnect with base on
+a different branch.
+"""
+
+import argparse
+import collections
+import subprocess
+import sys
+
+import filtered_utils
+import lazytree
+import utils
+
+
+class CommitMetadataFactory(dict):
+    """Dict-like class to read commit metadata"""
+
+    def __missing__(self, key):
+        """Reads commit metadata if missing"""
+        value = filtered_utils.get_metadata(key)
+        self.__setitem__(key, value)
+        return value
+
+
+def disconnect(source_commit, ref_commit):
+    """Creates a commit that disconnects files from source_commit.
+
+    All files existing in ref_commit will be removed from source_commit.
+
+    Args:
+        source_commit: commit hash to disconnect from.
+        ref_commit: commit hash to be a file list reference.
+    """
+    source_files = utils.get_file_list(source_commit)
+    ref_files = utils.get_file_list(ref_commit)
+    ref_files_set = set(ref.path for ref in ref_files)
+    kept_files = [ref for ref in source_files if ref.path not in ref_files_set]
+    tree = utils.git_mktree(kept_files)
+    return utils.git_commit(tree, [source_commit],
+                            message=b'Disconnect history from %s' %
+                            (source_commit.encode('ascii')))
+
+
+def connect_base(current_commit, base_commit):
+    """Creates a merge commit that takes files from base_commit.
+
+    Literally it's identical to git merge base_commit in current_commit.
+
+    Args:
+        current_commit: commit hashes on where to commit to.
+        base_commit: commit hashes contains file histories.
+    """
+    current_files = utils.get_file_list(current_commit)
+    base_files = utils.get_file_list(base_commit)
+    tree = utils.git_mktree(current_files + base_files)
+    return utils.git_commit(tree, [current_commit, base_commit],
+                            message=b'Connect history with base %s' %
+                            (base_commit.encode('ascii')))
+
+
+def blame_files(commithash, files):
+    """Blames files on givven commithash"""
+    blames = {}
+    for path in files:
+        blames[path] = utils.git_blame(commithash, path)
+    return blames
+
+
+def search_blame_line(blames, amend_commits, target_commit_hash):
+    """Searches blames matching target_commit_hash in amend_commits
+
+    Returns a map from file path to a list of tuple, each tuple has
+    len(amend_commits) + 1 elements.  0-th element is the line in blames. and
+    1st to n-th element are corresponding lines in amend_commits blaems.
+
+    Args:
+        blames: a dict from path to list of GitBlameLine, for files blamed on
+            target_commit_hash.
+        amend_commits: a list of commit hashes to provide actual history.
+        target_commit_hash: commit hash that blames are blaemd on.
+    """
+    blames_combined = {}
+    for blame_file_path, blame_file in blames.items():
+        blames_amend = [
+            utils.git_blame(commit, blame_file_path) for commit in amend_commits
+        ]
+        blames_combined[blame_file_path] = [
+            blame_combined for blame_combined in zip(blame_file, *blames_amend)
+            if blame_combined[0].commit == target_commit_hash
+        ]
+    return blames_combined
+
+
+def get_track_from_blames(blames_combined, virtual_goal_commit, amend_commits,
+                          commit_choice_cache, commit_msg_cache):
+    """Blames diffs and locate the amend commits.
+
+    Returns a tuple containing:
+     - a set of commit hashes in amend_commits tree;
+     - a line-by-line mapping for files in diff to commit hashes in
+       amend_commits tree of diffed lines.
+
+    Args:
+        blames_combined: a map from path to a list of tuple. each tuple reflect
+            one line, and has len(amend_commits)+1 elements. See more details in
+            search_blame_line.
+        virtual_goal_commit: a commit that contains no useful history for diffs.
+        amend_commits: list of HEAD commit hashes that refers to tree that can
+            amend the diffs.
+        commit_choice_cache: caches user choice on which amend commit to use.
+        commit_msg_cache: caches commit metadata.
+    """
+    blame_untracked_lines = {}
+    commits_to_track = set()
+
+    for blame_file_path, blame_lines in blames_combined.items():
+        blame_untracked_lines[blame_file_path] = []
+        for blame_line in blame_lines:
+            original_commits = tuple(
+                blame_amend.commit for blame_amend in list(blame_line)[1:])
+            chosen = commit_choice_cache.get(original_commits)
+            if chosen is None:
+                for idx, original_commit in enumerate(original_commits):
+                    print('%d: %s' %
+                          (idx, commit_msg_cache[original_commit].title))
+                # No validation on user_choice since no untrusted user.
+                # Also the developer can rerun if entered wrongly by accident.
+                user_choice = int(input('Choose patch: '))
+                chosen = original_commits[user_choice]
+                commit_choice_cache[original_commits] = chosen
+            commits_to_track.add(chosen)
+            blame_untracked_lines[blame_file_path].append(
+                (blame_line[0], chosen))
+
+    return commits_to_track, blame_untracked_lines
+
+
+def reconstruct_file(blame_goal, blame_base, lines_to_reconstruct,
+                     virtual_goal_commit):
+    """Reconstrucs a file to reflect changes in lines_to_reconstruct.
+
+    Takes lines to blame_base, and blame_goal it belongs lines_to_reconstruct.
+    It also deletes removed lines nearby.
+
+    Returns a binary for the new file content.
+
+    Args:
+        blame_goal: a list of utils.GitBlameLine blaming the file on
+            virtual_goal_commit.
+        blame_base: a list of utils.GitBlameLine blaming the file on last
+            commited commit.
+        lines_to_reconstruct: only to reconstruct these lines, instead of
+            everything in blame_goal. It is represented in a list of
+            GitBlameLine.
+        virtual_goal_commit: commit hash where blame_goal is based on.
+    """
+    idx_base, idx_goal = 0, 0
+    reconstructed_file = []
+
+    print('Changed lines are', [line.data for line in lines_to_reconstruct])
+    line_iter = iter(lines_to_reconstruct)
+    line = next(line_iter, None)
+    while idx_base < len(blame_base) or idx_goal < len(blame_goal):
+        # Both sides are idendical. We can't compare blame_base, and line
+        # directly due to blame commit difference could end up different lineno.
+        if (idx_base < len(blame_base) and
+                blame_base[idx_base].data == blame_goal[idx_goal].data and
+                blame_base[idx_base].commit == blame_goal[idx_goal].commit):
+            # We append this line if both sides are identical.
+            reconstructed_file.append(blame_base[idx_base].data)
+            idx_base += 1
+            idx_goal += 1
+            should_skip_base = False
+        elif line and blame_goal[idx_goal] == line:
+            # We append the line from goal, if blame_goal[idx_goal] is the line
+            # we're interested in.
+            reconstructed_file.append(line.data)
+            line = next(line_iter, None)
+            idx_goal += 1
+            should_skip_base = True
+        elif blame_goal[idx_goal].commit == virtual_goal_commit:
+            # We skip the line from goal, if the change in not in the commit
+            # we're interested. Thus, changed lines in other commits will not be
+            # reflected.
+            idx_goal += 1
+        else:
+            # We should skip base if we just appended some lines from goal.
+            # This would treat modified lines and append first and skip later.
+            # If we didn't append something from goal, lines from base should be
+            # preserved because the modified lines are not in the commit we're
+            # currently interested in.
+            if not should_skip_base:
+                reconstructed_file.append(blame_base[idx_base].data)
+            idx_base += 1
+
+    return b''.join([line + b'\n' for line in reconstructed_file])
+
+
+def reconstruct_files(track_commit, blame_untracked_lines, blames,
+                      current_base_commit, virtual_goal_commit):
+    """Reconstructs files to reflect changes in track_commit.
+
+    Returns a map from file path to file content for reconstructed files.
+
+    Args:
+        track_commit: commit hashes to track, and reconstruct from.
+        blame_untracked_lines: a line-by-line mapping regarding selected amend
+            commits for diffs. see get_track_from_blames for more.
+        blames: a map from filename to list of utils.GitBlameLine
+        current_base_commit: commit hashes for HEAD of base that contains base
+            history + already committed amend history.
+        virtual_goal_commit: commit hash for one giant commit that has no
+            history.  virtual_goal_commit is one commit ahead of
+            current_base_commit.
+    """
+    lines_to_track = collections.defaultdict(list)
+    for file, lines in blame_untracked_lines.items():
+        for line in lines:
+            if line[1] == track_commit:
+                lines_to_track[file].append(line[0])
+    constructed_files = {}
+    for current_file, current_file_lines in lines_to_track.items():
+        print('Reconstructing', current_file, 'for', track_commit)
+        blame_base = utils.git_blame(current_base_commit, current_file)
+        constructed_files[current_file] = reconstruct_file(
+            blames[current_file], blame_base, current_file_lines,
+            virtual_goal_commit)
+    return constructed_files
+
+
+def main():
+    # Init args
+    parser = argparse.ArgumentParser(description='Reconnect git history')
+    parser.add_argument('disconnect_from',
+                        metavar='disconnect_from',
+                        type=str,
+                        nargs=1,
+                        help='disconnect history from this commit')
+    parser.add_argument('base_commit',
+                        metavar='base_commit',
+                        type=str,
+                        nargs=1,
+                        help='base commit to use the history')
+    parser.add_argument('amend_commits',
+                        metavar='amend_commits',
+                        type=str,
+                        nargs='+',
+                        help='commits to amend histories from base_commit')
+
+    arg = parser.parse_args(sys.argv[1:])
+    empty_commit = disconnect(arg.disconnect_from[0], arg.base_commit[0])
+    connected_base = connect_base(empty_commit, arg.base_commit[0])
+
+    commit_msg_cache = CommitMetadataFactory()
+    commit_choice_cache = {}
+    last_commit = connected_base
+    # In each iteration of the loop, it
+    #  - re-create the new goal commit, (base + committed history + (one giant)
+    #  uncommited history).
+    #  - blame on new goal commit and tot of amend commits. map line-by-line
+    #  from uncommited to past histories.
+    #  - choose one of the past commits, reconstruct files to reflect changes in
+    #  that commit, and create a new commits.
+    # last_commit, commit_msg_cache, commit_choice_cache will be persistent
+    # across iteratins.
+    while True:
+        # One commit is processed per iteration.
+
+        # Create virtual target commit, and its diff.
+        virtual_goal = utils.git_commit(arg.disconnect_from[0] + '^{tree}',
+                                        [last_commit])
+        diffs = utils.git_difftree(None, virtual_goal)
+        if not diffs:
+            print('No diffs are found between %s and goal.' %
+                  (last_commit.decode('ascii'),))
+            break
+
+        blames = blame_files(virtual_goal, [diff.file.path for diff in diffs])
+        blames_combined = search_blame_line(blames, arg.amend_commits,
+                                            virtual_goal)
+
+        commits_to_track, blame_untracked_lines = get_track_from_blames(
+            blames_combined, virtual_goal, arg.amend_commits,
+            commit_choice_cache, commit_msg_cache)
+        if not commits_to_track:
+            print('no commits to track, stopping')
+            break
+
+        # Stablely choose one commit from commits_to_track, and reconstruct it.
+        track_commit = min(commits_to_track)
+        print('Reconstructing commit %s: %s' %
+              (track_commit, commit_msg_cache[track_commit].title))
+        constructed_files = reconstruct_files(track_commit,
+                                              blame_untracked_lines, blames,
+                                              last_commit, virtual_goal)
+
+        # Mktree and commit with re-constructed_files.
+        tree = lazytree.LazyTree(filtered_utils.get_metadata(last_commit).tree)
+        for filename, filedata in constructed_files.items():
+            blob = subprocess.check_output(
+                ['git', 'hash-object', '-w', '/dev/stdin'],
+                input=filedata).strip()
+            tree[filename] = utils.GitFile(filename, tree[filename].mode, blob)
+        meta = commit_msg_cache[track_commit]
+        last_commit = utils.git_commit(
+            tree.hash(), [last_commit],
+            (meta.message + b'\n(Reconstructed from ' + track_commit + b')\n'),
+            dict(GIT_AUTHOR_NAME=meta.authorship.name,
+                 GIT_AUTHOR_EMAIL=meta.authorship.email,
+                 GIT_AUTHOR_DATE=b' '.join(
+                     [meta.authorship.time, meta.authorship.timezone])))
+        print('Reconstructed as', last_commit)
+    # Make last commit for history reconstruction.
+    print(
+        utils.git_commit(
+            filtered_utils.get_metadata(arg.disconnect_from[0]).tree,
+            [last_commit],
+            b'Finished history reconstruction\n\nRemoving unnecessary lines\n'))
+
+
+if __name__ == '__main__':
+    main()
diff --git a/libchrome_tools/developer-tools/uprev/run_tests.py b/libchrome_tools/developer-tools/uprev/run_tests.py
new file mode 100755
index 0000000..e6ffa34
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/run_tests.py
@@ -0,0 +1,17 @@
+#!/usr/bin/env python3
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+Run ./run_tests.py to run all unittests
+"""
+
+import unittest
+
+
+def load_tests(loader, tests, pattern):
+    return loader.discover('.')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/libchrome_tools/developer-tools/uprev/test_filters.py b/libchrome_tools/developer-tools/uprev/test_filters.py
new file mode 100644
index 0000000..fc84ee7
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/test_filters.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python3
+# Copyright 2021 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import re
+import unittest
+
+import filters
+import utils
+
+
+class TestFilters(unittest.TestCase):
+
+    def _build_file_list(self, files):
+        return [
+            utils.GitFile(path.encode(), None, hash(path)) for path in files
+        ]
+
+    def test_filters(self):
+        test_filter = filters.Filter([re.compile(rb'want.*')],
+                                     [re.compile(rb'want_excluded.*')],
+                                     [re.compile(rb'want_excluded_always.*')])
+
+        self.assertEquals(
+            test_filter.filter_files(
+                self._build_file_list([
+                    'want/xxx',
+                    'want_excluded/xxx',
+                    'want_excluded_always/xxx',
+                    'unrelated_upstream_file',
+                ])),
+            self._build_file_list(
+                ['want/xxx', 'want_excluded_always/xxx']),
+        )
+
+    def test_path_filter(self):
+        test_filter = filters.Filter([filters.PathFilter([b'a/b/c', b'd'])], [],
+                                     [])
+
+        self.assertEquals(
+            test_filter.filter_files(
+                self._build_file_list(
+                    ['a', 'b', 'c', 'a/b', 'b/c', 'a/b/c', 'd'])),
+            self._build_file_list(['a/b/c', 'd']))
diff --git a/libchrome_tools/developer-tools/uprev/update_upstream.py b/libchrome_tools/developer-tools/uprev/update_upstream.py
new file mode 100755
index 0000000..acc6836
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/update_upstream.py
@@ -0,0 +1,248 @@
+#!/usr/bin/env python3
+# Copyright 2021 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+Script to generate cros/upstream branch.
+
+Usage: update_upstream.py [--delete | --add | --forward | --all]
+
+--delete: Run delete stage to delete unnecessary files. Create one single commit
+to delete unnecessary files.
+--add: Run add stage to add new files. Create a series of commits containing the
+history of new files, and one merge commit to add to cros/upstream.
+--forward: Run forward stage to update to newer version. Create a series commits
+to update cros/upstream to newer revision.
+--all: Run all stages. equals to --delete --add --forward
+"""
+
+import argparse
+import subprocess
+import sys
+import tempfile
+
+import filter_config
+import filtered_utils
+import filters
+import lazytree
+import utils
+
+GENERATED_FILTERED_TREE = 'libchrome_tools/developer-tools/uprev/generate_filtered_tree.py'
+CROS_LIBCHROME_RECOVERED_FROM_COMMIT = b'CrOS-Libchrome-Recovered-From-Commit'
+INITIAL_COMMIT = 'ba8bd83211d4bbca7a48793d567b06d5d4451005'
+
+
+def verify_tree(current):
+    """ Verifies current commit has the filtered files matching filter_config.
+
+    Returns True if if's correct, False otherwise.
+
+    Args:
+        current: current cros/upstream commit hash.
+    """
+    current_metadata = filtered_utils.get_metadata(current)
+    original_commit = current_metadata.original_commit_cursor
+    new_filter = filters.Filter(filter_config.WANT, filter_config.WANT_EXCLUDE,
+                                filter_config.ALWAYS_WANT)
+    expected_tree = lazytree.LazyTree()
+    for f in utils.get_file_list(original_commit):
+        if new_filter.want_file(f.path):
+            expected_tree[f.path] = f
+
+    return expected_tree.hash() == current_metadata.tree
+
+
+def verify_author(current):
+    """ Verifies current commit has the same authorship as original commit.
+
+    Returns True if if's correct, False otherwise.
+
+    Args:
+        current: current cros/upstream commit hash.
+    """
+    current_metadata = filtered_utils.get_metadata(current)
+    original_commit = current_metadata.original_commit_cursor
+    original_metadata = filtered_utils.get_metadata(original_commit)
+
+    return current_metadata.authorship == original_metadata.authorship
+
+
+def delete(current):
+    """ Deletes unnecessary files for new filters.
+
+    Returns a string containing the commit after delete.
+
+    Args:
+        current: current cros/upstream commit hash.
+    """
+    current_metadata = filtered_utils.get_metadata(current)
+    original_commit = current_metadata.original_commit_cursor
+    new_filter = filters.Filter(filter_config.WANT, filter_config.WANT_EXCLUDE,
+                                filter_config.ALWAYS_WANT)
+    tree = lazytree.LazyTree(current_metadata.tree)
+    current_files = utils.get_file_list(current)
+
+    for f in current_files:
+        if not new_filter.want_file(f.path):
+            del tree[f.path]
+
+    if tree.hash() == current_metadata.tree:
+        return current
+
+    msg = b'Remove unnecessary files due to filter change\n\n%s: %s' % (
+        filtered_utils.CROS_LIBCHROME_CURRENT_COMMIT, original_commit)
+    new_commit = subprocess.check_output(
+        ['git', 'commit-tree', '-p', current,
+         tree.hash()], input=msg).strip()
+    return new_commit.decode('ascii')
+
+
+def add(current):
+    """ Adds newly wanted files for new filters.
+
+    Args:
+        current: current cros/upstream commit hash.
+    """
+    current_metadata = filtered_utils.get_metadata(current)
+    original_commit = current_metadata.original_commit_cursor
+    new_filter = filters.Filter(filter_config.WANT, filter_config.WANT_EXCLUDE,
+                                filter_config.ALWAYS_WANT)
+
+    tree = lazytree.LazyTree()
+
+    original_files = utils.get_file_list(original_commit)
+    new_files = set(new_filter.filter_files(original_files))
+    for f in new_files:
+        if new_filter.want_file(f.path):
+            tree[f.path] = f
+
+    if tree.hash() == current_metadata.tree:
+        return current
+
+    old_files = set(utils.get_file_list(current))
+    files_to_add = list(new_files.difference(old_files))
+
+    if not files_to_add:
+        return current
+
+    proc = subprocess.run([
+        GENERATED_FILTERED_TREE,
+        INITIAL_COMMIT,
+        original_commit,
+        '--commit_hash_meta_name',
+        CROS_LIBCHROME_RECOVERED_FROM_COMMIT,
+        '--filter_files',
+        '/dev/stdin',
+    ],
+                          input=b''.join(f.path + b'\n' for f in files_to_add),
+                          stdout=subprocess.PIPE)
+    assert proc.returncode == 0
+    last_commit = proc.stdout.strip().decode('ascii')
+
+    current_tree = lazytree.LazyTree(current_metadata.tree)
+    new_file_history_head_filelist = utils.get_file_list(last_commit)
+    for f in new_file_history_head_filelist:
+        current_tree[f.path] = f
+
+    assert tree.hash() == current_tree.hash(), (tree.hash(),
+                                                current_tree.hash())
+
+    msg = b'Add new files due to filter change\n\n%s: %s' % (
+        filtered_utils.CROS_LIBCHROME_CURRENT_COMMIT, original_commit)
+    new_commit = subprocess.check_output(
+        ['git', 'commit-tree', '-p', current, '-p', last_commit,
+         tree.hash()],
+        input=msg).strip()
+    return new_commit.decode('ascii')
+
+
+def forward(current, target):
+    """ Forwards to given upstream Chromium commit.
+
+    Returns a string containing the commit after forward.
+
+    Args:
+        current: current cros/upstream commit hash.
+        target: target commit in Chromium src tree.
+    """
+    proc = subprocess.run([
+        GENERATED_FILTERED_TREE,
+        current,
+        target,
+    ],
+                          stdout=subprocess.PIPE)
+    assert proc.returncode == 0
+    return proc.stdout.strip().decode('ascii')
+
+
+def main():
+    # Init args
+    parser = argparse.ArgumentParser(
+        description='Generate Libchrome Upstream Branch')
+    parser.add_argument(
+        'current',
+        metavar='current',
+        type=str,
+        help='commit hash to start from, usually use cros/upstream.')
+    parser.add_argument(
+        'target',
+        metavar='target',
+        type=str,
+        help='commit hash in browser tot. only useful if --forward is enabled.')
+
+    parser.add_argument('--all',
+                        dest='all',
+                        action='store_const',
+                        const=True,
+                        default=False,
+                        help='Run all stages.')
+    parser.add_argument('--delete',
+                        dest='delete',
+                        action='store_const',
+                        const=True,
+                        default=False,
+                        help='Run delete files stage.')
+    parser.add_argument('--add',
+                        dest='add',
+                        action='store_const',
+                        const=True,
+                        default=False,
+                        help='Run add files stage.')
+    parser.add_argument('--forward',
+                        dest='forward',
+                        action='store_const',
+                        const=True,
+                        default=False,
+                        help='Run forward to <target> stage.')
+
+    args = parser.parse_args(sys.argv[1:])
+
+    current = args.current
+    target = args.target
+
+    assert args.all or args.delete or args.add or args.forward
+
+    if args.all or args.delete:
+        current = delete(current)
+
+    if args.all or args.add:
+        current = add(current)
+
+    if args.all or args.forward:
+        assert verify_tree(
+            current), 'Files must be correctly filtered before forward stage'
+        pre_forward = current
+        current = forward(current, target) or current
+        if current != pre_forward:
+            assert verify_tree(
+                current), 'Files must be correctly filtered after forward stage'
+            # Verify the last commit authorship, to ensure forward process
+            # correctly passed environment variables to git (especially if via
+            # Chromium Infra git wrapper)
+            assert verify_author(current), 'Commit must have original author'
+
+    print(current)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/libchrome_tools/developer-tools/uprev/utils.py b/libchrome_tools/developer-tools/uprev/utils.py
new file mode 100644
index 0000000..e1077b9
--- /dev/null
+++ b/libchrome_tools/developer-tools/uprev/utils.py
@@ -0,0 +1,270 @@
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Provide some basic utility functions for libchrome tools."""
+
+import collections
+import enum
+import os
+import re
+import subprocess
+
+
+class DiffOperations(enum.Enum):
+    """
+    Describes operations on files
+    """
+    ADD = 1
+    DEL = 2
+    REP = 3
+
+
+GitFile = collections.namedtuple('GitFile', [
+    'path',
+    'mode',
+    'id',
+])
+
+GitDiffTree = collections.namedtuple('GitDiffTree', [
+    'op',
+    'file',
+])
+
+GitBlameLine = collections.namedtuple('GitBlameLine', [
+    'data',
+    'commit',
+    'old_line',
+    'new_line',
+])
+
+# Describes a commit from git rev-list
+# It has commit_hash indicating the commit hash of the commit, and parent_hashes
+# (list) indicating the commit hashes of its parents.
+GitCommitInRevList = collections.namedtuple('GitCommitInRevList',
+                                            ['commit_hash', 'parent_hashes'])
+
+GIT_DIFFTREE_RE_LINE = re.compile(
+    rb'^:([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*) ([^ ]*)\t(.*)$')
+
+
+def _reverse(files):
+    """Creates a reverse map from file path to file.
+
+    Asserts if a file path exist only once in files.
+
+    Args:
+        files: list of files.
+    """
+    files_map = {}
+    for i in files:
+        if i.path in files_map:
+            assert i.path not in files_map
+        files_map[i.path] = i
+    return files_map
+
+
+def get_file_list(commit):
+    """Gets a list of the files of the commit.
+
+    Args:
+        commit: commit hash or refs.
+    """
+
+    output = subprocess.check_output(['git', 'ls-tree', '-r',
+                                      commit]).split(b'\n')
+    files = []
+    # Line looks like
+    # mode<space>type<space>id<tab>file name
+    # split by tab first, and by space.
+    re_line = re.compile(rb'^([^ ]*) ([^ ]*) ([^ ]*)\t(.*)$')
+    for line in output:
+        if not line:
+            continue
+        match = re_line.match(line)
+        mode, gittype, blobhash, path = match.groups()
+        if gittype == b'commit':
+            continue
+        assert gittype == b'blob', '%s\n\n%s' % (str(output), line)
+        files.append(GitFile(path, mode, blobhash))
+    return files
+
+
+def git_difftree(treeish1, treeish2):
+    """Gets diffs between treeish1 and treeish2.
+
+    It returns a list of GitDiffTree, each GitDiffTree contains an ADD, DEL or
+    REP operation and a GitFile.
+
+    Args:
+        treeish1, treeish2: treeish to diff.
+            treeish can be tree hash or commit hash. If treeish1 is None, it
+            generate difftrees with its parent.
+    """
+    out = None
+    if treeish1 is None:
+        # Remove first line since it's tree hash printed.
+        out = subprocess.check_output(['git', 'diff-tree', '-r',
+                                       treeish2]).split(b'\n')[1:]
+    else:
+        out = subprocess.check_output(
+            ['git', 'diff-tree', '-r', treeish1, treeish2]).split(b'\n')
+    diff = []
+    for line in out:
+        if not line:
+            continue
+        match = GIT_DIFFTREE_RE_LINE.match(line)
+        oldmode, newmode, oldhash, newhash, typeofchange, path = match.groups()
+        assert typeofchange in b'ADMT', (treeish1, treeish2, line)
+        if typeofchange == b'A':
+            diff.append(
+                GitDiffTree(DiffOperations.ADD, GitFile(path, newmode,
+                                                        newhash)))
+        elif typeofchange == b'D':
+            diff.append(
+                GitDiffTree(DiffOperations.DEL, GitFile(path, oldmode,
+                                                        oldhash)))
+        elif typeofchange == b'M' or typeofchange == b'T':
+            diff.append(
+                GitDiffTree(DiffOperations.REP, GitFile(path, newmode,
+                                                        newhash)))
+        else:
+            raise Exception(b"Unsupported type: " + line)
+    return diff
+
+
+def gen_op(current_files, target_files):
+    """Returns an operation list to convert files to target_files.
+
+    Generates list of operations (add/delete/replace files) if we want to
+    convert current_files in directory to target_files
+
+    Args:
+        current_files: list of files in current directory.
+        target_files: list of files we want it to be in current directory.
+    """
+    current_file_map = _reverse(current_files)
+    target_file_map = _reverse(target_files)
+    op = []
+    for i in sorted(current_file_map):
+        if i not in target_file_map:
+            op.append((DiffOperations.DEL, current_file_map[i]))
+    for i in sorted(target_file_map):
+        if i in current_file_map and current_file_map[i] != target_file_map[i]:
+            op.append((DiffOperations.REP, target_file_map[i]))
+        elif i not in current_file_map:
+            op.append((DiffOperations.ADD, target_file_map[i]))
+    return op
+
+
+def git_mktree(files):
+    """Returns a git tree object hash after mktree recursively."""
+
+    def recursive_default_dict():
+        return collections.defaultdict(recursive_default_dict)
+
+    tree = recursive_default_dict()
+    for f in files:
+        directories = f.path.split(b'/')
+        directories, filename = directories[:-1], directories[-1]
+        cwd = tree
+        for directory in directories:
+            # If cwd is a GitFile, which means a file and a directory shares the
+            # same name.
+            assert type(cwd) == collections.defaultdict
+            cwd = cwd[directory]
+        assert filename not in cwd
+        cwd[filename] = f
+
+    def _mktree(prefix, node):
+        objects = []
+        for name, val in node.items():
+            prefix.append(name)
+            if isinstance(val, collections.defaultdict):
+                tree_hash = _mktree(prefix, val)
+                objects.append(b'\t'.join(
+                    [b' '.join([b'040000', b'tree', tree_hash]), name]))
+            else:
+                path = b'/'.join(prefix)
+                assert path == val.path, '%s\n%s' % (str(path), str(val.path))
+                objects.append(b'\t'.join(
+                    [b' '.join([val.mode, b'blob', val.id]), name]))
+            prefix.pop(-1)
+        return subprocess.check_output(['git', 'mktree'],
+                                       input=b'\n'.join(objects)).strip(b'\n')
+
+    return _mktree([], tree)
+
+
+def git_commit(tree, parents, message=b"", extra_env={}):
+    """Creates a commit.
+
+    Args:
+        tree: tree object id.
+        parents: parent commit id.
+        message: commit message.
+        extra_env: extra environment variables passed to git.
+    """
+    parent_args = []
+    for parent in parents:
+        parent_args.append('-p')
+        parent_args.append(parent)
+    return subprocess.check_output(['git', 'commit-tree', tree] + parent_args,
+                                   input=message,
+                                   env=dict(os.environ,
+                                            **extra_env)).strip(b'\n')
+
+
+def git_revlist(from_commit, to_commit):
+    """Returns a list of commits and their parents.
+
+    Each item in the list is a tuple, containing two elements.
+    The first element is the commit hash; the second element is a list of parent
+    commits' hash.
+    """
+
+    commits = []
+    ret = None
+    if from_commit is None:
+        ret = subprocess.check_output(
+            ['git', 'rev-list', to_commit, '--topo-order', '--parents'])
+    else:
+        # b'...'.join() later requires all variable to be binary-typed.
+        if type(from_commit) == str:
+            from_commit = from_commit.encode('ascii')
+        if type(to_commit) == str:
+            to_commit = to_commit.encode('ascii')
+        commit_range = b'...'.join([from_commit, to_commit])
+        ret = subprocess.check_output(
+            ['git', 'rev-list', commit_range, '--topo-order', '--parents'])
+    ret = ret.split(b'\n')
+    for line in ret:
+        if not line:
+            continue
+        hashes = line.split(b' ')
+        commits.append(GitCommitInRevList(hashes[0], hashes[1:]))
+    return list(reversed(commits))
+
+
+def git_blame(commit, filepath):
+    """Returns line-by-line git blame.
+
+    Return value is represented by a list of GitBlameLine.
+
+    Args:
+        commit: commit hash to blame at.
+        filepath: file to blame.
+    """
+    output = subprocess.check_output(['git', 'blame', '-p', commit, filepath])
+    commit, old_line, new_line = None, None, None
+    blames = []
+    COMMIT_LINE_PREFIX = re.compile(b'^[0-9a-f]* ')
+    for line in output.split(b'\n'):
+        if not line:
+            continue
+        if line[0] == ord(b'\t'):
+            assert commit != None
+            blames.append(GitBlameLine(line[1:], commit, old_line, new_line))
+            commit, old_line, new_line = None, None, None
+        elif COMMIT_LINE_PREFIX.match(line):
+            commit, old_line, new_line = line.split(b' ', 3)[0:3]
+    return blames
diff --git a/libchrome_tools/disable_warnings.py b/libchrome_tools/disable_warnings.py
new file mode 100755
index 0000000..2f6fd4f
--- /dev/null
+++ b/libchrome_tools/disable_warnings.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python3
+# Copyright 2023 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+Tool to add `#pragma`s to libchrome files, so warnings can be disabled.
+
+Some ChromeOS projects require libchrome headers, and want to use more strict
+warnings than Chrome cares to use. This results in the need for `#pragma
+GCC warning disable` blocks around libchrome headers, which get repetitive and
+can be a bit error-prone to work with if used at `#include` sites.
+
+Rather than forcing ChromeOS projects to scatter these `#pragma`s around their
+codebases, this script lets us centralize them in libchrome without having to
+worry about merge conflicts.
+"""
+
+import argparse
+import logging
+import os
+import re
+from pathlib import Path
+import stat
+from typing import Dict, Iterable, List, NamedTuple, Optional, Sequence
+
+
+# A dict of header paths mapped to the series of warnings to disable for the
+# given header.
+WARNINGS_TO_SILENCE: Dict[str, Iterable[str]] = {
+    "base/memory/scoped_refptr.h": ("-Wsign-conversion",),
+    "base/numerics/clamped_math_impl.h": ("-Wimplicit-int-float-conversion",),
+    "base/time/time.h": ("-Wimplicit-int-float-conversion",),
+}
+
+
+def header_path_to_define(header_path: str) -> str:
+    """Turns a header name into a include-guard-like string.
+
+    The returned value is safe for use in a regexp without escaping.
+
+    >>> header_name_to_define("foo.h")
+    "FOO_H"
+    >>> header_name_to_define("foo/bar.h")
+    "FOO_BAR_H"
+    """
+    return re.sub(r"[^a-zA-Z0-9_]", "_", header_path).upper()
+
+
+def add_into_header_guards(
+    add_after_ifndef: str,
+    add_before_endif: str,
+    header_contents: str,
+    header_path: str,
+) -> str:
+    """Adds content between header guards in a C or C++ header.
+
+    Most C and C++ header files have header guards, like:
+
+    ```
+    #ifndef _FOO_H
+    #define _FOO_H
+    /* Meaningful header contents go here. */
+    #endif
+    ```
+
+    For style and build speed reasons, it's best to put all header content
+    between these guards. This function exists to identify these guards, and
+    place text between them.
+
+    Args:
+        add_after_ifndef: Text to add a line after the `#ifdef ... #define`
+           lines in the header.
+        add_before_endif: Text to add on the line before the `#endif` in the
+            header.
+        header_contents: The text of the header to modify.
+        header_path: The path to the header, rooted at libchrome's source.
+
+    Returns:
+        The text of the modified header.
+
+    Raises:
+        ValueError if include guards could not be detected in
+        `header_contents`.
+    """
+    # The heuristc here was selected after discussion on
+    # http://crrev.com/c/4859386.
+    header_define = header_path_to_define(header_path)
+
+    ifndef_regex_text = (
+        r"^\#ifndef\s+("
+        + header_define
+        + r"_?)\b.*?\n"
+        + r"\#define\s+\1\b.*?$"
+    )
+    ifndef_regex = re.compile(ifndef_regex_text, re.MULTILINE)
+
+    found = ifndef_regex.search(header_contents)
+    if not found:
+        raise ValueError("No `#ifndef ... #define` guard found in header")
+
+    # Add 1 so we get past the newline at the end of ifndef_regex.
+    after_ifndef = found.end() + 1
+    endif_regex = re.compile(
+        r"^#endif\s+//\s*" + re.escape(found.group(1)),
+        re.MULTILINE,
+    )
+
+    found = endif_regex.search(header_contents, after_ifndef)
+    if not found:
+        raise ValueError("No `#endif` found after include guard in header")
+
+    before_endif = found.start()
+    return "".join(
+        (
+            header_contents[:after_ifndef],
+            add_after_ifndef,
+            header_contents[after_ifndef:before_endif],
+            add_before_endif,
+            header_contents[before_endif:],
+        )
+    )
+
+
+def add_warnings_pragmas(
+    header_path: str, file_contents: str, warnings: List[str]
+) -> str:
+    """Adds pragmas to ignore `warnings` to the given file."""
+    assert warnings, "warnings lists shouldn't be empty"
+
+    add_after_ifndef_lines = ["#pragma GCC diagnostic push"]
+    for warning in warnings:
+        # No actual warning contains these, and if `warning` has neither
+        # backslashes nor quotes, we can skip quoting the warning.
+        if '"' in warning or "\\" in warning:
+            raise ValueError(f"invalid warning: {repr(warning)}")
+        add_after_ifndef_lines.append(
+            f'#pragma GCC diagnostic ignored "{warning}"'
+        )
+
+    # Ensure we append a trailing '\n' to `add_after_ifndef_lines`.
+    add_after_ifndef_lines.append("")
+    return add_into_header_guards(
+        add_after_ifndef="\n".join(add_after_ifndef_lines),
+        add_before_endif="#pragma GCC diagnostic pop\n",
+        header_contents=file_contents,
+        header_path=header_path,
+    )
+
+
+def main() -> None:
+    parser = argparse.ArgumentParser(
+        description="Disable warnings for select parts of libchrome."
+    )
+    parser.add_argument(
+        "--libchrome-path",
+        default=Path(__file__).resolve().parent.parent,
+        type=Path,
+        help=(
+            "Path of libchrome to apply warnings patches. "
+            "Defaults to parent of this file's directory."
+        ),
+    )
+    parser.add_argument(
+        "--dry-run",
+        action="store_true",
+        help="If specified, patched files won't actually be written.",
+    )
+    args = parser.parse_args()
+    logging.basicConfig(level=logging.INFO)
+
+    libchrome_path = args.libchrome_path
+    dry_run = args.dry_run
+
+    for file_path, all_warnings in sorted(WARNINGS_TO_SILENCE.items()):
+        path = libchrome_path / file_path
+        if path.suffix != ".h":
+            raise ValueError("WARNINGS_TO_SILENCE should only contain headers")
+        warnings = sorted(all_warnings)
+        logging.info("Patching %s to ignore %s...", path, warnings)
+
+        file_contents = path.read_text(encoding="utf-8")
+        new_contents = add_warnings_pragmas(file_path, file_contents, warnings)
+        if dry_run:
+            logging.info("--dry-run passed; skipping write to %s", path)
+        else:
+            path.write_text(new_contents, encoding="utf-8")
+
+
+if __name__ == "__main__":
+    main()
diff --git a/libchrome_tools/disable_warnings_test.py b/libchrome_tools/disable_warnings_test.py
new file mode 100755
index 0000000..e26b1a1
--- /dev/null
+++ b/libchrome_tools/disable_warnings_test.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python3
+# Copyright 2023 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Tests for disable_warnings.py"""
+
+import textwrap
+import unittest
+
+import disable_warnings
+
+
+class Test(unittest.TestCase):
+    """Unittests for disable_warnings.py."""
+
+    def test_header_to_define_works(self):
+        self.assertEqual(
+            disable_warnings.header_path_to_define("foo.h"),
+            "FOO_H",
+        )
+        self.assertEqual(
+            disable_warnings.header_path_to_define("foo/bar.h"),
+            "FOO_BAR_H",
+        )
+        self.assertEqual(
+            disable_warnings.header_path_to_define("b4r_baz.h"),
+            "B4R_BAZ_H",
+        )
+
+    def test_header_guard_detection_fails_on_bad_guards(self):
+        """Ensures that we `raise` if a header has bad guards."""
+
+        def add_into_header_guards(header_contents: str):
+            disable_warnings.add_into_header_guards(
+                add_after_ifndef="",
+                add_before_endif="",
+                header_contents=header_contents,
+                header_path="foo.h",
+            )
+            self.fail("No exception was thrown")
+
+        with self.assertRaisesRegex(ValueError, "^No `#ifndef"):
+            add_into_header_guards("")
+
+        with self.assertRaisesRegex(ValueError, "^No `#ifndef"):
+            add_into_header_guards(
+                textwrap.dedent(
+                    """\
+                    // Copyright bits here
+                    #ifndef FOO_H
+                    #define NOT_FOO_H
+                    #endif
+                    """
+                )
+            )
+
+        with self.assertRaisesRegex(ValueError, "^No `#endif`"):
+            add_into_header_guards(
+                textwrap.dedent(
+                    """\
+                    // Copyright bits here
+                    #ifndef FOO_H
+                    #define FOO_H
+                    int foo();
+                    // #endif
+                    """
+                )
+            )
+
+        with self.assertRaisesRegex(ValueError, "^No `#endif`"):
+            add_into_header_guards(
+                textwrap.dedent(
+                    """\
+                    // Copyright bits here
+                    #endif // FOO_H
+                    #ifndef FOO_H
+                    #define FOO_H
+                    int bar();
+                    #endif // broken ending FOO_H comment
+                    """
+                )
+            )
+
+    def test_header_guard_adds_code_after_guards(self):
+        """Tests a successful case of pragma-adding."""
+        header_before = textwrap.dedent(
+            """\
+            // Copyright bits here
+            #ifndef FOO_H // some comment
+            #define FOO_H // some other comment
+            int foo();
+            #endif  // FOO_H
+            """
+        )
+
+        fixed_header = disable_warnings.add_warnings_pragmas(
+            "foo.h",
+            header_before,
+            ["-Wwarning1", "-Wwarning2"],
+        )
+        self.assertEqual(
+            fixed_header,
+            textwrap.dedent(
+                """\
+                // Copyright bits here
+                #ifndef FOO_H // some comment
+                #define FOO_H // some other comment
+                #pragma GCC diagnostic push
+                #pragma GCC diagnostic ignored "-Wwarning1"
+                #pragma GCC diagnostic ignored "-Wwarning2"
+                int foo();
+                #pragma GCC diagnostic pop
+                #endif  // FOO_H
+                """
+            ),
+        )
+
+    def test_outermost_guards_are_selected(self):
+        """Tests a successful case of pragma-adding with nested guards."""
+        header_before = textwrap.dedent(
+            """\
+            // Copyright bits here
+            #ifndef FOO_H_
+            #define FOO_H_
+
+            #ifndef BAR_H
+            #define BAR_H
+            int foo();
+            #endif  // BAR_H
+
+            #endif  // FOO_H_
+            """
+        )
+
+        fixed_header = disable_warnings.add_warnings_pragmas(
+            "foo.h",
+            header_before,
+            ["-Wwarning"],
+        )
+        self.assertEqual(
+            fixed_header,
+            textwrap.dedent(
+                """\
+                // Copyright bits here
+                #ifndef FOO_H_
+                #define FOO_H_
+                #pragma GCC diagnostic push
+                #pragma GCC diagnostic ignored "-Wwarning"
+
+                #ifndef BAR_H
+                #define BAR_H
+                int foo();
+                #endif  // BAR_H
+
+                #pragma GCC diagnostic pop
+                #endif  // FOO_H_
+                """
+            ),
+        )
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/libchrome_tools/files_not_built b/libchrome_tools/files_not_built
new file mode 100755
index 0000000..1a96a8d
--- /dev/null
+++ b/libchrome_tools/files_not_built
@@ -0,0 +1,16 @@
+#!/bin/bash
+# Copyright 2020 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# List cc files not in BUILD.gn, and not excluded by patterns in BUILD.IGNORE
+# This list can be run by human for sanity check that no imporant things are
+# ignored after each uprev.
+
+cd $(dirname $0)/..
+find . -name '*.cc' \
+ | sed -e 's/^\.\///g' \
+ | xargs -n 1 -P 1 bash -c \
+   'for i in $(cat BUILD.IGNORE); do grep $i <(echo $0) >/dev/null && exit; done; echo $0' \
+ | xargs -n 1 -P 1 sh -c 'grep $0 BUILD.gn >/dev/null || echo $0'
+
diff --git a/libchrome_tools/gen_perfetto_headers b/libchrome_tools/gen_perfetto_headers
new file mode 100755
index 0000000..a7eb7dd
--- /dev/null
+++ b/libchrome_tools/gen_perfetto_headers
@@ -0,0 +1,47 @@
+#!/bin/bash
+# Copyright 2023 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Generates forwarding headers for Perfetto headers included by base. In
+# Chromium, these are found under "third_party/perfetto", but on ChromeOS we
+# must use <perfetto/perfetto.h> to use the system-provided implementation.
+set -e
+
+cd $(dirname $0)/..
+includes=$(find . -name '*.cc' -or -name '*.h' \
+  | xargs sed -n 's,^#include "\(third_party/perfetto/.*\)".*,\1,p')
+
+# Other headers included by generated protozero (.pbzero.h) headers.
+protozero_includes="
+  third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h
+  third_party/perfetto/include/perfetto/protozero/field_writer.h
+  third_party/perfetto/include/perfetto/protozero/message.h
+  third_party/perfetto/include/perfetto/protozero/packed_repeated_fields.h
+  third_party/perfetto/include/perfetto/protozero/proto_decoder.h
+  third_party/perfetto/include/perfetto/protozero/proto_utils.h
+  third_party/perfetto/include/protos/perfetto/trace/track_event/debug_annotation.pbzero.h
+  third_party/perfetto/include/protos/perfetto/trace/track_event/source_location.pbzero.h
+  third_party/perfetto/include/protos/perfetto/trace/track_event/track_event.pbzero.h"
+
+rm -rf third_party/perfetto
+
+for include in $includes $protozero_includes; do
+  if [ -f "$include" ]; then continue; fi
+  echo "Creating $include"
+  guard=$(echo $include | tr a-z A-Z | tr /. _)_
+  mkdir -p $(dirname "$include")
+  cat > "$include" <<EOF
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef $guard
+#define $guard
+
+// Automatically generated by $0. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // $guard
+EOF
+done
diff --git a/libchrome_tools/include_generator.py b/libchrome_tools/include_generator.py
new file mode 100755
index 0000000..4c115de
--- /dev/null
+++ b/libchrome_tools/include_generator.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2018 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.
+
+"""Generates wrapped include files to workaround -Wunused-parameter errors.
+
+In Chrome repository, "-Wunused-parameter" is disabled, and several header
+files in Chrome repository have actually unused-parameter.
+One of the typical scenarios is; in Chrome, Observer class is often defined
+as follows:
+
+class Foo {
+ public:
+  class Observer {
+   public:
+    virtual void OnSomeEvent(EventArg arg) {}
+    virtual void OnAnotherEvent(EventArg arg) {}
+    ...
+  };
+  ...
+};
+
+Here, On...Event() methods do nothing by default, and subclasses will override
+only necessary ones.
+In this use case, argument names can also work as documentation, and overrides
+can use these good interface-defined default names as a starting point for
+their implementation.
+
+On the other hand, in Android, -Wunused-parameter is enabled by default.
+Thus, if such a project includes header files from libchrome, it could cause
+a compile error (by the warning and "-Werror").
+
+To avoid such a situation, libchrome exports include files wrapped by the
+pragmas as follows.
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+${actual_include_file_content}
+#pragma GCC diagnostic pop
+
+so, the unused-parameter warning generated by the libchrome include headers
+will be ignored.
+Note that these GCC pragmas are also supported by clang for compatibility. cf)
+https://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics-via-pragmas
+
+Usage: include_generator.py $(in) $(out)
+"""
+
+import sys
+
+
+def _generate(input_path, output_path):
+    """Generates a include file wrapped by pragmas.
+
+    Reads the file at |input_path| and output the content with wrapping by
+    #pragma to ignore unused-parameter warning into the file at |output_path|.
+    If the parent directories of |output_path| do not exist, creates them.
+
+    Args:
+        input_path: Path to the source file. Expected this is a chrome's header
+            file.
+        output_path: Path to the output file.
+    """
+    with open(input_path, 'r') as f:
+        content = f.read()
+
+    with open(output_path, 'w') as f:
+        f.writelines([
+            '// Generated by %s\n' % sys.argv[0],
+            '#pragma GCC diagnostic push\n'
+            '#pragma GCC diagnostic ignored "-Wunused-parameter"\n',
+            content,
+            '#pragma GCC diagnostic pop\n'])
+
+
+def main():
+    _generate(*sys.argv[1:])
+
+
+if __name__ == '__main__':
+    main()
diff --git a/libchrome_tools/jni_generator_helper.sh b/libchrome_tools/jni_generator_helper.sh
new file mode 100755
index 0000000..d610801
--- /dev/null
+++ b/libchrome_tools/jni_generator_helper.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 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.
+#
+# Generates jni.
+
+set -e
+
+args=()
+files=()
+
+jni_generator=''
+
+for arg in "$@"; do
+  case "${arg}" in
+    --jni_generator=*)
+      jni_generator=${arg#'--jni_generator='}
+      ;;
+    --*)
+      args=("${args[@]}" "${arg}")
+      ;;
+    *)
+      files=("${files[@]}" "${arg}")
+      ;;
+  esac
+done
+
+for file in "${files[@]}"; do
+  "${jni_generator}" "${args[@]}" --input_file="${file}"
+done
diff --git a/libchrome_tools/jni_registration_generator_helper.sh b/libchrome_tools/jni_registration_generator_helper.sh
new file mode 100755
index 0000000..a1b9e17
--- /dev/null
+++ b/libchrome_tools/jni_registration_generator_helper.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+#
+# Copyright (C) 2018 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.
+#
+# Generates jni.
+
+set -e
+
+args=()
+files=()
+
+jni_generator=''
+
+for arg in "$@"; do
+  case "${arg}" in
+    --jni_generator=*)
+      jni_generator=${arg#'--jni_generator='}
+      ;;
+    --*)
+      args=("${args[@]}" "${arg}")
+      ;;
+    *)
+      files=("${files[@]}" "${arg}")
+      ;;
+  esac
+done
+
+"${jni_generator}" --sources-files=<(printf "%q\n" "${files[@]}") "${args[@]}"
diff --git a/libchrome_tools/mojom_generate_type_mappings.py b/libchrome_tools/mojom_generate_type_mappings.py
new file mode 100755
index 0000000..ca95091
--- /dev/null
+++ b/libchrome_tools/mojom_generate_type_mappings.py
@@ -0,0 +1,108 @@
+#!/usr/bin/python
+
+# Copyright (C) 2018 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.
+
+"""Drives mojom typemapping generator.
+
+Usage:
+
+% python libchrome_tools/mojom_generate_type_mappings.py \
+      --output ${output_type_mapping_file_path} \
+      ${list of .typemap files}
+"""
+
+import argparse
+import os
+import subprocess
+import sys
+
+
+try:
+    # ../build cannot be loaded if cwd is other directories
+    # e.g. when emerge libchrome
+    sys.path.append(os.path.join(os.path.dirname(sys.argv[0]), '..'))
+    from build import gn_helpers
+except ImportError:
+    # gn_helpers is located at the same directory when building other packages
+    # in system directory.
+    import gn_helpers
+
+# script in libchrome repositority is used when emerge libchrome.
+_GENERATE_TYPE_MAPPINGS_PATH = os.path.join(
+    os.path.dirname(__file__),
+    '../mojo/public/tools/bindings/generate_type_mappings.py')
+if not os.path.isfile(_GENERATE_TYPE_MAPPINGS_PATH):
+    # use system script in the same dir when building other packages.
+    _GENERATE_TYPE_MAPPINGS_PATH = os.path.join(
+        os.path.dirname(__file__),
+        'generate_type_mappings.py')
+
+def _read_typemap_config(path):
+  """Reads .typemap file.
+
+  Args:
+    path: File path to the .typemap location.
+
+  Returns:
+    A dictionary holding values in .typemap file.
+  """
+
+  with open(path) as f:
+    # gn_helpers does not handle comment lines.
+    content = [line for line in f if not line.strip().startswith('#')]
+  return gn_helpers.FromGNArgs(''.join(content))
+
+
+def _generate_type_mappings(input_paths, output):
+  """Generates __type_mappings file from given .typemap files.
+
+  Builds a command line to run generate_type_mappings.py, and executes it.
+
+  Args:
+    input_paths: a list of file paths for .typemap files.
+    output: a path to output __type_mappings file.
+  """
+  command = [_GENERATE_TYPE_MAPPINGS_PATH, '--output', output]
+
+  # TODO(hidehiko): Add dependency handling.
+
+  for path in input_paths:
+    typemap_config = _read_typemap_config(path)
+    command.append('--start-typemap')
+    for public_header in typemap_config.get('public_headers', []):
+      command.append('public_headers=' + public_header)
+    for traits_header in typemap_config.get('traits_headers', []):
+      command.append('traits_headers=' + traits_header)
+    for type_mapping in typemap_config.get('type_mappings', []):
+      command.append('type_mappings=' + type_mapping)
+
+  subprocess.check_call(command)
+
+
+def _parse_args():
+  parser = argparse.ArgumentParser()
+  parser.add_argument('--output', help='Output file path')
+  parser.add_argument('input_paths', metavar="INPUT-PATH", nargs='+',
+                      help='Input typemap files.')
+  return parser.parse_args()
+
+
+def main():
+  args = _parse_args()
+  _generate_type_mappings(args.input_paths, args.output)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/libchrome_tools/patches/backward-compatibility-0000-add-deprecated-base-Bind-APIs.patch b/libchrome_tools/patches/backward-compatibility-0000-add-deprecated-base-Bind-APIs.patch
new file mode 100644
index 0000000..994775a
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-0000-add-deprecated-base-Bind-APIs.patch
@@ -0,0 +1,83 @@
+From fc587a45532f2c4984f3e27e30ccae7d43993a9f Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Fri, 14 Oct 2022 15:46:20 +0900
+Subject: [PATCH] backward compatibility: add deprecated base::Bind APIs
+
+Adds base::Callback, base::Bind, etc as there are still many usages in
+CrOS.
+TODO(b/272116782): remove when they are all migrated to
+Once/Repeating variants.
+
+Change-Id: I3a02c2624ed603d2afecbdd04fb589293565ab7a
+patch-name: backward-compatibility-0000-add-deprecated-base-Bind-APIs.patch
+---
+ base/callback_list.h               | 3 +++
+ base/cancelable_callback.h         | 4 ++++
+ base/functional/bind.h             | 6 ++++++
+ base/functional/callback_forward.h | 4 ++++
+ 4 files changed, 17 insertions(+)
+
+diff --git a/base/callback_list.h b/base/callback_list.h
+index bf1c0c5f97..b4e42f66b3 100644
+--- a/base/callback_list.h
++++ b/base/callback_list.h
+@@ -344,6 +344,9 @@ class RepeatingCallbackList
+ using OnceClosureList = OnceCallbackList<void()>;
+ using RepeatingClosureList = RepeatingCallbackList<void()>;
+ 
++template <typename Signature>
++using CallbackList = RepeatingCallbackList<Signature>;
++
+ }  // namespace base
+ 
+ #endif  // BASE_CALLBACK_LIST_H_
+diff --git a/base/cancelable_callback.h b/base/cancelable_callback.h
+index 73add8ffcc..09ff55bb70 100644
+--- a/base/cancelable_callback.h
++++ b/base/cancelable_callback.h
+@@ -146,6 +146,10 @@ using CancelableRepeatingCallback =
+     internal::CancelableCallbackImpl<RepeatingCallback<Signature>>;
+ using CancelableRepeatingClosure = CancelableRepeatingCallback<void()>;
+ 
++template <typename Signature>
++using CancelableCallback = CancelableRepeatingCallback<Signature>;
++using CancelableClosure = CancelableRepeatingClosure;
++
+ }  // namespace base
+ 
+ #endif  // BASE_CANCELABLE_CALLBACK_H_
+diff --git a/base/functional/bind.h b/base/functional/bind.h
+index 999c6d5d3f..d79996db5d 100644
+--- a/base/functional/bind.h
++++ b/base/functional/bind.h
+@@ -112,6 +112,12 @@ struct BindFailedCheckPreviousErrors {};
+ BindFailedCheckPreviousErrors BindOnce(...);
+ BindFailedCheckPreviousErrors BindRepeating(...);
+ 
++template <typename Functor, typename... Args>
++decltype(auto) Bind(Functor &&functor, Args &&...args) {
++  return BindRepeating(std::forward<Functor>(functor),
++                       std::forward<Args>(args)...);
++}
++
+ // Unretained(), UnsafeDangling() and UnsafeDanglingUntriaged() allow binding a
+ // non-refcounted class, and to disable refcounting on arguments that are
+ // refcounted. The main difference is whether or not the raw pointers will be
+diff --git a/base/functional/callback_forward.h b/base/functional/callback_forward.h
+index 923fbef6e3..9ed3bb6440 100644
+--- a/base/functional/callback_forward.h
++++ b/base/functional/callback_forward.h
+@@ -19,6 +19,10 @@ class RepeatingCallback;
+ using OnceClosure = OnceCallback<void()>;
+ using RepeatingClosure = RepeatingCallback<void()>;
+ 
++template <typename Signature> using Callback = RepeatingCallback<Signature>;
++
++using Closure = RepeatingClosure;
++
+ }  // namespace base
+ 
+ #endif  // BASE_FUNCTIONAL_CALLBACK_FORWARD_H_
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-0100-Allow-StringPrintf-with-non-constexpr-format-string.patch b/libchrome_tools/patches/backward-compatibility-0100-Allow-StringPrintf-with-non-constexpr-format-string.patch
new file mode 100644
index 0000000..b92b80a
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-0100-Allow-StringPrintf-with-non-constexpr-format-string.patch
@@ -0,0 +1,73 @@
+From 8358b0061d7f625bc545b651e7398280279db445 Mon Sep 17 00:00:00 2001
+From: Ren-Pei Zeng <kamesan@google.com>
+Date: Mon, 16 Sep 2024 08:47:31 +0000
+Subject: [PATCH] Allow StringPrintf with non-constexpr format string
+
+Change-Id: I26f173619e76d5398ed80ad63da94d23cbc940a5
+---
+ base/strings/stringprintf.cc | 23 +++++++++++++++++++++++
+ base/strings/stringprintf.h  | 11 ++++-------
+ 2 files changed, 27 insertions(+), 7 deletions(-)
+
+diff --git a/base/strings/stringprintf.cc b/base/strings/stringprintf.cc
+index 71d77c5952..aab459fcfb 100644
+--- a/base/strings/stringprintf.cc
++++ b/base/strings/stringprintf.cc
+@@ -14,9 +14,32 @@
+ #include "base/strings/span_printf.h"
+ #include "base/strings/string_util.h"
+ #include "build/build_config.h"
++#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
+ 
+ namespace base {
+ 
++// `ENABLE_IF_ATTR()` is part of the function signature, so at least that
++// annotation, with a matching condition to the declaration, must be present, or
++// this would be considered a distinct overload (and other components will get
++// an unresolved symbol). The message need not match; anything put there will
++// only affect calls that see this definition instead of just the declaration,
++// i.e. calls within this file (i.e. none).
++std::string StringPrintf(const char* format, ...) {
++  va_list ap;
++  va_start(ap, format);
++  absl::Cleanup end_list = [&] { va_end(ap); };
++  return StringPrintV(format, ap);
++}
++
++#if HAS_ATTRIBUTE(enable_if)
++std::string StringPrintfNonConstexpr(const char* format, ...) {
++  va_list ap;
++  va_start(ap, format);
++  absl::Cleanup end_list = [&] { va_end(ap); };
++  return StringPrintV(format, ap);
++}
++#endif
++
+ std::string StringPrintV(const char* format, va_list ap) {
+   std::string result;
+   StringAppendV(&result, format, ap);
+diff --git a/base/strings/stringprintf.h b/base/strings/stringprintf.h
+index 81a70dc1c6..828835d1ff 100644
+--- a/base/strings/stringprintf.h
++++ b/base/strings/stringprintf.h
+@@ -19,13 +19,10 @@ namespace base {
+ 
+ // Returns a C++ string given `printf()`-like input. The format string must be a
+ // compile-time constant (like with `std::format()`), or this will not compile.
+-// TODO(crbug.com/40241565): Replace calls to this with direct calls to
+-// `absl::StrFormat()` and remove.
+-template <typename... Args>
+-[[nodiscard]] std::string StringPrintf(const absl::FormatSpec<Args...>& format,
+-                                       const Args&... args) {
+-  return absl::StrFormat(format, args...);
+-}
++// TODO(crbug.com/40241565): Implement in terms of `std::format()`,
++// `absl::StrFormat()`, or similar.
++[[nodiscard]] PRINTF_FORMAT(1, 2) BASE_EXPORT std::string
++    StringPrintf(const char* format, ...);
+ 
+ // Returns a C++ string given `vprintf()`-like input.
+ [[nodiscard]] PRINTF_FORMAT(1, 0) BASE_EXPORT std::string
+-- 
+2.47.1.613.gc27f4b7a9f-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-0600-Revert-Remove-int-WriteFile.patch b/libchrome_tools/patches/backward-compatibility-0600-Revert-Remove-int-WriteFile.patch
new file mode 100644
index 0000000..d3235c8
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-0600-Revert-Remove-int-WriteFile.patch
@@ -0,0 +1,90 @@
+From 50ca35630dfd00347e82e9acc5ccaf6cdf67eb7e Mon Sep 17 00:00:00 2001
+From: Kevin Lin <kevinptt@chromium.org>
+Date: Thu, 22 Aug 2024 15:39:36 +0800
+Subject: [PATCH] Revert "Remove "int WriteFile""
+
+This reverts commit 8e52932325b70125f50dce90e96fc4282fcbbfb5.
+---
+ base/files/file_util.cc       |  9 ++++++++-
+ base/files/file_util.h        |  9 +++++++++
+ base/files/file_util_posix.cc | 16 +++++++++++-----
+ 3 files changed, 28 insertions(+), 6 deletions(-)
+
+diff --git a/base/files/file_util.cc b/base/files/file_util.cc
+index 6211201ecb..7b0347ccc8 100644
+--- a/base/files/file_util.cc
++++ b/base/files/file_util.cc
+@@ -493,8 +493,15 @@ int ReadFile(const FilePath& filename, char* data, int max_size) {
+   return checked_cast<int>(result.value());
+ }
+ 
++bool WriteFile(const FilePath& filename, span<const uint8_t> data) {
++  int size = checked_cast<int>(data.size());
++  return WriteFile(filename, reinterpret_cast<const char*>(data.data()),
++                   size) == size;
++}
++
+ bool WriteFile(const FilePath& filename, std::string_view data) {
+-  return WriteFile(filename, as_byte_span(data));
++  int size = checked_cast<int>(data.size());
++  return WriteFile(filename, data.data(), size) == size;
+ }
+ 
+ FilePath GetUniquePath(const FilePath& path) {
+diff --git a/base/files/file_util.h b/base/files/file_util.h
+index 7c12d6d239..e41d82ad4f 100644
+--- a/base/files/file_util.h
++++ b/base/files/file_util.h
+@@ -565,6 +565,15 @@ BASE_EXPORT std::optional<uint64_t> ReadFile(const FilePath& filename,
+ // TODO(crbug.com/40284755): Migrate callers to the span variant.
+ BASE_EXPORT int ReadFile(const FilePath& filename, char* data, int max_size);
+ 
++// Writes the given buffer into the file, overwriting any data that was
++// previously there.  Returns the number of bytes written, or -1 on error.
++// If file doesn't exist, it gets created with read/write permissions for all.
++// Note that the other variants of WriteFile() below may be easier to use.
++// TODO(crbug.com/40284755): Migrate callers to the span variant.
++UNSAFE_BUFFER_USAGE BASE_EXPORT int WriteFile(const FilePath& filename,
++                                              const char* data,
++                                              int size);
++
+ // Writes |data| into the file, overwriting any data that was previously there.
+ // Returns true if and only if all of |data| was written. If the file does not
+ // exist, it gets created with read/write permissions for all.
+diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
+index c371e18ae8..f2eb238979 100644
+--- a/base/files/file_util_posix.cc
++++ b/base/files/file_util_posix.cc
+@@ -1071,18 +1071,24 @@ std::optional<uint64_t> ReadFile(const FilePath& filename, span<char> buffer) {
+   return bytes_read;
+ }
+ 
+-bool WriteFile(const FilePath& filename, span<const uint8_t> data) {
++int WriteFile(const FilePath& filename, const char* data, int size) {
+   ScopedBlockingCall scoped_blocking_call(FROM_HERE, BlockingType::MAY_BLOCK);
++  if (size < 0) {
++    return -1;
++  }
+   int fd = HANDLE_EINTR(creat(filename.value().c_str(), 0666));
+   if (fd < 0) {
+-    return false;
++    return -1;
+   }
+ 
+-  bool success = WriteFileDescriptor(fd, data);
++  int bytes_written =
++      WriteFileDescriptor(fd, std::string_view(data, static_cast<size_t>(size)))
++          ? size
++          : -1;
+   if (IGNORE_EINTR(close(fd)) < 0) {
+-    return false;
++    return -1;
+   }
+-  return success;
++  return bytes_written;
+ }
+ 
+ bool WriteFileDescriptor(int fd, span<const uint8_t> data) {
+-- 
+2.47.0.338.g60cca15819-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-0800-Revert-Make-CHECK-failures-understood-as-noreturn.patch b/libchrome_tools/patches/backward-compatibility-0800-Revert-Make-CHECK-failures-understood-as-noreturn.patch
new file mode 100644
index 0000000..b6bcc0d
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-0800-Revert-Make-CHECK-failures-understood-as-noreturn.patch
@@ -0,0 +1,236 @@
+From 17e379b1d4d26cceee5c088873edcdd39f0ce71d Mon Sep 17 00:00:00 2001
+From: Cici Ruan <cuicuiruan@google.com>
+Date: Thu, 19 Dec 2024 17:02:50 -0800
+Subject: [PATCH] Revert "Make CHECK() failures understood as [[noreturn]]"
+
+This reverts commit b37a2c2574209e3e86d67ff6733ab9bb42972722.
+
+Change-Id: I68c3088d4fbfa40dbcc2d91f22ad97fd45a0c276
+---
+ base/check.cc          | 36 +++++++++++++++++++++++++++---------
+ base/check.h           | 26 ++++++++++++++++++--------
+ base/check_op.h        |  4 ++--
+ base/check_unittest.cc | 41 +++++------------------------------------
+ base/notreached.h      |  2 +-
+ 5 files changed, 53 insertions(+), 56 deletions(-)
+
+diff --git a/base/check.cc b/base/check.cc
+index 337282a375..61dc7581fe 100644
+--- a/base/check.cc
++++ b/base/check.cc
+@@ -297,6 +297,24 @@ LogMessage* CheckError::DumpWillBeCheckOp(char* log_message_str,
+   return log_message;
+ }
+ 
++CheckError CheckError::PCheck(const char* condition,
++                              const base::Location& location) {
++  SystemErrorCode err_code = logging::GetLastSystemErrorCode();
++#if BUILDFLAG(IS_WIN)
++  auto* const log_message = new Win32ErrorLogMessage(
++      location.file_name(), location.line_number(), LOGGING_FATAL, err_code);
++#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
++  auto* const log_message = new ErrnoLogMessage(
++      location.file_name(), location.line_number(), LOGGING_FATAL, err_code);
++#endif
++  log_message->stream() << "Check failed: " << condition << ". ";
++  return CheckError(log_message);
++}
++
++CheckError CheckError::PCheck(const base::Location& location) {
++  return PCheck("", location);
++}
++
+ CheckError CheckError::DPCheck(const char* condition,
+                                const base::Location& location) {
+   SystemErrorCode err_code = logging::GetLastSystemErrorCode();
+@@ -309,6 +327,15 @@ CheckError CheckError::DPCheck(const char* condition,
+   return CheckError(log_message);
+ }
+ 
++CheckError CheckError::DumpWillBeNotReachedNoreturn(
++    const base::Location& location) {
++  auto* const log_message = new NotReachedLogMessage(
++      location, GetDumpSeverity(),
++      base::NotFatalUntil::NoSpecifiedMilestoneInternal);
++  log_message->stream() << "NOTREACHED hit. ";
++  return CheckError(log_message);
++}
++
+ CheckError CheckError::NotImplemented(const char* function,
+                                       const base::Location& location) {
+   auto* const log_message = new LogMessage(
+@@ -402,15 +429,6 @@ NotReachedError NotReachedError::NotReached(base::NotFatalUntil fatal_milestone,
+   return NotReachedError(log_message);
+ }
+ 
+-NotReachedError NotReachedError::DumpWillBeNotReached(
+-    const base::Location& location) {
+-  auto* const log_message = new NotReachedLogMessage(
+-      location, GetDumpSeverity(),
+-      base::NotFatalUntil::NoSpecifiedMilestoneInternal);
+-  log_message->stream() << "NOTREACHED hit. ";
+-  return NotReachedError(log_message);
+-}
+-
+ NotReachedError::~NotReachedError() = default;
+ 
+ NotReachedNoreturnError::NotReachedNoreturnError(const base::Location& location)
+diff --git a/base/check.h b/base/check.h
+index 96f17b9847..51df4bc730 100644
+--- a/base/check.h
++++ b/base/check.h
+@@ -90,13 +90,15 @@ class BASE_EXPORT CheckError {
+   // TODO(pbos): Make all static methods that currently return some version of
+   // CheckError return LogMessage*.
+   static CheckError Check(const char* condition,
+-                          base::NotFatalUntil fatal_milestone,
++                          base::NotFatalUntil fatal_milestone =
++                          base::NotFatalUntil::NoSpecifiedMilestoneInternal,
+                           const base::Location& location =
+                               base::Location::CurrentWithoutFunctionName());
+   // Takes ownership over (free()s after using) `log_message_str`, for use with
+   // CHECK_op macros.
+   static LogMessage* CheckOp(char* log_message_str,
+-                             base::NotFatalUntil fatal_milestone,
++                             base::NotFatalUntil fatal_milestone  =
++                                 base::NotFatalUntil::NoSpecifiedMilestoneInternal,
+                              const base::Location& location =
+                                  base::Location::CurrentWithoutFunctionName());
+ 
+@@ -120,10 +122,19 @@ class BASE_EXPORT CheckError {
+       const base::Location& location =
+           base::Location::CurrentWithoutFunctionName());
+ 
++  static CheckError PCheck(
++      const char* condition,
++      const base::Location& location = base::Location::Current());
++  static CheckError PCheck(
++      const base::Location& location = base::Location::Current());
++
+   static CheckError DPCheck(const char* condition,
+                             const base::Location& location =
+                                 base::Location::CurrentWithoutFunctionName());
+ 
++  static CheckError DumpWillBeNotReachedNoreturn(
++      const base::Location& location = base::Location::Current());
++
+   static CheckError NotImplemented(
+       const char* function,
+       const base::Location& location =
+@@ -270,7 +281,7 @@ class BASE_EXPORT NotReachedNoreturnError : public CheckError {
+ #define CHECK_WILL_STREAM() true
+ 
+ #define CHECK_INTERNAL_IMPL(cond) \
+-  LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckNoreturnError::Check(#cond), cond)
++  LOGGING_CHECK_FUNCTION_IMPL(::logging::CheckError::Check(#cond), cond)
+ 
+ #endif
+ 
+@@ -280,11 +291,10 @@ class BASE_EXPORT NotReachedNoreturnError : public CheckError {
+               logging::CheckError::Check(#cond, __VA_ARGS__), cond))
+ 
+ // Strip the conditional string based on CHECK_WILL_STREAM()
+-#define PCHECK(cond)                                        \
+-  LOGGING_CHECK_FUNCTION_IMPL(                              \
+-      BASE_IF(CHECK_WILL_STREAM(),                          \
+-              ::logging::CheckNoreturnError::PCheck(#cond), \
+-              ::logging::CheckNoreturnError::PCheck()),     \
++#define PCHECK(cond)                                                     \
++  LOGGING_CHECK_FUNCTION_IMPL(                                           \
++      BASE_IF(CHECK_WILL_STREAM(), ::logging::CheckError::PCheck(#cond), \
++              ::logging::CheckError::PCheck()),                          \
+       cond)
+ 
+ #if DCHECK_IS_ON()
+diff --git a/base/check_op.h b/base/check_op.h
+index f49470aeb0..1bb33aaca8 100644
+--- a/base/check_op.h
++++ b/base/check_op.h
+@@ -192,8 +192,8 @@ BASE_EXPORT char* CreateCheckOpLogMessageString(const char* expr_str,
+ #else
+ 
+ #define CHECK_OP_INTERNAL_IMPL(name, op, val1, val2)                       \
+-  CHECK_OP_FUNCTION_IMPL(::logging::CheckNoreturnError,                    \
+-                         ::logging::CheckNoreturnError::CheckOp, name, op, \
++  CHECK_OP_FUNCTION_IMPL(::logging::CheckError,                    \
++                         ::logging::CheckError::CheckOp, name, op, \
+                          val1, val2)
+ 
+ #endif
+diff --git a/base/check_unittest.cc b/base/check_unittest.cc
+index fd5287a7b8..67de7b77ae 100644
+--- a/base/check_unittest.cc
++++ b/base/check_unittest.cc
+@@ -547,51 +547,20 @@ TEST(CheckDeathTest, OstreamVsToString) {
+                CHECK_EQ(g, h));
+ }
+ 
+-TEST(CheckDeathTest, NotReached) {
+-  // Expect to be CHECK fatal but with a different error message.
+-  EXPECT_CHECK("NOTREACHED hit. foo", NOTREACHED() << "foo");
+-}
+-
+-// These non-void functions are here to make sure that CHECK failures and
+-// NOTREACHED() are properly annotated as [[noreturn]] by not requiring a return
+-// statement.
++// This non-void function is here to make sure that NOTREACHED() is properly
++// annotated as [[noreturn]] and does not require a return statement.
+ int NotReachedInFunction() {
+   NOTREACHED();
+   // No return statement here.
+ }
+ 
+-int CheckFailureInFunction() {
+-  constexpr int kFalse = false;
+-  CHECK(kFalse);
+-
+-  // No return statement here.
+-}
+-
+-int PCheckFailureInFunction() {
+-  constexpr int kFalse = false;
+-  PCHECK(kFalse);
+-
+-  // No return statement here.
+-}
+-
+-TEST(CheckDeathTest, CheckFailuresAreNoreturn) {
++TEST(CheckDeathTest, NotReached) {
++  // Expect to be CHECK fatal but with a different error message.
++  EXPECT_CHECK("NOTREACHED hit. foo", NOTREACHED() << "foo");
+   // This call can't use EXPECT_CHECK as the NOTREACHED happens on a different
+   // line.
+   EXPECT_DEATH_IF_SUPPORTED(NotReachedInFunction(),
+                             CHECK_WILL_STREAM() ? "NOTREACHED hit. " : "");
+-
+-  // This call can't use EXPECT_CHECK as the CHECK failure happens on a
+-  // different line.
+-  EXPECT_DEATH_IF_SUPPORTED(CheckFailureInFunction(),
+-                            CHECK_WILL_STREAM() ? "Check failed: " : "");
+-
+-  // This call can't use EXPECT_CHECK as the PCHECK failure happens on a
+-  // different line.
+-  EXPECT_DEATH_IF_SUPPORTED(PCheckFailureInFunction(),
+-                            CHECK_WILL_STREAM() ? "Check failed: " : "");
+-
+-  // TODO(crbug.com/40122554): Make sure CHECK_LT(1, 1) is [[noreturn]]. That
+-  // doesn't work in the current developer build.
+ }
+ 
+ TEST(CheckDeathTest, DumpWillBeCheck) {
+diff --git a/base/notreached.h b/base/notreached.h
+index d8f5b9d211..1fef9ab3d7 100644
+--- a/base/notreached.h
++++ b/base/notreached.h
+@@ -43,7 +43,7 @@ namespace logging {
+ // non-fatally dump in official builds if ever hit. See DUMP_WILL_BE_CHECK for
+ // suggested usage.
+ #define DUMP_WILL_BE_NOTREACHED() \
+-  ::logging::NotReachedError::DumpWillBeNotReached()
++  ::logging::CheckError::DumpWillBeNotReachedNoreturn()
+ 
+ }  // namespace logging
+ 
+-- 
+2.49.0.395.g12beb8f557-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-0900-Revert-Remove-NOTREACHED_IN_MIGRATION.patch b/libchrome_tools/patches/backward-compatibility-0900-Revert-Remove-NOTREACHED_IN_MIGRATION.patch
new file mode 100644
index 0000000..27a6eee
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-0900-Revert-Remove-NOTREACHED_IN_MIGRATION.patch
@@ -0,0 +1,87 @@
+From 11901a97f7d1a14ce4f39a65a723661ed6f9cd2c Mon Sep 17 00:00:00 2001
+From: Cici Ruan <cuicuiruan@google.com>
+Date: Thu, 19 Dec 2024 17:22:36 -0800
+Subject: [PATCH] Revert "Remove NOTREACHED_IN_MIGRATION()"
+
+This reverts commit 5e342fc336640bad90e2cecb96415e37bd720e97.
+
+Change-Id: I40d6386d02e106049d1afc0288b742e3951a264b
+---
+ base/check.cc     |  7 +++++++
+ base/check.h      | 14 ++++++++------
+ base/notreached.h | 14 ++++++++++++++
+ 3 files changed, 29 insertions(+), 6 deletions(-)
+
+diff --git a/base/check.cc b/base/check.cc
+index 87fcaf4132..04440b3ce9 100644
+--- a/base/check.cc
++++ b/base/check.cc
+@@ -425,6 +425,13 @@ NotReachedError NotReachedError::NotReached(base::NotFatalUntil fatal_milestone,
+   return NotReachedError(log_message);
+ }
+ 
++void NotReachedError::TriggerNotReached() {
++  // This triggers a NOTREACHED_IN_MIGRATION() error as the returned
++  // NotReachedError goes out of scope.
++  NotReached()
++      << "NOTREACHED log messages are omitted in official builds. Sorry!";
++}
++
+ NotReachedError::~NotReachedError() = default;
+ 
+ NotReachedNoreturnError::NotReachedNoreturnError(const base::Location& location)
+diff --git a/base/check.h b/base/check.h
+index 231b42bb6b..729caa0466 100644
+--- a/base/check.h
++++ b/base/check.h
+@@ -189,14 +189,16 @@ class BASE_EXPORT CheckNoreturnError : public CheckError {
+ class BASE_EXPORT NotReachedError : public CheckError {
+  public:
+   static NotReachedError NotReached(
+-      base::NotFatalUntil fatal_milestone,
+-      const base::Location& location =
+-          base::Location::CurrentWithoutFunctionName());
++      base::NotFatalUntil fatal_milestone =
++          base::NotFatalUntil::NoSpecifiedMilestoneInternal,
++      const base::Location& location = base::Location::Current());
+ 
+-  static NotReachedError DumpWillBeNotReached(
+-      const base::Location& location =
+-          base::Location::CurrentWithoutFunctionName());
++  // Used to trigger a NOTREACHED_IN_MIGRATION() without providing file or line
++  // while also discarding log-stream arguments. See base/notreached.h.
++  NOMERGE NOINLINE NOT_TAIL_CALLED static void TriggerNotReached();
+ 
++  // TODO(crbug.com/40580068): Mark [[noreturn]] once this is CHECK-fatal on all
++  // builds.
+   NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedError();
+ 
+  private:
+diff --git a/base/notreached.h b/base/notreached.h
+index 1fef9ab3d7..e4c8a34c45 100644
+--- a/base/notreached.h
++++ b/base/notreached.h
+@@ -16,6 +16,20 @@
+ 
+ namespace logging {
+ 
++// Migration in progress: For new code use NOTREACHED() or
++// NOTREACHED(base::NotFatalUntil::M*). NOTREACHED_IN_MIGRATION() is equally
++// fatal to NOTREACHED() without parameters but not annotated as [[noreturn]].
++#if CHECK_WILL_STREAM()
++#define NOTREACHED_IN_MIGRATION() \
++  LOGGING_CHECK_FUNCTION_IMPL(::logging::NotReachedError::NotReached(), false)
++#else
++#define NOTREACHED_IN_MIGRATION()                          \
++  (true) ? ::logging::NotReachedError::TriggerNotReached() \
++         : EAT_CHECK_STREAM_PARAMS()
++#endif
++
++// Migration in progress: Use NOTREACHED() directly without parameters instead.
++// TODO(crbug.com/40580068): Merge this with NOTREACHED().
+ #if CHECK_WILL_STREAM()
+ #define NOTREACHED_INTERNAL_IMPL() ::logging::NotReachedNoreturnError()
+ #else
+-- 
+2.47.1.613.gc27f4b7a9f-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-1000-Revert-Remove-make_span.patch b/libchrome_tools/patches/backward-compatibility-1000-Revert-Remove-make_span.patch
new file mode 100644
index 0000000..e052070
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-1000-Revert-Remove-make_span.patch
@@ -0,0 +1,52 @@
+From 4ab243887f96782b28a78208b33ec22c5cb35cf4 Mon Sep 17 00:00:00 2001
+From: Cici Ruan <cuicuiruan@google.com>
+Date: Thu, 19 Dec 2024 15:11:55 -0800
+Subject: [PATCH] Revert "Remove make_span."
+
+This reverts commit 2146e0b7c539469002f22820ff0f519d92f2b684.
+
+Change-Id: I33b09de8bdf1152cb0e2c3d5481a4bc35ed94aa8
+---
+ base/containers/span.h | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/base/containers/span.h b/base/containers/span.h
+index d2fdc81dd3..7132251854 100644
+--- a/base/containers/span.h
++++ b/base/containers/span.h
+@@ -1719,6 +1719,32 @@ constexpr auto as_writable_byte_span(
+   return as_writable_bytes(allow_nonunique_obj, span<ElementType, Extent>(arr));
+ }
+ 
++// Type-deducing helper to construct a span.
++// Deprecated: Use CTAD (i.e. use `span()` directly without template arguments).
++// TODO(crbug.com/341907909): Remove.
++template <int&... ExplicitArgumentBarrier, typename It, typename EndOrSize>
++  requires(std::contiguous_iterator<It>)
++// SAFETY: `it` must point to the first of a (possibly-empty) series of
++// contiguous valid elements. If `end_or_size` is a size, the series must
++// contain at least that many valid elements; if it is an iterator or sentinel,
++// it must refer to the same allocation, and all elements in the range [it,
++// end_or_size) must be valid. Otherwise, the span will allow access to invalid
++// elements, resulting in UB.
++UNSAFE_BUFFER_USAGE constexpr auto make_span(It it, EndOrSize end_or_size) {
++  return UNSAFE_BUFFERS(span(it, end_or_size));
++}
++template <int&... ExplicitArgumentBarrier, typename R>
++  requires(internal::SpanConstructibleFrom<R &&>)
++constexpr auto make_span(R&& r LIFETIME_BOUND) {
++  return span(std::forward<R>(r));
++}
++template <int&... ExplicitArgumentBarrier, typename R>
++  requires(internal::SpanConstructibleFrom<R &&> &&
++           std::ranges::borrowed_range<R>)
++constexpr auto make_span(R&& r) {
++  return span(std::forward<R>(r));
++}
++
+ }  // namespace base
+ 
+ #endif  // BASE_CONTAINERS_SPAN_H_
+-- 
+2.47.1.613.gc27f4b7a9f-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-1100-Revert-base-Convert-parts-of-base-to-std-atomic-from.patch b/libchrome_tools/patches/backward-compatibility-1100-Revert-base-Convert-parts-of-base-to-std-atomic-from.patch
new file mode 100644
index 0000000..394bad4
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-1100-Revert-base-Convert-parts-of-base-to-std-atomic-from.patch
@@ -0,0 +1,135 @@
+From 943f821220d48888e653c064a181ea021bc621e6 Mon Sep 17 00:00:00 2001
+From: Cici Ruan <cuicuiruan@google.com>
+Date: Tue, 17 Dec 2024 00:03:28 -0800
+Subject: [PATCH] Revert "[base] Convert parts of base to std::atomic from
+ atomicops"
+
+This reverts commit da933f570719e7aac8a1c2240154f6ffac6a119b.
+
+Change-Id: Id0b5599e76f7d198aa313df5e16fe4b2fc2906b8
+---
+ base/threading/thread_collision_warner.cc | 50 ++++++++++++++---------
+ base/threading/thread_collision_warner.h  |  9 ++--
+ 2 files changed, 33 insertions(+), 26 deletions(-)
+
+diff --git a/base/threading/thread_collision_warner.cc b/base/threading/thread_collision_warner.cc
+index c99661e2b9..ee055c01e7 100644
+--- a/base/threading/thread_collision_warner.cc
++++ b/base/threading/thread_collision_warner.cc
+@@ -4,7 +4,6 @@
+ 
+ #include "base/threading/thread_collision_warner.h"
+ 
+-#include <atomic>
+ #include <ostream>
+ 
+ #include "base/notreached.h"
+@@ -16,40 +15,51 @@ void DCheckAsserter::warn() {
+   NOTREACHED() << "Thread Collision";
+ }
+ 
++static subtle::Atomic32 CurrentThread() {
++  const PlatformThreadId current_thread_id = PlatformThread::CurrentId();
++  // We need to get the thread id into an atomic data type. This might be a
++  // truncating conversion, but any loss-of-information just increases the
++  // chance of a fault negative, not a false positive.
++  const subtle::Atomic32 atomic_thread_id =
++      static_cast<subtle::Atomic32>(current_thread_id);
++
++  return atomic_thread_id;
++}
++
+ void ThreadCollisionWarner::EnterSelf() {
+-  // If the active thread is kInvalidThreadId then I'll write the current thread
+-  // ID if two or more threads arrive here only one will succeed to write on
+-  // valid_thread_id_ the current thread ID.
+-  PlatformThreadId current_thread_id = PlatformThread::CurrentId();
+-  PlatformThreadId expected = kInvalidThreadId;
+-
+-  bool ok = valid_thread_id_.compare_exchange_strong(
+-      expected, current_thread_id, std::memory_order_relaxed,
+-      std::memory_order_relaxed);
+-  if (!ok && expected != current_thread_id) {
++  // If the active thread is 0 then I'll write the current thread ID
++  // if two or more threads arrive here only one will succeed to
++  // write on valid_thread_id_ the current thread ID.
++  subtle::Atomic32 current_thread_id = CurrentThread();
++
++  int previous_value = subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
++                                                        0,
++                                                        current_thread_id);
++  if (previous_value != 0 && previous_value != current_thread_id) {
+     // gotcha! a thread is trying to use the same class and that is
+     // not current thread.
+     asserter_->warn();
+   }
+-  counter_.fetch_add(1, std::memory_order_relaxed);
++
++  subtle::NoBarrier_AtomicIncrement(&counter_, 1);
+ }
+ 
+ void ThreadCollisionWarner::Enter() {
+-  PlatformThreadId current_thread_id = PlatformThread::CurrentId();
+-  PlatformThreadId expected = kInvalidThreadId;
++  subtle::Atomic32 current_thread_id = CurrentThread();
+ 
+-  if (!valid_thread_id_.compare_exchange_strong(expected, current_thread_id,
+-                                                std::memory_order_relaxed,
+-                                                std::memory_order_relaxed)) {
++  if (subtle::NoBarrier_CompareAndSwap(&valid_thread_id_,
++                                       0,
++                                       current_thread_id) != 0) {
+     // gotcha! another thread is trying to use the same class.
+     asserter_->warn();
+   }
+-  counter_.fetch_add(1, std::memory_order_relaxed);
++
++  subtle::NoBarrier_AtomicIncrement(&counter_, 1);
+ }
+ 
+ void ThreadCollisionWarner::Leave() {
+-  if (counter_.fetch_sub(1, std::memory_order_relaxed) == 1) {
+-    valid_thread_id_.store(kInvalidThreadId, std::memory_order_relaxed);
++  if (subtle::Barrier_AtomicIncrement(&counter_, -1) == 0) {
++    subtle::NoBarrier_Store(&valid_thread_id_, 0);
+   }
+ }
+ 
+diff --git a/base/threading/thread_collision_warner.h b/base/threading/thread_collision_warner.h
+index b6795c5589..41d99b89ff 100644
+--- a/base/threading/thread_collision_warner.h
++++ b/base/threading/thread_collision_warner.h
+@@ -5,14 +5,12 @@
+ #ifndef BASE_THREADING_THREAD_COLLISION_WARNER_H_
+ #define BASE_THREADING_THREAD_COLLISION_WARNER_H_
+ 
+-#include <atomic>
+-
++#include "base/atomicops.h"
+ #include "base/base_export.h"
+ #include "base/compiler_specific.h"
+ #include "base/dcheck_is_on.h"
+ #include "base/macros/uniquify.h"
+ #include "base/memory/raw_ptr.h"
+-#include "base/threading/platform_thread.h"
+ 
+ // A helper class alongside macros to be used to verify assumptions about thread
+ // safety of a class.
+@@ -233,12 +231,11 @@ class BASE_EXPORT ThreadCollisionWarner {
+ 
+   // This stores the thread id that is inside the critical section, if the
+   // value is 0 then no thread is inside.
+-  std::atomic<PlatformThreadId> valid_thread_id_;
+-  static_assert(std::atomic<PlatformThreadId>::is_always_lock_free, "");
++  volatile subtle::Atomic32 valid_thread_id_;
+ 
+   // Counter to trace how many time a critical section was "pinned"
+   // (when allowed) in order to unpin it when counter_ reaches 0.
+-  std::atomic<uint32_t> counter_;
++  volatile subtle::Atomic32 counter_;
+ 
+   // Here only for class unit tests purpose, during the test I need to not
+   // DCHECK but notify the collision with something else.
+-- 
+2.47.1.613.gc27f4b7a9f-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-1200-Revert-Make-byte-spans-check-for-unique-obj-representations.patch b/libchrome_tools/patches/backward-compatibility-1200-Revert-Make-byte-spans-check-for-unique-obj-representations.patch
new file mode 100644
index 0000000..f751501
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-1200-Revert-Make-byte-spans-check-for-unique-obj-representations.patch
@@ -0,0 +1,37 @@
+From 9930b6f3d41532872c17e4f5a04c5bb706486ab5 Mon Sep 17 00:00:00 2001
+From: Cici Ruan <cuicuiruan@google.com>
+Date: Wed, 18 Dec 2024 19:20:59 -0800
+Subject: [PATCH] Revert partial changes in span.h
+
+This CL reverts partial change in 1cad1f595be5c681571b407e05a28673f4760b46.
+
+Change-Id: I8a71dc51ea9af60f82b36459e21d4b967d8fadae
+---
+ base/containers/span.h | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/base/containers/span.h b/base/containers/span.h
+index d2fdc81dd3..df23862bf6 100644
+--- a/base/containers/span.h
++++ b/base/containers/span.h
+@@ -1391,7 +1391,6 @@ span(R&&) -> span<std::remove_reference_t<std::ranges::range_reference_t<R>>,
+ 
+ // [span.objectrep]: Views of object representation
+ template <typename ElementType, size_t Extent, typename InternalPtrType>
+-  requires(internal::CanSafelyConvertToByteSpan<ElementType>)
+ constexpr auto as_bytes(span<ElementType, Extent, InternalPtrType> s) {
+   return internal::as_byte_span<const uint8_t>(s);
+ }
+@@ -1432,8 +1431,7 @@ constexpr auto as_chars(allow_nonunique_obj_t,
+   return internal::as_byte_span<const char>(s);
+ }
+ template <typename ElementType, size_t Extent, typename InternalPtrType>
+-  requires(internal::CanSafelyConvertToByteSpan<ElementType> &&
+-           !std::is_const_v<ElementType>)
++  requires(!std::is_const_v<ElementType>)
+ constexpr auto as_writable_chars(span<ElementType, Extent, InternalPtrType> s) {
+   return internal::as_byte_span<char>(s);
+ }
+-- 
+2.47.1.613.gc27f4b7a9f-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-1600-Revert-mac-Use-pthread_threadid-for-ThreadId.patch b/libchrome_tools/patches/backward-compatibility-1600-Revert-mac-Use-pthread_threadid-for-ThreadId.patch
new file mode 100644
index 0000000..50387fc
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-1600-Revert-mac-Use-pthread_threadid-for-ThreadId.patch
@@ -0,0 +1,206 @@
+From 1b480bd2a198186f87db5aab010b49fc344abbd4 Mon Sep 17 00:00:00 2001
+From: Georg Neis <neis@chromium.org>
+Date: Fri, 14 Feb 2025 05:15:15 +0000
+Subject: [PATCH 1/2] Revert "[mac] Use pthread_threadid for ThreadId"
+
+This reverts commit 45a077c10ce0c6e9106c897cb7a036a16ebd5561.
+---
+ .../sampling_profiler_thread_token.cc         |  2 +-
+ .../profiler/sampling_profiler_thread_token.h |  6 +++---
+ base/threading/hang_watcher.cc                | 19 +++++++++++++++----
+ base/threading/hang_watcher.h                 | 11 ++++++++++-
+ base/threading/hang_watcher_unittest.cc       | 11 ++++++++++-
+ base/threading/platform_thread.h              |  5 ++++-
+ base/threading/platform_thread_posix.cc       |  4 +---
+ 7 files changed, 44 insertions(+), 14 deletions(-)
+
+diff --git a/base/profiler/sampling_profiler_thread_token.cc b/base/profiler/sampling_profiler_thread_token.cc
+index afb39f0bdd..5ef3ec4a57 100644
+--- a/base/profiler/sampling_profiler_thread_token.cc
++++ b/base/profiler/sampling_profiler_thread_token.cc
+@@ -16,7 +16,7 @@ namespace base {
+ 
+ SamplingProfilerThreadToken GetSamplingProfilerCurrentThreadToken() {
+   PlatformThreadId id = PlatformThread::CurrentId();
+-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_APPLE)
++#if BUILDFLAG(IS_ANDROID)
+   return {id, pthread_self()};
+ #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+   std::optional<uintptr_t> maybe_stack_base =
+diff --git a/base/profiler/sampling_profiler_thread_token.h b/base/profiler/sampling_profiler_thread_token.h
+index 29b5145d12..c2e9ef1b5d 100644
+--- a/base/profiler/sampling_profiler_thread_token.h
++++ b/base/profiler/sampling_profiler_thread_token.h
+@@ -11,7 +11,7 @@
+ #include "base/threading/platform_thread.h"
+ #include "build/build_config.h"
+ 
+-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_APPLE)
++#if BUILDFLAG(IS_ANDROID)
+ #include <pthread.h>
+ #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+ #include <stdint.h>
+@@ -21,11 +21,11 @@ namespace base {
+ 
+ // SamplingProfilerThreadToken represents the thread identifier(s) required by
+ // sampling profiler to operate on a thread. PlatformThreadId is needed for all
+-// platforms, while Android and Mac also require a pthread_t to pass to pthread
++// platforms, while Android also requires a pthread_t to pass to pthread
+ // functions used to obtain the stack base address.
+ struct SamplingProfilerThreadToken {
+   PlatformThreadId id;
+-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_APPLE)
++#if BUILDFLAG(IS_ANDROID)
+   pthread_t pthread_id;
+ #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+   // Due to the sandbox, we can only retrieve the stack base address for the
+diff --git a/base/threading/hang_watcher.cc b/base/threading/hang_watcher.cc
+index b5fe642c24..11fec1abbd 100644
+--- a/base/threading/hang_watcher.cc
++++ b/base/threading/hang_watcher.cc
+@@ -814,8 +814,8 @@ void HangWatcher::WatchStateSnapShot::Init(
+       // the next capture then they'll already be marked and will be included
+       // in the capture at that time.
+       if (thread_marked && all_threads_marked) {
+-        hung_watch_state_copies_.push_back(
+-            WatchStateCopy{deadline, watch_state.get()->GetThreadID()});
++        hung_watch_state_copies_.push_back(WatchStateCopy{
++            deadline, watch_state.get()->GetSystemWideThreadID()});
+       } else {
+         all_threads_marked = false;
+       }
+@@ -884,8 +884,7 @@ std::string HangWatcher::WatchStateSnapShot::PrepareHungThreadListCrashKey()
+ 
+   // Add as many thread ids to the crash key as possible.
+   for (const WatchStateCopy& copy : hung_watch_state_copies_) {
+-    std::string fragment =
+-        base::NumberToString(copy.thread_id.raw()) + kSeparator;
++    std::string fragment = base::NumberToString(copy.thread_id) + kSeparator;
+     if (list_of_hung_thread_ids.size() + fragment.size() <
+         static_cast<std::size_t>(debug::CrashKeySize::Size256)) {
+       list_of_hung_thread_ids += fragment;
+@@ -1224,6 +1223,9 @@ uint64_t HangWatchDeadline::SwitchBitsForTesting() {
+ 
+ HangWatchState::HangWatchState(HangWatcher::ThreadType thread_type)
+     : resetter_(&hang_watch_state, this, nullptr), thread_type_(thread_type) {
++#if BUILDFLAG(IS_MAC)
++  pthread_threadid_np(pthread_self(), &system_wide_thread_id_);
++#endif
+   thread_id_ = PlatformThread::CurrentId();
+ }
+ 
+@@ -1327,6 +1329,15 @@ PlatformThreadId HangWatchState::GetThreadID() const {
+   return thread_id_;
+ }
+ 
++uint64_t HangWatchState::GetSystemWideThreadID() const {
++#if BUILDFLAG(IS_MAC)
++  return system_wide_thread_id_;
++#else
++  CHECK_NE(thread_id_, kInvalidThreadId);
++  return static_cast<uint64_t>(thread_id_);
++#endif
++}
++
+ }  // namespace internal
+ 
+ }  // namespace base
+diff --git a/base/threading/hang_watcher.h b/base/threading/hang_watcher.h
+index 1e653a12ad..3ee0fc89ec 100644
+--- a/base/threading/hang_watcher.h
++++ b/base/threading/hang_watcher.h
+@@ -290,7 +290,7 @@ class BASE_EXPORT HangWatcher : public DelegateSimpleThread::Delegate {
+    public:
+     struct WatchStateCopy {
+       base::TimeTicks deadline;
+-      base::PlatformThreadId thread_id;
++      uint64_t thread_id;
+     };
+ 
+     WatchStateSnapShot();
+@@ -634,6 +634,7 @@ class BASE_EXPORT HangWatchState {
+ #endif
+ 
+   PlatformThreadId GetThreadID() const;
++  uint64_t GetSystemWideThreadID() const;
+ 
+   // Retrieve the current hang watch deadline directly. For testing only.
+   HangWatchDeadline* GetHangWatchDeadlineForTesting();
+@@ -665,6 +666,14 @@ class BASE_EXPORT HangWatchState {
+   // only.
+   PlatformThreadId thread_id_ = kInvalidThreadId;
+ 
++#if BUILDFLAG(IS_MAC)
++  // TODO(crbug.com/40187449): Remove this once macOS uses system-wide ids.
++  // On macOS the thread ids used by CrashPad are not the same as the ones
++  // provided by PlatformThread. Make sure to use the same for correct
++  // attribution.
++  uint64_t system_wide_thread_id_;
++#endif
++
+   // Number of active HangWatchScopeEnables on this thread.
+   int nesting_level_ = 0;
+ 
+diff --git a/base/threading/hang_watcher_unittest.cc b/base/threading/hang_watcher_unittest.cc
+index e8835011f8..bfbc9770d4 100644
+--- a/base/threading/hang_watcher_unittest.cc
++++ b/base/threading/hang_watcher_unittest.cc
+@@ -726,7 +726,16 @@ TEST_F(HangWatcherSnapshotTest, NonActionableReport) {
+   }
+ }
+ 
+-TEST_F(HangWatcherSnapshotTest, HungThreadIDs) {
++// TODO(crbug.com/40187449): On MAC, the base::PlatformThread::CurrentId(...)
++// should return the system wide IDs. The HungThreadIDs test fails because the
++// reported process ids do not match.
++#if BUILDFLAG(IS_MAC)
++#define MAYBE_HungThreadIDs DISABLED_HungThreadIDs
++#else
++#define MAYBE_HungThreadIDs HungThreadIDs
++#endif
++
++TEST_F(HangWatcherSnapshotTest, MAYBE_HungThreadIDs) {
+   // During hang capture the list of hung threads should be populated.
+   hang_watcher_.SetOnHangClosureForTesting(base::BindLambdaForTesting([this] {
+     EXPECT_EQ(hang_watcher_.GrabWatchStateSnapshotForTesting()
+diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h
+index dca4fc5b7b..06a667f3da 100644
+--- a/base/threading/platform_thread.h
++++ b/base/threading/platform_thread.h
+@@ -29,6 +29,8 @@
+ #include "base/win/windows_types.h"
+ #elif BUILDFLAG(IS_FUCHSIA)
+ #include <zircon/types.h>
++#elif BUILDFLAG(IS_APPLE)
++#include <mach/mach_types.h>
+ #elif BUILDFLAG(IS_POSIX)
+ #include <pthread.h>
+ #include <unistd.h>
+@@ -54,7 +56,8 @@ class BASE_EXPORT PlatformThreadId {
+ #elif BUILDFLAG(IS_FUCHSIA)
+   using UnderlyingType = zx_koid_t;
+ #elif BUILDFLAG(IS_APPLE)
+-  using UnderlyingType = uint64_t;
++  // TODO(crbug.com/40187449): Use uint64_t ids from pthread_threadid_np.
++  using UnderlyingType = mach_port_t;
+ #elif BUILDFLAG(IS_POSIX)
+   using UnderlyingType = pid_t;
+ #endif
+diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc
+index c9344ccad1..f5ea6363d0 100644
+--- a/base/threading/platform_thread_posix.cc
++++ b/base/threading/platform_thread_posix.cc
+@@ -218,9 +218,7 @@ PlatformThreadId PlatformThreadBase::CurrentId() {
+   // Pthreads doesn't have the concept of a thread ID, so we have to reach down
+   // into the kernel.
+ #if BUILDFLAG(IS_APPLE)
+-  uint64_t tid;
+-  CHECK_EQ(pthread_threadid_np(nullptr, &tid), 0);
+-  return PlatformThreadId(tid);
++  return PlatformThreadId(pthread_mach_thread_np(pthread_self()));
+ #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+   // Workaround false-positive MSAN use-of-uninitialized-value on
+   // thread_local storage for loaded libraries:
+-- 
+2.48.1.601.g30ceb7b040-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-1610-Revert-base-Use-wrapper-type-for-PlatformThreadId.patch b/libchrome_tools/patches/backward-compatibility-1610-Revert-base-Use-wrapper-type-for-PlatformThreadId.patch
new file mode 100644
index 0000000..5b007de
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-1610-Revert-base-Use-wrapper-type-for-PlatformThreadId.patch
@@ -0,0 +1,906 @@
+From 7f825f226910b0d1d8690e487fa3c6774972c91b Mon Sep 17 00:00:00 2001
+From: Jae Hoon Kim <kimjae@chromium.org>
+Date: Mon, 24 Mar 2025 22:55:51 -0700
+Subject: [PATCH] Revert "[base] Use wrapper type for PlatformThreadId"
+ (refreshed)
+
+This reverts commit 3498f5440cb6504429ff48613c04650537188f58.
+
+Change-Id: I4e24f0c7f19a48617cd72556b67912a2f352d702
+patch-name: backward-compatibility-1610-Revert-base-Use-wrapper-type-for-PlatformThreadId.patch
+---
+ base/android/early_trace_event_binding.cc     | 16 ++--
+ base/debug/stack_trace.cc                     |  5 +-
+ base/message_loop/message_pump_glib.cc        |  2 +-
+ base/process/internal_linux.h                 |  5 +-
+ base/process/process_unittest.cc              |  2 +-
+ base/process/set_process_title.cc             |  3 +-
+ base/profiler/stack_base_address_posix.cc     |  2 +-
+ .../stack_base_address_posix_unittest.cc      |  4 +-
+ .../stack_sampling_profiler_test_util.h       |  2 +-
+ .../thread_delegate_posix_unittest.cc         |  4 +-
+ .../sampling_heap_profiler.cc                 |  2 +-
+ .../sequence_manager/thread_controller.cc     |  2 +-
+ base/test/launcher/test_launcher_tracer.cc    | 14 +--
+ base/test/launcher/test_results_tracker.cc    | 16 +---
+ .../launcher/test_results_tracker_unittest.cc |  2 +-
+ base/threading/hang_watcher.cc                |  2 +-
+ base/threading/hang_watcher.h                 |  2 +-
+ base/threading/hang_watcher_unittest.cc       |  2 +-
+ base/threading/platform_thread.cc             |  5 -
+ base/threading/platform_thread.h              | 94 +++----------------
+ base/threading/platform_thread_android.cc     |  6 +-
+ base/threading/platform_thread_cros.cc        | 22 ++---
+ base/threading/platform_thread_linux.cc       | 12 +--
+ base/threading/platform_thread_posix.cc       | 20 ++--
+ base/threading/platform_thread_unittest.cc    |  2 +-
+ base/threading/thread_collision_warner.h      |  2 +-
+ base/trace_event/trace_event_impl.cc          | 23 +----
+ base/trace_event/trace_event_impl.h           |  2 +-
+ base/trace_event/trace_log.cc                 | 15 ++-
+ base/tracing/perfetto_platform.cc             |  3 +-
+ 30 files changed, 85 insertions(+), 208 deletions(-)
+
+diff --git a/base/android/early_trace_event_binding.cc b/base/android/early_trace_event_binding.cc
+index 66fce41a80..47673de66c 100644
+--- a/base/android/early_trace_event_binding.cc
++++ b/base/android/early_trace_event_binding.cc
+@@ -28,8 +28,8 @@ static void JNI_EarlyTraceEvent_RecordEarlyBeginEvent(JNIEnv* env,
+       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(internal::kJavaTraceCategory);
+   trace_event_internal::AddTraceEventWithThreadIdAndTimestamps(
+       TRACE_EVENT_PHASE_BEGIN, category_group_enabled, name.c_str(),
+-      /*scope=*/nullptr, trace_event_internal::kNoId,
+-      PlatformThreadId(thread_id), TimeTicks::FromJavaNanoTime(time_ns),
++      /*scope=*/nullptr, trace_event_internal::kNoId, thread_id,
++      TimeTicks::FromJavaNanoTime(time_ns),
+       ThreadTicks() + Milliseconds(thread_time_ms),
+       TRACE_EVENT_FLAG_JAVA_STRING_LITERALS | TRACE_EVENT_FLAG_COPY);
+ #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
+@@ -45,8 +45,8 @@ static void JNI_EarlyTraceEvent_RecordEarlyEndEvent(JNIEnv* env,
+       TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(internal::kJavaTraceCategory);
+   trace_event_internal::AddTraceEventWithThreadIdAndTimestamps(
+       TRACE_EVENT_PHASE_END, category_group_enabled, name.c_str(),
+-      /*scope=*/nullptr, trace_event_internal::kNoId,
+-      PlatformThreadId(thread_id), TimeTicks::FromJavaNanoTime(time_ns),
++      /*scope=*/nullptr, trace_event_internal::kNoId, thread_id,
++      TimeTicks::FromJavaNanoTime(time_ns),
+       ThreadTicks() + Milliseconds(thread_time_ms),
+       TRACE_EVENT_FLAG_JAVA_STRING_LITERALS | TRACE_EVENT_FLAG_COPY);
+ #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
+@@ -64,8 +64,8 @@ static void JNI_EarlyTraceEvent_RecordEarlyToplevelBeginEvent(
+           internal::kToplevelTraceCategory);
+   trace_event_internal::AddTraceEventWithThreadIdAndTimestamps(
+       TRACE_EVENT_PHASE_BEGIN, category_group_enabled, name.c_str(),
+-      /*scope=*/nullptr, trace_event_internal::kNoId,
+-      PlatformThreadId(thread_id), TimeTicks::FromJavaNanoTime(time_ns),
++      /*scope=*/nullptr, trace_event_internal::kNoId, thread_id,
++      TimeTicks::FromJavaNanoTime(time_ns),
+       ThreadTicks() + Milliseconds(thread_time_ms),
+       TRACE_EVENT_FLAG_JAVA_STRING_LITERALS | TRACE_EVENT_FLAG_COPY);
+ #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
+@@ -83,8 +83,8 @@ static void JNI_EarlyTraceEvent_RecordEarlyToplevelEndEvent(
+           internal::kToplevelTraceCategory);
+   trace_event_internal::AddTraceEventWithThreadIdAndTimestamps(
+       TRACE_EVENT_PHASE_END, category_group_enabled, name.c_str(),
+-      /*scope=*/nullptr, trace_event_internal::kNoId,
+-      PlatformThreadId(thread_id), TimeTicks::FromJavaNanoTime(time_ns),
++      /*scope=*/nullptr, trace_event_internal::kNoId, thread_id,
++      TimeTicks::FromJavaNanoTime(time_ns),
+       ThreadTicks() + Milliseconds(thread_time_ms),
+       TRACE_EVENT_FLAG_JAVA_STRING_LITERALS | TRACE_EVENT_FLAG_COPY);
+ #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
+diff --git a/base/debug/stack_trace.cc b/base/debug/stack_trace.cc
+index 2825e8a6ba..6f1572f10e 100644
+--- a/base/debug/stack_trace.cc
++++ b/base/debug/stack_trace.cc
+@@ -206,7 +206,7 @@ uintptr_t GetStackEnd() {
+   // values from its pthread_t argument.
+   static uintptr_t main_stack_end = 0;
+ 
+-  bool is_main_thread = GetCurrentProcId() == PlatformThread::CurrentId().raw();
++  bool is_main_thread = GetCurrentProcId() == PlatformThread::CurrentId();
+   if (is_main_thread && main_stack_end) {
+     return main_stack_end;
+   }
+@@ -234,8 +234,7 @@ uintptr_t GetStackEnd() {
+ #else
+ 
+ #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && defined(__GLIBC__)
+-  static_assert(std::is_same_v<ProcessId, PlatformThreadId::UnderlyingType>);
+-  if (GetCurrentProcId() == PlatformThread::CurrentId().raw()) {
++  if (GetCurrentProcId() == PlatformThread::CurrentId()) {
+     // For the main thread we have a shortcut.
+     return reinterpret_cast<uintptr_t>(__libc_stack_end);
+   }
+diff --git a/base/message_loop/message_pump_glib.cc b/base/message_loop/message_pump_glib.cc
+index 5df743e45e..6ce797e59e 100644
+--- a/base/message_loop/message_pump_glib.cc
++++ b/base/message_loop/message_pump_glib.cc
+@@ -53,7 +53,7 @@ int GetTimeIntervalMilliseconds(TimeTicks next_task_time) {
+ 
+ bool RunningOnMainThread() {
+   auto pid = getpid();
+-  auto tid = PlatformThread::CurrentId().raw();
++  auto tid = PlatformThread::CurrentId();
+   return pid > 0 && tid > 0 && pid == tid;
+ }
+ 
+diff --git a/base/process/internal_linux.h b/base/process/internal_linux.h
+index 9b621410c2..493722298b 100644
+--- a/base/process/internal_linux.h
++++ b/base/process/internal_linux.h
+@@ -158,11 +158,10 @@ void ForEachProcessTask(base::ProcessHandle process, Lambda&& lambda) {
+       continue;
+     }
+ 
+-    PlatformThreadId::UnderlyingType tid_value;
+-    if (!StringToInt(tid_str, &tid_value)) {
++    PlatformThreadId tid;
++    if (!StringToInt(tid_str, &tid)) {
+       continue;
+     }
+-    PlatformThreadId tid(tid_value);
+ 
+     FilePath task_path = fd_path.Append(tid_str);
+     lambda(tid, task_path);
+diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc
+index d18b91c58e..1d8579ca92 100644
+--- a/base/process/process_unittest.cc
++++ b/base/process/process_unittest.cc
+@@ -419,7 +419,7 @@ TEST_F(ProcessTest, SetProcessPriority) {
+ bool IsThreadRT(PlatformThreadId thread_id) {
+   // Check if the thread is running in real-time mode
+   int sched = sched_getscheduler(
+-      PlatformThread::CurrentId() == thread_id ? 0 : thread_id.raw());
++      PlatformThread::CurrentId() == thread_id ? 0 : thread_id);
+   if (sched == -1) {
+     // The thread may disappear for any reason so ignore ESRCH.
+     DPLOG_IF(ERROR, errno != ESRCH)
+diff --git a/base/process/set_process_title.cc b/base/process/set_process_title.cc
+index b638952395..edd8c78fb1 100644
+--- a/base/process/set_process_title.cc
++++ b/base/process/set_process_title.cc
+@@ -54,8 +54,7 @@ void SetProcessTitleFromCommandLine(const char** main_argv) {
+   bool have_argv0 = false;
+ 
+ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+-  DCHECK_EQ(base::PlatformThread::CurrentId(),
+-            base::PlatformThreadId(getpid()));
++  DCHECK_EQ(base::PlatformThread::CurrentId(), getpid());
+ 
+   if (main_argv) {
+     setproctitle_init(main_argv);
+diff --git a/base/profiler/stack_base_address_posix.cc b/base/profiler/stack_base_address_posix.cc
+index d043d6660d..9f2fbe5081 100644
+--- a/base/profiler/stack_base_address_posix.cc
++++ b/base/profiler/stack_base_address_posix.cc
+@@ -84,7 +84,7 @@ std::optional<uintptr_t> GetThreadStackBaseAddress(PlatformThreadId id,
+   // trying to work around the problem.
+   return std::nullopt;
+ #else
+-  const bool is_main_thread = id.raw() == GetCurrentProcId();
++  const bool is_main_thread = id == GetCurrentProcId();
+   if (is_main_thread) {
+ #if BUILDFLAG(IS_ANDROID)
+     // The implementation of pthread_getattr_np() in Bionic reads proc/self/maps
+diff --git a/base/profiler/stack_base_address_posix_unittest.cc b/base/profiler/stack_base_address_posix_unittest.cc
+index fc7dd1a6df..bfa0e543a8 100644
+--- a/base/profiler/stack_base_address_posix_unittest.cc
++++ b/base/profiler/stack_base_address_posix_unittest.cc
+@@ -40,8 +40,8 @@ TEST(GetThreadStackBaseAddressTest, MAYBE_CurrentThread) {
+ TEST(GetThreadStackBaseAddressTest, MainThread) {
+   // GetThreadStackBaseAddress does not use pthread_id for main thread on these
+   // platforms.
+-  std::optional<uintptr_t> base = GetThreadStackBaseAddress(
+-      PlatformThreadId(GetCurrentProcId()), pthread_t());
++  std::optional<uintptr_t> base =
++      GetThreadStackBaseAddress(GetCurrentProcId(), pthread_t());
+   EXPECT_THAT(base, Optional(Gt(0u)));
+ }
+ 
+diff --git a/base/profiler/stack_sampling_profiler_test_util.h b/base/profiler/stack_sampling_profiler_test_util.h
+index 8f0b74d152..8bcbdcd4b9 100644
+--- a/base/profiler/stack_sampling_profiler_test_util.h
++++ b/base/profiler/stack_sampling_profiler_test_util.h
+@@ -44,7 +44,7 @@ class TargetThread : public PlatformThread::Delegate {
+   SamplingProfilerThreadToken thread_token() const { return thread_token_; }
+ 
+  private:
+-  SamplingProfilerThreadToken thread_token_ = {kInvalidThreadId};
++  SamplingProfilerThreadToken thread_token_ = {0};
+   OnceClosure to_run_;
+   PlatformThreadHandle target_thread_handle_;
+ };
+diff --git a/base/profiler/thread_delegate_posix_unittest.cc b/base/profiler/thread_delegate_posix_unittest.cc
+index d6971674ba..b2b7b4e6fc 100644
+--- a/base/profiler/thread_delegate_posix_unittest.cc
++++ b/base/profiler/thread_delegate_posix_unittest.cc
+@@ -37,8 +37,8 @@ TEST(ThreadDelegatePosixTest, MAYBE_CurrentThreadBase) {
+ // GetThreadStackBaseAddressTest.MainThread.
+ TEST(ThreadDelegatePosixTest, MainThreadStackBase) {
+   // The delegate does not use pthread id for main thread.
+-  auto delegate = ThreadDelegatePosix::Create(SamplingProfilerThreadToken{
+-      PlatformThreadId(GetCurrentProcId()), pthread_t()});
++  auto delegate = ThreadDelegatePosix::Create(
++      SamplingProfilerThreadToken{GetCurrentProcId(), pthread_t()});
+   ASSERT_TRUE(delegate);
+   uintptr_t base = delegate->GetStackBaseAddress();
+   EXPECT_GT(base, 0u);
+diff --git a/base/sampling_heap_profiler/sampling_heap_profiler.cc b/base/sampling_heap_profiler/sampling_heap_profiler.cc
+index 81bf984b8c..a90d923318 100644
+--- a/base/sampling_heap_profiler/sampling_heap_profiler.cc
++++ b/base/sampling_heap_profiler/sampling_heap_profiler.cc
+@@ -94,7 +94,7 @@ const char* GetAndLeakThreadName() {
+   // Use tid if we don't have a thread name.
+   UNSAFE_TODO(snprintf(
+       name, sizeof(name), "Thread %lu",
+-      static_cast<unsigned long>(base::PlatformThread::CurrentId().raw())));
++      static_cast<unsigned long>(base::PlatformThread::CurrentId())));
+   return UNSAFE_TODO(strdup(name));
+ }
+ 
+diff --git a/base/task/sequence_manager/thread_controller.cc b/base/task/sequence_manager/thread_controller.cc
+index f82e2ab448..73c45d0938 100644
+--- a/base/task/sequence_manager/thread_controller.cc
++++ b/base/task/sequence_manager/thread_controller.cc
+@@ -155,7 +155,7 @@ void ThreadController::RunLevelTracker::TimeKeeper::EnableRecording(
+       // track id on some platforms (for example Mac OS), which results in
+       // async tracks not being associated with their thread.
+       perfetto::ThreadTrack::ForThread(
+-          base::PlatformThread::CurrentId().raw()));
++          base::PlatformThread::CurrentId()));
+   // TODO(crbug.com/42050015): Use Perfetto library to name this Track.
+   // auto desc = perfetto_track_->Serialize();
+   // desc.set_name(JoinString({"MessagePumpPhases", thread_name}, " "));
+diff --git a/base/test/launcher/test_launcher_tracer.cc b/base/test/launcher/test_launcher_tracer.cc
+index a9bfcb096f..ca4553ae32 100644
+--- a/base/test/launcher/test_launcher_tracer.cc
++++ b/base/test/launcher/test_launcher_tracer.cc
+@@ -43,19 +43,7 @@ bool TestLauncherTracer::Dump(const FilePath& path) {
+                        (event.timestamp - trace_start_time_).InMicroseconds()));
+     json_event.Set("dur", checked_cast<int>(event.duration.InMicroseconds()));
+ 
+-    // The TID might be an int64, however int64 values are not representable in
+-    // JS and JSON (cf. crbug.com/40228085) since JS numbers are float64. Since
+-    // thread IDs are likely to be allocated sequentially, truncation of the
+-    // high bits is preferable to loss of precision in the low bits, as threads
+-    // are more likely to differ in their low bit values, so we truncate the
+-    // value to int32. Since this is only used for dumping test runner state,
+-    // the loss of information is not catastrophic and won't happen in normal
+-    // browser execution. Additionally, the test thread ids are also truncated,
+-    // so the truncated values should match.
+-    //
+-    // LINT.IfChange(TestLauncherTidTruncation)
+-    json_event.Set("tid", event.thread_id.truncate_to_int32_for_display_only());
+-    // LINT.ThenChange(test_results_tracker.cc:TestLauncherTidTruncation)
++    json_event.Set("tid", checked_cast<int>(event.thread_id));
+ 
+     // Add fake values required by the trace viewer.
+     json_event.Set("pid", 0);
+diff --git a/base/test/launcher/test_results_tracker.cc b/base/test/launcher/test_results_tracker.cc
+index 5352815be2..40b1f37873 100644
+--- a/base/test/launcher/test_results_tracker.cc
++++ b/base/test/launcher/test_results_tracker.cc
+@@ -128,21 +128,7 @@ Value::Dict CreateTestResultValue(const TestResult& test_result) {
+             static_cast<int>(test_result.elapsed_time.InMilliseconds()));
+ 
+   if (test_result.thread_id) {
+-    // The thread id might be an int64, however int64 values are not
+-    // representable in JS and JSON (cf. crbug.com/40228085) since JS
+-    // numbers are float64. Since thread IDs are likely to be allocated
+-    // sequentially, truncation of the high bits is preferable to loss of
+-    // precision in the low bits, as threads are more likely to differ in
+-    // their low bit values, so we truncate the value to int32. Since this
+-    // is only used for dumping test runner state, the loss of information
+-    // is not catastrophic and won't happen in normal browser execution.
+-    // Additionally, the test launcher tid is also truncated, so the
+-    // truncated values should match.
+-    //
+-    // LINT.IfChange(TestLauncherTidTruncation)
+-    value.Set("thread_id",
+-              test_result.thread_id->truncate_to_int32_for_display_only());
+-    // LINT.ThenChange(test_launcher_tracer.cc:TestLauncherTidTruncation)
++    value.Set("thread_id", static_cast<int>(*test_result.thread_id));
+   }
+   if (test_result.process_num) {
+     value.Set("process_num", *test_result.process_num);
+diff --git a/base/test/launcher/test_results_tracker_unittest.cc b/base/test/launcher/test_results_tracker_unittest.cc
+index 225047a255..8787fac190 100644
+--- a/base/test/launcher/test_results_tracker_unittest.cc
++++ b/base/test/launcher/test_results_tracker_unittest.cc
+@@ -139,7 +139,7 @@ TEST(TestResultsTrackerTest, SaveSummaryAsJSONWithTimestampInResult) {
+   TestResultsTracker tracker;
+   TestResult result;
+   result.full_name = "A.B";
+-  result.thread_id = base::PlatformThreadId::ForTest(123);
++  result.thread_id = 123;
+   result.process_num = 456;
+   result.timestamp = Time::Now();
+ 
+diff --git a/base/threading/hang_watcher.cc b/base/threading/hang_watcher.cc
+index 11fec1abbd..14ba071ef3 100644
+--- a/base/threading/hang_watcher.cc
++++ b/base/threading/hang_watcher.cc
+@@ -797,7 +797,7 @@ void HangWatcher::WatchStateSnapShot::Init(
+                                                LoggingLevel::kUmaOnly)) {
+         const PlatformThreadId thread_id = watch_state.get()->GetThreadID();
+         const auto track = perfetto::Track::FromPointer(
+-            this, perfetto::ThreadTrack::ForThread(thread_id.raw()));
++            this, perfetto::ThreadTrack::ForThread(thread_id));
+         TRACE_EVENT_BEGIN("latency", "HangWatcher::ThreadHung", track,
+                           now - monitoring_period);
+         TRACE_EVENT_END("latency", track, now);
+diff --git a/base/threading/hang_watcher.h b/base/threading/hang_watcher.h
+index 3ee0fc89ec..7962db37e1 100644
+--- a/base/threading/hang_watcher.h
++++ b/base/threading/hang_watcher.h
+@@ -664,7 +664,7 @@ class BASE_EXPORT HangWatchState {
+ 
+   // A unique ID of the thread under watch. Used for logging in crash reports
+   // only.
+-  PlatformThreadId thread_id_ = kInvalidThreadId;
++  PlatformThreadId thread_id_ = 0;
+ 
+ #if BUILDFLAG(IS_MAC)
+   // TODO(crbug.com/40187449): Remove this once macOS uses system-wide ids.
+diff --git a/base/threading/hang_watcher_unittest.cc b/base/threading/hang_watcher_unittest.cc
+index bfbc9770d4..d620dd1d69 100644
+--- a/base/threading/hang_watcher_unittest.cc
++++ b/base/threading/hang_watcher_unittest.cc
+@@ -646,7 +646,7 @@ class HangWatcherSnapshotTest : public testing::Test {
+     constexpr char kSeparator{'|'};
+ 
+     for (PlatformThreadId id : ids) {
+-      result += base::NumberToString(id.raw()) + kSeparator;
++      result += base::NumberToString(id) + kSeparator;
+     }
+ 
+     return result;
+diff --git a/base/threading/platform_thread.cc b/base/threading/platform_thread.cc
+index abe6453165..e457a04dc2 100644
+--- a/base/threading/platform_thread.cc
++++ b/base/threading/platform_thread.cc
+@@ -6,7 +6,6 @@
+ 
+ #include "base/task/current_thread.h"
+ #include "base/threading/thread_id_name_manager.h"
+-#include "base/trace_event/base_tracing.h"
+ 
+ #if BUILDFLAG(IS_FUCHSIA)
+ #include "base/fuchsia/scheduler.h"
+@@ -20,10 +19,6 @@ constinit thread_local ThreadType current_thread_type = ThreadType::kDefault;
+ 
+ }  // namespace
+ 
+-void PlatformThreadId::WriteIntoTrace(perfetto::TracedValue&& context) const {
+-  perfetto::WriteIntoTracedValue(std::move(context), value_);
+-}
+-
+ // static
+ void PlatformThreadBase::SetCurrentThreadType(ThreadType thread_type) {
+   MessagePumpType message_pump_type = MessagePumpType::DEFAULT;
+diff --git a/base/threading/platform_thread.h b/base/threading/platform_thread.h
+index 06a667f3da..d6a7cc206d 100644
+--- a/base/threading/platform_thread.h
++++ b/base/threading/platform_thread.h
+@@ -12,7 +12,6 @@
+ #include <stddef.h>
+ 
+ #include <iosfwd>
+-#include <limits>
+ #include <optional>
+ #include <type_traits>
+ 
+@@ -21,7 +20,6 @@
+ #include "base/process/process_handle.h"
+ #include "base/threading/platform_thread_ref.h"
+ #include "base/time/time.h"
+-#include "base/trace_event/base_tracing_forward.h"
+ #include "base/types/strong_alias.h"
+ #include "build/build_config.h"
+ 
+@@ -42,87 +40,17 @@
+ 
+ namespace base {
+ 
+-// Used for uniquely identifying a thread.
+-//
+-// Wraps a platform-specific integer value with platform-specific size,
+-// guaranteed to have a maximum bitness of 64-bit. Getting a 32-bit value is
+-// possible only if we either know the platform-specific size (because we're in
+-// platform-specific code), or if we are ok with truncation of the value (e.g.
+-// because we are logging and the occasional false match is not catastrophic).
+-class BASE_EXPORT PlatformThreadId {
+- public:
++// Used for logging. Always an integer value.
+ #if BUILDFLAG(IS_WIN)
+-  using UnderlyingType = DWORD;
++  typedef DWORD PlatformThreadId;
+ #elif BUILDFLAG(IS_FUCHSIA)
+-  using UnderlyingType = zx_koid_t;
++  typedef zx_koid_t PlatformThreadId;
+ #elif BUILDFLAG(IS_APPLE)
+-  // TODO(crbug.com/40187449): Use uint64_t ids from pthread_threadid_np.
+-  using UnderlyingType = mach_port_t;
++  typedef mach_port_t PlatformThreadId;
+ #elif BUILDFLAG(IS_POSIX)
+-  using UnderlyingType = pid_t;
++  typedef pid_t PlatformThreadId;
+ #endif
+-  static_assert(std::is_integral_v<UnderlyingType>, "Always an integer value.");
+-
+-  constexpr PlatformThreadId() = default;
+-
+-  // Special templated constructor which prevents implicit conversion of the
+-  // integer argument.
+-  template <typename T>
+-  explicit constexpr PlatformThreadId(T value)
+-    requires(std::is_same_v<T, UnderlyingType>)
+-      : value_(value) {}
+-
+-  static constexpr PlatformThreadId ForTest(int value) {
+-    return PlatformThreadId(static_cast<UnderlyingType>(value));
+-  }
+-
+-  // Allow conversion to u/int64_t, whether the underlying type is signed or
+-  // not, and whether it is 32-bit or 64-bit.
+-  explicit constexpr operator uint64_t() const {
+-    static_assert(sizeof(uint64_t) >= sizeof(UnderlyingType));
+-    return static_cast<uint64_t>(value_);
+-  }
+-  explicit constexpr operator int64_t() const {
+-    static_assert(sizeof(int64_t) >= sizeof(UnderlyingType));
+-    return static_cast<int64_t>(value_);
+-  }
+-  // Forbid conversion to u/int32_t, since we might have a 64-bit
+-  // value -- use truncate_to_int32_for_display_only() or raw() instead.
+-  explicit constexpr operator uint32_t() const = delete;
+-  explicit constexpr operator int32_t() const = delete;
+-
+-  // Truncating getter for an int32 representation of the id.
+-  //
+-  // AVOID: This should only be used in cases where truncation is not
+-  // catastrophic, e.g. displaying the thread id in traces or logs. It will
+-  // always be preferable to display the full, untruncated thread id.
+-  constexpr int32_t truncate_to_int32_for_display_only() const {
+-    return static_cast<int32_t>(value_);
+-  }
+-
+-  // Getter for the underlying raw value. Should only be used when
+-  // exposing the UnderlyingType, e.g. passing into system APIs or passing into
+-  // functions overloaded on different integer sizes like NumberToString.
+-  constexpr UnderlyingType raw() const { return value_; }
+-
+-  constexpr friend auto operator<=>(const PlatformThreadId& lhs,
+-                                    const PlatformThreadId& rhs) = default;
+-  constexpr friend bool operator==(const PlatformThreadId& lhs,
+-                                   const PlatformThreadId& rhs) = default;
+-
+-  // Allow serialising into a trace.
+-  void WriteIntoTrace(perfetto::TracedValue&& context) const;
+-
+- private:
+-  // TODO(crbug.com/393384253): Use a system-specific invalid value, which might
+-  // be 0, -1, or some other value from a system header.
+-  UnderlyingType value_ = 0;
+-};
+-
+-inline std::ostream& operator<<(std::ostream& stream,
+-                                const PlatformThreadId& id) {
+-  return stream << id.raw();
+-}
++static_assert(std::is_integral_v<PlatformThreadId>, "Always an integer value.");
+ 
+ // Used to operate on threads.
+ class PlatformThreadHandle {
+@@ -149,7 +77,7 @@ class PlatformThreadHandle {
+   Handle handle_;
+ };
+ 
+-static constexpr PlatformThreadId kInvalidThreadId = PlatformThreadId();
++const PlatformThreadId kInvalidThreadId(0);
+ 
+ // Valid values for `thread_type` of Thread::Options, SimpleThread::Options,
+ // and SetCurrentThreadType(), listed in increasing order of importance.
+@@ -380,7 +308,7 @@ class BASE_EXPORT PlatformThreadLinux : public PlatformThreadBase {
+   // to change the priority of sandboxed threads for improved performance.
+   // Warning: Don't use this for a main thread because that will change the
+   // whole thread group's (i.e. process) priority.
+-  static void SetThreadType(ProcessId process_id,
++  static void SetThreadType(PlatformThreadId process_id,
+                             PlatformThreadId thread_id,
+                             ThreadType thread_type,
+                             IsViaIPC via_ipc);
+@@ -415,7 +343,7 @@ class BASE_EXPORT PlatformThreadChromeOS : public PlatformThreadLinux {
+   // Toggles a specific thread's type at runtime. This is the ChromeOS-specific
+   // version and includes Linux's functionality but does slightly more. See
+   // PlatformThreadLinux's SetThreadType() header comment for Linux details.
+-  static void SetThreadType(ProcessId process_id,
++  static void SetThreadType(PlatformThreadId process_id,
+                             PlatformThreadId thread_id,
+                             ThreadType thread_type,
+                             IsViaIPC via_ipc);
+@@ -470,13 +398,13 @@ void SetCurrentThreadTypeImpl(ThreadType thread_type,
+                               MessagePumpType pump_type_hint);
+ 
+ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+-void SetThreadTypeLinux(ProcessId process_id,
++void SetThreadTypeLinux(PlatformThreadId process_id,
+                         PlatformThreadId thread_id,
+                         ThreadType thread_type,
+                         IsViaIPC via_ipc);
+ #endif
+ #if BUILDFLAG(IS_CHROMEOS)
+-void SetThreadTypeChromeOS(ProcessId process_id,
++void SetThreadTypeChromeOS(PlatformThreadId process_id,
+                            PlatformThreadId thread_id,
+                            ThreadType thread_type,
+                            IsViaIPC via_ipc);
+diff --git a/base/threading/platform_thread_android.cc b/base/threading/platform_thread_android.cc
+index 4ffb477b32..b162aa8ef4 100644
+--- a/base/threading/platform_thread_android.cc
++++ b/base/threading/platform_thread_android.cc
+@@ -69,7 +69,7 @@ bool SetCurrentThreadTypeForPlatform(ThreadType thread_type,
+           base::android::SDK_VERSION_T) {
+     JNIEnv* env = base::android::AttachCurrentThread();
+     Java_ThreadUtils_setThreadPriorityAudio(env,
+-                                            PlatformThread::CurrentId().raw());
++                                            PlatformThread::CurrentId());
+     return true;
+   }
+   // Recent versions of Android (O+) up the priority of the UI thread
+@@ -87,7 +87,7 @@ std::optional<ThreadPriorityForTest>
+ GetCurrentThreadPriorityForPlatformForTest() {
+   JNIEnv* env = base::android::AttachCurrentThread();
+   if (Java_ThreadUtils_isThreadPriorityAudio(
+-          env, PlatformThread::CurrentId().raw())) {
++          env, PlatformThread::CurrentId())) {
+     return std::make_optional(ThreadPriorityForTest::kRealtimeAudio);
+   }
+   return std::nullopt;
+@@ -102,7 +102,7 @@ void PlatformThread::SetName(const std::string& name) {
+   // debugger by setting the process name for the LWP.
+   // We don't want to do this for the main thread because that would rename
+   // the process, causing tools like killall to stop working.
+-  if (PlatformThread::CurrentId().raw() == getpid()) {
++  if (PlatformThread::CurrentId() == getpid()) {
+     return;
+   }
+ 
+diff --git a/base/threading/platform_thread_cros.cc b/base/threading/platform_thread_cros.cc
+index a39e31e872..af8a4ac709 100644
+--- a/base/threading/platform_thread_cros.cc
++++ b/base/threading/platform_thread_cros.cc
+@@ -158,10 +158,9 @@ void SetThreadLatencySensitivity(ProcessId process_id,
+   // conversion from NS tid to global tid is done by the callers using
+   // FindThreadID().
+   FilePath thread_dir;
+-  if (thread_id != kInvalidThreadId &&
+-      thread_id != PlatformThread::CurrentId()) {
+-    thread_dir = FilePath(
+-        StringPrintf("/proc/%d/task/%d/", process_id, thread_id.raw()));
++  if (thread_id && thread_id != PlatformThread::CurrentId()) {
++    thread_dir =
++        FilePath(StringPrintf("/proc/%d/task/%d/", process_id, thread_id));
+   } else {
+     thread_dir = FilePath("/proc/thread-self/");
+   }
+@@ -173,7 +172,7 @@ void SetThreadLatencySensitivity(ProcessId process_id,
+   }
+ 
+   // Silently ignore if getattr fails due to sandboxing.
+-  if (sched_getattr(thread_id.raw(), &attr, sizeof(attr), 0) == -1 ||
++  if (sched_getattr(thread_id, &attr, sizeof(attr), 0) == -1 ||
+       attr.size != sizeof(attr)) {
+     return;
+   }
+@@ -218,7 +217,7 @@ void SetThreadLatencySensitivity(ProcessId process_id,
+   DCHECK_LE(attr.sched_util_max, kSchedulerUclampMax);
+ 
+   attr.size = sizeof(struct sched_attr);
+-  if (sched_setattr(thread_id.raw(), &attr, 0) == -1) {
++  if (sched_setattr(thread_id, &attr, 0) == -1) {
+     // We log it as an error because, if the PathExists above succeeded, we
+     // expect this syscall to also work since the kernel is new'ish.
+     PLOG_IF(ERROR, errno != E2BIG)
+@@ -239,8 +238,7 @@ std::optional<ThreadType> GetThreadTypeForNiceValue(int nice_value) {
+ std::optional<int> GetNiceValueForThreadId(PlatformThreadId thread_id) {
+   // Get the current nice value of the thread_id
+   errno = 0;
+-  int nice_value =
+-      getpriority(PRIO_PROCESS, static_cast<id_t>(thread_id.raw()));
++  int nice_value = getpriority(PRIO_PROCESS, static_cast<id_t>(thread_id));
+   if (nice_value == -1 && errno != 0) {
+     // The thread may disappear for any reason so ignore ESRCH.
+     DVPLOG_IF(1, errno != ESRCH)
+@@ -299,8 +297,8 @@ void SetThreadRTPrioFromType(ProcessId process_id,
+       return;
+   }
+ 
+-  pid_t syscall_tid =
+-      thread_id == PlatformThread::CurrentId() ? 0 : thread_id.raw();
++  PlatformThreadId syscall_tid =
++      thread_id == PlatformThread::CurrentId() ? 0 : thread_id;
+   if (sched_setscheduler(syscall_tid, policy, &prio) != 0) {
+     DVPLOG(1) << "Failed to set policy/priority for thread " << thread_id;
+   }
+@@ -309,8 +307,8 @@ void SetThreadRTPrioFromType(ProcessId process_id,
+ void SetThreadNiceFromType(ProcessId process_id,
+                            PlatformThreadId thread_id,
+                            ThreadType thread_type) {
+-  pid_t syscall_tid =
+-      thread_id == PlatformThread::CurrentId() ? 0 : thread_id.raw();
++  PlatformThreadId syscall_tid =
++      thread_id == PlatformThread::CurrentId() ? 0 : thread_id;
+   const int nice_setting = internal::ThreadTypeToNiceValue(thread_type);
+   if (setpriority(PRIO_PROCESS, static_cast<id_t>(syscall_tid), nice_setting)) {
+     DVPLOG(1) << "Failed to set nice value of thread " << thread_id << " to "
+diff --git a/base/threading/platform_thread_linux.cc b/base/threading/platform_thread_linux.cc
+index a91ebbdabc..8a07c474ca 100644
+--- a/base/threading/platform_thread_linux.cc
++++ b/base/threading/platform_thread_linux.cc
+@@ -66,7 +66,7 @@ FilePath ThreadTypeToCgroupDirectory(const FilePath& cgroup_filepath,
+ void SetThreadCgroup(PlatformThreadId thread_id,
+                      const FilePath& cgroup_directory) {
+   FilePath tasks_filepath = cgroup_directory.Append(FILE_PATH_LITERAL("tasks"));
+-  std::string tid = NumberToString(thread_id.raw());
++  std::string tid = NumberToString(thread_id);
+   if (!WriteFile(tasks_filepath, as_byte_span(tid))) {
+     DVLOG(1) << "Failed to add " << tid << " to " << tasks_filepath.value();
+   }
+@@ -180,7 +180,7 @@ bool PlatformThreadLinux::IsThreadBackgroundedForTest(
+   FilePath non_urgent_tasks_filepath =
+       non_urgent_cgroup_directory.Append(FILE_PATH_LITERAL("tasks"));
+ 
+-  std::string tid = NumberToString(thread_id.raw());
++  std::string tid = NumberToString(thread_id);
+   // Check if thread_id is in the urgent cpuset
+   std::string urgent_tasks;
+   if (!ReadFileToString(urgent_tasks_filepath, &urgent_tasks)) {
+@@ -209,7 +209,7 @@ void PlatformThreadBase::SetName(const std::string& name) {
+   // the process name for the LWP.  We don't want to do this for the main
+   // thread because that would rename the process, causing tools like killall
+   // to stop working.
+-  if (PlatformThread::CurrentId().raw() == getpid()) {
++  if (PlatformThread::CurrentId() == getpid()) {
+     return;
+   }
+ 
+@@ -267,11 +267,11 @@ void SetThreadTypeLinux(ProcessId process_id,
+   // global TID.
+   PlatformThreadId syscall_tid = thread_id;
+   if (thread_id == PlatformThreadLinux::CurrentId()) {
+-    syscall_tid = kInvalidThreadId;
++    syscall_tid = 0;
+   }
+ 
+   if (thread_type == ThreadType::kRealtimeAudio) {
+-    if (sched_setscheduler(syscall_tid.raw(), SCHED_RR,
++    if (sched_setscheduler(syscall_tid, SCHED_RR,
+                            &PlatformThreadLinux::kRealTimeAudioPrio) == 0) {
+       return;
+     }
+@@ -280,7 +280,7 @@ void SetThreadTypeLinux(ProcessId process_id,
+   }
+ 
+   const int nice_setting = ThreadTypeToNiceValue(thread_type);
+-  if (setpriority(PRIO_PROCESS, static_cast<id_t>(syscall_tid.raw()),
++  if (setpriority(PRIO_PROCESS, static_cast<id_t>(syscall_tid),
+                   nice_setting)) {
+     DVPLOG(1) << "Failed to set nice value of thread (" << thread_id << ") to "
+               << nice_setting;
+diff --git a/base/threading/platform_thread_posix.cc b/base/threading/platform_thread_posix.cc
+index f5ea6363d0..e749d5cb28 100644
+--- a/base/threading/platform_thread_posix.cc
++++ b/base/threading/platform_thread_posix.cc
+@@ -218,7 +218,9 @@ PlatformThreadId PlatformThreadBase::CurrentId() {
+   // Pthreads doesn't have the concept of a thread ID, so we have to reach down
+   // into the kernel.
+ #if BUILDFLAG(IS_APPLE)
+-  return PlatformThreadId(pthread_mach_thread_np(pthread_self()));
++  uint64_t tid;
++  CHECK_EQ(pthread_threadid_np(nullptr, &tid), 0);
++  return tid;
+ #elif BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
+   // Workaround false-positive MSAN use-of-uninitialized-value on
+   // thread_local storage for loaded libraries:
+@@ -249,29 +251,29 @@ PlatformThreadId PlatformThreadBase::CurrentId() {
+     }
+ #endif
+   }
+-  return PlatformThreadId(g_thread_id);
++  return g_thread_id;
+ #elif BUILDFLAG(IS_ANDROID)
+   // Note: do not cache the return value inside a thread_local variable on
+   // Android (as above). The reasons are:
+   // - thread_local is slow on Android (goes through emutls)
+   // - gettid() is fast, since its return value is cached in pthread (in the
+   //   thread control block of pthread). See gettid.c in bionic.
+-  return PlatformThreadId(gettid());
++  return gettid();
+ #elif BUILDFLAG(IS_FUCHSIA)
+   thread_local static zx_koid_t id =
+       GetKoid(*zx::thread::self()).value_or(ZX_KOID_INVALID);
+-  return PlatformThreadId(id);
++  return id;
+ #elif BUILDFLAG(IS_SOLARIS) || BUILDFLAG(IS_QNX)
+-  return PlatformThreadId(pthread_self());
++  return pthread_self();
+ #elif BUILDFLAG(IS_NACL) && defined(__GLIBC__)
+-  return PlatformThreadId(pthread_self());
++  return pthread_self();
+ #elif BUILDFLAG(IS_NACL) && !defined(__GLIBC__)
+   // Pointers are 32-bits in NaCl.
+-  return PlatformThreadId(reinterpret_cast<int32_t>(pthread_self()));
++  return reinterpret_cast<int32_t>(pthread_self());
+ #elif BUILDFLAG(IS_POSIX) && BUILDFLAG(IS_AIX)
+-  return PlatformThreadId(pthread_self());
++  return pthread_self();
+ #elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_AIX)
+-  return PlatformThreadId(reinterpret_cast<int64_t>(pthread_self()));
++  return reinterpret_cast<int64_t>(pthread_self());
+ #endif
+ }
+ 
+diff --git a/base/threading/platform_thread_unittest.cc b/base/threading/platform_thread_unittest.cc
+index 076fa2f6f6..ca20b4c808 100644
+--- a/base/threading/platform_thread_unittest.cc
++++ b/base/threading/platform_thread_unittest.cc
+@@ -629,7 +629,7 @@ INSTANTIATE_TEST_SUITE_P(
+ namespace {
+ 
+ bool IsTidCacheCorrect() {
+-  return PlatformThread::CurrentId().raw() == syscall(__NR_gettid);
++  return PlatformThread::CurrentId() == syscall(__NR_gettid);
+ }
+ 
+ void* CheckTidCacheCorrectWrapper(void*) {
+diff --git a/base/threading/thread_collision_warner.h b/base/threading/thread_collision_warner.h
+index a00923a237..4df63e934c 100644
+--- a/base/threading/thread_collision_warner.h
++++ b/base/threading/thread_collision_warner.h
+@@ -145,7 +145,7 @@ class BASE_EXPORT ThreadCollisionWarner {
+  public:
+   // The parameter asserter is there only for test purpose
+   explicit ThreadCollisionWarner(AsserterBase* asserter = new DCheckAsserter())
+-      : valid_thread_id_(kInvalidThreadId), counter_(0), asserter_(asserter) {}
++      : valid_thread_id_(0), counter_(0), asserter_(asserter) {}
+ 
+   ThreadCollisionWarner(const ThreadCollisionWarner&) = delete;
+   ThreadCollisionWarner& operator=(const ThreadCollisionWarner&) = delete;
+diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
+index 828c62d531..e86c41c74d 100644
+--- a/base/trace_event/trace_event_impl.cc
++++ b/base/trace_event/trace_event_impl.cc
+@@ -36,7 +36,7 @@ namespace legacy {
+ 
+ template <>
+ perfetto::ThreadTrack ConvertThreadId(const ::base::PlatformThreadId& thread) {
+-  return perfetto::ThreadTrack::ForThread(thread.raw());
++  return perfetto::ThreadTrack::ForThread(thread);
+ }
+ 
+ }  // namespace legacy
+@@ -159,11 +159,11 @@ void TraceEvent::AppendAsJSON(
+     const ArgumentFilterPredicate& argument_filter_predicate) const {
+   int64_t time_int64 = timestamp_.ToInternalValue();
+   ProcessId process_id;
+-  std::optional<PlatformThreadId> thread_id;
++  PlatformThreadId thread_id;
+   if ((flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID) &&
+       process_id_ != kNullProcessId) {
+     process_id = process_id_;
+-    thread_id = std::nullopt;
++    thread_id = static_cast<PlatformThreadId>(-1);
+   } else {
+     process_id = TraceLog::GetInstance()->process_id();
+     thread_id = thread_id_;
+@@ -171,26 +171,13 @@ void TraceEvent::AppendAsJSON(
+   const char* category_group_name =
+       TraceLog::GetCategoryGroupName(category_group_enabled_);
+ 
+-  // The thread id might be an int64, however int64 values are not
+-  // representable in JS and JSON (cf. crbug.com/40228085) since JS
+-  // numbers are float64. Since thread IDs are likely to be allocated
+-  // sequentially, truncation of the high bits is preferable to loss of
+-  // precision in the low bits, as threads are more likely to differ in
+-  // their low bit values, so we truncate the value to int32. Since this
+-  // is only used for legacy JSON trace events, the loss of information
+-  // is not catastrophic and won't affect normal browser execution, nor
+-  // tracing with perfetto protobufs. In the worst case, the trace events
+-  // will show up on a different thread track when displayed in a trace UI.
+-  int thread_id_for_json =
+-      thread_id ? thread_id->truncate_to_int32_for_display_only() : -1;
+-
+   // Category group checked at category creation time.
+   DCHECK(!strchr(name_, '"'));
+   StringAppendF(out,
+                 "{\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64
+                 ",\"ph\":\"%c\",\"cat\":\"%s\",\"name\":",
+-                static_cast<int>(process_id), thread_id_for_json, time_int64,
+-                phase_, category_group_name);
++                static_cast<int>(process_id), static_cast<int>(thread_id),
++                time_int64, phase_, category_group_name);
+   EscapeJSONString(name_, true, out);
+   *out += ",\"args\":";
+ 
+diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h
+index 64d705906d..892847d58f 100644
+--- a/base/trace_event/trace_event_impl.h
++++ b/base/trace_event/trace_event_impl.h
+@@ -158,7 +158,7 @@ class BASE_EXPORT TraceEvent {
+   //  tid: thread_id_, pid: current_process_id (default case).
+   //  tid: -1, pid: process_id_ (when flags_ & TRACE_EVENT_FLAG_HAS_PROCESS_ID).
+   union {
+-    PlatformThreadId thread_id_ = kInvalidThreadId;
++    PlatformThreadId thread_id_ = 0;
+     ProcessId process_id_;
+   };
+   unsigned int flags_ = 0;
+diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
+index be77932a48..b74b559025 100644
+--- a/base/trace_event/trace_log.cc
++++ b/base/trace_event/trace_log.cc
+@@ -198,11 +198,11 @@ void OnAddLegacyTraceEvent(TraceEvent* trace_event) {
+         break;
+     }
+   }
+-  if (trace_event->thread_id() != kInvalidThreadId &&
++  if (trace_event->thread_id() &&
+       trace_event->thread_id() != base::PlatformThread::CurrentId()) {
+     PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(
+         phase, category, trace_event->name(),
+-        perfetto::ThreadTrack::ForThread(trace_event->thread_id().raw()),
++        perfetto::ThreadTrack::ForThread(trace_event->thread_id()),
+         timestamp, write_args);
+     return;
+   }
+@@ -224,11 +224,11 @@ void OnUpdateLegacyTraceEventDuration(
+   auto phase = TRACE_EVENT_PHASE_END;
+   base::TimeTicks timestamp =
+       explicit_timestamps ? now : TRACE_TIME_TICKS_NOW();
+-  if (thread_id != kInvalidThreadId &&
++  if (thread_id &&
+       thread_id != base::PlatformThread::CurrentId()) {
+     PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(
+         phase, category, name,
+-        perfetto::ThreadTrack::ForThread(thread_id.raw()), timestamp);
++        perfetto::ThreadTrack::ForThread(thread_id), timestamp);
+     return;
+   }
+   PERFETTO_INTERNAL_LEGACY_EVENT_ON_TRACK(
+@@ -863,15 +863,12 @@ base::trace_event::TraceEventHandle AddTraceEventWithProcessId(
+     base::ProcessId process_id,
+     base::trace_event::TraceArguments* args,
+     unsigned int flags) {
+-  static_assert(sizeof(base::PlatformThreadId::UnderlyingType) >=
+-                sizeof(base::ProcessId));
+   base::TimeTicks now = TRACE_TIME_TICKS_NOW();
+   return AddTraceEventWithThreadIdAndTimestamp(
+       phase, category_group_enabled, name, scope, id,
+       trace_event_internal::kNoId,  // bind_id
+-      base::PlatformThreadId(
+-          static_cast<base::PlatformThreadId::UnderlyingType>(process_id)),
+-      now, args, flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
++      static_cast<base::PlatformThreadId>(process_id), now, args,
++      flags | TRACE_EVENT_FLAG_HAS_PROCESS_ID);
+ }
+ 
+ base::trace_event::TraceEventHandle AddTraceEventWithThreadIdAndTimestamp(
+diff --git a/base/tracing/perfetto_platform.cc b/base/tracing/perfetto_platform.cc
+index 92ed57c975..ddfc152831 100644
+--- a/base/tracing/perfetto_platform.cc
++++ b/base/tracing/perfetto_platform.cc
+@@ -90,8 +90,7 @@ std::string PerfettoPlatform::GetCurrentProcessName() {
+ }
+ 
+ perfetto::base::PlatformThreadId PerfettoPlatform::GetCurrentThreadId() {
+-  return base::strict_cast<perfetto::base::PlatformThreadId>(
+-      base::PlatformThread::CurrentId().raw());
++  return base::PlatformThread::CurrentId();
+ }
+ 
+ }  // namespace base::tracing
+-- 
+2.49.0.395.g12beb8f557-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-1700-Revert-Log-path-to-filename-line.patch b/libchrome_tools/patches/backward-compatibility-1700-Revert-Log-path-to-filename-line.patch
new file mode 100644
index 0000000..5dac772
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-1700-Revert-Log-path-to-filename-line.patch
@@ -0,0 +1,140 @@
+From c9fdc6ccbe99f02fb1ace41aa44b131111d14b26 Mon Sep 17 00:00:00 2001
+From: Ryo Hashimoto <hashimoto@chromium.org>
+Date: Mon, 17 Mar 2025 17:57:51 +0900
+Subject: [PATCH] Revert "Log path/to/filename:line"
+
+This reverts commit 22cee264b3adfb1d7126a74b933ccd6b932802a0.
+---
+ base/check_unittest.cc                       |  5 ++---
+ base/logging.cc                              | 21 ++++++--------------
+ base/logging_chromeos.cc                     |  2 +-
+ base/test/launcher/test_launcher.cc          |  8 +-------
+ base/test/launcher/test_launcher_unittest.cc |  9 +++------
+ 5 files changed, 13 insertions(+), 32 deletions(-)
+
+diff --git a/base/check_unittest.cc b/base/check_unittest.cc
+index fd5287a7b8..24df65ed84 100644
+--- a/base/check_unittest.cc
++++ b/base/check_unittest.cc
+@@ -60,9 +60,8 @@ class ScopedExpectDumpWithoutCrashing {
+ };
+ 
+ MATCHER_P2(LogErrorMatches, line, expected_msg, "") {
+-  EXPECT_THAT(arg,
+-              testing::HasSubstr(base::StringPrintf(
+-                  "%s:%d] ", base::Location::Current().file_name(), line)));
++  EXPECT_THAT(arg, testing::HasSubstr(
++                       base::StringPrintf("check_unittest.cc(%d)] ", line)));
+   if (std::string(expected_msg).find("=~") == 0) {
+     EXPECT_THAT(std::string(arg),
+                 testing::ContainsRegex(std::string(expected_msg).substr(2)));
+diff --git a/base/logging.cc b/base/logging.cc
+index bccc6c9eca..e996f8c614 100644
+--- a/base/logging.cc
++++ b/base/logging.cc
+@@ -960,20 +960,11 @@ void LogMessage::Init(const char* file, int line) {
+   // Don't let actions from this method affect the system error after returning.
+   base::ScopedClearLastError scoped_clear_last_error;
+ 
+-  // Most logging initializes `file` from __FILE__. Unfortunately, because we
+-  // build from out/Foo we get a `../../` (or \) prefix for all of our
+-  // __FILE__s. This isn't true for base::Location::Current() which already does
+-  // the stripping (and is used for some logging, especially CHECKs).
+-  //
+-  // Here we strip the first 6 (../../ or ..\..\) characters if `file` starts
+-  // with `.` but defensively clamp to strlen(file) just in case.
+-  //
+-  // TODO(pbos): Consider migrating LogMessage and the LOG() macros to use
+-  // base::Location directly. See base/check.h for inspiration.
+-  const std::string_view filename =
+-      file[0] == '.' ? std::string_view(file).substr(
+-                           std::min(std::size_t{6}, strlen(file)))
+-                     : file;
++  std::string_view filename(file);
++  size_t last_slash_pos = filename.find_last_of("\\/");
++  if (last_slash_pos != std::string_view::npos) {
++    filename.remove_prefix(last_slash_pos + 1);
++  }
+ 
+ #if BUILDFLAG(IS_CHROMEOS)
+   if (g_log_format == LogFormat::LOG_FORMAT_SYSLOG) {
+@@ -1027,7 +1018,7 @@ void LogMessage::Init(const char* file, int line) {
+     } else {
+       stream_ << "VERBOSE" << -severity_;
+     }
+-    stream_ << ":" << filename << ":" << line << "] ";
++    stream_ << ":" << filename << "(" << line << ")] ";
+   }
+   message_start_ = stream_.str().length();
+ }
+diff --git a/base/logging_chromeos.cc b/base/logging_chromeos.cc
+index 834b8adca3..0b43619980 100644
+--- a/base/logging_chromeos.cc
++++ b/base/logging_chromeos.cc
+@@ -86,7 +86,7 @@ void LogMessage::InitWithSyslogPrefix(std::string_view filename,
+     stream_ << "]";
+   }
+   stream_ << ": ";
+-  stream_ << "[" << filename << ":" << line << "] ";
++  stream_ << "[" << filename << "(" << line << ")] ";
+ }
+ 
+ }  // namespace logging
+diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc
+index 163fb4f806..2497ccbbd0 100644
+--- a/base/test/launcher/test_launcher.cc
++++ b/base/test/launcher/test_launcher.cc
+@@ -231,13 +231,7 @@ const size_t kOutputSnippetLinesLimit = 5000;
+ 
+ // Limit of output snippet size. Exceeding this limit
+ // results in truncating the output and failing the test.
+-// TODO(pbos): Investigate lowering this number (it used to be 300k before
+-// logging lines got longer, but even that seems excessive). If we need this to
+-// be even that high then try to figure out why and document that here. The
+-// author of this comment assumes that the prior limit was set to be submittable
+-// with the tests that were checked in at the time rather than thinking that
+-// logging 300k is a good threshold.
+-const size_t kOutputSnippetBytesLimit = 500 * 1024;
++const size_t kOutputSnippetBytesLimit = 300 * 1024;
+ 
+ // Limit of seed values for gtest shuffling. Arbitrary, but based on
+ // gtest's similarly arbitrary choice.
+diff --git a/base/test/launcher/test_launcher_unittest.cc b/base/test/launcher/test_launcher_unittest.cc
+index d594ca794f..ec9740eda6 100644
+--- a/base/test/launcher/test_launcher_unittest.cc
++++ b/base/test/launcher/test_launcher_unittest.cc
+@@ -43,8 +43,6 @@ using ::testing::InvokeWithoutArgs;
+ using ::testing::Return;
+ using ::testing::ReturnPointee;
+ 
+-constexpr int kExcessiveBytes = 700000;
+-
+ TestResult GenerateTestResult(const std::string& test_name,
+                               TestResult::Status status,
+                               TimeDelta elapsed_td = Milliseconds(30),
+@@ -617,7 +615,7 @@ TEST_F(TestLauncherTest, ExcessiveOutput) {
+   command_line->AppendSwitchASCII("test-launcher-print-test-stdio", "never");
+   TestResult test_result =
+       GenerateTestResult("Test.firstTest", TestResult::TEST_SUCCESS,
+-                         Milliseconds(30), std::string(kExcessiveBytes, 'a'));
++                         Milliseconds(30), std::string(500000, 'a'));
+   EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _, _))
+       .WillOnce(OnTestResult(&test_launcher, test_result));
+   EXPECT_FALSE(test_launcher.Run(command_line.get()));
+@@ -628,11 +626,10 @@ TEST_F(TestLauncherTest, OutputLimitSwitch) {
+   AddMockedTests("Test", {"firstTest"});
+   SetUpExpectCalls();
+   command_line->AppendSwitchASCII("test-launcher-print-test-stdio", "never");
+-  command_line->AppendSwitchASCII("test-launcher-output-bytes-limit",
+-                                  base::ToString(kExcessiveBytes + 100000));
++  command_line->AppendSwitchASCII("test-launcher-output-bytes-limit", "800000");
+   TestResult test_result =
+       GenerateTestResult("Test.firstTest", TestResult::TEST_SUCCESS,
+-                         Milliseconds(30), std::string(kExcessiveBytes, 'a'));
++                         Milliseconds(30), std::string(500000, 'a'));
+   EXPECT_CALL(test_launcher, LaunchChildGTestProcess(_, _, _, _))
+       .WillOnce(OnTestResult(&test_launcher, test_result));
+   EXPECT_TRUE(test_launcher.Run(command_line.get()));
+-- 
+2.49.0.rc1.451.g8f38331e32-goog
+
diff --git a/libchrome_tools/patches/backward-compatibility-1800-Revert-base-remove-base-numerics-aliases.patch b/libchrome_tools/patches/backward-compatibility-1800-Revert-base-remove-base-numerics-aliases.patch
new file mode 100644
index 0000000..72a4aa3
--- /dev/null
+++ b/libchrome_tools/patches/backward-compatibility-1800-Revert-base-remove-base-numerics-aliases.patch
@@ -0,0 +1,91 @@
+From 50b40665dcd408dfbc2c0bddcb4d22e19971a0d0 Mon Sep 17 00:00:00 2001
+From: Georg Neis <neis@chromium.org>
+Date: Wed, 30 Apr 2025 03:14:05 +0000
+Subject: [PATCH] Revert "base: remove base::numerics aliases"
+
+This reverts commit 7a2902059dab84b6d368aeeb83bcd0b84ee180e7.
+---
+ base/numerics/byte_conversions.h | 67 ++++++++++++++++++++++++++++++++
+ 1 file changed, 67 insertions(+)
+
+diff --git a/base/numerics/byte_conversions.h b/base/numerics/byte_conversions.h
+index cc8d6f8b35..c014fa79cd 100644
+--- a/base/numerics/byte_conversions.h
++++ b/base/numerics/byte_conversions.h
+@@ -708,6 +708,73 @@ inline constexpr std::array<uint8_t, 8u> DoubleToBigEndian(double val) {
+   return internal::ToLittleEndian(ByteSwap(std::bit_cast<uint64_t>(val)));
+ }
+ 
++// Deprecated: Prefer the shorter, less-namespaced names.
++// TODO(crbug.com/409350835): Remove these when callers have been migrated to
++// the shorter name.
++namespace numerics {
++using ::base::ByteSwap;
++using ::base::DoubleFromBigEndian;
++using ::base::DoubleFromLittleEndian;
++using ::base::DoubleFromNativeEndian;
++using ::base::DoubleToBigEndian;
++using ::base::DoubleToLittleEndian;
++using ::base::DoubleToNativeEndian;
++using ::base::FloatFromBigEndian;
++using ::base::FloatFromLittleEndian;
++using ::base::FloatFromNativeEndian;
++using ::base::FloatToBigEndian;
++using ::base::FloatToLittleEndian;
++using ::base::FloatToNativeEndian;
++using ::base::I16FromBigEndian;
++using ::base::I16FromLittleEndian;
++using ::base::I16FromNativeEndian;
++using ::base::I16ToBigEndian;
++using ::base::I16ToLittleEndian;
++using ::base::I16ToNativeEndian;
++using ::base::I32FromBigEndian;
++using ::base::I32FromLittleEndian;
++using ::base::I32FromNativeEndian;
++using ::base::I32ToBigEndian;
++using ::base::I32ToLittleEndian;
++using ::base::I32ToNativeEndian;
++using ::base::I64FromBigEndian;
++using ::base::I64FromLittleEndian;
++using ::base::I64FromNativeEndian;
++using ::base::I64ToBigEndian;
++using ::base::I64ToLittleEndian;
++using ::base::I64ToNativeEndian;
++using ::base::I8FromBigEndian;
++using ::base::I8FromLittleEndian;
++using ::base::I8FromNativeEndian;
++using ::base::I8ToBigEndian;
++using ::base::I8ToLittleEndian;
++using ::base::I8ToNativeEndian;
++using ::base::U16FromBigEndian;
++using ::base::U16FromLittleEndian;
++using ::base::U16FromNativeEndian;
++using ::base::U16ToBigEndian;
++using ::base::U16ToLittleEndian;
++using ::base::U16ToNativeEndian;
++using ::base::U32FromBigEndian;
++using ::base::U32FromLittleEndian;
++using ::base::U32FromNativeEndian;
++using ::base::U32ToBigEndian;
++using ::base::U32ToLittleEndian;
++using ::base::U32ToNativeEndian;
++using ::base::U64FromBigEndian;
++using ::base::U64FromLittleEndian;
++using ::base::U64FromNativeEndian;
++using ::base::U64ToBigEndian;
++using ::base::U64ToLittleEndian;
++using ::base::U64ToNativeEndian;
++using ::base::U8FromBigEndian;
++using ::base::U8FromLittleEndian;
++using ::base::U8FromNativeEndian;
++using ::base::U8ToBigEndian;
++using ::base::U8ToLittleEndian;
++using ::base::U8ToNativeEndian;
++}  // namespace numerics
++
+ }  // namespace base
+ 
+ #endif  // BASE_NUMERICS_BYTE_CONVERSIONS_H_
+-- 
+2.49.0.967.g6a0df3ecc3-goog
+
diff --git a/libchrome_tools/patches/long-term-0000-Add-libchrome-specific-build-configs.patch b/libchrome_tools/patches/long-term-0000-Add-libchrome-specific-build-configs.patch
new file mode 100644
index 0000000..5744cf7
--- /dev/null
+++ b/libchrome_tools/patches/long-term-0000-Add-libchrome-specific-build-configs.patch
@@ -0,0 +1,57 @@
+From c1f6674152aa6cf08fa03cc4c9c967ccd1ce12d8 Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Tue, 14 Jun 2022 22:11:19 +0900
+Subject: [PATCH] Add libchrome-specific build configs
+
+Change-Id: Ic6580e412c3f1a4f2fe7b425bf7ead6c2fb18dbb
+patch-name: long-term-0000-Add-libchrome-specific-build-configs.patch
+---
+ build/build_config.h | 28 ++++++++++++++++++++++++++--
+ 1 file changed, 26 insertions(+), 2 deletions(-)
+
+diff --git a/build/build_config.h b/build/build_config.h
+index fed5f3eb33..a7725b26cc 100644
+--- a/build/build_config.h
++++ b/build/build_config.h
+@@ -54,12 +54,36 @@
+ 
+ #include "build/buildflag.h"  // IWYU pragma: export
+ 
++// A brief primer on #defines:
++//
++// - __ANDROID__ is automatically defined by the Android toolchain (see
++//   https://goo.gl/v61lXa). It's not defined when building host code.
++// - __ANDROID_HOST__ is defined via -D by Android.mk when building host code
++//   within an Android checkout.
++// - ANDROID is defined via -D when building code for either Android targets or
++//   hosts. Use __ANDROID__ and __ANDROID_HOST__ instead.
++// - OS_ANDROID is a define used to build Chrome for Android within the NDK and
++//   to build Android targets.
++
++// Android targets and hosts don't use tcmalloc.
++#if defined(__ANDROID__) || defined(__ANDROID_HOST__)
++#define NO_TCMALLOC
++#endif  // defined(__ANDROID__) || defined(__ANDROID_HOST__)
++
++#if defined(__ANDROID__)  // Android targets
++
++#define OS_ANDROID 1
++
++#elif !defined(__ANDROID_HOST__)  // Chrome OS
++
++#define OS_CHROMEOS 1
++
++#endif  // defined(__ANDROID__)
++
+ // A set of macros to use for platform detection.
+ #if defined(__native_client__)
+ // __native_client__ must be first, so that other OS_ defines are not set.
+ #define OS_NACL 1
+-#elif defined(ANDROID)
+-#define OS_ANDROID
+ #elif defined(__APPLE__)
+ // Only include TargetConditionals after testing ANDROID as some Android builds
+ // on the Mac have this header available and it's not needed unless the target
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/long-term-0100-Remove-ICU-dependency-for-base-Time-Explode.patch b/libchrome_tools/patches/long-term-0100-Remove-ICU-dependency-for-base-Time-Explode.patch
new file mode 100644
index 0000000..ffab2ad
--- /dev/null
+++ b/libchrome_tools/patches/long-term-0100-Remove-ICU-dependency-for-base-Time-Explode.patch
@@ -0,0 +1,37 @@
+From 637cbeaf49c64e9879dedcbfddb893c159ee4fd5 Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Wed, 15 Jun 2022 23:23:05 +0900
+Subject: [PATCH] Remove ICU dependency for base::Time::Explode
+
+ICU dependency was introduced for Explode implementation to tackle Y2038
+problem but it signigicantly increases binary size. Removed as Y2038
+boards will be EOL by then.
+
+patch-name: long-term-0100-Remove-ICU-dependency-for-base-Time-Explode.patch
+Change-Id: I644b97c1c47481eb6ddff6b7b109d10e4ff27a82
+---
+ base/time/time_exploded_posix.cc | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/base/time/time_exploded_posix.cc b/base/time/time_exploded_posix.cc
+index 8cc737611a..3cba1afd6b 100644
+--- a/base/time/time_exploded_posix.cc
++++ b/base/time/time_exploded_posix.cc
+@@ -126,12 +126,14 @@ void Time::Explode(bool is_local, Exploded* exploded) const {
+ 
+   // For systems with a Y2038 problem, use ICU as the Explode() implementation.
+   if (sizeof(SysTime) < 8) {
++#if 0 // Not to introduce icu dependency for now. Y2038 boards will be EOL by then.
+ // TODO(b/167763382) Find an alternate solution for Chromecast devices, since
+ // adding the icui18n dep significantly increases the binary size.
+ #if !BUILDFLAG(IS_CASTOS) && !BUILDFLAG(IS_CAST_ANDROID)
+     ExplodeUsingIcu(millis_since_unix_epoch, is_local, exploded);
+     return;
+ #endif  // !BUILDFLAG(IS_CASTOS) && !BUILDFLAG(IS_CAST_ANDROID)
++#endif
+   }
+ 
+   // Split the |millis_since_unix_epoch| into separate seconds and millisecond
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/long-term-0200-disable-allocator-sanitizer.patch b/libchrome_tools/patches/long-term-0200-disable-allocator-sanitizer.patch
new file mode 100644
index 0000000..6715235
--- /dev/null
+++ b/libchrome_tools/patches/long-term-0200-disable-allocator-sanitizer.patch
@@ -0,0 +1,59 @@
+From 7db43407d72c399d20b94ba07a8ffb47e6506fd0 Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Fri, 14 Oct 2022 14:41:31 +0900
+Subject: [PATCH] disable allocator sanitizer
+
+Disable custom memory allocator when asan is used.
+
+Change-Id: I593b2acc1b51b8fbd310acdff264f58cd4947773
+patch-name: long-term-0200-disable-allocator-sanitizer.patch
+---
+ .../shim/allocator_shim_override_cpp_symbols.h                | 4 ++++
+ .../shim/allocator_shim_override_libc_symbols.h               | 4 ++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h
+index 5ec1625bf8..66e2b98774 100644
+--- a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h
++++ b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_cpp_symbols.h
+@@ -31,6 +31,9 @@
+ #define SHIM_CPP_SYMBOLS_EXPORT PA_NOINLINE
+ #endif
+ 
++// Disable custom memory allocator when asan is used.
++// https://crbug.com/807685
++#if !defined(DISABLE_ALLOCATOR_SANITIZER)
+ SHIM_CPP_SYMBOLS_EXPORT void* operator new(size_t size) {
+   return ShimCppNew(size);
+ }
+@@ -130,5 +133,6 @@ SHIM_CPP_SYMBOLS_EXPORT void operator delete[](void* p,
+                                                const std::nothrow_t&) __THROW {
+   ShimCppDelete(p);
+ }
++#endif
+ 
+ #endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_CPP_SYMBOLS_H_
+diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_libc_symbols.h b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_libc_symbols.h
+index 624a44610e..05030a8b1c 100644
+--- a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_libc_symbols.h
++++ b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_override_libc_symbols.h
+@@ -22,6 +22,9 @@
+ 
+ #include "base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_internals.h"
+ 
++// Disable custom memory allocator when asan is used.
++// https://crbug.com/807685
++#if !defined(DISABLE_ALLOCATOR_SANITIZER)
+ extern "C" {
+ 
+ // WARNING: Whenever a new function is added there (which, surprisingly enough,
+@@ -88,5 +91,6 @@ SHIM_ALWAYS_EXPORT size_t malloc_usable_size(void* address) __THROW {
+ //   struct mallinfo mallinfo(void);
+ 
+ }  // extern "C"
++#endif
+ 
+ #endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_LIBC_SYMBOLS_H_
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/long-term-0300-add-mock-object-manager.patch b/libchrome_tools/patches/long-term-0300-add-mock-object-manager.patch
new file mode 100644
index 0000000..c0143ac
--- /dev/null
+++ b/libchrome_tools/patches/long-term-0300-add-mock-object-manager.patch
@@ -0,0 +1,165 @@
+From cbdfe377c9b04ec298010c628a0a35266824012b Mon Sep 17 00:00:00 2001
+From: hscham <hscham@chromium.org>
+Date: Tue, 2 Nov 2021 14:04:39 +0900
+Subject: [PATCH] Add mock object manager
+
+Refer to crbug/1093642 on upstream or abandon these two patches.
+Add MockObjectManager, which is removed upstream.
+
+Change-Id: I9d40b2af0c2e03d9acbc4544fb4585aa3fee0777
+patch-name: long-term-0300-add-mock-object-manager.patch
+---
+ dbus/mock_object_manager.cc | 17 +++++++++++++++
+ dbus/mock_object_manager.h  | 41 +++++++++++++++++++++++++++++++++++++
+ dbus/object_manager.h       | 21 ++++++++++---------
+ 3 files changed, 69 insertions(+), 10 deletions(-)
+ create mode 100644 dbus/mock_object_manager.cc
+ create mode 100644 dbus/mock_object_manager.h
+
+diff --git a/dbus/mock_object_manager.cc b/dbus/mock_object_manager.cc
+new file mode 100644
+index 0000000000..9b5cb8fe04
+--- /dev/null
++++ b/dbus/mock_object_manager.cc
+@@ -0,0 +1,17 @@
++// Copyright 2013 The Chromium Authors
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#include "dbus/mock_object_manager.h"
++
++namespace dbus {
++
++MockObjectManager::MockObjectManager(Bus* bus,
++                                     const std::string& service_name,
++                                     const ObjectPath& object_path)
++    : ObjectManager(bus, service_name, object_path) {
++}
++
++MockObjectManager::~MockObjectManager() = default;
++
++}  // namespace dbus
+diff --git a/dbus/mock_object_manager.h b/dbus/mock_object_manager.h
+new file mode 100644
+index 0000000000..57212171d2
+--- /dev/null
++++ b/dbus/mock_object_manager.h
+@@ -0,0 +1,41 @@
++// Copyright 2013 The Chromium Authors
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++#ifndef DBUS_MOCK_OBJECT_MANAGER_H_
++#define DBUS_MOCK_OBJECT_MANAGER_H_
++
++#include <string>
++
++#include "dbus/message.h"
++#include "dbus/object_manager.h"
++#include "dbus/object_path.h"
++#include "dbus/object_proxy.h"
++#include "testing/gmock/include/gmock/gmock.h"
++
++namespace dbus {
++
++// Mock for ObjectManager.
++class MockObjectManager : public ObjectManager {
++ public:
++  MockObjectManager(Bus* bus,
++                    const std::string& service_name,
++                    const ObjectPath& object_path);
++
++  MOCK_METHOD2(RegisterInterface, void(const std::string&,
++                                       Interface*));
++  MOCK_METHOD1(UnregisterInterface, void(const std::string&));
++  MOCK_METHOD0(GetObjects, std::vector<ObjectPath>());
++  MOCK_METHOD1(GetObjectsWithInterface,
++               std::vector<ObjectPath>(const std::string&));
++  MOCK_METHOD1(GetObjectProxy, ObjectProxy*(const ObjectPath&));
++  MOCK_METHOD2(GetProperties, PropertySet*(const ObjectPath&,
++                                           const std::string&));
++
++ protected:
++  ~MockObjectManager() override;
++};
++
++}  // namespace dbus
++
++#endif  // DBUS_MOCK_OBJECT_MANAGER_H_
+diff --git a/dbus/object_manager.h b/dbus/object_manager.h
+index 9840aa5f86..ba16a88040 100644
+--- a/dbus/object_manager.h
++++ b/dbus/object_manager.h
+@@ -136,7 +136,7 @@ class Signal;
+ // ObjectManager implements both the D-Bus client components of the D-Bus
+ // Object Manager interface, as internal methods, and a public API for
+ // client classes to utilize.
+-class CHROME_DBUS_EXPORT ObjectManager final
++class CHROME_DBUS_EXPORT ObjectManager
+     : public base::RefCountedThreadSafe<ObjectManager> {
+  public:
+   // ObjectManager::Interface must be implemented by any class wishing to have
+@@ -195,38 +195,38 @@ class CHROME_DBUS_EXPORT ObjectManager final
+   // interface named in |interface_name|. That object's CreateProperties()
+   // method will be used to create instances of dbus::PropertySet* when
+   // required.
+-  void RegisterInterface(const std::string& interface_name,
+-                         Interface* interface);
++  virtual void RegisterInterface(const std::string& interface_name,
++                                 Interface* interface);
+ 
+   // Unregister the implementation class for the D-Bus interface named in
+   // |interface_name|, objects and properties of this interface will be
+   // ignored.
+-  void UnregisterInterface(const std::string& interface_name);
++  virtual void UnregisterInterface(const std::string& interface_name);
+ 
+   // Checks whether an interface is registered.
+   bool IsInterfaceRegisteredForTesting(const std::string& interface_name) const;
+ 
+   // Returns a list of object paths, in an undefined order, of objects known
+   // to this manager.
+-  std::vector<ObjectPath> GetObjects();
++  virtual std::vector<ObjectPath> GetObjects();
+ 
+   // Returns the list of object paths, in an undefined order, of objects
+   // implementing the interface named in |interface_name| known to this manager.
+-  std::vector<ObjectPath> GetObjectsWithInterface(
++  virtual std::vector<ObjectPath> GetObjectsWithInterface(
+       const std::string& interface_name);
+ 
+   // Returns a ObjectProxy pointer for the given |object_path|. Unlike
+   // the equivalent method on Bus this will return NULL if the object
+   // manager has not been informed of that object's existence.
+-  ObjectProxy* GetObjectProxy(const ObjectPath& object_path);
++  virtual ObjectProxy* GetObjectProxy(const ObjectPath& object_path);
+ 
+   // Returns a PropertySet* pointer for the given |object_path| and
+   // |interface_name|, or NULL if the object manager has not been informed of
+   // that object's existence or the interface's properties. The caller should
+   // cast the returned pointer to the appropriate type, e.g.:
+   //   static_cast<Properties*>(GetProperties(object_path, my_interface));
+-  PropertySet* GetProperties(const ObjectPath& object_path,
+-                             const std::string& interface_name);
++  virtual PropertySet* GetProperties(const ObjectPath& object_path,
++                                     const std::string& interface_name);
+ 
+   // Instructs the object manager to refresh its list of managed objects;
+   // automatically called by the D-Bus thread manager, there should never be
+@@ -241,11 +241,12 @@ class CHROME_DBUS_EXPORT ObjectManager final
+ 
+  private:
+   friend class base::RefCountedThreadSafe<ObjectManager>;
++  friend class MockObjectManager;
+ 
+   ObjectManager(Bus* bus,
+                 const std::string& service_name,
+                 const ObjectPath& object_path);
+-  ~ObjectManager();
++  virtual ~ObjectManager();
+ 
+   // Called from the constructor to add a match rule for PropertiesChanged
+   // signals on the D-Bus thread and set up a corresponding filter function.
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/long-term-0400-absl-thread-annotation-conflict.patch b/libchrome_tools/patches/long-term-0400-absl-thread-annotation-conflict.patch
new file mode 100644
index 0000000..6d3df95
--- /dev/null
+++ b/libchrome_tools/patches/long-term-0400-absl-thread-annotation-conflict.patch
@@ -0,0 +1,41 @@
+From a6ec4c929ed31bbb2efe383eff53021a09c8983b Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Thu, 27 Oct 2022 10:35:46 +0900
+Subject: [PATCH] Solve name conflict with abseil in absl package
+
+When a program in Chromium OS depends on both abseil and libchrome.
+
+Change-Id: I2dbd833347a59fffa8888c817a1fccdc78e5ff0e
+patch-name: long-term-0400-absl-thread-annotation-conflict.patch
+---
+ base/thread_annotations.h | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/base/thread_annotations.h b/base/thread_annotations.h
+index 4fadaeecb6..c6b5533884 100644
+--- a/base/thread_annotations.h
++++ b/base/thread_annotations.h
+@@ -225,8 +225,11 @@
+ // Disables warnings for a single read operation.  This can be used to avoid
+ // warnings when it is known that the read is not actually involved in a race,
+ // but the compiler cannot confirm that.
+-#define TS_UNCHECKED_READ(x) thread_safety_analysis::ts_unchecked_read(x)
++#ifndef TS_UNCHECKED_READ
++#define TS_UNCHECKED_READ(x) libchrome::thread_safety_analysis::ts_unchecked_read(x)
++#endif
+ 
++namespace libchrome {
+ namespace thread_safety_analysis {
+ 
+ // Takes a reference to a guarded data member, and returns an unguarded
+@@ -242,6 +245,7 @@ inline T& ts_unchecked_read(T& v) NO_THREAD_SAFETY_ANALYSIS {
+ }
+ 
+ }  // namespace thread_safety_analysis
++}  // namespace libchrome
+ 
+ // The above is imported as-is from abseil-cpp. The following Chromium-specific
+ // synonyms are added for Chromium concepts (SequenceChecker/ThreadChecker).
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/long-term-0600-select-nacl-md5-sha1-implementation.patch b/libchrome_tools/patches/long-term-0600-select-nacl-md5-sha1-implementation.patch
new file mode 100644
index 0000000..82846f0
--- /dev/null
+++ b/libchrome_tools/patches/long-term-0600-select-nacl-md5-sha1-implementation.patch
@@ -0,0 +1,45 @@
+From c053d30e41147735663e2c2082eccb6243340fcb Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Mon, 12 Dec 2022 15:54:19 +0900
+Subject: [PATCH] Select sha1_nacl.cc implementation.
+
+Select sha1_nacl.cc, md5_nacl.cc implementation.
+NACL doesn't have boringssl either, we can just select NACL implementation for
+MD5/SHA1 used in upstream Chromium.
+
+Change-Id: I82e14ea2a001fdb435da9aa813379191aec8d4f4
+patch-name: long-term-0600-select-nacl-md5-sha1-implementation.patch
+---
+ base/hash/md5.h  | 2 +-
+ base/hash/sha1.h | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/base/hash/md5.h b/base/hash/md5.h
+index aa889f350e..fab9794d42 100644
+--- a/base/hash/md5.h
++++ b/base/hash/md5.h
+@@ -11,7 +11,7 @@
+ #include "base/strings/string_piece.h"
+ #include "build/build_config.h"
+ 
+-#if BUILDFLAG(IS_NACL)
++#if BUILDFLAG(IS_NACL) || 1
+ #include "base/hash/md5_nacl.h"
+ #else
+ #include "base/hash/md5_boringssl.h"
+diff --git a/base/hash/sha1.h b/base/hash/sha1.h
+index 29626e5853..c357078fb8 100644
+--- a/base/hash/sha1.h
++++ b/base/hash/sha1.h
+@@ -14,7 +14,7 @@
+ #include "base/containers/span.h"
+ #include "base/strings/string_piece.h"
+ #include "build/build_config.h"
+-#if BUILDFLAG(IS_NACL)
++#if BUILDFLAG(IS_NACL) || 1
+ #include "base/hash/sha1_nacl.h"
+ #else
+ #include "base/hash/sha1_boringssl.h"
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/long-term-0700-Do-not-use-boringssl-in-base-UnguessableToken.patch b/libchrome_tools/patches/long-term-0700-Do-not-use-boringssl-in-base-UnguessableToken.patch
new file mode 100644
index 0000000..49a940a
--- /dev/null
+++ b/libchrome_tools/patches/long-term-0700-Do-not-use-boringssl-in-base-UnguessableToken.patch
@@ -0,0 +1,102 @@
+From eacb72284f699a9ee9833edd1a81eb58631e9bb6 Mon Sep 17 00:00:00 2001
+From: Jeff Lin <jeffulin@google.com>
+Date: Mon, 1 Jul 2024 15:37:35 +0800
+Subject: [PATCH] Do not use boringssl in base::UnguessableToken
+
+Introduced in r930012 (crrev.com/c/3343574).
+Updated in r1230523 (crrev.com/c/5075453).
+Updated in r1321254 (crrev.com/c/5669584).
+
+Change-Id: I4035f5c236b9b2ca8b3c4f6296a36786cfe85ae7
+---
+ base/unguessable_token.cc | 22 +++++++++++-----------
+ base/unguessable_token.h  | 17 ++++++++---------
+ 2 files changed, 19 insertions(+), 20 deletions(-)
+
+diff --git a/base/unguessable_token.cc b/base/unguessable_token.cc
+index ea33ca66f3..dfc6bc1b6f 100644
+--- a/base/unguessable_token.cc
++++ b/base/unguessable_token.cc
+@@ -12,9 +12,9 @@
+ #include "base/rand_util.h"
+ #include "build/build_config.h"
+ 
+-#if !BUILDFLAG(IS_NACL)
+-#include "third_party/boringssl/src/include/openssl/mem.h"
+-#endif
++// #if !BUILDFLAG(IS_NACL)
++// #include "third_party/boringssl/src/include/openssl/mem.h"
++// #endif
+ 
+ namespace base {
+ 
+@@ -57,15 +57,15 @@ std::optional<UnguessableToken> UnguessableToken::DeserializeFromString(
+   return UnguessableToken(token.value());
+ }
+ 
+-bool operator==(const UnguessableToken& lhs, const UnguessableToken& rhs) {
+-#if BUILDFLAG(IS_NACL)
++bool UnguessableToken::operator==(const UnguessableToken& other) const {
++// #if BUILDFLAG(IS_NACL)
+   // BoringSSL is unavailable for NaCl builds so it remains timing dependent.
+-  return lhs.token_ == rhs.token_;
+-#else
+-  auto bytes = lhs.token_.AsBytes();
+-  auto other_bytes = rhs.token_.AsBytes();
+-  return CRYPTO_memcmp(bytes.data(), other_bytes.data(), bytes.size()) == 0;
+-#endif
++  return token_ == other.token_;
++// #else
++//   auto bytes = lhs.token_.AsBytes();
++//   auto other_bytes = rhs.token_.AsBytes();
++//   return CRYPTO_memcmp(bytes.data(), other_bytes.data(), bytes.size()) == 0;
++// #endif
+ }
+ 
+ std::ostream& operator<<(std::ostream& out, const UnguessableToken& token) {
+diff --git a/base/unguessable_token.h b/base/unguessable_token.h
+index 2021d4b35e..49a97f9851 100644
+--- a/base/unguessable_token.h
++++ b/base/unguessable_token.h
+@@ -8,7 +8,6 @@
+ #include <stdint.h>
+ #include <string.h>
+ 
+-#include <compare>
+ #include <iosfwd>
+ #include <string_view>
+ #include <tuple>
+@@ -107,12 +106,15 @@ class BASE_EXPORT UnguessableToken {
+ 
+   span<const uint8_t, 16> AsBytes() const { return token_.AsBytes(); }
+ 
+-  friend constexpr auto operator<=>(const UnguessableToken& lhs,
+-                                    const UnguessableToken& rhs) = default;
++  constexpr bool operator<(const UnguessableToken& other) const {
++     return token_ < other.token_;
++   }
+ 
+-  // operator== uses constant-time comparison for security where available.
+-  friend BASE_EXPORT bool operator==(const UnguessableToken& lhs,
+-                                     const UnguessableToken& rhs);
++  bool operator==(const UnguessableToken& other) const;
++
++  bool operator!=(const UnguessableToken& other) const {
++    return !(*this == other);
++  }
+ 
+ #if defined(UNIT_TEST)
+   static UnguessableToken CreateForTesting(uint64_t high, uint64_t low) {
+@@ -129,9 +131,6 @@ class BASE_EXPORT UnguessableToken {
+   base::Token token_;
+ };
+ 
+-BASE_EXPORT bool operator==(const UnguessableToken& lhs,
+-                            const UnguessableToken& rhs);
+-
+ BASE_EXPORT std::ostream& operator<<(std::ostream& out,
+                                      const UnguessableToken& token);
+ 
+-- 
+2.45.2.803.g4e1b14247a-goog
+
diff --git a/libchrome_tools/patches/long-term-0800-disable-boringssl-in-base-RandBytes.patch b/libchrome_tools/patches/long-term-0800-disable-boringssl-in-base-RandBytes.patch
new file mode 100644
index 0000000..eb874ed
--- /dev/null
+++ b/libchrome_tools/patches/long-term-0800-disable-boringssl-in-base-RandBytes.patch
@@ -0,0 +1,77 @@
+From 64194dc354c3d89aefc5038d375aa39aae0779c0 Mon Sep 17 00:00:00 2001
+From: Jeff Lin <jeffulin@google.com>
+Date: Mon, 1 Jul 2024 15:59:21 +0800
+Subject: [PATCH] disable boringssl in base::RandBytes
+
+Introduced in r1045239 (crrev.com/c/3880863).
+Updated in r1321254 (crrev.com/c/5669584).
+
+Change-Id: I2cdc2fe34a83b8debad12c0143e881a7a52c5bf5
+---
+ base/feature_list.cc    | 2 +-
+ base/rand_util.h        | 2 +-
+ base/rand_util_posix.cc | 6 +++---
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/base/feature_list.cc b/base/feature_list.cc
+index 895b710fdf..80b80df74c 100644
+--- a/base/feature_list.cc
++++ b/base/feature_list.cc
+@@ -614,7 +614,7 @@ void FeatureList::SetInstance(std::unique_ptr<FeatureList> instance) {
+   // FeatureList instance, as the state of the involved Features might change
+   // with the final FeatureList for this process.
+   if (!g_feature_list_instance->IsEarlyAccessInstance()) {
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+     // Configured first because it takes precedence over the getrandom() trial.
+     internal::ConfigureBoringSSLBackedRandBytesFieldTrial();
+ #endif
+diff --git a/base/rand_util.h b/base/rand_util.h
+index 746166bf75..5c9c3b1ad0 100644
+--- a/base/rand_util.h
++++ b/base/rand_util.h
+@@ -38,7 +38,7 @@ namespace internal {
+ void ConfigureRandBytesFieldTrial();
+ #endif
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+ void ConfigureBoringSSLBackedRandBytesFieldTrial();
+ #endif
+ 
+diff --git a/base/rand_util_posix.cc b/base/rand_util_posix.cc
+index 00fcb8547e..a388e9f2fc 100644
+--- a/base/rand_util_posix.cc
++++ b/base/rand_util_posix.cc
+@@ -36,7 +36,7 @@
+ #include <sys/random.h>
+ #endif
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+ #include "third_party/boringssl/src/include/openssl/rand.h"
+ #endif
+ 
+@@ -153,9 +153,9 @@ void ConfigureRandBytesFieldTrial() {
+ }
+ #endif
+ 
++#if !BUILDFLAG(IS_NACL) && 0
+ namespace {
+ 
+-#if !BUILDFLAG(IS_NACL)
+ // The BoringSSl helpers are duplicated in rand_util_fuchsia.cc and
+ // rand_util_win.cc.
+ std::atomic<bool> g_use_boringssl;
+@@ -181,7 +181,7 @@ bool UseBoringSSLForRandBytes() {
+ namespace {
+ 
+ void RandBytesInternal(span<uint8_t> output, bool avoid_allocation) {
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+   // The BoringSSL experiment takes priority over everything else.
+   if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) {
+     // BoringSSL's RAND_bytes always returns 1. Any error aborts the program.
+-- 
+2.45.2.803.g4e1b14247a-goog
+
diff --git a/libchrome_tools/patches/long-term-0900-Call-getrandom-from-sys-random.h.patch b/libchrome_tools/patches/long-term-0900-Call-getrandom-from-sys-random.h.patch
new file mode 100644
index 0000000..d070090
--- /dev/null
+++ b/libchrome_tools/patches/long-term-0900-Call-getrandom-from-sys-random.h.patch
@@ -0,0 +1,33 @@
+From 299b149b7b47779f6f183605eb3ae14ba67cd709 Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Wed, 5 Oct 2022 15:43:01 +0900
+Subject: [PATCH] Call `getrandom` from sys/random.h
+
+TODO(b/190018559): third_party/lss/linux_syscall_support.h is not
+provided at current libchrome tree.
+
+Change-Id: Ifc96beb4987ff027ab32f885687e88dbd7c8dc34
+patch-name: long-term-0900-Call-getrandom-from-sys-random.h.patch
+---
+ base/rand_util_posix.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/base/rand_util_posix.cc b/base/rand_util_posix.cc
+index 37dd2d32ea..50f7aea8db 100644
+--- a/base/rand_util_posix.cc
++++ b/base/rand_util_posix.cc
+@@ -28,9 +28,9 @@
+ #include "base/time/time.h"
+ #include "build/build_config.h"
+ 
+-#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && !BUILDFLAG(IS_NACL)
++#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && !BUILDFLAG(IS_NACL) && 0
+ #include "third_party/lss/linux_syscall_support.h"
+-#elif BUILDFLAG(IS_MAC)
++#elif BUILDFLAG(IS_MAC) || 1
+ // TODO(crbug.com/40641285): Waiting for this header to appear in the iOS SDK.
+ // (See below.)
+ #include <sys/random.h>
+-- 
+2.45.0.rc0.197.gbae5840b3b-goog
+
diff --git a/libchrome_tools/patches/long-term-1000-Don-t-set-legacy-trace-event-macro.patch b/libchrome_tools/patches/long-term-1000-Don-t-set-legacy-trace-event-macro.patch
new file mode 100644
index 0000000..9608744
--- /dev/null
+++ b/libchrome_tools/patches/long-term-1000-Don-t-set-legacy-trace-event-macro.patch
@@ -0,0 +1,28 @@
+From cfca078f42e8546cb4e06745680e142d5cf6a718 Mon Sep 17 00:00:00 2001
+From: Sami Kyostila <skyostil@chromium.org>
+Date: Thu, 27 Jul 2023 09:49:14 +0000
+Subject: [PATCH] Don't set legacy trace event macro
+
+Change-Id: Iae43089b3456a335fb1d957f06b0762d1973d673
+patch-name: long-term-1000-Don-t-set-legacy-trace-event-macro.patch
+---
+ base/trace_event/common/trace_event_common.h | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/base/trace_event/common/trace_event_common.h b/base/trace_event/common/trace_event_common.h
+index c1bb2e2ef1..b98b35bbbd 100644
+--- a/base/trace_event/common/trace_event_common.h
++++ b/base/trace_event/common/trace_event_common.h
+@@ -208,9 +208,6 @@
+ #include "base/time/time.h"
+ #include "build/build_config.h"
+ 
+-// Enable legacy trace event macros (e.g., TRACE_EVENT{0,1,2}).
+-#define PERFETTO_ENABLE_LEGACY_TRACE_EVENTS 1
+-
+ // Macros for reading the current trace time (bypassing any virtual time
+ // overrides).
+ #define TRACE_TIME_TICKS_NOW() ::base::subtle::TimeTicksNowIgnoringOverride()
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/long-term-1050-Don-t-initialize-Perfetto-for-testing.patch b/libchrome_tools/patches/long-term-1050-Don-t-initialize-Perfetto-for-testing.patch
new file mode 100644
index 0000000..325ae39
--- /dev/null
+++ b/libchrome_tools/patches/long-term-1050-Don-t-initialize-Perfetto-for-testing.patch
@@ -0,0 +1,39 @@
+From 812237934487ce10c2c7eee36842138970842648 Mon Sep 17 00:00:00 2001
+From: Sami Kyostila <skyostil@chromium.org>
+Date: Mon, 14 Aug 2023 04:50:32 +0000
+Subject: [PATCH] base/trace_event: Don't initialize Perfetto for testing
+
+Disable the code for initializing Perfetto for testing. This saves
+300+ KiB of binary size by removing the dependency on Perfetto's
+in-process tracing service which isn't needed by production code.
+
+Change-Id: I99c002b6ee50fe237c2aa7dd4943949a4faad793
+patch-name: long-term-1050-Don-t-initialize-Perfetto-for-testing.patch
+---
+ base/trace_event/trace_log.cc | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
+index dd3b5dbe5e..eb1307e4d0 100644
+--- a/base/trace_event/trace_log.cc
++++ b/base/trace_event/trace_log.cc
+@@ -953,6 +953,8 @@ perfetto::DataSourceConfig TraceLog::GetCurrentTrackEventDataSourceConfig()
+ }
+ 
+ void TraceLog::InitializePerfettoIfNeeded() {
++  // Disable the code to initialize Perfetto for testing to save binary size.
++#if 0
+   // When we're using the Perfetto client library, only tests should be
+   // recording traces directly through TraceLog. Production code should instead
+   // use perfetto::Tracing::NewTrace(). Let's make sure the tracing service
+@@ -977,6 +979,7 @@ void TraceLog::InitializePerfettoIfNeeded() {
+   init_args.disallow_merging_with_system_tracks = true;
+   perfetto::Tracing::Initialize(init_args);
+   TrackEvent::Register();
++#endif
+ }
+ 
+ bool TraceLog::IsPerfettoInitializedByTraceLog() const {
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/long-term-1100-Revert-base-allocator-Support-max-alloc-size-with-us.patch b/libchrome_tools/patches/long-term-1100-Revert-base-allocator-Support-max-alloc-size-with-us.patch
new file mode 100644
index 0000000..096d642
--- /dev/null
+++ b/libchrome_tools/patches/long-term-1100-Revert-base-allocator-Support-max-alloc-size-with-us.patch
@@ -0,0 +1,111 @@
+From c67effc769a21fd01db70960d1d282f5e784663c Mon Sep 17 00:00:00 2001
+From: Nathan Muggli <nmuggli@google.com>
+Date: Mon, 8 Jul 2024 10:15:38 -0600
+Subject: [PATCH] Revert "[base/allocator] Support max alloc size with
+ use_allocator = "none"."
+
+Revert of r921558
+When malloc of more than (or close to) max size is called, it should
+return nullptr (and handled by caller) instead of crashing as the
+original patch will do.
+
+This reverts commit 324e03c9fba0fd78a721524032eeac43c80dd1db.
+This partially reverts commit e558947377db0b8e4f66687fd3c272ab6c34963e
+(The UncheckedRealloc pieces).
+
+patch-name: long-term-1100-Revert-base-allocator-Support-max-alloc-size-with-us.patch
+Change-Id: If83feeb40d469d4f91e5f13255b96d5a986a459a
+---
+ ...llocator_shim_default_dispatch_to_glibc.cc | 46 +------------------
+ 1 file changed, 2 insertions(+), 44 deletions(-)
+
+diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc
+index 699d98da76..bdcf15e6ca 100644
+--- a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc
++++ b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_glibc.cc
+@@ -2,8 +2,6 @@
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ 
+-#include <limits>
+-
+ #include "partition_alloc/oom.h"
+ #include "partition_alloc/partition_alloc_base/compiler_specific.h"
+ #include "partition_alloc/partition_alloc_base/numerics/checked_math.h"
+@@ -28,59 +26,19 @@ namespace {
+ 
+ using allocator_shim::AllocatorDispatch;
+ 
+-// Strictly speaking, it would make more sense to not subtract amything, but
+-// other shims limit to something lower than INT_MAX (which is 0x7FFFFFFF on
+-// most platforms), and tests expect that.
+-constexpr size_t kMaxAllowedSize = std::numeric_limits<int>::max() - (1 << 12);
+-
+ void* GlibcMalloc(size_t size, void* context) {
+-  // Cannot force glibc's malloc() to crash when a large size is requested, do
+-  // it in the shim instead.
+-  if (size >= kMaxAllowedSize) [[unlikely]] {
+-    partition_alloc::TerminateBecauseOutOfMemory(size);
+-  }
+-
+-  return __libc_malloc(size);
+-}
+-
+-void* GlibcUncheckedMalloc(size_t size, void* context) {
+-  if (size >= kMaxAllowedSize) [[unlikely]] {
+-    return nullptr;
+-  }
+-
+   return __libc_malloc(size);
+ }
+ 
+ void* GlibcCalloc(size_t n, size_t size, void* context) {
+-  const auto total = partition_alloc::internal::base::CheckMul(n, size);
+-  if (!total.IsValid() || total.ValueOrDie() >= kMaxAllowedSize) [[unlikely]] {
+-    partition_alloc::TerminateBecauseOutOfMemory(size * n);
+-  }
+-
+   return __libc_calloc(n, size);
+ }
+ 
+ void* GlibcRealloc(void* address, size_t size, void* context) {
+-  if (size >= kMaxAllowedSize) [[unlikely]] {
+-    partition_alloc::TerminateBecauseOutOfMemory(size);
+-  }
+-
+-  return __libc_realloc(address, size);
+-}
+-
+-void* GlibcUncheckedRealloc(void* address, size_t size, void* context) {
+-  if (size >= kMaxAllowedSize) [[unlikely]] {
+-    return nullptr;
+-  }
+-
+   return __libc_realloc(address, size);
+ }
+ 
+ void* GlibcMemalign(size_t alignment, size_t size, void* context) {
+-  if (size >= kMaxAllowedSize) [[unlikely]] {
+-    partition_alloc::TerminateBecauseOutOfMemory(size);
+-  }
+-
+   return __libc_memalign(alignment, size);
+ }
+ 
+@@ -106,11 +64,11 @@ size_t GlibcGetSizeEstimate(void* address, void* context) {
+ 
+ const AllocatorDispatch AllocatorDispatch::default_dispatch = {
+     &GlibcMalloc,           /* alloc_function */
+-    &GlibcUncheckedMalloc,  /* alloc_unchecked_function */
++    &GlibcMalloc,           /* alloc_unchecked_function */
+     &GlibcCalloc,           /* alloc_zero_initialized_function */
+     &GlibcMemalign,         /* alloc_aligned_function */
+     &GlibcRealloc,          /* realloc_function */
+-    &GlibcUncheckedRealloc, /* realloc_unchecked_function */
++    &GlibcRealloc,          /* realloc_unchecked_function */
+     &GlibcFree,             /* free_function */
+     &GlibcGetSizeEstimate,  /* get_size_estimate_function */
+     nullptr,                /* good_size_function */
+-- 
+2.46.0.76.ge559c4bf1a-goog
+
diff --git a/libchrome_tools/patches/long-term-1300-Always-include-base-thread-platform_thread_ref.h.patch b/libchrome_tools/patches/long-term-1300-Always-include-base-thread-platform_thread_ref.h.patch
new file mode 100644
index 0000000..06b4cc5
--- /dev/null
+++ b/libchrome_tools/patches/long-term-1300-Always-include-base-thread-platform_thread_ref.h.patch
@@ -0,0 +1,31 @@
+From f1f63f778e489973c2df519211c7c38abd295acf Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Thu, 27 Oct 2022 11:04:47 +0900
+Subject: [PATCH] Always include base/thread/platform_thread_ref.h
+
+Libchrome prefer to have consistent include headers across debug or
+non-debug, since release builders have a lot delay. That may cuase our
+client program unable to discover compilation failure at CQ/postsubmit.
+
+Change-Id: Iaca5e691c1fae13cac3b08b361820a3348a646f9
+patch-name: long-term-1300-Always-include-base-thread-platform_thread_ref.h.patch
+---
+ base/synchronization/lock.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/base/synchronization/lock.h b/base/synchronization/lock.h
+index 4b8381ce9a..717b06cc73 100644
+--- a/base/synchronization/lock.h
++++ b/base/synchronization/lock.h
+@@ -14,7 +14,7 @@
+ #include "base/thread_annotations.h"
+ #include "build/build_config.h"
+ 
+-#if DCHECK_IS_ON()
++#if DCHECK_IS_ON() | 1
+ #include <memory>
+ 
+ #include "base/compiler_specific.h"
+-- 
+2.47.0.338.g60cca15819-goog
+
diff --git a/libchrome_tools/patches/long-term-1500-Revert-Make-base-VerifyPathControlledByUser-Mac-only.patch b/libchrome_tools/patches/long-term-1500-Revert-Make-base-VerifyPathControlledByUser-Mac-only.patch
new file mode 100644
index 0000000..01ee512
--- /dev/null
+++ b/libchrome_tools/patches/long-term-1500-Revert-Make-base-VerifyPathControlledByUser-Mac-only.patch
@@ -0,0 +1,126 @@
+From 18a22868fa02255a49dec4df0fce0136aea25bbd Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Wed, 11 May 2022 13:44:41 +0900
+Subject: [PATCH] Revert "Make base::VerifyPathControlledByUser() Mac-only."
+
+Revert of r980844 (crrev.com/c/3508824) since
+base::VerifyPathControlledByUser is used in CrOS.
+
+This reverts commit 9b16796d1ebbb68f7dc1f8adf2128fc4b00f4a61.
+
+patch-name: long-term-1500-Revert-Make-base-VerifyPathControlledByUser-Mac-only.patch
+Change-Id: I3b4595ad4891dc1a67bfdcf03f934971ff93f4df
+---
+ base/files/file_util.h           |  4 ++--
+ base/files/file_util_posix.cc    |  4 +---
+ base/files/file_util_unittest.cc | 12 ++++++------
+ 3 files changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/base/files/file_util.h b/base/files/file_util.h
+index 1d3fe9d1d7..020a9e316e 100644
+--- a/base/files/file_util.h
++++ b/base/files/file_util.h
+@@ -651,9 +651,7 @@ BASE_EXPORT bool SetCloseOnExec(int fd);
+ // Returns true if it was able to remove the close-on-exec flag, otherwise
+ // false.
+ BASE_EXPORT bool RemoveCloseOnExec(int fd);
+-#endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
+ 
+-#if BUILDFLAG(IS_MAC)
+ // Test that |path| can only be changed by a given user and members of
+ // a given set of groups.
+ // Specifically, test that all parts of |path| under (and including) |base|:
+@@ -669,7 +667,9 @@ BASE_EXPORT bool VerifyPathControlledByUser(const base::FilePath& base,
+                                             const base::FilePath& path,
+                                             uid_t owner_uid,
+                                             const std::set<gid_t>& group_gids);
++#endif  // BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
+ 
++#if BUILDFLAG(IS_MAC)
+ // Is |path| writable only by a user with administrator privileges?
+ // This function uses Mac OS conventions.  The super user is assumed to have
+ // uid 0, and the administrator group is assumed to be named "admin".
+diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
+index acb98a7e3e..705202e1ea 100644
+--- a/base/files/file_util_posix.cc
++++ b/base/files/file_util_posix.cc
+@@ -77,7 +77,6 @@ namespace base {
+ 
+ namespace {
+ 
+-#if BUILDFLAG(IS_MAC)
+ // Helper for VerifyPathControlledByUser.
+ bool VerifySpecificPathControlledByUser(const FilePath& path,
+                                         uid_t owner_uid,
+@@ -113,7 +112,6 @@ bool VerifySpecificPathControlledByUser(const FilePath& path,
+ 
+   return true;
+ }
+-#endif
+ 
+ base::FilePath GetTempTemplate() {
+   return FormatTemporaryFileName("XXXXXX");
+@@ -1103,7 +1101,6 @@ bool SetCurrentDirectory(const FilePath& path) {
+   return chdir(path.value().c_str()) == 0;
+ }
+ 
+-#if BUILDFLAG(IS_MAC)
+ bool VerifyPathControlledByUser(const FilePath& base,
+                                 const FilePath& path,
+                                 uid_t owner_uid,
+@@ -1139,6 +1136,7 @@ bool VerifyPathControlledByUser(const FilePath& base,
+   return true;
+ }
+ 
++#if BUILDFLAG(IS_MAC)
+ bool VerifyPathControlledByAdmin(const FilePath& path) {
+   const unsigned kRootUid = 0;
+   const FilePath kFileSystemRoot("/");
+diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc
+index ea3c7672aa..7a7d7a7e76 100644
+--- a/base/files/file_util_unittest.cc
++++ b/base/files/file_util_unittest.cc
+@@ -217,7 +217,9 @@ class ReparsePoint {
+ 
+ #endif
+ 
+-#if BUILDFLAG(IS_MAC)
++// Fuchsia doesn't support file permissions.
++#if !BUILDFLAG(IS_FUCHSIA)
++#if BUILDFLAG(IS_POSIX)
+ // Provide a simple way to change the permissions bits on |path| in tests.
+ // ASSERT failures will return, but not stop the test.  Caller should wrap
+ // calls to this function in ASSERT_NO_FATAL_FAILURE().
+@@ -233,10 +235,8 @@ void ChangePosixFilePermissions(const FilePath& path,
+   mode &= ~mode_bits_to_clear;
+   ASSERT_TRUE(SetPosixFilePermissions(path, mode));
+ }
+-#endif  // BUILDFLAG(IS_MAC)
++#endif  // BUILDFLAG(IS_POSIX)
+ 
+-// Fuchsia doesn't support file permissions.
+-#if !BUILDFLAG(IS_FUCHSIA)
+ // Sets the source file to read-only.
+ void SetReadOnly(const FilePath& path, bool read_only) {
+ #if BUILDFLAG(IS_WIN)
+@@ -4115,7 +4115,7 @@ TEST_F(FileUtilTest, SetCloseOnExec) {
+ 
+ #endif
+ 
+-#if BUILDFLAG(IS_MAC)
++#if BUILDFLAG(IS_POSIX)
+ 
+ // Testing VerifyPathControlledByAdmin() is hard, because there is no
+ // way a test can make a file owned by root, or change file paths
+@@ -4399,7 +4399,7 @@ TEST_F(VerifyPathControlledByUserTest, WriteBitChecks) {
+   EXPECT_TRUE(VerifyPathControlledByUser(sub_dir_, text_file_, uid_, ok_gids_));
+ }
+ 
+-#endif  // BUILDFLAG(IS_MAC)
++#endif  // BUILDFLAG(IS_POSIX)
+ 
+ // Flaky test: crbug/1054637
+ #if BUILDFLAG(IS_ANDROID)
+-- 
+2.43.0.rc0.421.g78406f8d94-goog
+
diff --git a/libchrome_tools/patches/long-term-1600-libchrome-Query-spaced-for-free-total-disk-space.patch b/libchrome_tools/patches/long-term-1600-libchrome-Query-spaced-for-free-total-disk-space.patch
new file mode 100644
index 0000000..c45588e
--- /dev/null
+++ b/libchrome_tools/patches/long-term-1600-libchrome-Query-spaced-for-free-total-disk-space.patch
@@ -0,0 +1,287 @@
+From d3f1580dd202ac17ea7ba4197d8f5fdc398d0f24 Mon Sep 17 00:00:00 2001
+From: Sarthak Kukreti <sarthakkukreti@google.com>
+Date: Mon, 22 Nov 2021 08:55:31 +0000
+Subject: [PATCH] Reland "Query spaced for free/total disk space"
+
+TODO(b/229799189): Remove once performance problems with spaced in
+chrome are fixed.
+
+This is a reland of 5082d819e3110642e0aa0ccf8dfa730820db855a
+
+This reland CL contains no changes because the issues listed
+below have been resolved.
+
+The change was reverted due to two reasons:
+1. b/206260036 resulted in the change getting tested with older
+release images. This has since been fixed.
+2. crbug.com/1270613: A larger query time added performance regressions
+in copy/move semantics, which has now been mitigated via
+https://crrev.com/c/3289568
+
+Original change's description:
+> Query spaced for free/total disk space
+>
+> On ChromeOS, spaced is the central source-of-truth for free
+> disk space information. Spaced accounts for the available
+> extents on the underlying thinpool on thinly provisioned filesystems
+> so that clients can accurately know the true amount of disk space
+> available on the device.
+>
+> BUG=b:177966496
+> TEST=test Storage Management page on ChromeOS reflects the correct
+> values.
+> TEST=unittests
+>
+> Change-Id: Iabe6f7a704813d90deb3cfd6886b25f541c49ceb
+> Reviewed-on:
+> https://chromium-review.googlesource.com/c/chromium/src/+/3171506
+> Commit-Queue: Sarthak Kukreti <sarthakkukreti@chromium.org>
+> Reviewed-by: Lei Zhang <thestig@chromium.org>
+> Cr-Commit-Position: refs/heads/main@{#939202}
+
+Conflicts: extra headers on ToT.
+
+Bug: b:177966496
+Change-Id: Ida266fffe48a4cb0bcacbe08e499c1f39d19d55b
+Reviewed-on:
+https: //chromium-review.googlesource.com/c/chromium/src/+/3293987
+Commit-Queue: Sarthak Kukreti <sarthakkukreti@chromium.org>
+Reviewed-by: Lei Zhang <thestig@chromium.org>
+Cr-Commit-Position: refs/heads/main@{#943984}
+patch-name: long-term-1600-libchrome-Query-spaced-for-free-total-disk-space.patch
+---
+ base/system/sys_info.h           | 24 ++++++++++++++++
+ base/system/sys_info_chromeos.cc | 44 +++++++++++++++++++++++++++++
+ base/system/sys_info_posix.cc    | 11 ++++++++
+ base/system/sys_info_unittest.cc | 48 ++++++++++++++++++++++++++++++++
+ 4 files changed, 127 insertions(+)
+
+diff --git a/base/system/sys_info.h b/base/system/sys_info.h
+index b5ae4fdfe7..ea37906077 100644
+--- a/base/system/sys_info.h
++++ b/base/system/sys_info.h
+@@ -47,6 +47,7 @@ namespace test {
+ class ScopedAmountOfPhysicalMemoryOverride;
+ }
+ 
++class CommandLine;
+ class FilePath;
+ struct SystemMemoryInfoKB;
+ 
+@@ -105,6 +106,21 @@ class BASE_EXPORT SysInfo {
+   // on failure.
+   static int64_t AmountOfTotalDiskSpace(const FilePath& path);
+ 
++#if BUILDFLAG(IS_CHROMEOS)
++  // On ChromeOS, spaced is the central source-of-truth for disk space
++  // information. Spaced takes into account the available extents on the
++  // underlying thinpool to make sure that thinly provisioned filesystems
++  // return only the available physical extents as the free space.
++  //
++  // Return the available disk space in bytes on the volume containing |path|,
++  // or -1 on failure.
++  static int64_t GetFreeDiskSpaceFromSpaced(const FilePath& path);
++
++  // Return the total disk space in bytes on the volume containing |path|, or -1
++  // on failure.
++  static int64_t GetTotalDiskSpaceFromSpaced(const FilePath& path);
++#endif
++
+ #if BUILDFLAG(IS_FUCHSIA)
+   // Sets the total amount of disk space to report under the specified |path|.
+   // If |bytes| is -ve then any existing entry for |path| is removed.
+@@ -252,6 +268,14 @@ class BASE_EXPORT SysInfo {
+   // Undoes the function above.
+   static void ResetChromeOSVersionInfoForTest();
+ 
++  // Overrides the command runner for running commands. Overrides cannot be
++  // nested. Users must call SetChromeOSGetAppOutputForTest(nullptr) to revert
++  // the test function.
++  using GetAppOutputCallback =
++      RepeatingCallback<bool(const CommandLine&, std::string*)>;
++
++  static void SetChromeOSGetAppOutputForTest(GetAppOutputCallback* callback);
++
+   // Returns the kernel version of the host operating system.
+   static std::string KernelVersion();
+ 
+diff --git a/base/system/sys_info_chromeos.cc b/base/system/sys_info_chromeos.cc
+index 0eff17c938..8ba8c48dd3 100644
+--- a/base/system/sys_info_chromeos.cc
++++ b/base/system/sys_info_chromeos.cc
+@@ -14,12 +14,15 @@
+ #include <sys/utsname.h>
+ 
+ #include "base/compiler_specific.h"
++#include "base/functional/callback.h"
++#include "base/command_line.h"
+ #include "base/environment.h"
+ #include "base/files/file.h"
+ #include "base/files/file_path.h"
+ #include "base/files/file_util.h"
+ #include "base/no_destructor.h"
+ #include "base/notreached.h"
++#include "base/process/launch.h"
+ #include "base/strings/string_number_conversions.h"
+ #include "base/strings/string_split.h"
+ #include "base/strings/string_tokenizer.h"
+@@ -53,6 +56,10 @@ const char kLsbReleaseSourceKey[] = "lsb-release";
+ const char kLsbReleaseSourceEnv[] = "env";
+ const char kLsbReleaseSourceFile[] = "file";
+ 
++const char kSpacedCliPath[] = "/usr/sbin/spaced_cli";
++const char kSpacedGetFreeDiskSpaceAction[] = "get_free_disk_space";
++const char kSpacedGetTotalDiskSpaceAction[] = "get_total_disk_space";
++
+ }  // namespace
+ 
+ class ChromeOSVersionInfo {
+@@ -185,6 +192,28 @@ ChromeOSVersionInfo& GetChromeOSVersionInfo() {
+   return *version_info;
+ }
+ 
++SysInfo::GetAppOutputCallback* g_chromeos_get_app_output_for_test = nullptr;
++
++int64_t GetInfoFromSpaced(std::string_view action, const base::FilePath& path) {
++  CommandLine command((base::FilePath(kSpacedCliPath)));
++  command.AppendSwitchPath(action, path);
++
++  std::string output;
++  bool ret;
++  if (g_chromeos_get_app_output_for_test) {
++    ret = g_chromeos_get_app_output_for_test->Run(command, &output);
++  } else {
++    ret = GetAppOutput(command, &output);
++  }
++
++  int64_t result;
++  if (!ret || !StringToInt64(output, &result) || result < 0) {
++    return -1;
++  }
++
++  return result;
++}
++
+ // static
+ std::string SysInfo::HardwareModelName() {
+   std::string board = GetLsbReleaseBoard();
+@@ -267,6 +296,11 @@ void SysInfo::ResetChromeOSVersionInfoForTest() {
+   g_chromeos_version_info_for_test = nullptr;
+ }
+ 
++// static
++void SysInfo::SetChromeOSGetAppOutputForTest(GetAppOutputCallback* callback) {
++  g_chromeos_get_app_output_for_test = callback;
++}
++
+ // static
+ void SysInfo::CrashIfChromeOSNonTestImage() {
+   if (!IsRunningOnChromeOS()) {
+@@ -285,6 +319,16 @@ void SysInfo::CrashIfChromeOSNonTestImage() {
+   CHECK_NE(track.find(kTestImageRelease), std::string::npos);
+ }
+ 
++// static
++int64_t SysInfo::GetFreeDiskSpaceFromSpaced(const base::FilePath& path) {
++  return GetInfoFromSpaced(kSpacedGetFreeDiskSpaceAction, path);
++}
++
++// static
++int64_t SysInfo::GetTotalDiskSpaceFromSpaced(const base::FilePath& path) {
++  return GetInfoFromSpaced(kSpacedGetTotalDiskSpaceAction, path);
++}
++
+ SysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() {
+   HardwareInfo info;
+   // Manufacturer of ChromeOS device is always Google so hardcode it.
+diff --git a/base/system/sys_info_posix.cc b/base/system/sys_info_posix.cc
+index 3abeea32e6..c77d6b2a48 100644
+--- a/base/system/sys_info_posix.cc
++++ b/base/system/sys_info_posix.cc
+@@ -186,6 +186,11 @@ uint64_t SysInfo::AmountOfVirtualMemory() {
+ int64_t SysInfo::AmountOfFreeDiskSpace(const FilePath& path) {
+   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                 base::BlockingType::MAY_BLOCK);
++#if BUILDFLAG(IS_CHROMEOS)
++  int64_t ret = GetFreeDiskSpaceFromSpaced(path);
++  if (ret != -1)
++    return ret;
++#endif
+ 
+   int64_t available;
+   if (!GetDiskSpaceInfo(path, &available, nullptr)) {
+@@ -199,6 +204,12 @@ int64_t SysInfo::AmountOfTotalDiskSpace(const FilePath& path) {
+   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                 base::BlockingType::MAY_BLOCK);
+ 
++#if BUILDFLAG(IS_CHROMEOS)
++  int64_t ret = GetTotalDiskSpaceFromSpaced(path);
++  if (ret != -1)
++    return ret;
++#endif
++
+   int64_t total;
+   if (!GetDiskSpaceInfo(path, nullptr, &total)) {
+     return -1;
+diff --git a/base/system/sys_info_unittest.cc b/base/system/sys_info_unittest.cc
+index 1983447cb9..bbaf780bb8 100644
+--- a/base/system/sys_info_unittest.cc
++++ b/base/system/sys_info_unittest.cc
+@@ -460,6 +460,54 @@ TEST_F(SysInfoTest, ScopedRunningOnChromeOS) {
+   EXPECT_EQ(was_running, SysInfo::IsRunningOnChromeOS());
+ }
+ 
++SysInfo::GetAppOutputCallback MockGetAppOutputTestCallback(
++    const std::string& mock_output,
++    bool mock_ret) {
++  return BindRepeating(
++      [](const std::string& expected_output, bool return_value,
++         const CommandLine& cl, std::string* out) -> bool {
++        *out = expected_output;
++        return return_value;
++      },
++      mock_output, mock_ret);
++}
++
++TEST_F(SysInfoTest, SpacedValidQuery) {
++  FilePath dummy_path("/a/b/c");
++  auto mock_get_app_output = MockGetAppOutputTestCallback("1234", true);
++  SysInfo::SetChromeOSGetAppOutputForTest(&mock_get_app_output);
++  EXPECT_EQ(SysInfo::GetTotalDiskSpaceFromSpaced(dummy_path), 1234);
++  EXPECT_EQ(SysInfo::GetFreeDiskSpaceFromSpaced(dummy_path), 1234);
++  SysInfo::SetChromeOSGetAppOutputForTest(nullptr);
++}
++
++TEST_F(SysInfoTest, SpacedInternalFailure) {
++  FilePath dummy_path("/a/b/c");
++  auto mock_get_app_output = MockGetAppOutputTestCallback("-1", true);
++  SysInfo::SetChromeOSGetAppOutputForTest(&mock_get_app_output);
++  EXPECT_EQ(SysInfo::GetTotalDiskSpaceFromSpaced(dummy_path), -1);
++  EXPECT_EQ(SysInfo::GetFreeDiskSpaceFromSpaced(dummy_path), -1);
++  SysInfo::SetChromeOSGetAppOutputForTest(nullptr);
++}
++
++TEST_F(SysInfoTest, SpacedFailedInvocation) {
++  FilePath dummy_path("/a/b/c");
++  auto mock_get_app_output = MockGetAppOutputTestCallback("5", false);
++  SysInfo::SetChromeOSGetAppOutputForTest(&mock_get_app_output);
++  EXPECT_EQ(SysInfo::GetTotalDiskSpaceFromSpaced(dummy_path), -1);
++  EXPECT_EQ(SysInfo::GetFreeDiskSpaceFromSpaced(dummy_path), -1);
++  SysInfo::SetChromeOSGetAppOutputForTest(nullptr);
++}
++
++TEST_F(SysInfoTest, SpacedInvalidOutput) {
++  FilePath dummy_path("/a/b/c");
++  auto mock_get_app_output = MockGetAppOutputTestCallback("foo", true);
++  SysInfo::SetChromeOSGetAppOutputForTest(&mock_get_app_output);
++  EXPECT_EQ(SysInfo::GetTotalDiskSpaceFromSpaced(dummy_path), -1);
++  EXPECT_EQ(SysInfo::GetFreeDiskSpaceFromSpaced(dummy_path), -1);
++  SysInfo::SetChromeOSGetAppOutputForTest(nullptr);
++}
++
+ #endif  // BUILDFLAG(IS_CHROMEOS)
+ 
+ }  // namespace base
+-- 
+2.47.1.613.gc27f4b7a9f-goog
+
diff --git a/libchrome_tools/patches/long-term-2000-disable-boringssl-used-in-base-NonAllocatingRandomBitGenerator.patch b/libchrome_tools/patches/long-term-2000-disable-boringssl-used-in-base-NonAllocatingRandomBitGenerator.patch
new file mode 100644
index 0000000..19008bf
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2000-disable-boringssl-used-in-base-NonAllocatingRandomBitGenerator.patch
@@ -0,0 +1,39 @@
+From ddf9c2dd1a1e9e5b8f0382839e281c1d1c0dd491 Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Tue, 1 Nov 2022 16:25:27 +0900
+Subject: [PATCH] disable boringssl used in
+ base::NonAllocatingRandomBitGenerator
+
+Introduced in crrev.com/1057955: libchrome does not support boringssl.
+
+Change-Id: I71b29173282129b5b61a93971ef5dd24ee6b60a9
+patch-name: long-term-2000-disable-boringssl-used-in-base-NonAllocatingRandomBitGenerator.patch
+---
+ base/rand_util.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/base/rand_util.h b/base/rand_util.h
+index 74cabc6d43..c25a73b80f 100644
+--- a/base/rand_util.h
++++ b/base/rand_util.h
+@@ -16,7 +16,7 @@
+ #include "base/gtest_prod_util.h"
+ #include "build/build_config.h"
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+ #include "third_party/boringssl/src/include/openssl/rand.h"
+ #endif
+ 
+@@ -97,7 +97,7 @@ class RandomBitGenerator {
+   ~RandomBitGenerator() = default;
+ };
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+ class NonAllocatingRandomBitGenerator {
+  public:
+   using result_type = uint64_t;
+-- 
+2.42.0.582.g8ccd20d70d-goog
+
diff --git a/libchrome_tools/patches/long-term-2100-rewrite-partition-alloc-include-paths.sh b/libchrome_tools/patches/long-term-2100-rewrite-partition-alloc-include-paths.sh
new file mode 100755
index 0000000..985e17b
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2100-rewrite-partition-alloc-include-paths.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+# Copyright 2023 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# crrev.com/c/5023994 changed include paths of partition allocator header files.
+# Rewrite them to their original forms.
+
+set -eu
+
+find -type f | xargs sed -i 's|^#include "partition_alloc/|#include "base/allocator/partition_allocator/src/partition_alloc/|g'
diff --git a/libchrome_tools/patches/long-term-2200-pre-genreated-check-version-internal-header.patch b/libchrome_tools/patches/long-term-2200-pre-genreated-check-version-internal-header.patch
new file mode 100644
index 0000000..5b1e22c
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2200-pre-genreated-check-version-internal-header.patch
@@ -0,0 +1,35 @@
+From 66877364a8d2c5fab8ee9c0f4b30e33ac3f7f071 Mon Sep 17 00:00:00 2001
+From: Jae Hoon Kim <kimjae@google.com>
+Date: Mon, 11 Dec 2023 23:25:28 +0000
+Subject: [PATCH] Pre-generated check version internal header
+
+.. chromium changes crrev/c/5031517 depend on chromium sources.
+
+Change-Id: I96c962598f24dd432ab10c9ea965dc981d685b1e
+---
+ base/check_version_internal.h | 13 +++++++++++++
+ 1 file changed, 13 insertions(+)
+ create mode 100644 base/check_version_internal.h
+
+diff --git a/base/check_version_internal.h b/base/check_version_internal.h
+new file mode 100644
+index 0000000000..12f7bef1de
+--- /dev/null
++++ b/base/check_version_internal.h
+@@ -0,0 +1,13 @@
++// Copyright 2023 The Chromium Authors
++// Use of this source code is governed by a BSD-style license that can be
++// found in the LICENSE file.
++
++// version.h is generated from version.h.in.  Edit the source!
++
++#ifndef BASE_CHECK_VERSION_INTERNAL_H_
++#define BASE_CHECK_VERSION_INTERNAL_H_
++
++#define BASE_CHECK_VERSION_INTERNAL 9998
++#define BASE_CHECK_NEXT_VERSION_INTERNAL 9999
++
++#endif  // BASE_CHECK_VERSION_INTERNAL_H_
+-- 
+2.43.0.472.g3155946c3a-goog
+
diff --git a/libchrome_tools/patches/long-term-2300-Fix-partition_alloc-buildflag-generation-logic.patch b/libchrome_tools/patches/long-term-2300-Fix-partition_alloc-buildflag-generation-logic.patch
new file mode 100644
index 0000000..b4e0738
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2300-Fix-partition_alloc-buildflag-generation-logic.patch
@@ -0,0 +1,56 @@
+From 89f800b70a1c32bbce206005217625588549582b Mon Sep 17 00:00:00 2001
+From: Cici Ruan <cuicuiruan@google.com>
+Date: Wed, 5 Jun 2024 15:47:08 -0700
+Subject: [PATCH] Fix partition_alloc buildflag generation logic for libchrome
+
+- Fix buildflag_header.gni to locate the script correctly, and to remove
+  the dependency on the build_config source set which doesn't exist in
+  libchrome.
+- Fix write_buildflag_header.py to fix the include paths in the
+  generated header files.
+
+Introduced in r1294816 (crrev.com/c/5504598).
+Updated in r1321254 (crrev.com/c/5669584).
+
+Change-Id: Id342a17dd2e912d4d681fc64bb7ea642d72d5de4
+---
+ .../src/partition_alloc/buildflag_header.gni                   | 3 +--
+ .../src/partition_alloc/write_buildflag_header.py              | 2 +-
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/base/allocator/partition_allocator/src/partition_alloc/buildflag_header.gni b/base/allocator/partition_allocator/src/partition_alloc/buildflag_header.gni
+index 979042758e..8b0b76f921 100644
+--- a/base/allocator/partition_allocator/src/partition_alloc/buildflag_header.gni
++++ b/base/allocator/partition_allocator/src/partition_alloc/buildflag_header.gni
+@@ -79,7 +79,7 @@ _current_dir = get_path_info(".", "abspath")
+ #   }
+ template("pa_buildflag_header") {
+   action(target_name) {
+-    script = "./write_buildflag_header.py"
++    script = "${_current_dir}/write_buildflag_header.py"
+ 
+     if (defined(invoker.header_dir)) {
+       header_file = "${invoker.header_dir}/${invoker.header}"
+@@ -116,6 +116,5 @@ template("pa_buildflag_header") {
+                              "visibility",
+                            ])
+ 
+-    public_deps = [ "${_current_dir}:buildflag_macro" ]
+   }
+ }
+diff --git a/base/allocator/partition_allocator/src/partition_alloc/write_buildflag_header.py b/base/allocator/partition_allocator/src/partition_alloc/write_buildflag_header.py
+index e2eaf33165..156ef7656a 100755
+--- a/base/allocator/partition_allocator/src/partition_alloc/write_buildflag_header.py
++++ b/base/allocator/partition_allocator/src/partition_alloc/write_buildflag_header.py
+@@ -86,7 +86,7 @@ def WriteHeader(options):
+ 
+     output_file.write('\n#ifndef %s\n' % options.header_guard)
+     output_file.write('#define %s\n\n' % options.header_guard)
+-    output_file.write('#include "partition_alloc/buildflag.h" // IWYU pragma: export\n\n')
++    output_file.write('#include "base/allocator/partition_allocator/src/partition_alloc/buildflag.h" // IWYU pragma: export\n\n')
+ 
+     for pair in options.flags:
+       output_file.write('#define PA_BUILDFLAG_INTERNAL_%s() (%s)\n' % pair)
+-- 
+2.45.2.803.g4e1b14247a-goog
+
diff --git a/libchrome_tools/patches/long-term-2400-select-non-libz-Crc32-implementation.patch b/libchrome_tools/patches/long-term-2400-select-non-libz-Crc32-implementation.patch
new file mode 100644
index 0000000..344eab5
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2400-select-non-libz-Crc32-implementation.patch
@@ -0,0 +1,36 @@
+From bee0e8e091b70f6235309bb2ec3ee5a93e7390f7 Mon Sep 17 00:00:00 2001
+From: Brett Brotherton <bbrotherton@google.com>
+Date: Fri, 19 Jul 2024 09:06:52 -0600
+Subject: [PATCH] [PATCH] select non libz Crc32 implementation
+
+use the older builtin Crc32 implementation rather than importing the
+zlib third party library for this single function
+
+Change-Id: I7fc55eb548130e28b78c54fcb030c15e61192553
+---
+ base/metrics/crc32.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/base/metrics/crc32.cc b/base/metrics/crc32.cc
+index 83e3cee257..1e24bd79e6 100644
+--- a/base/metrics/crc32.cc
++++ b/base/metrics/crc32.cc
+@@ -4,13 +4,13 @@
+ 
+ #include "base/metrics/crc32.h"
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+ #include "third_party/zlib/zlib.h"
+ #endif  // !BUILDFLAG(IS_NACL)
+ 
+ namespace base {
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+ uint32_t Crc32(uint32_t sum, span<const uint8_t> data) {
+   if (data.empty()) {
+     return sum;
+-- 
+2.45.2.1089.g2a221341d9-goog
+
diff --git a/libchrome_tools/patches/long-term-2500-Revert-MessagePumpEpoll-Add-debug-logs-for-a-test-fa.patch b/libchrome_tools/patches/long-term-2500-Revert-MessagePumpEpoll-Add-debug-logs-for-a-test-fa.patch
new file mode 100644
index 0000000..35e96a5
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2500-Revert-MessagePumpEpoll-Add-debug-logs-for-a-test-fa.patch
@@ -0,0 +1,125 @@
+From a93f31ab2ecbd87f93135638659b4e985c8e103d Mon Sep 17 00:00:00 2001
+From: Georg Neis <neis@chromium.org>
+Date: Tue, 3 Sep 2024 05:14:19 +0000
+Subject: [PATCH] Revert "MessagePumpEpoll: Add debug logs for a test failure
+ investigation"
+
+This reverts commit 1254da4cedc4f264a61938155da5e8b3a8cdb821.
+---
+ base/message_loop/message_pump_epoll.cc | 27 -------------------------
+ base/message_loop/message_pump_epoll.h  | 26 ------------------------
+ 2 files changed, 53 deletions(-)
+
+diff --git a/base/message_loop/message_pump_epoll.cc b/base/message_loop/message_pump_epoll.cc
+index 7b755471e3..e6db1ca0b1 100644
+--- a/base/message_loop/message_pump_epoll.cc
++++ b/base/message_loop/message_pump_epoll.cc
+@@ -24,10 +24,6 @@
+ #include "base/time/time.h"
+ #include "base/trace_event/base_tracing.h"
+ 
+-#if DCHECK_IS_ON()
+-#include <iomanip>
+-#endif
+-
+ namespace base {
+ 
+ namespace {
+@@ -317,23 +313,6 @@ void MessagePumpEpoll::AddEpollEvent(EpollEventEntry& entry) {
+   const uint32_t events = entry.ComputeActiveEvents();
+   epoll_event event{.events = events, .data = {.ptr = &entry}};
+   int rv = epoll_ctl(epoll_.get(), EPOLL_CTL_ADD, entry.fd, &event);
+-#if DCHECK_IS_ON()
+-  // TODO(361611793): Remove these debug logs after resolving the issue.
+-  if (rv != 0) {
+-    for (auto& history : entry.epoll_history_) {
+-      if (history.event) {
+-        auto& e = history.event.value();
+-        LOG(ERROR) << "events=0x" << std::hex << std::setfill('0')
+-                   << std::setw(8) << e.events;
+-        LOG(ERROR) << "data=0x" << std::hex << std::setfill('0')
+-                   << std::setw(16) << e.data.u64;
+-      }
+-      LOG(ERROR) << history.stack_trace;
+-    }
+-  } else {
+-    entry.PushEpollHistory(std::make_optional(event));
+-  }
+-#endif
+   DPCHECK(rv == 0);
+   entry.registered_events = events;
+ 
+@@ -375,9 +354,6 @@ void MessagePumpEpoll::UpdateEpollEvent(EpollEventEntry& entry) {
+     epoll_event event{.events = events, .data = {.ptr = &entry}};
+     int rv = epoll_ctl(epoll_.get(), EPOLL_CTL_MOD, entry.fd, &event);
+     DPCHECK(rv == 0);
+-#if DCHECK_IS_ON()
+-    entry.PushEpollHistory(std::make_optional(event));
+-#endif
+     entry.registered_events = events;
+ 
+     auto poll_entry = FindPollEntry(entry.fd);
+@@ -395,9 +371,6 @@ void MessagePumpEpoll::StopEpollEvent(EpollEventEntry& entry) {
+   if (!entry.stopped) {
+     int rv = epoll_ctl(epoll_.get(), EPOLL_CTL_DEL, entry.fd, nullptr);
+     DPCHECK(rv == 0);
+-#if DCHECK_IS_ON()
+-    entry.PushEpollHistory(std::nullopt);
+-#endif
+     entry.stopped = true;
+     entry.registered_events = 0;
+     RemovePollEntry(entry.fd);
+diff --git a/base/message_loop/message_pump_epoll.h b/base/message_loop/message_pump_epoll.h
+index 06735898b8..a1fbefaa9d 100644
+--- a/base/message_loop/message_pump_epoll.h
++++ b/base/message_loop/message_pump_epoll.h
+@@ -12,7 +12,6 @@
+ #include <map>
+ 
+ #include "base/base_export.h"
+-#include "base/dcheck_is_on.h"
+ #include "base/feature_list.h"
+ #include "base/files/scoped_file.h"
+ #include "base/memory/raw_ptr.h"
+@@ -25,13 +24,6 @@
+ #include "base/time/time.h"
+ #include "third_party/abseil-cpp/absl/container/inlined_vector.h"
+ 
+-#if DCHECK_IS_ON()
+-#include <deque>
+-#include <optional>
+-
+-#include "base/debug/stack_trace.h"
+-#endif
+-
+ namespace base {
+ 
+ // Use poll() rather than epoll().
+@@ -191,24 +183,6 @@ class BASE_EXPORT MessagePumpEpoll : public MessagePump,
+     // it from the epoll interest list to avoid unconditionally epoll_wait
+     // return, and prevent any future update on this `EpollEventEntry`.
+     bool stopped = false;
+-
+-#if DCHECK_IS_ON()
+-    struct EpollHistory {
+-      base::debug::StackTrace stack_trace;
+-      std::optional<epoll_event> event;
+-    };
+-    static constexpr ssize_t kEpollHistoryWindowSize = 5;
+-    std::deque<EpollHistory> epoll_history_;
+-
+-    void PushEpollHistory(std::optional<epoll_event> event) {
+-      EpollHistory info = {.stack_trace = base::debug::StackTrace(),
+-                           .event = event};
+-      epoll_history_.push_back(info);
+-      if (epoll_history_.size() > kEpollHistoryWindowSize) {
+-        epoll_history_.pop_front();
+-      }
+-    }
+-#endif
+   };
+ 
+   // State which lives on the stack within Run(), to support nested run loops.
+-- 
+2.46.0.469.g59c65b2a67-goog
+
diff --git a/libchrome_tools/patches/long-term-2600-Make-NOTREACHED_IN_MIGRATION-non-fatal.patch b/libchrome_tools/patches/long-term-2600-Make-NOTREACHED_IN_MIGRATION-non-fatal.patch
new file mode 100644
index 0000000..43f7ab2
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2600-Make-NOTREACHED_IN_MIGRATION-non-fatal.patch
@@ -0,0 +1,48 @@
+From 19e0c1c5713e9eb7116d591da24ceb2de0045dcf Mon Sep 17 00:00:00 2001
+From: Ryo Hashimoto <hashimoto@chromium.org>
+Date: Tue, 17 Sep 2024 16:25:53 +0900
+Subject: [PATCH] Make NOTREACHED_IN_MIGRATION non-fatal
+
+BUG=b:367556630
+TEST=CQ
+
+Change-Id: I3eebfc618a0b05bd0b20225a1c53e602ad443789
+---
+ base/check.cc | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+diff --git a/base/check.cc b/base/check.cc
+index bd63d5a88e..6a15acb852 100644
+--- a/base/check.cc
++++ b/base/check.cc
+@@ -30,13 +30,12 @@ namespace logging {
+ namespace {
+ 
+ LogSeverity GetDumpSeverity() {
+-#if defined(OFFICIAL_BUILD)
+-  return DCHECK_IS_ON() ? LOGGING_DCHECK : LOGGING_ERROR;
+-#else
+-  // Crash outside official builds (outside user-facing builds) to detect
+-  // invariant violations early in release-build testing like fuzzing, etc.
+-  // These should eventually be migrated to fatal CHECKs.
++#if BUILDFLAG(USE_FUZZING_ENGINE)
++  // Crash in fuzzing builds because non-fatal CHECKs will eventually be
++  // migrated to fatal CHECKs.
+   return LOGGING_FATAL;
++#else
++  return DCHECK_IS_ON() ? LOGGING_DCHECK : LOGGING_ERROR;
+ #endif
+ }
+ 
+@@ -347,7 +346,7 @@ CheckError::CheckError(LogMessage* log_message) : log_message_(log_message) {}
+ NotReachedError NotReachedError::NotReached(base::NotFatalUntil fatal_milestone,
+                                             const base::Location& location) {
+   auto* const log_message = new NotReachedLogMessage(
+-      location, GetCheckSeverity(fatal_milestone), fatal_milestone);
++      location, GetNotFatalUntilSeverity(fatal_milestone), fatal_milestone);
+ 
+   // TODO(pbos): Consider a better message for NotReached(), this is here to
+   // match existing behavior + test expectations.
+-- 
+2.46.0.662.g92d0881bb0-goog
+
diff --git a/libchrome_tools/patches/long-term-2700-Revert-Fix-32bit-ARM-Linux-build-for-Cast.patch b/libchrome_tools/patches/long-term-2700-Revert-Fix-32bit-ARM-Linux-build-for-Cast.patch
new file mode 100644
index 0000000..6b5f367
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2700-Revert-Fix-32bit-ARM-Linux-build-for-Cast.patch
@@ -0,0 +1,31 @@
+From 28406ec9430f436b19df68383a2d46fd998087b2 Mon Sep 17 00:00:00 2001
+From: Jeff Lin <jeffulin@google.com>
+Date: Fri, 27 Sep 2024 15:30:35 +0800
+Subject: [PATCH] Revert "Fix 32bit ARM Linux build for Cast."
+
+The fix is for CastOS only.
+
+This reverts commit afd8319889fd6e5873a43c07889490e356456732.
+
+Change-Id: If858cef9ec6c68751d7af2d1cdef076f817db71e
+---
+ base/time/time_exploded_posix.cc | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/base/time/time_exploded_posix.cc b/base/time/time_exploded_posix.cc
+index 6f4ead4fb2..8f8cf67daf 100644
+--- a/base/time/time_exploded_posix.cc
++++ b/base/time/time_exploded_posix.cc
+@@ -142,8 +142,7 @@ void Time::Explode(bool is_local, Exploded* exploded) const {
+   // Split the |millis_since_unix_epoch| into separate seconds and millisecond
+   // components because the platform calendar-explode operates at one-second
+   // granularity.
+-  auto seconds = base::checked_cast<SysTime>(millis_since_unix_epoch /
+-                                             Time::kMillisecondsPerSecond);
++  SysTime seconds = millis_since_unix_epoch / Time::kMillisecondsPerSecond;
+   int64_t millisecond = millis_since_unix_epoch % Time::kMillisecondsPerSecond;
+   if (millisecond < 0) {
+     // Make the the |millisecond| component positive, within the range [0,999],
+-- 
+2.46.1.824.gd892dcdcdd-goog
+
diff --git a/libchrome_tools/patches/long-term-2800-Disable-unneeded-Rust-logging-integration.patch b/libchrome_tools/patches/long-term-2800-Disable-unneeded-Rust-logging-integration.patch
new file mode 100644
index 0000000..545b76e
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2800-Disable-unneeded-Rust-logging-integration.patch
@@ -0,0 +1,35 @@
+From 09e1796d4a48de1dfa34c819ace899f41c5da36f Mon Sep 17 00:00:00 2001
+From: Ryo Hashimoto <hashimoto@chromium.org>
+Date: Fri, 18 Oct 2024 12:04:26 +0900
+Subject: [PATCH] Disable unneeded Rust logging integration
+
+Change-Id: Ic0bf93a07ed2d3f4422544cc699e17086d096d75
+---
+ base/logging.cc | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/base/logging.cc b/base/logging.cc
+index 508ce13513..db39d91f14 100644
+--- a/base/logging.cc
++++ b/base/logging.cc
+@@ -126,7 +126,7 @@ typedef FILE* FileHandle;
+ #include "base/fuchsia/scoped_fx_logger.h"
+ #endif
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+ #include "base/logging/rust_logger.rs.h"
+ #endif
+ 
+@@ -526,7 +526,7 @@ bool BaseInitLoggingImpl(const LoggingSettings& settings) {
+   }
+ #endif
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+   // Connects Rust logging with the //base logging functionality.
+   internal::init_rust_log_crate();
+ #endif
+-- 
+2.47.0.105.g07ac214952-goog
+
diff --git a/libchrome_tools/patches/long-term-2900-Disable-Rust-in-json_reader.patch b/libchrome_tools/patches/long-term-2900-Disable-Rust-in-json_reader.patch
new file mode 100644
index 0000000..9a8fedc
--- /dev/null
+++ b/libchrome_tools/patches/long-term-2900-Disable-Rust-in-json_reader.patch
@@ -0,0 +1,62 @@
+From 7b267465bf32844fb9a8552b5c155e605a352946 Mon Sep 17 00:00:00 2001
+From: Andrew Moylan <amoylan@google.com>
+Date: Tue, 12 Nov 2024 12:01:52 +1100
+Subject: [PATCH] Disable Rust in json_reader
+
+Change-Id: I6883925e7216b967ee3830d087792bc6fa25034f
+---
+ base/json/json_reader.cc | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc
+index b3db0dea0f..9fe9d0b4a0 100644
+--- a/base/json/json_reader.cc
++++ b/base/json/json_reader.cc
+@@ -13,7 +13,7 @@
+ #include "base/metrics/histogram_macros.h"
+ #include "build/build_config.h"
+ 
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+ #include "base/strings/string_view_rust.h"
+ #include "third_party/rust/serde_json_lenient/v0_2/wrapper/functions.h"
+ #include "third_party/rust/serde_json_lenient/v0_2/wrapper/lib.rs.h"
+@@ -23,7 +23,7 @@ namespace base {
+ 
+ // TODO(crbug.com/40811643): Move the C++ parser into components/nacl to just
+ // run in-process there. Don't compile base::JSONReader on NaCL at all.
+-#if !BUILDFLAG(IS_NACL)
++#if !BUILDFLAG(IS_NACL) && 0
+ 
+ namespace {
+ using serde_json_lenient::ContextPointer;
+@@ -140,7 +140,7 @@ JSONReader::Result DecodeJSONInRust(std::string_view json,
+ std::optional<Value> JSONReader::Read(std::string_view json,
+                                       int options,
+                                       size_t max_depth) {
+-#if BUILDFLAG(IS_NACL)
++#if BUILDFLAG(IS_NACL) || 1
+   internal::JSONParser parser(options, max_depth);
+   return parser.Parse(json);
+ #else   // BUILDFLAG(IS_NACL)
+@@ -173,7 +173,7 @@ std::optional<Value::Dict> JSONReader::ReadDict(std::string_view json,
+ JSONReader::Result JSONReader::ReadAndReturnValueWithError(
+     std::string_view json,
+     int options) {
+-#if BUILDFLAG(IS_NACL)
++#if BUILDFLAG(IS_NACL) || 1
+   internal::JSONParser parser(options);
+   auto value = parser.Parse(json);
+   if (!value) {
+@@ -213,7 +213,7 @@ bool JSONReader::UsingRust() {
+   if (!base::FeatureList::GetInstance()) {
+     return false;
+   }
+-#if BUILDFLAG(IS_NACL)
++#if BUILDFLAG(IS_NACL) || 1
+   return false;
+ #else
+   return base::FeatureList::IsEnabled(base::features::kUseRustJsonParser);
+-- 
+2.47.0.277.g8800431eea-goog
+
diff --git a/libchrome_tools/patches/patches.config b/libchrome_tools/patches/patches.config
new file mode 100644
index 0000000..ebd88f0
--- /dev/null
+++ b/libchrome_tools/patches/patches.config
@@ -0,0 +1,13 @@
+# This file will be used by emerge in libchrome-XXXX.ebuild to determine
+# patches that are selectively applied.
+#
+# Support selectively applying patch by use flag, examples:
+# * To apply foo.patch to every board, add
+#   `foo.patch`
+# * To apply foo.patch to board bar only, add
+#   `foo.patch board_use_bar`
+# * To apply foo.patch to board installing package baz only, add
+#   `foo.patch board_use_baz`
+# Note: add flag to IUSE in libchrome ebuild if it is not already there.
+#
+# Patches not listed in this file will always be applied.
diff --git a/libchrome_tools/test_apply_patches.py b/libchrome_tools/test_apply_patches.py
new file mode 100644
index 0000000..de5042a
--- /dev/null
+++ b/libchrome_tools/test_apply_patches.py
@@ -0,0 +1,756 @@
+#!/usr/bin/env python
+# Copyright 2023 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import re
+import subprocess
+import tempfile
+import unittest
+import unittest.mock
+from pathlib import Path
+from shutil import copy
+from typing import Sequence
+
+import apply_patches
+
+
+def init_git_repo_with_patches(inject_error: bool = False):
+    # Create tmp directory as a git repository (acting-libchrome) with
+    # patches directory structure.
+    repo_dir = tempfile.TemporaryDirectory()
+    repo_dir_path = repo_dir.name
+    logging.debug('temporary directory at: %s', repo_dir_path)
+    patch_dir = os.path.join(repo_dir_path, 'libchrome_tools/', 'patches/')
+    os.makedirs(patch_dir)
+
+    # Copy all files in local test data directory to tmp directory.
+    os.chdir(
+        os.path.join(
+            Path(__file__).resolve().parent, 'testdata', 'apply_patches'))
+    for patch in os.listdir():
+        copy(patch, patch_dir)
+
+    # Change to tmp directory for git commands. Make initial commit.
+    os.chdir(repo_dir_path)
+    subprocess.check_call(["git", "init"])
+    with open(os.path.join(repo_dir_path, "init_file.txt"),
+              "w",
+              encoding='utf-8') as f:
+        f.write("foo\n")
+    subprocess.check_call(["git", "add", "."])
+    subprocess.check_call(["git", "commit", "-m", "initial commit"])
+
+    # Need to be done in separate step (not writing a different line to the file
+    # directly in above initial commit) otherwise 3-way merge will fail with
+    # "repository lacks the necessary blob to perform 3-way merge" error.
+    if inject_error:
+        with open(os.path.join(repo_dir_path, "init_file.txt"),
+                  "w",
+                  encoding='utf-8') as f:
+            f.write("wrong line\n")
+        subprocess.check_call(["git", "commit", "-a", "--amend", "--no-edit"])
+
+    subprocess.check_call(["git", "checkout", "-b", "new-branch"])
+    return repo_dir
+
+
+def git_log_length() -> int:
+    git_log = subprocess.check_output(["git", "log", "--oneline"]).strip()
+    return len(git_log.splitlines())
+
+
+def get_HEAD_commit_oneline() -> str:
+    return subprocess.check_output(["git", "log", "HEAD", "-1", "--oneline"],
+                                   universal_newlines=True).strip()
+
+
+def read_file(file_path: str) -> str:
+    with open(file_path, "r", encoding='utf-8') as f:
+        return f.read()
+
+
+def assertRegexIn(pattern, sequence: Sequence[str]) -> re.Match:
+    """Assert that >=1 string in the sequence matches the regex pattern.
+
+    Returns:
+        The matched object of the first matched string in sequence.
+    """
+    regex = re.compile(pattern)
+    for s in sequence:
+        m = regex.search(s)
+        if m:
+            return m
+    raise AssertionError(
+        f'No item in sequence {",".join(sequence)} matches regex '
+        f'{pattern}.')
+
+
+class TestCommandNotRun(unittest.TestCase):
+    def setUp(self):
+        """Create temporary git directory to be act as the libchrome directory.
+
+        Containing a target file to be modified (init_file.txt) and patches to
+        be applied.
+        """
+        logging.basicConfig(level=logging.DEBUG)
+        logging.info("Running test: %s", self.id)
+        self.repo_dir = init_git_repo_with_patches()
+        self.repo_dir_path = self.repo_dir.name
+
+    def tearDown(self):
+        self.repo_dir.cleanup()
+
+
+    def read_init_file(self) -> str:
+        return read_file(os.path.join(self.repo_dir_path, "init_file.txt"))
+
+    def test_dirty_git_repo(self):
+        with open(os.path.join(self.repo_dir_path, "init_file.txt"),
+                  "w",
+                  encoding='utf-8') as f:
+            f.write("dirty git repo\n")
+
+        with self.assertRaisesRegex(
+                RuntimeError, 'Git working directory is dirty. Abort script.'):
+            apply_patches.assert_git_repo_state_and_get_current_branch()
+
+        self.assertEqual(self.read_init_file(), "dirty git repo\n")
+
+    def test_git_repo_no_branch(self):
+        # Go to 'detached HEAD' state.
+        head_hash = subprocess.check_output(["git", "log", "--oneline", "-1"],
+                                            universal_newlines=True).split()[0]
+        subprocess.check_call(["git", "checkout", head_hash])
+
+        with self.assertRaisesRegex(RuntimeError,
+                                    'Not on a branch. Abort script.'):
+            apply_patches.assert_git_repo_state_and_get_current_branch()
+
+        self.assertEqual(self.read_init_file(), "foo\n")
+
+
+class TestSanitizePatchArgs(unittest.TestCase):
+    def setUp(self):
+        """Create temporary git directory to be act as the libchrome directory.
+
+        Containing a target file to be modified (init_file.txt) and patches to
+        be applied.
+        """
+        logging.basicConfig(level=logging.DEBUG)
+        logging.info("Running test: %s", self.id)
+        self.repo_dir = init_git_repo_with_patches(True)
+        self.repo_dir_path = self.repo_dir.name
+
+    def tearDown(self):
+        self.repo_dir.cleanup()
+
+    def first_patch_not_found(self):
+        wrong_patch_name = 'wrong_patch_name.patch'
+        with self.assertRaisesRegex(
+                ValueError, "--first ({wrong_patch_name})) does not exist"):
+            apply_patches.sanitize_patch_args(
+                'first', wrong_patch_name, self.repo_dir_path)
+
+    def last_patch_not_found(self):
+        wrong_patch_name = 'wrong_patch_name.patch'
+        with self.assertRaisesRegex(
+                ValueError, "--last ({wrong_patch_name})) does not exist"):
+            apply_patches.sanitize_patch_args(
+                'last', wrong_patch_name, self.repo_dir_path)
+
+    def patch_arg_in_wrong_dir(self):
+        patch_path_with_wrong_dir = 'foo/wrong_patch_name.patch'
+        with self.assertRaisesRegex(
+                ValueError,
+                f"--first ({patch_path_with_wrong_dir})) is given as a path "
+                "but its parent directory is not"):
+            apply_patches.apply_patches(
+                'first', patch_path_with_wrong_dir, self.repo_dir_path)
+
+    def invalid_file_as_patch_arg(self):
+        # Add file without correct patch prefix to patches directory.
+        invalid_file = "invalid_patch_name.patch"
+        with open(invalid_file, "w") as f:
+            f.write("testing\n")
+        subprocess.check_call(["git", "commit", "-a", "--amend", "--no-edit"])
+
+        with self.assertRaisesRegex(
+                ValueError,
+                f"{invalid_file} is not a valid patch: patch name must start "
+                "with prefixes"):
+            apply_patches.apply_patches(
+                'first', invalid_file, self.repo_dir_path)
+
+
+class TestApplyPatchGetPatchCommitsSinceTag(unittest.TestCase):
+    def setUp(self) -> None:
+        """Create temporary git directory to be act as the libchrome directory.
+
+        Containing a target file to be modified (init_file.txt) and patches to
+        be applied.
+        """
+        logging.basicConfig(level=logging.INFO)
+        logging.info(self._testMethodName)
+        self.repo_dir = init_git_repo_with_patches()
+        self.repo_dir_path = self.repo_dir.name
+
+    def tearDown(self):
+        self.repo_dir.cleanup()
+
+    def test_allow_no_patch_head_tag(self):
+        """Tag HEAD commit when there is no HEAD-before-patching tag."""
+        head_commit = get_HEAD_commit_oneline()
+        with self.assertLogs("root", level='INFO') as context:
+            patch_commits = apply_patches.get_patch_commits_since_tag(
+                "new-branch")
+        self.assertIn("INFO:root:Tagged current HEAD as HEAD-before-patching.",
+                      context.output)
+        self.assertEqual(patch_commits, [])
+
+        patch_head = apply_patches.get_patch_head_commit()
+        self.assertIsNotNone(patch_head)
+        self.assertEqual(
+            patch_head.split(maxsplit=1)[0],
+            head_commit.split(maxsplit=1)[0])
+
+    def test_forbid_no_patch_head_tag(self):
+        """Abort when there is no HEAD-before-patching tag."""
+        with self.assertRaisesRegex(
+                RuntimeError,
+                rf"Tag {apply_patches.TAG} does not exist\. Please run `git "
+                rf"tag \<hash\> {apply_patches.TAG}` with hash being commit to "
+                r"reset to if you have applied patches manually\."):
+            apply_patches.get_patch_commits_since_tag("new-branch", False)
+
+    def test_keep_existing_valid_patch_head_tag(self):
+        """Skip tagging automatically if current tag is valid."""
+        old_patch_head = get_HEAD_commit_oneline()
+        old_patch_head_hash = old_patch_head.split(maxsplit=1)[0]
+        subprocess.check_call(['git', 'tag', apply_patches.TAG])
+        # Run apply_patches to get patch commits (only) in git log.
+        apply_patches.apply_patches(self.repo_dir_path,
+                                    ebuild=False,
+                                    no_commit=False)
+
+        with self.assertLogs("root", level='INFO') as context:
+            patch_commits = apply_patches.get_patch_commits_since_tag(
+                "new-branch")
+        self.assertIn(
+            f"INFO:root:Tag {apply_patches.TAG} already exists: "
+            f"{old_patch_head}.", context.output)
+        self.assertIn(
+            f"INFO:root:Confirmed only patch commits from {apply_patches.TAG} "
+            "to HEAD.", context.output)
+        # Applied patch commits since HEAD-before-patching should be the same
+        # as all patches in the patches directory.
+        self.assertEqual([c.patch_name for c in patch_commits], [
+            os.path.basename(p)
+            for p in apply_patches.get_all_patches(self.repo_dir_path)
+        ])
+
+        # Commit tagged as HEAD-before-patching should remain the same.
+        patch_head = apply_patches.get_patch_head_commit()
+        self.assertIsNotNone(patch_head)
+        self.assertEqual(patch_head.split(maxsplit=1)[0], old_patch_head_hash)
+
+    def test_abort_patch_head_tag_with_non_patch_commits_in_history(self):
+        """Abort when there is any non-patch commits."""
+        # Tag HEAD as HEAD-before-patching and add commit without patch-name
+        # trailer (i.e. non-patch commit).
+        head_commit = get_HEAD_commit_oneline()
+        subprocess.check_call(['git', 'tag', apply_patches.TAG])
+        subprocess.check_call(
+            ['git', 'commit', '-m', "empty non-patch commit", "--allow-empty"])
+        empty_commit_hash = get_HEAD_commit_oneline().split(maxsplit=1)[0]
+
+        with self.assertRaisesRegex(
+                RuntimeError,
+                re.compile(
+                    fr"There is non-patch commit from {apply_patches.TAG} to "
+                    r"HEAD:\n"
+                    fr"{empty_commit_hash}.*: 0 patch-name trailer\(s\).",
+                    re.MULTILINE)):
+            apply_patches.get_patch_commits_since_tag("new-branch")
+
+        # Commit tagged as HEAD-before-patching should remain the same.
+        patch_head = apply_patches.get_patch_head_commit()
+        self.assertIsNotNone(patch_head)
+        self.assertEqual(
+            patch_head.split(maxsplit=1)[0],
+            head_commit.split(maxsplit=1)[0])
+
+    def test_abort_patch_head_tag_with_patch_commits_in_wrong_order(self):
+        """Abort if the commits are in a different order than at built time."""
+        # Tag HEAD as HEAD-before-patching and add empty commits with patch-name
+        # trailer such that they are in wrong order (backward compatibility
+        # patches before long term patches).
+        head_commit = get_HEAD_commit_oneline()
+        subprocess.check_call(['git', 'tag', apply_patches.TAG])
+        subprocess.check_call([
+            'git', 'commit', '--allow-empty', '-m',
+            "backward compatibility patch commit", '-m', '', '-m',
+            'patch-name: backward-compatibility-0001-empty.patch'
+        ])
+        subprocess.check_call([
+            'git', 'commit', '--allow-empty', '-m', "long term patch commit",
+            '-m', '', '-m', 'patch-name: long-term-0005-empty.patch'
+        ])
+
+        with self.assertRaisesRegex(
+                RuntimeError,
+                r"Applied patches in git log are not in correct application "
+                r"order. This may cause unexpected apply failure when `emerge "
+                r"libchrome` with the generated patches."):
+            apply_patches.get_patch_commits_since_tag("new-branch")
+
+        # Commit tagged as HEAD-before-patching should remain the same.
+        patch_head = apply_patches.get_patch_head_commit()
+        self.assertIsNotNone(patch_head)
+        self.assertEqual(
+            patch_head.split(maxsplit=1)[0],
+            head_commit.split(maxsplit=1)[0])
+
+
+class TestClampPatchesNoAppliedPatchCommits(unittest.TestCase):
+    def setUp(self):
+        logging.basicConfig(level=logging.DEBUG)
+        logging.info("Running test: %s", self.id)
+        self.patches = [
+            "long-term-0000-foo.patch",
+            "long-term-0001-bar.patch",
+            "backward-compatibility-0001-baz.patch",
+        ]
+
+    def test_no_clamp(self):
+        clamped_patches = apply_patches.clamp_patches(self.patches, [], None,
+                                                      None)
+        self.assertEqual(clamped_patches, self.patches)
+
+    def test_clamp_only_first_specified(self):
+        clamped_patches = apply_patches.clamp_patches(self.patches, [],
+                                                      self.patches[-1], None)
+        self.assertEqual(clamped_patches, self.patches[-1:])
+
+    def test_clamp_only_last_specified(self):
+        clamped_patches = apply_patches.clamp_patches(self.patches, [], None,
+                                                      self.patches[1])
+        self.assertEqual(clamped_patches, self.patches[:2])
+
+    def test_clamp_first_last_specified(self):
+        clamped_patches = apply_patches.clamp_patches(self.patches, [],
+                                                      self.patches[1],
+                                                      self.patches[1])
+        self.assertEqual(clamped_patches, self.patches[1:2])
+
+    def test_clamp_first_after_last(self):
+        with self.assertRaises(
+                RuntimeError,
+                msg=
+                f"Invalid input --last {self.patches[0]}: last patch to apply "
+                "should not be applied before the first one "
+                f"({self.patches[1]})."):
+            apply_patches.clamp_patches(self.patches, [], self.patches[1],
+                                        self.patches[0])
+
+
+def _patch_name_to_patch_commit(patch_name: str) -> apply_patches.PatchCommit:
+    return apply_patches.PatchCommit('mockHash', patch_name)
+
+
+class TestClampPatchesWithAppliedPatchCommitsInHistory(unittest.TestCase):
+    def setUp(self):
+        logging.basicConfig(level=logging.DEBUG)
+        logging.info("Running test: %s", self.id)
+        self.patches = [
+            "long-term-0000-foo.patch",
+            "long-term-0001-bar.patch",
+            "backward-compatibility-0001-baz.patch",
+        ]
+
+    def test_no_clamp(self):
+        # Apply all patches after the first one which is already in history.
+        clamped_patches = apply_patches.clamp_patches(
+            self.patches,
+            [_patch_name_to_patch_commit(pn)
+             for pn in self.patches[:1]], None, None)
+        self.assertEqual(clamped_patches, self.patches[1:])
+
+    def test_clamp_only_first_specified(self):
+        # Apply all patches after the specified --first.
+        # Skipping (the second) patch is allowed as long as order is right.
+        clamped_patches = apply_patches.clamp_patches(
+            self.patches,
+            [_patch_name_to_patch_commit(pn)
+             for pn in self.patches[:1]], self.patches[2], None)
+        self.assertEqual(clamped_patches, self.patches[2:])
+
+    def test_clamp_only_last_specified(self):
+        # Apply the second patch only -- first is already in history and second
+        # is specified to be --last.
+        clamped_patches = apply_patches.clamp_patches(
+            self.patches,
+            [_patch_name_to_patch_commit(pn)
+             for pn in self.patches[:1]], None, self.patches[1])
+        self.assertEqual(clamped_patches, self.patches[1:2])
+
+    def test_clamp_first_last_specified(self):
+        # Apply all patches after the specified --first and until --last.
+        clamped_patches = apply_patches.clamp_patches(
+            self.patches,
+            [_patch_name_to_patch_commit(pn)
+             for pn in self.patches[:1]], self.patches[2], self.patches[2])
+        self.assertEqual(clamped_patches, self.patches[2:])
+
+    def test_clamp_first_not_after_last_applied_patch(self):
+        with self.assertRaises(
+                RuntimeError,
+                msg=f"Invalid input --first {self.patches[0]}: first patch to "
+                "apply should be applied after the last patch commit "
+                f"({self.patches[0]}) in history."):
+            apply_patches.clamp_patches(
+                self.patches,
+                [_patch_name_to_patch_commit(pn)
+                 for pn in self.patches[:1]], self.patches[0], None)
+
+    def test_clamp_last_not_after_last_applied_patch(self):
+        with self.assertRaises(
+                RuntimeError,
+                msg=
+                f"Invalid input --last {self.patches[0]}: last patch to apply "
+                "should not be applied before the first one "
+                f"({self.patches[1]})."):
+            apply_patches.clamp_patches(
+                self.patches,
+                [_patch_name_to_patch_commit(pn)
+                 for pn in self.patches[:2]], None, self.patches[0])
+
+
+class TestApplyPatchesSucceed(unittest.TestCase):
+    def setUp(self):
+        """Create temporary git directory to be act as the libchrome directory.
+
+        Containing a target file to be modified (init_file.txt) and patches to
+        be applied.
+        """
+        logging.basicConfig(level=logging.DEBUG)
+        logging.info("Running test: %s", self.id)
+        self.repo_dir = init_git_repo_with_patches()
+        self.repo_dir_path = self.repo_dir.name
+
+    def tearDown(self):
+        self.repo_dir.cleanup()
+
+    def read_init_file(self) -> str:
+        return read_file(os.path.join(self.repo_dir_path, "init_file.txt"))
+
+    def test_dryrun(self):
+        apply_patches.apply_patches(self.repo_dir_path,
+                                    ebuild=False,
+                                    no_commit=True,
+                                    dry_run=True)
+        # Initial commit only.
+        self.assertEqual(git_log_length(), 1)
+        # File content unchanged.
+        self.assertEqual(self.read_init_file(), "foo\n")
+
+    def test_default_apply(self):
+        head_commit = get_HEAD_commit_oneline()
+        apply_patches.apply_patches(self.repo_dir_path,
+                                    ebuild=False,
+                                    no_commit=False)
+        self.assertEqual(self.read_init_file(), "bar\nbaz\nfoo\n")
+        # Initial commit and 3 commits from patches.
+        self.assertEqual(git_log_length(), 4)
+        # Assert commit message contains trailer for patch name.
+        patch_name_trailers = subprocess.check_output(
+            [
+                'git', 'log', '--format=%(trailers:key=patch-name,valueonly)',
+                '-n3'
+            ],
+            universal_newlines=True,
+        ).strip().split('\n\n')
+        self.assertEqual(patch_name_trailers, [
+            'backward-compatibility-0500-add-foo-to-end-of-file.patch',
+            'long-term-0100-remove-foo.patch',
+            'long-term-0000-add-bar-and-baz.patch',
+        ])
+
+    def test_default_apply_patch_overwrite_trailer_with_new_name(self):
+        # Add trailer with a different patch-name than its file name to patch.
+        trailer_patch_name = "backward-compatibility-0500-old-patch-name.patch"
+        patch_file_name = (
+            "backward-compatibility-0500-add-foo-to-end-of-file.patch")
+        subprocess.check_call([
+            "git", "interpret-trailers", "--trailer",
+            f"patch-name: {trailer_patch_name}", "--in-place",
+            os.path.join("libchrome_tools", "patches", patch_file_name)
+        ])
+        subprocess.check_call(["git", "commit", "-a", "--amend", "--no-edit"])
+
+        # Assert warning-level message is logged for overwriting trailer value.
+        with self.assertLogs("root", level='WARNING') as context:
+            apply_patches.apply_patches(self.repo_dir_path,
+                                        ebuild=False,
+                                        no_commit=False,
+                                        dry_run=False)
+        self.assertIn(
+            "WARNING:root:Applied patch contains patch-name trailers "
+            f"(['{trailer_patch_name}']) different from filename "
+            f"({patch_file_name}). Overwriting with filename.", context.output)
+
+        # Assert last commit's message has only one patch-name trailer and value
+        # is its current filename.
+        patch_name_trailers = subprocess.check_output(
+            [
+                'git', 'log', '--format=%(trailers:key=patch-name,valueonly)',
+                '-n1'
+            ],
+            universal_newlines=True,
+        ).strip().split('\n\n', maxsplit=1)[0].split('\n')
+        self.assertEqual(len(patch_name_trailers), 1)
+        self.assertEqual(patch_name_trailers[0], patch_file_name)
+
+    def test_apply_with_first_and_last_args(self):
+        apply_patches.apply_patches(
+            self.repo_dir_path,
+            ebuild=False,
+            no_commit=False,
+            last='long-term-0000-add-bar-and-baz.patch')
+        self.assertEqual(self.read_init_file(), "foo\nbar\nbaz\n")
+        # Initial commit and 1 commit from the first patch.
+        self.assertEqual(git_log_length(), 2)
+
+        apply_patches.apply_patches(self.repo_dir_path,
+                                    ebuild=False,
+                                    no_commit=False,
+                                    first='long-term-0100-remove-foo.patch',
+                                    last='long-term-0100-remove-foo.patch')
+        self.assertEqual(self.read_init_file(), "bar\nbaz\n")
+        # Initial commit and 2 commits (applied in two different runs).
+        self.assertEqual(git_log_length(), 3)
+
+        apply_patches.apply_patches(
+            self.repo_dir_path,
+            ebuild=False,
+            no_commit=False,
+            first='backward-compatibility-0500-add-foo-to-end-of-file.patch')
+        self.assertEqual(self.read_init_file(), "bar\nbaz\nfoo\n")
+        # Initial commit and 3 commits (applied in three different runs).
+        self.assertEqual(git_log_length(), 4)
+
+    def test_no_commit_apply(self):
+        apply_patches.apply_patches(self.repo_dir_path,
+                                    ebuild=False,
+                                    no_commit=True)
+        self.assertEqual(self.read_init_file(), "bar\nbaz\nfoo\n")
+        # Initial commit only.
+        self.assertEqual(git_log_length(), 1)
+
+    def test_ebuild_apply(self):
+        apply_patches.apply_patches(self.repo_dir_path,
+                                    ebuild=True,
+                                    no_commit=True)
+        self.assertEqual(self.read_init_file(), "bar\nbaz\nfoo\n")
+
+
+class TestApplyPatchesFail(unittest.TestCase):
+    def setUp(self):
+        """Create temporary git directory to be act as the libchrome directory.
+
+        Containing a target file to be modified (init_file.txt) and patches to
+        be applied.
+        """
+        logging.basicConfig(level=logging.DEBUG)
+        logging.info("Running test: %s", self.id)
+        self.repo_dir = init_git_repo_with_patches(inject_error=True)
+        self.repo_dir_path = self.repo_dir.name
+
+    def tearDown(self):
+        self.repo_dir.cleanup()
+
+    def read_init_file(self) -> str:
+        return read_file(os.path.join(self.repo_dir_path, "init_file.txt"))
+
+    def test_default_apply(self):
+        with self.assertRaisesRegex(
+                RuntimeError,
+                'Failed to git am patch long-term-0000-add-bar-and-baz.patch'):
+            apply_patches.apply_patches(self.repo_dir_path,
+                                        ebuild=False,
+                                        no_commit=False)
+        # Initial commit only with 3-way merge markers.
+        self.assertEqual(git_log_length(), 1)
+        self.assertEqual(
+            self.read_init_file(), "<<<<<<< HEAD\n"
+            "wrong line\n"
+            "=======\n"
+            "foo\n"
+            "bar\n"
+            "baz\n"
+            ">>>>>>> Add bar and baz\n")
+
+    def test_no_commit_apply(self):
+        # Assert the git apply command failed with --3way option.
+        with self.assertRaisesRegex(
+                RuntimeError,
+                'Failed to git apply patch long-term-0000-add-bar-and-baz.patch'
+        ):
+            apply_patches.apply_patches(self.repo_dir_path,
+                                        ebuild=False,
+                                        no_commit=True)
+
+        # Initial commit only and file now contains 3-way merge markers.
+        self.assertEqual(git_log_length(), 1)
+        self.assertEqual(
+            self.read_init_file(), "<<<<<<< ours\n"
+            "wrong line\n"
+            "=======\n"
+            "foo\n"
+            "bar\n"
+            "baz\n"
+            ">>>>>>> theirs\n")
+
+    def test_ebuild_apply(self):
+        # Assert the function failed with self-defined RuntimeError.
+        with self.assertRaisesRegex(
+                subprocess.CalledProcessError, r"\['git', 'apply', '-C1', '"
+                r".*/long-term-0000-add-bar-and-baz.patch'\]"):
+            apply_patches.apply_patches(self.repo_dir_path,
+                                        ebuild=True,
+                                        no_commit=True)
+
+        # Initial commit only and file is not modified.
+        self.assertEqual(git_log_length(), 1)
+        self.assertEqual(self.read_init_file(), "wrong line\n")
+
+
+class TestFormatPatchesSucceed(unittest.TestCase):
+    def setUp(self):
+        """Create temporary git directory to be act as the libchrome directory.
+
+        Containing a target file to be modified (init_file.txt) and patches to
+        be applied.
+
+        Apply all patches.
+        """
+        logging.basicConfig(level=logging.DEBUG)
+        logging.info("Running test: %s", self.id)
+        self.repo_dir = init_git_repo_with_patches()
+        self.repo_dir_path = self.repo_dir.name
+        self.HEAD_before_patching = get_HEAD_commit_oneline()
+        apply_patches.apply_patches(self.repo_dir_path,
+                                    ebuild=False,
+                                    no_commit=False)
+
+    def tearDown(self):
+        self.repo_dir.cleanup()
+
+    def read_init_file(self) -> str:
+        return read_file(os.path.join(self.repo_dir_path, "init_file.txt"))
+
+    def test_basic_run(self):
+        # Amend last patch to write two "foo"'s instead of one.
+        with open(os.path.join(self.repo_dir_path, "init_file.txt"),
+                  "a",
+                  encoding='utf-8') as f:
+            f.write("foo\n")
+        subprocess.check_call(["git", "commit", "-a", "--amend", "--no-edit"])
+
+        apply_patches.format_patches(self.repo_dir_path)
+
+        # Check git repo has been reset to original commit.
+        current_HEAD = get_HEAD_commit_oneline()
+        self.assertEqual(current_HEAD, self.HEAD_before_patching)
+        # File should contain original content.
+        self.assertEqual(self.read_init_file(), "foo\n")
+        # HEAD-before-patching tag no longer exists.
+        patch_head = apply_patches.get_patch_head_commit()
+        self.assertIsNone(patch_head)
+
+        os.chdir(os.path.join(self.repo_dir_path, "libchrome_tools",
+                              "patches"))
+        # Get summary of uncommitted changes.
+        git_status_short = subprocess.check_output(
+            ["git", "status", "--short"],
+            universal_newlines=True).splitlines()
+        self.assertEqual(len(git_status_short), 3)
+        # Each line is status of file (e.g. M for modified, D for deleted)
+        # followed by file name.
+        git_status_short = [line.split() for line in git_status_short]
+        # All files are modified (hash of patch file changes although no change
+        # to patch content).
+        self.assertSetEqual(set(s for (s, _) in git_status_short), set("M"))
+        self.assertSetEqual(set(f for (_, f) in git_status_short),
+                            set(os.listdir(".")))
+
+        # Save changes of new patches and reapply them.
+        subprocess.check_call(["git", "commit", "-a", "--amend", "--no-edit"])
+        apply_patches.apply_patches(self.repo_dir_path,
+                                    ebuild=False,
+                                    no_commit=False)
+
+        # The file now contains two foo's.
+        self.assertEqual(self.read_init_file(), "bar\nbaz\nfoo\nfoo\n")
+
+    def test_with_renamed_patch(self):
+        old_patch_name = (
+            "backward-compatibility-0500-add-foo-to-end-of-file.patch")
+        new_patch_name = "backward-compatibility-0100-add-foo.patch"
+        # Change last patch's patch-name trailer value.
+        subprocess.check_call([
+            "git", "-c", "trailer.ifexists=replace", "commit", "--amend",
+            "--no-edit", "--trailer", f"patch-name: {new_patch_name}"
+        ])
+
+        apply_patches.format_patches(self.repo_dir_path)
+
+        os.chdir(os.path.join(self.repo_dir_path, "libchrome_tools",
+                              "patches"))
+        # Get summary of uncommitted changes.
+        git_status_short = subprocess.check_output(
+            ["git", "status", "--short"],
+            universal_newlines=True).splitlines()
+        self.assertEqual(len(git_status_short), 3)
+        # Each line is status of file (e.g. M for modified, D for deleted)
+        # followed by file name.
+        git_status_short = [line.split() for line in git_status_short]
+        # Local changes includes the new patch file as untracked file, and not
+        # the old patch file.
+        self.assertIn(["??", new_patch_name], git_status_short)
+        self.assertNotIn(old_patch_name, [f for (_, f) in git_status_short])
+
+    def test_backup_branch(self):
+        with self.assertLogs("root", level='INFO') as context:
+            apply_patches.format_patches(self.repo_dir_path,
+                                         backup_branch=True)
+        backup_branch = assertRegexIn(
+            r"Backed up git history to branch (apply-patch-backup-\d{14}).",
+            context.output).group(1)
+
+        # Check that the backup branch indeed exists.
+        branches = subprocess.check_output(
+            ["git", "branch", "--format=%(refname:short)"],
+            universal_newlines=True).splitlines()
+        self.assertIn(backup_branch, branches)
+
+        # Go to backup branch.
+        subprocess.check_call(["git", "checkout", backup_branch])
+        # Check that the initial commit and 3 patch commits are in history.
+        self.assertEqual(git_log_length(), 4)
+        patch_name_trailers = subprocess.check_output(
+            [
+                'git', 'log', '--format=%(trailers:key=patch-name,valueonly)',
+                '-n3'
+            ],
+            universal_newlines=True,
+        ).strip().split('\n\n')
+        self.assertEqual(patch_name_trailers, [
+            'backward-compatibility-0500-add-foo-to-end-of-file.patch',
+            'long-term-0100-remove-foo.patch',
+            'long-term-0000-add-bar-and-baz.patch',
+        ])
+        # Check that file content is the same as after applying the 3 patches.
+        self.assertEqual(self.read_init_file(), "bar\nbaz\nfoo\n")
diff --git a/libchrome_tools/testdata/apply_patches/backward-compatibility-0500-add-foo-to-end-of-file.patch b/libchrome_tools/testdata/apply_patches/backward-compatibility-0500-add-foo-to-end-of-file.patch
new file mode 100644
index 0000000..d442f58
--- /dev/null
+++ b/libchrome_tools/testdata/apply_patches/backward-compatibility-0500-add-foo-to-end-of-file.patch
@@ -0,0 +1,20 @@
+From 6af0900055e2eff704c486c80f5637ec764e9f0e Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Thu, 10 Aug 2023 17:36:56 +0900
+Subject: [PATCH 2/2] Add foo to end of file
+
+---
+ init_file.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/init_file.txt b/init_file.txt
+index e2994c5..aee7988 100644
+--- a/init_file.txt
++++ b/init_file.txt
+@@ -1,2 +1,3 @@
+ bar
+ baz
++foo
+-- 
+2.41.0.640.ga95def55d0-goog
+
diff --git a/libchrome_tools/testdata/apply_patches/long-term-0000-add-bar-and-baz.patch b/libchrome_tools/testdata/apply_patches/long-term-0000-add-bar-and-baz.patch
new file mode 100644
index 0000000..4a1695f
--- /dev/null
+++ b/libchrome_tools/testdata/apply_patches/long-term-0000-add-bar-and-baz.patch
@@ -0,0 +1,20 @@
+From b35f1a2bbf1c8f336b4b0cb303a4f4744287f250 Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Thu, 10 Aug 2023 17:33:06 +0900
+Subject: [PATCH] Add bar and baz
+
+---
+ init_file.txt | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/init_file.txt b/init_file.txt
+index 257cc56..86e041d 100644
+--- a/init_file.txt
++++ b/init_file.txt
+@@ -1 +1,3 @@
+ foo
++bar
++baz
+-- 
+2.41.0.640.ga95def55d0-goog
+
diff --git a/libchrome_tools/testdata/apply_patches/long-term-0100-remove-foo.patch b/libchrome_tools/testdata/apply_patches/long-term-0100-remove-foo.patch
new file mode 100644
index 0000000..9581c39
--- /dev/null
+++ b/libchrome_tools/testdata/apply_patches/long-term-0100-remove-foo.patch
@@ -0,0 +1,20 @@
+From 209e119f08a28dbc16cbed72c95ea8d69724579e Mon Sep 17 00:00:00 2001
+From: Grace Cham <hscham@chromium.org>
+Date: Thu, 10 Aug 2023 17:36:33 +0900
+Subject: [PATCH 1/2] Remove foo
+
+---
+ init_file.txt | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/init_file.txt b/init_file.txt
+index 86e041d..e2994c5 100644
+--- a/init_file.txt
++++ b/init_file.txt
+@@ -1,3 +1,2 @@
+-foo
+ bar
+ baz
+-- 
+2.41.0.640.ga95def55d0-goog
+
diff --git a/libchrome_tools/testdata/change_header_test.cc b/libchrome_tools/testdata/change_header_test.cc
new file mode 100644
index 0000000..f9579b2
--- /dev/null
+++ b/libchrome_tools/testdata/change_header_test.cc
@@ -0,0 +1,20 @@
+// Copyright 2020 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "change_header.h"
+
+#include <memory>
+
+extern "C" {
+#include <vboot/vboot_host.h>
+}
+
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/strings/string_util.h>
+#include <brillo/flag_helper.h>
+
+namespace foo {
+
+}  // namespace foo
diff --git a/libchrome_tools/testdata/check-libchrome-test.cc b/libchrome_tools/testdata/check-libchrome-test.cc
new file mode 100644
index 0000000..9c1012f
--- /dev/null
+++ b/libchrome_tools/testdata/check-libchrome-test.cc
@@ -0,0 +1 @@
+// DO_NOT_USE_IN_LIBCHROME
diff --git a/libchrome_tools/uprev b/libchrome_tools/uprev
new file mode 120000
index 0000000..a34d323
--- /dev/null
+++ b/libchrome_tools/uprev
@@ -0,0 +1 @@
+developer-tools/uprev/
\ No newline at end of file
diff --git a/mojo/core/handle_table.h b/mojo/core/handle_table.h
index 545b84b..89c06ef 100644
--- a/mojo/core/handle_table.h
+++ b/mojo/core/handle_table.h
@@ -24,7 +24,6 @@
     : public base::trace_event::MemoryDumpProvider {
  public:
   HandleTable();
-
   HandleTable(const HandleTable&) = delete;
   HandleTable& operator=(const HandleTable&) = delete;
 
diff --git a/mojo/public/cpp/bindings/lib/message_dumper.cc b/mojo/public/cpp/bindings/lib/message_dumper.cc
index 282f3b1..64e1e83 100644
--- a/mojo/public/cpp/bindings/lib/message_dumper.cc
+++ b/mojo/public/cpp/bindings/lib/message_dumper.cc
@@ -28,6 +28,7 @@
   return *dump_directory;
 }
 
+#if 0
 void WriteMessage(uint64_t identifier,
                   const mojo::MessageDumper::MessageEntry& entry) {
   static uint64_t num = 0;
@@ -54,6 +55,7 @@
 
   file.WriteAtCurrentPos(entry.data_bytes);
 }
+#endif
 
 }  // namespace
 
@@ -76,8 +78,9 @@
 MessageDumper::~MessageDumper() {}
 
 bool MessageDumper::Accept(mojo::Message* message) {
+#if 0
   MessageEntry entry(message->data(), message->data_num_bytes(),
-                     message->interface_name(), message->method_name());
+                     "unknown interface", "unknown name");
 
   static base::NoDestructor<scoped_refptr<base::TaskRunner>> task_runner(
       base::ThreadPool::CreateSequencedTaskRunner(
@@ -87,6 +90,7 @@
   (*task_runner)
       ->PostTask(FROM_HERE,
                  base::BindOnce(&WriteMessage, identifier_, std::move(entry)));
+#endif
   return true;
 }
 
diff --git a/mojo/public/cpp/bindings/struct_ptr.h b/mojo/public/cpp/bindings/struct_ptr.h
index 936a821..2c21cc3 100644
--- a/mojo/public/cpp/bindings/struct_ptr.h
+++ b/mojo/public/cpp/bindings/struct_ptr.h
@@ -112,11 +112,13 @@
   explicit operator bool() const { return !is_null(); }
 
   // If T is serialisable into trace, StructPtr<T> is also serialisable.
+#if 0
   template <class U = S>
   typename perfetto::check_traced_value_support<U>::type WriteIntoTrace(
       perfetto::TracedValue&& context) const {
     perfetto::WriteIntoTracedValue(std::move(context), ptr_);
   }
+#endif
 
  private:
   friend class internal::StructPtrWTFHelper<Struct>;
@@ -213,12 +215,14 @@
 
   explicit operator bool() const { return !is_null(); }
 
+#if 0
   // If T is serialisable into trace, StructPtr<T> is also serialisable.
   template <class U = S>
   typename perfetto::check_traced_value_support<U>::type WriteIntoTrace(
       perfetto::TracedValue&& context) const {
     perfetto::WriteIntoTracedValue(std::move(context), get());
   }
+#endif
 
  private:
   friend class internal::InlinedStructPtrWTFHelper<Struct>;
diff --git a/mojo/public/mojom/base/file_path.mojom b/mojo/public/mojom/base/file_path.mojom
index ff2aac6..85f3f5f 100644
--- a/mojo/public/mojom/base/file_path.mojom
+++ b/mojo/public/mojom/base/file_path.mojom
@@ -38,7 +38,13 @@
 // the need to trust any explicit parameters from the renderer process.
 [Stable]
 struct FilePath {
-  [EnableIf=file_path_is_string]
+  // In chrome, ninja have a goal that can define file_path_is_string for a set
+  // of mojom files.
+  // In android we don't have such ability ,one would have to add
+  // "--enable_feature file_path_is_string" to all targets generating pickle
+  //  files, headers and sources, and also in all project including them.
+  // Faster solution was to just remove this "EnableIf" definition in libchrome.
+  // [EnableIf=file_path_is_string]
   string path;
 
   // This duplicates the contents of mojo_base.mojom.String16. String16 isn't
@@ -55,7 +61,13 @@
 // things like IsParent().
 [Stable]
 struct RelativeFilePath {
-  [EnableIf=file_path_is_string]
+  // In chrome, ninja have a goal that can define file_path_is_string for a set
+  // of mojom files.
+  // In android we don't have such ability ,one would have to add
+  // "--enable_feature file_path_is_string" to all targets generating pickle
+  //  files, headers and sources, and also in all project including them.
+  // Faster solution was to just remove this "EnableIf" definition in libchrome.
+  // [EnableIf=file_path_is_string]
   string path;
 
   [EnableIf=file_path_is_string16]
diff --git a/soong/Android.bp b/soong/Android.bp
new file mode 100644
index 0000000..7230b81
--- /dev/null
+++ b/soong/Android.bp
@@ -0,0 +1,14 @@
+bootstrap_go_package {
+    name: "soong-libchrome",
+    pkgPath: "android/soong/external/libchrome",
+    deps: [
+        "blueprint",
+        "soong",
+        "soong-android",
+        "soong-genrule",
+    ],
+    srcs: [
+        "bindings_generator.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/soong/bindings_generator.go b/soong/bindings_generator.go
new file mode 100644
index 0000000..7ff9826
--- /dev/null
+++ b/soong/bindings_generator.go
@@ -0,0 +1,531 @@
+package libchrome
+
+import (
+	"fmt"
+	"path"
+	"strings"
+
+	"android/soong/android"
+	"android/soong/genrule"
+
+	"github.com/google/blueprint"
+)
+
+func init() {
+	android.RegisterModuleType("generate_mojom_downgraded_files", mojomDowngradedFilesFactory)
+	android.RegisterModuleType("generate_mojom_pickles", mojomPicklesFactory)
+	android.RegisterModuleType("generate_mojom_headers", mojomHeadersFactory)
+	android.RegisterModuleType("generate_mojom_srcs", mojomSrcsFactory)
+	android.RegisterModuleType("generate_mojom_srcjar", mojomSrcjarFactory)
+}
+
+var (
+	pctx = android.NewPackageContext("android/soong/external/libchrome")
+
+	mojomBindingsGenerator = pctx.HostBinToolVariable("mojomBindingsGenerator", "mojom_bindings_generator")
+	mojomTypesDowngrader   = pctx.HostBinToolVariable("mojomTypesDowngrader", "mojom_types_downgrader")
+	mergeZips              = pctx.HostBinToolVariable("mergeZips", "merge_zips")
+
+	downgradeMojomTypesRule = pctx.StaticRule("downgradeMojomTypesRule", blueprint.RuleParams{
+		Command: `${mojomTypesDowngrader}
+		${in}
+		--outdir ${outDir}`,
+		CommandDeps: []string{
+			"${mojomTypesDowngrader}",
+		},
+		Description: "Downgrade mojom files $in => $out",
+	}, "outDir")
+
+	generateMojomPicklesRule = pctx.StaticRule("generateMojomPicklesRule", blueprint.RuleParams{
+		Command: `${mojomBindingsGenerator}
+		--use_bundled_pylibs parse
+		-d ${package}
+		${flags}
+		-o ${outDir}
+		${in}`,
+		CommandDeps: []string{
+			"${mojomBindingsGenerator}",
+		},
+		Description: "Mojo pickles generation $in => $out",
+		Restat:      true,
+	}, "package", "flags", "outDir")
+
+	generateMojomSrcsRule = pctx.StaticRule("generateMojomSrcsRule", blueprint.RuleParams{
+		Command: `${mojomBindingsGenerator}
+		--use_bundled_pylibs generate
+		-o ${outDir}
+		-I=${package}:${package}
+		-d ${package}
+		${flags}
+		--bytecode_path=${templateDir}
+		--generators=${mojomGenerator}
+		--use_new_wrapper_types
+		${in}`,
+		CommandDeps: []string{
+			"${mojomBindingsGenerator}",
+		},
+		Description: "Mojo sources generation $in => $out",
+		Restat:      true,
+	}, "mojomGenerator", "package", "flags", "outDir", "templateDir")
+
+	mergeSrcjarsRule = pctx.StaticRule("mergeSrcjarsRule", blueprint.RuleParams{
+		Command: "${mergeZips} ${out} ${in}",
+		CommandDeps: []string{
+			"${mergeZips}",
+		},
+		Description: "Merge .srcjars $in => $out",
+	})
+)
+
+type mojomDowngradedFilesProperties struct {
+	// list of input files
+	Srcs []string
+}
+
+type mojomDowngradedFiles struct {
+	android.ModuleBase
+
+	properties mojomDowngradedFilesProperties
+
+	generatedSrcs android.Paths
+	outDir        android.Path
+}
+
+var _ genrule.SourceFileGenerator = (*mojomDowngradedFiles)(nil)
+
+func (m *mojomDowngradedFiles) DepsMutator(ctx android.BottomUpMutatorContext) {
+	android.ExtractSourcesDeps(ctx, m.properties.Srcs)
+}
+
+func (m *mojomDowngradedFiles) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	m.outDir = android.PathForModuleGen(ctx, "")
+
+	for _, in := range ctx.ExpandSources(m.properties.Srcs, nil) {
+		if !strings.HasSuffix(in.Rel(), ".mojom") {
+			ctx.PropertyErrorf("srcs", "Source is not a .mojom file: %s", in.Rel())
+			continue
+		}
+
+		out := android.PathForModuleGen(ctx, in.Rel())
+		m.generatedSrcs = append(m.generatedSrcs, out)
+
+		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+			Rule:   downgradeMojomTypesRule,
+			Input:  in,
+			Output: out,
+			Args: map[string]string{
+				"outDir":  path.Dir(out.String()),
+			},
+		})
+	}
+}
+
+func (m *mojomDowngradedFiles) GeneratedHeaderDirs() android.Paths {
+	return nil
+}
+
+func (m *mojomDowngradedFiles) GeneratedDeps() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomDowngradedFiles) GeneratedSourceFiles() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomDowngradedFiles) Srcs() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func mojomDowngradedFilesFactory() android.Module {
+	m := &mojomDowngradedFiles{}
+	m.AddProperties(&m.properties)
+	android.InitAndroidModule(m)
+	return m
+}
+
+type mojomPicklesProperties struct {
+	// list of input files
+	Srcs []string
+}
+
+type mojomPickles struct {
+	android.ModuleBase
+
+	properties mojomPicklesProperties
+
+	generatedSrcs android.Paths
+	outDir        android.Path
+}
+
+var _ genrule.SourceFileGenerator = (*mojomPickles)(nil)
+
+func (m *mojomPickles) DepsMutator(ctx android.BottomUpMutatorContext) {
+	android.ExtractSourcesDeps(ctx, m.properties.Srcs)
+}
+
+func (m *mojomPickles) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	m.outDir = android.PathForModuleGen(ctx, "")
+
+	for _, in := range ctx.ExpandSources(m.properties.Srcs, nil) {
+		if !strings.HasSuffix(in.Rel(), ".mojom") {
+			ctx.PropertyErrorf("srcs", "Source is not a .mojom file: %s", in.Rel())
+			continue
+		}
+
+		srcRoot := strings.TrimSuffix(in.String(), in.Rel())
+
+		relStem := strings.TrimSuffix(in.Rel(), ".mojom")
+
+		out := android.PathForModuleGen(ctx, relStem+".p")
+		m.generatedSrcs = append(m.generatedSrcs, out)
+
+		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+			Rule:   generateMojomPicklesRule,
+			Input:  in,
+			Output: out,
+			Args: map[string]string{
+				"package": srcRoot,
+				"outDir":  m.outDir.String(),
+			},
+		})
+	}
+}
+
+func (m *mojomPickles) GeneratedHeaderDirs() android.Paths {
+	return nil
+}
+
+func (m *mojomPickles) GeneratedDeps() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomPickles) GeneratedSourceFiles() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomPickles) Srcs() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func mojomPicklesFactory() android.Module {
+	m := &mojomPickles{}
+	m.AddProperties(&m.properties)
+	android.InitAndroidModule(m)
+	return m
+}
+
+// mojomGenerationProperties are the common properties across the header,
+// source and Java source modules.
+type mojomGenerationProperties struct {
+	// list of input files
+	Srcs []string
+
+	// name of the output .srcjar
+	Srcjar string
+
+	// name of the templates module
+	Templates string
+
+	// Additional flags to pass to the bindings generation script
+	Flags string
+
+	// list of pickles modules that will be imported
+	Pickles []string
+
+	// list of include paths
+	Includes []string
+
+	// list of typemaps modules that will be imported
+	Typemaps []string
+
+	// If true, set --use_once_callback flag to the generator.
+	// This works only on C++ generation.
+	Use_once_callback bool
+}
+
+// extractSources adds any necessary dependencies to satisfy filegroup or
+// generated sources modules listed in the properties using ":module" syntax,
+// if any.
+func (p *mojomGenerationProperties) extractSources(ctx android.BottomUpMutatorContext) {
+	android.ExtractSourcesDeps(ctx, p.Srcs)
+	android.ExtractSourcesDeps(ctx, p.Typemaps)
+	android.ExtractSourcesDeps(ctx, p.Pickles)
+	android.ExtractSourceDeps(ctx, &p.Templates)
+}
+
+// flags generates all needed flags for the build rule.
+func (p *mojomGenerationProperties) flags(ctx android.ModuleContext) string {
+	flags := []string{}
+
+	for _, typemap := range ctx.ExpandSources(p.Typemaps, nil) {
+		flags = append(flags, fmt.Sprintf("--typemap=%s", typemap.String()))
+	}
+	for _, include := range android.PathsForSource(ctx, p.Includes) {
+		flags = append(flags, fmt.Sprintf("-I=%s:%s", include, include))
+	}
+	for _, pickle := range p.Pickles {
+		m := android.SrcIsModule(pickle)
+		if m == "" {
+			ctx.PropertyErrorf("pickles", "not a module: %q", m)
+			continue
+		}
+		module := ctx.GetDirectDepWithTag(m, android.SourceDepTag).(*mojomPickles)
+		flags = append(flags, fmt.Sprintf("--gen_dir=%s", module.outDir.String()))
+	}
+	if p.Flags != "" {
+		flags = append(flags, p.Flags)
+	}
+	if p.Use_once_callback {
+		flags = append(flags, "--use_once_callback")
+	}
+
+	return strings.Join(flags, " ")
+}
+
+// implicitDeps collects all dependencies of the module.
+func (p *mojomGenerationProperties) implicitDeps(ctx android.ModuleContext) android.Paths {
+	deps := android.Paths{}
+	deps = append(deps, ctx.ExpandSources(p.Pickles, nil)...)
+	deps = append(deps, ctx.ExpandSources(p.Typemaps, nil)...)
+	deps = append(deps, ctx.ExpandSources([]string{p.Templates}, nil)...)
+	return deps
+}
+
+// templateDir returns the path where the template .zips are located.
+func (p *mojomGenerationProperties) templateDir(ctx android.ModuleContext) string {
+	srcFiles := ctx.ExpandSources([]string{p.Templates}, nil)
+	if len(srcFiles) == 0 {
+		ctx.PropertyErrorf("templates", "module %s does not produce any files", p.Templates)
+		return ""
+	}
+	return path.Dir(srcFiles[0].String())
+}
+
+// mojomSrcsRuleDescription has the necessary arguments to perform one
+// invocation of generateMojomSrcsRule.
+type mojomSrcsRuleDescription struct {
+	generatedExtensions []string
+	extraFlags          string
+}
+
+// generateBuildActions generates all the necessary build actions for the
+// current module.
+func (p *mojomGenerationProperties) generateBuildActions(
+	ctx android.ModuleContext,
+	mojomGenerator string,
+	descriptions []mojomSrcsRuleDescription,
+) android.Paths {
+	outDir := android.PathForModuleGen(ctx, "")
+	implicitDeps := p.implicitDeps(ctx)
+	templateDir := p.templateDir(ctx)
+	generatedSrcs := android.Paths{}
+
+	for _, in := range ctx.ExpandSources(p.Srcs, nil) {
+		if !strings.HasSuffix(in.Rel(), ".mojom") {
+			ctx.PropertyErrorf("srcs", "Source is not a .mojom file: %s", in.Rel())
+			continue
+		}
+		relStem := strings.TrimSuffix(in.Rel(), ".mojom")
+		srcRoot := strings.TrimSuffix(in.String(), in.Rel())
+
+		for _, description := range descriptions {
+			outs := android.WritablePaths{}
+			for _, ext := range description.generatedExtensions {
+				out := android.PathForModuleGen(ctx, relStem+ext)
+				outs = append(outs, out)
+				generatedSrcs = append(generatedSrcs, out)
+			}
+			ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+				Rule:      generateMojomSrcsRule,
+				Input:     in,
+				Implicits: implicitDeps,
+				Outputs:   outs,
+				Args: map[string]string{
+					"mojomGenerator": mojomGenerator,
+					"package":        srcRoot,
+					"flags":          fmt.Sprintf("%s %s", p.flags(ctx), description.extraFlags),
+					"outDir":         outDir.String(),
+					"templateDir":    templateDir,
+				},
+			})
+		}
+	}
+
+	return generatedSrcs
+}
+
+// mojomHeaders generates all the .h files for a .mojom source.
+type mojomHeaders struct {
+	android.ModuleBase
+
+	properties mojomGenerationProperties
+
+	exportedHeaderDirs android.Paths
+	generatedSrcs      android.Paths
+}
+
+var _ genrule.SourceFileGenerator = (*mojomHeaders)(nil)
+
+func (m *mojomHeaders) DepsMutator(ctx android.BottomUpMutatorContext) {
+	m.properties.extractSources(ctx)
+}
+
+func (m *mojomHeaders) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	m.generatedSrcs = m.properties.generateBuildActions(
+		ctx,
+		"c++",
+		[]mojomSrcsRuleDescription{
+			{
+				generatedExtensions: []string{".mojom.h"},
+				extraFlags:          "",
+			},
+			{
+				generatedExtensions: []string{".mojom-shared.h", ".mojom-shared-internal.h"},
+				extraFlags:          "--generate_non_variant_code",
+			},
+			{
+				generatedExtensions: []string{".mojom-shared-message-ids.h"},
+				extraFlags:          "--generate_message_ids --generate_non_variant_code",
+			},
+		},
+	)
+	m.exportedHeaderDirs = append(m.exportedHeaderDirs, android.PathForModuleGen(ctx, ""))
+}
+
+func (m *mojomHeaders) GeneratedHeaderDirs() android.Paths {
+	return m.exportedHeaderDirs
+}
+
+func (m *mojomHeaders) GeneratedDeps() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomHeaders) GeneratedSourceFiles() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomHeaders) Srcs() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func mojomHeadersFactory() android.Module {
+	m := &mojomHeaders{}
+	m.AddProperties(&m.properties)
+	android.InitAndroidModule(m)
+	return m
+}
+
+// mojomHeaders generates all the .cc files for a .mojom source.
+type mojomSrcs struct {
+	android.ModuleBase
+
+	properties mojomGenerationProperties
+
+	generatedSrcs android.Paths
+}
+
+var _ genrule.SourceFileGenerator = (*mojomSrcs)(nil)
+
+func (m *mojomSrcs) DepsMutator(ctx android.BottomUpMutatorContext) {
+	m.properties.extractSources(ctx)
+}
+
+func (m *mojomSrcs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	m.generatedSrcs = m.properties.generateBuildActions(
+		ctx,
+		"c++",
+		[]mojomSrcsRuleDescription{
+			{
+				generatedExtensions: []string{".mojom.cc"},
+				extraFlags:          "",
+			},
+			{
+				generatedExtensions: []string{".mojom-shared.cc"},
+				extraFlags:          "--generate_non_variant_code",
+			},
+		},
+	)
+}
+
+func (m *mojomSrcs) GeneratedHeaderDirs() android.Paths {
+	return nil
+}
+
+func (m *mojomSrcs) GeneratedDeps() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomSrcs) GeneratedSourceFiles() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomSrcs) Srcs() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func mojomSrcsFactory() android.Module {
+	m := &mojomSrcs{}
+	m.AddProperties(&m.properties)
+	android.InitAndroidModule(m)
+	return m
+}
+
+// mojomHeaders generates the .srcjar file for a set of .mojom source.
+type mojomSrcjar struct {
+	android.ModuleBase
+
+	properties mojomGenerationProperties
+
+	outDir        android.Path
+	generatedSrcs android.Paths
+}
+
+var _ genrule.SourceFileGenerator = (*mojomSrcjar)(nil)
+
+func (m *mojomSrcjar) DepsMutator(ctx android.BottomUpMutatorContext) {
+	m.properties.extractSources(ctx)
+}
+
+func (m *mojomSrcjar) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	srcjars := m.properties.generateBuildActions(
+		ctx,
+		"java",
+		[]mojomSrcsRuleDescription{
+			{
+				generatedExtensions: []string{".mojom.srcjar"},
+				extraFlags:          "",
+			},
+		},
+	)
+
+	out := android.PathForModuleGen(ctx, m.properties.Srcjar)
+	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
+		Rule:   mergeSrcjarsRule,
+		Inputs: srcjars,
+		Output: out,
+	})
+	m.generatedSrcs = append(m.generatedSrcs, out)
+}
+
+func (m *mojomSrcjar) GeneratedHeaderDirs() android.Paths {
+	return nil
+}
+
+func (m *mojomSrcjar) GeneratedDeps() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomSrcjar) GeneratedSourceFiles() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func (m *mojomSrcjar) Srcs() android.Paths {
+	return append(android.Paths{}, m.generatedSrcs...)
+}
+
+func mojomSrcjarFactory() android.Module {
+	m := &mojomSrcjar{}
+	m.AddProperties(&m.properties)
+	android.InitAndroidModule(m)
+	return m
+}
diff --git a/testing/gmock/include/gmock/gmock-matchers.h b/testing/gmock/include/gmock/gmock-matchers.h
new file mode 100644
index 0000000..6472746
--- /dev/null
+++ b/testing/gmock/include/gmock/gmock-matchers.h
@@ -0,0 +1 @@
+#include <gmock/gmock-matchers.h>
diff --git a/testing/gmock/include/gmock/gmock.h b/testing/gmock/include/gmock/gmock.h
new file mode 100644
index 0000000..9678b68
--- /dev/null
+++ b/testing/gmock/include/gmock/gmock.h
@@ -0,0 +1 @@
+#include <gmock/gmock.h>
diff --git a/testing/gtest/include/gtest/gtest.h b/testing/gtest/include/gtest/gtest.h
new file mode 100644
index 0000000..2180533
--- /dev/null
+++ b/testing/gtest/include/gtest/gtest.h
@@ -0,0 +1 @@
+#include <gtest/gtest.h>
diff --git a/testing/gtest/include/gtest/gtest_prod.h b/testing/gtest/include/gtest/gtest_prod.h
new file mode 100644
index 0000000..00174fc
--- /dev/null
+++ b/testing/gtest/include/gtest/gtest_prod.h
@@ -0,0 +1 @@
+#include <gtest/gtest_prod.h>
diff --git a/testrunner.cc b/testrunner.cc
new file mode 100644
index 0000000..07117a5
--- /dev/null
+++ b/testrunner.cc
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 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 <gtest/gtest.h>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+
+int main(int argc, char** argv) {
+  base::AtExitManager at_exit_manager;
+  base::CommandLine::Init(argc, argv);
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/third_party/abseil-cpp/absl/base/attributes.h b/third_party/abseil-cpp/absl/base/attributes.h
new file mode 100644
index 0000000..7709117
--- /dev/null
+++ b/third_party/abseil-cpp/absl/base/attributes.h
@@ -0,0 +1 @@
+#include <absl/base/attributes.h>
diff --git a/third_party/abseil-cpp/absl/base/dynamic_annotations.h b/third_party/abseil-cpp/absl/base/dynamic_annotations.h
new file mode 100644
index 0000000..dec1cb8
--- /dev/null
+++ b/third_party/abseil-cpp/absl/base/dynamic_annotations.h
@@ -0,0 +1,5 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <absl/base/dynamic_annotations.h>
diff --git a/third_party/abseil-cpp/absl/base/internal/raw_logging.h b/third_party/abseil-cpp/absl/base/internal/raw_logging.h
new file mode 100644
index 0000000..8180b89
--- /dev/null
+++ b/third_party/abseil-cpp/absl/base/internal/raw_logging.h
@@ -0,0 +1 @@
+#include <absl/base/internal/raw_logging.h>
diff --git a/third_party/abseil-cpp/absl/base/macros.h b/third_party/abseil-cpp/absl/base/macros.h
new file mode 100644
index 0000000..8566d96
--- /dev/null
+++ b/third_party/abseil-cpp/absl/base/macros.h
@@ -0,0 +1 @@
+#include <absl/base/macros.h>
diff --git a/third_party/abseil-cpp/absl/base/optimization.h b/third_party/abseil-cpp/absl/base/optimization.h
new file mode 100644
index 0000000..d23bed5
--- /dev/null
+++ b/third_party/abseil-cpp/absl/base/optimization.h
@@ -0,0 +1 @@
+#include <absl/base/optimization.h>
diff --git a/third_party/abseil-cpp/absl/base/thread_annotations.h b/third_party/abseil-cpp/absl/base/thread_annotations.h
new file mode 100644
index 0000000..22a3491
--- /dev/null
+++ b/third_party/abseil-cpp/absl/base/thread_annotations.h
@@ -0,0 +1 @@
+#include <absl/base/thread_annotations.h>
diff --git a/third_party/abseil-cpp/absl/cleanup/cleanup.h b/third_party/abseil-cpp/absl/cleanup/cleanup.h
new file mode 100644
index 0000000..b07005f
--- /dev/null
+++ b/third_party/abseil-cpp/absl/cleanup/cleanup.h
@@ -0,0 +1 @@
+#include <absl/cleanup/cleanup.h>
diff --git a/third_party/abseil-cpp/absl/container/fixed_array.h b/third_party/abseil-cpp/absl/container/fixed_array.h
new file mode 100644
index 0000000..09b8a72
--- /dev/null
+++ b/third_party/abseil-cpp/absl/container/fixed_array.h
@@ -0,0 +1,5 @@
+// Copyright 2024 The ChromiumOS Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <absl/container/fixed_array.h>
diff --git a/third_party/abseil-cpp/absl/container/flat_hash_map.h b/third_party/abseil-cpp/absl/container/flat_hash_map.h
new file mode 100644
index 0000000..9109e0d
--- /dev/null
+++ b/third_party/abseil-cpp/absl/container/flat_hash_map.h
@@ -0,0 +1 @@
+#include <absl/container/flat_hash_map.h>
diff --git a/third_party/abseil-cpp/absl/container/flat_hash_set.h b/third_party/abseil-cpp/absl/container/flat_hash_set.h
new file mode 100644
index 0000000..ef0c7f6
--- /dev/null
+++ b/third_party/abseil-cpp/absl/container/flat_hash_set.h
@@ -0,0 +1 @@
+#include <absl/container/flat_hash_set.h>
diff --git a/third_party/abseil-cpp/absl/container/hash_container_defaults.h b/third_party/abseil-cpp/absl/container/hash_container_defaults.h
new file mode 100644
index 0000000..6e46fad
--- /dev/null
+++ b/third_party/abseil-cpp/absl/container/hash_container_defaults.h
@@ -0,0 +1 @@
+#include <absl/container/hash_container_defaults.h>
diff --git a/third_party/abseil-cpp/absl/container/inlined_vector.h b/third_party/abseil-cpp/absl/container/inlined_vector.h
new file mode 100644
index 0000000..c22d7e9
--- /dev/null
+++ b/third_party/abseil-cpp/absl/container/inlined_vector.h
@@ -0,0 +1 @@
+#include <absl/container/inlined_vector.h>
diff --git a/third_party/abseil-cpp/absl/functional/function_ref.h b/third_party/abseil-cpp/absl/functional/function_ref.h
new file mode 100644
index 0000000..2b74bd9
--- /dev/null
+++ b/third_party/abseil-cpp/absl/functional/function_ref.h
@@ -0,0 +1 @@
+#include <absl/functional/function_ref.h>
diff --git a/third_party/abseil-cpp/absl/meta/type_traits.h b/third_party/abseil-cpp/absl/meta/type_traits.h
new file mode 100644
index 0000000..9aa7fe1
--- /dev/null
+++ b/third_party/abseil-cpp/absl/meta/type_traits.h
@@ -0,0 +1 @@
+#include <absl/meta/type_traits.h>
diff --git a/third_party/abseil-cpp/absl/numeric/bits.h b/third_party/abseil-cpp/absl/numeric/bits.h
new file mode 100644
index 0000000..daa6ec9
--- /dev/null
+++ b/third_party/abseil-cpp/absl/numeric/bits.h
@@ -0,0 +1 @@
+#include <absl/numeric/bits.h>
diff --git a/third_party/abseil-cpp/absl/strings/ascii.h b/third_party/abseil-cpp/absl/strings/ascii.h
new file mode 100644
index 0000000..59b1bf6
--- /dev/null
+++ b/third_party/abseil-cpp/absl/strings/ascii.h
@@ -0,0 +1 @@
+#include <absl/strings/ascii.h>
diff --git a/third_party/abseil-cpp/absl/strings/str_cat.h b/third_party/abseil-cpp/absl/strings/str_cat.h
new file mode 100644
index 0000000..ef24848
--- /dev/null
+++ b/third_party/abseil-cpp/absl/strings/str_cat.h
@@ -0,0 +1 @@
+#include <absl/strings/str_cat.h>
diff --git a/third_party/abseil-cpp/absl/strings/str_format.h b/third_party/abseil-cpp/absl/strings/str_format.h
new file mode 100644
index 0000000..ce48e1c
--- /dev/null
+++ b/third_party/abseil-cpp/absl/strings/str_format.h
@@ -0,0 +1 @@
+#include <absl/strings/str_format.h>
diff --git a/third_party/abseil-cpp/absl/synchronization/mutex.h b/third_party/abseil-cpp/absl/synchronization/mutex.h
new file mode 100644
index 0000000..87e88a0
--- /dev/null
+++ b/third_party/abseil-cpp/absl/synchronization/mutex.h
@@ -0,0 +1 @@
+#include <absl/synchronization/mutex.h>
diff --git a/third_party/abseil-cpp/absl/types/optional.h b/third_party/abseil-cpp/absl/types/optional.h
new file mode 100644
index 0000000..990d98b
--- /dev/null
+++ b/third_party/abseil-cpp/absl/types/optional.h
@@ -0,0 +1 @@
+#include <absl/types/optional.h>
diff --git a/third_party/abseil-cpp/absl/types/span.h b/third_party/abseil-cpp/absl/types/span.h
new file mode 100644
index 0000000..8ae183e
--- /dev/null
+++ b/third_party/abseil-cpp/absl/types/span.h
@@ -0,0 +1 @@
+#include <absl/types/span.h>
diff --git a/third_party/abseil-cpp/absl/types/variant.h b/third_party/abseil-cpp/absl/types/variant.h
new file mode 100644
index 0000000..888b622
--- /dev/null
+++ b/third_party/abseil-cpp/absl/types/variant.h
@@ -0,0 +1 @@
+#include <absl/types/variant.h>
diff --git a/third_party/abseil-cpp/absl/utility/utility.h b/third_party/abseil-cpp/absl/utility/utility.h
new file mode 100644
index 0000000..d59100b
--- /dev/null
+++ b/third_party/abseil-cpp/absl/utility/utility.h
@@ -0,0 +1 @@
+#include <absl/utility/utility.h>
diff --git a/third_party/ashmem/ashmem.h b/third_party/ashmem/ashmem.h
new file mode 100644
index 0000000..7a26a18
--- /dev/null
+++ b/third_party/ashmem/ashmem.h
@@ -0,0 +1,32 @@
+// Copyright (C) 2018 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.
+
+// third_party/ashmem is Android shared memory. Instead of clone it here,
+// use cutils/ashmem.h directly.
+#include <cutils/ashmem.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+inline int ashmem_get_prot_region(int fd) {
+  int ret = ashmem_valid(fd);
+  if (ret < 0)
+    return ret;
+  return TEMP_FAILURE_RETRY(ioctl(fd, ASHMEM_GET_PROT_MASK));
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/third_party/ipcz/src/disable_api.cc b/third_party/ipcz/src/disable_api.cc
new file mode 100644
index 0000000..7b6127a
--- /dev/null
+++ b/third_party/ipcz/src/disable_api.cc
@@ -0,0 +1,18 @@
+// Copyright 2024 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(crbug.com/41494930): remove this file once ipcz is enabled on ChromeOS.
+
+// This file is only compiled if the `ipcz` USE flag is disabled,
+// to conditionally disable IPCz in libchrome.
+
+#include "api.h"
+
+extern "C" {
+
+IPCZ_EXPORT IpczResult IPCZ_API IpczGetAPI(IpczAPI* api) {
+  return IPCZ_RESULT_UNKNOWN;
+};
+
+}  // namespace "C"
diff --git a/third_party/libevent/event.h b/third_party/libevent/event.h
new file mode 100644
index 0000000..d47d797
--- /dev/null
+++ b/third_party/libevent/event.h
@@ -0,0 +1,10 @@
+// The Chromium build contains its own checkout of libevent. This stub is used
+// when building the Chrome OS or Android libchrome package to instead use the
+// system headers.
+#if defined(__ANDROID__) || defined(__ANDROID_HOST__)
+#include <event2/event.h>
+#include <event2/event_compat.h>
+#include <event2/event_struct.h>
+#else
+#include <event.h>
+#endif
diff --git a/third_party/modp_b64/modp_b64.h b/third_party/modp_b64/modp_b64.h
new file mode 100644
index 0000000..2079e1a
--- /dev/null
+++ b/third_party/modp_b64/modp_b64.h
@@ -0,0 +1,22 @@
+// Copyright (C) 2018 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.
+
+// Redirect to system header.
+#include <modp_b64/modp_b64.h>
+
+#include <limits.h>
+
+#ifndef MODP_B64_MAX_INPUT_LEN
+#define MODP_B64_MAX_INPUT_LEN ((SIZE_MAX - 1) / 4 * 3)
+#endif
diff --git a/third_party/perfetto/include/perfetto/base/task_runner.h b/third_party/perfetto/include/perfetto/base/task_runner.h
new file mode 100644
index 0000000..0d0c6cf
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/base/task_runner.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_BASE_TASK_RUNNER_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_BASE_TASK_RUNNER_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_BASE_TASK_RUNNER_H_
diff --git a/third_party/perfetto/include/perfetto/base/thread_utils.h b/third_party/perfetto/include/perfetto/base/thread_utils.h
new file mode 100644
index 0000000..bfd6f0a
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/base/thread_utils.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_BASE_THREAD_UTILS_H_
diff --git a/third_party/perfetto/include/perfetto/base/time.h b/third_party/perfetto/include/perfetto/base/time.h
new file mode 100644
index 0000000..dc5fa3f
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/base/time.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_BASE_TIME_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_BASE_TIME_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_BASE_TIME_H_
diff --git a/third_party/perfetto/include/perfetto/ext/base/thread_task_runner.h b/third_party/perfetto/include/perfetto/ext/base/thread_task_runner.h
new file mode 100644
index 0000000..57184be
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/ext/base/thread_task_runner.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_EXT_BASE_THREAD_TASK_RUNNER_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_EXT_BASE_THREAD_TASK_RUNNER_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_EXT_BASE_THREAD_TASK_RUNNER_H_
diff --git a/third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h b/third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h
new file mode 100644
index 0000000..4ca2256
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_EXPORT_JSON_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_EXPORT_JSON_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_EXT_TRACE_PROCESSOR_EXPORT_JSON_H_
diff --git a/third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h b/third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h
new file mode 100644
index 0000000..3191656
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/protozero/contiguous_memory_range.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_CONTIGUOUS_MEMORY_RANGE_H_
diff --git a/third_party/perfetto/include/perfetto/protozero/field_writer.h b/third_party/perfetto/include/perfetto/protozero/field_writer.h
new file mode 100644
index 0000000..d876311
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/protozero/field_writer.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_FIELD_WRITER_H_
diff --git a/third_party/perfetto/include/perfetto/protozero/message.h b/third_party/perfetto/include/perfetto/protozero/message.h
new file mode 100644
index 0000000..76de78d
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/protozero/message.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_MESSAGE_H_
diff --git a/third_party/perfetto/include/perfetto/protozero/message_handle.h b/third_party/perfetto/include/perfetto/protozero/message_handle.h
new file mode 100644
index 0000000..e6712d4
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/protozero/message_handle.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_MESSAGE_HANDLE_H_
diff --git a/third_party/perfetto/include/perfetto/protozero/packed_repeated_fields.h b/third_party/perfetto/include/perfetto/protozero/packed_repeated_fields.h
new file mode 100644
index 0000000..965722f
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/protozero/packed_repeated_fields.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_PACKED_REPEATED_FIELDS_H_
diff --git a/third_party/perfetto/include/perfetto/protozero/proto_decoder.h b/third_party/perfetto/include/perfetto/protozero/proto_decoder.h
new file mode 100644
index 0000000..2593906
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/protozero/proto_decoder.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_PROTO_DECODER_H_
diff --git a/third_party/perfetto/include/perfetto/protozero/proto_utils.h b/third_party/perfetto/include/perfetto/protozero/proto_utils.h
new file mode 100644
index 0000000..6a015b5
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/protozero/proto_utils.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_PROTO_UTILS_H_
diff --git a/third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h b/third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h
new file mode 100644
index 0000000..a8d534a
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_PROTOZERO_SCATTERED_HEAP_BUFFER_H_
diff --git a/third_party/perfetto/include/perfetto/test/traced_value_test_support.h b/third_party/perfetto/include/perfetto/test/traced_value_test_support.h
new file mode 100644
index 0000000..659e15b
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/test/traced_value_test_support.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TEST_TRACED_VALUE_TEST_SUPPORT_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TEST_TRACED_VALUE_TEST_SUPPORT_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TEST_TRACED_VALUE_TEST_SUPPORT_H_
diff --git a/third_party/perfetto/include/perfetto/trace_processor/trace_processor.h b/third_party/perfetto/include/perfetto/trace_processor/trace_processor.h
new file mode 100644
index 0000000..97d2da3
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/trace_processor/trace_processor.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_H_
diff --git a/third_party/perfetto/include/perfetto/trace_processor/trace_processor_storage.h b/third_party/perfetto/include/perfetto/trace_processor/trace_processor_storage.h
new file mode 100644
index 0000000..60b1a75
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/trace_processor/trace_processor_storage.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACE_PROCESSOR_TRACE_PROCESSOR_STORAGE_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/console_interceptor.h b/third_party/perfetto/include/perfetto/tracing/console_interceptor.h
new file mode 100644
index 0000000..5bf1f1f
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/console_interceptor.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_CONSOLE_INTERCEPTOR_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/core/data_source_config.h b/third_party/perfetto/include/perfetto/tracing/core/data_source_config.h
new file mode 100644
index 0000000..25e78e5
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/core/data_source_config.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_CORE_DATA_SOURCE_CONFIG_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/core/trace_config.h b/third_party/perfetto/include/perfetto/tracing/core/trace_config.h
new file mode 100644
index 0000000..c3e26e9
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/core/trace_config.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_CORE_TRACE_CONFIG_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/event_context.h b/third_party/perfetto/include/perfetto/tracing/event_context.h
new file mode 100644
index 0000000..1586742
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/event_context.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_EVENT_CONTEXT_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h b/third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h
new file mode 100644
index 0000000..0e924e5
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/internal/track_event_internal.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_INTERNAL_TRACK_EVENT_INTERNAL_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/internal/write_track_event_args.h b/third_party/perfetto/include/perfetto/tracing/internal/write_track_event_args.h
new file mode 100644
index 0000000..8210098
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/internal/write_track_event_args.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_INTERNAL_WRITE_TRACK_EVENT_ARGS_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_INTERNAL_WRITE_TRACK_EVENT_ARGS_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_INTERNAL_WRITE_TRACK_EVENT_ARGS_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/platform.h b/third_party/perfetto/include/perfetto/tracing/platform.h
new file mode 100644
index 0000000..72ae590
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/platform.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_PLATFORM_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_PLATFORM_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_PLATFORM_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/string_helpers.h b/third_party/perfetto/include/perfetto/tracing/string_helpers.h
new file mode 100644
index 0000000..d8e11dc
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/string_helpers.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_STRING_HELPERS_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_STRING_HELPERS_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_STRING_HELPERS_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/traced_proto.h b/third_party/perfetto/include/perfetto/tracing/traced_proto.h
new file mode 100644
index 0000000..611435f
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/traced_proto.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_PROTO_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_PROTO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_PROTO_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/traced_value.h b/third_party/perfetto/include/perfetto/tracing/traced_value.h
new file mode 100644
index 0000000..1892c38
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/traced_value.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/traced_value_forward.h b/third_party/perfetto/include/perfetto/tracing/traced_value_forward.h
new file mode 100644
index 0000000..d2a2cf8
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/traced_value_forward.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_VALUE_FORWARD_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_VALUE_FORWARD_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_VALUE_FORWARD_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/tracing.h b/third_party/perfetto/include/perfetto/tracing/tracing.h
new file mode 100644
index 0000000..3f5020d
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/tracing.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACING_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACING_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACING_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/track.h b/third_party/perfetto/include/perfetto/tracing/track.h
new file mode 100644
index 0000000..41a7223
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/track.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/track_event.h b/third_party/perfetto/include/perfetto/tracing/track_event.h
new file mode 100644
index 0000000..71e837f
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/track_event.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_EVENT_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h b/third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h
new file mode 100644
index 0000000..7174752
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/track_event_interned_data_index.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_EVENT_INTERNED_DATA_INDEX_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_EVENT_INTERNED_DATA_INDEX_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_EVENT_INTERNED_DATA_INDEX_H_
diff --git a/third_party/perfetto/include/perfetto/tracing/track_event_legacy.h b/third_party/perfetto/include/perfetto/tracing/track_event_legacy.h
new file mode 100644
index 0000000..8a29d26
--- /dev/null
+++ b/third_party/perfetto/include/perfetto/tracing/track_event_legacy.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_EVENT_LEGACY_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_EVENT_LEGACY_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACK_EVENT_LEGACY_H_
diff --git a/third_party/perfetto/include/protos/perfetto/trace/track_event/debug_annotation.pbzero.h b/third_party/perfetto/include/protos/perfetto/trace/track_event/debug_annotation.pbzero.h
new file mode 100644
index 0000000..28646b1
--- /dev/null
+++ b/third_party/perfetto/include/protos/perfetto/trace/track_event/debug_annotation.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PBZERO_H_
diff --git a/third_party/perfetto/include/protos/perfetto/trace/track_event/source_location.pbzero.h b/third_party/perfetto/include/protos/perfetto/trace/track_event/source_location.pbzero.h
new file mode 100644
index 0000000..25d2f4d
--- /dev/null
+++ b/third_party/perfetto/include/protos/perfetto/trace/track_event/source_location.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PBZERO_H_
diff --git a/third_party/perfetto/include/protos/perfetto/trace/track_event/track_event.pbzero.h b/third_party/perfetto/include/protos/perfetto/trace/track_event/track_event.pbzero.h
new file mode 100644
index 0000000..31872d5
--- /dev/null
+++ b/third_party/perfetto/include/protos/perfetto/trace/track_event/track_event.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_INCLUDE_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_INCLUDE_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_INCLUDE_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/common/builtin_clock.pbzero.h b/third_party/perfetto/protos/perfetto/common/builtin_clock.pbzero.h
new file mode 100644
index 0000000..07c2cf1
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/common/builtin_clock.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_COMMON_BUILTIN_CLOCK_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_COMMON_BUILTIN_CLOCK_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_COMMON_BUILTIN_CLOCK_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/config/chrome/chrome_config.gen.h b/third_party/perfetto/protos/perfetto/config/chrome/chrome_config.gen.h
new file mode 100644
index 0000000..572f6ed
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/config/chrome/chrome_config.gen.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_CHROME_CHROME_CONFIG_GEN_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_CHROME_CHROME_CONFIG_GEN_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_CHROME_CHROME_CONFIG_GEN_H_
diff --git a/third_party/perfetto/protos/perfetto/config/interceptor_config.gen.h b/third_party/perfetto/protos/perfetto/config/interceptor_config.gen.h
new file mode 100644
index 0000000..fcecf9e
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/config/interceptor_config.gen.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_INTERCEPTOR_CONFIG_GEN_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_INTERCEPTOR_CONFIG_GEN_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_INTERCEPTOR_CONFIG_GEN_H_
diff --git a/third_party/perfetto/protos/perfetto/config/trace_config.gen.h b/third_party/perfetto/protos/perfetto/config/trace_config.gen.h
new file mode 100644
index 0000000..7fd4e27
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/config/trace_config.gen.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_GEN_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_GEN_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_TRACE_CONFIG_GEN_H_
diff --git a/third_party/perfetto/protos/perfetto/config/track_event/track_event_config.gen.h b/third_party/perfetto/protos/perfetto/config/track_event/track_event_config.gen.h
new file mode 100644
index 0000000..0cc9ac1
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/config/track_event/track_event_config.gen.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_TRACK_EVENT_TRACK_EVENT_CONFIG_GEN_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_TRACK_EVENT_TRACK_EVENT_CONFIG_GEN_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_CONFIG_TRACK_EVENT_TRACK_EVENT_CONFIG_GEN_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/extension_descriptor.pbzero.h b/third_party/perfetto/protos/perfetto/trace/extension_descriptor.pbzero.h
new file mode 100644
index 0000000..95c997d
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/extension_descriptor.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_EXTENSION_DESCRIPTOR_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_EXTENSION_DESCRIPTOR_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_EXTENSION_DESCRIPTOR_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pb.h b/third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pb.h
new file mode 100644
index 0000000..6141049
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pb.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_INTERNED_DATA_INTERNED_DATA_PB_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_INTERNED_DATA_INTERNED_DATA_PB_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_INTERNED_DATA_INTERNED_DATA_PB_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h b/third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h
new file mode 100644
index 0000000..c7cbd7d
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/interned_data/interned_data.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_INTERNED_DATA_INTERNED_DATA_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_INTERNED_DATA_INTERNED_DATA_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_INTERNED_DATA_INTERNED_DATA_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h b/third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h
new file mode 100644
index 0000000..5fd2859
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/memory_graph.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_MEMORY_GRAPH_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_MEMORY_GRAPH_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_MEMORY_GRAPH_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.h b/third_party/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.h
new file mode 100644
index 0000000..2396626
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/profiling/profile_common.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_PROFILING_PROFILE_COMMON_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_PROFILING_PROFILE_COMMON_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_PROFILING_PROFILE_COMMON_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/trace.pb.h b/third_party/perfetto/protos/perfetto/trace/trace.pb.h
new file mode 100644
index 0000000..a21f5fe
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/trace.pb.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACE_PB_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACE_PB_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACE_PB_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h b/third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h
new file mode 100644
index 0000000..9b7a41a
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACE_PACKET_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACE_PACKET_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACE_PACKET_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/chrome_application_state_info.pbzero.h b/third_party/perfetto/protos/perfetto/trace/track_event/chrome_application_state_info.pbzero.h
new file mode 100644
index 0000000..8997619
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/chrome_application_state_info.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_APPLICATION_STATE_INFO_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_APPLICATION_STATE_INFO_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_APPLICATION_STATE_INFO_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h b/third_party/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h
new file mode 100644
index 0000000..447f70c
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/chrome_legacy_ipc.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LEGACY_IPC_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LEGACY_IPC_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_LEGACY_IPC_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.h b/third_party/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.h
new file mode 100644
index 0000000..4a53494
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MOJO_EVENT_INFO_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MOJO_EVENT_INFO_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_MOJO_EVENT_INFO_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h b/third_party/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h
new file mode 100644
index 0000000..42996b8
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/chrome_process_descriptor.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_PROCESS_DESCRIPTOR_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_PROCESS_DESCRIPTOR_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_CHROME_PROCESS_DESCRIPTOR_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h b/third_party/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h
new file mode 100644
index 0000000..f715325
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_DEBUG_ANNOTATION_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h b/third_party/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h
new file mode 100644
index 0000000..3801098
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/log_message.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_LOG_MESSAGE_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_LOG_MESSAGE_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_LOG_MESSAGE_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.h b/third_party/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.h
new file mode 100644
index 0000000..a9d2615
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/process_descriptor.gen.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PROCESS_DESCRIPTOR_GEN_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PROCESS_DESCRIPTOR_GEN_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_PROCESS_DESCRIPTOR_GEN_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/source_location.pb.h b/third_party/perfetto/protos/perfetto/trace/track_event/source_location.pb.h
new file mode 100644
index 0000000..8347f01
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/source_location.pb.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PB_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PB_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PB_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h b/third_party/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h
new file mode 100644
index 0000000..38eeab5
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/source_location.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_SOURCE_LOCATION_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h b/third_party/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h
new file mode 100644
index 0000000..aac6060
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/task_execution.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TASK_EXECUTION_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TASK_EXECUTION_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TASK_EXECUTION_PBZERO_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.h b/third_party/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.h
new file mode 100644
index 0000000..e16507b
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/thread_descriptor.gen.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_THREAD_DESCRIPTOR_GEN_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_THREAD_DESCRIPTOR_GEN_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_THREAD_DESCRIPTOR_GEN_H_
diff --git a/third_party/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h b/third_party/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h
new file mode 100644
index 0000000..aa1f18c
--- /dev/null
+++ b/third_party/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h
@@ -0,0 +1,11 @@
+// Copyright 2023 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PBZERO_H_
+#define THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PBZERO_H_
+
+// Automatically generated by ./gen_perfetto_headers. Do not edit.
+
+#include <perfetto/perfetto.h>
+
+#endif  // THIRD_PARTY_PERFETTO_PROTOS_PERFETTO_TRACE_TRACK_EVENT_TRACK_EVENT_PBZERO_H_
diff --git a/third_party/protobuf/src/google/protobuf/message_lite.h b/third_party/protobuf/src/google/protobuf/message_lite.h
new file mode 100644
index 0000000..c472844
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/message_lite.h
@@ -0,0 +1 @@
+#include <google/protobuf/message_lite.h>
diff --git a/third_party/re2/src/re2/re2.h b/third_party/re2/src/re2/re2.h
new file mode 100644
index 0000000..9f0f186
--- /dev/null
+++ b/third_party/re2/src/re2/re2.h
@@ -0,0 +1,6 @@
+// Copyright 2019 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Redirect to system header.
+#include <re2/re2.h>
diff --git a/unblocked_terms.txt b/unblocked_terms.txt
new file mode 100644
index 0000000..5e6b1eb
--- /dev/null
+++ b/unblocked_terms.txt
@@ -0,0 +1,17 @@
+# Don't delete this file if you want to keep keyword_check enabled even if it's
+# empty.
+#
+# See repohooks/README.md for more details.
+
+black.?list
+crazy
+dummy
+\bhe\b
+\bher\b
+master
+\bnative
+\b(in)?sane(\b|\d)
+sanity
+slave
+white.?list
+\bwtf