1 /* 2 * Copyright (C) 2012 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 "ICrypto" 19 #include <binder/Parcel.h> 20 #include <binder/IMemory.h> 21 #include <cutils/log.h> 22 #include <media/stagefright/MediaErrors.h> 23 #include <media/stagefright/foundation/ADebug.h> 24 #include <media/stagefright/foundation/AString.h> 25 #include <mediadrm/ICrypto.h> 26 #include <utils/Log.h> 27 28 namespace android { 29 30 enum { 31 INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION, 32 IS_CRYPTO_SUPPORTED, 33 CREATE_PLUGIN, 34 DESTROY_PLUGIN, 35 REQUIRES_SECURE_COMPONENT, 36 DECRYPT, 37 NOTIFY_RESOLUTION, 38 SET_MEDIADRM_SESSION, 39 SET_HEAP, 40 UNSET_HEAP, 41 }; 42 43 struct BpCrypto : public BpInterface<ICrypto> { 44 explicit BpCrypto(const sp<IBinder> &impl) 45 : BpInterface<ICrypto>(impl) { 46 } 47 48 virtual status_t initCheck() const { 49 Parcel data, reply; 50 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 51 remote()->transact(INIT_CHECK, data, &reply); 52 53 return reply.readInt32(); 54 } 55 56 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) { 57 Parcel data, reply; 58 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 59 data.write(uuid, 16); 60 remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply); 61 62 return reply.readInt32() != 0; 63 } 64 65 virtual status_t createPlugin( 66 const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) { 67 Parcel data, reply; 68 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 69 data.write(uuid, 16); 70 data.writeInt32(opaqueSize); 71 72 if (opaqueSize > 0) { 73 data.write(opaqueData, opaqueSize); 74 } 75 76 remote()->transact(CREATE_PLUGIN, data, &reply); 77 78 return reply.readInt32(); 79 } 80 81 virtual status_t destroyPlugin() { 82 Parcel data, reply; 83 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 84 remote()->transact(DESTROY_PLUGIN, data, &reply); 85 86 return reply.readInt32(); 87 } 88 89 virtual bool requiresSecureDecoderComponent( 90 const char *mime) const { 91 Parcel data, reply; 92 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 93 data.writeCString(mime); 94 remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply); 95 96 return reply.readInt32() != 0; 97 } 98 99 virtual ssize_t decrypt(const uint8_t key[16], const uint8_t iv[16], 100 CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern, 101 const SourceBuffer &source, size_t offset, 102 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, 103 const DestinationBuffer &destination, AString *errorDetailMsg) { 104 Parcel data, reply; 105 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 106 data.writeInt32(mode); 107 data.writeInt32(pattern.mEncryptBlocks); 108 data.writeInt32(pattern.mSkipBlocks); 109 110 static const uint8_t kDummy[16] = { 0 }; 111 112 if (key == NULL) { 113 key = kDummy; 114 } 115 116 if (iv == NULL) { 117 iv = kDummy; 118 } 119 120 data.write(key, 16); 121 data.write(iv, 16); 122 123 size_t totalSize = 0; 124 for (size_t i = 0; i < numSubSamples; ++i) { 125 totalSize += subSamples[i].mNumBytesOfEncryptedData; 126 totalSize += subSamples[i].mNumBytesOfClearData; 127 } 128 129 data.writeInt32(totalSize); 130 data.writeStrongBinder(IInterface::asBinder(source.mSharedMemory)); 131 data.writeInt32(source.mHeapSeqNum); 132 data.writeInt32(offset); 133 134 data.writeInt32(numSubSamples); 135 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); 136 137 data.writeInt32((int32_t)destination.mType); 138 if (destination.mType == kDestinationTypeNativeHandle) { 139 if (destination.mHandle == NULL) { 140 return BAD_VALUE; 141 } 142 data.writeNativeHandle(destination.mHandle); 143 } else { 144 if (destination.mSharedMemory == NULL) { 145 return BAD_VALUE; 146 } 147 data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory)); 148 } 149 150 remote()->transact(DECRYPT, data, &reply); 151 152 ssize_t result = reply.readInt32(); 153 154 if (isCryptoError(result)) { 155 AString msg = reply.readCString(); 156 if (errorDetailMsg) { 157 *errorDetailMsg = msg; 158 } 159 } 160 161 return result; 162 } 163 164 virtual void notifyResolution( 165 uint32_t width, uint32_t height) { 166 Parcel data, reply; 167 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 168 data.writeInt32(width); 169 data.writeInt32(height); 170 remote()->transact(NOTIFY_RESOLUTION, data, &reply); 171 } 172 173 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) { 174 Parcel data, reply; 175 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 176 177 writeVector(data, sessionId); 178 remote()->transact(SET_MEDIADRM_SESSION, data, &reply); 179 180 return reply.readInt32(); 181 } 182 183 virtual int32_t setHeap(const sp<IMemoryHeap> &heap) { 184 Parcel data, reply; 185 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 186 data.writeStrongBinder(IInterface::asBinder(heap)); 187 status_t err = remote()->transact(SET_HEAP, data, &reply); 188 if (err != NO_ERROR) { 189 return -1; 190 } 191 int32_t seqNum; 192 if (reply.readInt32(&seqNum) != NO_ERROR) { 193 return -1; 194 } 195 return seqNum; 196 } 197 198 virtual void unsetHeap(int32_t seqNum) { 199 Parcel data, reply; 200 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 201 data.writeInt32(seqNum); 202 remote()->transact(UNSET_HEAP, data, &reply); 203 return; 204 } 205 206 207 private: 208 void readVector(Parcel &reply, Vector<uint8_t> &vector) const { 209 uint32_t size = reply.readInt32(); 210 vector.insertAt((size_t)0, size); 211 reply.read(vector.editArray(), size); 212 } 213 214 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const { 215 data.writeInt32(vector.size()); 216 data.write(vector.array(), vector.size()); 217 } 218 219 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto); 220 }; 221 222 IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto"); 223 224 //////////////////////////////////////////////////////////////////////////////// 225 226 void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const { 227 uint32_t size = data.readInt32(); 228 vector.insertAt((size_t)0, size); 229 data.read(vector.editArray(), size); 230 } 231 232 void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const { 233 reply->writeInt32(vector.size()); 234 reply->write(vector.array(), vector.size()); 235 } 236 237 status_t BnCrypto::onTransact( 238 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 239 switch (code) { 240 case INIT_CHECK: 241 { 242 CHECK_INTERFACE(ICrypto, data, reply); 243 reply->writeInt32(initCheck()); 244 245 return OK; 246 } 247 248 case IS_CRYPTO_SUPPORTED: 249 { 250 CHECK_INTERFACE(ICrypto, data, reply); 251 uint8_t uuid[16]; 252 data.read(uuid, sizeof(uuid)); 253 reply->writeInt32(isCryptoSchemeSupported(uuid)); 254 255 return OK; 256 } 257 258 case CREATE_PLUGIN: 259 { 260 CHECK_INTERFACE(ICrypto, data, reply); 261 262 uint8_t uuid[16]; 263 data.read(uuid, sizeof(uuid)); 264 265 size_t opaqueSize = data.readInt32(); 266 void *opaqueData = NULL; 267 268 const size_t kMaxOpaqueSize = 100 * 1024; 269 if (opaqueSize > kMaxOpaqueSize) { 270 return BAD_VALUE; 271 } 272 273 opaqueData = malloc(opaqueSize); 274 if (NULL == opaqueData) { 275 return NO_MEMORY; 276 } 277 278 data.read(opaqueData, opaqueSize); 279 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); 280 281 free(opaqueData); 282 opaqueData = NULL; 283 284 return OK; 285 } 286 287 case DESTROY_PLUGIN: 288 { 289 CHECK_INTERFACE(ICrypto, data, reply); 290 reply->writeInt32(destroyPlugin()); 291 292 return OK; 293 } 294 295 case REQUIRES_SECURE_COMPONENT: 296 { 297 CHECK_INTERFACE(ICrypto, data, reply); 298 299 const char *mime = data.readCString(); 300 if (mime == NULL) { 301 reply->writeInt32(BAD_VALUE); 302 } else { 303 reply->writeInt32(requiresSecureDecoderComponent(mime)); 304 } 305 306 return OK; 307 } 308 309 case DECRYPT: 310 { 311 CHECK_INTERFACE(ICrypto, data, reply); 312 313 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); 314 CryptoPlugin::Pattern pattern; 315 pattern.mEncryptBlocks = data.readInt32(); 316 pattern.mSkipBlocks = data.readInt32(); 317 318 uint8_t key[16]; 319 data.read(key, sizeof(key)); 320 321 uint8_t iv[16]; 322 data.read(iv, sizeof(iv)); 323 324 size_t totalSize = data.readInt32(); 325 326 SourceBuffer source; 327 328 source.mSharedMemory = 329 interface_cast<IMemory>(data.readStrongBinder()); 330 if (source.mSharedMemory == NULL) { 331 reply->writeInt32(BAD_VALUE); 332 return OK; 333 } 334 source.mHeapSeqNum = data.readInt32(); 335 336 int32_t offset = data.readInt32(); 337 338 int32_t numSubSamples = data.readInt32(); 339 if (numSubSamples < 0 || numSubSamples > 0xffff) { 340 reply->writeInt32(BAD_VALUE); 341 return OK; 342 } 343 344 std::unique_ptr<CryptoPlugin::SubSample[]> subSamples = 345 std::make_unique<CryptoPlugin::SubSample[]>(numSubSamples); 346 347 data.read(subSamples.get(), 348 sizeof(CryptoPlugin::SubSample) * numSubSamples); 349 350 DestinationBuffer destination; 351 destination.mType = (DestinationType)data.readInt32(); 352 if (destination.mType == kDestinationTypeNativeHandle) { 353 destination.mHandle = data.readNativeHandle(); 354 if (destination.mHandle == NULL) { 355 reply->writeInt32(BAD_VALUE); 356 return OK; 357 } 358 } else if (destination.mType == kDestinationTypeSharedMemory) { 359 destination.mSharedMemory = 360 interface_cast<IMemory>(data.readStrongBinder()); 361 if (destination.mSharedMemory == NULL) { 362 reply->writeInt32(BAD_VALUE); 363 return OK; 364 } 365 sp<IMemory> dest = destination.mSharedMemory; 366 if (totalSize > dest->size() || 367 (size_t)dest->offset() > dest->size() - totalSize) { 368 reply->writeInt32(BAD_VALUE); 369 android_errorWriteLog(0x534e4554, "71389378"); 370 return OK; 371 } 372 } else { 373 reply->writeInt32(BAD_VALUE); 374 android_errorWriteLog(0x534e4554, "70526702"); 375 return OK; 376 } 377 378 AString errorDetailMsg; 379 ssize_t result; 380 381 size_t sumSubsampleSizes = 0; 382 bool overflow = false; 383 for (int32_t i = 0; i < numSubSamples; ++i) { 384 CryptoPlugin::SubSample &ss = subSamples[i]; 385 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) { 386 sumSubsampleSizes += ss.mNumBytesOfEncryptedData; 387 } else { 388 overflow = true; 389 } 390 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) { 391 sumSubsampleSizes += ss.mNumBytesOfClearData; 392 } else { 393 overflow = true; 394 } 395 } 396 397 if (overflow || sumSubsampleSizes != totalSize) { 398 result = -EINVAL; 399 } else if (totalSize > source.mSharedMemory->size()) { 400 result = -EINVAL; 401 } else if ((size_t)offset > source.mSharedMemory->size() - totalSize) { 402 result = -EINVAL; 403 } else { 404 result = decrypt(key, iv, mode, pattern, source, offset, 405 subSamples.get(), numSubSamples, destination, &errorDetailMsg); 406 } 407 408 reply->writeInt32(result); 409 410 if (isCryptoError(result)) { 411 reply->writeCString(errorDetailMsg.c_str()); 412 } 413 414 if (destination.mType == kDestinationTypeNativeHandle) { 415 int err; 416 if ((err = native_handle_close(destination.mHandle)) < 0) { 417 ALOGW("secure buffer native_handle_close failed: %d", err); 418 } 419 if ((err = native_handle_delete(destination.mHandle)) < 0) { 420 ALOGW("secure buffer native_handle_delete failed: %d", err); 421 } 422 } 423 424 subSamples.reset(); 425 return OK; 426 } 427 428 case NOTIFY_RESOLUTION: 429 { 430 CHECK_INTERFACE(ICrypto, data, reply); 431 432 int32_t width = data.readInt32(); 433 int32_t height = data.readInt32(); 434 notifyResolution(width, height); 435 436 return OK; 437 } 438 439 case SET_MEDIADRM_SESSION: 440 { 441 CHECK_INTERFACE(IDrm, data, reply); 442 Vector<uint8_t> sessionId; 443 readVector(data, sessionId); 444 reply->writeInt32(setMediaDrmSession(sessionId)); 445 return OK; 446 } 447 448 case SET_HEAP: 449 { 450 CHECK_INTERFACE(ICrypto, data, reply); 451 sp<IMemoryHeap> heap = 452 interface_cast<IMemoryHeap>(data.readStrongBinder()); 453 reply->writeInt32(setHeap(heap)); 454 return OK; 455 } 456 457 case UNSET_HEAP: 458 { 459 CHECK_INTERFACE(ICrypto, data, reply); 460 int32_t seqNum = data.readInt32(); 461 unsetHeap(seqNum); 462 return OK; 463 } 464 465 default: 466 return BBinder::onTransact(code, data, reply, flags); 467 } 468 } 469 470 } // namespace android 471