1 /* 2 * Copyright (C) 2017 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 "CryptoHal" 19 #include <utils/Log.h> 20 21 #include <android/hardware/drm/1.0/types.h> 22 #include <android/hidl/manager/1.0/IServiceManager.h> 23 24 #include <binder/IMemory.h> 25 #include <hidlmemory/FrameworkUtils.h> 26 #include <media/hardware/CryptoAPI.h> 27 #include <media/stagefright/foundation/ADebug.h> 28 #include <media/stagefright/foundation/AString.h> 29 #include <media/stagefright/foundation/hexdump.h> 30 #include <media/stagefright/MediaErrors.h> 31 #include <mediadrm/CryptoHal.h> 32 33 34 using ::android::hardware::drm::V1_0::BufferType; 35 using ::android::hardware::drm::V1_0::DestinationBuffer; 36 using ::android::hardware::drm::V1_0::ICryptoFactory; 37 using ::android::hardware::drm::V1_0::ICryptoPlugin; 38 using ::android::hardware::drm::V1_0::Mode; 39 using ::android::hardware::drm::V1_0::Pattern; 40 using ::android::hardware::drm::V1_0::SharedBuffer; 41 using ::android::hardware::drm::V1_0::Status; 42 using ::android::hardware::drm::V1_0::SubSample; 43 using ::android::hardware::hidl_array; 44 using ::android::hardware::hidl_handle; 45 using ::android::hardware::hidl_memory; 46 using ::android::hardware::hidl_string; 47 using ::android::hardware::hidl_vec; 48 using ::android::hardware::Return; 49 using ::android::hardware::Void; 50 using ::android::hidl::manager::V1_0::IServiceManager; 51 using ::android::sp; 52 53 54 namespace android { 55 56 static status_t toStatusT(Status status) { 57 switch (status) { 58 case Status::OK: 59 return OK; 60 case Status::ERROR_DRM_NO_LICENSE: 61 return ERROR_DRM_NO_LICENSE; 62 case Status::ERROR_DRM_LICENSE_EXPIRED: 63 return ERROR_DRM_LICENSE_EXPIRED; 64 case Status::ERROR_DRM_RESOURCE_BUSY: 65 return ERROR_DRM_RESOURCE_BUSY; 66 case Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION: 67 return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION; 68 case Status::ERROR_DRM_SESSION_NOT_OPENED: 69 return ERROR_DRM_SESSION_NOT_OPENED; 70 case Status::ERROR_DRM_CANNOT_HANDLE: 71 return ERROR_DRM_CANNOT_HANDLE; 72 case Status::ERROR_DRM_DECRYPT: 73 return ERROR_DRM_DECRYPT; 74 default: 75 return UNKNOWN_ERROR; 76 } 77 } 78 79 80 static hidl_vec<uint8_t> toHidlVec(const Vector<uint8_t> &vector) { 81 hidl_vec<uint8_t> vec; 82 vec.setToExternal(const_cast<uint8_t *>(vector.array()), vector.size()); 83 return vec; 84 } 85 86 static hidl_vec<uint8_t> toHidlVec(const void *ptr, size_t size) { 87 hidl_vec<uint8_t> vec; 88 vec.resize(size); 89 memcpy(vec.data(), ptr, size); 90 return vec; 91 } 92 93 static hidl_array<uint8_t, 16> toHidlArray16(const uint8_t *ptr) { 94 if (!ptr) { 95 return hidl_array<uint8_t, 16>(); 96 } 97 return hidl_array<uint8_t, 16>(ptr); 98 } 99 100 101 static String8 toString8(hidl_string hString) { 102 return String8(hString.c_str()); 103 } 104 105 106 CryptoHal::CryptoHal() 107 : mFactories(makeCryptoFactories()), 108 mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT), 109 mNextBufferId(0), 110 mHeapSeqNum(0) { 111 } 112 113 CryptoHal::~CryptoHal() { 114 } 115 116 Vector<sp<ICryptoFactory>> CryptoHal::makeCryptoFactories() { 117 Vector<sp<ICryptoFactory>> factories; 118 119 auto manager = ::IServiceManager::getService(); 120 if (manager != NULL) { 121 manager->listByInterface(drm::V1_0::ICryptoFactory::descriptor, 122 [&factories](const hidl_vec<hidl_string> ®istered) { 123 for (const auto &instance : registered) { 124 auto factory = drm::V1_0::ICryptoFactory::getService(instance); 125 if (factory != NULL) { 126 ALOGD("found drm (at) 1.0 ICryptoFactory %s", instance.c_str()); 127 factories.push_back(factory); 128 } 129 } 130 } 131 ); 132 manager->listByInterface(drm::V1_1::ICryptoFactory::descriptor, 133 [&factories](const hidl_vec<hidl_string> ®istered) { 134 for (const auto &instance : registered) { 135 auto factory = drm::V1_1::ICryptoFactory::getService(instance); 136 if (factory != NULL) { 137 ALOGD("found drm (at) 1.1 ICryptoFactory %s", instance.c_str()); 138 factories.push_back(factory); 139 } 140 } 141 } 142 ); 143 } 144 145 if (factories.size() == 0) { 146 // must be in passthrough mode, load the default passthrough service 147 auto passthrough = ICryptoFactory::getService(); 148 if (passthrough != NULL) { 149 ALOGI("makeCryptoFactories: using default passthrough crypto instance"); 150 factories.push_back(passthrough); 151 } else { 152 ALOGE("Failed to find any crypto factories"); 153 } 154 } 155 return factories; 156 } 157 158 sp<ICryptoPlugin> CryptoHal::makeCryptoPlugin(const sp<ICryptoFactory>& factory, 159 const uint8_t uuid[16], const void *initData, size_t initDataSize) { 160 161 sp<ICryptoPlugin> plugin; 162 Return<void> hResult = factory->createPlugin(toHidlArray16(uuid), 163 toHidlVec(initData, initDataSize), 164 [&](Status status, const sp<ICryptoPlugin>& hPlugin) { 165 if (status != Status::OK) { 166 ALOGE("Failed to make crypto plugin"); 167 return; 168 } 169 plugin = hPlugin; 170 } 171 ); 172 return plugin; 173 } 174 175 176 status_t CryptoHal::initCheck() const { 177 return mInitCheck; 178 } 179 180 181 bool CryptoHal::isCryptoSchemeSupported(const uint8_t uuid[16]) { 182 Mutex::Autolock autoLock(mLock); 183 184 for (size_t i = 0; i < mFactories.size(); i++) { 185 if (mFactories[i]->isCryptoSchemeSupported(uuid)) { 186 return true; 187 } 188 } 189 return false; 190 } 191 192 status_t CryptoHal::createPlugin(const uint8_t uuid[16], const void *data, 193 size_t size) { 194 Mutex::Autolock autoLock(mLock); 195 196 for (size_t i = 0; i < mFactories.size(); i++) { 197 if (mFactories[i]->isCryptoSchemeSupported(uuid)) { 198 mPlugin = makeCryptoPlugin(mFactories[i], uuid, data, size); 199 } 200 } 201 202 if (mPlugin == NULL) { 203 mInitCheck = ERROR_UNSUPPORTED; 204 } else { 205 mInitCheck = OK; 206 } 207 208 return mInitCheck; 209 } 210 211 status_t CryptoHal::destroyPlugin() { 212 Mutex::Autolock autoLock(mLock); 213 214 if (mInitCheck != OK) { 215 return mInitCheck; 216 } 217 218 mPlugin.clear(); 219 return OK; 220 } 221 222 bool CryptoHal::requiresSecureDecoderComponent(const char *mime) const { 223 Mutex::Autolock autoLock(mLock); 224 225 if (mInitCheck != OK) { 226 return false; 227 } 228 229 Return<bool> hResult = mPlugin->requiresSecureDecoderComponent(hidl_string(mime)); 230 if (!hResult.isOk()) { 231 return false; 232 } 233 return hResult; 234 } 235 236 237 /** 238 * If the heap base isn't set, get the heap base from the IMemory 239 * and send it to the HAL so it can map a remote heap of the same 240 * size. Once the heap base is established, shared memory buffers 241 * are sent by providing an offset into the heap and a buffer size. 242 */ 243 int32_t CryptoHal::setHeapBase(const sp<IMemoryHeap>& heap) { 244 using ::android::hardware::fromHeap; 245 using ::android::hardware::HidlMemory; 246 247 if (heap == NULL) { 248 ALOGE("setHeapBase(): heap is NULL"); 249 return -1; 250 } 251 252 Mutex::Autolock autoLock(mLock); 253 254 int32_t seqNum = mHeapSeqNum++; 255 sp<HidlMemory> hidlMemory = fromHeap(heap); 256 mHeapBases.add(seqNum, HeapBase(mNextBufferId, heap->getSize())); 257 Return<void> hResult = mPlugin->setSharedBufferBase(*hidlMemory, mNextBufferId++); 258 ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed"); 259 return seqNum; 260 } 261 262 void CryptoHal::clearHeapBase(int32_t seqNum) { 263 Mutex::Autolock autoLock(mLock); 264 265 /* 266 * Clear the remote shared memory mapping by setting the shared 267 * buffer base to a null hidl_memory. 268 * 269 * TODO: Add a releaseSharedBuffer method in a future DRM HAL 270 * API version to make this explicit. 271 */ 272 ssize_t index = mHeapBases.indexOfKey(seqNum); 273 if (index >= 0) { 274 if (mPlugin != NULL) { 275 uint32_t bufferId = mHeapBases[index].getBufferId(); 276 Return<void> hResult = mPlugin->setSharedBufferBase(hidl_memory(), bufferId); 277 ALOGE_IF(!hResult.isOk(), "setSharedBufferBase(): remote call failed"); 278 } 279 mHeapBases.removeItem(seqNum); 280 } 281 } 282 283 status_t CryptoHal::toSharedBuffer(const sp<IMemory>& memory, int32_t seqNum, ::SharedBuffer* buffer) { 284 ssize_t offset; 285 size_t size; 286 287 if (memory == NULL && buffer == NULL) { 288 return UNEXPECTED_NULL; 289 } 290 291 sp<IMemoryHeap> heap = memory->getMemory(&offset, &size); 292 if (heap == NULL) { 293 return UNEXPECTED_NULL; 294 } 295 296 // memory must be in one of the heaps that have been set 297 if (mHeapBases.indexOfKey(seqNum) < 0) { 298 return UNKNOWN_ERROR; 299 } 300 301 // heap must be the same size as the one that was set in setHeapBase 302 if (mHeapBases.valueFor(seqNum).getSize() != heap->getSize()) { 303 android_errorWriteLog(0x534e4554, "76221123"); 304 return UNKNOWN_ERROR; 305 } 306 307 // memory must be within the address space of the heap 308 if (memory->pointer() != static_cast<uint8_t *>(heap->getBase()) + memory->offset() || 309 heap->getSize() < memory->offset() + memory->size() || 310 SIZE_MAX - memory->offset() < memory->size()) { 311 android_errorWriteLog(0x534e4554, "76221123"); 312 return UNKNOWN_ERROR; 313 } 314 315 buffer->bufferId = mHeapBases.valueFor(seqNum).getBufferId(); 316 buffer->offset = offset >= 0 ? offset : 0; 317 buffer->size = size; 318 return OK; 319 } 320 321 ssize_t CryptoHal::decrypt(const uint8_t keyId[16], const uint8_t iv[16], 322 CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern, 323 const ICrypto::SourceBuffer &source, size_t offset, 324 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, 325 const ICrypto::DestinationBuffer &destination, AString *errorDetailMsg) { 326 Mutex::Autolock autoLock(mLock); 327 328 if (mInitCheck != OK) { 329 return mInitCheck; 330 } 331 332 Mode hMode; 333 switch(mode) { 334 case CryptoPlugin::kMode_Unencrypted: 335 hMode = Mode::UNENCRYPTED ; 336 break; 337 case CryptoPlugin::kMode_AES_CTR: 338 hMode = Mode::AES_CTR; 339 break; 340 case CryptoPlugin::kMode_AES_WV: 341 hMode = Mode::AES_CBC_CTS; 342 break; 343 case CryptoPlugin::kMode_AES_CBC: 344 hMode = Mode::AES_CBC; 345 break; 346 default: 347 return UNKNOWN_ERROR; 348 } 349 350 Pattern hPattern; 351 hPattern.encryptBlocks = pattern.mEncryptBlocks; 352 hPattern.skipBlocks = pattern.mSkipBlocks; 353 354 std::vector<SubSample> stdSubSamples; 355 for (size_t i = 0; i < numSubSamples; i++) { 356 SubSample subSample; 357 subSample.numBytesOfClearData = subSamples[i].mNumBytesOfClearData; 358 subSample.numBytesOfEncryptedData = subSamples[i].mNumBytesOfEncryptedData; 359 stdSubSamples.push_back(subSample); 360 } 361 auto hSubSamples = hidl_vec<SubSample>(stdSubSamples); 362 363 int32_t heapSeqNum = source.mHeapSeqNum; 364 bool secure; 365 ::DestinationBuffer hDestination; 366 if (destination.mType == kDestinationTypeSharedMemory) { 367 hDestination.type = BufferType::SHARED_MEMORY; 368 status_t status = toSharedBuffer(destination.mSharedMemory, heapSeqNum, 369 &hDestination.nonsecureMemory); 370 if (status != OK) { 371 return status; 372 } 373 secure = false; 374 } else if (destination.mType == kDestinationTypeNativeHandle) { 375 hDestination.type = BufferType::NATIVE_HANDLE; 376 hDestination.secureMemory = hidl_handle(destination.mHandle); 377 secure = true; 378 } else { 379 android_errorWriteLog(0x534e4554, "70526702"); 380 return UNKNOWN_ERROR; 381 } 382 383 ::SharedBuffer hSource; 384 status_t status = toSharedBuffer(source.mSharedMemory, heapSeqNum, &hSource); 385 if (status != OK) { 386 return status; 387 } 388 389 status_t err = UNKNOWN_ERROR; 390 uint32_t bytesWritten = 0; 391 392 Return<void> hResult = mPlugin->decrypt(secure, toHidlArray16(keyId), toHidlArray16(iv), hMode, 393 hPattern, hSubSamples, hSource, offset, hDestination, 394 [&](Status status, uint32_t hBytesWritten, hidl_string hDetailedError) { 395 if (status == Status::OK) { 396 bytesWritten = hBytesWritten; 397 *errorDetailMsg = toString8(hDetailedError); 398 } 399 err = toStatusT(status); 400 } 401 ); 402 403 if (!hResult.isOk()) { 404 err = DEAD_OBJECT; 405 } 406 407 if (err == OK) { 408 return bytesWritten; 409 } 410 return err; 411 } 412 413 void CryptoHal::notifyResolution(uint32_t width, uint32_t height) { 414 Mutex::Autolock autoLock(mLock); 415 416 if (mInitCheck != OK) { 417 return; 418 } 419 420 mPlugin->notifyResolution(width, height); 421 } 422 423 status_t CryptoHal::setMediaDrmSession(const Vector<uint8_t> &sessionId) { 424 Mutex::Autolock autoLock(mLock); 425 426 if (mInitCheck != OK) { 427 return mInitCheck; 428 } 429 430 return toStatusT(mPlugin->setMediaDrmSession(toHidlVec(sessionId))); 431 } 432 433 } // namespace android 434