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