Merge changes from topic "revert-1900930-version-bump-TMGXYBHYHZ"

* changes:
  Revert "Bump keystore2 AIDL API version 1->2"
  Revert "keystore2: cope with new curve25519 enum"
diff --git a/ondevice-signing/VerityUtils.cpp b/ondevice-signing/VerityUtils.cpp
index e5a872a..54490bd 100644
--- a/ondevice-signing/VerityUtils.cpp
+++ b/ondevice-signing/VerityUtils.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <charconv>
 #include <filesystem>
 #include <map>
 #include <span>
@@ -33,7 +34,6 @@
 
 #include "CertUtils.h"
 #include "SigningKey.h"
-#include "compos_signature.pb.h"
 
 #define FS_VERITY_MAX_DIGEST_SIZE 64
 
@@ -42,14 +42,7 @@
 using android::base::Result;
 using android::base::unique_fd;
 
-using compos::proto::Signature;
-
 static const char* kFsVerityInitPath = "/system/bin/fsverity_init";
-static const char* kSignatureExtension = ".signature";
-
-static bool isSignatureFile(const std::filesystem::path& path) {
-    return path.extension().native() == kSignatureExtension;
-}
 
 static std::string toHex(std::span<const uint8_t> data) {
     std::stringstream ss;
@@ -59,6 +52,23 @@
     return ss.str();
 }
 
+static std::vector<uint8_t> fromHex(std::string_view hex) {
+    if (hex.size() % 2 != 0) {
+        return {};
+    }
+    std::vector<uint8_t> result;
+    result.reserve(hex.size() / 2);
+    for (size_t i = 0; i < hex.size(); i += 2) {
+        uint8_t byte;
+        auto conversion_result = std::from_chars(&hex[i], &hex[i + 2], byte, 16);
+        if (conversion_result.ptr != &hex[i + 2] || conversion_result.ec != std::errc()) {
+            return {};
+        }
+        result.push_back(byte);
+    }
+    return result;
+}
+
 static int read_callback(void* file, void* buf, size_t count) {
     int* fd = (int*)file;
     if (TEMP_FAILURE_RETRY(read(*fd, buf, count)) < 0) return errno ? -errno : -EIO;
@@ -285,99 +295,62 @@
     return digests;
 }
 
-Result<Signature> readSignature(const std::filesystem::path& signature_path) {
-    unique_fd fd(TEMP_FAILURE_RETRY(open(signature_path.c_str(), O_RDONLY | O_CLOEXEC)));
-    if (fd == -1) {
-        return ErrnoError();
-    }
-    Signature signature;
-    if (!signature.ParseFromFileDescriptor(fd.get())) {
-        return Error() << "Failed to parse";
-    }
-    return signature;
-}
-
-Result<std::map<std::string, std::string>>
-verifyAllFilesUsingCompOs(const std::string& directory_path,
-                          const std::vector<uint8_t>& compos_key) {
-    std::map<std::string, std::string> new_digests;
-    std::vector<std::filesystem::path> signature_files;
-
+Result<void> verifyAllFilesUsingCompOs(const std::string& directory_path,
+                                       std::map<std::string, std::string> digests,
+                                       const SigningKey& signing_key) {
     std::error_code ec;
     auto it = std::filesystem::recursive_directory_iterator(directory_path, ec);
+    size_t verified_count = 0;
     for (auto end = std::filesystem::recursive_directory_iterator(); it != end; it.increment(ec)) {
         auto& path = it->path();
         if (it->is_regular_file()) {
-            if (isSignatureFile(path)) {
-                continue;
+            auto entry = digests.find(path);
+            if (entry == digests.end()) {
+                return Error() << "Unexpected file found: " << path;
             }
+            auto& compos_digest = entry->second;
 
             unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
             if (!fd.ok()) {
                 return ErrnoError() << "Can't open " << path;
             }
 
-            auto signature_path = path;
-            signature_path += kSignatureExtension;
-            auto signature = readSignature(signature_path);
-            if (!signature.ok()) {
-                return Error() << "Invalid signature " << signature_path << ": "
-                               << signature.error();
-            }
-            signature_files.push_back(signature_path);
-
-            // Note that these values are not yet trusted.
-            auto& raw_digest = signature->digest();
-            auto& raw_signature = signature->signature();
-
-            // Re-construct the fsverity_formatted_digest that was signed, so we
-            // can verify the signature.
-            std::vector<uint8_t> buffer(sizeof(fsverity_formatted_digest) + raw_digest.size());
-            auto signed_data = new (buffer.data()) fsverity_formatted_digest;
-            memcpy(signed_data->magic, "FSVerity", sizeof signed_data->magic);
-            signed_data->digest_algorithm = __cpu_to_le16(FS_VERITY_HASH_ALG_SHA256);
-            signed_data->digest_size = __cpu_to_le16(raw_digest.size());
-            memcpy(signed_data->digest, raw_digest.data(), raw_digest.size());
-
-            // Make sure the signature matches the CompOs public key, and not some other
-            // fs-verity trusted key.
-            std::string to_verify(reinterpret_cast<char*>(buffer.data()), buffer.size());
-
-            auto verified = verifyRsaPublicKeySignature(to_verify, raw_signature, compos_key);
-            if (!verified.ok()) {
-                return Error() << verified.error() << ": " << path;
-            }
-
-            std::span<const uint8_t> digest_bytes(
-                reinterpret_cast<const uint8_t*>(raw_digest.data()), raw_digest.size());
-            std::string compos_digest = toHex(digest_bytes);
-
             auto verity_digest = isFileInVerity(fd);
             if (verity_digest.ok()) {
                 // The file is already in fs-verity. We need to make sure it was signed
-                // by CompOs, so we just check that it has the digest we expect.
-                if (verity_digest.value() != compos_digest) {
-                    return Error() << "fs-verity digest does not match signature file: " << path;
+                // by CompOS, so we just check that it has the digest we expect.
+                if (verity_digest.value() == compos_digest) {
+                    ++verified_count;
+                } else {
+                    return Error() << "fs-verity digest does not match CompOS digest: " << path;
                 }
             } else {
-                // Not in fs-verity yet. But we have a valid signature of some
-                // digest. If it's not the correct digest for the file then
-                // enabling fs-verity will fail, so we don't need to check it
-                // explicitly ourselves. Otherwise we should be good.
-                std::vector<uint8_t> signature_bytes(raw_signature.begin(), raw_signature.end());
-                auto pkcs7 = createPkcs7(signature_bytes, kCompOsSubject);
-                if (!pkcs7.ok()) {
-                    return Error() << pkcs7.error() << ": " << path;
-                }
-
+                // Not in fs-verity yet. We know the digest CompOS provided; If
+                // it's not the correct digest for the file then enabling
+                // fs-verity will fail, so we don't need to check it explicitly
+                // ourselves. Otherwise we should be good.
                 LOG(INFO) << "Adding " << path << " to fs-verity...";
-                auto enabled = enableFsVerity(fd, pkcs7.value());
-                if (!enabled.ok()) {
-                    return Error() << enabled.error() << ": " << path;
-                }
-            }
 
-            new_digests[path] = compos_digest;
+                auto digest_bytes = fromHex(compos_digest);
+                if (digest_bytes.empty()) {
+                    return Error() << "Invalid digest " << compos_digest;
+                }
+                auto signed_digest = signDigest(signing_key, digest_bytes);
+                if (!signed_digest.ok()) {
+                    return signed_digest.error();
+                }
+
+                auto pkcs7_data = createPkcs7(signed_digest.value(), kRootSubject);
+                if (!pkcs7_data.ok()) {
+                    return pkcs7_data.error();
+                }
+
+                auto enabled = enableFsVerity(fd, pkcs7_data.value());
+                if (!enabled.ok()) {
+                    return Error() << enabled.error();
+                }
+                ++verified_count;
+            }
         } else if (it->is_directory()) {
             // These are fine to ignore
         } else if (it->is_symlink()) {
@@ -389,18 +362,12 @@
     if (ec) {
         return Error() << "Failed to iterate " << directory_path << ": " << ec.message();
     }
-
-    // Delete the signature files now that they have served their purpose.  (ART
-    // has no use for them, and their presence could cause verification to fail
-    // on subsequent boots.)
-    for (auto& signature_path : signature_files) {
-        std::filesystem::remove(signature_path, ec);
-        if (ec) {
-            return Error() << "Failed to delete " << signature_path << ": " << ec.message();
-        }
+    // Make sure all the files we expected have been seen
+    if (verified_count != digests.size()) {
+        return Error() << "Verified " << verified_count << "files, but expected " << digests.size();
     }
 
-    return new_digests;
+    return {};
 }
 
 Result<void> addCertToFsVerityKeyring(const std::string& path, const char* keyName) {
diff --git a/ondevice-signing/include/VerityUtils.h b/ondevice-signing/include/VerityUtils.h
index 76b2229..7715628 100644
--- a/ondevice-signing/include/VerityUtils.h
+++ b/ondevice-signing/include/VerityUtils.h
@@ -18,6 +18,10 @@
 
 #include <android-base/result.h>
 
+#include <map>
+#include <string>
+#include <vector>
+
 #include "SigningKey.h"
 
 android::base::Result<void> addCertToFsVerityKeyring(const std::string& path, const char* keyName);
@@ -30,5 +34,6 @@
 android::base::Result<std::map<std::string, std::string>>
 addFilesToVerityRecursive(const std::string& path, const SigningKey& key);
 
-android::base::Result<std::map<std::string, std::string>>
-verifyAllFilesUsingCompOs(const std::string& path, const std::vector<uint8_t>& compos_key);
+android::base::Result<void> verifyAllFilesUsingCompOs(const std::string& directory_path,
+                                                      std::map<std::string, std::string> digests,
+                                                      const SigningKey& signing_key);
diff --git a/ondevice-signing/odsign_main.cpp b/ondevice-signing/odsign_main.cpp
index 6ea20ea..ec4a997 100644
--- a/ondevice-signing/odsign_main.cpp
+++ b/ondevice-signing/odsign_main.cpp
@@ -65,8 +65,14 @@
     "/data/misc/apexdata/com.android.compos/current/key.pubkey";
 const std::string kCompOsPendingPublicKey =
     "/data/misc/apexdata/com.android.compos/pending/key.pubkey";
-
 const std::string kCompOsPendingArtifactsDir = "/data/misc/apexdata/com.android.art/compos-pending";
+const std::string kCompOsInfo = kArtArtifactsDir + "/compos.info";
+const std::string kCompOsInfoSignature = kCompOsInfo + ".signature";
+
+constexpr const char* kCompOsPendingInfoPath =
+    "/data/misc/apexdata/com.android.art/compos-pending/compos.info";
+constexpr const char* kCompOsPendingInfoSignaturePath =
+    "/data/misc/apexdata/com.android.art/compos-pending/compos.info.signature";
 
 constexpr const char* kOdsignVerificationDoneProp = "odsign.verification.done";
 constexpr const char* kOdsignKeyDoneProp = "odsign.key.done";
@@ -241,7 +247,7 @@
         auto existing_key =
             extractRsaPublicKeyFromLeafCert(signingKey, kCompOsCert, kCompOsSubject.commonName);
         if (existing_key.ok()) {
-            LOG(INFO) << "Found and verified existing CompOs public key certificate: "
+            LOG(INFO) << "Found and verified existing CompOS public key certificate: "
                       << kCompOsCert;
             return existing_key.value();
         }
@@ -254,7 +260,7 @@
     }
 
     if (!verified) {
-        return Error() << "No valid CompOs key present.";
+        return Error() << "No valid CompOS key present.";
     }
 
     // If the pending key was verified it will have been promoted to current, so
@@ -262,7 +268,7 @@
     auto publicKey = readBytesFromFile(kCompOsCurrentPublicKey);
     if (publicKey.empty()) {
         // This shouldn`t really happen.
-        return Error() << "Failed to read CompOs key.";
+        return Error() << "Failed to read CompOS key.";
     }
 
     // One way or another we now have a valid public key. Persist a certificate so
@@ -274,10 +280,10 @@
     auto certStatus = createLeafCertificate(kCompOsSubject, publicKey, signFunction,
                                             kSigningKeyCert, kCompOsCert);
     if (!certStatus.ok()) {
-        return Error() << "Failed to create CompOs cert: " << certStatus.error();
+        return Error() << "Failed to create CompOS cert: " << certStatus.error();
     }
 
-    LOG(INFO) << "Verified key, wrote new CompOs cert";
+    LOG(INFO) << "Verified key, wrote new CompOS cert";
 
     return publicKey;
 }
@@ -447,23 +453,58 @@
     if (!cert_add_result.ok()) {
         // Best efforts only - nothing we can do if deletion fails.
         unlink(kCompOsCert.c_str());
-        return Error() << "Failed to add CompOs certificate to fs-verity keyring: "
+        return Error() << "Failed to add CompOS certificate to fs-verity keyring: "
                        << cert_add_result.error();
     }
 
     return publicKey;
 }
 
+Result<OdsignInfo> getComposInfo(const std::vector<uint8_t>& compos_key) {
+    std::string compos_signature;
+    if (!android::base::ReadFileToString(kCompOsInfoSignature, &compos_signature)) {
+        return ErrnoError() << "Failed to read " << kCompOsInfoSignature;
+    }
+
+    std::string compos_info_str;
+    if (!android::base::ReadFileToString(kCompOsInfo, &compos_info_str)) {
+        return ErrnoError() << "Failed to read " << kCompOsInfo;
+    }
+
+    // Delete the files - if they're valid we don't need them any more, and
+    // they'd confuse artifact verification; if they're not we never need to
+    // look at them again.
+    if (unlink(kCompOsInfo.c_str()) != 0 || unlink(kCompOsInfoSignature.c_str()) != 0) {
+        return ErrnoError() << "Unable to delete CompOS info/signature file";
+    }
+
+    // Verify the signature
+    auto verified = verifyRsaPublicKeySignature(compos_info_str, compos_signature, compos_key);
+    if (!verified.ok()) {
+        return Error() << kCompOsInfoSignature << " does not match.";
+    } else {
+        LOG(INFO) << kCompOsInfoSignature << " matches.";
+    }
+
+    OdsignInfo compos_info;
+    if (!compos_info.ParseFromString(compos_info_str)) {
+        return Error() << "Failed to parse " << kCompOsInfo;
+    }
+
+    LOG(INFO) << "Loaded " << kCompOsInfo;
+    return compos_info;
+}
+
 art::odrefresh::ExitCode checkCompOsPendingArtifacts(const std::vector<uint8_t>& compos_key,
-                                                     const SigningKey& signingKey,
+                                                     const SigningKey& signing_key,
                                                      bool* digests_verified) {
     if (!directoryHasContent(kCompOsPendingArtifactsDir)) {
         return art::odrefresh::ExitCode::kCompilationRequired;
     }
 
-    // CompOs has generated some artifacts that may, or may not, match the
+    // CompOS has generated some artifacts that may, or may not, match the
     // current state.  But if there are already valid artifacts present the
-    // CompOs ones are redundant.
+    // CompOS ones are redundant.
     art::odrefresh::ExitCode odrefresh_status = checkArtifacts();
     if (odrefresh_status != art::odrefresh::ExitCode::kCompilationRequired) {
         if (odrefresh_status == art::odrefresh::ExitCode::kOkay) {
@@ -473,7 +514,14 @@
         return odrefresh_status;
     }
 
-    // No useful current artifacts, lets see if the CompOs ones are ok
+    // No useful current artifacts, lets see if the CompOS ones are ok
+    if (access(kCompOsPendingInfoPath, R_OK) != 0 ||
+        access(kCompOsPendingInfoSignaturePath, R_OK) != 0) {
+        LOG(INFO) << "Missing CompOS info/signature, deleting pending artifacts";
+        removeDirectory(kCompOsPendingArtifactsDir);
+        return art::odrefresh::ExitCode::kCompilationRequired;
+    }
+
     LOG(INFO) << "Current artifacts are out of date, switching to pending artifacts";
     removeDirectory(kArtArtifactsDir);
     if (!rename(kCompOsPendingArtifactsDir, kArtArtifactsDir)) {
@@ -481,9 +529,6 @@
         return art::odrefresh::ExitCode::kCompilationRequired;
     }
 
-    // TODO: Make sure that we check here that the contents of the artifacts
-    // correspond to their filenames (and extensions) - the CompOs signatures
-    // can't guarantee that.
     odrefresh_status = checkArtifacts();
     if (odrefresh_status != art::odrefresh::ExitCode::kOkay) {
         LOG(WARNING) << "Pending artifacts are not OK";
@@ -492,24 +537,28 @@
 
     // The artifacts appear to be up to date - but we haven't
     // verified that they are genuine yet.
-    Result<std::map<std::string, std::string>> digests =
-        verifyAllFilesUsingCompOs(kArtArtifactsDir, compos_key);
 
-    if (digests.ok()) {
-        auto persisted = persistDigests(digests.value(), signingKey);
-
-        // Having signed the digests (or failed to), we're done with the signing key.
-        SetProperty(kOdsignKeyDoneProp, "1");
-
-        if (persisted.ok()) {
-            *digests_verified = true;
-            LOG(INFO) << "Pending artifacts successfully verified.";
-            return art::odrefresh::ExitCode::kOkay;
-        } else {
-            LOG(WARNING) << persisted.error();
-        }
+    auto compos_info = getComposInfo(compos_key);
+    if (!compos_info.ok()) {
+        LOG(WARNING) << compos_info.error();
     } else {
-        LOG(WARNING) << "Pending artifact verification failed: " << digests.error();
+        std::map<std::string, std::string> compos_digests(compos_info->file_hashes().begin(),
+                                                          compos_info->file_hashes().end());
+
+        auto status = verifyAllFilesUsingCompOs(kArtArtifactsDir, compos_digests, signing_key);
+        if (!status.ok()) {
+            LOG(WARNING) << status.error();
+        } else {
+            auto persisted = persistDigests(compos_digests, signing_key);
+
+            if (!persisted.ok()) {
+                LOG(WARNING) << persisted.error();
+            } else {
+                LOG(INFO) << "Pending artifacts successfully verified.";
+                *digests_verified = true;
+                return art::odrefresh::ExitCode::kOkay;
+            }
+        }
     }
 
     // We can't use the existing artifacts, so we will need to generate new
diff --git a/ondevice-signing/proto/Android.bp b/ondevice-signing/proto/Android.bp
index 173aae4..d6e3354 100644
--- a/ondevice-signing/proto/Android.bp
+++ b/ondevice-signing/proto/Android.bp
@@ -32,6 +32,17 @@
     ],
 }
 
+rust_protobuf {
+    name: "libodsign_proto_rust",
+    crate_name: "odsign_proto",
+    protos: ["odsign_info.proto"],
+    source_stem: "odsign_proto",
+    host_supported: true,
+    apex_available: [
+        "com.android.compos",
+    ],
+}
+
 cc_library_static {
     name: "lib_compos_proto",
     host_supported: true,