Commit message: None
CVE: CVE-2016-2419
CWE: CWE-264
Vulnerability description: media/libmedia/IDrm.cpp in mediaserver in Android 6.x before 2016-04-01 does not initialize a certain key-request data structure, which allows attackers to obtain sensitive information from process memory, and consequently bypass an unspecified protection mechanism, via unspecified vectors, as demonstrated by obtaining Signature or SignatureOrSystem access, aka internal bug 26323455.

Project: Android

 BpDrm(const sp<IBinder> &impl)
 : BpInterface<IDrm>(impl) {
 }

Project: Android

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

        writeVector(data, sessionId);
 status_t status = remote()->transact(CLOSE_SESSION, data, &reply);
 if (status != OK) {
 return status;
 }

 return reply.readInt32();
 }

Project: Android

 virtual status_t decrypt(Vector<uint8_t> const &sessionId,
 Vector<uint8_t> const &keyId,
 Vector<uint8_t> const &input,
 Vector<uint8_t> const &iv,
 Vector<uint8_t> &output) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, sessionId);
        writeVector(data, keyId);
        writeVector(data, input);
        writeVector(data, iv);

 status_t status = remote()->transact(DECRYPT, data, &reply);
 if (status != OK) {
 return status;
 }
        readVector(reply, output);

 return reply.readInt32();
 }

Project: Android

 virtual status_t destroyPlugin() {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 status_t status = remote()->transact(DESTROY_PLUGIN, data, &reply);
 if (status != OK) {
 return status;
 }

 return reply.readInt32();
 }

Project: Android

 virtual status_t encrypt(Vector<uint8_t> const &sessionId,
 Vector<uint8_t> const &keyId,
 Vector<uint8_t> const &input,
 Vector<uint8_t> const &iv,
 Vector<uint8_t> &output) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, sessionId);
        writeVector(data, keyId);
        writeVector(data, input);
        writeVector(data, iv);

 status_t status = remote()->transact(ENCRYPT, data, &reply);
 if (status != OK) {
 return status;
 }
        readVector(reply, output);

 return reply.readInt32();
 }

Project: Android

        getKeyRequest(Vector<uint8_t> const &sessionId,
 Vector<uint8_t> const &initData,
 String8 const &mimeType, DrmPlugin::KeyType keyType,
 KeyedVector<String8, String8> const &optionalParameters,
 Vector<uint8_t> &request, String8 &defaultUrl,
 DrmPlugin::KeyRequestType *keyRequestType) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, sessionId);
        writeVector(data, initData);
        data.writeString8(mimeType);
        data.writeInt32((uint32_t)keyType);

        data.writeInt32(optionalParameters.size());
 for (size_t i = 0; i < optionalParameters.size(); ++i) {
            data.writeString8(optionalParameters.keyAt(i));
            data.writeString8(optionalParameters.valueAt(i));
 }

 status_t status = remote()->transact(GET_KEY_REQUEST, data, &reply);
 if (status != OK) {
 return status;
 }

        readVector(reply, request);
        defaultUrl = reply.readString8();
 *keyRequestType = static_cast<DrmPlugin::KeyRequestType>(reply.readInt32());

 return reply.readInt32();
 }

Project: Android

 virtual status_t getPropertyByteArray(String8 const &name, Vector<uint8_t> &value) const {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        data.writeString8(name);
 status_t status = remote()->transact(GET_PROPERTY_BYTE_ARRAY, data, &reply);
 if (status != OK) {
 return status;
 }

        readVector(reply, value);
 return reply.readInt32();
 }

Project: Android

 virtual status_t getPropertyString(String8 const &name, String8 &value) const {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        data.writeString8(name);
 status_t status = remote()->transact(GET_PROPERTY_STRING, data, &reply);
 if (status != OK) {
 return status;
 }

        value = reply.readString8();
 return reply.readInt32();
 }

Project: Android

 virtual status_t getProvisionRequest(String8 const &certType,
 String8 const &certAuthority,
 Vector<uint8_t> &request,
 String8 &defaultUrl) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        data.writeString8(certType);
        data.writeString8(certAuthority);
 status_t status = remote()->transact(GET_PROVISION_REQUEST, data, &reply);
 if (status != OK) {
 return status;
 }

        readVector(reply, request);
        defaultUrl = reply.readString8();

 return reply.readInt32();
 }

Project: Android

 virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, ssid);
 status_t status = remote()->transact(GET_SECURE_STOP, data, &reply);
 if (status != OK) {
 return status;
 }

        readVector(reply, secureStop);
 return reply.readInt32();
 }

Project: Android

 virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

 status_t status = remote()->transact(GET_SECURE_STOPS, data, &reply);
 if (status != OK) {
 return status;
 }

        secureStops.clear();
 uint32_t count = reply.readInt32();
 for (size_t i = 0; i < count; i++) {
 Vector<uint8_t> secureStop;
            readVector(reply, secureStop);
            secureStops.push_back(secureStop);
 }
 return reply.readInt32();
 }

Project: Android

 virtual status_t initCheck() const {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
 status_t status = remote()->transact(INIT_CHECK, data, &reply);
 if (status != OK) {
 return status;
 }

 return reply.readInt32();
 }

Project: Android

 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
        data.write(uuid, 16);
        data.writeString8(mimeType);
 status_t status = remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply);
 if (status != OK) {
            ALOGE("isCryptoSchemeSupported: binder call failed: %d", status);
 return false;
 }

 return reply.readInt32() != 0;
 }

Project: Android

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

 status_t status = remote()->transact(OPEN_SESSION, data, &reply);
 if (status != OK) {
 return status;
 }
        readVector(reply, sessionId);

 return reply.readInt32();
 }

Project: Android

 virtual status_t provideKeyResponse(Vector<uint8_t> const &sessionId,
 Vector<uint8_t> const &response,
 Vector<uint8_t> &keySetId) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
        writeVector(data, sessionId);
        writeVector(data, response);

 status_t status = remote()->transact(PROVIDE_KEY_RESPONSE, data, &reply);
 if (status != OK) {
 return status;
 }

        readVector(reply, keySetId);

 return reply.readInt32();
 }

Project: Android

 virtual status_t provideProvisionResponse(Vector<uint8_t> const &response,
 Vector<uint8_t> &certificate,
 Vector<uint8_t> &wrappedKey) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, response);
 status_t status = remote()->transact(PROVIDE_PROVISION_RESPONSE, data, &reply);
 if (status != OK) {
 return status;
 }

        readVector(reply, certificate);
        readVector(reply, wrappedKey);

 return reply.readInt32();
 }

Project: Android

 virtual status_t queryKeyStatus(Vector<uint8_t> const &sessionId,
 KeyedVector<String8, String8> &infoMap) const {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, sessionId);
 status_t status = remote()->transact(QUERY_KEY_STATUS, data, &reply);
 if (status != OK) {
 return status;
 }

        infoMap.clear();
 size_t count = reply.readInt32();
 for (size_t i = 0; i < count; i++) {
 String8 key = reply.readString8();
 String8 value = reply.readString8();
            infoMap.add(key, value);
 }
 return reply.readInt32();
 }

Project: Android

 void readVector(Parcel &reply, Vector<uint8_t> &vector) const {
 uint32_t size = reply.readInt32();
 vector.insertAt((size_t)0, size);
        reply.read(vector.editArray(), size);
 }

Project: Android

void BnDrm::readVector(const Parcel &data, Vector<uint8_t> &vector) const {
 uint32_t size = data.readInt32();
 vector.insertAt((size_t)0, size);
    data.read(vector.editArray(), size);
}

Project: Android

 virtual status_t releaseAllSecureStops() {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

 status_t status = remote()->transact(RELEASE_ALL_SECURE_STOPS, data, &reply);
 if (status != OK) {
 return status;
 }

 return reply.readInt32();
 }

Project: Android

 virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, ssRelease);
 status_t status = remote()->transact(RELEASE_SECURE_STOPS, data, &reply);
 if (status != OK) {
 return status;
 }

 return reply.readInt32();
 }

Project: Android

 virtual status_t removeKeys(Vector<uint8_t> const &keySetId) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, keySetId);
 status_t status = remote()->transact(REMOVE_KEYS, data, &reply);
 if (status != OK) {
 return status;
 }

 return reply.readInt32();
 }

Project: Android

 virtual status_t setListener(const sp<IDrmClient>& listener) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
        data.writeStrongBinder(IInterface::asBinder(listener));
 status_t status = remote()->transact(SET_LISTENER, data, &reply);
 if (status != OK) {
 return status;
 }
 return reply.readInt32();
 }

Project: Android

 virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId,
 String8 const &algorithm) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, sessionId);
        data.writeString8(algorithm);
 status_t status = remote()->transact(SET_MAC_ALGORITHM, data, &reply);
 if (status != OK) {
 return status;
 }
 return reply.readInt32();
 }

Project: Android

 virtual status_t setPropertyByteArray(String8 const &name,
 Vector<uint8_t> const &value) const {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        data.writeString8(name);
        writeVector(data, value);
 status_t status = remote()->transact(SET_PROPERTY_BYTE_ARRAY, data, &reply);
 if (status != OK) {
 return status;
 }

 return reply.readInt32();
 }

Project: Android

 virtual status_t setPropertyString(String8 const &name, String8 const &value) const {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        data.writeString8(name);
        data.writeString8(value);
 status_t status = remote()->transact(SET_PROPERTY_STRING, data, &reply);
 if (status != OK) {
 return status;
 }

 return reply.readInt32();
 }

Project: Android

 virtual status_t sign(Vector<uint8_t> const &sessionId,
 Vector<uint8_t> const &keyId,
 Vector<uint8_t> const &message,
 Vector<uint8_t> &signature) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, sessionId);
        writeVector(data, keyId);
        writeVector(data, message);

 status_t status = remote()->transact(SIGN, data, &reply);
 if (status != OK) {
 return status;
 }
        readVector(reply, signature);

 return reply.readInt32();
 }

Project: Android

 virtual status_t signRSA(Vector<uint8_t> const &sessionId,
 String8 const &algorithm,
 Vector<uint8_t> const &message,
 Vector<uint8_t> const &wrappedKey,
 Vector<uint8_t> &signature) {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

        writeVector(data, sessionId);
        data.writeString8(algorithm);
        writeVector(data, message);
        writeVector(data, wrappedKey);

 status_t status = remote()->transact(SIGN_RSA, data, &reply);
 if (status != OK) {
 return status;
 }
        readVector(reply, signature);

 return reply.readInt32();
 }

Project: Android

 virtual status_t unprovisionDevice() {
 Parcel data, reply;
        data.writeInterfaceToken(IDrm::getInterfaceDescriptor());

 status_t status = remote()->transact(UNPROVISION_DEVICE, data, &reply);
 if (status != OK) {
 return status;
 }

 return reply.readInt32();
 }

Project: Android

 void writeVector(Parcel &data, Vector<uint8_t> const &vector) const {
        data.writeInt32(vector.size());
        data.write(vector.array(), vector.size());
 }

Project: Android

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