Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0d6204e2 authored by Tri Vo's avatar Tri Vo
Browse files

Update VtsHalRemotelyProvisionedComponentTargetTest to v3

Bug: 235265072
Test: atest VtsHalRemotelyProvisionedComponentTargetTest
Change-Id: I01e387a0784c3548a4661a73d7bd3d5bec9fb42e
parent f48a2a7b
Loading
Loading
Loading
Loading
+156 −7
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ using ::std::vector;
namespace {

constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
constexpr int32_t VERSION_WITHOUT_TEST_MODE = 3;

#define INSTANTIATE_REM_PROV_AIDL_TEST(name)                                         \
    GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name);                             \
@@ -180,6 +181,15 @@ class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::
        return params;
    }

    void checkMacedPubkeyVersioned(const MacedPublicKey& macedPubKey, bool testMode,
                                   vector<uint8_t>* payload_value) {
        if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
            check_maced_pubkey(macedPubKey, false, payload_value);
        } else {
            check_maced_pubkey(macedPubKey, testMode, payload_value);
        }
    }

  protected:
    std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
    RpcHardwareInfo rpcHardwareInfo;
@@ -256,7 +266,7 @@ TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
    auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
    ASSERT_TRUE(status.isOk());
    vector<uint8_t> coseKeyData;
    check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
    checkMacedPubkeyVersioned(macedPubKey, testMode, &coseKeyData);
}

/**
@@ -279,7 +289,7 @@ TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
    auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
    ASSERT_TRUE(status.isOk());
    vector<uint8_t> coseKeyData;
    check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
    checkMacedPubkeyVersioned(macedPubKey, testMode, &coseKeyData);

    AttestationKey attestKey;
    attestKey.keyBlob = std::move(privateKeyBlob);
@@ -334,13 +344,13 @@ TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
    bool testMode = true;
    auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
    ASSERT_TRUE(status.isOk());

    check_maced_pubkey(macedPubKey, testMode, nullptr);
    checkMacedPubkeyVersioned(macedPubKey, testMode, nullptr);
}

class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
  protected:
    CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
    CertificateRequestTestBase()
        : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}

    void generateTestEekChain(size_t eekLength) {
        auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
@@ -359,7 +369,7 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
            ASSERT_TRUE(status.isOk()) << status.getMessage();

            vector<uint8_t> payload_value;
            check_maced_pubkey(key, testMode, &payload_value);
            checkMacedPubkeyVersioned(key, testMode, &payload_value);
            cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
        }
    }
@@ -372,6 +382,18 @@ class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
    cppbor::Array cborKeysToSign_;
};

class CertificateRequestTest : public CertificateRequestTestBase {
  protected:
    void SetUp() override {
        CertificateRequestTestBase::SetUp();

        if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
            GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
                         << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
        }
    }
};

/**
 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
 * content.
@@ -638,4 +660,131 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {

INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);

class CertificateRequestV2Test : public CertificateRequestTestBase {
    void SetUp() override {
        CertificateRequestTestBase::SetUp();

        if (rpcHardwareInfo.versionNumber < VERSION_WITHOUT_TEST_MODE) {
            GTEST_SKIP() << "This test case only applies to RKP v3 and above. "
                         << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
        }
    }
};

/**
 * Generate an empty certificate request, and decrypt and verify the structure and content.
 */
TEST_P(CertificateRequestV2Test, EmptyRequest) {
    bytevec csr;

    auto status =
            provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
    ASSERT_TRUE(status.isOk()) << status.getMessage();

    auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
    ASSERT_TRUE(result) << result.message();
}

/**
 * Generate a non-empty certificate request.  Decrypt, parse and validate the contents.
 */
TEST_P(CertificateRequestV2Test, NonEmptyRequest) {
    generateKeys(false /* testMode */, 1 /* numKeys */);

    bytevec csr;

    auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
    ASSERT_TRUE(status.isOk()) << status.getMessage();

    auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
    ASSERT_TRUE(result) << result.message();
}

/**
 * Generate a non-empty certificate request.  Make sure contents are reproducible.
 */
TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) {
    generateKeys(false /* testMode */, 1 /* numKeys */);

    bytevec csr;

    auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
    ASSERT_TRUE(status.isOk()) << status.getMessage();

    auto firstBcc = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
    ASSERT_TRUE(firstBcc) << firstBcc.message();

    status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
    ASSERT_TRUE(status.isOk()) << status.getMessage();

    auto secondBcc = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
    ASSERT_TRUE(secondBcc) << secondBcc.message();

    ASSERT_EQ(firstBcc->size(), secondBcc->size());
    for (auto i = 0; i < firstBcc->size(); i++) {
        ASSERT_EQ(firstBcc->at(i).pubKey, secondBcc->at(i).pubKey);
    }
}

/**
 * Generate a non-empty certificate request with multiple keys.
 */
TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) {
    // TODO(b/254137722): define a minimum number of keys that must be supported.
    generateKeys(false /* testMode */, 5 /* numKeys */);

    bytevec csr;

    auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
    ASSERT_TRUE(status.isOk()) << status.getMessage();

    auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
    ASSERT_TRUE(result) << result.message();
}

/**
 * Generate a non-empty certificate request, but with the MAC corrupted on the keypair.
 */
TEST_P(CertificateRequestV2Test, NonEmptyRequestCorruptMac) {
    generateKeys(false /* testMode */, 1 /* numKeys */);
    auto result = corrupt_maced_key(keysToSign_[0]);
    ASSERT_TRUE(result) << result.moveMessage();
    MacedPublicKey keyWithCorruptMac = result.moveValue();

    bytevec csr;
    auto status =
            provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
    ASSERT_FALSE(status.isOk()) << status.getMessage();
    EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
}

/**
 * Generate a non-empty certificate request in prod mode, with test keys.  Test mode must be
 * ignored, i.e. test must pass.
 */
TEST_P(CertificateRequestV2Test, NonEmptyRequest_testKeyInProdCert) {
    generateKeys(true /* testMode */, 1 /* numKeys */);

    bytevec csr;
    auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
    ASSERT_TRUE(status.isOk()) << status.getMessage();
}

/**
 * Call generateCertificateRequest(). Make sure it's removed.
 */
TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed) {
    generateTestEekChain(2);
    bytevec keysToSignMac;
    DeviceInfo deviceInfo;
    ProtectedData protectedData;
    auto status = provisionable_->generateCertificateRequest(
            true /* testMode */, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
            &protectedData, &keysToSignMac);
    ASSERT_FALSE(status.isOk()) << status.getMessage();
    EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
}

INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);

}  // namespace aidl::android::hardware::security::keymint::test
+15 −0
Original line number Diff line number Diff line
@@ -177,4 +177,19 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData(
        const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);

/**
 * Verify the CSR as if the device is still early in the factory process and may not
 * have all device identifiers provisioned yet.
 */
ErrMsgOr<std::vector<BccEntryData>> verifyFactoryCsr(const cppbor::Array& keysToSign,
                                                     const std::vector<uint8_t>& csr,
                                                     IRemotelyProvisionedComponent* provisionable,
                                                     const std::vector<uint8_t>& challenge);
/**
 * Verify the CSR as if the device is a final production sample.
 */
ErrMsgOr<std::vector<BccEntryData>> verifyProductionCsr(
        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);

}  // namespace aidl::android::hardware::security::keymint::remote_prov
+282 −14
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <openssl/base64.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
#include <remote_prov/remote_prov_utils.h>

namespace aidl::android::hardware::security::keymint::remote_prov {
@@ -45,6 +46,8 @@ constexpr int kP256AffinePointSize = 32;
using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;
using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
using EVP_PKEY_CTX_Ptr = bssl::UniquePtr<EVP_PKEY_CTX>;
using X509_Ptr = bssl::UniquePtr<X509>;
using CRYPTO_BUFFER_Ptr = bssl::UniquePtr<CRYPTO_BUFFER>;

ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) {
    // Extract private key.
@@ -527,6 +530,10 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
    if (parsed->clone()->asMap()->canonicalize().encode() != deviceInfoBytes) {
        return "DeviceInfo ordering is non-canonical.";
    }

    RpcHardwareInfo info;
    provisionable->getHardwareInfo(&info);
    if (info.versionNumber < 3) {
        const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
        if (!version) {
            return "Device info is missing version";
@@ -534,15 +541,16 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
        if (!version->asUint()) {
            return "version must be an unsigned integer";
        }
    RpcHardwareInfo info;
    provisionable->getHardwareInfo(&info);
        if (version->asUint()->value() != info.versionNumber) {
            return "DeviceInfo version (" + std::to_string(version->asUint()->value()) +
                   ") does not match the remotely provisioned component version (" +
                   std::to_string(info.versionNumber) + ").";
        }
    }

    std::string error;
    switch (version->asUint()->value()) {
    switch (info.versionNumber) {
        case 3:
        case 2:
            for (const auto& entry : kAttestationIdEntrySet) {
                error += checkMapEntry(isFactory && !entry.alwaysValidate, *parsed, cppbor::TSTR,
@@ -579,7 +587,7 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
                                   kValidAttIdStates);
            break;
        default:
            return "Unrecognized version: " + std::to_string(version->asUint()->value());
            return "Unrecognized version: " + std::to_string(info.versionNumber);
    }

    if (!error.empty()) {
@@ -734,4 +742,264 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData(
                               /*isFactory=*/false);
}

ErrMsgOr<X509_Ptr> parseX509Cert(const std::vector<uint8_t>& cert) {
    CRYPTO_BUFFER_Ptr certBuf(CRYPTO_BUFFER_new(cert.data(), cert.size(), nullptr));
    if (!certBuf.get()) {
        return "Failed to create crypto buffer.";
    }
    X509_Ptr result(X509_parse_from_buffer(certBuf.get()));
    if (!result.get()) {
        return "Failed to parse certificate.";
    }
    return result;
}

std::string getX509IssuerName(const X509_Ptr& cert) {
    char* name = X509_NAME_oneline(X509_get_issuer_name(cert.get()), nullptr, 0);
    std::string result(name);
    OPENSSL_free(name);
    return result;
}

std::string getX509SubjectName(const X509_Ptr& cert) {
    char* name = X509_NAME_oneline(X509_get_subject_name(cert.get()), nullptr, 0);
    std::string result(name);
    OPENSSL_free(name);
    return result;
}

// Validates the certificate chain and returns the leaf public key.
ErrMsgOr<bytevec> validateCertChain(const cppbor::Array& chain) {
    uint8_t rawPubKey[64];
    size_t rawPubKeySize = sizeof(rawPubKey);
    for (size_t i = 0; i < chain.size(); ++i) {
        // Root must be self-signed.
        size_t signingCertIndex = (i > 1) ? i - 1 : i;
        auto& keyCertItem = chain[i];
        auto& signingCertItem = chain[signingCertIndex];
        if (!keyCertItem || !keyCertItem->asBstr()) {
            return "Key certificate must be a Bstr.";
        }
        if (!signingCertItem || !signingCertItem->asBstr()) {
            return "Signing certificate must be a Bstr.";
        }

        auto keyCert = parseX509Cert(keyCertItem->asBstr()->value());
        if (!keyCert) {
            return keyCert.message();
        }
        auto signingCert = parseX509Cert(keyCertItem->asBstr()->value());
        if (!signingCert) {
            return signingCert.message();
        }

        EVP_PKEY_Ptr pubKey(X509_get_pubkey(keyCert->get()));
        if (!pubKey.get()) {
            return "Failed to get public key.";
        }
        EVP_PKEY_Ptr signingPubKey(X509_get_pubkey(signingCert->get()));
        if (!signingPubKey.get()) {
            return "Failed to get signing public key.";
        }

        if (!X509_verify(keyCert->get(), signingPubKey.get())) {
            return "Verification of certificate " + std::to_string(i) +
                   " faile. OpenSSL error string: " + ERR_error_string(ERR_get_error(), NULL);
        }

        auto certIssuer = getX509IssuerName(*keyCert);
        auto signerSubj = getX509SubjectName(*signingCert);
        if (certIssuer != signerSubj) {
            return "Certificate " + std::to_string(i) + " has wrong issuer. Signer subject is " +
                   signerSubj + " Issuer subject is " + certIssuer;
        }

        rawPubKeySize = sizeof(rawPubKey);
        if (!EVP_PKEY_get_raw_public_key(pubKey.get(), rawPubKey, &rawPubKeySize)) {
            return "Failed to get raw public key.";
        }
    }

    return bytevec(rawPubKey, rawPubKey + rawPubKeySize);
}

std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsPub) {
    for (const auto& [signerName, udsCertChain] : udsCerts) {
        if (!signerName || !signerName->asTstr()) {
            return "Signer Name must be a Tstr.";
        }
        if (!udsCertChain || !udsCertChain->asArray()) {
            return "UDS certificate chain must be an Array.";
        }
        if (udsCertChain->asArray()->size() < 2) {
            return "UDS certificate chain must have at least two entries: root and leaf.";
        }

        auto leafPubKey = validateCertChain(*udsCertChain->asArray());
        if (!leafPubKey) {
            return leafPubKey.message();
        }
        if (*leafPubKey != udsPub) {
            return "Leaf public key in UDS certificat chain doesn't match UDS public key.";
        }
    }
    return "";
}

ErrMsgOr<cppbor::Array> parseAndValidateCsrPayload(const cppbor::Array& keysToSign,
                                                   const std::vector<uint8_t>& csrPayload,
                                                   IRemotelyProvisionedComponent* provisionable,
                                                   const std::vector<uint8_t>& challenge,
                                                   bool isFactory) {
    auto [parsedCsrPayload, _, errMsg] = cppbor::parse(csrPayload);
    if (!parsedCsrPayload) {
        return errMsg;
    }
    if (!parsedCsrPayload->asArray()) {
        return "CSR payload is not a CBOR array.";
    }
    if (parsedCsrPayload->asArray()->size() != 5U) {
        return "CSR payload must contain version, certificate type, device info, challenge, keys. "
               "However, the parsed CSR payload has " +
               std::to_string(parsedCsrPayload->asArray()->size()) + " entries.";
    }

    auto& signedVersion = parsedCsrPayload->asArray()->get(0);
    auto& signedCertificateType = parsedCsrPayload->asArray()->get(1);
    auto& signedDeviceInfo = parsedCsrPayload->asArray()->get(2);
    auto& signedChallenge = parsedCsrPayload->asArray()->get(3);
    auto& signedKeys = parsedCsrPayload->asArray()->get(4);

    if (!signedVersion || !signedVersion->asUint() || signedVersion->asUint()->value() != 1U) {
        return "CSR payload version must be an unsigned integer and must be equal to 1.";
    }
    if (!signedCertificateType || !signedCertificateType->asTstr()) {
        // Certificate type is allowed to be extendend by vendor, i.e. we can't
        // enforce its value.
        return "Certificate type must be a Tstr.";
    }
    if (!signedDeviceInfo || !signedDeviceInfo->asMap()) {
        return "Device info must be an Map.";
    }
    if (!signedChallenge || !signedChallenge->asBstr()) {
        return "Challenge must be a Bstr.";
    }
    if (!signedKeys || !signedKeys->asArray()) {
        return "Keys must be an Array.";
    }

    auto result = parseAndValidateDeviceInfo(signedDeviceInfo->asMap()->encode(), provisionable,
                                             isFactory);
    if (!result) {
        return result.message();
    }

    if (challenge.size() < 32 || challenge.size() > 64) {
        return "Challenge size must be between 32 and 64 bytes inclusive. "
               "However, challenge is " +
               std::to_string(challenge.size()) + " bytes long.";
    }

    auto challengeBstr = cppbor::Bstr(challenge);
    if (*signedChallenge->asBstr() != challengeBstr) {
        return "Signed challenge does not match."
               "\n  Actual: " +
               cppbor::prettyPrint(signedChallenge->asBstr(), 64 /* maxBStrSize */) +
               "\nExpected: " + cppbor::prettyPrint(&challengeBstr, 64 /* maxBStrSize */);
    }

    if (signedKeys->asArray()->encode() != keysToSign.encode()) {
        return "Signed keys do not match.";
    }

    return std::move(*parsedCsrPayload->asArray());
}

ErrMsgOr<std::vector<BccEntryData>> verifyCsr(const cppbor::Array& keysToSign,
                                              const std::vector<uint8_t>& csr,
                                              IRemotelyProvisionedComponent* provisionable,
                                              const std::vector<uint8_t>& challenge,
                                              bool isFactory) {
    auto [parsedCsr, _, csrErrMsg] = cppbor::parse(csr);
    if (!parsedCsr) {
        return csrErrMsg;
    }
    if (!parsedCsr->asArray()) {
        return "CSR is not a CBOR array.";
    }
    if (parsedCsr->asArray()->size() != 4U) {
        return "CSR must contain version, UDS certificates, DICE chain, and signed data. "
               "However, the parsed CSR has " +
               std::to_string(parsedCsr->asArray()->size()) + " entries.";
    }

    auto& version = parsedCsr->asArray()->get(0);
    auto& udsCerts = parsedCsr->asArray()->get(1);
    auto& diceCertChain = parsedCsr->asArray()->get(2);
    auto& signedData = parsedCsr->asArray()->get(3);

    if (!version || !version->asUint() || version->asUint()->value() != 3U) {
        return "Version must be an unsigned integer and must be equal to 3.";
    }
    if (!udsCerts || !udsCerts->asMap()) {
        return "UdsCerts must be an Map.";
    }
    if (!diceCertChain || !diceCertChain->asArray()) {
        return "DiceCertChain must be an Array.";
    }
    if (!signedData || !signedData->asArray()) {
        return "SignedData must be an Array.";
    }

    RpcHardwareInfo info;
    provisionable->getHardwareInfo(&info);
    if (version->asUint()->value() != info.versionNumber) {
        return "CSR version (" + std::to_string(version->asUint()->value()) +
               ") does not match the remotely provisioned component version (" +
               std::to_string(info.versionNumber) + ").";
    }

    // DICE chain is [ pubkey, + DiceChainEntry ]. Its format is the same as BCC from RKP v1-2.
    auto diceContents = validateBcc(diceCertChain->asArray());
    if (!diceContents) {
        return diceContents.message() + "\n" + prettyPrint(diceCertChain.get());
    }
    if (diceContents->size() == 0U) {
        return "The DICE chain is empty. It must contain at least one entry.";
    }

    auto& udsPub = diceContents->back().pubKey;

    auto error = validateUdsCerts(*udsCerts->asMap(), udsPub);
    if (!error.empty()) {
        return error;
    }

    auto csrPayload = verifyAndParseCoseSign1(signedData->asArray(), udsPub, {} /* aad */);
    if (!csrPayload) {
        return csrPayload.message();
    }

    auto parsedCsrPayload = parseAndValidateCsrPayload(keysToSign, *csrPayload, provisionable,
                                                       challenge, isFactory);
    if (!parsedCsrPayload) {
        return parsedCsrPayload.message();
    }

    return *diceContents;
}

ErrMsgOr<std::vector<BccEntryData>> verifyFactoryCsr(const cppbor::Array& keysToSign,
                                                     const std::vector<uint8_t>& csr,
                                                     IRemotelyProvisionedComponent* provisionable,
                                                     const std::vector<uint8_t>& challenge) {
    return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/true);
}

ErrMsgOr<std::vector<BccEntryData>> verifyProductionCsr(
        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
        IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
    return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false);
}

}  // namespace aidl::android::hardware::security::keymint::remote_prov