Merge "Replacing manual CBOR with serde-cbor"
diff --git a/fsverity/Android.bp b/fsverity/Android.bp
index b1d8965..5fb38ae 100644
--- a/fsverity/Android.bp
+++ b/fsverity/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "system_security_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["system_security_license"],
+}
+
 python_library_host {
     name: "fsverity_digests_proto_python",
     srcs: [
diff --git a/fsverity/OWNERS b/fsverity/OWNERS
new file mode 100644
index 0000000..f9e7b25
--- /dev/null
+++ b/fsverity/OWNERS
@@ -0,0 +1,5 @@
+alanstokes@google.com
+ebiggers@google.com
+jeffv@google.com
+jiyong@google.com
+victorhsieh@google.com
diff --git a/fsverity_init/Android.bp b/fsverity_init/Android.bp
index 39d4e6b..83c5945 100644
--- a/fsverity_init/Android.bp
+++ b/fsverity_init/Android.bp
@@ -10,17 +10,34 @@
 cc_binary {
     name: "fsverity_init",
     srcs: [
-        "fsverity_init.cpp",
+        "main.cpp",
     ],
     static_libs: [
         "libc++fs",
+        "libfsverity_init",
+        "libmini_keyctl_static",
+    ],
+    shared_libs: [
+        "libbase",
+        "libkeyutils",
+        "liblog",
+    ],
+    cflags: ["-Werror", "-Wall", "-Wextra"],
+}
+
+cc_library {
+    name: "libfsverity_init",
+    srcs: ["fsverity_init.cpp"],
+    static_libs: [
+        "libc++fs",
         "libmini_keyctl_static",
     ],
     shared_libs: [
         "libbase",
         "libkeyutils",
         "liblog",
-        "liblogwrap",
     ],
     cflags: ["-Werror", "-Wall", "-Wextra"],
+    export_include_dirs: ["include"],
+    recovery_available: true,
 }
diff --git a/fsverity_init/OWNERS b/fsverity_init/OWNERS
new file mode 100644
index 0000000..f9e7b25
--- /dev/null
+++ b/fsverity_init/OWNERS
@@ -0,0 +1,5 @@
+alanstokes@google.com
+ebiggers@google.com
+jeffv@google.com
+jiyong@google.com
+victorhsieh@google.com
diff --git a/fsverity_init/fsverity_init.cpp b/fsverity_init/fsverity_init.cpp
index 7bc6022..61f84dd 100644
--- a/fsverity_init/fsverity_init.cpp
+++ b/fsverity_init/fsverity_init.cpp
@@ -81,47 +81,3 @@
     LoadKeyFromDirectory(keyring_id, "fsv_system_", "/system/etc/security/fsverity");
     LoadKeyFromDirectory(keyring_id, "fsv_product_", "/product/etc/security/fsverity");
 }
-
-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;
-    }
-
-    const std::string_view command = argv[1];
-
-    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;
-        }
-        if (!LoadKeyFromStdin(keyring_id, argv[2])) {
-            return -1;
-        }
-    } 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;
-}
diff --git a/fsverity_init/include/fsverity_init.h b/fsverity_init/include/fsverity_init.h
new file mode 100644
index 0000000..c3bc93b
--- /dev/null
+++ b/fsverity_init/include/fsverity_init.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 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 <mini_keyctl_utils.h>
+
+bool LoadKeyFromStdin(key_serial_t keyring_id, const char* keyname);
+void LoadKeyFromFile(key_serial_t keyring_id, const char* keyname, const std::string& path);
+void LoadKeyFromVerifiedPartitions(key_serial_t keyring_id);
diff --git a/fsverity_init/main.cpp b/fsverity_init/main.cpp
new file mode 100644
index 0000000..3f75dca
--- /dev/null
+++ b/fsverity_init/main.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 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 <string>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <fsverity_init.h>
+#include <log/log.h>
+#include <mini_keyctl_utils.h>
+
+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;
+    }
+
+    const std::string_view command = argv[1];
+
+    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;
+        }
+        if (!LoadKeyFromStdin(keyring_id, argv[2])) {
+            return -1;
+        }
+    } 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;
+}
diff --git a/keystore/keystore_cli_v2.cpp b/keystore/keystore_cli_v2.cpp
index 1cfb4f6..1e9126d 100644
--- a/keystore/keystore_cli_v2.cpp
+++ b/keystore/keystore_cli_v2.cpp
@@ -19,6 +19,7 @@
 #include <iostream>
 #include <memory>
 #include <string>
+#include <variant>
 #include <vector>
 
 #include <base/command_line.h>
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 3f6cf36..57abc26 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -215,6 +215,8 @@
 
     fn migrate_key_namespace(source: &KeyDescriptor, destination: &KeyDescriptor) -> Result<()> {
         let caller_uid = ThreadState::get_calling_uid();
+        let migrate_any_key_permission =
+            check_keystore_permission(KeystorePerm::MigrateAnyKey).is_ok();
 
         DB.with(|db| {
             let key_id_guard = match source.domain {
@@ -227,9 +229,12 @@
                                 KeyEntryLoadBits::NONE,
                                 caller_uid,
                                 |k, av| {
-                                    check_key_permission(KeyPerm::Use, k, &av)?;
-                                    check_key_permission(KeyPerm::Delete, k, &av)?;
-                                    check_key_permission(KeyPerm::Grant, k, &av)
+                                    if !migrate_any_key_permission {
+                                        check_key_permission(KeyPerm::Use, k, &av)?;
+                                        check_key_permission(KeyPerm::Delete, k, &av)?;
+                                        check_key_permission(KeyPerm::Grant, k, &av)?;
+                                    }
+                                    Ok(())
                                 },
                             )
                         })
@@ -245,7 +250,10 @@
             };
 
             db.borrow_mut().migrate_key_namespace(key_id_guard, destination, caller_uid, |k| {
-                check_key_permission(KeyPerm::Rebind, k, &None)
+                if !migrate_any_key_permission {
+                    check_key_permission(KeyPerm::Rebind, k, &None)?;
+                }
+                Ok(())
             })
         })
     }
diff --git a/keystore2/src/permission.rs b/keystore2/src/permission.rs
index f280341..e6d61b0 100644
--- a/keystore2/src/permission.rs
+++ b/keystore2/src/permission.rs
@@ -145,6 +145,10 @@
         /// Checked when IKeystoreMaintenance::deleteAllKeys is called.
         #[selinux(name = delete_all_keys)]
         DeleteAllKeys,
+        /// Checked when migrating any key from any namespace to any other namespace. It was
+        /// introduced for migrating keys when an app leaves a sharedUserId.
+        #[selinux(name = migrate_any_key)]
+        MigrateAnyKey,
     }
 );
 
diff --git a/ondevice-signing/VerityUtils.cpp b/ondevice-signing/VerityUtils.cpp
index 2beb7eb..e5a872a 100644
--- a/ondevice-signing/VerityUtils.cpp
+++ b/ondevice-signing/VerityUtils.cpp
@@ -155,15 +155,10 @@
     return {};
 }
 
-Result<std::string> enableFsVerity(const std::string& path, const SigningKey& key) {
-    unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
-    if (!fd.ok()) {
-        return ErrnoError() << "Failed to open " << path;
-    }
-
-    auto digest = createDigest(fd.get());
+Result<std::string> enableFsVerity(int fd, const SigningKey& key) {
+    auto digest = createDigest(fd);
     if (!digest.ok()) {
-        return Error() << digest.error() << ": " << path;
+        return Error() << digest.error();
     }
 
     auto signed_digest = signDigest(key, digest.value());
@@ -176,36 +171,26 @@
         return pkcs7_data.error();
     }
 
-    auto enabled = enableFsVerity(fd.get(), pkcs7_data.value());
+    auto enabled = enableFsVerity(fd, pkcs7_data.value());
     if (!enabled.ok()) {
-        return Error() << enabled.error() << ": " << path;
+        return Error() << enabled.error();
     }
 
     // Return the root hash as a hex string
     return toHex(digest.value());
 }
 
-Result<std::map<std::string, std::string>> addFilesToVerityRecursive(const std::string& path,
-                                                                     const SigningKey& key) {
-    std::map<std::string, std::string> digests;
-
-    std::error_code ec;
-    auto it = std::filesystem::recursive_directory_iterator(path, ec);
-    for (auto end = std::filesystem::recursive_directory_iterator(); it != end; it.increment(ec)) {
-        if (it->is_regular_file()) {
-            LOG(INFO) << "Adding " << it->path() << " to fs-verity...";
-            auto result = enableFsVerity(it->path(), key);
-            if (!result.ok()) {
-                return result.error();
-            }
-            digests[it->path()] = *result;
-        }
-    }
-    if (ec) {
-        return Error() << "Failed to iterate " << path << ": " << ec.message();
+Result<std::string> enableFsVerity(const std::string& path, const SigningKey& key) {
+    unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+    if (!fd.ok()) {
+        return ErrnoError() << "Failed to open " << path;
     }
 
-    return digests;
+    auto enableStatus = enableFsVerity(fd.get(), key);
+    if (!enableStatus.ok()) {
+        return Error() << path << ": " << enableStatus.error();
+    }
+    return enableStatus;
 }
 
 Result<std::string> isFileInVerity(int fd) {
@@ -228,7 +213,7 @@
         return ErrnoError() << "Failed to open " << path;
     }
 
-    auto digest = isFileInVerity(fd);
+    auto digest = isFileInVerity(fd.get());
     if (!digest.ok()) {
         return Error() << digest.error() << ": " << path;
     }
@@ -236,6 +221,39 @@
     return digest;
 }
 
+Result<std::map<std::string, std::string>> addFilesToVerityRecursive(const std::string& path,
+                                                                     const SigningKey& key) {
+    std::map<std::string, std::string> digests;
+
+    std::error_code ec;
+    auto it = std::filesystem::recursive_directory_iterator(path, ec);
+    for (auto end = std::filesystem::recursive_directory_iterator(); it != end; it.increment(ec)) {
+        if (it->is_regular_file()) {
+            unique_fd fd(TEMP_FAILURE_RETRY(open(it->path().c_str(), O_RDONLY | O_CLOEXEC)));
+            if (!fd.ok()) {
+                return ErrnoError() << "Failed to open " << path;
+            }
+            auto digest = isFileInVerity(fd);
+            if (!digest.ok()) {
+                LOG(INFO) << "Adding " << it->path() << " to fs-verity...";
+                auto result = enableFsVerity(fd, key);
+                if (!result.ok()) {
+                    return result.error();
+                }
+                digests[it->path()] = *result;
+            } else {
+                LOG(INFO) << it->path() << " was already in fs-verity.";
+                digests[it->path()] = *digest;
+            }
+        }
+    }
+    if (ec) {
+        return Error() << "Failed to iterate " << path << ": " << ec.message();
+    }
+
+    return digests;
+}
+
 Result<std::map<std::string, std::string>> verifyAllFilesInVerity(const std::string& path) {
     std::map<std::string, std::string> digests;
     std::error_code ec;
diff --git a/ondevice-signing/VerityUtils.h b/ondevice-signing/VerityUtils.h
index 8d8e62c..76b2229 100644
--- a/ondevice-signing/VerityUtils.h
+++ b/ondevice-signing/VerityUtils.h
@@ -25,6 +25,8 @@
 android::base::Result<std::map<std::string, std::string>>
 verifyAllFilesInVerity(const std::string& path);
 
+// Note that this function will skip files that are already in fs-verity, and
+// for those files it will return the existing digest.
 android::base::Result<std::map<std::string, std::string>>
 addFilesToVerityRecursive(const std::string& path, const SigningKey& key);
 
diff --git a/provisioner/rkp_factory_extraction_tool.cpp b/provisioner/rkp_factory_extraction_tool.cpp
index 2e59dbd..9786c3d 100644
--- a/provisioner/rkp_factory_extraction_tool.cpp
+++ b/provisioner/rkp_factory_extraction_tool.cpp
@@ -77,9 +77,13 @@
     uint8_t* writePtr = challenge.data();
     while (bytesRemaining > 0) {
         int bytesRead = getrandom(writePtr, bytesRemaining, /*flags=*/0);
-        if (bytesRead < 0 && errno != EINTR) {
-            std::cerr << errno << ": " << strerror(errno) << std::endl;
-            exit(-1);
+        if (bytesRead < 0) {
+            if (errno == EINTR) {
+                continue;
+            } else {
+                std::cerr << errno << ": " << strerror(errno) << std::endl;
+                exit(-1);
+            }
         }
         bytesRemaining -= bytesRead;
         writePtr += bytesRead;
@@ -158,7 +162,7 @@
     auto rkp_service = IRemotelyProvisionedComponent::fromBinder(rkp_binder);
     if (!rkp_service) {
         std::cerr << "Unable to get binder object for '" << fullName << "', skipping.";
-        return;
+        exit(-1);
     }
 
     std::vector<uint8_t> keysToSignMac;