diff options
Diffstat (limited to 'fuzzer/k4_AndroidKeymaster4Device_fuzzer.cpp')
-rw-r--r-- | fuzzer/k4_AndroidKeymaster4Device_fuzzer.cpp | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/fuzzer/k4_AndroidKeymaster4Device_fuzzer.cpp b/fuzzer/k4_AndroidKeymaster4Device_fuzzer.cpp new file mode 100644 index 0000000..be60b75 --- /dev/null +++ b/fuzzer/k4_AndroidKeymaster4Device_fuzzer.cpp @@ -0,0 +1,265 @@ +/* + * 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 <AndroidKeymaster4Device.h> +#include <android/hardware/keymaster/4.0/IKeymasterDevice.h> +#include <fuzzer/FuzzedDataProvider.h> +#include <keymasterV4_0/authorization_set.h> + +namespace keymaster::V4_0::ng::fuzzer { + +using ::android::hardware::hidl_string; +using ::android::hardware::keymaster::V4_0::AuthorizationSet; +using ::android::hardware::keymaster::V4_0::AuthorizationSetBuilder; +using ::android::hardware::keymaster::V4_0::Digest; +using ::android::hardware::keymaster::V4_0::KeyFormat; +using ::android::hardware::keymaster::V4_0::KeyPurpose; +using ::android::hardware::keymaster::V4_0::PaddingMode; + +constexpr SecurityLevel kSecurityLevel[] = { + SecurityLevel::SOFTWARE, + SecurityLevel::TRUSTED_ENVIRONMENT, + SecurityLevel::STRONGBOX, +}; + +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, +}; + +constexpr KeyFormat kKeyFormat[] = { + KeyFormat::X509, + KeyFormat::PKCS8, + KeyFormat::RAW, +}; + +constexpr KeyPurpose kKeyPurpose[] = { + KeyPurpose::ENCRYPT, KeyPurpose::DECRYPT, KeyPurpose::SIGN, + KeyPurpose::VERIFY, KeyPurpose::WRAP_KEY, +}; + +constexpr uint32_t kRSAKeySize[] = {1024, 2048, 3072, 4096}; +constexpr uint32_t kECCKeySize[] = {224, 256, 384, 521}; +constexpr size_t kMinBytes = 0; +constexpr size_t kMaxBytes = 100; + +class KeyMaster4DeviceFuzzer { + public: + bool init(const uint8_t* data, size_t size); + void process(); + + private: + AuthorizationSet getAuthorizationSet(); + sp<IKeymasterDevice> mKeymaster = nullptr; + std::unique_ptr<FuzzedDataProvider> mFdp = nullptr; +}; + +AuthorizationSet KeyMaster4DeviceFuzzer::getAuthorizationSet() { + auto keyMasterFunction = mFdp->PickValueInArray< + const std::function<android::hardware::keymaster::V4_0::AuthorizationSet()>>({ + [&]() { + return AuthorizationSetBuilder() + .RsaSigningKey(mFdp->PickValueInArray(kRSAKeySize), + mFdp->ConsumeIntegral<uint32_t>()) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .EcdsaKey(mFdp->PickValueInArray(kECCKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .AesKey(mFdp->PickValueInArray(kECCKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .TripleDesKey(mFdp->PickValueInArray(kRSAKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .HmacKey(mFdp->PickValueInArray(kRSAKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .RsaEncryptionKey(mFdp->PickValueInArray(kRSAKeySize), + mFdp->ConsumeIntegral<uint64_t>()) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .EcdsaSigningKey(mFdp->PickValueInArray(kRSAKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .AesEncryptionKey(mFdp->PickValueInArray(kECCKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .TripleDesEncryptionKey(mFdp->PickValueInArray(kRSAKeySize)) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + [&]() { + return AuthorizationSetBuilder() + .RsaKey(mFdp->PickValueInArray(kRSAKeySize), mFdp->ConsumeIntegral<uint64_t>()) + .Digest(mFdp->PickValueInArray(kDigest)) + .Padding(mFdp->PickValueInArray(kPaddingMode)); + }, + }); + return keyMasterFunction(); +} + +bool KeyMaster4DeviceFuzzer::init(const uint8_t* data, size_t size) { + mFdp = std::make_unique<FuzzedDataProvider>(data, size); + mKeymaster = CreateKeymasterDevice(mFdp->PickValueInArray(kSecurityLevel)); + if (!mKeymaster) { + return false; + } + return true; +} + +void KeyMaster4DeviceFuzzer::process() { + std::vector<uint8_t> dataVec = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->addRngEntropy(dataVec); + + hidl_vec<uint8_t> keyBlob = {}; + mKeymaster->generateKey(getAuthorizationSet().hidl_data(), + [&]([[maybe_unused]] ErrorCode hidlError, + const hidl_vec<uint8_t>& hidlKeyBlob, + [[maybe_unused]] const KeyCharacteristics& hidlKeyCharacteristics) { + keyBlob = hidlKeyBlob; + }); + + mKeymaster->attestKey( + keyBlob, getAuthorizationSet().hidl_data(), + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<hidl_vec<uint8_t>>& hidlCertificateChain) {}); + + mKeymaster->upgradeKey(keyBlob, hidl_vec<KeyParameter>(), + [&]([[maybe_unused]] ErrorCode error, + [[maybe_unused]] const hidl_vec<uint8_t>& upgraded_blob) {}); + + std::vector<uint8_t> clientId = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + std::vector<uint8_t> appData = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->getKeyCharacteristics( + keyBlob, clientId, appData, + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const KeyCharacteristics& hidlKeyCharacteristics) {}); + + KeyFormat keyFormat = mFdp->PickValueInArray(kKeyFormat); + std::vector<uint8_t> keyData; + keyData = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + ErrorCode importKeyError; + if (mKeymaster + ->importKey(getAuthorizationSet().hidl_data(), keyFormat, keyData, + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlKeyBlob, + [[maybe_unused]] const KeyCharacteristics& hidlKeyCharacteristics) { + importKeyError = hidlError; + }) + .isOk()) { + if (importKeyError == ErrorCode::OK) { + abort(); + } + } + + std::vector<uint8_t> wrappedKey, wrappingKey, maskingKey; + wrappedKey = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + wrappingKey = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + maskingKey = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + uint64_t passwordSid = mFdp->ConsumeIntegral<uint64_t>(); + uint64_t biometricSid = mFdp->ConsumeIntegral<uint64_t>(); + mKeymaster->importWrappedKey( + wrappedKey, wrappingKey, maskingKey, getAuthorizationSet().hidl_data(), passwordSid, + biometricSid, + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlKeyBlob, + [[maybe_unused]] const KeyCharacteristics& hidlKeyCharacteristics) {}); + + std::vector<uint8_t> keyBlobExportKey = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->exportKey(keyFormat, keyBlobExportKey, clientId, appData, + [&]([[maybe_unused]] ErrorCode hidlErrorCode, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlKeyMaterial) {}); + + KeyPurpose keyPurpose = mFdp->PickValueInArray(kKeyPurpose); + mKeymaster->begin(keyPurpose, keyBlob, getAuthorizationSet().hidl_data(), HardwareAuthToken(), + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<KeyParameter>& hidlOutParams, + [[maybe_unused]] uint64_t hidlOpHandle) {}); + + uint64_t operationHandle = mFdp->ConsumeIntegral<uint64_t>(); + std::vector<uint8_t> input = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->update(operationHandle, getAuthorizationSet().hidl_data(), input, + HardwareAuthToken(), VerificationToken(), + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] uint32_t hidlInputConsumed, + [[maybe_unused]] const hidl_vec<KeyParameter>& hidlOutParams, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlOutput) {}); + + std::vector<uint8_t> signature = + mFdp->ConsumeBytes<uint8_t>(mFdp->ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes)); + mKeymaster->finish(operationHandle, getAuthorizationSet().hidl_data(), input, signature, + HardwareAuthToken(), VerificationToken(), + [&]([[maybe_unused]] ErrorCode hidlError, + [[maybe_unused]] const hidl_vec<KeyParameter>& hidlOutParams, + [[maybe_unused]] const hidl_vec<uint8_t>& hidlOutput) {}); + + mKeymaster->deleteKey(keyBlob); + mKeymaster->deleteAllKeys(); + mKeymaster->abort(mFdp->ConsumeIntegral<uint64_t>()); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + KeyMaster4DeviceFuzzer km4DeviceFuzzer; + if (km4DeviceFuzzer.init(data, size)) { + km4DeviceFuzzer.process(); + } + return 0; +} +} // namespace keymaster::V4_0::ng::fuzzer |