Commit message: None
CVE: CVE-2016-0811
CWE: CWE-200
Vulnerability description: Integer overflow in the BnCrypto::onTransact function in media/libmedia/ICrypto.cpp in libmediaplayerservice in Android 6.x before 2016-02-01 allows attackers to obtain sensitive information, and consequently bypass an unspecified protection mechanism, by triggering an improper size calculation, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bug 25800375.

Project: Android

 virtual status_t createPlugin(
 const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) {
 Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.write(uuid, 16);
        data.writeInt32(opaqueSize);

 if (opaqueSize > 0) {
            data.write(opaqueData, opaqueSize);
 }

        remote()->transact(CREATE_PLUGIN, data, &reply);

 return reply.readInt32();
 }

Project: Android

 virtual ssize_t decrypt(
 bool secure,
 const uint8_t key[16],
 const uint8_t iv[16],
 CryptoPlugin::Mode mode,
 const sp<IMemory> &sharedBuffer, size_t offset,
 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
 void *dstPtr,
 AString *errorDetailMsg) {
 Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeInt32(secure);
        data.writeInt32(mode);

 static const uint8_t kDummy[16] = { 0 };

 if (key == NULL) {
            key = kDummy;
 }

 if (iv == NULL) {
            iv = kDummy;
 }

        data.write(key, 16);
        data.write(iv, 16);

 size_t totalSize = 0;
 for (size_t i = 0; i < numSubSamples; ++i) {
            totalSize += subSamples[i].mNumBytesOfEncryptedData;
            totalSize += subSamples[i].mNumBytesOfClearData;
 }

        data.writeInt32(totalSize);
        data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
        data.writeInt32(offset);

        data.writeInt32(numSubSamples);
        data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);

 if (secure) {
            data.writeInt64(static_cast<uint64_t>(reinterpret_cast<uintptr_t>(dstPtr)));
 }

        remote()->transact(DECRYPT, data, &reply);

 ssize_t result = reply.readInt32();

 if (isCryptoError(result)) {
            errorDetailMsg->setTo(reply.readCString());
 }

 if (!secure && result >= 0) {
            reply.read(dstPtr, result);
 }

 return result;
 }

Project: Android

 virtual status_t destroyPlugin() {
 Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        remote()->transact(DESTROY_PLUGIN, data, &reply);

 return reply.readInt32();
 }

Project: Android

 virtual status_t initCheck() const {
 Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        remote()->transact(INIT_CHECK, data, &reply);

 return reply.readInt32();
 }

Project: Android

 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) {
 Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.write(uuid, 16);
        remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);

 return reply.readInt32() != 0;
 }

Project: Android

 virtual void notifyResolution(
 uint32_t width, uint32_t height) {
 Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeInt32(width);
        data.writeInt32(height);
        remote()->transact(NOTIFY_RESOLUTION, data, &reply);
 }

Project: Android

 virtual bool requiresSecureDecoderComponent(
 const char *mime) const {
 Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());
        data.writeCString(mime);
        remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply);

 return reply.readInt32() != 0;
 }

Project: Android

 virtual status_t setMediaDrmSession(const Vector<uint8_t> &sessionId) {
 Parcel data, reply;
        data.writeInterfaceToken(ICrypto::getInterfaceDescriptor());

        writeVector(data, sessionId);
        remote()->transact(SET_MEDIADRM_SESSION, data, &reply);

 return reply.readInt32();
 }

Project: Android

void BnCrypto::writeVector(Parcel *reply, Vector<uint8_t> const &vector) const {
    reply->writeInt32(vector.size());
    reply->write(vector.array(), vector.size());
}