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

Commit 84646b67 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Refactor function signatures to remove mocked IRPC" into main

parents d9c02724 2d2385bc
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