Loading security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp +7 −3 Original line number Diff line number Diff line Loading @@ -79,9 +79,13 @@ void KeyMintRemoteProv::process() { while (mFdp.remaining_bytes()) { auto invokeProvAPI = mFdp.PickValueInArray<const std::function<void()>>({ [&]() { verifyFactoryCsr(cborKeysToSign, csr, gRPC.get(), challenge); }, [&]() { verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), challenge); }, [&]() { isCsrWithProperDiceChain(csr); }, [&]() { verifyFactoryCsr(cborKeysToSign, csr, gRPC.get(), kServiceName, challenge); }, [&]() { verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), kServiceName, challenge); }, [&]() { isCsrWithProperDiceChain(csr, kServiceName); }, }); invokeProvAPI(); } Loading security/keymint/support/include/remote_prov/remote_prov_utils.h +17 −9 Original line number Diff line number Diff line Loading @@ -89,6 +89,11 @@ inline constexpr uint8_t kCoseEncodedEcdsa256GeekCert[] = { */ bytevec randomBytes(size_t numBytes); const std::string DEFAULT_INSTANCE_NAME = "android.hardware.security.keymint.IRemotelyProvisionedComponent/default"; const std::string RKPVM_INSTANCE_NAME = "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf"; struct EekChain { bytevec chain; bytevec last_pubkey; Loading Loading @@ -160,7 +165,8 @@ ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge); /** * Verify the protected data as if the device is a final production sample. */ Loading @@ -168,8 +174,8 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowAnyMode = false); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowAnyMode = false); /** * Verify the CSR as if the device is still early in the factory process and may not Loading @@ -177,22 +183,24 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData( */ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr( const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowDegenerate = true); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowDegenerate = true); /** * Verify the CSR as if the device is a final production sample. */ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr( const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowAnyMode = false); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowAnyMode = false); /** Checks whether the CSR has a proper DICE chain. */ ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr); ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr, const std::string& instanceName); /** Verify the DICE chain. */ ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc, hwtrust::DiceChain::Kind kind, bool allowAnyMode, bool allowDegenerate); bool allowDegenerate, const std::string& instanceName); } // namespace aidl::android::hardware::security::keymint::remote_prov security/keymint/support/remote_prov_utils.cpp +38 −22 Original line number Diff line number Diff line Loading @@ -52,6 +52,14 @@ using EVP_PKEY_CTX_Ptr = bssl::UniquePtr<EVP_PKEY_CTX>; using X509_Ptr = bssl::UniquePtr<X509>; using CRYPTO_BUFFER_Ptr = bssl::UniquePtr<CRYPTO_BUFFER>; std::string device_suffix(const std::string& name) { size_t pos = name.find('/'); if (pos == std::string::npos) { return name; } return name.substr(pos + 1); } ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) { // Extract private key. const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey); Loading Loading @@ -325,7 +333,8 @@ bytevec getProdEekChain(int32_t supportedEekCurve) { ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc, hwtrust::DiceChain::Kind kind, bool allowAnyMode, bool allowDegenerate) { bool allowDegenerate, const std::string& instanceName) { auto encodedBcc = bcc->encode(); // Use ro.build.type instead of ro.debuggable because ro.debuggable=1 for VTS testing Loading @@ -334,7 +343,8 @@ ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc, allowAnyMode = true; } auto chain = hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode); auto chain = hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode, device_suffix(instanceName)); if (!chain.ok()) return chain.error().message(); if (!allowDegenerate && !chain->IsProper()) { Loading Loading @@ -649,8 +659,8 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false) { IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false) { auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData); if (!parsedProtectedData) { return protDataErrMsg; Loading Loading @@ -707,7 +717,7 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData( // BCC is [ pubkey, + BccEntry] auto bccContents = validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr13, allowAnyMode, /*allowDegenerate=*/true); /*allowDegenerate=*/true, instanceName); if (!bccContents) { return bccContents.message() + "\n" + prettyPrint(bcc.get()); } Loading Loading @@ -750,9 +760,10 @@ ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) { IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge) { return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain, eekId, supportedEekCurve, provisionable, challenge, eekId, supportedEekCurve, provisionable, instanceName, challenge, /*isFactory=*/true); } Loading @@ -760,10 +771,10 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowAnyMode) { IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowAnyMode) { return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain, eekId, supportedEekCurve, provisionable, challenge, eekId, supportedEekCurve, provisionable, instanceName, challenge, /*isFactory=*/false, allowAnyMode); } Loading Loading @@ -1003,6 +1014,7 @@ ErrMsgOr<hwtrust::DiceChain::Kind> getDiceChainKind() { ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t>& request, const std::vector<uint8_t>& challenge, const std::string& instanceName, bool allowAnyMode = false, bool allowDegenerate = true) { auto [parsedRequest, _, csrErrMsg] = cppbor::parse(request); Loading Loading @@ -1042,7 +1054,8 @@ ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t return diceChainKind.message(); } auto diceContents = validateBcc(diceCertChain, *diceChainKind, allowAnyMode, allowDegenerate); auto diceContents = validateBcc(diceCertChain, *diceChainKind, allowAnyMode, allowDegenerate, instanceName); if (!diceContents) { return diceContents.message() + "\n" + prettyPrint(diceCertChain); } Loading Loading @@ -1071,6 +1084,7 @@ ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false, bool allowDegenerate = true) { Loading @@ -1081,8 +1095,8 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSi ") does not match expected version (3)."; } auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge, allowAnyMode, allowDegenerate); auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge, instanceName, allowAnyMode, allowDegenerate); if (!csrPayload) { return csrPayload.message(); } Loading @@ -1092,20 +1106,22 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSi ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr( const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowDegenerate) { return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/true, IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowDegenerate) { return verifyCsr(keysToSign, csr, provisionable, instanceName, challenge, /*isFactory=*/true, /*allowAnyMode=*/false, allowDegenerate); } ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr( const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowAnyMode) { return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false, allowAnyMode); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowAnyMode) { return verifyCsr(keysToSign, csr, provisionable, instanceName, challenge, /*isFactory=*/false, allowAnyMode); } ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr) { ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr, const std::string& instanceName) { auto [parsedRequest, _, csrErrMsg] = cppbor::parse(csr); if (!parsedRequest) { return csrErrMsg; Loading Loading @@ -1136,8 +1152,8 @@ ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr) { } auto encodedDiceChain = diceCertChain->encode(); auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind, /*allowAnyMode=*/false); auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind, /*allowAnyMode=*/false, device_suffix(instanceName)); if (!chain.ok()) return chain.error().message(); return chain->IsProper(); } Loading security/keymint/support/remote_prov_utils_test.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -298,9 +298,11 @@ TEST(RemoteProvUtilsTest, validateBccDegenerate) { ASSERT_TRUE(bcc) << "Error: " << errMsg; EXPECT_TRUE(validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr16, /*allowAnyMode=*/false, /*allowDegenerate=*/true)); /*allowAnyMode=*/false, /*allowDegenerate=*/true, DEFAULT_INSTANCE_NAME)); EXPECT_FALSE(validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr16, /*allowAnyMode=*/false, /*allowDegenerate=*/false)); /*allowAnyMode=*/false, /*allowDegenerate=*/false, DEFAULT_INSTANCE_NAME)); } } // namespace } // namespace aidl::android::hardware::security::keymint::remote_prov security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp +26 −26 Original line number Diff line number Diff line Loading @@ -55,10 +55,7 @@ constexpr int32_t VERSION_WITH_SUPPORTED_NUM_KEYS_IN_CSR = 3; constexpr uint8_t MIN_CHALLENGE_SIZE = 0; constexpr uint8_t MAX_CHALLENGE_SIZE = 64; const string DEFAULT_INSTANCE_NAME = "android.hardware.security.keymint.IRemotelyProvisionedComponent/default"; const string RKP_VM_INSTANCE_NAME = "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf"; const string KEYMINT_STRONGBOX_INSTANCE_NAME = "android.hardware.security.keymint.IKeyMintDevice/strongbox"; Loading Loading @@ -188,7 +185,7 @@ class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std:: } ASSERT_NE(provisionable_, nullptr); auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo); isRkpVmInstance_ = GetParam() == RKP_VM_INSTANCE_NAME; isRkpVmInstance_ = GetParam() == RKPVM_INSTANCE_NAME; if (isRkpVmInstance_) { if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) { GTEST_SKIP() << "The RKP VM is not supported on this system."; Loading Loading @@ -227,7 +224,7 @@ TEST(NonParameterizedTests, eachRpcHasAUniqueId) { RpcHardwareInfo hwInfo; auto status = rpc->getHardwareInfo(&hwInfo); if (hal == RKP_VM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) { if (hal == RKPVM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) { GTEST_SKIP() << "The RKP VM is not supported on this system."; } ASSERT_TRUE(status.isOk()); Loading Loading @@ -268,7 +265,7 @@ TEST(NonParameterizedTests, requireDiceOnDefaultInstanceIfStrongboxPresent) { auto status = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr); EXPECT_TRUE(status.isOk()) << status.getDescription(); auto result = isCsrWithProperDiceChain(csr); auto result = isCsrWithProperDiceChain(csr, DEFAULT_INSTANCE_NAME); ASSERT_TRUE(result) << result.message(); ASSERT_TRUE(*result); } Loading Loading @@ -494,7 +491,7 @@ TEST_P(CertificateRequestTest, EmptyRequest_testMode) { auto result = verifyProductionProtectedData( deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_); rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(result) << result.message(); } } Loading @@ -517,9 +514,10 @@ TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) { &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto firstBcc = verifyProductionProtectedData( deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_); auto firstBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(firstBcc) << firstBcc.message(); status = provisionable_->generateCertificateRequest( Loading @@ -527,9 +525,10 @@ TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) { &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto secondBcc = verifyProductionProtectedData( deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_); auto secondBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(secondBcc) << secondBcc.message(); // Verify that none of the keys in the first BCC are repeated in the second one. Loading Loading @@ -579,7 +578,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) { auto result = verifyProductionProtectedData( deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_); rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(result) << result.message(); } } Loading Loading @@ -767,8 +766,8 @@ TEST_P(CertificateRequestV2Test, EmptyRequest) { provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge, isRkpVmInstance_); auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), GetParam(), challenge, isRkpVmInstance_); ASSERT_TRUE(result) << result.message(); } } Loading @@ -789,8 +788,8 @@ TEST_P(CertificateRequestV2Test, NonEmptyRequest) { auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge, isRkpVmInstance_); auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(), challenge, isRkpVmInstance_); ASSERT_TRUE(result) << result.message(); } } Loading Loading @@ -820,15 +819,15 @@ TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) { auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_, isRkpVmInstance_); auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(), challenge_, isRkpVmInstance_); ASSERT_TRUE(firstCsr) << firstCsr.message(); status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_, isRkpVmInstance_); auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(), challenge_, isRkpVmInstance_); ASSERT_TRUE(secondCsr) << secondCsr.message(); ASSERT_EQ(**firstCsr, **secondCsr); Loading @@ -846,8 +845,8 @@ TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) { auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_, isRkpVmInstance_); auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(), challenge_, isRkpVmInstance_); ASSERT_TRUE(result) << result.message(); } Loading Loading @@ -977,7 +976,8 @@ TEST_P(CertificateRequestV2Test, DeviceInfo) { provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr); ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getDescription(); auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_); auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(result) << result.message(); std::unique_ptr<cppbor::Array> csrPayload = std::move(*result); Loading Loading
security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp +7 −3 Original line number Diff line number Diff line Loading @@ -79,9 +79,13 @@ void KeyMintRemoteProv::process() { while (mFdp.remaining_bytes()) { auto invokeProvAPI = mFdp.PickValueInArray<const std::function<void()>>({ [&]() { verifyFactoryCsr(cborKeysToSign, csr, gRPC.get(), challenge); }, [&]() { verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), challenge); }, [&]() { isCsrWithProperDiceChain(csr); }, [&]() { verifyFactoryCsr(cborKeysToSign, csr, gRPC.get(), kServiceName, challenge); }, [&]() { verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), kServiceName, challenge); }, [&]() { isCsrWithProperDiceChain(csr, kServiceName); }, }); invokeProvAPI(); } Loading
security/keymint/support/include/remote_prov/remote_prov_utils.h +17 −9 Original line number Diff line number Diff line Loading @@ -89,6 +89,11 @@ inline constexpr uint8_t kCoseEncodedEcdsa256GeekCert[] = { */ bytevec randomBytes(size_t numBytes); const std::string DEFAULT_INSTANCE_NAME = "android.hardware.security.keymint.IRemotelyProvisionedComponent/default"; const std::string RKPVM_INSTANCE_NAME = "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf"; struct EekChain { bytevec chain; bytevec last_pubkey; Loading Loading @@ -160,7 +165,8 @@ ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge); /** * Verify the protected data as if the device is a final production sample. */ Loading @@ -168,8 +174,8 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowAnyMode = false); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowAnyMode = false); /** * Verify the CSR as if the device is still early in the factory process and may not Loading @@ -177,22 +183,24 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData( */ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr( const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowDegenerate = true); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowDegenerate = true); /** * Verify the CSR as if the device is a final production sample. */ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr( const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowAnyMode = false); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowAnyMode = false); /** Checks whether the CSR has a proper DICE chain. */ ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr); ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr, const std::string& instanceName); /** Verify the DICE chain. */ ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc, hwtrust::DiceChain::Kind kind, bool allowAnyMode, bool allowDegenerate); bool allowDegenerate, const std::string& instanceName); } // namespace aidl::android::hardware::security::keymint::remote_prov
security/keymint/support/remote_prov_utils.cpp +38 −22 Original line number Diff line number Diff line Loading @@ -52,6 +52,14 @@ using EVP_PKEY_CTX_Ptr = bssl::UniquePtr<EVP_PKEY_CTX>; using X509_Ptr = bssl::UniquePtr<X509>; using CRYPTO_BUFFER_Ptr = bssl::UniquePtr<CRYPTO_BUFFER>; std::string device_suffix(const std::string& name) { size_t pos = name.find('/'); if (pos == std::string::npos) { return name; } return name.substr(pos + 1); } ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) { // Extract private key. const BIGNUM* bignum = EC_KEY_get0_private_key(ecKey); Loading Loading @@ -325,7 +333,8 @@ bytevec getProdEekChain(int32_t supportedEekCurve) { ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc, hwtrust::DiceChain::Kind kind, bool allowAnyMode, bool allowDegenerate) { bool allowDegenerate, const std::string& instanceName) { auto encodedBcc = bcc->encode(); // Use ro.build.type instead of ro.debuggable because ro.debuggable=1 for VTS testing Loading @@ -334,7 +343,8 @@ ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc, allowAnyMode = true; } auto chain = hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode); auto chain = hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode, device_suffix(instanceName)); if (!chain.ok()) return chain.error().message(); if (!allowDegenerate && !chain->IsProper()) { Loading Loading @@ -649,8 +659,8 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false) { IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false) { auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData); if (!parsedProtectedData) { return protDataErrMsg; Loading Loading @@ -707,7 +717,7 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData( // BCC is [ pubkey, + BccEntry] auto bccContents = validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr13, allowAnyMode, /*allowDegenerate=*/true); /*allowDegenerate=*/true, instanceName); if (!bccContents) { return bccContents.message() + "\n" + prettyPrint(bcc.get()); } Loading Loading @@ -750,9 +760,10 @@ ErrMsgOr<std::vector<BccEntryData>> verifyFactoryProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) { IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge) { return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain, eekId, supportedEekCurve, provisionable, challenge, eekId, supportedEekCurve, provisionable, instanceName, challenge, /*isFactory=*/true); } Loading @@ -760,10 +771,10 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProductionProtectedData( const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign, const std::vector<uint8_t>& keysToSignMac, const ProtectedData& protectedData, const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowAnyMode) { IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowAnyMode) { return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain, eekId, supportedEekCurve, provisionable, challenge, eekId, supportedEekCurve, provisionable, instanceName, challenge, /*isFactory=*/false, allowAnyMode); } Loading Loading @@ -1003,6 +1014,7 @@ ErrMsgOr<hwtrust::DiceChain::Kind> getDiceChainKind() { ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t>& request, const std::vector<uint8_t>& challenge, const std::string& instanceName, bool allowAnyMode = false, bool allowDegenerate = true) { auto [parsedRequest, _, csrErrMsg] = cppbor::parse(request); Loading Loading @@ -1042,7 +1054,8 @@ ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t return diceChainKind.message(); } auto diceContents = validateBcc(diceCertChain, *diceChainKind, allowAnyMode, allowDegenerate); auto diceContents = validateBcc(diceCertChain, *diceChainKind, allowAnyMode, allowDegenerate, instanceName); if (!diceContents) { return diceContents.message() + "\n" + prettyPrint(diceCertChain); } Loading Loading @@ -1071,6 +1084,7 @@ ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false, bool allowDegenerate = true) { Loading @@ -1081,8 +1095,8 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSi ") does not match expected version (3)."; } auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge, allowAnyMode, allowDegenerate); auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge, instanceName, allowAnyMode, allowDegenerate); if (!csrPayload) { return csrPayload.message(); } Loading @@ -1092,20 +1106,22 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSi ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr( const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowDegenerate) { return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/true, IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowDegenerate) { return verifyCsr(keysToSign, csr, provisionable, instanceName, challenge, /*isFactory=*/true, /*allowAnyMode=*/false, allowDegenerate); } ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr( const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr, IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge, bool allowAnyMode) { return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false, allowAnyMode); IRemotelyProvisionedComponent* provisionable, const std::string& instanceName, const std::vector<uint8_t>& challenge, bool allowAnyMode) { return verifyCsr(keysToSign, csr, provisionable, instanceName, challenge, /*isFactory=*/false, allowAnyMode); } ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr) { ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr, const std::string& instanceName) { auto [parsedRequest, _, csrErrMsg] = cppbor::parse(csr); if (!parsedRequest) { return csrErrMsg; Loading Loading @@ -1136,8 +1152,8 @@ ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr) { } auto encodedDiceChain = diceCertChain->encode(); auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind, /*allowAnyMode=*/false); auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind, /*allowAnyMode=*/false, device_suffix(instanceName)); if (!chain.ok()) return chain.error().message(); return chain->IsProper(); } Loading
security/keymint/support/remote_prov_utils_test.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -298,9 +298,11 @@ TEST(RemoteProvUtilsTest, validateBccDegenerate) { ASSERT_TRUE(bcc) << "Error: " << errMsg; EXPECT_TRUE(validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr16, /*allowAnyMode=*/false, /*allowDegenerate=*/true)); /*allowAnyMode=*/false, /*allowDegenerate=*/true, DEFAULT_INSTANCE_NAME)); EXPECT_FALSE(validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr16, /*allowAnyMode=*/false, /*allowDegenerate=*/false)); /*allowAnyMode=*/false, /*allowDegenerate=*/false, DEFAULT_INSTANCE_NAME)); } } // namespace } // namespace aidl::android::hardware::security::keymint::remote_prov
security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp +26 −26 Original line number Diff line number Diff line Loading @@ -55,10 +55,7 @@ constexpr int32_t VERSION_WITH_SUPPORTED_NUM_KEYS_IN_CSR = 3; constexpr uint8_t MIN_CHALLENGE_SIZE = 0; constexpr uint8_t MAX_CHALLENGE_SIZE = 64; const string DEFAULT_INSTANCE_NAME = "android.hardware.security.keymint.IRemotelyProvisionedComponent/default"; const string RKP_VM_INSTANCE_NAME = "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf"; const string KEYMINT_STRONGBOX_INSTANCE_NAME = "android.hardware.security.keymint.IKeyMintDevice/strongbox"; Loading Loading @@ -188,7 +185,7 @@ class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std:: } ASSERT_NE(provisionable_, nullptr); auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo); isRkpVmInstance_ = GetParam() == RKP_VM_INSTANCE_NAME; isRkpVmInstance_ = GetParam() == RKPVM_INSTANCE_NAME; if (isRkpVmInstance_) { if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) { GTEST_SKIP() << "The RKP VM is not supported on this system."; Loading Loading @@ -227,7 +224,7 @@ TEST(NonParameterizedTests, eachRpcHasAUniqueId) { RpcHardwareInfo hwInfo; auto status = rpc->getHardwareInfo(&hwInfo); if (hal == RKP_VM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) { if (hal == RKPVM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) { GTEST_SKIP() << "The RKP VM is not supported on this system."; } ASSERT_TRUE(status.isOk()); Loading Loading @@ -268,7 +265,7 @@ TEST(NonParameterizedTests, requireDiceOnDefaultInstanceIfStrongboxPresent) { auto status = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr); EXPECT_TRUE(status.isOk()) << status.getDescription(); auto result = isCsrWithProperDiceChain(csr); auto result = isCsrWithProperDiceChain(csr, DEFAULT_INSTANCE_NAME); ASSERT_TRUE(result) << result.message(); ASSERT_TRUE(*result); } Loading Loading @@ -494,7 +491,7 @@ TEST_P(CertificateRequestTest, EmptyRequest_testMode) { auto result = verifyProductionProtectedData( deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_); rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(result) << result.message(); } } Loading @@ -517,9 +514,10 @@ TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) { &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto firstBcc = verifyProductionProtectedData( deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_); auto firstBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(firstBcc) << firstBcc.message(); status = provisionable_->generateCertificateRequest( Loading @@ -527,9 +525,10 @@ TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) { &protectedData, &keysToSignMac); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto secondBcc = verifyProductionProtectedData( deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_); auto secondBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(secondBcc) << secondBcc.message(); // Verify that none of the keys in the first BCC are repeated in the second one. Loading Loading @@ -579,7 +578,7 @@ TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) { auto result = verifyProductionProtectedData( deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_); rpcHardwareInfo.supportedEekCurve, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(result) << result.message(); } } Loading Loading @@ -767,8 +766,8 @@ TEST_P(CertificateRequestV2Test, EmptyRequest) { provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge, isRkpVmInstance_); auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), GetParam(), challenge, isRkpVmInstance_); ASSERT_TRUE(result) << result.message(); } } Loading @@ -789,8 +788,8 @@ TEST_P(CertificateRequestV2Test, NonEmptyRequest) { auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge, isRkpVmInstance_); auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(), challenge, isRkpVmInstance_); ASSERT_TRUE(result) << result.message(); } } Loading Loading @@ -820,15 +819,15 @@ TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) { auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_, isRkpVmInstance_); auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(), challenge_, isRkpVmInstance_); ASSERT_TRUE(firstCsr) << firstCsr.message(); status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_, isRkpVmInstance_); auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(), challenge_, isRkpVmInstance_); ASSERT_TRUE(secondCsr) << secondCsr.message(); ASSERT_EQ(**firstCsr, **secondCsr); Loading @@ -846,8 +845,8 @@ TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) { auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr); ASSERT_TRUE(status.isOk()) << status.getDescription(); auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_, isRkpVmInstance_); auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), GetParam(), challenge_, isRkpVmInstance_); ASSERT_TRUE(result) << result.message(); } Loading Loading @@ -977,7 +976,8 @@ TEST_P(CertificateRequestV2Test, DeviceInfo) { provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr); ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getDescription(); auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_); auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), GetParam(), challenge_); ASSERT_TRUE(result) << result.message(); std::unique_ptr<cppbor::Array> csrPayload = std::move(*result); Loading