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