/* * 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) : fdp_(data, size){}; void Process(); private: FuzzedDataProvider fdp_; }; void CreateResponseMessage(std::string &response_message, FuzzedDataProvider &fdp) { if (fdp.ConsumeBool()) { DrmCertificate drm_certificate; DrmCertificate_Algorithm algorithm = (DrmCertificate_Algorithm)fdp.ConsumeIntegralInRange( DrmCertificate_Algorithm:: DrmCertificate_Algorithm_UNKNOWN_ALGORITHM, DrmCertificate_Algorithm::DrmCertificate_Algorithm_ECC_SECP521R1); drm_certificate.set_algorithm(algorithm); std::string set_drm; if (fdp.ConsumeBool()) { drm_certificate.SerializeToString(&set_drm); } else { set_drm = fdp.ConsumeRandomLengthString(kMaxByte); } SignedDrmCertificate signed_drm_certificate; signed_drm_certificate.set_drm_certificate(set_drm); std::string set_device; if (fdp.ConsumeBool()) { signed_drm_certificate.SerializeToString(&set_device); } else { set_device = fdp.ConsumeRandomLengthString(kMaxByte); } ProvisioningResponse provisioning_response; ProvisioningResponse_ProvisioningStatus status = (ProvisioningResponse_ProvisioningStatus)fdp.ConsumeIntegralInRange< int32_t>( ProvisioningResponse_ProvisioningStatus:: ProvisioningResponse_ProvisioningStatus_NO_ERROR, ProvisioningResponse_ProvisioningStatus:: ProvisioningResponse_ProvisioningStatus_REVOKED_DEVICE_SERIES); provisioning_response.set_status(status); if (fdp.ConsumeBool()) { provisioning_response.set_device_certificate(set_device); } std::string set_message; if (fdp.ConsumeBool()) { provisioning_response.SerializeToString(&set_message); } else { set_message = fdp.ConsumeRandomLengthString(kMaxByte); } SignedProvisioningMessage signed_provisioning_message; if (fdp.ConsumeBool()) { signed_provisioning_message.set_message(set_message); } else { signed_provisioning_message.set_message( fdp.ConsumeRandomLengthString(kMaxByte)); } signed_provisioning_message.set_signature( fdp.ConsumeRandomLengthString(kMaxByte)); if (fdp.ConsumeBool()) { signed_provisioning_message.set_provisioning_type( (SignedProvisioningMessage_ProvisioningType)fdp.PickValueInArray( kProvisioningType)); } else { signed_provisioning_message.set_provisioning_type( (SignedProvisioningMessage_ProvisioningType) fdp.ConsumeIntegral()); } signed_provisioning_message.set_oemcrypto_core_message( fdp.ConsumeRandomLengthString(kMaxByte)); if (fdp.ConsumeBool()) { signed_provisioning_message.SerializeToString(&response_message); } else { response_message = fdp.ConsumeRandomLengthString(kMaxByte); } } response_message = (fdp.ConsumeBool() ? "\"signedResponse\": \"" : "") + (fdp.ConsumeBool() ? Base64SafeEncode(response_message) : "") + (fdp.ConsumeBool() ? "\"" : ""); } void CertificateProvisioningFuzzer::Process() { FileSystem file_system; metrics::CryptoMetrics crypto_metrics; CertificateProvisioning certificateProvisioning(&crypto_metrics); certificateProvisioning.Init( fdp_.ConsumeRandomLengthString(kMaxByte) /* service_certificate */ ); while (fdp_.remaining_bytes()) { auto invokeCertificateProvisioningAPI = fdp_.PickValueInArray>( {[&]() { CdmProvisioningRequest request; std::string default_url; certificateProvisioning.GetProvisioningRequest( &file_system, (RequestedSecurityLevel)fdp_.ConsumeBool() ? kLevelDefault : kLevel3, /* requested_security_level */ (CdmCertificateType)fdp_.ConsumeIntegralInRange( kMinCdmCertificateType, kMaxCdmCertificateType), /* cert_type */ fdp_.ConsumeRandomLengthString( kMaxByte), /* cert_authority */ fdp_.ConsumeRandomLengthString(kMaxByte), /* origin */ fdp_.ConsumeRandomLengthString(kMaxByte), /* spoid */ fdp_.ConsumeBool() ? &request : nullptr, &default_url); }, [&]() { CdmProvisioningResponse response_message; CreateResponseMessage(response_message, fdp_); std::string cert; std::string wrapped_key; certificateProvisioning.HandleProvisioningResponse( &file_system, response_message, &cert, &wrapped_key); }, [&]() { std::string default_url; CertificateProvisioning::GetProvisioningServerUrl( fdp_.ConsumeBool() ? &default_url : nullptr); }}); invokeCertificateProvisioningAPI(); } } extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { CertificateProvisioningFuzzer certificate_provisioning_fuzzer(data, size); certificate_provisioning_fuzzer.Process(); return 0; }