Update VtsHalRemotelyProvisionedComponentTargetTest to v3
Bug: 235265072
Test: atest VtsHalRemotelyProvisionedComponentTargetTest
Change-Id: I01e387a0784c3548a4661a73d7bd3d5bec9fb42e
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 9b21e4e..4f361bb 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -46,6 +46,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
diff --git a/security/keymint/support/include/remote_prov/remote_prov_utils.h b/security/keymint/support/include/remote_prov/remote_prov_utils.h
index 9ea20ac..6871e1b 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -177,4 +177,19 @@
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
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 0651496..f7ab3ac 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -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 @@
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,22 +530,27 @@
if (parsed->clone()->asMap()->canonicalize().encode() != deviceInfoBytes) {
return "DeviceInfo ordering is non-canonical.";
}
- const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
- if (!version) {
- return "Device info is missing version";
- }
- 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) + ").";
+ if (info.versionNumber < 3) {
+ const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
+ if (!version) {
+ return "Device info is missing version";
+ }
+ if (!version->asUint()) {
+ return "version must be an unsigned integer";
+ }
+ 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 @@
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 @@
/*isFactory=*/false);
}
-} // namespace aidl::android::hardware::security::keymint::remote_prov
\ No newline at end of file
+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