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