• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "v1_0/media_key_session_service.h"
17 #include "v1_0/media_key_system_types.h"
18 #include "v1_0/media_decrypt_module_service.h"
19 #include <hdf_base.h>
20 #include <hdf_log.h>
21 #include <unistd.h>
22 #include <dirent.h>
23 #include <errno.h>
24 #include "base64_utils.h"
25 #include "data_parser.h"
26 #include "securec.h"
27 
28 #define HDF_LOG_TAG media_key_session_service
29 
30 namespace OHOS {
31 namespace HDI {
32 namespace Drm {
33 namespace V1_0 {
MediaKeySessionService()34 MediaKeySessionService::MediaKeySessionService()
35 {
36     HDF_LOGI("%{public}s: start", __func__);
37     HDF_LOGI("%{public}s: end", __func__);
38 }
39 
MediaKeySessionService(ContentProtectionLevel level)40 MediaKeySessionService::MediaKeySessionService(ContentProtectionLevel level)
41 {
42     HDF_LOGI("%{public}s: start", __func__);
43     level_ = level;
44     HDF_LOGI("%{public}s: end", __func__);
45 }
46 
GenerateMediaKeyRequest(const MediaKeyRequestInfo & licenseRequestInfo,MediaKeyRequest & licenseRequest)47 int32_t MediaKeySessionService::GenerateMediaKeyRequest(const MediaKeyRequestInfo &licenseRequestInfo,
48     MediaKeyRequest &licenseRequest)
49 {
50     HDF_LOGI("%{public}s: start", __func__);
51     int32_t ret = HDF_SUCCESS;
52     licenseRequest.requestType = MEDIA_KEY_REQUEST_TYPE_INITIAL;
53     licenseRequest.defaultUrl = "http://default.com";
54     if (vdiCallbackObj != nullptr) {
55         std::string eventData = "KEY NEEDED";
56         std::vector<uint8_t> data(eventData.begin(), eventData.end());
57         vdiCallbackObj->SendEvent(EVENTTYPE_KEYREQUIRED, 0, data);
58     }
59     ret = session_->getKeyRequest(licenseRequestInfo.initData, licenseRequestInfo.mimeType,
60         licenseRequestInfo.mediaKeyType, licenseRequestInfo.optionalData, &licenseRequest.data);
61     HDF_LOGI("%{public}s: end", __func__);
62     return ret;
63 }
64 
ProcessMediaKeyResponse(const std::vector<uint8_t> & licenseResponse,std::vector<uint8_t> & licenseId)65 int32_t MediaKeySessionService::ProcessMediaKeyResponse(const std::vector<uint8_t> &licenseResponse,
66     std::vector<uint8_t> &licenseId)
67 {
68     HDF_LOGI("%{public}s: start", __func__);
69     licenseId.clear();
70     size_t commaPos = 0;
71     std::vector<std::vector<uint8_t>> keyIdAndValuePairs;
72     for (size_t i = 0; i < licenseResponse.size(); i++) {
73         if (licenseResponse[i] == ',') {
74             keyIdAndValuePairs.push_back(
75                 std::vector<uint8_t>(licenseResponse.begin() + commaPos, licenseResponse.begin() + i));
76             commaPos = i + 1;
77         }
78     }
79     keyIdAndValuePairs.push_back(std::vector<uint8_t>(licenseResponse.begin() + commaPos, licenseResponse.end()));
80     for (auto &keyIdAndValuePair : keyIdAndValuePairs) {
81         size_t colonPos = 0;
82         MediaKeyType mediaKeyType = MEDIA_KEY_TYPE_ONLINE;
83         if (keyIdAndValuePair[0] == '0') {
84             mediaKeyType = MEDIA_KEY_TYPE_ONLINE;
85         } else if (keyIdAndValuePair[0] == '1') {
86             mediaKeyType = MEDIA_KEY_TYPE_OFFLINE;
87         } else {
88             HDF_LOGE("%{public}s: without  '0/1'", __func__);
89             return HDF_ERR_INVALID_PARAM;
90         }
91         while (colonPos < keyIdAndValuePair.size() && keyIdAndValuePair[colonPos] != ':') {
92             ++colonPos;
93         }
94         if (colonPos == keyIdAndValuePair.size()) {
95             HDF_LOGE("%{public}s: without char ':'", __func__);
96             return HDF_ERR_INVALID_PARAM;
97         }
98         std::string keyIdBase64(keyIdAndValuePair.begin() + 1, keyIdAndValuePair.begin() + colonPos);
99         std::string keyValueBase64(keyIdAndValuePair.begin() + colonPos + 1, keyIdAndValuePair.end());
100         std::string keyIdString = Decode(keyIdBase64);
101         std::string keyValueString = Decode(keyValueBase64);
102 
103         std::vector<uint8_t> localKeyId(keyIdString.begin(), keyIdString.end());
104         std::vector<uint8_t> value(keyValueString.begin(), keyValueString.end());
105         licenseId.assign(localKeyId.begin(), localKeyId.end());
106         int32_t ret = session_->setKeyIdAndKeyValue(localKeyId, value);
107         if (ret != HDF_SUCCESS) {
108             HDF_LOGE("%{public}s: setKeyIdAndKeyValue faild", __func__);
109             return ret;
110         }
111         if (mediaKeyType == MEDIA_KEY_TYPE_OFFLINE) {
112             offlineKeyMutex_.lock();
113             ret = GetOfflineKeyFromFile();
114             if (ret != HDF_SUCCESS) {
115                 offlineKeyMutex_.unlock();
116                 HDF_LOGE("%{public}s: GetOfflineKeyFromFile faild", __func__);
117                 return ret;
118             }
119             offlineKeyIdAndKeyValueBase64_[keyIdBase64] = keyValueBase64;
120             ret = SetOfflineKeyToFile();
121             if (ret != HDF_SUCCESS) {
122                 offlineKeyMutex_.unlock();
123                 HDF_LOGE("%{public}s: SetOfflineKeyToFile  faild", __func__);
124                 return ret;
125             }
126             session_->keyIdStatusMap[licenseId] = OFFLINE_MEDIA_KEY_STATUS_USABLE;
127             offlineKeyMutex_.unlock();
128         }
129     }
130     if (vdiCallbackObj != nullptr) {
131         std::vector<uint8_t> licenseIdVec(licenseId.begin(), licenseId.end());
132         std::map<std::vector<uint8_t>, MediaKeySessionKeyStatus> keyStatus;
133         MediaKeySessionKeyStatus status = MEDIA_KEY_SESSION_KEY_STATUS_USABLE;
134         keyStatus.insert(std::make_pair(licenseIdVec, status));
135         vdiCallbackObj->SendEventKeyChange(keyStatus, true);
136     }
137 
138     HDF_LOGI("%{public}s: end", __func__);
139     return HDF_SUCCESS;
140 }
141 
CheckMediaKeyStatus(std::map<std::string,std::string> & mediaKeyStatus)142 int32_t MediaKeySessionService::CheckMediaKeyStatus(std::map<std::string, std::string>& mediaKeyStatus)
143 {
144     HDF_LOGI("%{public}s: start", __func__);
145     for (auto &keyValuePair : session_->keyIdAndKeyValue_) {
146         std::string name = std::string(keyValuePair.first.begin(), keyValuePair.first.end());
147         std::string value = "MediaKey is OK";
148         mediaKeyStatus.insert(std::make_pair(name, value));
149     }
150     HDF_LOGI("%{public}s: end", __func__);
151     return HDF_SUCCESS;
152 }
153 
ClearMediaKeys()154 int32_t MediaKeySessionService::ClearMediaKeys()
155 {
156     HDF_LOGI("%{public}s: start", __func__);
157     session_->keyIdAndKeyValue_.clear();
158     if (session_->keyIdAndKeyValue_.size() != 0) {
159         return HDF_FAILURE;
160     }
161     if (vdiCallbackObj != nullptr) {
162         std::string eventData = "KEY EXPIRED";
163         std::vector<uint8_t> data(eventData.begin(), eventData.end());
164         vdiCallbackObj->SendEvent(EVENTTYPE_KEYEXPIRED, 0, data);
165     }
166     HDF_LOGI("%{public}s: end", __func__);
167     return HDF_SUCCESS;
168 }
169 
GetOfflineReleaseRequest(const std::vector<uint8_t> & licenseId,std::vector<uint8_t> & releaseRequest)170 int32_t MediaKeySessionService::GetOfflineReleaseRequest(const std::vector<uint8_t> &licenseId,
171     std::vector<uint8_t> &releaseRequest)
172 {
173     HDF_LOGI("%{public}s: start", __func__);
174     releaseRequest.clear();
175     std::string requestJson;
176     std::vector<std::vector<uint8_t>> keyIds;
177     keyIds.push_back(licenseId);
178     if (generateRequest(MEDIA_KEY_TYPE_OFFLINE, keyIds, &requestJson) != HDF_SUCCESS) {
179         HDF_LOGE("%{public}s: generateRequest failed", __func__);
180         return HDF_ERR_INVALID_PARAM;
181     }
182     releaseRequest = std::vector<uint8_t>(requestJson.begin(), requestJson.end());
183     HDF_LOGI("%{public}s: end", __func__);
184     return HDF_SUCCESS;
185 }
186 
ProcessOfflineReleaseResponse(const std::vector<uint8_t> & licenseId,const std::vector<uint8_t> & response)187 int32_t MediaKeySessionService::ProcessOfflineReleaseResponse(const std::vector<uint8_t> &licenseId,
188     const std::vector<uint8_t> &response)
189 {
190     HDF_LOGI("%{public}s: start", __func__);
191     std::string releaseResponseData(response.begin(), response.end());
192     HDF_LOGI("%{public}s: response: %{public}s", __func__, releaseResponseData.c_str());
193     offlineKeyMutex_.lock();
194     int32_t ret = GetOfflineKeyFromFile();
195     if (ret != HDF_SUCCESS) {
196         offlineKeyMutex_.unlock();
197         return ret;
198     }
199     std::string keyIdString(licenseId.begin(), licenseId.end());
200     std::string keyIdBase64 = Encode(keyIdString);
201     auto it = offlineKeyIdAndKeyValueBase64_.find(keyIdBase64);
202     if (it != offlineKeyIdAndKeyValueBase64_.end()) {
203         session_->keyIdStatusMap[licenseId] = OFFLINE_MEDIA_KEY_STATUS_INACTIVE;
204         offlineKeyMutex_.unlock();
205         HDF_LOGI("%{public}s: end", __func__);
206         return HDF_SUCCESS;
207     }
208     offlineKeyMutex_.unlock();
209     HDF_LOGI("%{public}s: do not find offline license, keyId: %{public}s", __func__, licenseId.data());
210     HDF_LOGI("%{public}s: end", __func__);
211     return HDF_FAILURE;
212 }
213 
RestoreOfflineMediaKeys(const std::vector<uint8_t> & licenseId)214 int32_t MediaKeySessionService::RestoreOfflineMediaKeys(const std::vector<uint8_t> &licenseId)
215 {
216     HDF_LOGI("%{public}s: start", __func__);
217     if (session_ == nullptr) {
218         return HDF_FAILURE;
219     }
220     offlineKeyMutex_.lock();
221     int32_t ret = GetOfflineKeyFromFile();
222     if (ret != HDF_SUCCESS) {
223         offlineKeyMutex_.unlock();
224         return ret;
225     }
226     std::string keyIdString(licenseId.begin(), licenseId.end());
227     std::string keyIdBase64 = Encode(keyIdString);
228     keyIdBase64.erase(std::remove(keyIdBase64.begin(), keyIdBase64.end(), '\0'), keyIdBase64.end());
229     if (offlineKeyIdAndKeyValueBase64_.find(keyIdBase64) == offlineKeyIdAndKeyValueBase64_.end()) {
230         offlineKeyMutex_.unlock();
231         HDF_LOGE("%{public}s: do not find offline license, licenseId: %{public}s", __func__, licenseId.data());
232         return HDF_FAILURE;
233     }
234     session_->keyIdStatusMap[licenseId] = OFFLINE_MEDIA_KEY_STATUS_USABLE;
235     std::string keyValueString = Decode(offlineKeyIdAndKeyValueBase64_[keyIdBase64]);
236     std::vector<uint8_t> value(keyValueString.begin(), keyValueString.end());
237     offlineKeyIdAndKeyValueBase64_.clear();
238     offlineKeyMutex_.unlock();
239     if (vdiCallbackObj != nullptr) {
240         std::string eventData = "KEY EXPIRATION UPDATE";
241         std::vector<uint8_t> data(eventData.begin(), eventData.end());
242         vdiCallbackObj->SendEvent(EVENTTYPE_EXPIRATIONUPDATE, 0, data);
243     }
244     HDF_LOGI("%{public}s: end", __func__);
245     return ret;
246 }
247 
GetContentProtectionLevel(ContentProtectionLevel & level)248 int32_t MediaKeySessionService::GetContentProtectionLevel(ContentProtectionLevel &level)
249 {
250     HDF_LOGI("%{public}s: start", __func__);
251     level = level_;
252     HDF_LOGI("%{public}s: end", __func__);
253     return HDF_SUCCESS;
254 }
255 
RequiresSecureDecoderModule(const std::string & mimeType,bool & required)256 int32_t MediaKeySessionService::RequiresSecureDecoderModule(const std::string &mimeType, bool &required)
257 {
258     HDF_LOGI("%{public}s: start", __func__);
259     required = false;
260     HDF_LOGI("%{public}s: end", __func__);
261     return HDF_SUCCESS;
262 }
263 
SetCallback(const sptr<OHOS::HDI::Drm::V1_0::IMediaKeySessionCallback> & sessionCallback)264 int32_t MediaKeySessionService::SetCallback(const sptr<OHOS::HDI::Drm::V1_0::IMediaKeySessionCallback> &sessionCallback)
265 {
266     HDF_LOGI("%{public}s: start", __func__);
267     vdiCallbackObj = new (std::nothrow) MediaKeySessionCallbackService(sessionCallback);
268     if (vdiCallbackObj == nullptr) {
269         HDF_LOGE("new MediaKeySessionCallbackService() failed");
270         return HDF_ERR_MALLOC_FAIL;
271     }
272 
273     HDF_LOGI("%{public}s: end", __func__);
274     return HDF_SUCCESS;
275 }
276 
GetMediaDecryptModule(sptr<OHOS::HDI::Drm::V1_0::IMediaDecryptModule> & decryptModule)277 int32_t MediaKeySessionService::GetMediaDecryptModule(sptr<OHOS::HDI::Drm::V1_0::IMediaDecryptModule> &decryptModule)
278 {
279     HDF_LOGI("%{public}s: start", __func__);
280     if (decryptModule_ == nullptr) {
281         return HDF_FAILURE;
282     }
283     decryptModule = decryptModule_;
284     HDF_LOGI("%{public}s: end", __func__);
285     return HDF_SUCCESS;
286 }
287 
Init()288 int32_t MediaKeySessionService::Init()
289 {
290     HDF_LOGI("%{public}s: start", __func__);
291     session_ = new (std::nothrow) Session();
292     if (session_ == nullptr) {
293         return HDF_ERR_MALLOC_FAIL;
294     }
295     decryptModule_ = new (std::nothrow) MediaDecryptModuleService(session_);
296     if (decryptModule_ == nullptr) {
297         HDF_LOGE("new MediaDecryptModuleService() failed");
298         return HDF_ERR_MALLOC_FAIL;
299     }
300 
301     HDF_LOGI("%{public}s: end", __func__);
302     return HDF_SUCCESS;
303 }
304 
Destroy()305 int32_t MediaKeySessionService::Destroy()
306 {
307     HDF_LOGI("%{public}s: start", __func__);
308     offlineKeyMutex_.lock();
309     offlineKeyIdAndKeyValueBase64_.clear();
310     offlineKeyMutex_.unlock();
311     if (sessionCallback_ != nullptr) {
312         sessionCallback_->CloseKeySessionService(this);
313     }
314     sessionCallback_ = nullptr;
315     HDF_LOGI("%{public}s: end", __func__);
316     return HDF_SUCCESS;
317 }
318 
SetKeySessionServiceCallback(sptr<KeySessionServiceCallback> callback)319 int32_t MediaKeySessionService::SetKeySessionServiceCallback(sptr<KeySessionServiceCallback> callback)
320 {
321     HDF_LOGI("%{public}s: start", __func__);
322     if (callback == nullptr) {
323         HDF_LOGE("SetKeySessionServiceCallback callback is null");
324         return HDF_ERR_INVALID_PARAM;
325     }
326     sessionCallback_ = callback;
327     HDF_LOGI("%{public}s: end", __func__);
328     return HDF_SUCCESS;
329 }
330 
GetDecryptNumber()331 int32_t MediaKeySessionService::GetDecryptNumber()
332 {
333     HDF_LOGI("%{public}s: start", __func__);
334     HDF_LOGI("%{public}s: end", __func__);
335     return decryptModule_->GetDecryptNumber();
336 }
337 
GetDecryptMaxTimes(double time,std::vector<double> & topThreeTimes)338 void MediaKeySessionService::GetDecryptMaxTimes(double time, std::vector<double> &topThreeTimes)
339 {
340     if (topThreeTimes.size() < topThree) {
341         topThreeTimes.push_back(time);
342     } else {
343         auto minIt = std::min_element(topThreeTimes.begin(), topThreeTimes.end());
344         if (time > *minIt) {
345             *minIt = time;
346         }
347     }
348     if (topThreeTimes.size() > topThree) {
349         topThreeTimes.resize(topThree);
350     }
351 
352     std::sort(topThreeTimes.begin(), topThreeTimes.end(), std::greater<int>());
353 }
354 
GetDecryptTimes(std::vector<double> & topThreeTimes)355 int32_t MediaKeySessionService::GetDecryptTimes(std::vector<double> &topThreeTimes)
356 {
357     HDF_LOGI("%{public}s: start", __func__);
358     std::vector<double> times;
359     decryptModule_->GetDecryptTimes(times);
360     for (auto time : times) {
361         GetDecryptMaxTimes(time, topThreeTimes);
362     }
363     HDF_LOGI("%{public}s: end", __func__);
364     return HDF_SUCCESS;
365 }
366 
GetErrorDecryptNumber()367 int32_t MediaKeySessionService::GetErrorDecryptNumber()
368 {
369     HDF_LOGI("%{public}s: start", __func__);
370     HDF_LOGI("%{public}s: end", __func__);
371     return decryptModule_->GetErrorDecryptNumber();
372 }
373 
GetOfflineKeyFromFile()374 int32_t MediaKeySessionService::GetOfflineKeyFromFile()
375 {
376     HDF_LOGI("%{public}s: start", __func__);
377     FILE *offlineKeyFile = fopen(offlineKeyFileName, "r+");
378     if (offlineKeyFile == NULL) {
379         HDF_LOGE("%{public}s: open: \"%{public}s\" failed", __func__, offlineKeyFileName);
380         // file do not exist, is allright
381         return HDF_SUCCESS;
382     }
383     char keyIdBase64Chars[keyIdMaxLength];
384     char keyValueBase64Chars[keyIdMaxLength];
385     while (fscanf_s(offlineKeyFile, "%s %s", keyIdBase64Chars, sizeof(keyIdBase64Chars), keyValueBase64Chars,
386         sizeof(keyValueBase64Chars)) != EOF) {
387         std::string tempKeyIdBase64 = keyIdBase64Chars;
388         std::string tempKeyValueBase64 = keyValueBase64Chars;
389         tempKeyIdBase64.erase(std::remove(tempKeyIdBase64.begin(), tempKeyIdBase64.end(), '\0'), tempKeyIdBase64.end());
390         offlineKeyIdAndKeyValueBase64_[tempKeyIdBase64] = tempKeyValueBase64;
391     }
392     fclose(offlineKeyFile);
393     HDF_LOGI("%{public}s: end", __func__);
394     return HDF_SUCCESS;
395 }
396 
SetOfflineKeyToFile()397 int32_t MediaKeySessionService::SetOfflineKeyToFile()
398 {
399     HDF_LOGI("%{public}s: start", __func__);
400     FILE *offlineKeyFile = fopen(offlineKeyFileName, "w+");
401     if (offlineKeyFile == NULL) {
402         offlineKeyIdAndKeyValueBase64_.clear();
403         HDF_LOGE("%{public}s: create failed, ret: %{public}s", __func__, strerror(errno));
404         return HDF_FAILURE;
405     }
406     for (auto &keyIdValueBase64Pair : offlineKeyIdAndKeyValueBase64_) {
407         fprintf(offlineKeyFile, "%s %s\n", keyIdValueBase64Pair.first.c_str(), keyIdValueBase64Pair.second.c_str());
408         fflush(offlineKeyFile);
409     }
410     offlineKeyIdAndKeyValueBase64_.clear();
411     fclose(offlineKeyFile);
412     HDF_LOGI("%{public}s: end", __func__);
413     return HDF_SUCCESS;
414 }
415 } // V1_0
416 } // Drm
417 } // HDI
418 } // OHOS
419