266 lines
11 KiB
C++
266 lines
11 KiB
C++
/*
|
|
* 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
|