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

Commit 2146152d authored by Andrew Scull's avatar Andrew Scull
Browse files

Require proper DICE if StrongBox is present

If a decice provides a StrongBox KeyMint instance then the default IRPC
instance is required to use a proper, non-degenerate DICE chain.

Expose a function to check whether the CSR contains a proper DICE chain
and use that from VTS to implement the test.

Bug: 302204396
Test: atest VtsHalRemotelyProvisionedComponentTargetTest
Change-Id: I90cf070bc2279fc52e0a8e7fd0039d3fdb68c1d7
parent b9591926
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -183,4 +183,7 @@ 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);

/** Checks whether the CSR has a proper DICE chain. */
ErrMsgOr<bool> isCsrWithProperDiceChain(const std::vector<uint8_t>& csr);

}  // namespace aidl::android::hardware::security::keymint::remote_prov
+36 −0
Original line number Diff line number Diff line
@@ -1081,4 +1081,40 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
    return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false);
}

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

    auto version = parsedRequest->asArray()->get(0)->asUint();
    auto diceCertChain = parsedRequest->asArray()->get(2)->asArray();

    if (!version || version->value() != 1U) {
        return "AuthenticatedRequest version must be an unsigned integer and must be equal to 1.";
    }
    if (!diceCertChain) {
        return "AuthenticatedRequest DiceCertChain must be an Array.";
    }

    // DICE chain is [ pubkey, + DiceChainEntry ].
    auto diceChainKind = getDiceChainKind();
    if (!diceChainKind) {
        return diceChainKind.message();
    }

    auto encodedDiceChain = diceCertChain->encode();
    auto chain = hwtrust::DiceChain::Verify(encodedDiceChain, *diceChainKind);
    if (!chain.ok()) return chain.error().message();
    return chain->IsProper();
}

}  // namespace aidl::android::hardware::security::keymint::remote_prov
+35 −0
Original line number Diff line number Diff line
@@ -55,8 +55,12 @@ 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";

#define INSTANTIATE_REM_PROV_AIDL_TEST(name)                                         \
    GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name);                             \
@@ -230,6 +234,37 @@ TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
    }
}

/**
 * Verify that the default implementation supports DICE if there is a StrongBox KeyMint instance
 * on the device.
 */
// @VsrTest = 3.10-015
TEST(NonParameterizedTests, requireDiceOnDefaultInstanceIfStrongboxPresent) {
    int vsr_api_level = get_vsr_api_level();
    if (vsr_api_level < 35) {
        GTEST_SKIP() << "Applies only to VSR API level 35 or newer, this device is: "
                     << vsr_api_level;
    }

    if (!AServiceManager_isDeclared(KEYMINT_STRONGBOX_INSTANCE_NAME.c_str())) {
        GTEST_SKIP() << "Strongbox is not present on this device.";
    }

    ::ndk::SpAIBinder binder(AServiceManager_waitForService(DEFAULT_INSTANCE_NAME.c_str()));
    std::shared_ptr<IRemotelyProvisionedComponent> rpc =
            IRemotelyProvisionedComponent::fromBinder(binder);
    ASSERT_NE(rpc, nullptr);

    bytevec challenge = randomBytes(64);
    bytevec csr;
    auto status = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
    EXPECT_TRUE(status.isOk()) << status.getDescription();

    auto result = isCsrWithProperDiceChain(csr);
    ASSERT_TRUE(result) << result.message();
    ASSERT_TRUE(*result);
}

using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;

INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);