ICrypto.cpp revision 93e29c0846e0f7583ae96edafbf5e8a3169711ee
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 const size_t kMaxOpaqueSize = 100 * 1024; 242 if (opaqueSize > kMaxOpaqueSize) { 243 return BAD_VALUE; 244 } 245 246 opaqueData = malloc(opaqueSize); 247 if (NULL == opaqueData) { 248 return NO_MEMORY; 249 } 250 251 data.read(opaqueData, opaqueSize); 252 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); 253 254 free(opaqueData); 255 opaqueData = NULL; 256 257 return OK; 258 } 259 260 case DESTROY_PLUGIN: 261 { 262 CHECK_INTERFACE(ICrypto, data, reply); 263 reply->writeInt32(destroyPlugin()); 264 265 return OK; 266 } 267 268 case REQUIRES_SECURE_COMPONENT: 269 { 270 CHECK_INTERFACE(ICrypto, data, reply); 271 272 const char *mime = data.readCString(); 273 if (mime == NULL) { 274 reply->writeInt32(BAD_VALUE); 275 } else { 276 reply->writeInt32(requiresSecureDecoderComponent(mime)); 277 } 278 279 return OK; 280 } 281 282 case DECRYPT: 283 { 284 CHECK_INTERFACE(ICrypto, data, reply); 285 286 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); 287 CryptoPlugin::Pattern pattern; 288 pattern.mEncryptBlocks = data.readInt32(); 289 pattern.mSkipBlocks = data.readInt32(); 290 291 uint8_t key[16]; 292 data.read(key, sizeof(key)); 293 294 uint8_t iv[16]; 295 data.read(iv, sizeof(iv)); 296 297 size_t totalSize = data.readInt32(); 298 sp<IMemory> source = 299 interface_cast<IMemory>(data.readStrongBinder()); 300 if (source == NULL) { 301 reply->writeInt32(BAD_VALUE); 302 return OK; 303 } 304 int32_t offset = data.readInt32(); 305 306 int32_t numSubSamples = data.readInt32(); 307 if (numSubSamples < 0 || numSubSamples > 0xffff) { 308 reply->writeInt32(BAD_VALUE); 309 return OK; 310 } 311 312 CryptoPlugin::SubSample *subSamples = 313 new CryptoPlugin::SubSample[numSubSamples]; 314 315 data.read(subSamples, 316 sizeof(CryptoPlugin::SubSample) * numSubSamples); 317 318 DestinationBuffer destination; 319 destination.mType = (DestinationType)data.readInt32(); 320 if (destination.mType == kDestinationTypeNativeHandle) { 321 destination.mHandle = data.readNativeHandle(); 322 if (destination.mHandle == NULL) { 323 reply->writeInt32(BAD_VALUE); 324 return OK; 325 } 326 } else if (destination.mType == kDestinationTypeSharedMemory) { 327 destination.mSharedMemory = 328 interface_cast<IMemory>(data.readStrongBinder()); 329 if (destination.mSharedMemory == NULL) { 330 reply->writeInt32(BAD_VALUE); 331 return OK; 332 } 333 } 334 335 AString errorDetailMsg; 336 ssize_t result; 337 338 size_t sumSubsampleSizes = 0; 339 bool overflow = false; 340 for (int32_t i = 0; i < numSubSamples; ++i) { 341 CryptoPlugin::SubSample &ss = subSamples[i]; 342 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) { 343 sumSubsampleSizes += ss.mNumBytesOfEncryptedData; 344 } else { 345 overflow = true; 346 } 347 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) { 348 sumSubsampleSizes += ss.mNumBytesOfClearData; 349 } else { 350 overflow = true; 351 } 352 } 353 354 if (overflow || sumSubsampleSizes != totalSize) { 355 result = -EINVAL; 356 } else if (totalSize > source->size()) { 357 result = -EINVAL; 358 } else if ((size_t)offset > source->size() - totalSize) { 359 result = -EINVAL; 360 } else { 361 result = decrypt(key, iv, mode, pattern, source, offset, 362 subSamples, numSubSamples, destination, &errorDetailMsg); 363 } 364 365 reply->writeInt32(result); 366 367 if (isCryptoError(result)) { 368 reply->writeCString(errorDetailMsg.c_str()); 369 } 370 371 if (destination.mType == kDestinationTypeNativeHandle) { 372 int err; 373 if ((err = native_handle_close(destination.mHandle)) < 0) { 374 ALOGW("secure buffer native_handle_close failed: %d", err); 375 } 376 if ((err = native_handle_delete(destination.mHandle)) < 0) { 377 ALOGW("secure buffer native_handle_delete failed: %d", err); 378 } 379 } 380 381 delete[] subSamples; 382 subSamples = NULL; 383 384 return OK; 385 } 386 387 case NOTIFY_RESOLUTION: 388 { 389 CHECK_INTERFACE(ICrypto, data, reply); 390 391 int32_t width = data.readInt32(); 392 int32_t height = data.readInt32(); 393 notifyResolution(width, height); 394 395 return OK; 396 } 397 398 case SET_MEDIADRM_SESSION: 399 { 400 CHECK_INTERFACE(IDrm, data, reply); 401 Vector<uint8_t> sessionId; 402 readVector(data, sessionId); 403 reply->writeInt32(setMediaDrmSession(sessionId)); 404 return OK; 405 } 406 407 default: 408 return BBinder::onTransact(code, data, reply, flags); 409 } 410} 411 412} // namespace android 413