ICrypto.cpp revision 4b75a9c8b93a90749bc5d22912ad0d96c12f4ecf
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 <media/ICrypto.h> 23#include <media/stagefright/foundation/ADebug.h> 24 25namespace android { 26 27enum { 28 INIT_CHECK = IBinder::FIRST_CALL_TRANSACTION, 29 IS_CRYPTO_SUPPORTED, 30 CREATE_PLUGIN, 31 DESTROY_PLUGIN, 32 REQUIRES_SECURE_COMPONENT, 33 DECRYPT, 34}; 35 36struct BpCrypto : public BpInterface<ICrypto> { 37 BpCrypto(const sp<IBinder> &impl) 38 : BpInterface<ICrypto>(impl) { 39 } 40 41 virtual status_t initCheck() const { 42 Parcel data, reply; 43 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 44 remote()->transact(INIT_CHECK, data, &reply); 45 46 return reply.readInt32(); 47 } 48 49 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) const { 50 Parcel data, reply; 51 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 52 data.write(uuid, 16); 53 remote()->transact(IS_CRYPTO_SUPPORTED, data, &reply); 54 55 return reply.readInt32() != 0; 56 } 57 58 virtual status_t createPlugin( 59 const uint8_t uuid[16], const void *opaqueData, size_t opaqueSize) { 60 Parcel data, reply; 61 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 62 data.write(uuid, 16); 63 data.writeInt32(opaqueSize); 64 data.write(opaqueData, opaqueSize); 65 remote()->transact(CREATE_PLUGIN, data, &reply); 66 67 return reply.readInt32(); 68 } 69 70 virtual status_t destroyPlugin() { 71 Parcel data, reply; 72 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 73 remote()->transact(DESTROY_PLUGIN, data, &reply); 74 75 return reply.readInt32(); 76 } 77 78 virtual bool requiresSecureDecoderComponent( 79 const char *mime) const { 80 Parcel data, reply; 81 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 82 data.writeCString(mime); 83 remote()->transact(REQUIRES_SECURE_COMPONENT, data, &reply); 84 85 return reply.readInt32() != 0; 86 } 87 88 virtual status_t decrypt( 89 bool secure, 90 const uint8_t key[16], 91 const uint8_t iv[16], 92 CryptoPlugin::Mode mode, 93 const void *srcPtr, 94 const CryptoPlugin::SubSample *subSamples, size_t numSubSamples, 95 void *dstPtr) { 96 Parcel data, reply; 97 data.writeInterfaceToken(ICrypto::getInterfaceDescriptor()); 98 data.writeInt32(secure); 99 data.writeInt32(mode); 100 101 static const uint8_t kDummy[16] = { 0 }; 102 103 if (key == NULL) { 104 key = kDummy; 105 } 106 107 if (iv == NULL) { 108 iv = kDummy; 109 } 110 111 data.write(key, 16); 112 data.write(iv, 16); 113 114 size_t totalSize = 0; 115 for (size_t i = 0; i < numSubSamples; ++i) { 116 totalSize += subSamples[i].mNumBytesOfEncryptedData; 117 totalSize += subSamples[i].mNumBytesOfClearData; 118 } 119 120 data.writeInt32(totalSize); 121 data.write(srcPtr, totalSize); 122 123 data.writeInt32(numSubSamples); 124 data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples); 125 126 if (secure) { 127 data.writeIntPtr((intptr_t)dstPtr); 128 } 129 130 remote()->transact(DECRYPT, data, &reply); 131 132 status_t result = reply.readInt32(); 133 134 if (result != OK) { 135 return result; 136 } 137 138 if (!secure) { 139 reply.read(dstPtr, totalSize); 140 } 141 142 return OK; 143 } 144 145private: 146 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto); 147}; 148 149IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto"); 150 151//////////////////////////////////////////////////////////////////////////////// 152 153status_t BnCrypto::onTransact( 154 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 155 switch (code) { 156 case INIT_CHECK: 157 { 158 CHECK_INTERFACE(ICrypto, data, reply); 159 reply->writeInt32(initCheck()); 160 161 return OK; 162 } 163 164 case IS_CRYPTO_SUPPORTED: 165 { 166 CHECK_INTERFACE(ICrypto, data, reply); 167 uint8_t uuid[16]; 168 data.read(uuid, sizeof(uuid)); 169 reply->writeInt32(isCryptoSchemeSupported(uuid)); 170 171 return OK; 172 } 173 174 case CREATE_PLUGIN: 175 { 176 CHECK_INTERFACE(ICrypto, data, reply); 177 178 uint8_t uuid[16]; 179 data.read(uuid, sizeof(uuid)); 180 181 size_t opaqueSize = data.readInt32(); 182 void *opaqueData = malloc(opaqueSize); 183 data.read(opaqueData, opaqueSize); 184 185 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); 186 187 free(opaqueData); 188 opaqueData = NULL; 189 190 return OK; 191 } 192 193 case DESTROY_PLUGIN: 194 { 195 CHECK_INTERFACE(ICrypto, data, reply); 196 reply->writeInt32(destroyPlugin()); 197 198 return OK; 199 } 200 201 case REQUIRES_SECURE_COMPONENT: 202 { 203 CHECK_INTERFACE(ICrypto, data, reply); 204 205 const char *mime = data.readCString(); 206 reply->writeInt32(requiresSecureDecoderComponent(mime)); 207 208 return OK; 209 } 210 211 case DECRYPT: 212 { 213 CHECK_INTERFACE(ICrypto, data, reply); 214 215 bool secure = data.readInt32() != 0; 216 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); 217 218 uint8_t key[16]; 219 data.read(key, sizeof(key)); 220 221 uint8_t iv[16]; 222 data.read(iv, sizeof(iv)); 223 224 size_t totalSize = data.readInt32(); 225 void *srcData = malloc(totalSize); 226 data.read(srcData, totalSize); 227 228 int32_t numSubSamples = data.readInt32(); 229 230 CryptoPlugin::SubSample *subSamples = 231 new CryptoPlugin::SubSample[numSubSamples]; 232 233 data.read( 234 subSamples, 235 sizeof(CryptoPlugin::SubSample) * numSubSamples); 236 237 void *dstPtr; 238 if (secure) { 239 dstPtr = (void *)data.readIntPtr(); 240 } else { 241 dstPtr = malloc(totalSize); 242 } 243 244 status_t err = decrypt( 245 secure, 246 key, 247 iv, 248 mode, 249 srcData, 250 subSamples, numSubSamples, 251 dstPtr); 252 253 reply->writeInt32(err); 254 255 if (!secure) { 256 if (err == OK) { 257 reply->write(dstPtr, totalSize); 258 } 259 260 free(dstPtr); 261 dstPtr = NULL; 262 } 263 264 delete[] subSamples; 265 subSamples = NULL; 266 267 free(srcData); 268 srcData = NULL; 269 270 return OK; 271 } 272 273 default: 274 return BBinder::onTransact(code, data, reply, flags); 275 } 276} 277 278} // namespace android 279 280