Added fuzz targets for libkeystore-attestation-application-id
This patch adds following fuzz
targets: keystoreSignature_fuzzer, keystorePackageInfo_fuzzer,
keystoreApplicationId_fuzzer and keystoreAttestationId_fuzzer.
Test: ./keystoreSignature_fuzzer
Test: ./keystorePackageInfo_fuzzer
Test: ./keystoreApplicationId-fuzzer
Test: ./keystoreAttestationId_fuzzer
Bug: 187131475
Change-Id: I129a577208624b32a3eea24e877995828922acbb
diff --git a/keystore/tests/fuzzer/Android.bp b/keystore/tests/fuzzer/Android.bp
index b05effd..194d397 100644
--- a/keystore/tests/fuzzer/Android.bp
+++ b/keystore/tests/fuzzer/Android.bp
@@ -36,3 +36,64 @@
componentid: 155276,
},
}
+
+cc_defaults {
+ name: "keystoreAttestation_defaults",
+ static_libs: [
+ "libkeystore-attestation-application-id",
+ "liblog",
+ "libutils",
+ "libbase",
+ "libhidlbase",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libcrypto",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
+
+cc_fuzz {
+ name: "keystoreSignature_fuzzer",
+ srcs: [
+ "keystoreSignature_fuzzer.cpp",
+ ],
+ defaults: [
+ "keystoreAttestation_defaults",
+ ],
+}
+
+cc_fuzz {
+ name: "keystorePackageInfo_fuzzer",
+ srcs: [
+ "keystorePackageInfo_fuzzer.cpp",
+ ],
+ defaults: [
+ "keystoreAttestation_defaults",
+ ],
+}
+
+cc_fuzz {
+ name: "keystoreApplicationId_fuzzer",
+ srcs: [
+ "keystoreApplicationId_fuzzer.cpp",
+ ],
+ defaults: [
+ "keystoreAttestation_defaults",
+ ],
+}
+
+cc_fuzz {
+ name: "keystoreAttestationId_fuzzer",
+ srcs: [
+ "keystoreAttestationId_fuzzer.cpp",
+ ],
+ defaults: [
+ "keystoreAttestation_defaults",
+ ],
+}
diff --git a/keystore/tests/fuzzer/README.md b/keystore/tests/fuzzer/README.md
index 0861e5e..25d53ab 100644
--- a/keystore/tests/fuzzer/README.md
+++ b/keystore/tests/fuzzer/README.md
@@ -1,6 +1,7 @@
# Fuzzer for libkeystore
## Table of contents
+ [libkeystore-get-wifi-hidl](#libkeystore-get-wifi-hidl)
++ [libkeystore_attestation_application_id](#libkeystore_attestation_application_id)
# <a name="libkeystore-get-wifi-hidl"></a> Fuzzer for libkeystore-get-wifi-hidl
## Plugin Design Considerations
@@ -44,6 +45,59 @@
$ adb shell /data/fuzz/${TARGET_ARCH}/keystoreGetWifiHidl_fuzzer/keystoreGetWifiHidl_fuzzer
```
+# <a name="libkeystore_attestation_application_id"></a> Fuzzer for libkeystore_attestation_application_id
+## Plugin Design Considerations
+The fuzzer plugin for libkeystore-attestation-application-id are designed based on the understanding of the library and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+libkeystore-attestation-application-id supports the following parameters:
+1. Package Name (parameter name: `packageName`)
+2. Version Code (parameter name: `versionCode`)
+3. Uid (parameter name: `uid`)
+
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `packageName` | `String` | Value obtained from FuzzedDataProvider|
+| `versionCode` | `INT64_MIN` to `INT64_MAX` | Value obtained from FuzzedDataProvider|
+| `uid` | `0` to `1000` | Value obtained from FuzzedDataProvider|
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugins feed the entire input data to the libkeystore_attestation_application_id module.
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build keystoreSignature_fuzzer, keystorePackageInfo_fuzzer, keystoreApplicationId_fuzzer and keystoreAttestationId_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+ $ mm -j$(nproc) keystoreSignature_fuzzer
+ $ mm -j$(nproc) keystorePackageInfo_fuzzer
+ $ mm -j$(nproc) keystoreApplicationId_fuzzer
+ $ mm -j$(nproc) keystoreAttestationId_fuzzer
+```
+#### Steps to run
+
+To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/${TARGET_ARCH}/keystoreSignature_fuzzer/keystoreSignature_fuzzer
+ $ adb shell /data/fuzz/${TARGET_ARCH}/keystorePackageInfo_fuzzer/keystorePackageInfo_fuzzer
+ $ adb shell /data/fuzz/${TARGET_ARCH}/keystoreApplicationId_fuzzer/keystoreApplicationId_fuzzer
+ $ adb shell /data/fuzz/${TARGET_ARCH}/keystoreAttestationId_fuzzer/keystoreAttestationId_fuzzer
+```
+
## References:
* http://llvm.org/docs/LibFuzzer.html
* https://github.com/google/oss-fuzz
diff --git a/keystore/tests/fuzzer/keystoreApplicationId_fuzzer.cpp b/keystore/tests/fuzzer/keystoreApplicationId_fuzzer.cpp
new file mode 100644
index 0000000..0eddb9a
--- /dev/null
+++ b/keystore/tests/fuzzer/keystoreApplicationId_fuzzer.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 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 "keystoreCommon.h"
+#include <keystore/KeyAttestationApplicationId.h>
+
+using ::security::keymaster::KeyAttestationApplicationId;
+
+constexpr size_t kPackageVectorSizeMin = 1;
+constexpr size_t kPackageVectorSizeMax = 10;
+
+class KeystoreApplicationId {
+ public:
+ void process(const uint8_t* data, size_t size);
+ ~KeystoreApplicationId() {}
+
+ private:
+ void invokeApplicationId();
+ std::unique_ptr<FuzzedDataProvider> mFdp;
+};
+
+void KeystoreApplicationId::invokeApplicationId() {
+ std::optional<KeyAttestationApplicationId> applicationId;
+ bool shouldUsePackageInfoVector = mFdp->ConsumeBool();
+ if (shouldUsePackageInfoVector) {
+ KeyAttestationApplicationId::PackageInfoVector packageInfoVector;
+ int32_t packageVectorSize =
+ mFdp->ConsumeIntegralInRange<int32_t>(kPackageVectorSizeMin, kPackageVectorSizeMax);
+ for (int32_t packageSize = 0; packageSize < packageVectorSize; ++packageSize) {
+ auto packageInfoData = initPackageInfoData(mFdp.get());
+ packageInfoVector.push_back(make_optional<KeyAttestationPackageInfo>(
+ String16((packageInfoData.packageName).c_str()), packageInfoData.versionCode,
+ packageInfoData.sharedSignaturesVector));
+ }
+ applicationId = KeyAttestationApplicationId(std::move(packageInfoVector));
+ } else {
+ auto packageInfoData = initPackageInfoData(mFdp.get());
+ applicationId = KeyAttestationApplicationId(make_optional<KeyAttestationPackageInfo>(
+ String16((packageInfoData.packageName).c_str()), packageInfoData.versionCode,
+ packageInfoData.sharedSignaturesVector));
+ }
+ invokeReadWriteParcel(&applicationId.value());
+}
+
+void KeystoreApplicationId::process(const uint8_t* data, size_t size) {
+ mFdp = std::make_unique<FuzzedDataProvider>(data, size);
+ invokeApplicationId();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ KeystoreApplicationId keystoreApplicationId;
+ keystoreApplicationId.process(data, size);
+ return 0;
+}
diff --git a/keystore/tests/fuzzer/keystoreAttestationId_fuzzer.cpp b/keystore/tests/fuzzer/keystoreAttestationId_fuzzer.cpp
new file mode 100644
index 0000000..581da46
--- /dev/null
+++ b/keystore/tests/fuzzer/keystoreAttestationId_fuzzer.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 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 <keystore/keystore_attestation_id.h>
+
+#include "fuzzer/FuzzedDataProvider.h"
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider fdp = FuzzedDataProvider(data, size);
+ uint32_t uid = fdp.ConsumeIntegral<uint32_t>();
+ auto result = android::security::gather_attestation_application_id(uid);
+ result.isOk();
+ result.status();
+ result.value();
+ return 0;
+}
diff --git a/keystore/tests/fuzzer/keystoreCommon.h b/keystore/tests/fuzzer/keystoreCommon.h
new file mode 100644
index 0000000..7af3ba8
--- /dev/null
+++ b/keystore/tests/fuzzer/keystoreCommon.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+#ifndef KEYSTORECOMMON_H
+#define KEYSTORECOMMON_H
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+#include <keystore/KeyAttestationPackageInfo.h>
+#include <keystore/Signature.h>
+#include <vector>
+
+#include "fuzzer/FuzzedDataProvider.h"
+
+using namespace android;
+using namespace std;
+using ::content::pm::Signature;
+using ::security::keymaster::KeyAttestationPackageInfo;
+
+constexpr size_t kSignatureSizeMin = 1;
+constexpr size_t kSignatureSizeMax = 1000;
+constexpr size_t kRandomStringLength = 256;
+constexpr size_t kSignatureVectorSizeMin = 1;
+constexpr size_t kSignatureVectorSizeMax = 1000;
+
+struct PackageInfoData {
+ string packageName;
+ int64_t versionCode;
+ KeyAttestationPackageInfo::SharedSignaturesVector sharedSignaturesVector;
+};
+
+inline void invokeReadWriteParcel(Parcelable* obj) {
+ Parcel parcel;
+ obj->writeToParcel(&parcel);
+ parcel.setDataPosition(0);
+ obj->readFromParcel(&parcel);
+}
+
+inline vector<uint8_t> initSignatureData(FuzzedDataProvider* fdp) {
+ size_t signatureSize = fdp->ConsumeIntegralInRange(kSignatureSizeMin, kSignatureSizeMax);
+ vector<uint8_t> signatureData = fdp->ConsumeBytes<uint8_t>(signatureSize);
+ return signatureData;
+}
+
+inline PackageInfoData initPackageInfoData(FuzzedDataProvider* fdp) {
+ PackageInfoData packageInfoData;
+ packageInfoData.packageName = fdp->ConsumeRandomLengthString(kRandomStringLength);
+ packageInfoData.versionCode = fdp->ConsumeIntegral<int64_t>();
+ size_t signatureVectorSize =
+ fdp->ConsumeIntegralInRange(kSignatureVectorSizeMin, kSignatureVectorSizeMax);
+ KeyAttestationPackageInfo::SignaturesVector signatureVector;
+ for (size_t size = 0; size < signatureVectorSize; ++size) {
+ bool shouldUseParameterizedConstructor = fdp->ConsumeBool();
+ if (shouldUseParameterizedConstructor) {
+ vector<uint8_t> signatureData = initSignatureData(fdp);
+ signatureVector.push_back(make_optional<Signature>(signatureData));
+ } else {
+ signatureVector.push_back(std::nullopt);
+ }
+ }
+ packageInfoData.sharedSignaturesVector =
+ make_shared<KeyAttestationPackageInfo::SignaturesVector>(move(signatureVector));
+ return packageInfoData;
+}
+#endif // KEYSTORECOMMON_H
diff --git a/keystore/tests/fuzzer/keystorePackageInfo_fuzzer.cpp b/keystore/tests/fuzzer/keystorePackageInfo_fuzzer.cpp
new file mode 100644
index 0000000..63899ff
--- /dev/null
+++ b/keystore/tests/fuzzer/keystorePackageInfo_fuzzer.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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 "keystoreCommon.h"
+
+class KeystorePackageInfoFuzzer {
+ public:
+ void process(const uint8_t* data, size_t size);
+ ~KeystorePackageInfoFuzzer() {}
+
+ private:
+ void invokePackageInfo();
+ std::unique_ptr<FuzzedDataProvider> mFdp;
+};
+
+void KeystorePackageInfoFuzzer::invokePackageInfo() {
+ auto packageInfoData = initPackageInfoData(mFdp.get());
+ KeyAttestationPackageInfo packageInfo(String16((packageInfoData.packageName).c_str()),
+ packageInfoData.versionCode,
+ packageInfoData.sharedSignaturesVector);
+ invokeReadWriteParcel(&packageInfo);
+}
+
+void KeystorePackageInfoFuzzer::process(const uint8_t* data, size_t size) {
+ mFdp = std::make_unique<FuzzedDataProvider>(data, size);
+ invokePackageInfo();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ KeystorePackageInfoFuzzer keystorePackageInfoFuzzer;
+ keystorePackageInfoFuzzer.process(data, size);
+ return 0;
+}
diff --git a/keystore/tests/fuzzer/keystoreSignature_fuzzer.cpp b/keystore/tests/fuzzer/keystoreSignature_fuzzer.cpp
new file mode 100644
index 0000000..b8f8a73
--- /dev/null
+++ b/keystore/tests/fuzzer/keystoreSignature_fuzzer.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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 "keystoreCommon.h"
+#include <keystore/Signature.h>
+
+class KeystoreSignatureFuzzer {
+ public:
+ void process(const uint8_t* data, size_t size);
+ ~KeystoreSignatureFuzzer() {}
+
+ private:
+ void invokeSignature();
+ std::unique_ptr<FuzzedDataProvider> mFdp;
+};
+
+void KeystoreSignatureFuzzer::invokeSignature() {
+ std::optional<Signature> signature;
+ bool shouldUseParameterizedConstructor = mFdp->ConsumeBool();
+ if (shouldUseParameterizedConstructor) {
+ std::vector<uint8_t> signatureData = initSignatureData(mFdp.get());
+ signature = Signature(signatureData);
+ } else {
+ signature = Signature();
+ }
+ invokeReadWriteParcel(&signature.value());
+}
+
+void KeystoreSignatureFuzzer::process(const uint8_t* data, size_t size) {
+ mFdp = std::make_unique<FuzzedDataProvider>(data, size);
+ invokeSignature();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ KeystoreSignatureFuzzer keystoreSignatureFuzzer;
+ keystoreSignatureFuzzer.process(data, size);
+ return 0;
+}