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_ClearKeyCryptoPlugin"
19#include <utils/Log.h>
20
21#include "CryptoPlugin.h"
22#include "SessionLibrary.h"
23#include "TypeConvert.h"
24
25#include <hidlmemory/mapping.h>
26
27namespace android {
28namespace hardware {
29namespace drm {
30namespace V1_1 {
31namespace clearkey {
32
33using ::android::hardware::drm::V1_0::BufferType;
34
35Return<void> CryptoPlugin::setSharedBufferBase(
36        const hidl_memory& base, uint32_t bufferId) {
37    sp<IMemory> hidlMemory = mapMemory(base);
38    ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr");
39
40    // allow mapMemory to return nullptr
41    mSharedBufferMap[bufferId] = hidlMemory;
42    return Void();
43}
44
45// Returns negative values for error code and positive values for the size of
46// decrypted data.  In theory, the output size can be larger than the input
47// size, but in practice this will never happen for AES-CTR.
48Return<void> CryptoPlugin::decrypt(
49        bool secure,
50        const hidl_array<uint8_t, KEY_ID_SIZE>& keyId,
51        const hidl_array<uint8_t, KEY_IV_SIZE>& iv,
52        Mode mode,
53        const Pattern& pattern,
54        const hidl_vec<SubSample>& subSamples,
55        const SharedBuffer& source,
56        uint64_t offset,
57        const DestinationBuffer& destination,
58        decrypt_cb _hidl_cb) {
59    UNUSED(pattern);
60
61    if (secure) {
62        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
63            "Secure decryption is not supported with ClearKey.");
64        return Void();
65    }
66
67    if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
68      _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
69               "source decrypt buffer base not set");
70      return Void();
71    }
72
73    if (destination.type == BufferType::SHARED_MEMORY) {
74      const SharedBuffer& dest = destination.nonsecureMemory;
75      if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
76        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
77                 "destination decrypt buffer base not set");
78        return Void();
79      }
80    }
81
82    sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
83    if (sourceBase == nullptr) {
84        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
85        return Void();
86    }
87
88    if (source.offset + offset + source.size > sourceBase->getSize()) {
89        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
90        return Void();
91    }
92
93    uint8_t *base = static_cast<uint8_t *>
94            (static_cast<void *>(sourceBase->getPointer()));
95    uint8_t* srcPtr = static_cast<uint8_t *>(base + source.offset + offset);
96    void* destPtr = NULL;
97    if (destination.type == BufferType::SHARED_MEMORY) {
98        const SharedBuffer& destBuffer = destination.nonsecureMemory;
99        sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
100        if (destBase == nullptr) {
101            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
102            return Void();
103        }
104
105        if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
106            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
107            return Void();
108        }
109        destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
110    } else if (destination.type == BufferType::NATIVE_HANDLE) {
111        native_handle_t *handle = const_cast<native_handle_t *>(
112        destination.secureMemory.getNativeHandle());
113        destPtr = static_cast<void *>(handle);
114    }
115
116    // Calculate the output buffer size and determine if any subsamples are
117    // encrypted.
118    size_t destSize = 0;
119    bool haveEncryptedSubsamples = false;
120    for (size_t i = 0; i < subSamples.size(); i++) {
121        const SubSample &subSample = subSamples[i];
122        destSize += subSample.numBytesOfClearData;
123        destSize += subSample.numBytesOfEncryptedData;
124        if (subSample.numBytesOfEncryptedData > 0) {
125        haveEncryptedSubsamples = true;
126        }
127    }
128
129    if (mode == Mode::UNENCRYPTED) {
130        if (haveEncryptedSubsamples) {
131            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
132                    "Encrypted subsamples found in allegedly unencrypted data.");
133            return Void();
134        }
135
136        size_t offset = 0;
137        for (size_t i = 0; i < subSamples.size(); ++i) {
138            const SubSample& subSample = subSamples[i];
139            if (subSample.numBytesOfClearData != 0) {
140                memcpy(reinterpret_cast<uint8_t*>(destPtr) + offset,
141                       reinterpret_cast<const uint8_t*>(srcPtr) + offset,
142                       subSample.numBytesOfClearData);
143                offset += subSample.numBytesOfClearData;
144            }
145        }
146
147        _hidl_cb(Status::OK, static_cast<ssize_t>(offset), "");
148        return Void();
149    } else if (mode == Mode::AES_CTR) {
150        size_t bytesDecrypted;
151        Status res = mSession->decrypt(keyId.data(), iv.data(), srcPtr,
152                static_cast<uint8_t*>(destPtr), toVector(subSamples), &bytesDecrypted);
153        if (res == Status::OK) {
154            _hidl_cb(Status::OK, static_cast<ssize_t>(bytesDecrypted), "");
155            return Void();
156        } else {
157            _hidl_cb(Status::ERROR_DRM_DECRYPT, static_cast<ssize_t>(res),
158                    "Decryption Error");
159            return Void();
160        }
161    } else {
162        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0,
163                "Selected encryption mode is not supported by the ClearKey DRM Plugin.");
164        return Void();
165    }
166}
167
168Return<Status> CryptoPlugin::setMediaDrmSession(
169        const hidl_vec<uint8_t>& sessionId) {
170    if (!sessionId.size()) {
171        mSession = nullptr;
172    } else {
173        mSession = SessionLibrary::get()->findSession(sessionId);
174        if (!mSession.get()) {
175            return Status::ERROR_DRM_SESSION_NOT_OPENED;
176        }
177    }
178    return Status::OK;
179}
180
181} // namespace clearkey
182} // namespace V1_1
183} // namespace drm
184} // namespace hardware
185} // namespace android
186