1 /* 2 * Copyright (C) 2013 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 #ifndef DRM_API_H_ 18 #define DRM_API_H_ 19 20 #include <utils/List.h> 21 #include <utils/String8.h> 22 #include <utils/Vector.h> 23 #include <utils/KeyedVector.h> 24 #include <utils/RefBase.h> 25 #include <utils/Mutex.h> 26 #include <media/stagefright/foundation/ABase.h> 27 28 // Loadable DrmEngine shared libraries should define the entry points 29 // createDrmFactory and createCryptoFactory as shown below: 30 // 31 // extern "C" { 32 // extern android::DrmFactory *createDrmFactory(); 33 // extern android::CryptoFactory *createCryptoFactory(); 34 // } 35 36 namespace android { 37 38 class DrmPlugin; 39 class DrmPluginListener; 40 41 // DRMs are implemented in DrmEngine plugins, which are dynamically 42 // loadable shared libraries that implement the entry points 43 // createDrmFactory and createCryptoFactory. createDrmFactory 44 // constructs and returns an instance of a DrmFactory object. Similarly, 45 // createCryptoFactory creates an instance of a CryptoFactory object. 46 // When a MediaCrypto or MediaDrm object needs to be constructed, all 47 // available DrmEngines present in the plugins directory on the device 48 // are scanned for a matching DrmEngine that can support the crypto 49 // scheme. When a match is found, the DrmEngine's createCryptoPlugin and 50 // createDrmPlugin methods are used to create CryptoPlugin or 51 // DrmPlugin instances to support that DRM scheme. 52 53 class DrmFactory { 54 public: DrmFactory()55 DrmFactory() {} ~DrmFactory()56 virtual ~DrmFactory() {} 57 58 // DrmFactory::isCryptoSchemeSupported can be called to determine 59 // if the plugin factory is able to construct plugins that support a 60 // given crypto scheme, which is specified by a UUID. 61 virtual bool isCryptoSchemeSupported(const uint8_t uuid[16]) = 0; 62 63 // DrmFactory::isContentTypeSupported can be called to determine 64 // if the plugin factory is able to construct plugins that support a 65 // given media container format specified by mimeType 66 virtual bool isContentTypeSupported(const String8 &mimeType) = 0; 67 68 // Construct a DrmPlugin for the crypto scheme specified by UUID. 69 virtual status_t createDrmPlugin( 70 const uint8_t uuid[16], DrmPlugin **plugin) = 0; 71 72 private: 73 DrmFactory(const DrmFactory &); 74 DrmFactory &operator=(const DrmFactory &); 75 }; 76 77 class DrmPlugin { 78 public: 79 enum EventType { 80 kDrmPluginEventProvisionRequired = 1, 81 kDrmPluginEventKeyNeeded, 82 kDrmPluginEventKeyExpired, 83 kDrmPluginEventVendorDefined, 84 kDrmPluginEventSessionReclaimed, 85 kDrmPluginEventExpirationUpdate, 86 kDrmPluginEventKeysChange, 87 }; 88 89 // Drm keys can be for offline content or for online streaming. 90 // Offline keys are persisted on the device and may be used when the device 91 // is disconnected from the network. The Release type is used to request 92 // that offline keys be no longer restricted to offline use. 93 enum KeyType { 94 kKeyType_Offline, 95 kKeyType_Streaming, 96 kKeyType_Release 97 }; 98 99 // Enumerate KeyRequestTypes to allow an app to determine the 100 // type of a key request returned from getKeyRequest. 101 enum KeyRequestType { 102 kKeyRequestType_Unknown, 103 kKeyRequestType_Initial, 104 kKeyRequestType_Renewal, 105 kKeyRequestType_Release 106 }; 107 108 // Enumerate KeyStatusTypes which indicate the state of a key 109 enum KeyStatusType 110 { 111 kKeyStatusType_Usable, 112 kKeyStatusType_Expired, 113 kKeyStatusType_OutputNotAllowed, 114 kKeyStatusType_StatusPending, 115 kKeyStatusType_InternalError 116 }; 117 118 // Used by sendKeysChange to report the usability status of each 119 // key to the app. 120 struct KeyStatus 121 { 122 Vector<uint8_t> mKeyId; 123 KeyStatusType mType; 124 }; 125 DrmPlugin()126 DrmPlugin() {} ~DrmPlugin()127 virtual ~DrmPlugin() {} 128 129 // Open a new session with the DrmPlugin object. A session ID is returned 130 // in the sessionId parameter. 131 virtual status_t openSession(Vector<uint8_t> &sessionId) = 0; 132 133 // Close a session on the DrmPlugin object. 134 virtual status_t closeSession(Vector<uint8_t> const &sessionId) = 0; 135 136 // A key request/response exchange occurs between the app and a License 137 // Server to obtain the keys required to decrypt the content. getKeyRequest() 138 // is used to obtain an opaque key request blob that is delivered to the 139 // license server. 140 // 141 // The scope parameter may be a sessionId or a keySetId, depending on the 142 // specified keyType. When the keyType is kKeyType_Offline or 143 // kKeyType_Streaming, scope should be set to the sessionId the keys will be 144 // provided to. When the keyType is kKeyType_Release, scope should be set to 145 // the keySetId of the keys being released. Releasing keys from a device 146 // invalidates them for all sessions. 147 // 148 // The init data passed to getKeyRequest is container-specific and its 149 // meaning is interpreted based on the mime type provided in the mimeType 150 // parameter to getKeyRequest. It could contain, for example, the content 151 // ID, key ID or other data obtained from the content metadata that is required 152 // in generating the key request. Init may be null when keyType is 153 // kKeyType_Release. 154 // 155 // mimeType identifies the mime type of the content 156 // 157 // keyType specifies if the keys are to be used for streaming or offline content 158 // 159 // optionalParameters are included in the key request message to allow a 160 // client application to provide additional message parameters to the server. 161 // 162 // If successful, the opaque key request blob is returned to the caller. 163 virtual status_t 164 getKeyRequest(Vector<uint8_t> const &scope, 165 Vector<uint8_t> const &initData, 166 String8 const &mimeType, KeyType keyType, 167 KeyedVector<String8, String8> const &optionalParameters, 168 Vector<uint8_t> &request, String8 &defaultUrl, 169 KeyRequestType *keyRequestType) = 0; 170 171 // 172 // After a key response is received by the app, it is provided to the 173 // Drm plugin using provideKeyResponse. 174 // 175 // scope may be a sessionId or a keySetId depending on the type of the 176 // response. Scope should be set to the sessionId when the response is 177 // for either streaming or offline key requests. Scope should be set to the 178 // keySetId when the response is for a release request. 179 // 180 // When the response is for an offline key request, a keySetId is returned 181 // in the keySetId vector parameter that can be used to later restore the 182 // keys to a new session with the method restoreKeys. When the response is 183 // for a streaming or release request, no keySetId is returned. 184 // 185 virtual status_t provideKeyResponse(Vector<uint8_t> const &scope, 186 Vector<uint8_t> const &response, 187 Vector<uint8_t> &keySetId) = 0; 188 189 // Remove the current keys from a session 190 virtual status_t removeKeys(Vector<uint8_t> const &sessionId) = 0; 191 192 // Restore persisted offline keys into a new session. keySetId identifies 193 // the keys to load, obtained from a prior call to provideKeyResponse(). 194 virtual status_t restoreKeys(Vector<uint8_t> const &sessionId, 195 Vector<uint8_t> const &keySetId) = 0; 196 197 // Request an informative description of the license for the session. The status 198 // is in the form of {name, value} pairs. Since DRM license policies vary by 199 // vendor, the specific status field names are determined by each DRM vendor. 200 // Refer to your DRM provider documentation for definitions of the field names 201 // for a particular DrmEngine. 202 virtual status_t 203 queryKeyStatus(Vector<uint8_t> const &sessionId, 204 KeyedVector<String8, String8> &infoMap) const = 0; 205 206 // A provision request/response exchange occurs between the app and a 207 // provisioning server to retrieve a device certificate. getProvisionRequest 208 // is used to obtain an opaque key request blob that is delivered to the 209 // provisioning server. 210 // 211 // If successful, the opaque provision request blob is returned to the caller. 212 virtual status_t getProvisionRequest(String8 const &cert_type, 213 String8 const &cert_authority, 214 Vector<uint8_t> &request, 215 String8 &defaultUrl) = 0; 216 217 // After a provision response is received by the app, it is provided to the 218 // Drm plugin using provideProvisionResponse. 219 virtual status_t provideProvisionResponse(Vector<uint8_t> const &response, 220 Vector<uint8_t> &certificate, 221 Vector<uint8_t> &wrapped_key) = 0; 222 223 // Remove device provisioning. 224 virtual status_t unprovisionDevice() = 0; 225 226 // A means of enforcing the contractual requirement for a concurrent stream 227 // limit per subscriber across devices is provided via SecureStop. SecureStop 228 // is a means of securely monitoring the lifetime of sessions. Since playback 229 // on a device can be interrupted due to reboot, power failure, etc. a means 230 // of persisting the lifetime information on the device is needed. 231 // 232 // A signed version of the sessionID is written to persistent storage on the 233 // device when each MediaCrypto object is created. The sessionID is signed by 234 // the device private key to prevent tampering. 235 // 236 // In the normal case, playback will be completed, the session destroyed and 237 // the Secure Stops will be queried. The App queries secure stops and forwards 238 // the secure stop message to the server which verifies the signature and 239 // notifies the server side database that the session destruction has been 240 // confirmed. The persisted record on the client is only removed after positive 241 // confirmation that the server received the message using releaseSecureStops(). 242 virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) = 0; 243 virtual status_t getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) = 0; 244 virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0; 245 virtual status_t releaseAllSecureStops() = 0; 246 247 // Read a property value given the device property string. There are a few forms 248 // of property access methods, depending on the data type returned. 249 // Since DRM plugin properties may vary, additional field names may be defined 250 // by each DRM vendor. Refer to your DRM provider documentation for definitions 251 // of its additional field names. 252 // 253 // Standard values are: 254 // "vendor" [string] identifies the maker of the plugin 255 // "version" [string] identifies the version of the plugin 256 // "description" [string] describes the plugin 257 // 'deviceUniqueId' [byte array] The device unique identifier is established 258 // during device provisioning and provides a means of uniquely identifying 259 // each device. 260 virtual status_t getPropertyString(String8 const &name, String8 &value ) const = 0; 261 virtual status_t getPropertyByteArray(String8 const &name, 262 Vector<uint8_t> &value ) const = 0; 263 264 // Write a property value given the device property string. There are a few forms 265 // of property setting methods, depending on the data type. 266 // Since DRM plugin properties may vary, additional field names may be defined 267 // by each DRM vendor. Refer to your DRM provider documentation for definitions 268 // of its field names. 269 virtual status_t setPropertyString(String8 const &name, 270 String8 const &value ) = 0; 271 virtual status_t setPropertyByteArray(String8 const &name, 272 Vector<uint8_t> const &value ) = 0; 273 274 // The following methods implement operations on a CryptoSession to support 275 // encrypt, decrypt, sign verify operations on operator-provided 276 // session keys. 277 278 // 279 // The algorithm string conforms to JCA Standard Names for Cipher 280 // Transforms and is case insensitive. For example "AES/CBC/PKCS5Padding". 281 // 282 // Return OK if the algorithm is supported, otherwise return BAD_VALUE 283 // 284 virtual status_t setCipherAlgorithm(Vector<uint8_t> const &sessionId, 285 String8 const &algorithm) = 0; 286 287 // 288 // The algorithm string conforms to JCA Standard Names for Mac 289 // Algorithms and is case insensitive. For example "HmacSHA256". 290 // 291 // Return OK if the algorithm is supported, otherwise return BAD_VALUE 292 // 293 virtual status_t setMacAlgorithm(Vector<uint8_t> const &sessionId, 294 String8 const &algorithm) = 0; 295 296 // Encrypt the provided input buffer with the cipher algorithm 297 // specified by setCipherAlgorithm and the key selected by keyId, 298 // and return the encrypted data. 299 virtual status_t encrypt(Vector<uint8_t> const &sessionId, 300 Vector<uint8_t> const &keyId, 301 Vector<uint8_t> const &input, 302 Vector<uint8_t> const &iv, 303 Vector<uint8_t> &output) = 0; 304 305 // Decrypt the provided input buffer with the cipher algorithm 306 // specified by setCipherAlgorithm and the key selected by keyId, 307 // and return the decrypted data. 308 virtual status_t decrypt(Vector<uint8_t> const &sessionId, 309 Vector<uint8_t> const &keyId, 310 Vector<uint8_t> const &input, 311 Vector<uint8_t> const &iv, 312 Vector<uint8_t> &output) = 0; 313 314 // Compute a signature on the provided message using the mac algorithm 315 // specified by setMacAlgorithm and the key selected by keyId, 316 // and return the signature. 317 virtual status_t sign(Vector<uint8_t> const &sessionId, 318 Vector<uint8_t> const &keyId, 319 Vector<uint8_t> const &message, 320 Vector<uint8_t> &signature) = 0; 321 322 // Compute a signature on the provided message using the mac algorithm 323 // specified by setMacAlgorithm and the key selected by keyId, 324 // and compare with the expected result. Set result to true or 325 // false depending on the outcome. 326 virtual status_t verify(Vector<uint8_t> const &sessionId, 327 Vector<uint8_t> const &keyId, 328 Vector<uint8_t> const &message, 329 Vector<uint8_t> const &signature, 330 bool &match) = 0; 331 332 333 // Compute an RSA signature on the provided message using the algorithm 334 // specified by algorithm. 335 virtual status_t signRSA(Vector<uint8_t> const &sessionId, 336 String8 const &algorithm, 337 Vector<uint8_t> const &message, 338 Vector<uint8_t> const &wrapped_key, 339 Vector<uint8_t> &signature) = 0; 340 341 setListener(const sp<DrmPluginListener> & listener)342 status_t setListener(const sp<DrmPluginListener>& listener) { 343 Mutex::Autolock lock(mEventLock); 344 mListener = listener; 345 return OK; 346 } 347 348 protected: 349 // Plugins call these methods to deliver events to the java app 350 void sendEvent(EventType eventType, int extra, 351 Vector<uint8_t> const *sessionId, 352 Vector<uint8_t> const *data); 353 354 void sendExpirationUpdate(Vector<uint8_t> const *sessionId, 355 int64_t expiryTimeInMS); 356 357 void sendKeysChange(Vector<uint8_t> const *sessionId, 358 Vector<DrmPlugin::KeyStatus> const *keyStatusList, 359 bool hasNewUsableKey); 360 361 private: 362 Mutex mEventLock; 363 sp<DrmPluginListener> mListener; 364 365 DISALLOW_EVIL_CONSTRUCTORS(DrmPlugin); 366 }; 367 368 class DrmPluginListener: virtual public RefBase 369 { 370 public: 371 virtual void sendEvent(DrmPlugin::EventType eventType, int extra, 372 Vector<uint8_t> const *sessionId, 373 Vector<uint8_t> const *data) = 0; 374 375 virtual void sendExpirationUpdate(Vector<uint8_t> const *sessionId, 376 int64_t expiryTimeInMS) = 0; 377 378 virtual void sendKeysChange(Vector<uint8_t> const *sessionId, 379 Vector<DrmPlugin::KeyStatus> const *keyStatusList, 380 bool hasNewUsableKey) = 0; 381 }; 382 sendEvent(EventType eventType,int extra,Vector<uint8_t> const * sessionId,Vector<uint8_t> const * data)383 inline void DrmPlugin::sendEvent(EventType eventType, int extra, 384 Vector<uint8_t> const *sessionId, 385 Vector<uint8_t> const *data) { 386 mEventLock.lock(); 387 sp<DrmPluginListener> listener = mListener; 388 mEventLock.unlock(); 389 390 if (listener != NULL) { 391 listener->sendEvent(eventType, extra, sessionId, data); 392 } 393 } 394 sendExpirationUpdate(Vector<uint8_t> const * sessionId,int64_t expiryTimeInMS)395 inline void DrmPlugin::sendExpirationUpdate(Vector<uint8_t> const *sessionId, 396 int64_t expiryTimeInMS) { 397 mEventLock.lock(); 398 sp<DrmPluginListener> listener = mListener; 399 mEventLock.unlock(); 400 401 if (listener != NULL) { 402 listener->sendExpirationUpdate(sessionId, expiryTimeInMS); 403 } 404 } 405 sendKeysChange(Vector<uint8_t> const * sessionId,Vector<DrmPlugin::KeyStatus> const * keyStatusList,bool hasNewUsableKey)406 inline void DrmPlugin::sendKeysChange(Vector<uint8_t> const *sessionId, 407 Vector<DrmPlugin::KeyStatus> const *keyStatusList, 408 bool hasNewUsableKey) { 409 mEventLock.lock(); 410 sp<DrmPluginListener> listener = mListener; 411 mEventLock.unlock(); 412 413 if (listener != NULL) { 414 listener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey); 415 } 416 } 417 } // namespace android 418 419 #endif // DRM_API_H_ 420