1 /*
2  * Copyright 2022 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 "CryptoAsync"
19 
20 #include <log/log.h>
21 
22 #include "hidl/HidlSupport.h"
23 #include <media/stagefright/foundation/AMessage.h>
24 #include <media/stagefright/foundation/ABuffer.h>
25 #include <media/stagefright/foundation/ADebug.h>
26 
27 #include <media/MediaCodecBuffer.h>
28 #include <media/stagefright/MediaCodec.h>
29 #include <media/stagefright/CryptoAsync.h>
30 
31 namespace android {
32 
CryptoAsyncInfo(const std::unique_ptr<CodecCryptoInfo> & info)33 CryptoAsync::CryptoAsyncInfo::CryptoAsyncInfo(const std::unique_ptr<CodecCryptoInfo> &info) {
34     if (info == nullptr) {
35         return;
36     }
37     size_t key_len = (info->mKey != nullptr)? 16 : 0;
38     size_t iv_len = (info->mIv != nullptr)? 16 : 0;
39     mNumSubSamples = info->mNumSubSamples;
40     mMode = info->mMode;
41     mPattern = info->mPattern;
42     if (key_len > 0) {
43         mKeyBuffer = ABuffer::CreateAsCopy((void*)info->mKey, key_len);
44         mKey = (uint8_t*)(mKeyBuffer.get() != nullptr ? mKeyBuffer.get()->data() : nullptr);
45     }
46     if (iv_len > 0) {
47         mIvBuffer = ABuffer::CreateAsCopy((void*)info->mIv, iv_len);
48         mIv = (uint8_t*)(mIvBuffer.get() != nullptr ? mIvBuffer.get()->data() : nullptr);
49     }
50     mSubSamplesBuffer =
51         new ABuffer(sizeof(CryptoPlugin::SubSample) * mNumSubSamples);
52     if (mSubSamplesBuffer.get()) {
53         CryptoPlugin::SubSample * samples =
54            (CryptoPlugin::SubSample *)(mSubSamplesBuffer.get()->data());
55         for (int s = 0 ; s < mNumSubSamples ; s++) {
56             samples[s].mNumBytesOfClearData = info->mSubSamples[s].mNumBytesOfClearData;
57             samples[s].mNumBytesOfEncryptedData = info->mSubSamples[s].mNumBytesOfEncryptedData;
58         }
59         mSubSamples = (CryptoPlugin::SubSample *)mSubSamplesBuffer.get()->data();
60     }
61 }
62 
~CryptoAsync()63 CryptoAsync::~CryptoAsync() {
64 }
65 
decrypt(sp<AMessage> & msg)66 status_t CryptoAsync::decrypt(sp<AMessage> &msg) {
67     int32_t decryptAction;
68     CHECK(msg->findInt32("action", &decryptAction));
69     if (mCallback == nullptr) {
70        ALOGE("Crypto callback channel is not set");
71        return -ENOSYS;
72     }
73     bool shouldPost = false;
74     Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
75     if (mState != kCryptoAsyncActive) {
76        ALOGE("Cannot decrypt in errored state");
77        return -ENOSYS;
78     }
79     shouldPost = pendingBuffers->size() == 0 ? true : false;
80     pendingBuffers->push_back(std::move(msg));
81     if (shouldPost) {
82        sp<AMessage> decryptMsg = new AMessage(kWhatDecrypt, this);
83        decryptMsg->post();
84     }
85     return OK;
86 }
87 
stop(std::list<sp<AMessage>> * const buffers)88 void CryptoAsync::stop(std::list<sp<AMessage>> * const buffers) {
89     sp<AMessage>  stopMsg = new AMessage(kWhatStop, this);
90     stopMsg->setPointer("remaining", static_cast<void*>(buffers));
91     sp<AMessage> response;
92     status_t err = stopMsg->postAndAwaitResponse(&response);
93     if (err == OK && response != NULL) {
94         CHECK(response->findInt32("err", &err));
95     } else {
96         ALOGE("Error handling stop in CryptoAsync");
97         //TODO: handle the error here.
98     }
99 }
100 
decryptAndQueue(sp<AMessage> & msg)101 status_t CryptoAsync::decryptAndQueue(sp<AMessage> & msg) {
102     std::shared_ptr<BufferChannelBase> channel = mBufferChannel.lock();
103     status_t err = OK;
104     sp<RefBase> obj;
105     size_t numSubSamples = 0;
106     int32_t secure = 0;
107     CryptoPlugin::Mode mode;
108     CryptoPlugin::Pattern pattern;
109     sp<ABuffer> keyBuffer;
110     sp<ABuffer> ivBuffer;
111     sp<ABuffer> subSamplesBuffer;
112     AString errorDetailMsg;
113     msg->findObject("buffer", &obj);
114     msg->findInt32("secure", &secure);
115     sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
116     if (buffer->meta()->findObject("cryptoInfos", &obj)) {
117         err = channel->queueSecureInputBuffers(buffer, secure, &errorDetailMsg);
118     } else {
119         msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks);
120         msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks);
121         msg->findBuffer("key", &keyBuffer);
122         msg->findBuffer("iv", &ivBuffer);
123         msg->findBuffer("subSamples", &subSamplesBuffer);
124         msg->findSize("numSubSamples", &numSubSamples);
125         msg->findInt32("mode", (int32_t*)&mode);
126         const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr;
127         const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr;
128         const CryptoPlugin::SubSample * subSamples =
129            (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data());
130         err = channel->queueSecureInputBuffer(buffer, secure, key, iv, mode,
131             pattern, subSamples, numSubSamples, &errorDetailMsg);
132     }
133     if (err != OK) {
134         std::list<sp<AMessage>> errorList;
135         msg->removeEntryByName("buffer");
136         msg->setInt32("err", err);
137         msg->setInt32("actionCode", ACTION_CODE_FATAL);
138         msg->setString("errorDetail", errorDetailMsg);
139         errorList.push_back(std::move(msg));
140         mCallback->onDecryptError(errorList);
141    }
142    return err;
143 }
144 
attachEncryptedBufferAndQueue(sp<AMessage> & msg)145 status_t CryptoAsync::attachEncryptedBufferAndQueue(sp<AMessage> & msg) {
146     std::shared_ptr<BufferChannelBase> channel = mBufferChannel.lock();
147     status_t err = OK;
148     sp<RefBase> obj;
149     sp<RefBase> mem_obj;
150     sp<hardware::HidlMemory> memory;
151     size_t numSubSamples = 0;
152     int32_t secure = 0;
153     size_t offset;
154     size_t size;
155     CryptoPlugin::Mode mode;
156     CryptoPlugin::Pattern pattern;
157     sp<ABuffer> keyBuffer;
158     sp<ABuffer> ivBuffer;
159     sp<ABuffer> subSamplesBuffer;
160     msg->findInt32("encryptBlocks", (int32_t*)&pattern.mEncryptBlocks);
161     msg->findInt32("skipBlocks", (int32_t*)&pattern.mSkipBlocks);
162     msg->findBuffer("key", &keyBuffer);
163     msg->findBuffer("iv", &ivBuffer);
164     msg->findBuffer("subSamples", &subSamplesBuffer);
165     msg->findInt32("secure", &secure);
166     msg->findSize("numSubSamples", &numSubSamples);
167     msg->findObject("buffer", &obj);
168     msg->findInt32("mode", (int32_t*)&mode);
169     CHECK(msg->findObject("memory", &mem_obj));
170     CHECK(msg->findSize("offset", (size_t*)&offset));
171     AString errorDetailMsg;
172     // get key info
173     const uint8_t * key = keyBuffer.get() != nullptr ? keyBuffer.get()->data() : nullptr;
174     // get iv info
175     const uint8_t * iv = ivBuffer.get() != nullptr ? ivBuffer.get()->data() : nullptr;
176 
177     const CryptoPlugin::SubSample * subSamples =
178      (CryptoPlugin::SubSample *)(subSamplesBuffer.get()->data());
179 
180     // get MediaCodecBuffer
181     sp<MediaCodecBuffer> buffer = static_cast<MediaCodecBuffer *>(obj.get());
182 
183     // get HidlMemory
184     memory = static_cast<MediaCodec::WrapperObject<sp<hardware::HidlMemory>> *>
185         (mem_obj.get())->value;
186 
187     // attach buffer
188     err = channel->attachEncryptedBuffer(
189         memory, secure, key, iv, mode, pattern,
190         offset, subSamples, numSubSamples, buffer, &errorDetailMsg);
191 
192     // a generic error
193     auto handleError = [this, &err, &msg]() {
194         std::list<sp<AMessage>> errorList;
195         msg->removeEntryByName("buffer");
196         msg->setInt32("err", err);
197         msg->setInt32("actionCode", ACTION_CODE_FATAL);
198         errorList.push_back(std::move(msg));
199         mCallback->onDecryptError(errorList);
200     };
201     if (err != OK) {
202         handleError();
203         return err;
204      }
205      offset = buffer->offset();
206      size = buffer->size();
207 
208     if (offset + size > buffer->capacity()) {
209         err = -ENOSYS;
210         handleError();
211         return err;
212     }
213     buffer->setRange(offset, size);
214     err = channel->queueInputBuffer(buffer);
215     if (err != OK) {
216         handleError();
217         return err;
218     }
219    return err;
220 }
221 
onMessageReceived(const sp<AMessage> & msg)222 void CryptoAsync::onMessageReceived(const sp<AMessage> & msg) {
223     status_t err = OK;
224     auto getCurrentAndNextTask =
225         [this](sp<AMessage> * const  current, uint32_t & nextTask) -> status_t {
226         sp<AMessage> obj;
227         Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
228         if ((pendingBuffers->size() == 0) || (mState != kCryptoAsyncActive)) {
229            return -ENOMSG;
230         }
231         *current = std::move(*(pendingBuffers->begin()));
232         pendingBuffers->pop_front();
233         //Try to see if we will be able to process next buffer
234         while((nextTask == kWhatDoNothing) && pendingBuffers->size() > 0)
235         {
236             sp<AMessage> & nextBuffer = pendingBuffers->front();
237             if (nextBuffer == nullptr) {
238                 pendingBuffers->pop_front();
239                 continue;
240             }
241             nextTask = kWhatDecrypt;
242         }
243         return OK;
244     };
245     switch(msg->what()) {
246         case kWhatDecrypt:
247         {
248             sp<AMessage> thisMsg;
249             uint32_t nextTask = kWhatDoNothing;
250             if(OK != getCurrentAndNextTask(&thisMsg, nextTask)) {
251                 return;
252             }
253             if (thisMsg != nullptr) {
254                 int32_t action;
255                 err = OK;
256                 CHECK(thisMsg->findInt32("action", &action));
257                 switch(action) {
258                     case kActionDecrypt:
259                     {
260                         err = decryptAndQueue(thisMsg);
261                         break;
262                     }
263 
264                     case kActionAttachEncryptedBuffer:
265                     {
266                         err = attachEncryptedBufferAndQueue(thisMsg);
267                         break;
268                     }
269 
270                     default:
271                     {
272                         ALOGE("Unrecognized action in decrypt");
273                     }
274                 }
275                 if (err != OK) {
276                     Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
277                     mState = kCryptoAsyncError;
278                 }
279             }
280             // we won't take  next buffers if buffer caused
281             // an error. We want the caller to deal with the error first
282             // Expected behahiour is that the caller acknowledge the error
283             // with a call to stop() which clear the queues.
284             // Then move forward with processing of next set of buffers.
285             if (mState == kCryptoAsyncActive && nextTask != kWhatDoNothing) {
286                 sp<AMessage> nextMsg = new AMessage(nextTask,this);
287                 nextMsg->post();
288             }
289             break;
290         }
291 
292         case kWhatStop:
293         {
294             typedef std::list<sp<AMessage>> ReturnListType;
295             ReturnListType * returnList = nullptr;
296             sp<AReplyToken> replyID;
297             CHECK(msg->senderAwaitsResponse(&replyID));
298             sp<AMessage> response = new AMessage;
299             msg->findPointer("remaining", (void**)(&returnList));
300             Mutexed<std::list<sp<AMessage>>>::Locked pendingBuffers(mPendingBuffers);
301             if (returnList) {
302                 returnList->clear();
303                 returnList->splice(returnList->end(), std::move(*pendingBuffers));
304             }
305             pendingBuffers->clear();
306             mState = kCryptoAsyncActive;
307             response->setInt32("err", OK);
308             response->postReply(replyID);
309 
310             break;
311         }
312 
313         default:
314         {
315             status_t err = OK;
316             //TODO: do something with error here.
317             (void)err;
318             break;
319         }
320     }
321 }
322 
323 }  // namespace android
324