/* * Copyright (C) 2023 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 using namespace wvcdm; using namespace wvutil; using namespace video_widevine; static constexpr uint16_t kMaxByte = 256; static constexpr uint16_t kMaxVectorSize = 1000; static constexpr uint8_t kMinVectorSize = 0; static constexpr uint8_t kMinCdmCertificateType = 0; static constexpr uint8_t kMaxCdmCertificateType = 2; static constexpr uint8_t kMinKeySetId = 0; static constexpr uint8_t kMaxKeySetId = 100; static constexpr uint8_t kProvisioningType[] = { SignedProvisioningMessage_ProvisioningType_PROVISIONING_TYPE_UNSPECIFIED, SignedProvisioningMessage_ProvisioningType_SERVICE_CERTIFICATE_REQUEST, SignedProvisioningMessage_ProvisioningType_PROVISIONING_20, SignedProvisioningMessage_ProvisioningType_PROVISIONING_30, SignedProvisioningMessage_ProvisioningType_PROVISIONING_40, SignedProvisioningMessage_ProvisioningType_ARCPP_PROVISIONING, SignedProvisioningMessage_ProvisioningType_ANDROID_ATTESTATION_KEYBOX_OTA, SignedProvisioningMessage_ProvisioningType_INTEL_SIGMA_101, SignedProvisioningMessage_ProvisioningType_INTEL_SIGMA_210}; class CertificateProvisioningFuzzer { public: CertificateProvisioningFuzzer(const uint8_t *data, size_t size) : mFdp(data, size){}; void process(); private: FuzzedDataProvider mFdp; }; void createResponseMessage(std::string &responseMessage, FuzzedDataProvider &mFdp) { if (mFdp.ConsumeBool()) { DrmCertificate drmCertificate; DrmCertificate_Algorithm algorithm = (DrmCertificate_Algorithm)mFdp.ConsumeIntegralInRange( DrmCertificate_Algorithm:: DrmCertificate_Algorithm_UNKNOWN_ALGORITHM, DrmCertificate_Algorithm::DrmCertificate_Algorithm_ECC_SECP521R1); drmCertificate.set_algorithm(algorithm); std::string setDrm; if (mFdp.ConsumeBool()) { drmCertificate.SerializeToString(&setDrm); } else { setDrm = mFdp.ConsumeRandomLengthString(kMaxByte); } SignedDrmCertificate signedDrmCertificate; signedDrmCertificate.set_drm_certificate(setDrm); std::string setDevice; if (mFdp.ConsumeBool()) { signedDrmCertificate.SerializeToString(&setDevice); } else { setDevice = mFdp.ConsumeRandomLengthString(kMaxByte); } ProvisioningResponse provisioningResponse; ProvisioningResponse_ProvisioningStatus status = (ProvisioningResponse_ProvisioningStatus)mFdp.ConsumeIntegralInRange< int32_t>( ProvisioningResponse_ProvisioningStatus:: ProvisioningResponse_ProvisioningStatus_NO_ERROR, ProvisioningResponse_ProvisioningStatus:: ProvisioningResponse_ProvisioningStatus_REVOKED_DEVICE_SERIES); provisioningResponse.set_status(status); if (mFdp.ConsumeBool()) { provisioningResponse.set_device_certificate(setDevice); } std::string setMessage; if (mFdp.ConsumeBool()) { provisioningResponse.SerializeToString(&setMessage); } else { setMessage = mFdp.ConsumeRandomLengthString(kMaxByte); } SignedProvisioningMessage signedProvisioningMessage; if (mFdp.ConsumeBool()) { signedProvisioningMessage.set_message(setMessage); } else { signedProvisioningMessage.set_message( mFdp.ConsumeRandomLengthString(kMaxByte)); } signedProvisioningMessage.set_signature( mFdp.ConsumeRandomLengthString(kMaxByte)); if (mFdp.ConsumeBool()) { signedProvisioningMessage.set_provisioning_type( (SignedProvisioningMessage_ProvisioningType)mFdp.PickValueInArray( kProvisioningType)); } else { signedProvisioningMessage.set_provisioning_type( (SignedProvisioningMessage_ProvisioningType) mFdp.ConsumeIntegral()); } signedProvisioningMessage.set_oemcrypto_core_message( mFdp.ConsumeRandomLengthString(kMaxByte)); if (mFdp.ConsumeBool()) { signedProvisioningMessage.SerializeToString(&responseMessage); } else { responseMessage = mFdp.ConsumeRandomLengthString(kMaxByte); } } responseMessage = (mFdp.ConsumeBool() ? "\"signedResponse\": \"" : "") + (mFdp.ConsumeBool() ? Base64SafeEncode(responseMessage) : "") + (mFdp.ConsumeBool() ? "\"" : ""); } void CertificateProvisioningFuzzer::process() { FileSystem fileSystem; metrics::CryptoMetrics cryptoMetrics; CertificateProvisioning certificateProvisioning(&cryptoMetrics); certificateProvisioning.Init( mFdp.ConsumeRandomLengthString(kMaxByte) /* service_certificate */ ); while (mFdp.remaining_bytes()) { auto invokeCertificateProvisioningAPI = mFdp.PickValueInArray>( {[&]() { CdmProvisioningRequest request; std::string defaultUrl; certificateProvisioning.GetProvisioningRequest( &fileSystem, (RequestedSecurityLevel)mFdp.ConsumeBool() ? kLevelDefault : kLevel3, /* requested_security_level */ (CdmCertificateType)mFdp.ConsumeIntegralInRange( kMinCdmCertificateType, kMaxCdmCertificateType), /* cert_type */ mFdp.ConsumeRandomLengthString( kMaxByte), /* cert_authority */ mFdp.ConsumeRandomLengthString(kMaxByte), /* origin */ mFdp.ConsumeRandomLengthString(kMaxByte), /* spoid */ mFdp.ConsumeBool() ? &request : nullptr, &defaultUrl); }, [&]() { CdmProvisioningResponse responseMessage; createResponseMessage(responseMessage, mFdp); std::string cert; std::string wrappedKey; certificateProvisioning.HandleProvisioningResponse( &fileSystem, responseMessage, &cert, &wrappedKey); }, [&]() { std::string defaultUrl; CertificateProvisioning::GetProvisioningServerUrl( mFdp.ConsumeBool() ? &defaultUrl : nullptr); }}); invokeCertificateProvisioningAPI(); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { CertificateProvisioningFuzzer certificateProvisioningFuzzer(data, size); certificateProvisioningFuzzer.process(); return 0; }