Merge "Also populate lastUpdateMillis in ActivateFlattenedApexesIfPossible" into sc-dev
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index 3d63a44..5356b00 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -141,7 +141,6 @@
     // Do not ever allow this library to be vendor_available as a shared library.
     // It does not have a stable interface.
     name: "libfs_mgr",
-    ramdisk_available: true,
     recovery_available: true,
     defaults: [
         "libfs_mgr_defaults",
@@ -166,7 +165,6 @@
     // It does not have a stable interface.
     name: "libfstab",
     vendor_available: true,
-    ramdisk_available: true,
     recovery_available: true,
     host_supported: true,
     defaults: ["fs_mgr_defaults"],
diff --git a/fs_mgr/libfiemap/Android.bp b/fs_mgr/libfiemap/Android.bp
index b62e33f..1c5872e 100644
--- a/fs_mgr/libfiemap/Android.bp
+++ b/fs_mgr/libfiemap/Android.bp
@@ -20,7 +20,6 @@
 
 cc_library_headers {
     name: "libfiemap_headers",
-    ramdisk_available: true,
     recovery_available: true,
     export_include_dirs: ["include"],
 }
diff --git a/fs_mgr/libfs_avb/Android.bp b/fs_mgr/libfs_avb/Android.bp
index 62493eb..6892025 100644
--- a/fs_mgr/libfs_avb/Android.bp
+++ b/fs_mgr/libfs_avb/Android.bp
@@ -27,7 +27,6 @@
 cc_library_static {
     name: "libfs_avb",
     defaults: ["fs_mgr_defaults"],
-    ramdisk_available: true,
     recovery_available: true,
     host_supported: true,
     export_include_dirs: ["include"],
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index 86ca8f3..7e528b1 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -30,7 +30,6 @@
 cc_library {
     name: "liblp",
     host_supported: true,
-    ramdisk_available: true,
     recovery_available: true,
     defaults: ["fs_mgr_defaults"],
     cppflags: [
diff --git a/fs_mgr/libsnapshot/Android.bp b/fs_mgr/libsnapshot/Android.bp
index aa1f415..6a764e4 100644
--- a/fs_mgr/libsnapshot/Android.bp
+++ b/fs_mgr/libsnapshot/Android.bp
@@ -118,7 +118,6 @@
     native_coverage : true,
     defaults: ["libsnapshot_defaults"],
     srcs: [":libsnapshot_sources"],
-    ramdisk_available: true,
     recovery_available: true,
     cflags: [
         "-DLIBSNAPSHOT_NO_COW_WRITE",
diff --git a/fs_mgr/libstorage_literals/Android.bp b/fs_mgr/libstorage_literals/Android.bp
index fd7ea04..5b07168 100644
--- a/fs_mgr/libstorage_literals/Android.bp
+++ b/fs_mgr/libstorage_literals/Android.bp
@@ -6,7 +6,6 @@
 cc_library_headers {
     name: "libstorage_literals_headers",
     host_supported: true,
-    ramdisk_available: true,
     recovery_available: true,
     export_include_dirs: ["."],
     target: {
diff --git a/init/Android.bp b/init/Android.bp
index d0b58ca..7eeafa2 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -253,32 +253,11 @@
     visibility: ["//packages/modules/Virtualization/microdroid"],
 }
 
-soong_config_module_type {
-    name: "init_first_stage_cc_defaults",
-    module_type: "cc_defaults",
-    config_namespace: "ANDROID",
-    bool_variables: ["BOARD_BUILD_SYSTEM_ROOT_IMAGE", "BOARD_USES_RECOVERY_AS_BOOT"],
-    properties: ["installable"],
-}
-
-// Do not install init_first_stage even with mma if we're system-as-root.
-// Otherwise, it will overwrite the symlink.
-init_first_stage_cc_defaults {
-    name: "init_first_stage_defaults",
-    soong_config_variables: {
-        BOARD_BUILD_SYSTEM_ROOT_IMAGE: {
-            installable: false,
-        },
-        BOARD_USES_RECOVERY_AS_BOOT: {
-            installable: false,
-        },
-    },
-}
-
+// This currently is only for the VM usecase.
+// TODO(jiyong): replace init_first_stage in Android.mk with this
 cc_binary {
-    name: "init_first_stage",
-    stem: "init",
-    defaults: ["init_first_stage_defaults"],
+    name: "init_first_stage_soong",
+    stem: "init_vendor",
 
     srcs: [
         "block_dev_initializer.cpp",
@@ -334,7 +313,6 @@
     ],
 
     static_executable: true,
-    system_shared_libs: [],
 
     cflags: [
         "-Wall",
@@ -385,23 +363,8 @@
 
     sanitize: {
         misc_undefined: ["signed-integer-overflow"],
-
-        // First stage init is weird: it may start without stdout/stderr, and no /proc.
         hwaddress: false,
     },
-
-    // Install adb_debug.prop into debug ramdisk.
-    // This allows adb root on a user build, when debug ramdisk is used.
-    required: ["adb_debug.prop"],
-
-    ramdisk: true,
-
-    install_in_root: true,
-}
-
-phony {
-    name: "init_system",
-    required: ["init_second_stage"],
 }
 
 // Tests
diff --git a/init/Android.mk b/init/Android.mk
index c08fe03..3c7d95a 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -2,6 +2,153 @@
 
 LOCAL_PATH:= $(call my-dir)
 
+-include system/sepolicy/policy_version.mk
+
+# --
+
+ifneq (,$(filter userdebug eng,$(TARGET_BUILD_VARIANT)))
+init_options += \
+    -DALLOW_FIRST_STAGE_CONSOLE=1 \
+    -DALLOW_LOCAL_PROP_OVERRIDE=1 \
+    -DALLOW_PERMISSIVE_SELINUX=1 \
+    -DREBOOT_BOOTLOADER_ON_PANIC=1 \
+    -DWORLD_WRITABLE_KMSG=1 \
+    -DDUMP_ON_UMOUNT_FAILURE=1
+else
+init_options += \
+    -DALLOW_FIRST_STAGE_CONSOLE=0 \
+    -DALLOW_LOCAL_PROP_OVERRIDE=0 \
+    -DALLOW_PERMISSIVE_SELINUX=0 \
+    -DREBOOT_BOOTLOADER_ON_PANIC=0 \
+    -DWORLD_WRITABLE_KMSG=0 \
+    -DDUMP_ON_UMOUNT_FAILURE=0
+endif
+
+ifneq (,$(filter eng,$(TARGET_BUILD_VARIANT)))
+init_options += \
+    -DSHUTDOWN_ZERO_TIMEOUT=1
+else
+init_options += \
+    -DSHUTDOWN_ZERO_TIMEOUT=0
+endif
+
+init_options += -DLOG_UEVENTS=0 \
+    -DSEPOLICY_VERSION=$(POLICYVERS)
+
+init_cflags += \
+    $(init_options) \
+    -Wall -Wextra \
+    -Wno-unused-parameter \
+    -Werror \
+
+# --
+
+# Do not build this even with mmma if we're system-as-root, otherwise it will overwrite the symlink.
+ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
+include $(CLEAR_VARS)
+LOCAL_CPPFLAGS := $(init_cflags)
+LOCAL_SRC_FILES := \
+    block_dev_initializer.cpp \
+    devices.cpp \
+    first_stage_console.cpp \
+    first_stage_init.cpp \
+    first_stage_main.cpp \
+    first_stage_mount.cpp \
+    reboot_utils.cpp \
+    selabel.cpp \
+    selinux.cpp \
+    service_utils.cpp \
+    snapuserd_transition.cpp \
+    switch_root.cpp \
+    uevent_listener.cpp \
+    util.cpp \
+
+LOCAL_MODULE := init_first_stage
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
+LOCAL_MODULE_STEM := init
+
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+
+LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)
+LOCAL_UNSTRIPPED_PATH := $(TARGET_RAMDISK_OUT_UNSTRIPPED)
+
+# Install adb_debug.prop into debug ramdisk.
+# This allows adb root on a user build, when debug ramdisk is used.
+LOCAL_REQUIRED_MODULES := \
+   adb_debug.prop \
+
+# Set up the directories that first stage init mounts on.
+
+my_ramdisk_dirs := \
+    debug_ramdisk \
+    dev \
+    metadata \
+    mnt \
+    proc \
+    second_stage_resources \
+    sys \
+
+LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_RAMDISK_OUT)/,$(my_ramdisk_dirs))
+ifeq (true,$(BOARD_USES_GENERIC_KERNEL_IMAGE))
+    LOCAL_POST_INSTALL_CMD += $(addprefix $(TARGET_RAMDISK_OUT)/first_stage_ramdisk/,$(my_ramdisk_dirs))
+endif
+
+my_ramdisk_dirs :=
+
+LOCAL_STATIC_LIBRARIES := \
+    libc++fs \
+    libfs_avb \
+    libfs_mgr \
+    libfec \
+    libfec_rs \
+    libsquashfs_utils \
+    liblogwrap \
+    libext4_utils \
+    libcrypto_utils \
+    libsparse \
+    libavb \
+    libkeyutils \
+    liblp \
+    libcutils \
+    libbase \
+    liblog \
+    libcrypto_static \
+    libdl \
+    libz \
+    libselinux \
+    libcap \
+    libgsi \
+    libcom.android.sysprop.apex \
+    liblzma \
+    libunwindstack_no_dex \
+    libbacktrace_no_dex \
+    libmodprobe \
+    libext2_uuid \
+    libprotobuf-cpp-lite \
+    libsnapshot_cow \
+    libsnapshot_init \
+    update_metadata-protos \
+    libprocinfo \
+
+LOCAL_SANITIZE := signed-integer-overflow
+# First stage init is weird: it may start without stdout/stderr, and no /proc.
+LOCAL_NOSANITIZE := hwaddress
+include $(BUILD_EXECUTABLE)
+endif
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := init_system
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
+LOCAL_REQUIRED_MODULES := \
+   init_second_stage \
+
+include $(BUILD_PHONY_PACKAGE)
+
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := init_vendor
@@ -9,10 +156,8 @@
 LOCAL_LICENSE_CONDITIONS := notice
 LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
 ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
-ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
 LOCAL_REQUIRED_MODULES := \
    init_first_stage \
 
-endif  # BOARD_USES_RECOVERY_AS_BOOT
-endif  # BOARD_BUILD_SYSTEM_ROOT_IMAGE
+endif
 include $(BUILD_PHONY_PACKAGE)
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
index c8a183b..b33d46d 100644
--- a/libcrypto_utils/Android.bp
+++ b/libcrypto_utils/Android.bp
@@ -21,7 +21,6 @@
 cc_library {
     name: "libcrypto_utils",
     vendor_available: true,
-    ramdisk_available: true,
     recovery_available: true,
     vndk: {
         enabled: true,
diff --git a/libkeyutils/Android.bp b/libkeyutils/Android.bp
index a940b8c..86f68fb 100644
--- a/libkeyutils/Android.bp
+++ b/libkeyutils/Android.bp
@@ -15,7 +15,6 @@
     name: "libkeyutils",
     cflags: ["-Werror"],
     defaults: ["linux_bionic_supported"],
-    ramdisk_available: true,
     recovery_available: true,
     export_include_dirs: ["include/"],
     local_include_dirs: ["include/"],
diff --git a/libmodprobe/Android.bp b/libmodprobe/Android.bp
index 525a880..ba11dc9 100644
--- a/libmodprobe/Android.bp
+++ b/libmodprobe/Android.bp
@@ -8,7 +8,6 @@
         "-Werror",
     ],
     vendor_available: true,
-    ramdisk_available: true,
     recovery_available: true,
     srcs: [
         "libmodprobe.cpp",
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 5c7a75d..c824376 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -224,7 +224,11 @@
  * transferred for the user/group passed as uid/gid before system_server can properly access them.
  */
 static bool MkdirAndChown(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
-    if (mkdir(path.c_str(), mode) == -1 && errno != EEXIST) {
+    if (mkdir(path.c_str(), mode) == -1) {
+        if (errno == EEXIST) {
+            // Directory already exists and permissions have been set at the time it was created
+            return true;
+        }
         return false;
     }
 
diff --git a/rootdir/Android.bp b/rootdir/Android.bp
index e98733a..ae21633 100644
--- a/rootdir/Android.bp
+++ b/rootdir/Android.bp
@@ -45,11 +45,4 @@
     src: "etc/public.libraries.android.txt",
     filename: "public.libraries.txt",
     installable: false,
-}
-
-// adb_debug.prop in debug ramdisk
-prebuilt_root {
-    name: "adb_debug.prop",
-    src: "adb_debug.prop",
-    debug_ramdisk: true,
-}
+}
\ No newline at end of file
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 9b80575..99d8f9a 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -210,4 +210,15 @@
 	$(hide) $(foreach lib,$(PRIVATE_SANITIZER_RUNTIME_LIBRARIES), \
 		echo $(lib) >> $@;)
 
+#######################################
+# adb_debug.prop in debug ramdisk
+include $(CLEAR_VARS)
+LOCAL_MODULE := adb_debug.prop
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_DEBUG_RAMDISK_OUT)
+include $(BUILD_PREBUILT)
+
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 33eb335..ff6460d 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -100,6 +100,7 @@
         "ipc/trusty_keymaster_ipc.cpp",
         "keymint/TrustyKeyMintDevice.cpp",
         "keymint/TrustyKeyMintOperation.cpp",
+        "keymint/TrustyRemotelyProvisionedComponentDevice.cpp",
         "keymint/TrustySecureClock.cpp",
         "keymint/TrustySharedSecret.cpp",
         "keymint/service.cpp",
@@ -118,7 +119,6 @@
         "libtrusty",
     ],
     required: [
-        "RemoteProvisioner",
         "android.hardware.hardware_keystore.xml",
     ],
 }
diff --git a/trusty/keymaster/TrustyKeymaster.cpp b/trusty/keymaster/TrustyKeymaster.cpp
index ef5fc3f..aee3333 100644
--- a/trusty/keymaster/TrustyKeymaster.cpp
+++ b/trusty/keymaster/TrustyKeymaster.cpp
@@ -158,6 +158,16 @@
     }
 }
 
+void TrustyKeymaster::GenerateRkpKey(const GenerateRkpKeyRequest& request,
+                                     GenerateRkpKeyResponse* response) {
+    ForwardCommand(KM_GENERATE_RKP_KEY, request, response);
+}
+
+void TrustyKeymaster::GenerateCsr(const GenerateCsrRequest& request,
+                                  GenerateCsrResponse* response) {
+    ForwardCommand(KM_GENERATE_CSR, request, response);
+}
+
 void TrustyKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
                                             GetKeyCharacteristicsResponse* response) {
     ForwardCommand(KM_GET_KEY_CHARACTERISTICS, request, response);
diff --git a/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h b/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h
index 45ebf7f..35eda45 100644
--- a/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h
+++ b/trusty/keymaster/include/trusty_keymaster/TrustyKeymaster.h
@@ -42,6 +42,8 @@
     void AddRngEntropy(const AddEntropyRequest& request, AddEntropyResponse* response);
     void Configure(const ConfigureRequest& request, ConfigureResponse* response);
     void GenerateKey(const GenerateKeyRequest& request, GenerateKeyResponse* response);
+    void GenerateRkpKey(const GenerateRkpKeyRequest& request, GenerateRkpKeyResponse* response);
+    void GenerateCsr(const GenerateCsrRequest& request, GenerateCsrResponse* response);
     void GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
                                GetKeyCharacteristicsResponse* response);
     void ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response);
diff --git a/trusty/keymaster/include/trusty_keymaster/TrustyRemotelyProvisionedComponentDevice.h b/trusty/keymaster/include/trusty_keymaster/TrustyRemotelyProvisionedComponentDevice.h
new file mode 100644
index 0000000..d544b51
--- /dev/null
+++ b/trusty/keymaster/include/trusty_keymaster/TrustyRemotelyProvisionedComponentDevice.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021, 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/security/keymint/BnRemotelyProvisionedComponent.h>
+#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
+#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
+
+#include <trusty_keymaster/TrustyKeymaster.h>
+
+namespace aidl::android::hardware::security::keymint::trusty {
+
+using ::keymaster::TrustyKeymaster;
+using ::ndk::ScopedAStatus;
+using ::std::shared_ptr;
+
+class TrustyRemotelyProvisionedComponentDevice : public BnRemotelyProvisionedComponent {
+  public:
+    explicit TrustyRemotelyProvisionedComponentDevice(shared_ptr<TrustyKeymaster> impl)
+        : impl_(std::move(impl)) {}
+    virtual ~TrustyRemotelyProvisionedComponentDevice() = default;
+
+    ScopedAStatus getHardwareInfo(RpcHardwareInfo* info) override;
+
+    ScopedAStatus generateEcdsaP256KeyPair(bool testMode, MacedPublicKey* macedPublicKey,
+                                           std::vector<uint8_t>* privateKeyHandle) override;
+
+    ScopedAStatus generateCertificateRequest(bool testMode,
+                                             const std::vector<MacedPublicKey>& keysToSign,
+                                             const std::vector<uint8_t>& endpointEncCertChain,
+                                             const std::vector<uint8_t>& challenge,
+                                             DeviceInfo* deviceInfo, ProtectedData* protectedData,
+                                             std::vector<uint8_t>* keysToSignMac) override;
+
+  private:
+    std::shared_ptr<::keymaster::TrustyKeymaster> impl_;
+};
+
+}  // namespace aidl::android::hardware::security::keymint::trusty
diff --git a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
index 71f3ccf..17fee15 100644
--- a/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
+++ b/trusty/keymaster/include/trusty_keymaster/ipc/keymaster_ipc.h
@@ -56,6 +56,8 @@
     KM_GET_VERSION_2                = (28 << KEYMASTER_REQ_SHIFT),
     KM_EARLY_BOOT_ENDED             = (29 << KEYMASTER_REQ_SHIFT),
     KM_DEVICE_LOCKED                = (30 << KEYMASTER_REQ_SHIFT),
+    KM_GENERATE_RKP_KEY             = (31 << KEYMASTER_REQ_SHIFT),
+    KM_GENERATE_CSR                 = (32 << KEYMASTER_REQ_SHIFT),
 
     // Bootloader/provisioning calls.
     KM_SET_BOOT_PARAMS = (0x1000 << KEYMASTER_REQ_SHIFT),
diff --git a/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp b/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
new file mode 100644
index 0000000..5664829
--- /dev/null
+++ b/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2021, 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 <trusty_keymaster/TrustyRemotelyProvisionedComponentDevice.h>
+
+#include <assert.h>
+#include <variant>
+
+#include <KeyMintUtils.h>
+#include <keymaster/keymaster_configuration.h>
+
+#include <trusty_keymaster/TrustyKeyMintDevice.h>
+
+namespace aidl::android::hardware::security::keymint::trusty {
+
+using keymaster::GenerateCsrRequest;
+using keymaster::GenerateCsrResponse;
+using keymaster::GenerateRkpKeyRequest;
+using keymaster::GenerateRkpKeyResponse;
+using keymaster::KeymasterBlob;
+using ::std::string;
+using ::std::unique_ptr;
+using ::std::vector;
+using bytevec = ::std::vector<uint8_t>;
+
+namespace {
+
+constexpr auto STATUS_FAILED = IRemotelyProvisionedComponent::STATUS_FAILED;
+
+struct AStatusDeleter {
+    void operator()(AStatus* p) { AStatus_delete(p); }
+};
+
+class Status {
+  public:
+    Status() : status_(AStatus_newOk()) {}
+    Status(int32_t errCode, const std::string& errMsg)
+        : status_(AStatus_fromServiceSpecificErrorWithMessage(errCode, errMsg.c_str())) {}
+    explicit Status(const std::string& errMsg)
+        : status_(AStatus_fromServiceSpecificErrorWithMessage(STATUS_FAILED, errMsg.c_str())) {}
+    explicit Status(AStatus* status) : status_(status ? status : AStatus_newOk()) {}
+
+    Status(Status&&) = default;
+    Status(const Status&) = delete;
+
+    operator ::ndk::ScopedAStatus() && {  // NOLINT(google-explicit-constructor)
+        return ndk::ScopedAStatus(status_.release());
+    }
+
+    bool isOk() const { return AStatus_isOk(status_.get()); }
+
+    const char* getMessage() const { return AStatus_getMessage(status_.get()); }
+
+  private:
+    std::unique_ptr<AStatus, AStatusDeleter> status_;
+};
+
+}  // namespace
+
+ScopedAStatus TrustyRemotelyProvisionedComponentDevice::getHardwareInfo(RpcHardwareInfo* info) {
+    info->versionNumber = 1;
+    info->rpcAuthorName = "Google";
+    info->supportedEekCurve = RpcHardwareInfo::CURVE_25519;
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus TrustyRemotelyProvisionedComponentDevice::generateEcdsaP256KeyPair(
+        bool testMode, MacedPublicKey* macedPublicKey, bytevec* privateKeyHandle) {
+    GenerateRkpKeyRequest request(impl_->message_version());
+    request.test_mode = testMode;
+    GenerateRkpKeyResponse response(impl_->message_version());
+    impl_->GenerateRkpKey(request, &response);
+    if (response.error != KM_ERROR_OK) {
+        return Status(-static_cast<int32_t>(response.error), "Failure in key generation.");
+    }
+
+    macedPublicKey->macedKey = km_utils::kmBlob2vector(response.maced_public_key);
+    *privateKeyHandle = km_utils::kmBlob2vector(response.key_blob);
+    return ScopedAStatus::ok();
+}
+
+ScopedAStatus TrustyRemotelyProvisionedComponentDevice::generateCertificateRequest(
+        bool testMode, const vector<MacedPublicKey>& keysToSign,
+        const bytevec& endpointEncCertChain, const bytevec& challenge, DeviceInfo* deviceInfo,
+        ProtectedData* protectedData, bytevec* keysToSignMac) {
+    GenerateCsrRequest request(impl_->message_version());
+    request.test_mode = testMode;
+    request.num_keys = keysToSign.size();
+    request.keys_to_sign_array = new KeymasterBlob[keysToSign.size()];
+    for (size_t i = 0; i < keysToSign.size(); i++) {
+        request.SetKeyToSign(i, keysToSign[i].macedKey.data(), keysToSign[i].macedKey.size());
+    }
+    request.SetEndpointEncCertChain(endpointEncCertChain.data(), endpointEncCertChain.size());
+    request.SetChallenge(challenge.data(), challenge.size());
+    GenerateCsrResponse response(impl_->message_version());
+    impl_->GenerateCsr(request, &response);
+
+    if (response.error != KM_ERROR_OK) {
+        return Status(-static_cast<int32_t>(response.error), "Failure in CSR Generation.");
+    }
+    deviceInfo->deviceInfo = km_utils::kmBlob2vector(response.device_info_blob);
+    protectedData->protectedData = km_utils::kmBlob2vector(response.protected_data_blob);
+    *keysToSignMac = km_utils::kmBlob2vector(response.keys_to_sign_mac);
+    return ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::security::keymint::trusty
diff --git a/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml b/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml
index 0ab3d64..7ca5050 100644
--- a/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml
+++ b/trusty/keymaster/keymint/android.hardware.security.keymint-service.trusty.xml
@@ -11,4 +11,8 @@
         <name>android.hardware.security.sharedsecret</name>
         <fqname>ISharedSecret/default</fqname>
     </hal>
+    <hal format="aidl">
+        <name>android.hardware.security.keymint</name>
+        <fqname>IRemotelyProvisionedComponent/default</fqname>
+    </hal>
 </manifest>
diff --git a/trusty/keymaster/keymint/service.cpp b/trusty/keymaster/keymint/service.cpp
index 8f5f0f8..4060278 100644
--- a/trusty/keymaster/keymint/service.cpp
+++ b/trusty/keymaster/keymint/service.cpp
@@ -20,10 +20,12 @@
 #include <android/binder_process.h>
 
 #include <trusty_keymaster/TrustyKeyMintDevice.h>
+#include <trusty_keymaster/TrustyRemotelyProvisionedComponentDevice.h>
 #include <trusty_keymaster/TrustySecureClock.h>
 #include <trusty_keymaster/TrustySharedSecret.h>
 
 using aidl::android::hardware::security::keymint::trusty::TrustyKeyMintDevice;
+using aidl::android::hardware::security::keymint::trusty::TrustyRemotelyProvisionedComponentDevice;
 using aidl::android::hardware::security::secureclock::trusty::TrustySecureClock;
 using aidl::android::hardware::security::sharedsecret::trusty::TrustySharedSecret;
 
@@ -52,7 +54,8 @@
     auto keyMint = addService<TrustyKeyMintDevice>(trustyKeymaster);
     auto secureClock = addService<TrustySecureClock>(trustyKeymaster);
     auto sharedSecret = addService<TrustySharedSecret>(trustyKeymaster);
-
+    auto remotelyProvisionedComponent =
+            addService<TrustyRemotelyProvisionedComponentDevice>(trustyKeymaster);
     ABinderProcess_joinThreadPool();
     return EXIT_FAILURE;  // should not reach
 }