Added fuzzers for libkeymaster4support

This patch adds following fuzz targets: keymaster4_attestation_fuzzer, keymaster4_authSet_fuzzer and keymaster4_utils_fuzzer

Test: ./keymaster4_attestation_fuzzer
Test: ./keymaster4_authSet_fuzzer
Test: ./keymaster4_utils_fuzzer
Bug: 189053968

Change-Id: Ieca5ba012f395a25cca9e37856d197031daf7dd9
diff --git a/keymaster/4.0/support/fuzzer/Android.bp b/keymaster/4.0/support/fuzzer/Android.bp
new file mode 100644
index 0000000..57a2d26
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/Android.bp
@@ -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.
+ *
+ */
+
+cc_defaults {
+    name: "keymaster4_fuzzer_defaults",
+    static_libs: [
+        "libbase",
+        "liblog",
+        "libkeymaster4support",
+        "libutils",
+    ],
+    shared_libs: [
+        "android.hardware.keymaster@4.0",
+        "libcrypto",
+        "libhidlbase",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 533764,
+    },
+}
+
+cc_fuzz {
+    name: "keymaster4_attestation_fuzzer",
+    defaults: [
+        "keymaster4_fuzzer_defaults",
+    ],
+    srcs: [
+        "keymaster4_attestation_fuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "keymaster4_authSet_fuzzer",
+    defaults: [
+        "keymaster4_fuzzer_defaults",
+    ],
+    srcs: [
+        "keymaster4_authSet_fuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "keymaster4_utils_fuzzer",
+    defaults: [
+        "keymaster4_fuzzer_defaults",
+    ],
+    srcs: [
+        "keymaster4_utils_fuzzer.cpp",
+    ],
+}
diff --git a/keymaster/4.0/support/fuzzer/README.md b/keymaster/4.0/support/fuzzer/README.md
new file mode 100644
index 0000000..bf4af25
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/README.md
@@ -0,0 +1,58 @@
+# Fuzzers for libkeymaster4support
+
+## Plugin Design Considerations
+The fuzzer plugins for libkeymaster4support are designed based on the understanding of the
+source code and try 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 fuzzers.
+
+libkeymaster4support supports the following parameters:
+1. Security Level (parameter name: `securityLevel`)
+2. Ec Curve (parameter name: `ecCurve`)
+3. Padding Mode (parameter name: `paddingMode`)
+4. Digest (parameter name: `digest`)
+5. Tag (parameter name: `tag`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `securityLevel` | 0.`SecurityLevel::SOFTWARE` 1.`SecurityLevel::TRUSTED_ENVIRONMENT` 2.`SecurityLevel::STRONGBOX`| Value obtained from FuzzedDataProvider|
+| `ecCurve` | 0.`EcCurve::P_224` 1.`EcCurve::P_256` 2.`EcCurve::P_384` 3. `EcCurve::P_521`| Value obtained from FuzzedDataProvider|
+| `paddingMode` | 0.`PaddingMode::NONE` 1.`PaddingMode::RSA_OAEP` 2.`PaddingMode::RSA_PSS` 3. `PaddingMode::RSA_PKCS1_1_5_ENCRYPT` 4.`PaddingMode::RSA_PKCS1_1_5_SIGN` 5.`PaddingMode::PKCS7`| Value obtained from FuzzedDataProvider|
+| `digest` | 1. `Digest::NONE` 2.`Digest::MD5` 3.`Digest::SHA1` 4.`Digest::SHA_2_224` 5.`Digest::SHA_2_256` 6.`Digest::SHA_2_384`  7.`Digest::SHA_2_512`| Value obtained from FuzzedDataProvider|
+| `tag` | 1. `Tag::INVALID` 2.`Tag::PURPOSE` 3.`Tag::ALGORITHM` 4.`Tag::KEY_SIZE` 5.`Tag::BLOCK_MODE` 6.`Tag::DIGEST` 7.`Tag::PADDING` 8.`Tag::CALLER_NONCE` 9.`Tag::MIN_MAC_LENGTH` 10.`Tag::EC_CURVE` 11.`Tag::RSA_PUBLIC_EXPONENT` 12.`Tag::INCLUDE_UNIQUE_ID` 13. `Tag::BLOB_USAGE_REQUIREMENTS` 14.`Tag::BOOTLOADER_ONLY` 15.`Tag::ROLLBACK_RESISTANCE` 16.`Tag::HARDWARE_TYPE` 17.`Tag::ACTIVE_DATETIME` 18. `Tag::ORIGINATION_EXPIRE_DATETIME` 19.`Tag::USAGE_EXPIRE_DATETIME` 20.`Tag::MIN_SECONDS_BETWEEN_OPS` 21.`Tag::MAX_USES_PER_BOOT` 22.`Tag::USER_ID` 23.` Tag::USER_SECURE_ID` 24.`Tag::NO_AUTH_REQUIRED` 25.`Tag::USER_AUTH_TYPE` 26.`Tag::AUTH_TIMEOUT` 27.`Tag::ALLOW_WHILE_ON_BODY` 28.`Tag::TRUSTED_USER_PRESENCE_REQUIRED` 29.`Tag::TRUSTED_CONFIRMATION_REQUIRED` 30.`Tag::UNLOCKED_DEVICE_REQUIRED` 31.`Tag::APPLICATION_ID` 32.`Tag::APPLICATION_DATA` 33.`Tag::CREATION_DATETIME` 34.`Tag::ORIGIN` 35.`Tag::ROOT_OF_TRUST` 36.`Tag::OS_VERSION` 37.`Tag::OS_PATCHLEVEL` 38.`Tag::UNIQUE_ID` 39.`Tag::ATTESTATION_CHALLENGE` 40.`Tag::ATTESTATION_APPLICATION_ID` 41.`Tag::ATTESTATION_ID_BRAND` 42.`Tag::ATTESTATION_ID_DEVICE` 43.`Tag::ATTESTATION_ID_PRODUCT` 44.`Tag::ATTESTATION_ID_SERIAL` 45.`Tag::ATTESTATION_ID_IMEI` 46.`Tag::ATTESTATION_ID_MEID` 47.`Tag::ATTESTATION_ID_MANUFACTURER` 48.`Tag::ATTESTATION_ID_MODEL` 49.`Tag::VENDOR_PATCHLEVEL` 50.`Tag::BOOT_PATCHLEVEL` 51.`Tag::ASSOCIATED_DATA` 52.`Tag::NONCE` 53.`Tag::MAC_LENGTH` 54.`Tag::RESET_SINCE_ID_ROTATION` 55.`Tag::CONFIRMATION_TOKEN`| Value obtained from FuzzedDataProvider|
+
+This also ensures that the plugins are always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugins feed the entire input data to the module.
+This ensures that the plugins tolerate any kind of input (empty, huge,
+malformed, etc) and dont `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build keymaster4_attestation_fuzzer, keymaster4_authSet_fuzzer and keymaster4_utils_fuzzer binaries
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) keymaster4_attestation_fuzzer
+  $ mm -j$(nproc) keymaster4_authSet_fuzzer
+  $ mm -j$(nproc) keymaster4_utils_fuzzer
+```
+#### Steps to run
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/${TARGET_ARCH}/keymaster4_attestation_fuzzer/keymaster4_attestation_fuzzer
+  $ adb shell /data/fuzz/${TARGET_ARCH}/keymaster4_authSet_fuzzer/keymaster4_authSet_fuzzer
+  $ adb shell /data/fuzz/${TARGET_ARCH}/keymaster4_utils_fuzzer/keymaster4_utils_fuzzer
+```
+
+## References:
+ * http://llvm.org/docs/LibFuzzer.html
+ * https://github.com/google/oss-fuzz
diff --git a/keymaster/4.0/support/fuzzer/keymaster4_attestation_fuzzer.cpp b/keymaster/4.0/support/fuzzer/keymaster4_attestation_fuzzer.cpp
new file mode 100644
index 0000000..b8b858d
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/keymaster4_attestation_fuzzer.cpp
@@ -0,0 +1,185 @@
+/*
+ * 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 <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <keymasterV4_0/attestation_record.h>
+#include <keymasterV4_0/openssl_utils.h>
+#include "keymaster4_common.h"
+
+namespace android::hardware::keymaster::V4_0::fuzzer {
+
+constexpr size_t kMinBytes = 1;
+constexpr size_t kMaxBytes = 10;
+
+class KeyMaster4AttestationFuzzer {
+  public:
+    void process(const uint8_t* data, size_t size);
+
+  private:
+    ErrorCode generateKey(const AuthorizationSet& keyDesc, hidl_vec<uint8_t>* keyBlob,
+                          KeyCharacteristics* keyCharacteristics);
+    ErrorCode attestKey(hidl_vec<uint8_t>& keyBlob, const AuthorizationSet& attestParams,
+                        hidl_vec<hidl_vec<uint8_t>>* certificateChain);
+    X509_Ptr parseCertificateBlob(const hidl_vec<uint8_t>& blob);
+    ASN1_OCTET_STRING* getAttestationRecord(const X509* certificate);
+    bool verifyAttestationRecord(const hidl_vec<uint8_t>& attestationCert);
+    void invokeAttestationRecord();
+
+    sp<IKeymasterDevice> mKeymaster = nullptr;
+    std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
+};
+
+ErrorCode KeyMaster4AttestationFuzzer::generateKey(const AuthorizationSet& key_desc,
+                                                   hidl_vec<uint8_t>* keyBlob,
+                                                   KeyCharacteristics* keyCharacteristics) {
+    ErrorCode error;
+    mKeymaster->generateKey(key_desc.hidl_data(),
+                            [&](ErrorCode hidlError, const hidl_vec<uint8_t>& hidlKeyBlob,
+                                const KeyCharacteristics& hidlKeyCharacteristics) {
+                                error = hidlError;
+                                *keyBlob = hidlKeyBlob;
+                                *keyCharacteristics = hidlKeyCharacteristics;
+                            });
+    return error;
+}
+
+ErrorCode KeyMaster4AttestationFuzzer::attestKey(hidl_vec<uint8_t>& keyBlob,
+                                                 const AuthorizationSet& attestParams,
+                                                 hidl_vec<hidl_vec<uint8_t>>* certificateChain) {
+    ErrorCode error;
+    auto rc = mKeymaster->attestKey(
+            keyBlob, attestParams.hidl_data(),
+            [&](ErrorCode hidlError, const hidl_vec<hidl_vec<uint8_t>>& hidlCertificateChain) {
+                error = hidlError;
+                *certificateChain = hidlCertificateChain;
+            });
+
+    if (!rc.isOk()) {
+        return ErrorCode::UNKNOWN_ERROR;
+    }
+    return error;
+}
+
+X509_Ptr KeyMaster4AttestationFuzzer::parseCertificateBlob(const hidl_vec<uint8_t>& blob) {
+    const uint8_t* p = blob.data();
+    return X509_Ptr(d2i_X509(nullptr, &p, blob.size()));
+}
+
+/**
+ * @brief getAttestationRecord() accepts a 'certificate' pointer and the return value points to the
+ * data owned by 'certificate'. Hence, 'certificate' should not be freed and the return value cannot
+ * outlive 'certificate'
+ */
+ASN1_OCTET_STRING* KeyMaster4AttestationFuzzer::getAttestationRecord(const X509* certificate) {
+    ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
+    if (!oid.get()) {
+        return nullptr;
+    }
+
+    int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
+    if (location == -1) {
+        return nullptr;
+    }
+
+    X509_EXTENSION* attestRecordExt = X509_get_ext(certificate, location);
+    if (!attestRecordExt) {
+        return nullptr;
+    }
+
+    ASN1_OCTET_STRING* attestRecord = X509_EXTENSION_get_data(attestRecordExt);
+    return attestRecord;
+}
+
+bool KeyMaster4AttestationFuzzer::verifyAttestationRecord(
+        const hidl_vec<uint8_t>& attestationCert) {
+    X509_Ptr cert(parseCertificateBlob(attestationCert));
+    if (!cert.get()) {
+        return false;
+    }
+
+    ASN1_OCTET_STRING* attestRecord = getAttestationRecord(cert.get());
+    if (!attestRecord) {
+        return false;
+    }
+
+    AuthorizationSet attestationSwEnforced;
+    AuthorizationSet attestationHwEnforced;
+    uint32_t attestationVersion;
+    uint32_t keymasterVersion;
+    SecurityLevel securityLevel;
+    SecurityLevel keymasterSecurityLevel;
+    hidl_vec<uint8_t> attestationChallenge;
+    hidl_vec<uint8_t> attestationUniqueId;
+
+    auto error = parse_attestation_record(
+            attestRecord->data, attestRecord->length, &attestationVersion, &securityLevel,
+            &keymasterVersion, &keymasterSecurityLevel, &attestationChallenge,
+            &attestationSwEnforced, &attestationHwEnforced, &attestationUniqueId);
+    if (error != ErrorCode::OK) {
+        return false;
+    }
+
+    hidl_vec<uint8_t> verifiedBootKey;
+    keymaster_verified_boot_t verifiedBootState;
+    bool device_locked;
+    hidl_vec<uint8_t> verifiedBootHash;
+
+    parse_root_of_trust(attestRecord->data, attestRecord->length, &verifiedBootKey,
+                        &verifiedBootState, &device_locked, &verifiedBootHash);
+    return true;
+}
+
+void KeyMaster4AttestationFuzzer::invokeAttestationRecord() {
+    mKeymaster = IKeymasterDevice::getService();
+    if (!mKeymaster) {
+        return;
+    }
+
+    hidl_vec<uint8_t> keyBlob;
+    KeyCharacteristics keyCharacteristics;
+    generateKey(createAuthorizationSet(mFdp), &keyBlob, &keyCharacteristics);
+
+    hidl_vec<hidl_vec<uint8_t>> certificateChain;
+
+    std::vector<uint8_t> challenge, attestationId;
+    challenge =
+            mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
+    attestationId =
+            mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
+    attestKey(keyBlob,
+              AuthorizationSetBuilder()
+                      .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+                      .Authorization(TAG_ATTESTATION_APPLICATION_ID, attestationId),
+              &certificateChain);
+
+    if (certificateChain.size() > 0) {
+        verifyAttestationRecord(certificateChain[mFdp->ConsumeIntegralInRange<size_t>(
+                0, certificateChain.size() - 1)]);
+    }
+}
+
+void KeyMaster4AttestationFuzzer::process(const uint8_t* data, size_t size) {
+    mFdp = std::make_unique<FuzzedDataProvider>(data, size);
+    invokeAttestationRecord();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMaster4AttestationFuzzer km4AttestationFuzzer;
+    km4AttestationFuzzer.process(data, size);
+    return 0;
+}
+
+}  // namespace android::hardware::keymaster::V4_0::fuzzer
diff --git a/keymaster/4.0/support/fuzzer/keymaster4_authSet_fuzzer.cpp b/keymaster/4.0/support/fuzzer/keymaster4_authSet_fuzzer.cpp
new file mode 100644
index 0000000..63e0499
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/keymaster4_authSet_fuzzer.cpp
@@ -0,0 +1,202 @@
+/*
+ * 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 <fstream>
+#include "keymaster4_common.h"
+
+namespace android::hardware::keymaster::V4_0::fuzzer {
+
+constexpr size_t kMaxVectorSize = 100;
+constexpr size_t kMaxKeyParameter = 10;
+
+constexpr Tag kTagArray[] = {Tag::INVALID,
+                             Tag::PURPOSE,
+                             Tag::ALGORITHM,
+                             Tag::KEY_SIZE,
+                             Tag::BLOCK_MODE,
+                             Tag::DIGEST,
+                             Tag::PADDING,
+                             Tag::CALLER_NONCE,
+                             Tag::MIN_MAC_LENGTH,
+                             Tag::EC_CURVE,
+                             Tag::RSA_PUBLIC_EXPONENT,
+                             Tag::INCLUDE_UNIQUE_ID,
+                             Tag::BLOB_USAGE_REQUIREMENTS,
+                             Tag::BOOTLOADER_ONLY,
+                             Tag::ROLLBACK_RESISTANCE,
+                             Tag::HARDWARE_TYPE,
+                             Tag::ACTIVE_DATETIME,
+                             Tag::ORIGINATION_EXPIRE_DATETIME,
+                             Tag::USAGE_EXPIRE_DATETIME,
+                             Tag::MIN_SECONDS_BETWEEN_OPS,
+                             Tag::MAX_USES_PER_BOOT,
+                             Tag::USER_ID,
+                             Tag::USER_SECURE_ID,
+                             Tag::NO_AUTH_REQUIRED,
+                             Tag::USER_AUTH_TYPE,
+                             Tag::AUTH_TIMEOUT,
+                             Tag::ALLOW_WHILE_ON_BODY,
+                             Tag::TRUSTED_USER_PRESENCE_REQUIRED,
+                             Tag::TRUSTED_CONFIRMATION_REQUIRED,
+                             Tag::UNLOCKED_DEVICE_REQUIRED,
+                             Tag::APPLICATION_ID,
+                             Tag::APPLICATION_DATA,
+                             Tag::CREATION_DATETIME,
+                             Tag::ORIGIN,
+                             Tag::ROOT_OF_TRUST,
+                             Tag::OS_VERSION,
+                             Tag::OS_PATCHLEVEL,
+                             Tag::UNIQUE_ID,
+                             Tag::ATTESTATION_CHALLENGE,
+                             Tag::ATTESTATION_APPLICATION_ID,
+                             Tag::ATTESTATION_ID_BRAND,
+                             Tag::ATTESTATION_ID_DEVICE,
+                             Tag::ATTESTATION_ID_PRODUCT,
+                             Tag::ATTESTATION_ID_SERIAL,
+                             Tag::ATTESTATION_ID_IMEI,
+                             Tag::ATTESTATION_ID_MEID,
+                             Tag::ATTESTATION_ID_MANUFACTURER,
+                             Tag::ATTESTATION_ID_MODEL,
+                             Tag::VENDOR_PATCHLEVEL,
+                             Tag::BOOT_PATCHLEVEL,
+                             Tag::ASSOCIATED_DATA,
+                             Tag::NONCE,
+                             Tag::MAC_LENGTH,
+                             Tag::RESET_SINCE_ID_ROTATION,
+                             Tag::CONFIRMATION_TOKEN};
+
+class KeyMaster4AuthSetFuzzer {
+  public:
+    void process(const uint8_t* data, size_t size);
+
+  private:
+    void invokeAuthSetAPIs();
+    std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
+};
+
+/**
+ * @brief invokeAuthSetAPIs() function aims at calling functions of authorization_set.cpp
+ * and authorization_set.h in order to get a good coverage for libkeymaster4support.
+ */
+void KeyMaster4AuthSetFuzzer::invokeAuthSetAPIs() {
+    AuthorizationSet authSet = createAuthorizationSet(mFdp);
+    while (mFdp->remaining_bytes() > 0) {
+        uint32_t action = mFdp->ConsumeIntegralInRange<uint32_t>(0, 15);
+        switch (action) {
+            case 0: {
+                authSet.Sort();
+            } break;
+            case 1: {
+                authSet.Deduplicate();
+            } break;
+            case 2: {
+                authSet.Union(createAuthorizationSet(mFdp));
+            } break;
+            case 3: {
+                authSet.Subtract(createAuthorizationSet(mFdp));
+            } break;
+            case 4: {
+                std::filebuf fbOut;
+                fbOut.open("/dev/zero", std::ios::out);
+                std::ostream out(&fbOut);
+                authSet.Serialize(&out);
+            } break;
+            case 5: {
+                std::filebuf fbIn;
+                fbIn.open("/dev/zero", std::ios::in);
+                std::istream in(&fbIn);
+                authSet.Deserialize(&in);
+            } break;
+            case 6: {  // invoke push_back()
+                AuthorizationSetBuilder builder = AuthorizationSetBuilder();
+                for (const KeyParameter& tag : authSet) {
+                    builder.push_back(tag);
+                }
+                AuthorizationSet params = createAuthorizationSet(mFdp);
+                authSet.push_back(params);
+            } break;
+            case 7: {  // invoke copy constructor
+                auto params = AuthorizationSetBuilder().Authorizations(authSet);
+                authSet = params;
+            } break;
+            case 8: {  // invoke move constructor
+                auto params = AuthorizationSetBuilder().Authorizations(authSet);
+                authSet = std::move(params);
+            } break;
+            case 9: {  // invoke Constructor from hidl_vec<KeyParameter>
+                hidl_vec<KeyParameter> keyParam;
+                size_t numKeyParam = mFdp->ConsumeIntegralInRange<size_t>(1, kMaxKeyParameter);
+                keyParam.resize(numKeyParam);
+                for (size_t i = 0; i < numKeyParam - 1; ++i) {
+                    keyParam[i].tag = mFdp->PickValueInArray(kTagArray);
+                    std::vector<uint8_t> dataVector = mFdp->ConsumeBytes<uint8_t>(
+                            mFdp->ConsumeIntegralInRange<size_t>(0, kMaxVectorSize));
+                    keyParam[i].blob = dataVector;
+                }
+                if (mFdp->ConsumeBool()) {
+                    AuthorizationSet auths(keyParam);
+                    auths.push_back(AuthorizationSet(keyParam));
+                } else {  // invoke operator=
+                    AuthorizationSet auths = keyParam;
+                }
+            } break;
+            case 10: {  // invoke 'Contains()'
+                Tag tag;
+                if (authSet.size() > 0) {
+                    tag = authSet[mFdp->ConsumeIntegralInRange<size_t>(0, authSet.size() - 1)].tag;
+                }
+                authSet.Contains(mFdp->ConsumeBool() ? tag : mFdp->PickValueInArray(kTagArray));
+            } break;
+            case 11: {  // invoke 'GetTagCount()'
+                Tag tag;
+                if (authSet.size() > 0) {
+                    tag = authSet[mFdp->ConsumeIntegralInRange<size_t>(0, authSet.size() - 1)].tag;
+                }
+                authSet.GetTagCount(mFdp->ConsumeBool() ? tag : mFdp->PickValueInArray(kTagArray));
+            } break;
+            case 12: {  // invoke 'empty()'
+                authSet.empty();
+            } break;
+            case 13: {  // invoke 'data()'
+                authSet.data();
+            } break;
+            case 14: {  // invoke 'hidl_data()'
+                authSet.hidl_data();
+            } break;
+            case 15: {  // invoke 'erase()'
+                if (authSet.size() > 0) {
+                    authSet.erase(mFdp->ConsumeIntegralInRange<size_t>(0, authSet.size() - 1));
+                }
+            } break;
+            default:
+                break;
+        };
+    }
+    authSet.Clear();
+}
+
+void KeyMaster4AuthSetFuzzer::process(const uint8_t* data, size_t size) {
+    mFdp = std::make_unique<FuzzedDataProvider>(data, size);
+    invokeAuthSetAPIs();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMaster4AuthSetFuzzer km4AuthSetFuzzer;
+    km4AuthSetFuzzer.process(data, size);
+    return 0;
+}
+
+}  // namespace android::hardware::keymaster::V4_0::fuzzer
diff --git a/keymaster/4.0/support/fuzzer/keymaster4_common.h b/keymaster/4.0/support/fuzzer/keymaster4_common.h
new file mode 100644
index 0000000..f6e53ee
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/keymaster4_common.h
@@ -0,0 +1,198 @@
+/*
+ * 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 __KEYMASTER4_COMMON_H__
+#define __KEYMASTER4_COMMON_H__
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <keymasterV4_0/authorization_set.h>
+
+namespace android::hardware::keymaster::V4_0::fuzzer {
+
+using ::android::hardware::hidl_vec;
+
+constexpr uint32_t kKeySize = 2048;
+constexpr uint32_t kPublicExponent = 65537;
+
+constexpr EcCurve kCurve[] = {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
+
+constexpr PaddingMode kPaddingMode[] = {
+        PaddingMode::NONE,
+        PaddingMode::RSA_OAEP,
+        PaddingMode::RSA_PSS,
+        PaddingMode::RSA_PKCS1_1_5_ENCRYPT,
+        PaddingMode::RSA_PKCS1_1_5_SIGN,
+        PaddingMode::PKCS7,
+};
+
+constexpr Digest kDigest[] = {
+        Digest::NONE,      Digest::MD5,       Digest::SHA1,      Digest::SHA_2_224,
+        Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512,
+};
+
+enum AuthSet : uint32_t {
+    RSA_SIGNING_KEY = 0u,
+    RSA_ENCRYPRION_KEY,
+    ECDSA_SIGNING_CURVE,
+    ECDSA_SIGNING_KEY,
+    AES_ENCRYPTION_KEY,
+    TRIPLE_DES,
+    HMAC,
+    NO_DIGEST,
+    ECB_MODE,
+    GSM_MODE_MIN_MAC,
+    GSM_MODE_MAC,
+    BLOCK_MODE,
+    kMaxValue = BLOCK_MODE
+};
+
+AuthorizationSet createAuthorizationSet(std::unique_ptr<FuzzedDataProvider>& dataProvider) {
+    uint32_t authSet = dataProvider->ConsumeEnum<AuthSet>();
+    switch (authSet) {
+        case RSA_SIGNING_KEY: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .RsaSigningKey(kKeySize, kPublicExponent)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case RSA_ENCRYPRION_KEY: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .RsaEncryptionKey(kKeySize, kPublicExponent)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case ECDSA_SIGNING_CURVE: {
+            EcCurve ecCurve = dataProvider->PickValueInArray(kCurve);
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcdsaSigningKey(ecCurve)
+                    .Digest(digest)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case ECDSA_SIGNING_KEY: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcdsaSigningKey(kKeySize)
+                    .Digest(digest)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case AES_ENCRYPTION_KEY: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .AesEncryptionKey(kKeySize)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case TRIPLE_DES: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .TripleDesEncryptionKey(kKeySize)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case HMAC: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .HmacKey(kKeySize)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case NO_DIGEST: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .NoDigestOrPadding()
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case ECB_MODE: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .EcbMode()
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case GSM_MODE_MIN_MAC: {
+            uint32_t minMacLength = dataProvider->ConsumeIntegral<uint32_t>();
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .GcmModeMinMacLen(minMacLength)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case GSM_MODE_MAC: {
+            uint32_t macLength = dataProvider->ConsumeIntegral<uint32_t>();
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .GcmModeMacLen(macLength)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        case BLOCK_MODE: {
+            Digest digest = dataProvider->PickValueInArray(kDigest);
+            PaddingMode padding = dataProvider->PickValueInArray(kPaddingMode);
+            auto blockModes = {
+                    BlockMode::ECB,
+                    BlockMode::CBC,
+                    BlockMode::CTR,
+                    BlockMode::GCM,
+            };
+            return AuthorizationSetBuilder()
+                    .Authorization(TAG_NO_AUTH_REQUIRED)
+                    .BlockMode(blockModes)
+                    .Digest(digest)
+                    .Padding(padding)
+                    .Authorization(TAG_INCLUDE_UNIQUE_ID);
+        } break;
+        default:
+            break;
+    };
+    return AuthorizationSetBuilder();
+}
+
+}  // namespace android::hardware::keymaster::V4_0::fuzzer
+
+#endif  // __KEYMASTER4_COMMON_H__
diff --git a/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp b/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp
new file mode 100644
index 0000000..bf074e8
--- /dev/null
+++ b/keymaster/4.0/support/fuzzer/keymaster4_utils_fuzzer.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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 <hardware/hw_auth_token.h>
+#include <keymasterV4_0/keymaster_utils.h>
+#include "keymaster4_common.h"
+
+namespace android::hardware::keymaster::V4_0::fuzzer {
+
+using android::hardware::keymaster::V4_0::SecurityLevel;
+using android::hardware::keymaster::V4_0::VerificationToken;
+using android::hardware::keymaster::V4_0::support::deserializeVerificationToken;
+using android::hardware::keymaster::V4_0::support::serializeVerificationToken;
+
+constexpr SecurityLevel kSecurityLevel[]{
+        SecurityLevel::SOFTWARE,
+        SecurityLevel::TRUSTED_ENVIRONMENT,
+        SecurityLevel::STRONGBOX,
+};
+constexpr size_t kMaxVectorSize = 100;
+constexpr size_t kMaxCharacters = 100;
+
+class KeyMaster4UtilsFuzzer {
+  public:
+    void process(const uint8_t* data, size_t size);
+
+  private:
+    void invokeKeyMasterUtils();
+    std::unique_ptr<FuzzedDataProvider> mFdp = nullptr;
+};
+
+void KeyMaster4UtilsFuzzer::invokeKeyMasterUtils() {
+    support::getOsVersion();
+    support::getOsPatchlevel();
+
+    VerificationToken token;
+    token.challenge = mFdp->ConsumeIntegral<uint64_t>();
+    token.timestamp = mFdp->ConsumeIntegral<uint64_t>();
+    token.securityLevel = mFdp->PickValueInArray(kSecurityLevel);
+    size_t vectorSize = mFdp->ConsumeIntegralInRange<size_t>(0, kMaxVectorSize);
+    token.mac.resize(vectorSize);
+    for (size_t n = 0; n < vectorSize; ++n) {
+        token.mac[n] = n;
+    }
+    std::optional<std::vector<uint8_t>> serialized = serializeVerificationToken(token);
+    if (serialized.has_value()) {
+        std::optional<VerificationToken> deserialized =
+                deserializeVerificationToken(serialized.value());
+    }
+
+    std::vector<uint8_t> dataVector;
+    size_t size = mFdp->ConsumeIntegralInRange<size_t>(0, sizeof(hw_auth_token_t));
+    dataVector = mFdp->ConsumeBytes<uint8_t>(size);
+    support::blob2hidlVec(dataVector.data(), dataVector.size());
+
+    support::blob2hidlVec(dataVector);
+
+    std::string str = mFdp->ConsumeRandomLengthString(kMaxCharacters);
+    support::blob2hidlVec(str);
+
+    HardwareAuthToken authToken = support::hidlVec2AuthToken(dataVector);
+    hidl_vec<uint8_t> volatile hidlVector = support::authToken2HidlVec(authToken);
+}
+
+void KeyMaster4UtilsFuzzer::process(const uint8_t* data, size_t size) {
+    mFdp = std::make_unique<FuzzedDataProvider>(data, size);
+    invokeKeyMasterUtils();
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    KeyMaster4UtilsFuzzer kmUtilsFuzzer;
+    kmUtilsFuzzer.process(data, size);
+    return 0;
+}
+
+}  // namespace android::hardware::keymaster::V4_0::fuzzer