Home | History | Annotate | Download | only in libmedia
      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 
     28 namespace android {
     29 
     30 enum {
     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 
     41 struct 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         } else if (dstType == kDestinationTypeVmPointer) {
    154             // For the non-secure case, copy the decrypted
    155             // data from shared memory to its final destination
    156             memcpy(dstPtr, sharedBuffer->pointer(), 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 
    181 private:
    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 
    196 IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto");
    197 
    198 ////////////////////////////////////////////////////////////////////////////////
    199 
    200 void 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 
    206 void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
    207     reply->writeInt32(vector.size());
    208     reply->write(vector.array(), vector.size());
    209 }
    210 
    211 status_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                     // For the non-secure case, pass the decrypted
    373                     // data back via the shared buffer rather than
    374                     // copying it separately over binder to avoid
    375                     // binder's 1MB limit.
    376                     memcpy(sharedBuffer->pointer(), dstPtr, result);
    377                 }
    378                 free(dstPtr);
    379                 dstPtr = NULL;
    380             } else if (dstType == kDestinationTypeNativeHandle) {
    381                 int err;
    382                 if ((err = native_handle_close(nativeHandle)) < 0) {
    383                     ALOGW("secure buffer native_handle_close failed: %d", err);
    384                 }
    385                 if ((err = native_handle_delete(nativeHandle)) < 0) {
    386                     ALOGW("secure buffer native_handle_delete failed: %d", err);
    387                 }
    388             }
    389 
    390             delete[] subSamples;
    391             subSamples = NULL;
    392 
    393             return OK;
    394         }
    395 
    396         case NOTIFY_RESOLUTION:
    397         {
    398             CHECK_INTERFACE(ICrypto, data, reply);
    399 
    400             int32_t width = data.readInt32();
    401             int32_t height = data.readInt32();
    402             notifyResolution(width, height);
    403 
    404             return OK;
    405         }
    406 
    407         case SET_MEDIADRM_SESSION:
    408         {
    409             CHECK_INTERFACE(IDrm, data, reply);
    410             Vector<uint8_t> sessionId;
    411             readVector(data, sessionId);
    412             reply->writeInt32(setMediaDrmSession(sessionId));
    413             return OK;
    414         }
    415 
    416         default:
    417             return BBinder::onTransact(code, data, reply, flags);
    418     }
    419 }
    420 
    421 }  // namespace android
    422