Merge "Pass in allow_any_mode when verifying DICE chains" into main

This commit is contained in:
Karuna Wadhera
2024-08-28 14:03:19 +00:00
committed by Gerrit Code Review
3 changed files with 41 additions and 21 deletions

View File

@@ -167,7 +167,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);
IRemotelyProvisionedComponent* provisionable, 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
@@ -181,7 +182,8 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
*/
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);
IRemotelyProvisionedComponent* provisionable, 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);

View File

@@ -325,9 +325,16 @@ bytevec getProdEekChain(int32_t supportedEekCurve) {
}
ErrMsgOr<std::vector<BccEntryData>> validateBcc(const cppbor::Array* bcc,
hwtrust::DiceChain::Kind kind) {
hwtrust::DiceChain::Kind kind, bool allowAnyMode) {
auto encodedBcc = bcc->encode();
auto chain = hwtrust::DiceChain::Verify(encodedBcc, kind);
// Use ro.build.type instead of ro.debuggable because ro.debuggable=1 for VTS testing
std::string build_type = ::android::base::GetProperty("ro.build.type", "");
if (!build_type.empty() && build_type != "user") {
allowAnyMode = true;
}
auto chain = hwtrust::DiceChain::Verify(encodedBcc, kind, allowAnyMode);
if (!chain.ok()) return chain.error().message();
auto keys = chain->CosePublicKeys();
if (!keys.ok()) return keys.error().message();
@@ -638,7 +645,7 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData(
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 isFactory, bool allowAnyMode = false) {
auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
if (!parsedProtectedData) {
return protDataErrMsg;
@@ -694,7 +701,7 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData(
}
// BCC is [ pubkey, + BccEntry]
auto bccContents = validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr13);
auto bccContents = validateBcc(bcc->asArray(), hwtrust::DiceChain::Kind::kVsr13, allowAnyMode);
if (!bccContents) {
return bccContents.message() + "\n" + prettyPrint(bcc.get());
}
@@ -747,10 +754,11 @@ 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) {
IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
bool allowAnyMode) {
return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
eekId, supportedEekCurve, provisionable, challenge,
/*isFactory=*/false);
/*isFactory=*/false, allowAnyMode);
}
ErrMsgOr<X509_Ptr> parseX509Cert(const std::vector<uint8_t>& cert) {
@@ -988,7 +996,8 @@ ErrMsgOr<hwtrust::DiceChain::Kind> getDiceChainKind() {
}
ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t>& request,
const std::vector<uint8_t>& challenge) {
const std::vector<uint8_t>& challenge,
bool allowAnyMode = false) {
auto [parsedRequest, _, csrErrMsg] = cppbor::parse(request);
if (!parsedRequest) {
return csrErrMsg;
@@ -1026,7 +1035,7 @@ ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t
return diceChainKind.message();
}
auto diceContents = validateBcc(diceCertChain, *diceChainKind);
auto diceContents = validateBcc(diceCertChain, *diceChainKind, allowAnyMode);
if (!diceContents) {
return diceContents.message() + "\n" + prettyPrint(diceCertChain);
}
@@ -1055,7 +1064,7 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSi
const std::vector<uint8_t>& csr,
IRemotelyProvisionedComponent* provisionable,
const std::vector<uint8_t>& challenge,
bool isFactory) {
bool isFactory, bool allowAnyMode = false) {
RpcHardwareInfo info;
provisionable->getHardwareInfo(&info);
if (info.versionNumber != 3) {
@@ -1063,7 +1072,7 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSi
") does not match expected version (3).";
}
auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge);
auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge, allowAnyMode);
if (!csrPayload) {
return csrPayload.message();
}
@@ -1079,8 +1088,9 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
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) {
return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false);
IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge,
bool allowAnyMode) {
return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false, allowAnyMode);
}
ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr) {
@@ -1114,7 +1124,8 @@ ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr) {
}
auto encodedDiceChain = diceCertChain->encode();
auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind);
auto chain =
hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind, /*allowAnyMode=*/false);
if (!chain.ok()) return chain.error().message();
return chain->IsProper();
}

View File

@@ -188,7 +188,8 @@ class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::
}
ASSERT_NE(provisionable_, nullptr);
auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo);
if (GetParam() == RKP_VM_INSTANCE_NAME) {
isRkpVmInstance_ = GetParam() == RKP_VM_INSTANCE_NAME;
if (isRkpVmInstance_) {
if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
GTEST_SKIP() << "The RKP VM is not supported on this system.";
}
@@ -209,6 +210,7 @@ class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::
protected:
std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
RpcHardwareInfo rpcHardwareInfo;
bool isRkpVmInstance_;
};
/**
@@ -765,7 +767,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);
auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge,
isRkpVmInstance_);
ASSERT_TRUE(result) << result.message();
}
}
@@ -786,7 +789,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);
auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge,
isRkpVmInstance_);
ASSERT_TRUE(result) << result.message();
}
}
@@ -816,13 +820,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_);
auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), 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_);
auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_,
isRkpVmInstance_);
ASSERT_TRUE(secondCsr) << secondCsr.message();
ASSERT_EQ(**firstCsr, **secondCsr);
@@ -840,7 +846,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_);
auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_,
isRkpVmInstance_);
ASSERT_TRUE(result) << result.message();
}