Split fsverity_init in multiple phases.

Soon we'll have a need for multiple fs-verity keys in the keyring; we
need a central place to manage the keys, as well as restrict the
keyring. fsverity_init makes most sense for this.

Allow fsverity_init to be called in 3 different ways:
--load-verified-keys: loads preloaded keys from trusted partitions
--load-extra-key: loads an additional key passed in from stdin; the key
name is given as an argument.
--lock: locks the keyring, and prevents new keys from being loaded

Bug: 165630556
Test: boot, cat /proc/keys/
Change-Id: I758e49a5c4229edc531d01ac2e8873a22a1da73e
diff --git a/fsverity_init/fsverity_init.cpp b/fsverity_init/fsverity_init.cpp
index 4ed25cd..b81fb22 100644
--- a/fsverity_init/fsverity_init.cpp
+++ b/fsverity_init/fsverity_init.cpp
@@ -37,19 +37,36 @@
     return true;
 }
 
+void LoadKeyFromStdin(key_serial_t keyring_id, const char* keyname) {
+    std::string content;
+    if (!android::base::ReadFdToString(STDIN_FILENO, &content)) {
+        LOG(ERROR) << "Failed to read key from stdin";
+        return;
+    }
+    if (!LoadKeyToKeyring(keyring_id, keyname, content.c_str(), content.size())) {
+        LOG(ERROR) << "Failed to load key from stdin";
+    }
+}
+
+void LoadKeyFromFile(key_serial_t keyring_id, const char* keyname, const std::string& path) {
+    std::string content;
+    if (!android::base::ReadFileToString(path, &content)) {
+        LOG(ERROR) << "Failed to read key from " << path;
+        return;
+    }
+    if (!LoadKeyToKeyring(keyring_id, keyname, content.c_str(), content.size())) {
+        LOG(ERROR) << "Failed to load key from " << path;
+    }
+}
+
 void LoadKeyFromDirectory(key_serial_t keyring_id, const char* keyname, const char* dir) {
     if (!std::filesystem::exists(dir)) {
         return;
     }
     for (const auto& entry : std::filesystem::directory_iterator(dir)) {
         if (!android::base::EndsWithIgnoreCase(entry.path().c_str(), ".der")) continue;
-        std::string content;
-        if (!android::base::ReadFileToString(entry.path(), &content)) {
-            continue;
-        }
-        if (!LoadKeyToKeyring(keyring_id, keyname, content.c_str(), content.size())) {
-            LOG(ERROR) << "Failed to load key from " << entry.path();
-        }
+
+        LoadKeyFromFile(keyring_id, keyname, entry.path());
     }
 }
 
@@ -60,25 +77,44 @@
     LoadKeyFromDirectory(keyring_id, "fsv_product", "/product/etc/security/fsverity");
 }
 
-int main(int /*argc*/, const char** /*argv*/) {
+int main(int argc, const char** argv) {
+    if (argc < 2) {
+        LOG(ERROR) << "Not enough arguments";
+        return -1;
+    }
+
     key_serial_t keyring_id = android::GetKeyringId(".fs-verity");
     if (keyring_id < 0) {
         LOG(ERROR) << "Failed to find .fs-verity keyring id";
         return -1;
     }
 
-    // Requires files backed by fs-verity to be verified with a key in .fs-verity
-    // keyring.
-    if (!android::base::WriteStringToFile("1", "/proc/sys/fs/verity/require_signatures")) {
-        PLOG(ERROR) << "Failed to enforce fs-verity signature";
-    }
+    const std::string_view command = argv[1];
 
-    LoadKeyFromVerifiedPartitions(keyring_id);
-
-    if (!android::base::GetBoolProperty("ro.debuggable", false)) {
-        if (keyctl_restrict_keyring(keyring_id, nullptr, nullptr) < 0) {
-            PLOG(ERROR) << "Cannot restrict .fs-verity keyring";
+    if (command == "--load-verified-keys") {
+        LoadKeyFromVerifiedPartitions(keyring_id);
+    } else if (command == "--load-extra-key") {
+        if (argc != 3) {
+            LOG(ERROR) << "--load-extra-key requires <key_name> argument.";
+            return -1;
         }
+        LoadKeyFromStdin(keyring_id, argv[2]);
+    } else if (command == "--lock") {
+        // Requires files backed by fs-verity to be verified with a key in .fs-verity
+        // keyring.
+        if (!android::base::WriteStringToFile("1", "/proc/sys/fs/verity/require_signatures")) {
+            PLOG(ERROR) << "Failed to enforce fs-verity signature";
+        }
+
+        if (!android::base::GetBoolProperty("ro.debuggable", false)) {
+            if (keyctl_restrict_keyring(keyring_id, nullptr, nullptr) < 0) {
+                PLOG(ERROR) << "Cannot restrict .fs-verity keyring";
+            }
+        }
+    } else {
+        LOG(ERROR) << "Unknown argument(s).";
+        return -1;
     }
+
     return 0;
 }