/* * 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 #include #include #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* keyBlob, KeyCharacteristics* keyCharacteristics); ErrorCode attestKey(hidl_vec& keyBlob, const AuthorizationSet& attestParams, hidl_vec>* certificateChain); X509_Ptr parseCertificateBlob(const hidl_vec& blob); ASN1_OCTET_STRING* getAttestationRecord(const X509* certificate); bool verifyAttestationRecord(const hidl_vec& attestationCert); void invokeAttestationRecord(); sp mKeymaster = nullptr; std::unique_ptr mFdp = nullptr; }; ErrorCode KeyMaster4AttestationFuzzer::generateKey(const AuthorizationSet& key_desc, hidl_vec* keyBlob, KeyCharacteristics* keyCharacteristics) { ErrorCode error; mKeymaster->generateKey(key_desc.hidl_data(), [&](ErrorCode hidlError, const hidl_vec& hidlKeyBlob, const KeyCharacteristics& hidlKeyCharacteristics) { error = hidlError; *keyBlob = hidlKeyBlob; *keyCharacteristics = hidlKeyCharacteristics; }); return error; } ErrorCode KeyMaster4AttestationFuzzer::attestKey(hidl_vec& keyBlob, const AuthorizationSet& attestParams, hidl_vec>* certificateChain) { ErrorCode error; auto rc = mKeymaster->attestKey( keyBlob, attestParams.hidl_data(), [&](ErrorCode hidlError, const hidl_vec>& hidlCertificateChain) { error = hidlError; *certificateChain = hidlCertificateChain; }); if (!rc.isOk()) { return ErrorCode::UNKNOWN_ERROR; } return error; } X509_Ptr KeyMaster4AttestationFuzzer::parseCertificateBlob(const hidl_vec& 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& 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 attestationChallenge; hidl_vec 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 verifiedBootKey; keymaster_verified_boot_t verifiedBootState; bool device_locked; hidl_vec 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 keyBlob; KeyCharacteristics keyCharacteristics; generateKey(createAuthorizationSet(mFdp), &keyBlob, &keyCharacteristics); hidl_vec> certificateChain; std::vector challenge, attestationId; challenge = mFdp->ConsumeBytes(mFdp->ConsumeIntegralInRange(kMinBytes, kMaxBytes)); attestationId = mFdp->ConsumeBytes(mFdp->ConsumeIntegralInRange(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( 0, certificateChain.size() - 1)]); } } void KeyMaster4AttestationFuzzer::process(const uint8_t* data, size_t size) { mFdp = std::make_unique(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