diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp index 2553b5bc..a44a711e 100644 --- a/fuzzer/Android.bp +++ b/fuzzer/Android.bp @@ -122,3 +122,9 @@ cc_fuzz { srcs: ["cdm_engine_fuzzer.cpp"], defaults: ["libcdm_fuzzer_defaults"], } + +cc_fuzz { + name: "certificate_provisioning_fuzzer", + srcs: ["certificate_provisioning_fuzzer.cpp"], + defaults: ["libcdm_fuzzer_defaults"], +} diff --git a/fuzzer/README.md b/fuzzer/README.md index 9a6f74df..9ab1e445 100644 --- a/fuzzer/README.md +++ b/fuzzer/README.md @@ -11,6 +11,7 @@ + [crypto_session_fuzzer](#CryptoSession) + [buffer_reader_fuzzer](#BufferReader) + [cdm_engine_fuzzer](#CdmEngine) ++ [certificate_provisioning_fuzzer](#CertificateProvisioning) # Fuzzer for PolicyEngine @@ -259,3 +260,26 @@ CdmEngine supports the following parameters: $ adb sync data $ adb shell LD_LIBRARY_PATH=/vendor/lib64 /data/fuzz/arm64/cdm_engine_fuzzer/vendor/cdm_engine_fuzzer ``` +# Fuzzer for CertificateProvisioning + +CertificateProvisioning supports the following parameters: +1. service_certificate (parameter name: "service_certificate") +2. responseMessage (parameter name: "response") +3. type (parameter name: "type") + +| Parameter| Valid Values| Configured Value| +|------------- |-------------| ----- | +|`service_certificate`| `String` |Value obtained from FuzzedDataProvider| +|`responseMessage`| `String` |Value obtained from FuzzedDataProvider| +|`type`| 1. `ResponseType::kNoError`
2. `ResponseType::kResponseTypeBase`
3. `ResponseType::kObjectNotInitialized`
4. `ResponseType::kParameterNull`
5. `ResponseType::kBasePathUnavailable`
6. `ResponseType::kFileOpenFailed`
7. `ResponseType::kFileWriteError`
8. `ResponseType::kFileReadError`
9. `ResponseType::kInvalidFileSize`
10. `ResponseType::kHashComputationFailed`
11. `ResponseType::kFileHashMismatch`
12. `ResponseType::kFileParseError1`
13. `ResponseType::kFileParseError2`
14. `ResponseType::kUnknownLicenseState`
15. `ResponseType::kIncorrectFileType`
16. `ResponseType::kIncorrectFileVersion`
17. `ResponseType::kLicenseNotPresent` |Value obtained from FuzzedDataProvider| + +#### Steps to run +1. Build the fuzzer +``` + $ mm -j$(nproc) certificate_provisioning_fuzzer +``` +2. Run on device +``` + $ adb sync data + $ adb shell /data/fuzz/arm64/certificate_provisioning_fuzzer/vendor/certificate_provisioning_fuzzer +``` diff --git a/fuzzer/certificate_provisioning_fuzzer.cpp b/fuzzer/certificate_provisioning_fuzzer.cpp new file mode 100644 index 00000000..800752b4 --- /dev/null +++ b/fuzzer/certificate_provisioning_fuzzer.cpp @@ -0,0 +1,198 @@ +/* + * 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; +}