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

Commit ddbaa66b authored by Akhilesh Sanikop's avatar Akhilesh Sanikop
Browse files

Added keymint_remote_prov_fuzzer

exec/s: 12
Test: ./keymint_remote_prov_fuzzer
Bug: 337985606

Change-Id: Ifaa5c32616904c1aa5b6d8a21c566a014ed882cf
parent 974ff63e
Loading
Loading
Loading
Loading
+25 −0
Original line number Original line Diff line number Diff line
@@ -48,6 +48,20 @@ cc_defaults {
    ],
    ],
}
}


cc_defaults {
    name: "keymint_remote_fuzzer_defaults",
    static_libs: [
        "libkeymint_remote_prov_support",
        "android.hardware.security.rkp-V3-ndk",
    ],
    shared_libs: [
        "libcppbor",
        "libcppcose_rkp",
        "libjsoncpp",
        "libkeymaster_portable",
    ],
}

cc_fuzz {
cc_fuzz {
    name: "keymint_attestation_fuzzer",
    name: "keymint_attestation_fuzzer",
    srcs: [
    srcs: [
@@ -67,3 +81,14 @@ cc_fuzz {
        "keymint_fuzzer_defaults",
        "keymint_fuzzer_defaults",
    ],
    ],
}
}

cc_fuzz {
    name: "keymint_remote_prov_fuzzer",
    srcs: [
        "keymint_remote_prov_fuzzer.cpp",
    ],
    defaults: [
        "keymint_fuzzer_defaults",
        "keymint_remote_fuzzer_defaults",
    ],
}
+24 −0
Original line number Original line Diff line number Diff line
@@ -12,6 +12,7 @@ The plugins feed the entire input data to the module. This ensures that the plug
## Table of contents
## Table of contents
+ [keymint_attestation_fuzzer](#KeyMintAttestation)
+ [keymint_attestation_fuzzer](#KeyMintAttestation)
+ [keymint_authSet_fuzzer](#KeyMintAuthSet)
+ [keymint_authSet_fuzzer](#KeyMintAuthSet)
+ [keymint_remote_prov_fuzzer](#KeyMintRemoteProv)


# <a name="KeyMintAttestation"></a> Fuzzer for KeyMintAttestation
# <a name="KeyMintAttestation"></a> Fuzzer for KeyMintAttestation
KeyMintAttestation supports the following parameters:
KeyMintAttestation supports the following parameters:
@@ -77,3 +78,26 @@ $ mm -j$(nproc) keymint_authSet_fuzzer
$ adb sync data
$ adb sync data
$ adb shell /data/fuzz/arm64/keymint_authSet_fuzzer/keymint_authSet_fuzzer
$ adb shell /data/fuzz/arm64/keymint_authSet_fuzzer/keymint_authSet_fuzzer
```
```

# <a name="KeyMintRemoteProv"></a> Fuzzer for KeyMintRemoteProv
KeyMintRemoteProv supports the following parameters:
1. ChallengeSize(parameter name: "challengeSize")
2. Challenge(parameter name: "challenge")
3. NumKeys(parameter name: "numKeys")

| Parameter| Valid Values| Configured Value|
|------------- |--------------| -------------------- |
|`challengeSize`| `uint8_t` |Value obtained from FuzzedDataProvider|
|`challenge`| `std::vector<uint8_t>` |Value obtained from FuzzedDataProvider|
|`numKeys`| `uint8_t` |Value obtained from FuzzedDataProvider|

#### Steps to run
1. Build the fuzzer
```
$ mm -j$(nproc) keymint_remote_prov_fuzzer
```
2. Run on device
```
$ adb sync data
$ adb shell /data/fuzz/arm64/keymint_remote_prov_fuzzer/keymint_remote_prov_fuzzer
```
+103 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 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.
 *
 */
#include <android/binder_manager.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <remote_prov/remote_prov_utils.h>
#include <utils/Log.h>

namespace android::hardware::security::keymint_support::fuzzer {

using namespace cppcose;
using namespace aidl::android::hardware::security::keymint;
using namespace aidl::android::hardware::security::keymint::remote_prov;

constexpr size_t kMinSize = 0;
constexpr size_t kSupportedNumKeys = 4;
constexpr size_t kChallengeSize = 64;
constexpr size_t kMaxBytes = 128;
const std::string kServiceName =
        "android.hardware.security.keymint.IRemotelyProvisionedComponent/default";

std::shared_ptr<IRemotelyProvisionedComponent> gRPC = nullptr;

class KeyMintRemoteProv {
  public:
    KeyMintRemoteProv(const uint8_t* data, size_t size) : mFdp(data, size){};
    void process();

  private:
    std::vector<uint8_t> ExtractPayloadValue(const MacedPublicKey& macedPubKey);
    FuzzedDataProvider mFdp;
};

std::vector<uint8_t> KeyMintRemoteProv::ExtractPayloadValue(const MacedPublicKey& macedPubKey) {
    std::vector<uint8_t> payloadValue;

    auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
    if (coseMac0) {
        // The payload is a bstr holding an encoded COSE_Key
        auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
        if (payload != nullptr) {
            payloadValue = payload->value();
        }
    }
    return payloadValue;
}

void KeyMintRemoteProv::process() {
    std::vector<MacedPublicKey> keysToSign = std::vector<MacedPublicKey>(
            mFdp.ConsumeIntegralInRange<uint8_t>(kMinSize, kSupportedNumKeys));
    cppbor::Array cborKeysToSign;
    for (auto& key : keysToSign) {
        // TODO: b/350649166 - Randomize keysToSign
        std::vector<uint8_t> privateKeyBlob;
        gRPC->generateEcdsaP256KeyPair(false /* testMode */, &key, &privateKeyBlob);

        std::vector<uint8_t> payloadValue = ExtractPayloadValue(key);
        cborKeysToSign.add(cppbor::EncodedItem(payloadValue));
    }

    uint8_t challengeSize = mFdp.ConsumeIntegralInRange<uint8_t>(kMinSize, kChallengeSize);
    std::vector<uint8_t> challenge = mFdp.ConsumeBytes<uint8_t>(challengeSize);

    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(), challenge); },
                [&]() { verifyProductionCsr(cborKeysToSign, csr, gRPC.get(), challenge); },
                [&]() { isCsrWithProperDiceChain(csr); },
        });
        invokeProvAPI();
    }
}

extern "C" int LLVMFuzzerInitialize(int /* *argc */, char /* ***argv */) {
    ::ndk::SpAIBinder binder(AServiceManager_waitForService(kServiceName.c_str()));
    gRPC = IRemotelyProvisionedComponent::fromBinder(binder);
    LOG_ALWAYS_FATAL_IF(!gRPC, "Failed to get IRemotelyProvisionedComponent instance.");
    return 0;
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    KeyMintRemoteProv kmRemoteProv(data, size);
    kmRemoteProv.process();
    return 0;
}

}  // namespace android::hardware::security::keymint_support::fuzzer