ICrypto.cpp revision d07c92742fc5801cab8e99801f591365986acbe9
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 <utils/Log.h> 20 21#include <binder/Parcel.h> 22#include <binder/IMemory.h> 23#include <media/ICrypto.h> 24#include <media/stagefright/MediaErrors.h> 25#include <media/stagefright/foundation/ADebug.h> 26#include <media/stagefright/foundation/AString.h> 27 28namespace android { 29 30enum { 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 43struct 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 sp<IMemory> &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)); 131 data.writeInt32(offset); 132 133 data.writeInt32(numSubSamples); 134 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); 135 136 data.writeInt32((int32_t)destination.mType); 137 if (destination.mType == kDestinationTypeNativeHandle) { 138 if (destination.mHandle == NULL) { 139 return BAD_VALUE; 140 } 141 data.writeNativeHandle(destination.mHandle); 142 } else { 143 if (destination.mSharedMemory == NULL) { 144 return BAD_VALUE; 145 } 146 data.writeStrongBinder(IInterface::asBinder(destination.mSharedMemory)); 147 } 148 149 remote()->transact(DECRYPT, data, &reply); 150 151 ssize_t result = reply.readInt32(); 152 153 if (isCryptoError(result)) { 154 AString msg = reply.readCString(); 155 if (errorDetailMsg) { 156 *errorDetailMsg = msg; 157 } 158 } 159 160 return result; 161 } 162 163 virtual void notifyResolution( 164 uint32_t width, uint32_t height) { 165 Parcel data, reply; 166 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 167 data.writeInt32(width); 168 data.writeInt32(height); 169 remote()->transact(NOTIFY_RESOLUTION, data, &reply); 170 } 171 172 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) { 173 Parcel data, reply; 174 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 175 176 writeVector(data, sessionId); 177 remote()->transact(SET_MEDIADRM_SESSION, data, &reply); 178 179 return reply.readInt32(); 180 } 181 182 virtual void setHeap(const sp<IMemoryHeap> &heap) { 183 Parcel data, reply; 184 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 185 data.writeStrongBinder(IInterface::asBinder(heap)); 186 remote()->transact(SET_HEAP, data, &reply); 187 return; 188 } 189 190 virtual void unsetHeap(const sp<IMemoryHeap>& heap) { 191 Parcel data, reply; 192 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 193 data.writeStrongBinder(IInterface::asBinder(heap)); 194 remote()->transact(UNSET_HEAP, data, &reply); 195 return; 196 } 197 198 199private: 200 void readVector(Parcel &reply, Vector<uint8_t> &vector) const { 201 uint32_t size = reply.readInt32(); 202 vector.insertAt((size_t)0, size); 203 reply.read(vector.editArray(), size); 204 } 205 206 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const { 207 data.writeInt32(vector.size()); 208 data.write(vector.array(), vector.size()); 209 } 210 211 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto); 212}; 213 214IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto"); 215 216//////////////////////////////////////////////////////////////////////////////// 217 218void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const { 219 uint32_t size = data.readInt32(); 220 vector.insertAt((size_t)0, size); 221 data.read(vector.editArray(), size); 222} 223 224void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const { 225 reply->writeInt32(vector.size()); 226 reply->write(vector.array(), vector.size()); 227} 228 229status_t BnCrypto::onTransact( 230 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 231 switch (code) { 232 case INIT_CHECK: 233 { 234 CHECK_INTERFACE(ICrypto, data, reply); 235 reply->writeInt32(initCheck()); 236 237 return OK; 238 } 239 240 case IS_CRYPTO_SUPPORTED: 241 { 242 CHECK_INTERFACE(ICrypto, data, reply); 243 uint8_t uuid[16]; 244 data.read(uuid, sizeof(uuid)); 245 reply->writeInt32(isCryptoSchemeSupported(uuid)); 246 247 return OK; 248 } 249 250 case CREATE_PLUGIN: 251 { 252 CHECK_INTERFACE(ICrypto, data, reply); 253 254 uint8_t uuid[16]; 255 data.read(uuid, sizeof(uuid)); 256 257 size_t opaqueSize = data.readInt32(); 258 void *opaqueData = NULL; 259 260 const size_t kMaxOpaqueSize = 100 * 1024; 261 if (opaqueSize > kMaxOpaqueSize) { 262 return BAD_VALUE; 263 } 264 265 opaqueData = malloc(opaqueSize); 266 if (NULL == opaqueData) { 267 return NO_MEMORY; 268 } 269 270 data.read(opaqueData, opaqueSize); 271 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); 272 273 free(opaqueData); 274 opaqueData = NULL; 275 276 return OK; 277 } 278 279 case DESTROY_PLUGIN: 280 { 281 CHECK_INTERFACE(ICrypto, data, reply); 282 reply->writeInt32(destroyPlugin()); 283 284 return OK; 285 } 286 287 case REQUIRES_SECURE_COMPONENT: 288 { 289 CHECK_INTERFACE(ICrypto, data, reply); 290 291 const char *mime = data.readCString(); 292 if (mime == NULL) { 293 reply->writeInt32(BAD_VALUE); 294 } else { 295 reply->writeInt32(requiresSecureDecoderComponent(mime)); 296 } 297 298 return OK; 299 } 300 301 case DECRYPT: 302 { 303 CHECK_INTERFACE(ICrypto, data, reply); 304 305 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); 306 CryptoPlugin::Pattern pattern; 307 pattern.mEncryptBlocks = data.readInt32(); 308 pattern.mSkipBlocks = data.readInt32(); 309 310 uint8_t key[16]; 311 data.read(key, sizeof(key)); 312 313 uint8_t iv[16]; 314 data.read(iv, sizeof(iv)); 315 316 size_t totalSize = data.readInt32(); 317 sp<IMemory> source = 318 interface_cast<IMemory>(data.readStrongBinder()); 319 if (source == NULL) { 320 reply->writeInt32(BAD_VALUE); 321 return OK; 322 } 323 int32_t offset = data.readInt32(); 324 325 int32_t numSubSamples = data.readInt32(); 326 if (numSubSamples < 0 || numSubSamples > 0xffff) { 327 reply->writeInt32(BAD_VALUE); 328 return OK; 329 } 330 331 CryptoPlugin::SubSample *subSamples = 332 new CryptoPlugin::SubSample[numSubSamples]; 333 334 data.read(subSamples, 335 sizeof(CryptoPlugin::SubSample) * numSubSamples); 336 337 DestinationBuffer destination; 338 destination.mType = (DestinationType)data.readInt32(); 339 if (destination.mType == kDestinationTypeNativeHandle) { 340 destination.mHandle = data.readNativeHandle(); 341 if (destination.mHandle == NULL) { 342 reply->writeInt32(BAD_VALUE); 343 return OK; 344 } 345 } else if (destination.mType == kDestinationTypeSharedMemory) { 346 destination.mSharedMemory = 347 interface_cast<IMemory>(data.readStrongBinder()); 348 if (destination.mSharedMemory == NULL) { 349 reply->writeInt32(BAD_VALUE); 350 return OK; 351 } 352 } 353 354 AString errorDetailMsg; 355 ssize_t result; 356 357 size_t sumSubsampleSizes = 0; 358 bool overflow = false; 359 for (int32_t i = 0; i < numSubSamples; ++i) { 360 CryptoPlugin::SubSample &ss = subSamples[i]; 361 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) { 362 sumSubsampleSizes += ss.mNumBytesOfEncryptedData; 363 } else { 364 overflow = true; 365 } 366 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) { 367 sumSubsampleSizes += ss.mNumBytesOfClearData; 368 } else { 369 overflow = true; 370 } 371 } 372 373 if (overflow || sumSubsampleSizes != totalSize) { 374 result = -EINVAL; 375 } else if (totalSize > source->size()) { 376 result = -EINVAL; 377 } else if ((size_t)offset > source->size() - totalSize) { 378 result = -EINVAL; 379 } else { 380 result = decrypt(key, iv, mode, pattern, source, offset, 381 subSamples, numSubSamples, destination, &errorDetailMsg); 382 } 383 384 reply->writeInt32(result); 385 386 if (isCryptoError(result)) { 387 reply->writeCString(errorDetailMsg.c_str()); 388 } 389 390 if (destination.mType == kDestinationTypeNativeHandle) { 391 int err; 392 if ((err = native_handle_close(destination.mHandle)) < 0) { 393 ALOGW("secure buffer native_handle_close failed: %d", err); 394 } 395 if ((err = native_handle_delete(destination.mHandle)) < 0) { 396 ALOGW("secure buffer native_handle_delete failed: %d", err); 397 } 398 } 399 400 delete[] subSamples; 401 subSamples = NULL; 402 403 return OK; 404 } 405 406 case NOTIFY_RESOLUTION: 407 { 408 CHECK_INTERFACE(ICrypto, data, reply); 409 410 int32_t width = data.readInt32(); 411 int32_t height = data.readInt32(); 412 notifyResolution(width, height); 413 414 return OK; 415 } 416 417 case SET_MEDIADRM_SESSION: 418 { 419 CHECK_INTERFACE(IDrm, data, reply); 420 Vector<uint8_t> sessionId; 421 readVector(data, sessionId); 422 reply->writeInt32(setMediaDrmSession(sessionId)); 423 return OK; 424 } 425 426 case SET_HEAP: 427 { 428 CHECK_INTERFACE(ICrypto, data, reply); 429 sp<IMemoryHeap> heap = 430 interface_cast<IMemoryHeap>(data.readStrongBinder()); 431 setHeap(heap); 432 return OK; 433 } 434 435 case UNSET_HEAP: 436 { 437 CHECK_INTERFACE(ICrypto, data, reply); 438 sp<IMemoryHeap> heap = 439 interface_cast<IMemoryHeap>(data.readStrongBinder()); 440 unsetHeap(heap); 441 return OK; 442 } 443 444 default: 445 return BBinder::onTransact(code, data, reply, flags); 446 } 447} 448 449} // namespace android 450