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

Commit ca6d8cce authored by Karuna Wadhera's avatar Karuna Wadhera
Browse files

Pass in allow_any_mode when verifying DICE chains

1. allow_any_mode is set as true when the VM RKP instance is being
   tested (since the bootloader is unlocked for VTS tests and therefore
   the VM DICE chain will necessarily have at least one non-normal
   mode.)
2. allow_any_mode is set as true for non-user type builds.

Bug: 318483637
Test: atest VtsHalRemotelyProvisionedComponentTargetTest
Change-Id: I15ec3ad32f08eecd8478df14f8efa71fdb0b5d08
parent a7fffef3
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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);
+24 −13
Original line number Diff line number Diff line
@@ -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) {
@@ -987,7 +995,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;
@@ -1025,7 +1034,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);
    }
@@ -1054,7 +1063,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) {
@@ -1062,7 +1071,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();
    }
@@ -1078,8 +1087,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) {
@@ -1113,7 +1123,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();
}
+13 −6
Original line number Diff line number Diff line
@@ -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();
}