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