Add enableFsVerity function in VerityUtils.h

Bug: 218672709
Test: Replace "com.android.sepolicy.cert-release.der" -> "com.android.sepolicy.cert-debug.der" in
selinux.cpp > kSigningCertRelease, then manual tests

Change-Id: I5b1cd99200af2835aab58c2a5354494b74e71abc
diff --git a/ondevice-signing/VerityUtils.cpp b/ondevice-signing/VerityUtils.cpp
index 8ea0727..cd9a1ea 100644
--- a/ondevice-signing/VerityUtils.cpp
+++ b/ondevice-signing/VerityUtils.cpp
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 #include <asm/byteorder.h>
@@ -125,6 +126,19 @@
         }
     }
 };
+
+static Result<void> measureFsVerity(int fd, const fsverity_digest* digest) {
+    if (ioctl(fd, FS_IOC_MEASURE_VERITY, digest) != 0) {
+        if (errno == ENODATA) {
+            return Error() << "File is not in fs-verity";
+        } else {
+            return ErrnoError() << "Failed to FS_IOC_MEASURE_VERITY";
+        }
+    }
+
+    return {};
+}
+
 }  // namespace
 
 template <typename T> using trailing_unique_ptr = std::unique_ptr<T, DeleteAsPODArray<T>>;
@@ -198,14 +212,12 @@
 static Result<std::string> isFileInVerity(int fd) {
     auto d = makeUniqueWithTrailingData<fsverity_digest>(FS_VERITY_MAX_DIGEST_SIZE);
     d->digest_size = FS_VERITY_MAX_DIGEST_SIZE;
-    auto ret = ioctl(fd, FS_IOC_MEASURE_VERITY, d.get());
-    if (ret < 0) {
-        if (errno == ENODATA) {
-            return Error() << "File is not in fs-verity";
-        } else {
-            return ErrnoError() << "Failed to FS_IOC_MEASURE_VERITY";
-        }
+
+    const auto& status = measureFsVerity(fd, d.get());
+    if (!status.ok()) {
+        return status.error();
     }
+
     return toHex({&d->digest[0], &d->digest[d->digest_size]});
 }
 
@@ -256,6 +268,31 @@
     return digests;
 }
 
+Result<void> enableFsVerity(const std::string& path, const std::string& signature_path) {
+    unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+    if (!fd.ok()) {
+        return Error() << "Can't open " << path;
+    }
+
+    std::string signature;
+    android::base::ReadFileToString(signature_path, &signature);
+    std::vector<uint8_t> span = std::vector<uint8_t>(signature.begin(), signature.end());
+
+    const auto& enable = enableFsVerity(fd.get(), span);
+    if (!enable.ok()) {
+        return enable.error();
+    }
+
+    auto digest = makeUniqueWithTrailingData<fsverity_digest>(FS_VERITY_MAX_DIGEST_SIZE);
+    digest->digest_size = FS_VERITY_MAX_DIGEST_SIZE;
+    const auto& measure = measureFsVerity(fd.get(), digest.get());
+    if (!measure.ok()) {
+        return measure.error();
+    }
+
+    return {};
+}
+
 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/include/VerityUtils.h b/ondevice-signing/include/VerityUtils.h
index 0650563..e6e49c7 100644
--- a/ondevice-signing/include/VerityUtils.h
+++ b/ondevice-signing/include/VerityUtils.h
@@ -36,6 +36,10 @@
 android::base::Result<std::map<std::string, std::string>>
 addFilesToVerityRecursive(const std::string& path, const SigningKey& key);
 
+// Enable verity on the provided file, using the given PKCS7 signature.
+android::base::Result<void> enableFsVerity(const std::string& path,
+                                           const std::string& signature_path);
+
 android::base::Result<void>
 verifyAllFilesUsingCompOs(const std::string& directory_path,
                           const std::map<std::string, std::string>& digests,