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}; 40 41struct BpCrypto : public BpInterface<ICrypto> { 42 BpCrypto(const sp<IBinder> &impl) 43 : BpInterface<ICrypto>(impl) { 44 } 45 46 virtual status_t initCheck() const { 47 Parcel data, reply; 48 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 49 remote()->transact(INIT_CHECK, data, &reply); 50 51 return reply.readInt32(); 52 } 53 54 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) { 55 Parcel data, reply; 56 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 57 data.write(uuid, 16); 58 remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply); 59 60 return reply.readInt32() != 0; 61 } 62 63 virtual status_t createPlugin( 64 const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) { 65 Parcel data, reply; 66 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 67 data.write(uuid, 16); 68 data.writeInt32(opaqueSize); 69 70 if (opaqueSize > 0) { 71 data.write(opaqueData, opaqueSize); 72 } 73 74 remote()->transact(CREATE_PLUGIN, data, &reply); 75 76 return reply.readInt32(); 77 } 78 79 virtual status_t destroyPlugin() { 80 Parcel data, reply; 81 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 82 remote()->transact(DESTROY_PLUGIN, data, &reply); 83 84 return reply.readInt32(); 85 } 86 87 virtual bool requiresSecureDecoderComponent( 88 const char *mime) const { 89 Parcel data, reply; 90 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 91 data.writeCString(mime); 92 remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply); 93 94 return reply.readInt32() != 0; 95 } 96 97 virtual ssize_t decrypt( 98 DestinationType dstType, 99 const uint8_t key[16], 100 const uint8_t iv[16], 101 CryptoPlugin::Mode mode, const CryptoPlugin::Pattern &pattern, 102 const sp<IMemory> &sharedBuffer, size_t offset, 103 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, 104 void *dstPtr, 105 AString *errorDetailMsg) { 106 Parcel data, reply; 107 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 108 data.writeInt32((int32_t)dstType); 109 data.writeInt32(mode); 110 data.writeInt32(pattern.mEncryptBlocks); 111 data.writeInt32(pattern.mSkipBlocks); 112 113 static const uint8_t kDummy[16] = { 0 }; 114 115 if (key == NULL) { 116 key = kDummy; 117 } 118 119 if (iv == NULL) { 120 iv = kDummy; 121 } 122 123 data.write(key, 16); 124 data.write(iv, 16); 125 126 size_t totalSize = 0; 127 for (size_t i = 0; i < numSubSamples; ++i) { 128 totalSize += subSamples[i].mNumBytesOfEncryptedData; 129 totalSize += subSamples[i].mNumBytesOfClearData; 130 } 131 132 data.writeInt32(totalSize); 133 data.writeStrongBinder(IInterface::asBinder(sharedBuffer)); 134 data.writeInt32(offset); 135 136 data.writeInt32(numSubSamples); 137 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); 138 139 if (dstType == kDestinationTypeNativeHandle) { 140 data.writeNativeHandle(static_cast<native_handle_t *>(dstPtr)); 141 } else if (dstType == kDestinationTypeOpaqueHandle) { 142 data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr))); 143 } else { 144 dstType = kDestinationTypeVmPointer; 145 } 146 147 remote()->transact(DECRYPT, data, &reply); 148 149 ssize_t result = reply.readInt32(); 150 151 if (isCryptoError(result)) { 152 errorDetailMsg->setTo(reply.readCString()); 153 } 154 155 if (dstType == kDestinationTypeVmPointer && result >= 0) { 156 reply.read(dstPtr, result); 157 } 158 159 return result; 160 } 161 162 virtual void notifyResolution( 163 uint32_t width, uint32_t height) { 164 Parcel data, reply; 165 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 166 data.writeInt32(width); 167 data.writeInt32(height); 168 remote()->transact(NOTIFY_RESOLUTION, data, &reply); 169 } 170 171 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) { 172 Parcel data, reply; 173 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 174 175 writeVector(data, sessionId); 176 remote()->transact(SET_MEDIADRM_SESSION, data, &reply); 177 178 return reply.readInt32(); 179 } 180 181private: 182 void readVector(Parcel &reply, Vector<uint8_t> &vector) const { 183 uint32_t size = reply.readInt32(); 184 vector.insertAt((size_t)0, size); 185 reply.read(vector.editArray(), size); 186 } 187 188 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const { 189 data.writeInt32(vector.size()); 190 data.write(vector.array(), vector.size()); 191 } 192 193 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto); 194}; 195 196IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto"); 197 198//////////////////////////////////////////////////////////////////////////////// 199 200void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const { 201 uint32_t size = data.readInt32(); 202 vector.insertAt((size_t)0, size); 203 data.read(vector.editArray(), size); 204} 205 206void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const { 207 reply->writeInt32(vector.size()); 208 reply->write(vector.array(), vector.size()); 209} 210 211status_t BnCrypto::onTransact( 212 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 213 switch (code) { 214 case INIT_CHECK: 215 { 216 CHECK_INTERFACE(ICrypto, data, reply); 217 reply->writeInt32(initCheck()); 218 219 return OK; 220 } 221 222 case IS_CRYPTO_SUPPORTED: 223 { 224 CHECK_INTERFACE(ICrypto, data, reply); 225 uint8_t uuid[16]; 226 data.read(uuid, sizeof(uuid)); 227 reply->writeInt32(isCryptoSchemeSupported(uuid)); 228 229 return OK; 230 } 231 232 case CREATE_PLUGIN: 233 { 234 CHECK_INTERFACE(ICrypto, data, reply); 235 236 uint8_t uuid[16]; 237 data.read(uuid, sizeof(uuid)); 238 239 size_t opaqueSize = data.readInt32(); 240 void *opaqueData = NULL; 241 242 if (opaqueSize > 0) { 243 opaqueData = malloc(opaqueSize); 244 data.read(opaqueData, opaqueSize); 245 } 246 247 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); 248 249 if (opaqueData != NULL) { 250 free(opaqueData); 251 opaqueData = NULL; 252 } 253 254 return OK; 255 } 256 257 case DESTROY_PLUGIN: 258 { 259 CHECK_INTERFACE(ICrypto, data, reply); 260 reply->writeInt32(destroyPlugin()); 261 262 return OK; 263 } 264 265 case REQUIRES_SECURE_COMPONENT: 266 { 267 CHECK_INTERFACE(ICrypto, data, reply); 268 269 const char *mime = data.readCString(); 270 if (mime == NULL) { 271 reply->writeInt32(BAD_VALUE); 272 } else { 273 reply->writeInt32(requiresSecureDecoderComponent(mime)); 274 } 275 276 return OK; 277 } 278 279 case DECRYPT: 280 { 281 CHECK_INTERFACE(ICrypto, data, reply); 282 283 DestinationType dstType = (DestinationType)data.readInt32(); 284 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); 285 CryptoPlugin::Pattern pattern; 286 pattern.mEncryptBlocks = data.readInt32(); 287 pattern.mSkipBlocks = data.readInt32(); 288 289 uint8_t key[16]; 290 data.read(key, sizeof(key)); 291 292 uint8_t iv[16]; 293 data.read(iv, sizeof(iv)); 294 295 size_t totalSize = data.readInt32(); 296 sp<IMemory> sharedBuffer = 297 interface_cast<IMemory>(data.readStrongBinder()); 298 if (sharedBuffer == NULL) { 299 reply->writeInt32(BAD_VALUE); 300 return OK; 301 } 302 int32_t offset = data.readInt32(); 303 304 int32_t numSubSamples = data.readInt32(); 305 306 CryptoPlugin::SubSample *subSamples = 307 new CryptoPlugin::SubSample[numSubSamples]; 308 309 data.read( 310 subSamples, 311 sizeof(CryptoPlugin::SubSample) * numSubSamples); 312 313 native_handle_t *nativeHandle = NULL; 314 void *secureBufferId = NULL, *dstPtr; 315 if (dstType == kDestinationTypeNativeHandle) { 316 nativeHandle = data.readNativeHandle(); 317 dstPtr = static_cast<void *>(nativeHandle); 318 } else if (dstType == kDestinationTypeOpaqueHandle) { 319 secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64())); 320 dstPtr = secureBufferId; 321 } else { 322 dstType = kDestinationTypeVmPointer; 323 dstPtr = malloc(totalSize); 324 } 325 326 AString errorDetailMsg; 327 ssize_t result; 328 329 size_t sumSubsampleSizes = 0; 330 bool overflow = false; 331 for (int32_t i = 0; i < numSubSamples; ++i) { 332 CryptoPlugin::SubSample &ss = subSamples[i]; 333 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) { 334 sumSubsampleSizes += ss.mNumBytesOfEncryptedData; 335 } else { 336 overflow = true; 337 } 338 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) { 339 sumSubsampleSizes += ss.mNumBytesOfClearData; 340 } else { 341 overflow = true; 342 } 343 } 344 345 if (overflow || sumSubsampleSizes != totalSize) { 346 result = -EINVAL; 347 } else if (totalSize > sharedBuffer->size()) { 348 result = -EINVAL; 349 } else if ((size_t)offset > sharedBuffer->size() - totalSize) { 350 result = -EINVAL; 351 } else { 352 result = decrypt( 353 dstType, 354 key, 355 iv, 356 mode, pattern, 357 sharedBuffer, offset, 358 subSamples, numSubSamples, 359 dstPtr, 360 &errorDetailMsg); 361 } 362 363 reply->writeInt32(result); 364 365 if (isCryptoError(result)) { 366 reply->writeCString(errorDetailMsg.c_str()); 367 } 368 369 if (dstType == kDestinationTypeVmPointer) { 370 if (result >= 0) { 371 CHECK_LE(result, static_cast<ssize_t>(totalSize)); 372 reply->write(dstPtr, result); 373 } 374 free(dstPtr); 375 dstPtr = NULL; 376 } else if (dstType == kDestinationTypeNativeHandle) { 377 int err; 378 if ((err = native_handle_close(nativeHandle)) < 0) { 379 ALOGW("secure buffer native_handle_close failed: %d", err); 380 } 381 if ((err = native_handle_delete(nativeHandle)) < 0) { 382 ALOGW("secure buffer native_handle_delete failed: %d", err); 383 } 384 } 385 386 delete[] subSamples; 387 subSamples = NULL; 388 389 return OK; 390 } 391 392 case NOTIFY_RESOLUTION: 393 { 394 CHECK_INTERFACE(ICrypto, data, reply); 395 396 int32_t width = data.readInt32(); 397 int32_t height = data.readInt32(); 398 notifyResolution(width, height); 399 400 return OK; 401 } 402 403 case SET_MEDIADRM_SESSION: 404 { 405 CHECK_INTERFACE(IDrm, data, reply); 406 Vector<uint8_t> sessionId; 407 readVector(data, sessionId); 408 reply->writeInt32(setMediaDrmSession(sessionId)); 409 return OK; 410 } 411 412 default: 413 return BBinder::onTransact(code, data, reply, flags); 414 } 415} 416 417} // namespace android 418