diff --git a/libwvdrmengine/cdm/core/include/certificate_provisioning.h b/libwvdrmengine/cdm/core/include/certificate_provisioning.h index 05c0cad5..8189958b 100644 --- a/libwvdrmengine/cdm/core/include/certificate_provisioning.h +++ b/libwvdrmengine/cdm/core/include/certificate_provisioning.h @@ -82,12 +82,18 @@ class CertificateProvisioning { const std::string& origin, const std::string& spoid, CdmProvisioningRequest* request, std::string* default_url); CdmResponseType GetProvisioning40RequestInternal( - wvutil::FileSystem* file_system, CdmProvisioningRequest* request, + wvutil::FileSystem* file_system, const std::string& origin, + const std::string& spoid, CdmProvisioningRequest* request, std::string* default_url); CdmResponseType FillEncryptedClientId( const std::string& client_token, video_widevine::ProvisioningRequest& provisioning_request, const ServiceCertificate& service_certificate); + CdmResponseType FillEncryptedClientIdWithAdditionalParameter( + const std::string& client_token, + const CdmAppParameterMap& additional_parameter, + video_widevine::ProvisioningRequest& provisioning_request, + const ServiceCertificate& service_certificate); CdmResponseType HandleProvisioning40Response( wvutil::FileSystem* file_system, const std::string& response_message); diff --git a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp index 2f2f2339..50ae4410 100644 --- a/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp +++ b/libwvdrmengine/cdm/core/src/certificate_provisioning.cpp @@ -57,6 +57,11 @@ const std::string kCpProductionServiceCertificate = wvutil::a2bs_hex( "8598ed5751b38694419242a875d9e00d5a5832933024b934859ec8be78adccbb" "1ec7127ae9afeef9c5cd2e15bd3048e8ce652f7d8c5d595a0323238c598a28"); +// Used in provisioning 4 client identification name value pairs. +const std::string kKeyAppParameterSpoid = "spoid"; +const std::string kKeyAppParameterProviderId = "provider_id"; +const std::string kKeyAppParameterStableId = "stable_id"; + // Retrieves |stored_oem_cert| from |file_handle|, and load the OEM private key // to |crypto_session|. Returns true if all operations are successful. bool RetrieveOemCertificateAndLoadPrivateKey(CryptoSession& crypto_session, @@ -212,7 +217,8 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal( if (crypto_session_->GetPreProvisionTokenType() == kClientTokenBootCertChain) { - return GetProvisioning40RequestInternal(file_system, request, default_url); + return GetProvisioning40RequestInternal(file_system, origin, spoid, request, + default_url); } // Prepare device provisioning request. @@ -304,7 +310,8 @@ CdmResponseType CertificateProvisioning::GetProvisioningRequestInternal( } CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal( - wvutil::FileSystem* file_system, CdmProvisioningRequest* request, + wvutil::FileSystem* file_system, const std::string& origin, + const std::string& spoid, CdmProvisioningRequest* request, std::string* default_url) { if (!crypto_session_->IsOpen()) { LOGE("Crypto session is not open"); @@ -340,7 +347,27 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal( } } - CdmResponseType status = NO_ERROR; + // Retrieve the Spoid, but put it to the client identification instead, so it + // is encrypted. + CdmAppParameterMap additional_parameter; + CdmResponseType status = + SetSpoidParameter(origin, spoid, &provisioning_request); + if (status != NO_ERROR) return status; + if (provisioning_request.has_spoid()) { + additional_parameter[kKeyAppParameterSpoid] = provisioning_request.spoid(); + provisioning_request.clear_spoid(); + } + if (provisioning_request.has_provider_id()) { + additional_parameter[kKeyAppParameterProviderId] = + provisioning_request.provider_id(); + provisioning_request.clear_provider_id(); + } + if (provisioning_request.has_stable_id()) { + additional_parameter[kKeyAppParameterStableId] = + provisioning_request.stable_id(); + provisioning_request.clear_stable_id(); + } + if (stored_oem_cert.empty()) { // This is the first stage provisioning. default_url->assign(kProvisioningServerUrl + @@ -354,16 +381,18 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal( // Since |stored_oem_cert| is empty, the client identification token will be // retrieved from OEMCrypto, which is the BCC in this case. - status = FillEncryptedClientId(stored_oem_cert, provisioning_request, - wv_service_cert); + status = FillEncryptedClientIdWithAdditionalParameter( + stored_oem_cert, additional_parameter, provisioning_request, + wv_service_cert); if (status != NO_ERROR) return status; } else { // This is the second stage provisioning. default_url->assign(kProvisioningServerUrl); // Since |stored_oem_cert| is non-empty, it will be used as the client // identification token. - status = FillEncryptedClientId(stored_oem_cert, provisioning_request, - *service_certificate_); + status = FillEncryptedClientIdWithAdditionalParameter( + stored_oem_cert, additional_parameter, provisioning_request, + *service_certificate_); if (status != NO_ERROR) return status; } @@ -408,6 +437,17 @@ CdmResponseType CertificateProvisioning::GetProvisioning40RequestInternal( CdmResponseType CertificateProvisioning::FillEncryptedClientId( const std::string& client_token, ProvisioningRequest& provisioning_request, const ServiceCertificate& service_certificate) { + CdmAppParameterMap app_parameter; + return FillEncryptedClientIdWithAdditionalParameter( + client_token, app_parameter, provisioning_request, service_certificate); +} + +CdmResponseType +CertificateProvisioning::FillEncryptedClientIdWithAdditionalParameter( + const std::string& client_token, + const CdmAppParameterMap& additional_parameter, + ProvisioningRequest& provisioning_request, + const ServiceCertificate& service_certificate) { if (!crypto_session_->IsOpen()) { return UNKNOWN_ERROR; } @@ -418,8 +458,7 @@ CdmResponseType CertificateProvisioning::FillEncryptedClientId( if (status != NO_ERROR) return status; video_widevine::ClientIdentification client_id; - CdmAppParameterMap app_parameter; - status = id.Prepare(app_parameter, kEmptyString, &client_id); + status = id.Prepare(additional_parameter, kEmptyString, &client_id); if (status != NO_ERROR) return status; if (!service_certificate.has_certificate()) {