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

Commit 2d2385bc authored by Sean Thomas's avatar Sean Thomas
Browse files

Refactor function signatures to remove mocked IRPC

Test: atest libkeymint_remote_prov_support_test
      atest VtsHalRemotelyProvisionedComponentTargetTest

Change-Id: I8dd47bca149bcef244c223f8e94d3965deb13f13
parent d65b3820
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ cc_library {

cc_test {
    name: "libkeymint_remote_prov_support_test",
    cpp_std: "c++20",
    srcs: ["remote_prov_utils_test.cpp"],
    static_libs: [
        "android.hardware.security.rkp-V3-ndk",
+6 −2
Original line number Diff line number Diff line
@@ -74,16 +74,20 @@ void KeyMintRemoteProv::process() {
    uint8_t challengeSize = mFdp.ConsumeIntegralInRange<uint8_t>(kMinSize, kChallengeSize);
    std::vector<uint8_t> challenge = mFdp.ConsumeBytes<uint8_t>(challengeSize);

    RpcHardwareInfo rpcHardwareInfo;
    gRPC->getHardwareInfo(&rpcHardwareInfo);

    std::vector<uint8_t> csr;
    gRPC->generateCertificateRequestV2(keysToSign, challenge, &csr);

    while (mFdp.remaining_bytes()) {
        auto invokeProvAPI = mFdp.PickValueInArray<const std::function<void()>>({
                [&]() {
                    verifyFactoryCsr(cborKeysToSign, csr, gRPC.get(), kServiceName, challenge);
                    verifyFactoryCsr(cborKeysToSign, csr, rpcHardwareInfo, kServiceName, challenge);
                },
                [&]() {
                    verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), kServiceName, challenge);
                    verifyProductionCsr(cborKeysToSign, csr, rpcHardwareInfo, kServiceName,
                                        challenge);
                },
                [&]() { isCsrWithProperDiceChain(csr, kServiceName); },
        });
+0 −52
Original line number Diff line number Diff line
/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
#include <android-base/properties.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include <cstdint>

namespace aidl::android::hardware::security::keymint::remote_prov {

using ::ndk::ScopedAStatus;

class MockIRemotelyProvisionedComponent : public IRemotelyProvisionedComponentDefault {
  public:
    MOCK_METHOD(ScopedAStatus, getHardwareInfo, (RpcHardwareInfo * _aidl_return), (override));
    MOCK_METHOD(ScopedAStatus, generateEcdsaP256KeyPair,
                (bool in_testMode, MacedPublicKey* out_macedPublicKey,
                 std::vector<uint8_t>* _aidl_return),
                (override));
    MOCK_METHOD(ScopedAStatus, generateCertificateRequest,
                (bool in_testMode, const std::vector<MacedPublicKey>& in_keysToSign,
                 const std::vector<uint8_t>& in_endpointEncryptionCertChain,
                 const std::vector<uint8_t>& in_challenge, DeviceInfo* out_deviceInfo,
                 ProtectedData* out_protectedData, std::vector<uint8_t>* _aidl_return),
                (override));
    MOCK_METHOD(ScopedAStatus, generateCertificateRequestV2,
                (const std::vector<MacedPublicKey>& in_keysToSign,
                 const std::vector<uint8_t>& in_challenge, std::vector<uint8_t>* _aidl_return),
                (override));
    MOCK_METHOD(ScopedAStatus, getInterfaceVersion, (int32_t* _aidl_return), (override));
    MOCK_METHOD(ScopedAStatus, getInterfaceHash, (std::string * _aidl_return), (override));
};

}  // namespace aidl::android::hardware::security::keymint::remote_prov
 No newline at end of file
+20 −17
Original line number Diff line number Diff line
@@ -153,7 +153,7 @@ JsonOutput jsonEncodeCsrWithBuild(const std::string& instance_name, const cppbor
 * is parsed in the manufacturing process.
 */
ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable);
        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& info);

/**
 * Parses a DeviceInfo structure from the given CBOR data. The parsed data is then validated to
@@ -162,7 +162,7 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
 * suitable for the end user.
 */
ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable);
        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& info);

/**
 * Verify the protected data as if the device is still early in the factory process and may not
@@ -171,36 +171,39 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
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::string& instanceName,
        const std::vector<uint8_t>& challenge);
        const EekChain& eekChain, const std::vector<uint8_t>& eekId, const RpcHardwareInfo& info,
        const std::string& instanceName, const std::vector<uint8_t>& challenge);
/**
 * Verify the protected data as if the device is a final production sample.
 */
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::string& instanceName,
        const std::vector<uint8_t>& challenge, bool allowAnyMode = false);
        const EekChain& eekChain, const std::vector<uint8_t>& eekId, const RpcHardwareInfo& info,
        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
 * have all device identifiers provisioned yet.
 */
ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
        const std::vector<uint8_t>& challenge, bool allowDegenerate = true,
ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(const cppbor::Array& keysToSign,
                                                          const std::vector<uint8_t>& csr,
                                                          const RpcHardwareInfo& info,
                                                          const std::string& instanceName,
                                                          const std::vector<uint8_t>& challenge,
                                                          bool allowDegenerate = true,
                                                          bool requireUdsCerts = false);

/**
 * 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::string& instanceName,
        const std::vector<uint8_t>& challenge, bool allowAnyMode = false);
ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(const cppbor::Array& keysToSign,
                                                             const std::vector<uint8_t>& csr,
                                                             const RpcHardwareInfo& info,
                                                             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,
+38 −38
Original line number Diff line number Diff line
@@ -483,7 +483,7 @@ bool isTeeDeviceInfo(const cppbor::Map& devInfo) {
}

ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable,
        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& rpcHardwareInfo,
        bool isFactory) {
    const cppbor::Array kValidVbStates = {"green", "yellow", "orange"};
    const cppbor::Array kValidBootloaderStates = {"locked", "unlocked"};
@@ -530,9 +530,7 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
        return "DeviceInfo ordering is non-canonical.";
    }

    RpcHardwareInfo info;
    provisionable->getHardwareInfo(&info);
    if (info.versionNumber < 3) {
    if (rpcHardwareInfo.versionNumber < 3) {
        const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
        if (!version) {
            return "Device info is missing version";
@@ -540,10 +538,10 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
        if (!version->asUint()) {
            return "version must be an unsigned integer";
        }
        if (version->asUint()->value() != info.versionNumber) {
        if (version->asUint()->value() != rpcHardwareInfo.versionNumber) {
            return "DeviceInfo version (" + std::to_string(version->asUint()->value()) +
                   ") does not match the remotely provisioned component version (" +
                   std::to_string(info.versionNumber) + ").";
                   std::to_string(rpcHardwareInfo.versionNumber) + ").";
        }
    }
    // Bypasses the device info validation since the device info in AVF is currently
@@ -552,14 +550,14 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
    // TODO(b/300911665): This check is temporary and will be replaced once the markers
    // on the DICE chain become available. We need to determine if the CSR is from the
    // RKP VM using the markers on the DICE chain.
    if (info.uniqueId == "AVF Remote Provisioning 1") {
    if (rpcHardwareInfo.uniqueId == "AVF Remote Provisioning 1") {
        return std::move(parsed);
    }

    std::string error;
    std::string tmp;
    std::set<std::string_view> previousKeys;
    switch (info.versionNumber) {
    switch (rpcHardwareInfo.versionNumber) {
        case 3:
            if (isTeeDeviceInfo(*parsed) && parsed->size() != kNumTeeDeviceInfoEntries) {
                error += fmt::format(
@@ -626,7 +624,7 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
                                   kValidAttIdStates);
            break;
        default:
            return "Unrecognized version: " + std::to_string(info.versionNumber);
            return "Unrecognized version: " + std::to_string(rpcHardwareInfo.versionNumber);
    }

    if (!error.empty()) {
@@ -637,13 +635,13 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
}

ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateFactoryDeviceInfo(
        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
    return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/true);
        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& rpcHardwareInfo) {
    return parseAndValidateDeviceInfo(deviceInfoBytes, rpcHardwareInfo, /*isFactory=*/true);
}

ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateProductionDeviceInfo(
        const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable) {
    return parseAndValidateDeviceInfo(deviceInfoBytes, provisionable, /*isFactory=*/false);
        const std::vector<uint8_t>& deviceInfoBytes, const RpcHardwareInfo& rpcHardwareInfo) {
    return parseAndValidateDeviceInfo(deviceInfoBytes, rpcHardwareInfo, /*isFactory=*/false);
}

ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey,
@@ -661,8 +659,8 @@ ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPub
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::string& instanceName,
        const EekChain& eekChain, const std::vector<uint8_t>& eekId,
        const RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
        const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false) {
    auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
    if (!parsedProtectedData) {
@@ -685,7 +683,7 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData(
        return "The COSE_encrypt recipient does not match the expected EEK identifier";
    }

    auto sessionKey = getSessionKey(senderPubkey, eekChain, supportedEekCurve);
    auto sessionKey = getSessionKey(senderPubkey, eekChain, rpcHardwareInfo.supportedEekCurve);
    if (!sessionKey) {
        return sessionKey.message();
    }
@@ -726,7 +724,7 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData(
    }

    auto deviceInfoResult =
            parseAndValidateDeviceInfo(deviceInfo.deviceInfo, provisionable, isFactory);
            parseAndValidateDeviceInfo(deviceInfo.deviceInfo, rpcHardwareInfo, isFactory);
    if (!deviceInfoResult) {
        return deviceInfoResult.message();
    }
@@ -762,22 +760,22 @@ ErrMsgOr<std::vector<BccEntryData>> verifyProtectedData(
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::string& instanceName,
        const EekChain& eekChain, const std::vector<uint8_t>& eekId,
        const RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
        const std::vector<uint8_t>& challenge) {
    return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
                               eekId, supportedEekCurve, provisionable, instanceName, challenge,
                               eekId, rpcHardwareInfo, instanceName, challenge,
                               /*isFactory=*/true);
}

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::string& instanceName,
        const EekChain& eekChain, const std::vector<uint8_t>& eekId,
        const RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
        const std::vector<uint8_t>& challenge, bool allowAnyMode) {
    return verifyProtectedData(deviceInfo, keysToSign, keysToSignMac, protectedData, eekChain,
                               eekId, supportedEekCurve, provisionable, instanceName, challenge,
                               eekId, rpcHardwareInfo, instanceName, challenge,
                               /*isFactory=*/false, allowAnyMode);
}

@@ -912,7 +910,7 @@ std::optional<std::string> validateUdsCerts(const cppbor::Map& udsCerts,

ErrMsgOr<std::unique_ptr<cppbor::Array>> parseAndValidateCsrPayload(
        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csrPayload,
        IRemotelyProvisionedComponent* provisionable, bool isFactory) {
        const RpcHardwareInfo& rpcHardwareInfo, bool isFactory) {
    auto [parsedCsrPayload, _, errMsg] = cppbor::parse(csrPayload);
    if (!parsedCsrPayload) {
        return errMsg;
@@ -949,7 +947,8 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> parseAndValidateCsrPayload(
        return "Keys must be an Array.";
    }

    auto result = parseAndValidateDeviceInfo(signedDeviceInfo->encode(), provisionable, isFactory);
    auto result =
            parseAndValidateDeviceInfo(signedDeviceInfo->encode(), rpcHardwareInfo, isFactory);
    if (!result) {
        return result.message();
    }
@@ -1100,13 +1099,12 @@ 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 RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
        const std::vector<uint8_t>& challenge, bool isFactory, bool allowAnyMode = false,
        bool allowDegenerate = true, bool requireUdsCerts = false) {
    RpcHardwareInfo info;
    provisionable->getHardwareInfo(&info);
    if (info.versionNumber != 3) {
        return "Remotely provisioned component version (" + std::to_string(info.versionNumber) +
    if (rpcHardwareInfo.versionNumber != 3) {
        return "Remotely provisioned component version (" +
               std::to_string(rpcHardwareInfo.versionNumber) +
               ") does not match expected version (3).";
    }

@@ -1117,22 +1115,24 @@ ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(
        return csrPayload.message();
    }

    return parseAndValidateCsrPayload(keysToSign, *csrPayload, provisionable, isFactory);
    return parseAndValidateCsrPayload(keysToSign, *csrPayload, rpcHardwareInfo, isFactory);
}

ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
        const RpcHardwareInfo& rpcHardwareInfo, const std::string& instanceName,
        const std::vector<uint8_t>& challenge, bool allowDegenerate, bool requireUdsCerts) {
    return verifyCsr(keysToSign, csr, provisionable, instanceName, challenge, /*isFactory=*/true,
    return verifyCsr(keysToSign, csr, rpcHardwareInfo, instanceName, challenge, /*isFactory=*/true,
                     /*allowAnyMode=*/false, allowDegenerate, requireUdsCerts);
}

ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
        const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
        IRemotelyProvisionedComponent* provisionable, const std::string& instanceName,
        const std::vector<uint8_t>& challenge, bool allowAnyMode) {
    return verifyCsr(keysToSign, csr, provisionable, instanceName, challenge, /*isFactory=*/false,
ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(const cppbor::Array& keysToSign,
                                                             const std::vector<uint8_t>& csr,
                                                             const RpcHardwareInfo& rpcHardwareInfo,
                                                             const std::string& instanceName,
                                                             const std::vector<uint8_t>& challenge,
                                                             bool allowAnyMode) {
    return verifyCsr(keysToSign, csr, rpcHardwareInfo, instanceName, challenge, /*isFactory=*/false,
                     allowAnyMode);
}

Loading