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 27 namespace android { 28 29 enum { 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 38 struct 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]) { 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 ssize_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 ssize_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 (!secure && result >= 0) { 146 reply.read(dstPtr, result); 147 } 148 149 return result; 150 } 151 152 private: 153 DISALLOW_EVIL_CONSTRUCTORS(BpCrypto); 154 }; 155 156 IMPLEMENT_META_INTERFACE(Crypto, "android.hardware.ICrypto"); 157 158 //////////////////////////////////////////////////////////////////////////////// 159 160 status_t BnCrypto::onTransact( 161 uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) { 162 switch (code) { 163 case INIT_CHECK: 164 { 165 CHECK_INTERFACE(ICrypto, data, reply); 166 reply->writeInt32(initCheck()); 167 168 return OK; 169 } 170 171 case IS_CRYPTO_SUPPORTED: 172 { 173 CHECK_INTERFACE(ICrypto, data, reply); 174 uint8_t uuid[16]; 175 data.read(uuid, sizeof(uuid)); 176 reply->writeInt32(isCryptoSchemeSupported(uuid)); 177 178 return OK; 179 } 180 181 case CREATE_PLUGIN: 182 { 183 CHECK_INTERFACE(ICrypto, data, reply); 184 185 uint8_t uuid[16]; 186 data.read(uuid, sizeof(uuid)); 187 188 size_t opaqueSize = data.readInt32(); 189 void *opaqueData = NULL; 190 191 if (opaqueSize > 0) { 192 opaqueData = malloc(opaqueSize); 193 data.read(opaqueData, opaqueSize); 194 } 195 196 reply->writeInt32(createPlugin(uuid, opaqueData, opaqueSize)); 197 198 if (opaqueData != NULL) { 199 free(opaqueData); 200 opaqueData = NULL; 201 } 202 203 return OK; 204 } 205 206 case DESTROY_PLUGIN: 207 { 208 CHECK_INTERFACE(ICrypto, data, reply); 209 reply->writeInt32(destroyPlugin()); 210 211 return OK; 212 } 213 214 case REQUIRES_SECURE_COMPONENT: 215 { 216 CHECK_INTERFACE(ICrypto, data, reply); 217 218 const char *mime = data.readCString(); 219 reply->writeInt32(requiresSecureDecoderComponent(mime)); 220 221 return OK; 222 } 223 224 case DECRYPT: 225 { 226 CHECK_INTERFACE(ICrypto, data, reply); 227 228 bool secure = data.readInt32() != 0; 229 CryptoPlugin::Mode mode = (CryptoPlugin::Mode)data.readInt32(); 230 231 uint8_t key[16]; 232 data.read(key, sizeof(key)); 233 234 uint8_t iv[16]; 235 data.read(iv, sizeof(iv)); 236 237 size_t totalSize = data.readInt32(); 238 void *srcData = malloc(totalSize); 239 data.read(srcData, totalSize); 240 241 int32_t numSubSamples = data.readInt32(); 242 243 CryptoPlugin::SubSample *subSamples = 244 new CryptoPlugin::SubSample[numSubSamples]; 245 246 data.read( 247 subSamples, 248 sizeof(CryptoPlugin::SubSample) * numSubSamples); 249 250 void *dstPtr; 251 if (secure) { 252 dstPtr = (void *)data.readIntPtr(); 253 } else { 254 dstPtr = malloc(totalSize); 255 } 256 257 AString errorDetailMsg; 258 ssize_t result = decrypt( 259 secure, 260 key, 261 iv, 262 mode, 263 srcData, 264 subSamples, numSubSamples, 265 dstPtr, 266 &errorDetailMsg); 267 268 reply->writeInt32(result); 269 270 if (result >= ERROR_DRM_VENDOR_MIN 271 && result <= ERROR_DRM_VENDOR_MAX) { 272 reply->writeCString(errorDetailMsg.c_str()); 273 } 274 275 if (!secure) { 276 if (result >= 0) { 277 CHECK_LE(result, static_cast<ssize_t>(totalSize)); 278 reply->write(dstPtr, result); 279 } 280 free(dstPtr); 281 dstPtr = NULL; 282 } 283 284 delete[] subSamples; 285 subSamples = NULL; 286 287 free(srcData); 288 srcData = NULL; 289 290 return OK; 291 } 292 293 default: 294 return BBinder::onTransact(code, data, reply, flags); 295 } 296 } 297 298 } // namespace android 299 300