Merge "Added keymint_remote_prov_fuzzer" into main
diff --git a/security/keymint/support/fuzzer/Android.bp b/security/keymint/support/fuzzer/Android.bp
index 1b1a580..5b1bdb2 100644
--- a/security/keymint/support/fuzzer/Android.bp
+++ b/security/keymint/support/fuzzer/Android.bp
@@ -48,6 +48,20 @@
     ],
 }
 
+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 {
     name: "keymint_attestation_fuzzer",
     srcs: [
@@ -67,3 +81,14 @@
         "keymint_fuzzer_defaults",
     ],
 }
+
+cc_fuzz {
+    name: "keymint_remote_prov_fuzzer",
+    srcs: [
+        "keymint_remote_prov_fuzzer.cpp",
+    ],
+    defaults: [
+        "keymint_fuzzer_defaults",
+        "keymint_remote_fuzzer_defaults",
+    ],
+}
diff --git a/security/keymint/support/fuzzer/README.md b/security/keymint/support/fuzzer/README.md
index d41af08..13d3f34 100644
--- a/security/keymint/support/fuzzer/README.md
+++ b/security/keymint/support/fuzzer/README.md
@@ -12,6 +12,7 @@
 ## Table of contents
 + [keymint_attestation_fuzzer](#KeyMintAttestation)
 + [keymint_authSet_fuzzer](#KeyMintAuthSet)
++ [keymint_remote_prov_fuzzer](#KeyMintRemoteProv)
 
 # <a name="KeyMintAttestation"></a> Fuzzer for KeyMintAttestation
 KeyMintAttestation supports the following parameters:
@@ -77,3 +78,26 @@
 $ adb sync data
 $ 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
+```
diff --git a/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp b/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
new file mode 100644
index 0000000..6bd986c
--- /dev/null
+++ b/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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