1/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "hidl_ClearKeyPlugin"
19#include <utils/Log.h>
20
21#include <stdio.h>
22#include <inttypes.h>
23
24#include "DrmPlugin.h"
25#include "ClearKeyDrmProperties.h"
26#include "Session.h"
27#include "TypeConvert.h"
28
29namespace {
30const int kSecureStopIdStart = 100;
31const std::string kStreaming("Streaming");
32const std::string kOffline("Offline");
33const std::string kTrue("True");
34
35const std::string kQueryKeyLicenseType("LicenseType");
36    // Value: "Streaming" or "Offline"
37const std::string kQueryKeyPlayAllowed("PlayAllowed");
38    // Value: "True" or "False"
39const std::string kQueryKeyRenewAllowed("RenewAllowed");
40    // Value: "True" or "False"
41
42const int kSecureStopIdSize = 10;
43
44std::vector<uint8_t> uint32ToVector(uint32_t value) {
45    // 10 bytes to display max value 4294967295 + one byte null terminator
46    char buffer[kSecureStopIdSize];
47    memset(buffer, 0, kSecureStopIdSize);
48    snprintf(buffer, kSecureStopIdSize, "%" PRIu32, value);
49    return std::vector<uint8_t>(buffer, buffer + sizeof(buffer));
50}
51
52}; // unnamed namespace
53
54namespace android {
55namespace hardware {
56namespace drm {
57namespace V1_1 {
58namespace clearkey {
59
60DrmPlugin::DrmPlugin(SessionLibrary* sessionLibrary)
61        : mSessionLibrary(sessionLibrary),
62          mOpenSessionOkCount(0),
63          mCloseSessionOkCount(0),
64          mCloseSessionNotOpenedCount(0),
65          mNextSecureStopId(kSecureStopIdStart) {
66    mPlayPolicy.clear();
67    initProperties();
68    mSecureStops.clear();
69}
70
71void DrmPlugin::initProperties() {
72    mStringProperties.clear();
73    mStringProperties[kVendorKey] = kVendorValue;
74    mStringProperties[kVersionKey] = kVersionValue;
75    mStringProperties[kPluginDescriptionKey] = kPluginDescriptionValue;
76    mStringProperties[kAlgorithmsKey] = kAlgorithmsValue;
77    mStringProperties[kListenerTestSupportKey] = kListenerTestSupportValue;
78
79    std::vector<uint8_t> valueVector;
80    valueVector.clear();
81    valueVector.insert(valueVector.end(),
82            kTestDeviceIdData, kTestDeviceIdData + sizeof(kTestDeviceIdData) / sizeof(uint8_t));
83    mByteArrayProperties[kDeviceIdKey] = valueVector;
84
85    valueVector.clear();
86    valueVector.insert(valueVector.end(),
87            kMetricsData, kMetricsData + sizeof(kMetricsData) / sizeof(uint8_t));
88    mByteArrayProperties[kMetricsKey] = valueVector;
89}
90
91// The secure stop in ClearKey implementation is not installed securely.
92// This function merely creates a test environment for testing secure stops APIs.
93// The content in this secure stop is implementation dependent, the clearkey
94// secureStop does not serve as a reference implementation.
95void DrmPlugin::installSecureStop(const hidl_vec<uint8_t>& sessionId) {
96    ClearkeySecureStop clearkeySecureStop;
97    clearkeySecureStop.id = uint32ToVector(++mNextSecureStopId);
98    clearkeySecureStop.data.assign(sessionId.begin(), sessionId.end());
99
100    mSecureStops.insert(std::pair<std::vector<uint8_t>, ClearkeySecureStop>(
101            clearkeySecureStop.id, clearkeySecureStop));
102}
103
104Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
105    sp<Session> session = mSessionLibrary->createSession();
106    std::vector<uint8_t> sessionId = session->sessionId();
107
108    Status status = setSecurityLevel(sessionId, SecurityLevel::SW_SECURE_CRYPTO);
109    _hidl_cb(status, toHidlVec(sessionId));
110    mOpenSessionOkCount++;
111    return Void();
112}
113
114Return<void> DrmPlugin::openSession_1_1(SecurityLevel securityLevel,
115        openSession_1_1_cb _hidl_cb) {
116    sp<Session> session = mSessionLibrary->createSession();
117    std::vector<uint8_t> sessionId = session->sessionId();
118
119    Status status = setSecurityLevel(sessionId, securityLevel);
120    _hidl_cb(status, toHidlVec(sessionId));
121    mOpenSessionOkCount++;
122    return Void();
123}
124
125Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
126    if (sessionId.size() == 0) {
127        return Status::BAD_VALUE;
128    }
129
130    sp<Session> session = mSessionLibrary->findSession(toVector(sessionId));
131    if (session.get()) {
132        mCloseSessionOkCount++;
133        mSessionLibrary->destroySession(session);
134        return Status::OK;
135    }
136    mCloseSessionNotOpenedCount++;
137    return Status::ERROR_DRM_SESSION_NOT_OPENED;
138}
139
140Status DrmPlugin::getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
141        const hidl_vec<uint8_t>& initData,
142        const hidl_string& mimeType,
143        KeyType keyType,
144        const hidl_vec<KeyValue>& optionalParameters,
145        std::vector<uint8_t> *request,
146        KeyRequestType *keyRequestType,
147        std::string *defaultUrl) {
148        UNUSED(optionalParameters);
149
150    *defaultUrl = "";
151    *keyRequestType = KeyRequestType::UNKNOWN;
152    *request = std::vector<uint8_t>();
153
154    if (scope.size() == 0) {
155        return Status::BAD_VALUE;
156    }
157
158    if (keyType != KeyType::STREAMING) {
159        return Status::ERROR_DRM_CANNOT_HANDLE;
160    }
161
162    sp<Session> session = mSessionLibrary->findSession(toVector(scope));
163    if (!session.get()) {
164        return Status::ERROR_DRM_SESSION_NOT_OPENED;
165    }
166
167    Status status = session->getKeyRequest(initData, mimeType, request);
168    *keyRequestType = KeyRequestType::INITIAL;
169    return status;
170}
171
172Return<void> DrmPlugin::getKeyRequest(
173        const hidl_vec<uint8_t>& scope,
174        const hidl_vec<uint8_t>& initData,
175        const hidl_string& mimeType,
176        KeyType keyType,
177        const hidl_vec<KeyValue>& optionalParameters,
178        getKeyRequest_cb _hidl_cb) {
179    UNUSED(optionalParameters);
180
181    KeyRequestType keyRequestType = KeyRequestType::UNKNOWN;
182    std::string defaultUrl("");
183    std::vector<uint8_t> request;
184    Status status = getKeyRequestCommon(
185            scope, initData, mimeType, keyType, optionalParameters,
186            &request, &keyRequestType, &defaultUrl);
187
188    _hidl_cb(status, toHidlVec(request),
189            static_cast<drm::V1_0::KeyRequestType>(keyRequestType),
190            hidl_string(defaultUrl));
191    return Void();
192}
193
194Return<void> DrmPlugin::getKeyRequest_1_1(
195        const hidl_vec<uint8_t>& scope,
196        const hidl_vec<uint8_t>& initData,
197        const hidl_string& mimeType,
198        KeyType keyType,
199        const hidl_vec<KeyValue>& optionalParameters,
200        getKeyRequest_1_1_cb _hidl_cb) {
201    UNUSED(optionalParameters);
202
203    KeyRequestType keyRequestType = KeyRequestType::UNKNOWN;
204    std::string defaultUrl("");
205    std::vector<uint8_t> request;
206    Status status = getKeyRequestCommon(
207            scope, initData, mimeType, keyType, optionalParameters,
208            &request, &keyRequestType, &defaultUrl);
209
210    _hidl_cb(status, toHidlVec(request), keyRequestType, hidl_string(defaultUrl));
211    return Void();
212}
213
214void DrmPlugin::setPlayPolicy() {
215    mPlayPolicy.clear();
216
217    KeyValue policy;
218    policy.key = kQueryKeyLicenseType;
219    policy.value = kStreaming;
220    mPlayPolicy.push_back(policy);
221
222    policy.key = kQueryKeyPlayAllowed;
223    policy.value = kTrue;
224    mPlayPolicy.push_back(policy);
225
226    policy.key = kQueryKeyRenewAllowed;
227    mPlayPolicy.push_back(policy);
228}
229
230Return<void> DrmPlugin::provideKeyResponse(
231        const hidl_vec<uint8_t>& scope,
232        const hidl_vec<uint8_t>& response,
233        provideKeyResponse_cb _hidl_cb) {
234    if (scope.size() == 0 || response.size() == 0) {
235        // Returns empty keySetId
236        _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
237        return Void();
238    }
239
240    sp<Session> session = mSessionLibrary->findSession(toVector(scope));
241    if (!session.get()) {
242        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, hidl_vec<uint8_t>());
243        return Void();
244    }
245
246    setPlayPolicy();
247    std::vector<uint8_t> keySetId;
248    Status status = session->provideKeyResponse(response);
249    if (status == Status::OK) {
250        // This is for testing AMediaDrm_setOnEventListener only.
251        sendEvent(EventType::VENDOR_DEFINED, 0, scope);
252        keySetId.clear();
253    }
254
255    installSecureStop(scope);
256
257    // Returns status and empty keySetId
258    _hidl_cb(status, toHidlVec(keySetId));
259    return Void();
260}
261
262Return<void> DrmPlugin::getPropertyString(
263        const hidl_string& propertyName, getPropertyString_cb _hidl_cb) {
264    std::string name(propertyName.c_str());
265    std::string value;
266
267    if (name == kVendorKey) {
268        value = mStringProperties[kVendorKey];
269    } else if (name == kVersionKey) {
270        value = mStringProperties[kVersionKey];
271    } else if (name == kPluginDescriptionKey) {
272        value = mStringProperties[kPluginDescriptionKey];
273    } else if (name == kAlgorithmsKey) {
274        value = mStringProperties[kAlgorithmsKey];
275    } else if (name == kListenerTestSupportKey) {
276        value = mStringProperties[kListenerTestSupportKey];
277    } else {
278        ALOGE("App requested unknown string property %s", name.c_str());
279        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, "");
280        return Void();
281    }
282    _hidl_cb(Status::OK, value.c_str());
283    return Void();
284}
285
286Return<void> DrmPlugin::getPropertyByteArray(
287        const hidl_string& propertyName, getPropertyByteArray_cb _hidl_cb) {
288    std::map<std::string, std::vector<uint8_t> >::iterator itr =
289            mByteArrayProperties.find(std::string(propertyName.c_str()));
290    if (itr == mByteArrayProperties.end()) {
291        ALOGE("App requested unknown property: %s", propertyName.c_str());
292        _hidl_cb(Status::BAD_VALUE, std::vector<uint8_t>());
293        return Void();
294    }
295    _hidl_cb(Status::OK, itr->second);
296    return Void();
297
298}
299
300Return<Status> DrmPlugin::setPropertyString(
301    const hidl_string& name, const hidl_string& value) {
302    std::string immutableKeys;
303    immutableKeys.append(kAlgorithmsKey + ",");
304    immutableKeys.append(kPluginDescriptionKey + ",");
305    immutableKeys.append(kVendorKey + ",");
306    immutableKeys.append(kVersionKey + ",");
307
308    std::string key = std::string(name.c_str());
309    if (immutableKeys.find(key) != std::string::npos) {
310        ALOGD("Cannot set immutable property: %s", key.c_str());
311        return Status::BAD_VALUE;
312    }
313
314    std::map<std::string, std::string>::iterator itr =
315            mStringProperties.find(key);
316    if (itr == mStringProperties.end()) {
317        ALOGE("Cannot set undefined property string, key=%s", key.c_str());
318        return Status::BAD_VALUE;
319    }
320
321    mStringProperties[key] = std::string(value.c_str());
322    return Status::OK;
323}
324
325Return<Status> DrmPlugin::setPropertyByteArray(
326    const hidl_string& name, const hidl_vec<uint8_t>& value) {
327   UNUSED(value);
328   if (name == kDeviceIdKey) {
329      ALOGD("Cannot set immutable property: %s", name.c_str());
330      return Status::BAD_VALUE;
331   }
332
333   // Setting of undefined properties is not supported
334   ALOGE("Failed to set property byte array, key=%s", name.c_str());
335   return Status::ERROR_DRM_CANNOT_HANDLE;
336}
337
338Return<void> DrmPlugin::queryKeyStatus(
339        const hidl_vec<uint8_t>& sessionId,
340        queryKeyStatus_cb _hidl_cb) {
341
342    if (sessionId.size() == 0) {
343        // Returns empty key status KeyValue pair
344        _hidl_cb(Status::BAD_VALUE, hidl_vec<KeyValue>());
345        return Void();
346    }
347
348    std::vector<KeyValue> infoMapVec;
349    infoMapVec.clear();
350
351    KeyValue keyValuePair;
352    for (size_t i = 0; i < mPlayPolicy.size(); ++i) {
353        keyValuePair.key = mPlayPolicy[i].key;
354        keyValuePair.value = mPlayPolicy[i].value;
355        infoMapVec.push_back(keyValuePair);
356    }
357    _hidl_cb(Status::OK, toHidlVec(infoMapVec));
358    return Void();
359}
360
361Return<void> DrmPlugin::getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) {
362        uint32_t currentSessions = mSessionLibrary->numOpenSessions();
363        uint32_t maxSessions = 10;
364        _hidl_cb(Status::OK, currentSessions, maxSessions);
365        return Void();
366}
367
368Return<void> DrmPlugin::getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
369            getSecurityLevel_cb _hidl_cb) {
370    if (sessionId.size() == 0) {
371        _hidl_cb(Status::BAD_VALUE, SecurityLevel::UNKNOWN);
372        return Void();
373    }
374
375    std::vector<uint8_t> sid = toVector(sessionId);
376    sp<Session> session = mSessionLibrary->findSession(sid);
377    if (!session.get()) {
378        _hidl_cb(Status::ERROR_DRM_SESSION_NOT_OPENED, SecurityLevel::UNKNOWN);
379        return Void();
380    }
381
382    std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
383            mSecurityLevel.find(sid);
384    if (itr == mSecurityLevel.end()) {
385        ALOGE("Session id not found");
386        _hidl_cb(Status::ERROR_DRM_INVALID_STATE, SecurityLevel::UNKNOWN);
387        return Void();
388    }
389
390    _hidl_cb(Status::OK, itr->second);
391    return Void();
392}
393
394Return<Status> DrmPlugin::setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
395            SecurityLevel level) {
396    if (sessionId.size() == 0) {
397        ALOGE("Invalid empty session id");
398        return Status::BAD_VALUE;
399    }
400
401    if (level > SecurityLevel::SW_SECURE_CRYPTO) {
402        ALOGE("Cannot set security level > max");
403        return Status::ERROR_DRM_CANNOT_HANDLE;
404    }
405
406    std::vector<uint8_t> sid = toVector(sessionId);
407    sp<Session> session = mSessionLibrary->findSession(sid);
408    if (!session.get()) {
409        return Status::ERROR_DRM_SESSION_NOT_OPENED;
410    }
411
412    std::map<std::vector<uint8_t>, SecurityLevel>::iterator itr =
413            mSecurityLevel.find(sid);
414    if (itr != mSecurityLevel.end()) {
415        mSecurityLevel[sid] = level;
416    } else {
417        if (!mSecurityLevel.insert(
418                std::pair<std::vector<uint8_t>, SecurityLevel>(sid, level)).second) {
419            ALOGE("Failed to set security level");
420            return Status::ERROR_DRM_INVALID_STATE;
421        }
422    }
423    return Status::OK;
424}
425
426Return<void> DrmPlugin::getMetrics(getMetrics_cb _hidl_cb) {
427    // Set the open session count metric.
428    DrmMetricGroup::Attribute openSessionOkAttribute = {
429      "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
430    };
431    DrmMetricGroup::Value openSessionMetricValue = {
432      "count", DrmMetricGroup::ValueType::INT64_TYPE, mOpenSessionOkCount, 0.0, ""
433    };
434    DrmMetricGroup::Metric openSessionMetric = {
435      "open_session", { openSessionOkAttribute }, { openSessionMetricValue }
436    };
437
438    // Set the close session count metric.
439    DrmMetricGroup::Attribute closeSessionOkAttribute = {
440      "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, ""
441    };
442    DrmMetricGroup::Value closeSessionMetricValue = {
443      "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionOkCount, 0.0, ""
444    };
445    DrmMetricGroup::Metric closeSessionMetric = {
446      "close_session", { closeSessionOkAttribute }, { closeSessionMetricValue }
447    };
448
449    // Set the close session, not opened metric.
450    DrmMetricGroup::Attribute closeSessionNotOpenedAttribute = {
451      "status", DrmMetricGroup::ValueType::INT64_TYPE,
452      (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, ""
453    };
454    DrmMetricGroup::Value closeSessionNotOpenedMetricValue = {
455      "count", DrmMetricGroup::ValueType::INT64_TYPE, mCloseSessionNotOpenedCount, 0.0, ""
456    };
457    DrmMetricGroup::Metric closeSessionNotOpenedMetric = {
458      "close_session", { closeSessionNotOpenedAttribute }, { closeSessionNotOpenedMetricValue }
459    };
460
461    DrmMetricGroup metrics = { { openSessionMetric, closeSessionMetric,
462                                closeSessionNotOpenedMetric } };
463
464    _hidl_cb(Status::OK, hidl_vec<DrmMetricGroup>({metrics}));
465    return Void();
466}
467
468Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
469    std::vector<SecureStop> stops;
470    for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
471        ClearkeySecureStop clearkeyStop = itr->second;
472        std::vector<uint8_t> stopVec;
473        stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
474        stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
475
476        SecureStop stop;
477        stop.opaqueData = toHidlVec(stopVec);
478        stops.push_back(stop);
479    }
480    _hidl_cb(Status::OK, stops);
481    return Void();
482}
483
484Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
485        getSecureStop_cb _hidl_cb) {
486    SecureStop stop;
487    auto itr = mSecureStops.find(toVector(secureStopId));
488    if (itr != mSecureStops.end()) {
489        ClearkeySecureStop clearkeyStop = itr->second;
490        std::vector<uint8_t> stopVec;
491        stopVec.insert(stopVec.end(), clearkeyStop.id.begin(), clearkeyStop.id.end());
492        stopVec.insert(stopVec.end(), clearkeyStop.data.begin(), clearkeyStop.data.end());
493
494        stop.opaqueData = toHidlVec(stopVec);
495        _hidl_cb(Status::OK, stop);
496    } else {
497        _hidl_cb(Status::BAD_VALUE, stop);
498    }
499
500    return Void();
501}
502
503Return<Status> DrmPlugin::releaseSecureStop(const hidl_vec<uint8_t>& secureStopId) {
504    return removeSecureStop(secureStopId);
505}
506
507Return<Status> DrmPlugin::releaseAllSecureStops() {
508    return removeAllSecureStops();
509}
510
511Return<void> DrmPlugin::getSecureStopIds(getSecureStopIds_cb _hidl_cb) {
512    std::vector<SecureStopId> ids;
513    for (auto itr = mSecureStops.begin(); itr != mSecureStops.end(); ++itr) {
514        ids.push_back(itr->first);
515    }
516
517    _hidl_cb(Status::OK, toHidlVec(ids));
518    return Void();
519}
520
521Return<Status> DrmPlugin::releaseSecureStops(const SecureStopRelease& ssRelease) {
522    if (ssRelease.opaqueData.size() == 0) {
523        return Status::BAD_VALUE;
524    }
525
526    Status status = Status::OK;
527    std::vector<uint8_t> input = toVector(ssRelease.opaqueData);
528
529    // The format of opaqueData is shared between the server
530    // and the drm service. The clearkey implementation consists of:
531    //    count - number of secure stops
532    //    list of fixed length secure stops
533    size_t countBufferSize = sizeof(uint32_t);
534    uint32_t count = 0;
535    sscanf(reinterpret_cast<char*>(input.data()), "%04" PRIu32, &count);
536
537    // Avoid divide by 0 below.
538    if (count == 0) {
539        return Status::BAD_VALUE;
540    }
541
542    size_t secureStopSize = (input.size() - countBufferSize) / count;
543    uint8_t buffer[secureStopSize];
544    size_t offset = countBufferSize; // skip the count
545    for (size_t i = 0; i < count; ++i, offset += secureStopSize) {
546        memcpy(buffer, input.data() + offset, secureStopSize);
547        std::vector<uint8_t> id(buffer, buffer + kSecureStopIdSize);
548
549        status = removeSecureStop(toHidlVec(id));
550        if (Status::OK != status) break;
551    }
552
553    return status;
554}
555
556Return<Status> DrmPlugin::removeSecureStop(const hidl_vec<uint8_t>& secureStopId) {
557    if (1 != mSecureStops.erase(toVector(secureStopId))) {
558        return Status::BAD_VALUE;
559    }
560    return Status::OK;
561}
562
563Return<Status> DrmPlugin::removeAllSecureStops() {
564    mSecureStops.clear();
565    mNextSecureStopId = kSecureStopIdStart;
566    return Status::OK;
567}
568
569}  // namespace clearkey
570}  // namespace V1_1
571}  // namespace drm
572}  // namespace hardware
573}  // namespace android
574