Allow previously signed fs-verity files.

AddFilesToVerityRecursive() would fail if any of the files considered
was already in fs-verity. This is not desirable in case of partial
compilation, where some files might already have been generated and
signed on a previous boot. Allow such files, because earlier code will
already have verified that their signature matched the signature that we
remember anyway.

Bug: 205276874
Test: atest odsign_e2e_tests
Change-Id: Iaf35607d0054bdcd00501c6102ad629ce9fe7ac3
Merged-In: Iaf35607d0054bdcd00501c6102ad629ce9fe7ac3
diff --git a/ondevice-signing/VerityUtils.cpp b/ondevice-signing/VerityUtils.cpp
index 0bb3979..cd38308 100644
--- a/ondevice-signing/VerityUtils.cpp
+++ b/ondevice-signing/VerityUtils.cpp
@@ -172,32 +172,6 @@
     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);
-    auto end = std::filesystem::recursive_directory_iterator();
-
-    while (!ec && it != end) {
-        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;
-        }
-        ++it;
-    }
-    if (ec) {
-        return Error() << "Failed to iterate " << path << ": " << ec;
-    }
-
-    return digests;
-}
-
 Result<std::string> isFileInVerity(const std::string& path) {
     unsigned int flags;
 
@@ -223,6 +197,38 @@
     return toHex({&d->digest[0], &d->digest[d->digest_size]});
 }
 
+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);
+    auto end = std::filesystem::recursive_directory_iterator();
+
+    while (!ec && it != end) {
+        if (it->is_regular_file()) {
+            auto digest = isFileInVerity(it->path());
+            if (!digest.ok()) {
+                LOG(INFO) << "Adding " << it->path() << " to fs-verity...";
+                auto result = enableFsVerity(it->path(), 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;
+            }
+        }
+        ++it;
+    }
+    if (ec) {
+        return Error() << "Failed to iterate " << path << ": " << ec;
+    }
+
+    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 84af319..a834e61 100644
--- a/ondevice-signing/VerityUtils.h
+++ b/ondevice-signing/VerityUtils.h
@@ -24,5 +24,8 @@
 android::base::Result<std::vector<uint8_t>> createDigest(const std::string& path);
 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);