ICrypto.cpp revision 9247e10531fa3128d5263e3ad605a0fecefcd2d0
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 errorDetailMsg->setTo(reply.readCString()); 153 } 154 155 return result; 156 } 157 158 virtual void notifyResolution( 159 uint32_t width, uint32_t height) { 160 Parcel data, reply; 161 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 162 data.writeInt32(width); 163 data.writeInt32(height); 164 remote()->transact(NOTIFY_RESOLUTION, data, &reply); 165 } 166 167 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) { 168 Parcel data, reply; 169 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 170 171 writeVector(data, sessionId); 172 remote()->transact(SET_MEDIADRM_SESSION, data, &reply); 173 174 return reply.readInt32(); 175 } 176 177private: 178 void readVector(Parcel &reply, Vector<uint8_t> &vector) const { 179 uint32_t size = reply.readInt32(); 180 vector.insertAt((size_t)0, size); 181 reply.read(vector.editArray(), size); 182 } 183 184 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const { 185 data.writeInt32(vector.size()); 186 data.write(vector.array(), vector.size()); 187 } 188 189 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto); 190}; 191 192IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto"); 193 194//////////////////////////////////////////////////////////////////////////////// 195 196void BnCrypto::readVector(const Parcel &data, Vector<uint8_t> &vector) const { 197 uint32_t size = data.readInt32(); 198 vector.insertAt((size_t)0, size); 199 data.read(vector.editArray(), size); 200} 201 202void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const { 203 reply->writeInt32(vector.size()); 204 reply->write(vector.array(), vector.size()); 205} 206 207status_t BnCrypto::onTransact( 208 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 209 switch (code) { 210 case INIT_CHECK: 211 { 212 CHECK_INTERFACE(ICrypto, data, reply); 213 reply->writeInt32(initCheck()); 214 215 return OK; 216 } 217 218 case IS_CRYPTO_SUPPORTED: 219 { 220 CHECK_INTERFACE(ICrypto, data, reply); 221 uint8_t uuid[16]; 222 data.read(uuid, sizeof(uuid)); 223 reply->writeInt32(isCryptoSchemeSupported(uuid)); 224 225 return OK; 226 } 227 228 case CREATE_PLUGIN: 229 { 230 CHECK_INTERFACE(ICrypto, data, reply); 231 232 uint8_t uuid[16]; 233 data.read(uuid, sizeof(uuid)); 234 235 size_t opaqueSize = data.readInt32(); 236 void *opaqueData = NULL; 237 238 const size_t kMaxOpaqueSize = 100 * 1024; 239 if (opaqueSize > kMaxOpaqueSize) { 240 return BAD_VALUE; 241 } 242 243 opaqueData = malloc(opaqueSize); 244 if (NULL == opaqueData) { 245 return NO_MEMORY; 246 } 247 248 data.read(opaqueData, opaqueSize); 249 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); 250 251 free(opaqueData); 252 opaqueData = NULL; 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 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); 284 CryptoPlugin::Pattern pattern; 285 pattern.mEncryptBlocks = data.readInt32(); 286 pattern.mSkipBlocks = data.readInt32(); 287 288 uint8_t key[16]; 289 data.read(key, sizeof(key)); 290 291 uint8_t iv[16]; 292 data.read(iv, sizeof(iv)); 293 294 size_t totalSize = data.readInt32(); 295 sp<IMemory> source = 296 interface_cast<IMemory>(data.readStrongBinder()); 297 if (source == NULL) { 298 reply->writeInt32(BAD_VALUE); 299 return OK; 300 } 301 int32_t offset = data.readInt32(); 302 303 int32_t numSubSamples = data.readInt32(); 304 if (numSubSamples < 0 || numSubSamples > 0xffff) { 305 reply->writeInt32(BAD_VALUE); 306 return OK; 307 } 308 309 CryptoPlugin::SubSample *subSamples = 310 new CryptoPlugin::SubSample[numSubSamples]; 311 312 data.read(subSamples, 313 sizeof(CryptoPlugin::SubSample) * numSubSamples); 314 315 DestinationBuffer destination; 316 destination.mType = (DestinationType)data.readInt32(); 317 if (destination.mType == kDestinationTypeNativeHandle) { 318 destination.mHandle = data.readNativeHandle(); 319 if (destination.mHandle == NULL) { 320 reply->writeInt32(BAD_VALUE); 321 return OK; 322 } 323 } else if (destination.mType == kDestinationTypeSharedMemory) { 324 destination.mSharedMemory = 325 interface_cast<IMemory>(data.readStrongBinder()); 326 if (destination.mSharedMemory == NULL) { 327 reply->writeInt32(BAD_VALUE); 328 return OK; 329 } 330 } 331 332 AString errorDetailMsg; 333 ssize_t result; 334 335 size_t sumSubsampleSizes = 0; 336 bool overflow = false; 337 for (int32_t i = 0; i < numSubSamples; ++i) { 338 CryptoPlugin::SubSample &ss = subSamples[i]; 339 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfEncryptedData) { 340 sumSubsampleSizes += ss.mNumBytesOfEncryptedData; 341 } else { 342 overflow = true; 343 } 344 if (sumSubsampleSizes <= SIZE_MAX - ss.mNumBytesOfClearData) { 345 sumSubsampleSizes += ss.mNumBytesOfClearData; 346 } else { 347 overflow = true; 348 } 349 } 350 351 if (overflow || sumSubsampleSizes != totalSize) { 352 result = -EINVAL; 353 } else if (totalSize > source->size()) { 354 result = -EINVAL; 355 } else if ((size_t)offset > source->size() - totalSize) { 356 result = -EINVAL; 357 } else { 358 result = decrypt(key, iv, mode, pattern, source, offset, 359 subSamples, numSubSamples, destination, &errorDetailMsg); 360 } 361 362 reply->writeInt32(result); 363 364 if (isCryptoError(result)) { 365 reply->writeCString(errorDetailMsg.c_str()); 366 } 367 368 if (destination.mType == kDestinationTypeNativeHandle) { 369 int err; 370 if ((err = native_handle_close(destination.mHandle)) < 0) { 371 ALOGW("secure buffer native_handle_close failed: %d", err); 372 } 373 if ((err = native_handle_delete(destination.mHandle)) < 0) { 374 ALOGW("secure buffer native_handle_delete failed: %d", err); 375 } 376 } 377 378 delete[] subSamples; 379 subSamples = NULL; 380 381 return OK; 382 } 383 384 case NOTIFY_RESOLUTION: 385 { 386 CHECK_INTERFACE(ICrypto, data, reply); 387 388 int32_t width = data.readInt32(); 389 int32_t height = data.readInt32(); 390 notifyResolution(width, height); 391 392 return OK; 393 } 394 395 case SET_MEDIADRM_SESSION: 396 { 397 CHECK_INTERFACE(IDrm, data, reply); 398 Vector<uint8_t> sessionId; 399 readVector(data, sessionId); 400 reply->writeInt32(setMediaDrmSession(sessionId)); 401 return OK; 402 } 403 404 default: 405 return BBinder::onTransact(code, data, reply, flags); 406 } 407} 408 409} // namespace android 410