1 /*
2 * Copyright (C) 2021 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 #define LOG_TAG "clearkey-CryptoPlugin"
17
18 #include <utils/Log.h>
19 #include <cerrno>
20 #include <cstring>
21
22 #include "CryptoPlugin.h"
23 #include "SessionLibrary.h"
24 #include "AidlUtils.h"
25
26 namespace aidl {
27 namespace android {
28 namespace hardware {
29 namespace drm {
30 namespace clearkey {
31
32 using ::aidl::android::hardware::drm::Status;
33
decrypt(const DecryptArgs & in_args,int32_t * _aidl_return)34 ::ndk::ScopedAStatus CryptoPlugin::decrypt(const DecryptArgs& in_args, int32_t* _aidl_return) {
35 const char* detailedError = "";
36
37 *_aidl_return = 0;
38 if (in_args.secure) {
39 detailedError = "secure decryption is not supported with ClearKey";
40 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
41 }
42
43 std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
44 if (mSharedBufferMap.find(in_args.source.bufferId) == mSharedBufferMap.end()) {
45 detailedError = "source decrypt buffer base not set";
46 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
47 }
48
49 const auto NON_SECURE = DestinationBuffer::Tag::nonsecureMemory;
50 if (in_args.destination.getTag() != NON_SECURE) {
51 detailedError = "destination type not supported";
52 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
53 }
54
55 const SharedBuffer& destBuffer = in_args.destination.get<NON_SECURE>();
56 if (mSharedBufferMap.find(destBuffer.bufferId) == mSharedBufferMap.end()) {
57 detailedError = "destination decrypt buffer base not set";
58 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
59 }
60
61 auto src = mSharedBufferMap[in_args.source.bufferId];
62 if (src->mBase == nullptr) {
63 detailedError = "source is a nullptr";
64 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
65 }
66
67 size_t totalSize = 0;
68 if (__builtin_add_overflow(in_args.source.offset, in_args.offset, &totalSize) ||
69 __builtin_add_overflow(totalSize, in_args.source.size, &totalSize) ||
70 totalSize > src->mSize) {
71 android_errorWriteLog(0x534e4554, "176496160");
72 detailedError = "invalid buffer size";
73 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
74 }
75
76 // destination type must be non-secure shared memory
77 auto dest = mSharedBufferMap[destBuffer.bufferId];
78 if (dest->mBase == nullptr) {
79 detailedError = "destination is a nullptr";
80 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
81 }
82
83 totalSize = 0;
84 if (__builtin_add_overflow(destBuffer.offset, destBuffer.size, &totalSize) ||
85 totalSize > dest->mSize) {
86 android_errorWriteLog(0x534e4554, "176444622");
87 detailedError = "invalid buffer size";
88 return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE, detailedError);
89 }
90
91 // Calculate the output buffer size and determine if any subsamples are
92 // encrypted.
93 uint8_t* srcPtr = src->mBase + in_args.source.offset + in_args.offset;
94 uint8_t* destPtr = dest->mBase + destBuffer.offset;
95 size_t destSize = 0;
96 size_t srcSize = 0;
97 bool haveEncryptedSubsamples = false;
98 for (size_t i = 0; i < in_args.subSamples.size(); i++) {
99 const SubSample& subSample = in_args.subSamples[i];
100 if (__builtin_add_overflow(destSize, subSample.numBytesOfClearData, &destSize) ||
101 __builtin_add_overflow(srcSize, subSample.numBytesOfClearData, &srcSize)) {
102 detailedError = "subsample clear size overflow";
103 return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE, detailedError);
104 }
105 if (__builtin_add_overflow(destSize, subSample.numBytesOfEncryptedData, &destSize) ||
106 __builtin_add_overflow(srcSize, subSample.numBytesOfEncryptedData, &srcSize)) {
107 detailedError = "subsample encrypted size overflow";
108 return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE, detailedError);
109 }
110 if (subSample.numBytesOfEncryptedData > 0) {
111 haveEncryptedSubsamples = true;
112 }
113 }
114
115 if (destSize > destBuffer.size || srcSize > in_args.source.size) {
116 detailedError = "subsample sum too large";
117 return toNdkScopedAStatus(Status::ERROR_DRM_FRAME_TOO_LARGE, detailedError);
118 }
119
120 if (in_args.mode == Mode::UNENCRYPTED) {
121 if (haveEncryptedSubsamples) {
122 detailedError = "Encrypted subsamples found in allegedly unencrypted data.";
123 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
124 }
125
126 size_t offset = 0;
127 for (size_t i = 0; i < in_args.subSamples.size(); ++i) {
128 const SubSample& subSample = in_args.subSamples[i];
129 if (subSample.numBytesOfClearData != 0) {
130 memcpy(reinterpret_cast<uint8_t*>(destPtr) + offset,
131 reinterpret_cast<const uint8_t*>(srcPtr) + offset,
132 subSample.numBytesOfClearData);
133 offset += subSample.numBytesOfClearData;
134 }
135 }
136
137 *_aidl_return = static_cast<ssize_t>(offset);
138 return toNdkScopedAStatus(Status::OK);
139 } else if (in_args.mode == Mode::AES_CTR) {
140 if (!mSession) return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE,
141 "session not found");
142 size_t bytesDecrypted{};
143 std::vector<int32_t> clearDataLengths;
144 std::vector<int32_t> encryptedDataLengths;
145 for (auto ss : in_args.subSamples) {
146 clearDataLengths.push_back(ss.numBytesOfClearData);
147 encryptedDataLengths.push_back(ss.numBytesOfEncryptedData);
148 }
149 if (in_args.keyId.size() != kBlockSize || in_args.iv.size() != kBlockSize) {
150 android_errorWriteLog(0x534e4554, "244569759");
151 detailedError = "invalid decrypt parameter size";
152 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
153 }
154
155 auto res =
156 mSession->decrypt(in_args.keyId.data(), in_args.iv.data(),
157 srcPtr, static_cast<uint8_t*>(destPtr),
158 clearDataLengths, encryptedDataLengths,
159 &bytesDecrypted);
160 if (res == clearkeydrm::OK) {
161 *_aidl_return = static_cast<ssize_t>(bytesDecrypted);
162 return toNdkScopedAStatus(Status::OK);
163 } else {
164 *_aidl_return = 0;
165 detailedError = "Decryption Error";
166 return toNdkScopedAStatus(static_cast<Status>(res), detailedError);
167 }
168 } else {
169 *_aidl_return = 0;
170 detailedError = "selected encryption mode is not supported by the ClearKey DRM Plugin";
171 return toNdkScopedAStatus(Status::ERROR_DRM_CANNOT_HANDLE, detailedError);
172 }
173 }
174
getLogMessages(std::vector<::aidl::android::hardware::drm::LogMessage> * _aidl_return)175 ::ndk::ScopedAStatus CryptoPlugin::getLogMessages(
176 std::vector<::aidl::android::hardware::drm::LogMessage>* _aidl_return) {
177 using std::chrono::duration_cast;
178 using std::chrono::milliseconds;
179 using std::chrono::system_clock;
180
181 auto timeMillis = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
182
183 std::vector<::aidl::android::hardware::drm::LogMessage> logs = {
184 {timeMillis, ::aidl::android::hardware::drm::LogPriority::ERROR,
185 std::string("Not implemented")}};
186 *_aidl_return = logs;
187 return toNdkScopedAStatus(Status::OK);
188 }
189
notifyResolution(int32_t in_width,int32_t in_height)190 ::ndk::ScopedAStatus CryptoPlugin::notifyResolution(int32_t in_width, int32_t in_height) {
191 UNUSED(in_width);
192 UNUSED(in_height);
193 return ::ndk::ScopedAStatus::ok();
194 }
195
requiresSecureDecoderComponent(const std::string & in_mime,bool * _aidl_return)196 ::ndk::ScopedAStatus CryptoPlugin::requiresSecureDecoderComponent(const std::string& in_mime,
197 bool* _aidl_return) {
198 UNUSED(in_mime);
199 *_aidl_return = false;
200 return ::ndk::ScopedAStatus::ok();
201 }
202
setMediaDrmSession(const std::vector<uint8_t> & in_sessionId)203 ::ndk::ScopedAStatus CryptoPlugin::setMediaDrmSession(const std::vector<uint8_t>& in_sessionId) {
204 Status status = Status::OK;
205 if (!in_sessionId.size()) {
206 mSession = nullptr;
207 } else {
208 mSession = SessionLibrary::get()->findSession(in_sessionId);
209 if (!mSession.get()) {
210 status = Status::ERROR_DRM_SESSION_NOT_OPENED;
211 }
212 }
213 return toNdkScopedAStatus(status);
214 }
215
setSharedBufferBase(const SharedBuffer & in_base)216 ::ndk::ScopedAStatus CryptoPlugin::setSharedBufferBase(const SharedBuffer& in_base) {
217 std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
218 mSharedBufferMap[in_base.bufferId] = std::make_shared<SharedBufferBase>(in_base);
219 return ::ndk::ScopedAStatus::ok();
220 }
221
SharedBufferBase(const SharedBuffer & mem)222 SharedBufferBase::SharedBufferBase(const SharedBuffer& mem)
223 : mBase(nullptr),
224 mSize(mem.size) {
225 if (mem.handle.fds.empty()) {
226 return;
227 }
228 auto fd = mem.handle.fds[0].get();
229 auto addr = mmap(nullptr, mem.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
230 if (addr == MAP_FAILED) {
231 ALOGE("mmap err: fd %d; errno %s", fd, strerror(errno));
232 } else {
233 mBase = static_cast<uint8_t*>(addr);
234 }
235 }
236
~SharedBufferBase()237 SharedBufferBase::~SharedBufferBase() {
238 if (mBase && munmap(mBase, mSize)) {
239 ALOGE("munmap err: base %p; errno %s",
240 mBase, strerror(errno));
241 }
242 }
243 } // namespace clearkey
244 } // namespace drm
245 } // namespace hardware
246 } // namespace android
247 } // namespace aidl
248