Loading cmds/stagefright/SimplePlayer.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <gui/SurfaceTextureClient.h> #include <media/AudioTrack.h> #include <media/ICrypto.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> Loading Loading @@ -318,7 +319,9 @@ status_t SimplePlayer::onPrepare() { CHECK(state->mCodec != NULL); err = state->mCodec->configure( format, mNativeWindow->getSurfaceTextureClient(), format, mNativeWindow->getSurfaceTextureClient(), NULL /* crypto */, 0 /* flags */); CHECK_EQ(err, (status_t)OK); Loading cmds/stagefright/codec.cpp +66 −3 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ #include "SimplePlayer.h" #include <binder/IServiceManager.h> #include <binder/ProcessState.h> #include <media/ICrypto.h> #include <media/IMediaPlayerService.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/ALooper.h> Loading Loading @@ -59,6 +61,33 @@ struct CodecState { bool mIsAudio; }; static sp<ICrypto> makeCrypto( const uint8_t uuid[16], const void *data, size_t size) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(String16("media.player")); sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); CHECK(service != NULL); sp<ICrypto> crypto = service->makeCrypto(); if (crypto == NULL || crypto->initCheck() != OK) { return NULL; } status_t err = crypto->createPlugin(uuid, data, size); if (err != OK) { return NULL; } return crypto; } } // namespace android static int decode( Loading @@ -78,6 +107,8 @@ static int decode( return 1; } sp<ICrypto> crypto; KeyedVector<size_t, CodecState> stateByTrack; bool haveAudio = false; Loading Loading @@ -113,7 +144,38 @@ static int decode( state->mNumBuffersDecoded = 0; state->mIsAudio = isAudio; if (decryptInputBuffers && !isAudio) { if (decryptInputBuffers && crypto == NULL) { sp<ABuffer> emm; CHECK(format->findBuffer("emm", &emm)); sp<ABuffer> ecm; CHECK(format->findBuffer("ecm", &ecm)); struct WVOpaqueInitData { uint8_t mEMM[16]; uint8_t mECM[32]; } opaque; CHECK_EQ(emm->size(), sizeof(opaque.mEMM)); memcpy(opaque.mEMM, emm->data(), emm->size()); CHECK_EQ(ecm->size(), 80u); // bytes 16..47 of the original ecm stream data. memcpy(opaque.mECM, ecm->data() + 16, 32); static const uint8_t kUUIDWidevine[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; crypto = makeCrypto(kUUIDWidevine, &opaque, sizeof(opaque)); CHECK(crypto != NULL); CHECK_EQ(crypto->initCheck(), (status_t)OK); } if (decryptInputBuffers && crypto->requiresSecureDecoderComponent(mime.c_str())) { static const MediaCodecList *list = MediaCodecList::getInstance(); ssize_t index = Loading @@ -137,7 +199,8 @@ static int decode( err = state->mCodec->configure( format, isVideo ? surface : NULL, decryptInputBuffers ? MediaCodec::CONFIGURE_FLAG_SECURE : 0); crypto, 0 /* flags */); CHECK_EQ(err, (status_t)OK); Loading include/media/ICrypto.h +17 −16 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <binder/IInterface.h> #include <media/stagefright/foundation/ABase.h> #include <media/hardware/CryptoAPI.h> #ifndef ANDROID_ICRYPTO_H_ Loading @@ -26,26 +27,26 @@ namespace android { struct ICrypto : public IInterface { DECLARE_META_INTERFACE(Crypto); virtual status_t initialize() = 0; virtual status_t terminate() = 0; virtual status_t initCheck() const = 0; virtual status_t setEntitlementKey( const void *key, size_t keyLength) = 0; virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const = 0; virtual status_t setEntitlementControlMessage( const void *msg, size_t msgLength) = 0; virtual status_t createPlugin( const uint8_t uuid[16], const void *data, size_t size) = 0; // "dstData" is in media_server's address space (but inaccessible). virtual ssize_t decryptVideo( const void *iv, size_t ivLength, const void *srcData, size_t srcDataSize, void *dstData, size_t dstDataOffset) = 0; virtual status_t destroyPlugin() = 0; // "dstData" is in the calling process' address space. virtual ssize_t decryptAudio( const void *iv, size_t ivLength, const void *srcData, size_t srcDataSize, void *dstData, size_t dstDataSize) = 0; virtual bool requiresSecureDecoderComponent( const char *mime) const = 0; virtual status_t decrypt( bool secure, const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode, const void *srcPtr, const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, void *dstPtr) = 0; private: DISALLOW_EVIL_CONSTRUCTORS(ICrypto); Loading include/media/stagefright/MediaCodec.h +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ struct SurfaceTextureClient; struct MediaCodec : public AHandler { enum ConfigureFlags { CONFIGURE_FLAG_ENCODE = 1, CONFIGURE_FLAG_SECURE = 2, }; enum BufferFlags { Loading @@ -53,6 +52,7 @@ struct MediaCodec : public AHandler { status_t configure( const sp<AMessage> &format, const sp<SurfaceTextureClient> &nativeWindow, const sp<ICrypto> &crypto, uint32_t flags); status_t start(); Loading media/libmedia/ICrypto.cpp +122 −147 Original line number Diff line number Diff line Loading @@ -25,12 +25,12 @@ namespace android { enum { INITIALIZE = IBinder::FIRST_CALL_TRANSACTION, TERMINATE, SET_ENTITLEMENT_KEY, SET_ECM, DECRYPT_VIDEO, DECRYPT_AUDIO, INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION, IS_CRYPTO_SUPPORTED, CREATE_PLUGIN, DESTROY_PLUGIN, REQUIRES_SECURE_COMPONENT, DECRYPT, }; struct BpCrypto : public BpInterface<ICrypto> { Loading @@ -38,104 +38,97 @@ struct BpCrypto : public BpInterface<ICrypto> { : BpInterface<ICrypto>(impl) { } virtual status_t initialize() { virtual status_t initCheck() const { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); remote()->transact(INITIALIZE, data, &reply); remote()->transact(INIT_CHECK, data, &reply); return reply.readInt32(); } virtual status_t terminate() { virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); remote()->transact(TERMINATE, data, &reply); data.write(uuid, 16); remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply); return reply.readInt32(); return reply.readInt32() != 0; } virtual status_t setEntitlementKey( const void *key, size_t keyLength) { virtual status_t createPlugin( const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); data.writeInt32(keyLength); data.write(key, keyLength); remote()->transact(SET_ENTITLEMENT_KEY, data, &reply); data.write(uuid, 16); data.writeInt32(opaqueSize); data.write(opaqueData, opaqueSize); remote()->transact(CREATE_PLUGIN, data, &reply); return reply.readInt32(); } virtual status_t setEntitlementControlMessage( const void *msg, size_t msgLength) { virtual status_t destroyPlugin() { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); data.writeInt32(msgLength); data.write(msg, msgLength); remote()->transact(SET_ECM, data, &reply); remote()->transact(DESTROY_PLUGIN, data, &reply); return reply.readInt32(); } virtual ssize_t decryptVideo( const void *iv, size_t ivLength, const void *srcData, size_t srcDataSize, void *dstData, size_t dstDataOffset) { virtual bool requiresSecureDecoderComponent( const char *mime) const { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); if (iv == NULL) { if (ivLength > 0) { return -EINVAL; } data.writeInt32(-1); } else { data.writeInt32(ivLength); data.write(iv, ivLength); } data.writeCString(mime); remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply); data.writeInt32(srcDataSize); data.write(srcData, srcDataSize); data.writeIntPtr((intptr_t)dstData); data.writeInt32(dstDataOffset); remote()->transact(DECRYPT_VIDEO, data, &reply); return reply.readInt32(); return reply.readInt32() != 0; } virtual ssize_t decryptAudio( const void *iv, size_t ivLength, const void *srcData, size_t srcDataSize, void *dstData, size_t dstDataSize) { virtual status_t decrypt( bool secure, const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode, const void *srcPtr, const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, void *dstPtr) { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); if (iv == NULL) { if (ivLength > 0) { return -EINVAL; data.writeInt32(secure); data.writeInt32(mode); 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(-1); } else { data.writeInt32(ivLength); data.write(iv, ivLength); } data.writeInt32(totalSize); data.write(srcPtr, totalSize); data.writeInt32(numSubSamples); data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); data.writeInt32(srcDataSize); data.write(srcData, srcDataSize); data.writeInt32(dstDataSize); if (secure) { data.writeIntPtr((intptr_t)dstPtr); } remote()->transact(DECRYPT_AUDIO, data, &reply); remote()->transact(DECRYPT, data, &reply); ssize_t res = reply.readInt32(); status_t result = reply.readInt32(); if (res <= 0) { return res; if (result != OK) { return result; } reply.read(dstData, res); if (!secure) { reply.read(dstPtr, totalSize); } return res; return OK; } private: Loading @@ -149,138 +142,120 @@ IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto"); status_t BnCrypto::onTransact( uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { switch (code) { case INITIALIZE: case INIT_CHECK: { CHECK_INTERFACE(ICrypto, data, reply); reply->writeInt32(initialize()); reply->writeInt32(initCheck()); return OK; } case TERMINATE: case IS_CRYPTO_SUPPORTED: { CHECK_INTERFACE(ICrypto, data, reply); reply->writeInt32(terminate()); uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); reply->writeInt32(isCryptoSchemeSupported(uuid)); return OK; } case SET_ENTITLEMENT_KEY: case CREATE_PLUGIN: { CHECK_INTERFACE(ICrypto, data, reply); size_t keyLength = data.readInt32(); void *key = malloc(keyLength); data.read(key, keyLength); uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); reply->writeInt32(setEntitlementKey(key, keyLength)); size_t opaqueSize = data.readInt32(); void *opaqueData = malloc(opaqueSize); data.read(opaqueData, opaqueSize); free(key); key = NULL; reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); free(opaqueData); opaqueData = NULL; return OK; } case SET_ECM: case DESTROY_PLUGIN: { CHECK_INTERFACE(ICrypto, data, reply); size_t msgLength = data.readInt32(); void *msg = malloc(msgLength); data.read(msg, msgLength); reply->writeInt32(setEntitlementControlMessage(msg, msgLength)); free(msg); msg = NULL; reply->writeInt32(destroyPlugin()); return OK; } case DECRYPT_VIDEO: case REQUIRES_SECURE_COMPONENT: { CHECK_INTERFACE(ICrypto, data, reply); void *iv = NULL; const char *mime = data.readCString(); reply->writeInt32(requiresSecureDecoderComponent(mime)); int32_t ivLength = data.readInt32(); if (ivLength >= 0) { iv = malloc(ivLength); data.read(iv, ivLength); return OK; } size_t srcDataSize = data.readInt32(); void *srcData = malloc(srcDataSize); data.read(srcData, srcDataSize); case DECRYPT: { CHECK_INTERFACE(ICrypto, data, reply); void *dstData = (void *)data.readIntPtr(); size_t dstDataOffset = data.readInt32(); bool secure = data.readInt32() != 0; CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); reply->writeInt32( decryptVideo( iv, ivLength < 0 ? 0 : ivLength, srcData, srcDataSize, dstData, dstDataOffset)); uint8_t key[16]; data.read(key, sizeof(key)); free(srcData); srcData = NULL; uint8_t iv[16]; data.read(iv, sizeof(iv)); if (iv != NULL) { free(iv); iv = NULL; } size_t totalSize = data.readInt32(); void *srcData = malloc(totalSize); data.read(srcData, totalSize); return OK; } int32_t numSubSamples = data.readInt32(); case DECRYPT_AUDIO: { CHECK_INTERFACE(ICrypto, data, reply); CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[numSubSamples]; void *iv = NULL; data.read( subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); int32_t ivLength = data.readInt32(); if (ivLength >= 0) { iv = malloc(ivLength); data.read(iv, ivLength); void *dstPtr; if (secure) { dstPtr = (void *)data.readIntPtr(); } else { dstPtr = malloc(totalSize); } size_t srcDataSize = data.readInt32(); void *srcData = malloc(srcDataSize); data.read(srcData, srcDataSize); size_t dstDataSize = data.readInt32(); void *dstData = malloc(dstDataSize); ssize_t res = decryptAudio( status_t err = decrypt( secure, key, iv, ivLength < 0 ? 0 : ivLength, mode, srcData, srcDataSize, dstData, dstDataSize); subSamples, numSubSamples, dstPtr); reply->writeInt32(res); reply->writeInt32(err); if (res > 0) { reply->write(dstData, res); if (!secure) { if (err == OK) { reply->write(dstPtr, totalSize); } free(dstData); dstData = NULL; free(dstPtr); dstPtr = NULL; } delete[] subSamples; subSamples = NULL; free(srcData); srcData = NULL; if (iv != NULL) { free(iv); iv = NULL; } return OK; } Loading Loading
cmds/stagefright/SimplePlayer.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <gui/SurfaceTextureClient.h> #include <media/AudioTrack.h> #include <media/ICrypto.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> Loading Loading @@ -318,7 +319,9 @@ status_t SimplePlayer::onPrepare() { CHECK(state->mCodec != NULL); err = state->mCodec->configure( format, mNativeWindow->getSurfaceTextureClient(), format, mNativeWindow->getSurfaceTextureClient(), NULL /* crypto */, 0 /* flags */); CHECK_EQ(err, (status_t)OK); Loading
cmds/stagefright/codec.cpp +66 −3 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ #include "SimplePlayer.h" #include <binder/IServiceManager.h> #include <binder/ProcessState.h> #include <media/ICrypto.h> #include <media/IMediaPlayerService.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/ALooper.h> Loading Loading @@ -59,6 +61,33 @@ struct CodecState { bool mIsAudio; }; static sp<ICrypto> makeCrypto( const uint8_t uuid[16], const void *data, size_t size) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder = sm->getService(String16("media.player")); sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder); CHECK(service != NULL); sp<ICrypto> crypto = service->makeCrypto(); if (crypto == NULL || crypto->initCheck() != OK) { return NULL; } status_t err = crypto->createPlugin(uuid, data, size); if (err != OK) { return NULL; } return crypto; } } // namespace android static int decode( Loading @@ -78,6 +107,8 @@ static int decode( return 1; } sp<ICrypto> crypto; KeyedVector<size_t, CodecState> stateByTrack; bool haveAudio = false; Loading Loading @@ -113,7 +144,38 @@ static int decode( state->mNumBuffersDecoded = 0; state->mIsAudio = isAudio; if (decryptInputBuffers && !isAudio) { if (decryptInputBuffers && crypto == NULL) { sp<ABuffer> emm; CHECK(format->findBuffer("emm", &emm)); sp<ABuffer> ecm; CHECK(format->findBuffer("ecm", &ecm)); struct WVOpaqueInitData { uint8_t mEMM[16]; uint8_t mECM[32]; } opaque; CHECK_EQ(emm->size(), sizeof(opaque.mEMM)); memcpy(opaque.mEMM, emm->data(), emm->size()); CHECK_EQ(ecm->size(), 80u); // bytes 16..47 of the original ecm stream data. memcpy(opaque.mECM, ecm->data() + 16, 32); static const uint8_t kUUIDWidevine[16] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; crypto = makeCrypto(kUUIDWidevine, &opaque, sizeof(opaque)); CHECK(crypto != NULL); CHECK_EQ(crypto->initCheck(), (status_t)OK); } if (decryptInputBuffers && crypto->requiresSecureDecoderComponent(mime.c_str())) { static const MediaCodecList *list = MediaCodecList::getInstance(); ssize_t index = Loading @@ -137,7 +199,8 @@ static int decode( err = state->mCodec->configure( format, isVideo ? surface : NULL, decryptInputBuffers ? MediaCodec::CONFIGURE_FLAG_SECURE : 0); crypto, 0 /* flags */); CHECK_EQ(err, (status_t)OK); Loading
include/media/ICrypto.h +17 −16 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <binder/IInterface.h> #include <media/stagefright/foundation/ABase.h> #include <media/hardware/CryptoAPI.h> #ifndef ANDROID_ICRYPTO_H_ Loading @@ -26,26 +27,26 @@ namespace android { struct ICrypto : public IInterface { DECLARE_META_INTERFACE(Crypto); virtual status_t initialize() = 0; virtual status_t terminate() = 0; virtual status_t initCheck() const = 0; virtual status_t setEntitlementKey( const void *key, size_t keyLength) = 0; virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const = 0; virtual status_t setEntitlementControlMessage( const void *msg, size_t msgLength) = 0; virtual status_t createPlugin( const uint8_t uuid[16], const void *data, size_t size) = 0; // "dstData" is in media_server's address space (but inaccessible). virtual ssize_t decryptVideo( const void *iv, size_t ivLength, const void *srcData, size_t srcDataSize, void *dstData, size_t dstDataOffset) = 0; virtual status_t destroyPlugin() = 0; // "dstData" is in the calling process' address space. virtual ssize_t decryptAudio( const void *iv, size_t ivLength, const void *srcData, size_t srcDataSize, void *dstData, size_t dstDataSize) = 0; virtual bool requiresSecureDecoderComponent( const char *mime) const = 0; virtual status_t decrypt( bool secure, const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode, const void *srcPtr, const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, void *dstPtr) = 0; private: DISALLOW_EVIL_CONSTRUCTORS(ICrypto); Loading
include/media/stagefright/MediaCodec.h +1 −1 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ struct SurfaceTextureClient; struct MediaCodec : public AHandler { enum ConfigureFlags { CONFIGURE_FLAG_ENCODE = 1, CONFIGURE_FLAG_SECURE = 2, }; enum BufferFlags { Loading @@ -53,6 +52,7 @@ struct MediaCodec : public AHandler { status_t configure( const sp<AMessage> &format, const sp<SurfaceTextureClient> &nativeWindow, const sp<ICrypto> &crypto, uint32_t flags); status_t start(); Loading
media/libmedia/ICrypto.cpp +122 −147 Original line number Diff line number Diff line Loading @@ -25,12 +25,12 @@ namespace android { enum { INITIALIZE = IBinder::FIRST_CALL_TRANSACTION, TERMINATE, SET_ENTITLEMENT_KEY, SET_ECM, DECRYPT_VIDEO, DECRYPT_AUDIO, INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION, IS_CRYPTO_SUPPORTED, CREATE_PLUGIN, DESTROY_PLUGIN, REQUIRES_SECURE_COMPONENT, DECRYPT, }; struct BpCrypto : public BpInterface<ICrypto> { Loading @@ -38,104 +38,97 @@ struct BpCrypto : public BpInterface<ICrypto> { : BpInterface<ICrypto>(impl) { } virtual status_t initialize() { virtual status_t initCheck() const { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); remote()->transact(INITIALIZE, data, &reply); remote()->transact(INIT_CHECK, data, &reply); return reply.readInt32(); } virtual status_t terminate() { virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); remote()->transact(TERMINATE, data, &reply); data.write(uuid, 16); remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply); return reply.readInt32(); return reply.readInt32() != 0; } virtual status_t setEntitlementKey( const void *key, size_t keyLength) { virtual status_t createPlugin( const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); data.writeInt32(keyLength); data.write(key, keyLength); remote()->transact(SET_ENTITLEMENT_KEY, data, &reply); data.write(uuid, 16); data.writeInt32(opaqueSize); data.write(opaqueData, opaqueSize); remote()->transact(CREATE_PLUGIN, data, &reply); return reply.readInt32(); } virtual status_t setEntitlementControlMessage( const void *msg, size_t msgLength) { virtual status_t destroyPlugin() { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); data.writeInt32(msgLength); data.write(msg, msgLength); remote()->transact(SET_ECM, data, &reply); remote()->transact(DESTROY_PLUGIN, data, &reply); return reply.readInt32(); } virtual ssize_t decryptVideo( const void *iv, size_t ivLength, const void *srcData, size_t srcDataSize, void *dstData, size_t dstDataOffset) { virtual bool requiresSecureDecoderComponent( const char *mime) const { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); if (iv == NULL) { if (ivLength > 0) { return -EINVAL; } data.writeInt32(-1); } else { data.writeInt32(ivLength); data.write(iv, ivLength); } data.writeCString(mime); remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply); data.writeInt32(srcDataSize); data.write(srcData, srcDataSize); data.writeIntPtr((intptr_t)dstData); data.writeInt32(dstDataOffset); remote()->transact(DECRYPT_VIDEO, data, &reply); return reply.readInt32(); return reply.readInt32() != 0; } virtual ssize_t decryptAudio( const void *iv, size_t ivLength, const void *srcData, size_t srcDataSize, void *dstData, size_t dstDataSize) { virtual status_t decrypt( bool secure, const uint8_t key[16], const uint8_t iv[16], CryptoPlugin::Mode mode, const void *srcPtr, const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, void *dstPtr) { Parcel data, reply; data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); if (iv == NULL) { if (ivLength > 0) { return -EINVAL; data.writeInt32(secure); data.writeInt32(mode); 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(-1); } else { data.writeInt32(ivLength); data.write(iv, ivLength); } data.writeInt32(totalSize); data.write(srcPtr, totalSize); data.writeInt32(numSubSamples); data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); data.writeInt32(srcDataSize); data.write(srcData, srcDataSize); data.writeInt32(dstDataSize); if (secure) { data.writeIntPtr((intptr_t)dstPtr); } remote()->transact(DECRYPT_AUDIO, data, &reply); remote()->transact(DECRYPT, data, &reply); ssize_t res = reply.readInt32(); status_t result = reply.readInt32(); if (res <= 0) { return res; if (result != OK) { return result; } reply.read(dstData, res); if (!secure) { reply.read(dstPtr, totalSize); } return res; return OK; } private: Loading @@ -149,138 +142,120 @@ IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto"); status_t BnCrypto::onTransact( uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { switch (code) { case INITIALIZE: case INIT_CHECK: { CHECK_INTERFACE(ICrypto, data, reply); reply->writeInt32(initialize()); reply->writeInt32(initCheck()); return OK; } case TERMINATE: case IS_CRYPTO_SUPPORTED: { CHECK_INTERFACE(ICrypto, data, reply); reply->writeInt32(terminate()); uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); reply->writeInt32(isCryptoSchemeSupported(uuid)); return OK; } case SET_ENTITLEMENT_KEY: case CREATE_PLUGIN: { CHECK_INTERFACE(ICrypto, data, reply); size_t keyLength = data.readInt32(); void *key = malloc(keyLength); data.read(key, keyLength); uint8_t uuid[16]; data.read(uuid, sizeof(uuid)); reply->writeInt32(setEntitlementKey(key, keyLength)); size_t opaqueSize = data.readInt32(); void *opaqueData = malloc(opaqueSize); data.read(opaqueData, opaqueSize); free(key); key = NULL; reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); free(opaqueData); opaqueData = NULL; return OK; } case SET_ECM: case DESTROY_PLUGIN: { CHECK_INTERFACE(ICrypto, data, reply); size_t msgLength = data.readInt32(); void *msg = malloc(msgLength); data.read(msg, msgLength); reply->writeInt32(setEntitlementControlMessage(msg, msgLength)); free(msg); msg = NULL; reply->writeInt32(destroyPlugin()); return OK; } case DECRYPT_VIDEO: case REQUIRES_SECURE_COMPONENT: { CHECK_INTERFACE(ICrypto, data, reply); void *iv = NULL; const char *mime = data.readCString(); reply->writeInt32(requiresSecureDecoderComponent(mime)); int32_t ivLength = data.readInt32(); if (ivLength >= 0) { iv = malloc(ivLength); data.read(iv, ivLength); return OK; } size_t srcDataSize = data.readInt32(); void *srcData = malloc(srcDataSize); data.read(srcData, srcDataSize); case DECRYPT: { CHECK_INTERFACE(ICrypto, data, reply); void *dstData = (void *)data.readIntPtr(); size_t dstDataOffset = data.readInt32(); bool secure = data.readInt32() != 0; CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); reply->writeInt32( decryptVideo( iv, ivLength < 0 ? 0 : ivLength, srcData, srcDataSize, dstData, dstDataOffset)); uint8_t key[16]; data.read(key, sizeof(key)); free(srcData); srcData = NULL; uint8_t iv[16]; data.read(iv, sizeof(iv)); if (iv != NULL) { free(iv); iv = NULL; } size_t totalSize = data.readInt32(); void *srcData = malloc(totalSize); data.read(srcData, totalSize); return OK; } int32_t numSubSamples = data.readInt32(); case DECRYPT_AUDIO: { CHECK_INTERFACE(ICrypto, data, reply); CryptoPlugin::SubSample *subSamples = new CryptoPlugin::SubSample[numSubSamples]; void *iv = NULL; data.read( subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); int32_t ivLength = data.readInt32(); if (ivLength >= 0) { iv = malloc(ivLength); data.read(iv, ivLength); void *dstPtr; if (secure) { dstPtr = (void *)data.readIntPtr(); } else { dstPtr = malloc(totalSize); } size_t srcDataSize = data.readInt32(); void *srcData = malloc(srcDataSize); data.read(srcData, srcDataSize); size_t dstDataSize = data.readInt32(); void *dstData = malloc(dstDataSize); ssize_t res = decryptAudio( status_t err = decrypt( secure, key, iv, ivLength < 0 ? 0 : ivLength, mode, srcData, srcDataSize, dstData, dstDataSize); subSamples, numSubSamples, dstPtr); reply->writeInt32(res); reply->writeInt32(err); if (res > 0) { reply->write(dstData, res); if (!secure) { if (err == OK) { reply->write(dstPtr, totalSize); } free(dstData); dstData = NULL; free(dstPtr); dstPtr = NULL; } delete[] subSamples; subSamples = NULL; free(srcData); srcData = NULL; if (iv != NULL) { free(iv); iv = NULL; } return OK; } Loading