1 /*
2  * Copyright (C) 2014 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 /*
18  * This file defines an NDK API.
19  * Do not remove methods.
20  * Do not change method signatures.
21  * Do not change the value of constants.
22  * Do not change the size of any of the classes defined in here.
23  * Do not reference types that are not part of the NDK.
24  * Do not #include files that aren't part of the NDK.
25  */
26 
27 #ifndef _NDK_MEDIA_DRM_H
28 #define _NDK_MEDIA_DRM_H
29 
30 #include "NdkMediaError.h"
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #include <stdint.h>
37 #include <stdbool.h>
38 
39 struct AMediaDrm;
40 typedef struct AMediaDrm AMediaDrm;
41 
42 typedef struct {
43     const uint8_t *ptr;
44     size_t length;
45 } AMediaDrmByteArray;
46 
47 typedef AMediaDrmByteArray AMediaDrmSessionId;
48 typedef AMediaDrmByteArray AMediaDrmScope;
49 typedef AMediaDrmByteArray AMediaDrmKeySetId;
50 typedef AMediaDrmByteArray AMediaDrmSecureStop;
51 
52 
53 typedef enum AMediaDrmEventType {
54     /**
55      * This event type indicates that the app needs to request a certificate from
56      * the provisioning server.  The request message data is obtained using
57      * AMediaDrm_getProvisionRequest.
58      */
59     EVENT_PROVISION_REQUIRED = 1,
60 
61     /**
62      * This event type indicates that the app needs to request keys from a license
63      * server.  The request message data is obtained using AMediaDrm_getKeyRequest.
64      */
65     EVENT_KEY_REQUIRED = 2,
66 
67     /**
68      * This event type indicates that the licensed usage duration for keys in a session
69      * has expired.  The keys are no longer valid.
70      */
71     EVENT_KEY_EXPIRED = 3,
72 
73     /**
74      * This event may indicate some specific vendor-defined condition, see your
75      * DRM provider documentation for details
76      */
77     EVENT_VENDOR_DEFINED = 4
78 } AMediaDrmEventType;
79 
80 typedef void (*AMediaDrmEventListener)(AMediaDrm *, const AMediaDrmSessionId *sessionId,
81         AMediaDrmEventType eventType, int extra, const uint8_t *data, size_t dataSize);
82 
83 
84 /**
85  * Query if the given scheme identified by its UUID is supported on this device, and
86  * whether the drm plugin is able to handle the media container format specified by mimeType.
87  *
88  * uuid identifies the universal unique ID of the crypto scheme. uuid must be 16 bytes.
89  * mimeType is the MIME type of the media container, e.g. "video/mp4".  If mimeType
90  * is not known or required, it can be provided as NULL.
91  */
92 bool AMediaDrm_isCryptoSchemeSupported(const uint8_t *uuid, const char *mimeType);
93 
94 /**
95  * Create a MediaDrm instance from a UUID
96  * uuid identifies the universal unique ID of the crypto scheme. uuid must be 16 bytes.
97  */
98 AMediaDrm* AMediaDrm_createByUUID(const uint8_t *uuid);
99 
100 /**
101  * Release a MediaDrm object
102  */
103 void AMediaDrm_release(AMediaDrm *);
104 
105 /**
106  * Register a callback to be invoked when an event occurs
107  *
108  * listener is the callback that will be invoked on event
109  */
110 media_status_t AMediaDrm_setOnEventListener(AMediaDrm *, AMediaDrmEventListener listener);
111 
112 /**
113  * Open a new session with the MediaDrm object.  A session ID is returned.
114  *
115  * returns MEDIADRM_NOT_PROVISIONED_ERROR if provisioning is needed
116  * returns MEDIADRM_RESOURCE_BUSY_ERROR if required resources are in use
117  */
118 media_status_t AMediaDrm_openSession(AMediaDrm *, AMediaDrmSessionId *sessionId);
119 
120 /**
121  * Close a session on the MediaDrm object that was previously opened
122  * with AMediaDrm_openSession.
123  */
124 media_status_t AMediaDrm_closeSession(AMediaDrm *, const AMediaDrmSessionId *sessionId);
125 
126 typedef enum AMediaDrmKeyType {
127     /**
128      * This key request type species that the keys will be for online use, they will
129      * not be saved to the device for subsequent use when the device is not connected
130      * to a network.
131      */
132     KEY_TYPE_STREAMING = 1,
133 
134     /**
135      * This key request type specifies that the keys will be for offline use, they
136      * will be saved to the device for use when the device is not connected to a network.
137      */
138     KEY_TYPE_OFFLINE = 2,
139 
140     /**
141      * This key request type specifies that previously saved offline keys should be released.
142      */
143     KEY_TYPE_RELEASE = 3
144 } AMediaDrmKeyType;
145 
146 /**
147  *  Data type containing {key, value} pair
148  */
149 typedef struct AMediaDrmKeyValuePair {
150     const char *mKey;
151     const char *mValue;
152 } AMediaDrmKeyValue;
153 
154 /**
155  * A key request/response exchange occurs between the app and a license server
156  * to obtain or release keys used to decrypt encrypted content.
157  * AMediaDrm_getKeyRequest is used to obtain an opaque key request byte array that
158  * is delivered to the license server.  The opaque key request byte array is
159  * returned in KeyRequest.data.  The recommended URL to deliver the key request to
160  * is returned in KeyRequest.defaultUrl.
161  *
162  * After the app has received the key request response from the server,
163  * it should deliver to the response to the DRM engine plugin using the method
164  * AMediaDrm_provideKeyResponse.
165  *
166  * scope may be a sessionId or a keySetId, depending on the specified keyType.
167  * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, scope should be set
168  * to the sessionId the keys will be provided to.  When the keyType is
169  * KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys being released.
170  * Releasing keys from a device invalidates them for all sessions.
171  *
172  * init container-specific data, its meaning is interpreted based on the mime type
173  * provided in the mimeType parameter.  It could contain, for example, the content
174  * ID, key ID or other data obtained from the content metadata that is required in
175  * generating the key request. init may be null when keyType is KEY_TYPE_RELEASE.
176  *
177  * initSize is the number of bytes of initData
178  *
179  * mimeType identifies the mime type of the content.
180  *
181  * keyType specifes the type of the request. The request may be to acquire keys for
182  *   streaming or offline content, or to release previously acquired keys, which are
183  *   identified by a keySetId.
184  *
185  * optionalParameters are included in the key request message to allow a client
186  *   application to provide additional message parameters to the server.
187  *
188  * numOptionalParameters indicates the number of optional parameters provided
189  *   by the caller
190  *
191  * On exit:
192  *   1. The keyRequest pointer will reference the opaque key request data.  It
193  *       will reside in memory owned by the AMediaDrm object, and will remain
194  *       accessible until the next call to AMediaDrm_getKeyRequest or until the
195  *       MediaDrm object is released.
196  *   2. keyRequestSize will be set to the size of the request
197  *
198  * returns MEDIADRM_NOT_PROVISIONED_ERROR if reprovisioning is needed, due to a
199  * problem with the device certificate.
200 */
201 media_status_t AMediaDrm_getKeyRequest(AMediaDrm *, const AMediaDrmScope *scope,
202         const uint8_t *init, size_t initSize, const char *mimeType, AMediaDrmKeyType keyType,
203         const AMediaDrmKeyValue *optionalParameters, size_t numOptionalParameters,
204         const uint8_t **keyRequest, size_t *keyRequestSize);
205 
206 /**
207  * A key response is received from the license server by the app, then it is
208  * provided to the DRM engine plugin using provideKeyResponse.  When the
209  * response is for an offline key request, a keySetId is returned that can be
210  * used to later restore the keys to a new session with AMediaDrm_restoreKeys.
211  * When the response is for a streaming or release request, a null keySetId is
212  * returned.
213  *
214  * scope may be a sessionId or keySetId depending on the type of the
215  * response.  Scope should be set to the sessionId when the response is for either
216  * streaming or offline key requests.  Scope should be set to the keySetId when
217  * the response is for a release request.
218  *
219  * response points to the opaque response from the server
220  * responseSize should be set to the size of the response in bytes
221  */
222 
223 media_status_t AMediaDrm_provideKeyResponse(AMediaDrm *, const AMediaDrmScope *scope,
224         const uint8_t *response, size_t responseSize, AMediaDrmKeySetId *keySetId);
225 
226 /**
227  * Restore persisted offline keys into a new session.  keySetId identifies the
228  * keys to load, obtained from a prior call to AMediaDrm_provideKeyResponse.
229  *
230  * sessionId is the session ID for the DRM session
231  * keySetId identifies the saved key set to restore
232  */
233 media_status_t AMediaDrm_restoreKeys(AMediaDrm *, const AMediaDrmSessionId *sessionId,
234         const AMediaDrmKeySetId *keySetId);
235 
236 /**
237  * Remove the current keys from a session.
238  *
239  * keySetId identifies keys to remove
240  */
241 media_status_t AMediaDrm_removeKeys(AMediaDrm *, const AMediaDrmSessionId *keySetId);
242 
243 /**
244  * Request an informative description of the key status for the session.  The status is
245  * in the form of {key, value} pairs.  Since DRM license policies vary by vendor,
246  * the specific status field names are determined by each DRM vendor.  Refer to your
247  * DRM provider documentation for definitions of the field names for a particular
248  * DRM engine plugin.
249  *
250  * On entry, numPairs should be set by the caller to the maximum number of pairs
251  * that can be returned (the size of the array).  On exit, numPairs will be set
252  * to the number of entries written to the array.  If the number of {key, value} pairs
253  * to be returned is greater than *numPairs, MEDIADRM_SHORT_BUFFER will be returned
254  * and numPairs will be set to the number of pairs available.
255  */
256 media_status_t AMediaDrm_queryKeyStatus(AMediaDrm *, const AMediaDrmSessionId *sessionId,
257         AMediaDrmKeyValue *keyValuePairs, size_t *numPairs);
258 
259 
260 /**
261  * A provision request/response exchange occurs between the app and a provisioning
262  * server to retrieve a device certificate.  If provisionining is required, the
263  * EVENT_PROVISION_REQUIRED event will be sent to the event handler.
264  * getProvisionRequest is used to obtain the opaque provision request byte array that
265  * should be delivered to the provisioning server.
266  * On exit:
267  *    1. The provision request data will be referenced by provisionRequest, in
268  *        memory owned by the AMediaDrm object.  It will remain accessible until the
269  *        next call to getProvisionRequest.
270  *    2. provisionRequestSize will be set to the size of the request data.
271  *    3. serverUrl will reference a NULL terminated string containing the URL
272  *       the provisioning request should be sent to.  It will remain accessible until
273  *       the next call to getProvisionRequest.
274  */
275 media_status_t AMediaDrm_getProvisionRequest(AMediaDrm *, const uint8_t **provisionRequest,
276         size_t *provisionRequestSize, const char **serverUrl);
277 
278 
279 /**
280  * After a provision response is received by the app, it is provided to the DRM
281  * engine plugin using this method.
282  *
283  * response is the opaque provisioning response byte array to provide to the
284  *   DRM engine plugin.
285  * responseSize is the length of the provisioning response in bytes.
286  *
287  * returns MEDIADRM_DEVICE_REVOKED_ERROR if the response indicates that the
288  * server rejected the request
289  */
290 media_status_t AMediaDrm_provideProvisionResponse(AMediaDrm *,
291         const uint8_t *response, size_t responseSize);
292 
293 
294 /**
295  * A means of enforcing limits on the number of concurrent streams per subscriber
296  * across devices is provided via SecureStop. This is achieved by securely
297  * monitoring the lifetime of sessions.
298  *
299  * Information from the server related to the current playback session is written
300  * to persistent storage on the device when each MediaCrypto object is created.
301  *
302  * In the normal case, playback will be completed, the session destroyed and the
303  * Secure Stops will be queried. The app queries secure stops and forwards the
304  * secure stop message to the server which verifies the signature and notifies the
305  * server side database that the session destruction has been confirmed. The persisted
306  * record on the client is only removed after positive confirmation that the server
307  * received the message using releaseSecureStops().
308  *
309  * numSecureStops is set by the caller to the maximum number of secure stops to
310  * return.  On exit, *numSecureStops will be set to the number actually returned.
311  * If *numSecureStops is too small for the number of secure stops available,
312  * MEDIADRM_SHORT_BUFFER will be returned and *numSecureStops will be set to the
313  * number required.
314  */
315 media_status_t AMediaDrm_getSecureStops(AMediaDrm *,
316         AMediaDrmSecureStop *secureStops, size_t *numSecureStops);
317 
318 /**
319  * Process the SecureStop server response message ssRelease.  After authenticating
320  * the message, remove the SecureStops identified in the response.
321  *
322  * ssRelease is the server response indicating which secure stops to release
323  */
324 media_status_t AMediaDrm_releaseSecureStops(AMediaDrm *,
325         const AMediaDrmSecureStop *ssRelease);
326 
327 /**
328  * String property name: identifies the maker of the DRM engine plugin
329  */
330 #define PROPERTY_VENDOR "vendor"
331 
332 /**
333  * String property name: identifies the version of the DRM engine plugin
334  */
335 #define PROPERTY_VERSION "version"
336 
337 /**
338  * String property name: describes the DRM engine plugin
339  */
340 #define PROPERTY_DESCRIPTION "description"
341 
342 /**
343  * String property name: a comma-separated list of cipher and mac algorithms
344  * supported by CryptoSession.  The list may be empty if the DRM engine
345  * plugin does not support CryptoSession operations.
346  */
347 #define PROPERTY_ALGORITHMS "algorithms"
348 
349 /**
350  * Read a DRM engine plugin String property value, given the property name string.
351  *
352  * propertyName identifies the property to query
353  * On return, propertyValue will be set to point to the property value.  The
354  * memory that the value resides in is owned by the NDK MediaDrm API and
355  * will remain valid until the next call to AMediaDrm_getPropertyString.
356  */
357 media_status_t AMediaDrm_getPropertyString(AMediaDrm *, const char *propertyName,
358         const char **propertyValue);
359 
360 /**
361  * Byte array property name: the device unique identifier is established during
362  * device provisioning and provides a means of uniquely identifying each device.
363  */
364 #define PROPERTY_DEVICE_UNIQUE_ID "deviceUniqueId"
365 
366 /**
367  * Read a DRM engine plugin byte array property value, given the property name string.
368  * On return, *propertyValue will be set to point to the property value.  The
369  * memory that the value resides in is owned by the NDK MediaDrm API and
370  * will remain valid until the next call to AMediaDrm_getPropertyByteArray.
371  */
372 media_status_t AMediaDrm_getPropertyByteArray(AMediaDrm *, const char *propertyName,
373         AMediaDrmByteArray *propertyValue);
374 
375 /**
376  * Set a DRM engine plugin String property value.
377  */
378 media_status_t AMediaDrm_setPropertyString(AMediaDrm *, const char *propertyName,
379         const char *value);
380 
381 /**
382  * Set a DRM engine plugin byte array property value.
383  */
384 media_status_t AMediaDrm_setPropertyByteArray(AMediaDrm *, const char *propertyName,
385         const uint8_t *value, size_t valueSize);
386 
387 /**
388  * In addition to supporting decryption of DASH Common Encrypted Media, the
389  * MediaDrm APIs provide the ability to securely deliver session keys from
390  * an operator's session key server to a client device, based on the factory-installed
391  * root of trust, and then perform encrypt, decrypt, sign and verify operations
392  * with the session key on arbitrary user data.
393  *
394  * Operators create session key servers that receive session key requests and provide
395  * encrypted session keys which can be used for general purpose crypto operations.
396  *
397  * Generic encrypt/decrypt/sign/verify methods are based on the established session
398  * keys.  These keys are exchanged using the getKeyRequest/provideKeyResponse methods.
399  *
400  * Applications of this capability include securing various types of purchased or
401  * private content, such as applications, books and other media, photos or media
402  * delivery protocols.
403  */
404 
405 /*
406  * Encrypt the data referenced by input of length dataSize using algorithm specified
407  * by cipherAlgorithm, and write the encrypted result into output.  The caller must
408  * ensure that the output buffer is large enough to accept dataSize bytes. The key
409  * to use is identified by the 16 byte keyId.  The key must have been loaded into
410  * the session using provideKeyResponse.
411  */
412 media_status_t AMediaDrm_encrypt(AMediaDrm *, const AMediaDrmSessionId *sessionId,
413         const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
414         const uint8_t *input, uint8_t *output, size_t dataSize);
415 
416 /*
417  * Decrypt the data referenced by input of length dataSize using algorithm specified
418  * by cipherAlgorithm, and write the decrypted result into output.  The caller must
419  * ensure that the output buffer is large enough to accept dataSize bytes.  The key
420  * to use is identified by the 16 byte keyId.  The key must have been loaded into
421  * the session using provideKeyResponse.
422  */
423 media_status_t AMediaDrm_decrypt(AMediaDrm *, const AMediaDrmSessionId *sessionId,
424         const char *cipherAlgorithm, uint8_t *keyId, uint8_t *iv,
425         const uint8_t *input, uint8_t *output, size_t dataSize);
426 
427 /*
428  * Generate a signature using the specified macAlgorithm over the message data
429  * referenced by message of size messageSize and store the signature in the
430  * buffer referenced signature of max size *signatureSize.  If the buffer is not
431  * large enough to hold the signature, MEDIADRM_SHORT_BUFFER is returned and
432  * *signatureSize is set to the buffer size required.  The key to use is identified
433  * by the 16 byte keyId.  The key must have been loaded into the session using
434  * provideKeyResponse.
435  */
436 media_status_t AMediaDrm_sign(AMediaDrm *, const AMediaDrmSessionId *sessionId,
437         const char *macAlgorithm, uint8_t *keyId, uint8_t *message, size_t messageSize,
438         uint8_t *signature, size_t *signatureSize);
439 
440 /*
441  * Perform a signature verification using the specified macAlgorithm over the message
442  * data referenced by the message parameter of size messageSize. Returns MEDIADRM_OK
443  * if the signature matches, otherwise MEDAIDRM_VERIFY_FAILED is returned. The key to
444  * use is identified by the 16 byte keyId.  The key must have been loaded into the
445  * session using provideKeyResponse.
446  */
447 media_status_t AMediaDrm_verify(AMediaDrm *, const AMediaDrmSessionId *sessionId,
448         const char *macAlgorithm, uint8_t *keyId, const uint8_t *message, size_t messageSize,
449         const uint8_t *signature, size_t signatureSize);
450 
451 #ifdef __cplusplus
452 } // extern "C"
453 #endif
454 
455 #endif //_NDK_MEDIA_DRM_H
456