| /* |
| * 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 |