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