Merge changes from topic "expiration_pruning"

* changes:
  Adding additional call to delete expired keys
  Upgrade remotely provisioned keys if necessary.
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index a6ca179..3ade2cf 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -384,29 +384,39 @@
     return ssps;
 }
 
-void OperationSlots::setNumFreeSlots(uint8_t numFreeSlots) {
+void OperationSlotManager::setNumFreeSlots(uint8_t numFreeSlots) {
     std::lock_guard<std::mutex> lock(mNumFreeSlotsMutex);
     mNumFreeSlots = numFreeSlots;
 }
 
-bool OperationSlots::claimSlot() {
-    std::lock_guard<std::mutex> lock(mNumFreeSlotsMutex);
-    if (mNumFreeSlots > 0) {
-        mNumFreeSlots--;
-        return true;
+std::optional<OperationSlot>
+OperationSlotManager::claimSlot(std::shared_ptr<OperationSlotManager> operationSlots) {
+    std::lock_guard<std::mutex> lock(operationSlots->mNumFreeSlotsMutex);
+    if (operationSlots->mNumFreeSlots > 0) {
+        operationSlots->mNumFreeSlots--;
+        return OperationSlot(std::move(operationSlots), std::nullopt);
     }
-    return false;
+    return std::nullopt;
 }
 
-void OperationSlots::freeSlot() {
+OperationSlot
+OperationSlotManager::claimReservedSlot(std::shared_ptr<OperationSlotManager> operationSlots) {
+    std::unique_lock<std::mutex> reservedGuard(operationSlots->mReservedSlotMutex);
+    return OperationSlot(std::move(operationSlots), std::move(reservedGuard));
+}
+
+OperationSlot::OperationSlot(std::shared_ptr<OperationSlotManager> slots,
+                             std::optional<std::unique_lock<std::mutex>> reservedGuard)
+    : mOperationSlots(std::move(slots)), mReservedGuard(std::move(reservedGuard)) {}
+
+void OperationSlotManager::freeSlot() {
     std::lock_guard<std::mutex> lock(mNumFreeSlotsMutex);
     mNumFreeSlots++;
 }
 
-void OperationSlot::freeSlot() {
-    if (mIsActive) {
+OperationSlot::~OperationSlot() {
+    if (!mReservedGuard && mOperationSlots) {
         mOperationSlots->freeSlot();
-        mIsActive = false;
     }
 }
 
@@ -613,9 +623,15 @@
                                    const std::vector<KeyParameter>& in_inParams,
                                    const std::optional<HardwareAuthToken>& in_inAuthToken,
                                    BeginResult* _aidl_return) {
-    if (!mOperationSlots.claimSlot()) {
-        return convertErrorCode(V4_0_ErrorCode::TOO_MANY_OPERATIONS);
-    }
+    return beginInternal(in_inPurpose, prefixedKeyBlob, in_inParams, in_inAuthToken,
+                         false /* useReservedSlot */, _aidl_return);
+}
+
+ScopedAStatus KeyMintDevice::beginInternal(KeyPurpose in_inPurpose,
+                                           const std::vector<uint8_t>& prefixedKeyBlob,
+                                           const std::vector<KeyParameter>& in_inParams,
+                                           const std::optional<HardwareAuthToken>& in_inAuthToken,
+                                           bool useReservedSlot, BeginResult* _aidl_return) {
 
     const std::vector<uint8_t>& in_inKeyBlob = prefixedKeyBlobRemovePrefix(prefixedKeyBlob);
     if (prefixedKeyBlobIsSoftKeyMint(prefixedKeyBlob)) {
@@ -623,28 +639,41 @@
                                          _aidl_return);
     }
 
+    OperationSlot slot;
+    // No need to claim a slot for software device.
+    if (useReservedSlot) {
+        // There is only one reserved slot. This function blocks until
+        // the reserved slot becomes available.
+        slot = OperationSlotManager::claimReservedSlot(mOperationSlots);
+    } else {
+        if (auto opt_slot = OperationSlotManager::claimSlot(mOperationSlots)) {
+            slot = std::move(*opt_slot);
+        } else {
+            return convertErrorCode(V4_0_ErrorCode::TOO_MANY_OPERATIONS);
+        }
+    }
+
     auto legacyPurpose =
         static_cast<::android::hardware::keymaster::V4_0::KeyPurpose>(in_inPurpose);
     auto legacyParams = convertKeyParametersToLegacy(in_inParams);
     auto legacyAuthToken = convertAuthTokenToLegacy(in_inAuthToken);
     KMV1::ErrorCode errorCode;
-    auto result = mDevice->begin(
-        legacyPurpose, in_inKeyBlob, legacyParams, legacyAuthToken,
-        [&](V4_0_ErrorCode error, const hidl_vec<V4_0_KeyParameter>& outParams,
-            uint64_t operationHandle) {
-            errorCode = convert(error);
-            _aidl_return->challenge = operationHandle;
-            _aidl_return->params = convertKeyParametersFromLegacy(outParams);
-            _aidl_return->operation = ndk::SharedRefBase::make<KeyMintOperation>(
-                mDevice, operationHandle, &mOperationSlots, error == V4_0_ErrorCode::OK);
-        });
+    auto result =
+        mDevice->begin(legacyPurpose, in_inKeyBlob, legacyParams, legacyAuthToken,
+                       [&](V4_0_ErrorCode error, const hidl_vec<V4_0_KeyParameter>& outParams,
+                           uint64_t operationHandle) {
+                           errorCode = convert(error);
+                           if (error == V4_0_ErrorCode::OK) {
+                               _aidl_return->challenge = operationHandle;
+                               _aidl_return->params = convertKeyParametersFromLegacy(outParams);
+                               _aidl_return->operation = ndk::SharedRefBase::make<KeyMintOperation>(
+                                   mDevice, operationHandle, std::move(slot));
+                           }
+                       });
     if (!result.isOk()) {
         LOG(ERROR) << __func__ << " transaction failed. " << result.description();
         errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
     }
-    if (errorCode != KMV1::ErrorCode::OK) {
-        mOperationSlots.freeSlot();
-    }
     return convertErrorCode(errorCode);
 }
 
@@ -704,8 +733,9 @@
         LOG(ERROR) << __func__ << " export_key failed: " << ret.description();
         return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
     }
-    if (km_error != KMV1::ErrorCode::OK)
+    if (km_error != KMV1::ErrorCode::OK) {
         LOG(ERROR) << __func__ << " export_key failed, code " << int32_t(km_error);
+    }
 
     return convertErrorCode(km_error);
 }
@@ -757,7 +787,11 @@
         LOG(ERROR) << __func__ << " transaction failed. " << result.description();
         errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
     }
-    if (errorCode != KMV1::ErrorCode::OK) mOperationSlot.freeSlot();
+
+    // Operation slot is no longer occupied.
+    if (errorCode != KMV1::ErrorCode::OK) {
+        mOperationSlot = std::nullopt;
+    }
 
     return convertErrorCode(errorCode);
 }
@@ -815,7 +849,10 @@
         inputPos += consumed;
     }
 
-    if (errorCode != KMV1::ErrorCode::OK) mOperationSlot.freeSlot();
+    // Operation slot is no longer occupied.
+    if (errorCode != KMV1::ErrorCode::OK) {
+        mOperationSlot = std::nullopt;
+    }
 
     return convertErrorCode(errorCode);
 }
@@ -846,17 +883,19 @@
             *out_output = output;
         });
 
-    mOperationSlot.freeSlot();
     if (!result.isOk()) {
         LOG(ERROR) << __func__ << " transaction failed. " << result.description();
         errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
     }
+
+    mOperationSlot = std::nullopt;
+
     return convertErrorCode(errorCode);
 }
 
 ScopedAStatus KeyMintOperation::abort() {
     auto result = mDevice->abort(mOperationHandle);
-    mOperationSlot.freeSlot();
+    mOperationSlot = std::nullopt;
     if (!result.isOk()) {
         LOG(ERROR) << __func__ << " transaction failed. " << result.description();
         return convertErrorCode(KMV1::ErrorCode::UNKNOWN_ERROR);
@@ -865,7 +904,7 @@
 }
 
 KeyMintOperation::~KeyMintOperation() {
-    if (mOperationSlot.hasSlot()) {
+    if (mOperationSlot) {
         auto error = abort();
         if (!error.isOk()) {
             LOG(WARNING) << "Error calling abort in ~KeyMintOperation: " << error.getMessage();
@@ -1118,8 +1157,8 @@
                 kps.push_back(KMV1::makeKeyParameter(KMV1::TAG_PADDING, origPadding));
             }
             BeginResult beginResult;
-            auto error =
-                begin(KeyPurpose::SIGN, prefixedKeyBlob, kps, HardwareAuthToken(), &beginResult);
+            auto error = beginInternal(KeyPurpose::SIGN, prefixedKeyBlob, kps, HardwareAuthToken(),
+                                       true /* useReservedSlot */, &beginResult);
             if (!error.isOk()) {
                 errorCode = toErrorCode(error);
                 return std::vector<uint8_t>();
@@ -1355,13 +1394,14 @@
 }
 
 void KeyMintDevice::setNumFreeSlots(uint8_t numFreeSlots) {
-    mOperationSlots.setNumFreeSlots(numFreeSlots);
+    mOperationSlots->setNumFreeSlots(numFreeSlots);
 }
 
 // Constructors and helpers.
 
 KeyMintDevice::KeyMintDevice(sp<Keymaster> device, KeyMintSecurityLevel securityLevel)
-    : mDevice(device), securityLevel_(securityLevel) {
+    : mDevice(device), mOperationSlots(std::make_shared<OperationSlotManager>()),
+      securityLevel_(securityLevel) {
     if (securityLevel == KeyMintSecurityLevel::STRONGBOX) {
         setNumFreeSlots(3);
     } else {
diff --git a/keystore2/src/km_compat/km_compat.h b/keystore2/src/km_compat/km_compat.h
index c07470d..f6f5eb4 100644
--- a/keystore2/src/km_compat/km_compat.h
+++ b/keystore2/src/km_compat/km_compat.h
@@ -50,37 +50,49 @@
 using ::android::hardware::keymaster::V4_1::support::Keymaster;
 using ::ndk::ScopedAStatus;
 
-class OperationSlots {
-  private:
-    uint8_t mNumFreeSlots;
-    std::mutex mNumFreeSlotsMutex;
-
-  public:
-    void setNumFreeSlots(uint8_t numFreeSlots);
-    bool claimSlot();
-    void freeSlot();
-};
-
+class OperationSlot;
+class OperationSlotManager;
 // An abstraction for a single operation slot.
 // This contains logic to ensure that we do not free the slot multiple times,
 // e.g., if we call abort twice on the same operation.
 class OperationSlot {
+    friend OperationSlotManager;
+
   private:
-    OperationSlots* mOperationSlots;
-    bool mIsActive;
+    std::shared_ptr<OperationSlotManager> mOperationSlots;
+    std::optional<std::unique_lock<std::mutex>> mReservedGuard;
+
+  protected:
+    OperationSlot(std::shared_ptr<OperationSlotManager>,
+                  std::optional<std::unique_lock<std::mutex>> reservedGuard);
+    OperationSlot(const OperationSlot&) = delete;
+    OperationSlot& operator=(const OperationSlot&) = delete;
 
   public:
-    OperationSlot(OperationSlots* slots, bool isActive)
-        : mOperationSlots(slots), mIsActive(isActive) {}
+    OperationSlot() : mOperationSlots(nullptr), mReservedGuard(std::nullopt) {}
+    OperationSlot(OperationSlot&&) = default;
+    OperationSlot& operator=(OperationSlot&&) = default;
+    ~OperationSlot();
+};
 
+class OperationSlotManager {
+  private:
+    uint8_t mNumFreeSlots;
+    std::mutex mNumFreeSlotsMutex;
+    std::mutex mReservedSlotMutex;
+
+  public:
+    void setNumFreeSlots(uint8_t numFreeSlots);
+    static std::optional<OperationSlot>
+    claimSlot(std::shared_ptr<OperationSlotManager> operationSlots);
+    static OperationSlot claimReservedSlot(std::shared_ptr<OperationSlotManager> operationSlots);
     void freeSlot();
-    bool hasSlot() { return mIsActive; }
 };
 
 class KeyMintDevice : public aidl::android::hardware::security::keymint::BnKeyMintDevice {
   private:
     ::android::sp<Keymaster> mDevice;
-    OperationSlots mOperationSlots;
+    std::shared_ptr<OperationSlotManager> mOperationSlots;
 
   public:
     explicit KeyMintDevice(::android::sp<Keymaster>, KeyMintSecurityLevel);
@@ -109,10 +121,15 @@
     ScopedAStatus deleteKey(const std::vector<uint8_t>& in_inKeyBlob) override;
     ScopedAStatus deleteAllKeys() override;
     ScopedAStatus destroyAttestationIds() override;
+
     ScopedAStatus begin(KeyPurpose in_inPurpose, const std::vector<uint8_t>& in_inKeyBlob,
                         const std::vector<KeyParameter>& in_inParams,
                         const std::optional<HardwareAuthToken>& in_inAuthToken,
                         BeginResult* _aidl_return) override;
+    ScopedAStatus beginInternal(KeyPurpose in_inPurpose, const std::vector<uint8_t>& in_inKeyBlob,
+                                const std::vector<KeyParameter>& in_inParams,
+                                const std::optional<HardwareAuthToken>& in_inAuthToken,
+                                bool useReservedSlot, BeginResult* _aidl_return);
     ScopedAStatus deviceLocked(bool passwordOnly,
                                const std::optional<TimeStampToken>& timestampToken) override;
     ScopedAStatus earlyBootEnded() override;
@@ -143,9 +160,8 @@
 
 class KeyMintOperation : public aidl::android::hardware::security::keymint::BnKeyMintOperation {
   public:
-    KeyMintOperation(::android::sp<Keymaster> device, uint64_t operationHandle,
-                     OperationSlots* slots, bool isActive)
-        : mDevice(device), mOperationHandle(operationHandle), mOperationSlot(slots, isActive) {}
+    KeyMintOperation(::android::sp<Keymaster> device, uint64_t operationHandle, OperationSlot slot)
+        : mDevice(device), mOperationHandle(operationHandle), mOperationSlot(std::move(slot)) {}
     ~KeyMintOperation();
 
     ScopedAStatus updateAad(const std::vector<uint8_t>& input,
@@ -183,7 +199,7 @@
     std::vector<uint8_t> mUpdateBuffer;
     ::android::sp<Keymaster> mDevice;
     uint64_t mOperationHandle;
-    OperationSlot mOperationSlot;
+    std::optional<OperationSlot> mOperationSlot;
 };
 
 class SharedSecret : public aidl::android::hardware::security::sharedsecret::BnSharedSecret {
diff --git a/keystore2/src/km_compat/slot_test.cpp b/keystore2/src/km_compat/slot_test.cpp
index 3539c4d..d734970 100644
--- a/keystore2/src/km_compat/slot_test.cpp
+++ b/keystore2/src/km_compat/slot_test.cpp
@@ -26,6 +26,7 @@
 using ::aidl::android::hardware::security::keymint::BlockMode;
 using ::aidl::android::hardware::security::keymint::Certificate;
 using ::aidl::android::hardware::security::keymint::Digest;
+using ::aidl::android::hardware::security::keymint::EcCurve;
 using ::aidl::android::hardware::security::keymint::ErrorCode;
 using ::aidl::android::hardware::security::keymint::IKeyMintOperation;
 using ::aidl::android::hardware::security::keymint::KeyCharacteristics;
@@ -53,6 +54,25 @@
     return creationResult.keyBlob;
 }
 
+static bool generateECSingingKey(std::shared_ptr<KeyMintDevice> device) {
+    uint64_t now_ms = (uint64_t)time(nullptr) * 1000;
+
+    auto keyParams = std::vector<KeyParameter>({
+        KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::EC),
+        KMV1::makeKeyParameter(KMV1::TAG_EC_CURVE, EcCurve::P_256),
+        KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
+        KMV1::makeKeyParameter(KMV1::TAG_DIGEST, Digest::SHA_2_256),
+        KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
+        KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::VERIFY),
+        KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_BEFORE, now_ms - 60 * 60 * 1000),
+        KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_AFTER, now_ms + 60 * 60 * 1000),
+    });
+    KeyCreationResult creationResult;
+    auto status = device->generateKey(keyParams, std::nullopt /* attest_key */, &creationResult);
+    EXPECT_TRUE(status.isOk()) << status.getDescription();
+    return status.isOk();
+}
+
 static std::variant<BeginResult, ScopedAStatus> begin(std::shared_ptr<KeyMintDevice> device,
                                                       bool valid) {
     auto blob = generateAESKey(device);
@@ -69,6 +89,36 @@
     return beginResult;
 }
 
+static std::shared_ptr<KMV1::IKeyMintOperation>
+generateAndBeginECDHKeyOperation(std::shared_ptr<KeyMintDevice> device) {
+    uint64_t now_ms = (uint64_t)time(nullptr) * 1000;
+
+    auto keyParams = std::vector<KeyParameter>({
+        KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::EC),
+        KMV1::makeKeyParameter(KMV1::TAG_EC_CURVE, EcCurve::P_256),
+        KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
+        KMV1::makeKeyParameter(KMV1::TAG_DIGEST, Digest::NONE),
+        KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::AGREE_KEY),
+        KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_BEFORE, now_ms - 60 * 60 * 1000),
+        KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_AFTER, now_ms + 60 * 60 * 1000),
+    });
+    KeyCreationResult creationResult;
+    auto status = device->generateKey(keyParams, std::nullopt /* attest_key */, &creationResult);
+    EXPECT_TRUE(status.isOk()) << status.getDescription();
+    if (!status.isOk()) {
+        return {};
+    }
+    std::vector<KeyParameter> kps;
+    BeginResult beginResult;
+    auto bstatus = device->begin(KeyPurpose::AGREE_KEY, creationResult.keyBlob, kps,
+                                 HardwareAuthToken(), &beginResult);
+    EXPECT_TRUE(status.isOk()) << status.getDescription();
+    if (status.isOk()) {
+        return beginResult.operation;
+    }
+    return {};
+}
+
 static const int NUM_SLOTS = 2;
 
 TEST(SlotTest, TestSlots) {
@@ -82,6 +132,14 @@
     auto result = begin(device, false);
     ASSERT_TRUE(std::holds_alternative<ScopedAStatus>(result));
 
+    // Software emulated operations must not leak virtual slots.
+    ASSERT_TRUE(!!generateAndBeginECDHKeyOperation(device));
+
+    // Software emulated operations must not impact virtual slots accounting.
+    // As opposed to the previous call, the software operation is kept alive.
+    auto software_op = generateAndBeginECDHKeyOperation(device);
+    ASSERT_TRUE(!!software_op);
+
     // Fill up all the slots.
     std::vector<std::shared_ptr<IKeyMintOperation>> operations;
     for (int i = 0; i < NUM_SLOTS; i++) {
@@ -96,6 +154,14 @@
     ASSERT_EQ(std::get<ScopedAStatus>(result).getServiceSpecificError(),
               static_cast<int32_t>(ErrorCode::TOO_MANY_OPERATIONS));
 
+    // At this point all slots are in use. We should still be able to generate keys which
+    // require an operation slot during generation.
+    ASSERT_TRUE(generateECSingingKey(device));
+
+    // Software emulated operations should work despite having all virtual operation slots
+    // depleted.
+    ASSERT_TRUE(generateAndBeginECDHKeyOperation(device));
+
     // TODO: I'm not sure how to generate a failing update call to test that.
 
     // Calling finish should free up a slot.
diff --git a/ondevice-signing/odsign_main.cpp b/ondevice-signing/odsign_main.cpp
index 5c541ae..dadcf08 100644
--- a/ondevice-signing/odsign_main.cpp
+++ b/ondevice-signing/odsign_main.cpp
@@ -57,6 +57,7 @@
 constexpr bool kForceCompilation = false;
 constexpr bool kUseCompOs = true;
 
+constexpr const char* kNewCompOsVerifyPath = "/apex/com.android.compos/bin/compos_verify";
 const std::string kCompOsCert = "/data/misc/odsign/compos_key.cert";
 
 const std::string kCompOsCurrentPublicKey =
@@ -85,12 +86,6 @@
 
 namespace {
 
-std::vector<uint8_t> readBytesFromFile(const std::string& path) {
-    std::string str;
-    android::base::ReadFileToString(path, &str);
-    return std::vector<uint8_t>(str.begin(), str.end());
-}
-
 bool rename(const std::string& from, const std::string& to) {
     std::error_code ec;
     std::filesystem::rename(from, to, ec);
@@ -145,7 +140,7 @@
 
 bool compOsPresent() {
     // We must have the CompOS APEX
-    return access(kCompOsVerifyPath, X_OK) == 0;
+    return access(kNewCompOsVerifyPath, X_OK) == 0;
 }
 
 Result<void> verifyExistingRootCert(const SigningKey& key) {
@@ -182,108 +177,6 @@
     return createSelfSignedCertificate(*publicKey, keySignFunction, outPath);
 }
 
-Result<std::vector<uint8_t>> extractRsaPublicKeyFromLeafCert(const SigningKey& key,
-                                                             const std::string& certPath,
-                                                             const std::string& expectedCn) {
-    if (access(certPath.c_str(), F_OK) < 0) {
-        return ErrnoError() << "Certificate not found: " << certPath;
-    }
-    auto trustedPublicKey = key.getPublicKey();
-    if (!trustedPublicKey.ok()) {
-        return Error() << "Failed to retrieve signing public key: " << trustedPublicKey.error();
-    }
-
-    auto existingCertInfo = verifyAndExtractCertInfoFromX509(certPath, trustedPublicKey.value());
-    if (!existingCertInfo.ok()) {
-        return Error() << "Failed to verify certificate at " << certPath << ": "
-                       << existingCertInfo.error();
-    }
-
-    auto& actualCn = existingCertInfo.value().subjectCn;
-    if (actualCn != expectedCn) {
-        return Error() << "CN of existing certificate at " << certPath << " is " << actualCn
-                       << ", should be " << expectedCn;
-    }
-
-    return existingCertInfo.value().subjectRsaPublicKey;
-}
-
-// Attempt to start a CompOS VM for the specified instance to get it to
-// verify ita public key & key blob.
-bool startCompOsAndVerifyKey(CompOsInstance instance) {
-    bool isCurrent = instance == CompOsInstance::kCurrent;
-    const std::string& keyPath = isCurrent ? kCompOsCurrentPublicKey : kCompOsPendingPublicKey;
-    if (access(keyPath.c_str(), R_OK) != 0) {
-        return false;
-    }
-
-    const char* const argv[] = {kCompOsVerifyPath, "--instance", isCurrent ? "current" : "pending"};
-    int result =
-        logwrap_fork_execvp(arraysize(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
-    if (result == 0) {
-        return true;
-    }
-
-    LOG(ERROR) << kCompOsVerifyPath << " returned " << result;
-    return false;
-}
-
-Result<std::vector<uint8_t>> verifyCompOsKey(const SigningKey& signingKey) {
-    bool verified = false;
-
-    // If a pending key has been generated we don't know if it is the correct
-    // one for the pending CompOS VM, so we need to start it and ask it.
-    if (startCompOsAndVerifyKey(CompOsInstance::kPending)) {
-        verified = true;
-    }
-
-    if (!verified) {
-        // Alternatively if we signed a cert for the key on a previous boot, then we
-        // can use that straight away.
-        auto existing_key =
-            extractRsaPublicKeyFromLeafCert(signingKey, kCompOsCert, kCompOsSubject.commonName);
-        if (existing_key.ok()) {
-            LOG(INFO) << "Found and verified existing CompOS public key certificate: "
-                      << kCompOsCert;
-            return existing_key.value();
-        }
-    }
-
-    // Otherwise, if there is an existing key that we haven't signed yet, then we can sign
-    // it now if CompOS confirms it's OK.
-    if (!verified && startCompOsAndVerifyKey(CompOsInstance::kCurrent)) {
-        verified = true;
-    }
-
-    if (!verified) {
-        return Error() << "No valid CompOS key present.";
-    }
-
-    // If the pending key was verified it will have been promoted to current, so
-    // at this stage if there is a key it will be the current one.
-    auto publicKey = readBytesFromFile(kCompOsCurrentPublicKey);
-    if (publicKey.empty()) {
-        // This shouldn`t really happen.
-        return Error() << "Failed to read CompOS key.";
-    }
-
-    // One way or another we now have a valid public key. Persist a certificate so
-    // we can simplify the checks on subsequent boots.
-
-    auto signFunction = [&](const std::string& to_be_signed) {
-        return signingKey.sign(to_be_signed);
-    };
-    auto certStatus = createLeafCertificate(kCompOsSubject, publicKey, signFunction,
-                                            kSigningKeyCert, kCompOsCert);
-    if (!certStatus.ok()) {
-        return Error() << "Failed to create CompOS cert: " << certStatus.error();
-    }
-
-    LOG(INFO) << "Verified key, wrote new CompOS cert";
-
-    return publicKey;
-}
-
 Result<std::map<std::string, std::string>> computeDigests(const std::string& path) {
     std::error_code ec;
     std::map<std::string, std::string> digests;
@@ -439,27 +332,17 @@
     return {};
 }
 
-Result<std::vector<uint8_t>> addCompOsCertToFsVerityKeyring(const SigningKey& signingKey) {
-    auto publicKey = verifyCompOsKey(signingKey);
-    if (!publicKey.ok()) {
-        return publicKey.error();
-    }
-
-    auto cert_add_result = addCertToFsVerityKeyring(kCompOsCert, "fsv_compos");
-    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: "
-                       << cert_add_result.error();
-    }
-
-    return publicKey;
+Result<std::vector<uint8_t>> addCompOsCertToFsVerityKeyring(const SigningKey& /*signingKey*/) {
+    // TODO(b/218494522): Remove this and usages of compos_key.
+    return {};
 }
 
-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;
+Result<OdsignInfo> getComposInfo(const std::vector<uint8_t>& /*compos_key*/) {
+    const char* const argv[] = {kCompOsVerifyPath, "--instance", "current"};
+    int result =
+        logwrap_fork_execvp(arraysize(argv), argv, nullptr, false, LOG_ALOG, false, nullptr);
+    if (result != 0) {
+        return Error() << kCompOsVerifyPath << " returned " << result;
     }
 
     std::string compos_info_str;
@@ -467,21 +350,12 @@
         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.
+    // Delete the files - we don't need them any more, and they'd confuse
+    // artifact verification
     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;