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