//////////////////////////////////////////////////////////////////////////////// // Copyright 2016 Google LLC. // // This software is licensed under the terms defined in the Widevine Master // License Agreement. For a copy of this agreement, please contact // widevine-licensing@google.com. //////////////////////////////////////////////////////////////////////////////// #include "common/client_id_util.h" #include "glog/logging.h" #include "common/aes_cbc_util.h" #include "common/client_cert.h" #include "common/drm_service_certificate.h" #include "common/error_space.h" #include "common/keybox_client_cert.h" #include "protos/public/drm_certificate.pb.h" #include "protos/public/errors.pb.h" #include "protos/public/signed_drm_certificate.pb.h" namespace widevine { const char kModDrmMake[] = "company_name"; const char kModDrmModel[] = "model_name"; void AddClientInfo(ClientIdentification* client_id, absl::string_view name, absl::string_view value) { ClientIdentification_NameValue* nv = client_id->add_client_info(); nv->set_name(std::string(name)); nv->set_value(std::string(value)); } bool SetClientInfo(ClientIdentification* client_id, absl::string_view name, absl::string_view value) { int n = client_id->client_info_size(); for (int i = 0; i < n; i++) { if (client_id->client_info(i).name() == name) { client_id->mutable_client_info(i)->set_value(std::string(value)); return true; } } AddClientInfo(client_id, name, value); return false; } std::string GetClientInfo(const ClientIdentification& client_id, absl::string_view name) { return GetClientInfo(client_id, name, std::string()); } std::string GetClientInfo(const ClientIdentification& client_id, absl::string_view name, const std::string& default_value) { for (const auto& nv : client_id.client_info()) { if (nv.name() == name) { return nv.value(); } } return default_value; } Status DecryptEncryptedClientIdentification( const EncryptedClientIdentification& encrypted_client_id, ClientIdentification* client_id) { return DrmServiceCertificate::DecryptClientIdentification(encrypted_client_id, client_id); } Status DecryptEncryptedClientIdentification( const EncryptedClientIdentification& encrypted_client_id, const std::string& privacy_key, ClientIdentification* client_id) { DCHECK(client_id); if (!encrypted_client_id.has_encrypted_client_id() || encrypted_client_id.encrypted_client_id().empty()) { return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION, "missing-encrypted-client-id"); } if (!encrypted_client_id.has_encrypted_client_id_iv() || encrypted_client_id.encrypted_client_id_iv().empty()) { return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION, "missing-encrypted-client-id-iv"); } std::string serialized_client_id(crypto_util::DecryptAesCbc( privacy_key, encrypted_client_id.encrypted_client_id_iv(), encrypted_client_id.encrypted_client_id())); if (serialized_client_id.empty()) { return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION, "client-id-decryption-failed"); } if (!client_id->ParseFromString(serialized_client_id)) { return Status(error_space, INVALID_ENCRYPTED_CLIENT_IDENTIFICATION, "client-id-parse-failed"); } return OkStatus(); } uint32_t GetSystemId(const ClientIdentification& client_id) { uint32_t system_id = 0; if (client_id.has_token()) { switch (client_id.type()) { case ClientIdentification::KEYBOX: system_id = KeyboxClientCert::GetSystemId(client_id.token()); break; case ClientIdentification::DRM_DEVICE_CERTIFICATE: { SignedDrmCertificate signed_drm_certificate; if (signed_drm_certificate.ParseFromString(client_id.token())) { DrmCertificate drm_certificate; if (drm_certificate.ParseFromString( signed_drm_certificate.drm_certificate())) { system_id = drm_certificate.system_id(); } } } break; default: break; } } return system_id; } } // namespace widevine