• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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