1 /*
2  * Copyright (C) 2016 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 "android.hardware.drm@1.0-impl"
17 
18 #include "CryptoPlugin.h"
19 #include "TypeConvert.h"
20 
21 #include <android/hidl/memory/1.0/IMemory.h>
22 #include <hidlmemory/mapping.h>
23 #include <log/log.h>
24 #include <media/stagefright/foundation/AString.h>
25 
26 using android::hardware::hidl_memory;
27 using android::hidl::memory::V1_0::IMemory;
28 
29 namespace android {
30 namespace hardware {
31 namespace drm {
32 namespace V1_0 {
33 namespace implementation {
34 
35     // Methods from ::android::hardware::drm::V1_0::ICryptoPlugin follow
requiresSecureDecoderComponent(const hidl_string & mime)36     Return<bool> CryptoPlugin::requiresSecureDecoderComponent(
37             const hidl_string& mime) {
38         return mLegacyPlugin->requiresSecureDecoderComponent(mime.c_str());
39     }
40 
notifyResolution(uint32_t width,uint32_t height)41     Return<void> CryptoPlugin::notifyResolution(uint32_t width,
42             uint32_t height) {
43         mLegacyPlugin->notifyResolution(width, height);
44         return Void();
45     }
46 
setMediaDrmSession(const hidl_vec<uint8_t> & sessionId)47     Return<Status> CryptoPlugin::setMediaDrmSession(
48             const hidl_vec<uint8_t>& sessionId) {
49         return toStatus(mLegacyPlugin->setMediaDrmSession(toVector(sessionId)));
50     }
51 
setSharedBufferBase(const hidl_memory & base,uint32_t bufferId)52     Return<void> CryptoPlugin::setSharedBufferBase(const hidl_memory& base,
53             uint32_t bufferId) {
54         sp<IMemory> hidlMemory = mapMemory(base);
55 
56         std::lock_guard<std::mutex> shared_buffer_lock(mSharedBufferLock);
57 
58         // allow mapMemory to return nullptr
59         mSharedBufferMap[bufferId] = hidlMemory;
60         return Void();
61     }
62 
decrypt(bool secure,const hidl_array<uint8_t,16> & keyId,const hidl_array<uint8_t,16> & iv,Mode mode,const Pattern & pattern,const hidl_vec<SubSample> & subSamples,const SharedBuffer & source,uint64_t offset,const DestinationBuffer & destination,decrypt_cb _hidl_cb)63     Return<void> CryptoPlugin::decrypt(bool secure,
64             const hidl_array<uint8_t, 16>& keyId,
65             const hidl_array<uint8_t, 16>& iv, Mode mode,
66             const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
67             const SharedBuffer& source, uint64_t offset,
68             const DestinationBuffer& destination,
69             decrypt_cb _hidl_cb) {
70         std::unique_lock<std::mutex> shared_buffer_lock(mSharedBufferLock);
71         if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) {
72             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set");
73             return Void();
74         }
75 
76         if (destination.type == BufferType::SHARED_MEMORY) {
77             const SharedBuffer& dest = destination.nonsecureMemory;
78             if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) {
79                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination decrypt buffer base not set");
80                 return Void();
81             }
82         }
83 
84         android::CryptoPlugin::Mode legacyMode = android::CryptoPlugin::kMode_Unencrypted;
85         switch(mode) {
86         case Mode::UNENCRYPTED:
87             legacyMode = android::CryptoPlugin::kMode_Unencrypted;
88             break;
89         case Mode::AES_CTR:
90             legacyMode = android::CryptoPlugin::kMode_AES_CTR;
91             break;
92         case Mode::AES_CBC_CTS:
93             legacyMode = android::CryptoPlugin::kMode_AES_WV;
94             break;
95         case Mode::AES_CBC:
96             legacyMode = android::CryptoPlugin::kMode_AES_CBC;
97             break;
98         }
99         android::CryptoPlugin::Pattern legacyPattern;
100         legacyPattern.mEncryptBlocks = pattern.encryptBlocks;
101         legacyPattern.mSkipBlocks = pattern.skipBlocks;
102 
103         std::unique_ptr<android::CryptoPlugin::SubSample[]> legacySubSamples =
104                 std::make_unique<android::CryptoPlugin::SubSample[]>(subSamples.size());
105 
106         size_t destSize = 0;
107         for (size_t i = 0; i < subSamples.size(); i++) {
108             uint32_t numBytesOfClearData = subSamples[i].numBytesOfClearData;
109             legacySubSamples[i].mNumBytesOfClearData = numBytesOfClearData;
110             uint32_t numBytesOfEncryptedData = subSamples[i].numBytesOfEncryptedData;
111             legacySubSamples[i].mNumBytesOfEncryptedData = numBytesOfEncryptedData;
112             if (__builtin_add_overflow(destSize, numBytesOfClearData, &destSize)) {
113                 _hidl_cb(Status::BAD_VALUE, 0, "subsample clear size overflow");
114                 return Void();
115             }
116             if (__builtin_add_overflow(destSize, numBytesOfEncryptedData, &destSize)) {
117                 _hidl_cb(Status::BAD_VALUE, 0, "subsample encrypted size overflow");
118                 return Void();
119             }
120         }
121 
122         AString detailMessage;
123         sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
124         if (sourceBase == nullptr) {
125             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
126             return Void();
127         }
128 
129         size_t totalSize = 0;
130         if (__builtin_add_overflow(source.offset, offset, &totalSize) ||
131             __builtin_add_overflow(totalSize, source.size, &totalSize) ||
132             totalSize > sourceBase->getSize()) {
133             android_errorWriteLog(0x534e4554, "176496160");
134             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
135             return Void();
136         }
137 
138         uint8_t *base = static_cast<uint8_t *>
139                 (static_cast<void *>(sourceBase->getPointer()));
140         void *srcPtr = static_cast<void *>(base + source.offset + offset);
141 
142         void *destPtr = NULL;
143         if (destination.type == BufferType::SHARED_MEMORY) {
144             const SharedBuffer& destBuffer = destination.nonsecureMemory;
145             sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
146             if (destBase == nullptr) {
147                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
148                 return Void();
149             }
150 
151             size_t totalSize = 0;
152             if (__builtin_add_overflow(destBuffer.offset, destBuffer.size, &totalSize) ||
153                 totalSize > destBase->getSize()) {
154                 android_errorWriteLog(0x534e4554, "176496353");
155                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
156                 return Void();
157             }
158 
159             if (destSize > destBuffer.size) {
160                 _hidl_cb(Status::BAD_VALUE, 0, "subsample sum too large");
161                 return Void();
162             }
163 
164             base = static_cast<uint8_t *>(static_cast<void *>(destBase->getPointer()));
165             destPtr = static_cast<void*>(base + destination.nonsecureMemory.offset);
166         } else if (destination.type == BufferType::NATIVE_HANDLE) {
167             if (!secure) {
168                 _hidl_cb(Status::BAD_VALUE, 0, "native handle destination must be secure");
169                 return Void();
170             }
171             native_handle_t *handle = const_cast<native_handle_t *>(
172                     destination.secureMemory.getNativeHandle());
173             destPtr = static_cast<void *>(handle);
174         } else {
175             _hidl_cb(Status::BAD_VALUE, 0, "invalid destination type");
176             return Void();
177         }
178 
179         // release mSharedBufferLock
180         shared_buffer_lock.unlock();
181 
182         ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
183                 legacyMode, legacyPattern, srcPtr, legacySubSamples.get(),
184                 subSamples.size(), destPtr, &detailMessage);
185 
186         uint32_t status;
187         uint32_t bytesWritten;
188 
189         if (result >= 0) {
190             status = android::OK;
191             bytesWritten = result;
192         } else {
193             status = result;
194             bytesWritten = 0;
195         }
196 
197         _hidl_cb(toStatus(status), bytesWritten, detailMessage.c_str());
198         return Void();
199     }
200 
201 } // namespace implementation
202 }  // namespace V1_0
203 }  // namespace drm
204 }  // namespace hardware
205 }  // namespace android
206