xref: /aosp_15_r20/hardware/interfaces/security/keymint/support/fuzzer/keymint_remote_prov_fuzzer.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 #include <android/binder_manager.h>
18 #include <fuzzer/FuzzedDataProvider.h>
19 #include <remote_prov/remote_prov_utils.h>
20 #include <utils/Log.h>
21 
22 namespace android::hardware::security::keymint_support::fuzzer {
23 
24 using namespace cppcose;
25 using namespace aidl::android::hardware::security::keymint;
26 using namespace aidl::android::hardware::security::keymint::remote_prov;
27 
28 constexpr size_t kMinSize = 0;
29 constexpr size_t kSupportedNumKeys = 4;
30 constexpr size_t kChallengeSize = 64;
31 constexpr size_t kMaxBytes = 128;
32 const std::string kServiceName =
33         "android.hardware.security.keymint.IRemotelyProvisionedComponent/default";
34 
35 std::shared_ptr<IRemotelyProvisionedComponent> gRPC = nullptr;
36 
37 class KeyMintRemoteProv {
38   public:
KeyMintRemoteProv(const uint8_t * data,size_t size)39     KeyMintRemoteProv(const uint8_t* data, size_t size) : mFdp(data, size){};
40     void process();
41 
42   private:
43     std::vector<uint8_t> ExtractPayloadValue(const MacedPublicKey& macedPubKey);
44     FuzzedDataProvider mFdp;
45 };
46 
ExtractPayloadValue(const MacedPublicKey & macedPubKey)47 std::vector<uint8_t> KeyMintRemoteProv::ExtractPayloadValue(const MacedPublicKey& macedPubKey) {
48     std::vector<uint8_t> payloadValue;
49 
50     auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
51     if (coseMac0) {
52         // The payload is a bstr holding an encoded COSE_Key
53         auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
54         if (payload != nullptr) {
55             payloadValue = payload->value();
56         }
57     }
58     return payloadValue;
59 }
60 
process()61 void KeyMintRemoteProv::process() {
62     std::vector<MacedPublicKey> keysToSign = std::vector<MacedPublicKey>(
63             mFdp.ConsumeIntegralInRange<uint8_t>(kMinSize, kSupportedNumKeys));
64     cppbor::Array cborKeysToSign;
65     for (auto& key : keysToSign) {
66         // TODO: b/350649166 - Randomize keysToSign
67         std::vector<uint8_t> privateKeyBlob;
68         gRPC->generateEcdsaP256KeyPair(false /* testMode */, &key, &privateKeyBlob);
69 
70         std::vector<uint8_t> payloadValue = ExtractPayloadValue(key);
71         cborKeysToSign.add(cppbor::EncodedItem(payloadValue));
72     }
73 
74     uint8_t challengeSize = mFdp.ConsumeIntegralInRange<uint8_t>(kMinSize, kChallengeSize);
75     std::vector<uint8_t> challenge = mFdp.ConsumeBytes<uint8_t>(challengeSize);
76 
77     RpcHardwareInfo rpcHardwareInfo;
78     gRPC->getHardwareInfo(&rpcHardwareInfo);
79 
80     std::vector<uint8_t> csr;
81     gRPC->generateCertificateRequestV2(keysToSign, challenge, &csr);
82 
83     while (mFdp.remaining_bytes()) {
84         auto invokeProvAPI = mFdp.PickValueInArray<const std::function<void()>>({
85                 [&]() {
86                     verifyFactoryCsr(cborKeysToSign, csr, rpcHardwareInfo, kServiceName, challenge);
87                 },
88                 [&]() {
89                     verifyProductionCsr(cborKeysToSign, csr, rpcHardwareInfo, kServiceName,
90                                         challenge);
91                 },
92                 [&]() { isCsrWithProperDiceChain(csr, kServiceName); },
93         });
94         invokeProvAPI();
95     }
96 }
97 
LLVMFuzzerInitialize(int,char)98 extern "C" int LLVMFuzzerInitialize(int /* *argc */, char /* ***argv */) {
99     ::ndk::SpAIBinder binder(AServiceManager_waitForService(kServiceName.c_str()));
100     gRPC = IRemotelyProvisionedComponent::fromBinder(binder);
101     LOG_ALWAYS_FATAL_IF(!gRPC, "Failed to get IRemotelyProvisionedComponent instance.");
102     return 0;
103 }
104 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)105 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
106     KeyMintRemoteProv kmRemoteProv(data, size);
107     kmRemoteProv.process();
108     return 0;
109 }
110 
111 }  // namespace android::hardware::security::keymint_support::fuzzer
112