MediaDrm.java revision 53c90cf916ddd1151f042a61a569ea75a220b26e
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 17package android.media; 18 19import java.lang.ref.WeakReference; 20import java.util.UUID; 21import java.util.HashMap; 22import java.util.List; 23import android.os.Binder; 24import android.os.Debug; 25import android.os.Handler; 26import android.os.Looper; 27import android.os.Message; 28import android.os.Parcel; 29import android.util.Log; 30import android.content.Context; 31 32/** 33 * MediaDrm can be used to obtain keys for decrypting protected media streams, in 34 * conjunction with {@link android.media.MediaCrypto}. The MediaDrm APIs 35 * are designed to support the ISO/IEC 23001-7: Common Encryption standard, but 36 * may also be used to implement other encryption schemes. 37 * <p> 38 * Encrypted content is prepared using an encryption server and stored in a content 39 * library. The encrypted content is streamed or downloaded from the content library to 40 * client devices via content servers. Licenses to view the content are obtained from 41 * a License Server. 42 * <p> 43 * <p><img src="../../../images/mediadrm_overview.png" 44 * alt="MediaDrm Overview diagram" 45 * border="0" /></p> 46 * <p> 47 * Keys are requested from the license server using a key request. The key 48 * response is delivered to the client app, which provides the response to the 49 * MediaDrm API. 50 * <p> 51 * A Provisioning server may be required to distribute device-unique credentials to 52 * the devices. 53 * <p> 54 * Enforcing requirements related to the number of devices that may play content 55 * simultaneously can be performed either through key renewal or using the secure 56 * stop methods. 57 * <p> 58 * The following sequence diagram shows the interactions between the objects 59 * involved while playing back encrypted content: 60 * <p> 61 * <p><img src="../../../images/mediadrm_decryption_sequence.png" 62 * alt="MediaDrm Overview diagram" 63 * border="0" /></p> 64 * <p> 65 * The app first constructs {@link android.media.MediaExtractor} and 66 * {@link android.media.MediaCodec} objects. It accesses the DRM-scheme-identifying UUID, 67 * typically from metadata in the content, and uses this UUID to construct an instance 68 * of a MediaDrm object that is able to support the DRM scheme required by the content. 69 * Crypto schemes are assigned 16 byte UUIDs. The method {@link #isCryptoSchemeSupported} 70 * can be used to query if a given scheme is supported on the device. 71 * <p> 72 * The app calls {@link #openSession} to generate a sessionId that will uniquely identify 73 * the session in subsequent interactions. The app next uses the MediaDrm object to 74 * obtain a key request message and send it to the license server, then provide 75 * the server's response to the MediaDrm object. 76 * <p> 77 * Once the app has a sessionId, it can construct a MediaCrypto object from the UUID and 78 * sessionId. The MediaCrypto object is registered with the MediaCodec in the 79 * {@link MediaCodec.#configure} method to enable the codec to decrypt content. 80 * <p> 81 * When the app has constructed {@link android.media.MediaExtractor}, 82 * {@link android.media.MediaCodec} and {@link android.media.MediaCrypto} objects, 83 * it proceeds to pull samples from the extractor and queue them into the decoder. For 84 * encrypted content, the samples returned from the extractor remain encrypted, they 85 * are only decrypted when the samples are delivered to the decoder. 86 * <p> 87 * <a name="Callbacks"></a> 88 * <h3>Callbacks</h3> 89 * <p>Applications should register for informational events in order 90 * to be informed of key state updates during playback or streaming. 91 * Registration for these events is done via a call to 92 * {@link #setOnEventListener}. In order to receive the respective 93 * callback associated with this listener, applications are required to create 94 * MediaDrm objects on a thread with its own Looper running (main UI 95 * thread by default has a Looper running). 96 */ 97public final class MediaDrm { 98 99 private final static String TAG = "MediaDrm"; 100 101 private EventHandler mEventHandler; 102 private OnEventListener mOnEventListener; 103 104 private long mNativeContext; 105 106 /** 107 * Specify no certificate type 108 * 109 * @hide - not part of the public API at this time 110 */ 111 public static final int CERTIFICATE_TYPE_NONE = 0; 112 113 /** 114 * Specify X.509 certificate type 115 * 116 * @hide - not part of the public API at this time 117 */ 118 public static final int CERTIFICATE_TYPE_X509 = 1; 119 120 /** 121 * Query if the given scheme identified by its UUID is supported on 122 * this device. 123 * @param uuid The UUID of the crypto scheme. 124 */ 125 public static final boolean isCryptoSchemeSupported(UUID uuid) { 126 return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), null); 127 } 128 129 /** 130 * Query if the given scheme identified by its UUID is supported on 131 * this device, and whether the drm plugin is able to handle the 132 * media container format specified by mimeType. 133 * @param uuid The UUID of the crypto scheme. 134 * @param mimeType The MIME type of the media container, e.g. "video/mp4" 135 * or "video/webm" 136 */ 137 public static final boolean isCryptoSchemeSupported(UUID uuid, String mimeType) { 138 return isCryptoSchemeSupportedNative(getByteArrayFromUUID(uuid), mimeType); 139 } 140 141 private static final byte[] getByteArrayFromUUID(UUID uuid) { 142 long msb = uuid.getMostSignificantBits(); 143 long lsb = uuid.getLeastSignificantBits(); 144 145 byte[] uuidBytes = new byte[16]; 146 for (int i = 0; i < 8; ++i) { 147 uuidBytes[i] = (byte)(msb >>> (8 * (7 - i))); 148 uuidBytes[8 + i] = (byte)(lsb >>> (8 * (7 - i))); 149 } 150 151 return uuidBytes; 152 } 153 154 private static final native boolean isCryptoSchemeSupportedNative(byte[] uuid, 155 String mimeType); 156 157 /** 158 * Instantiate a MediaDrm object 159 * 160 * @param uuid The UUID of the crypto scheme. 161 * 162 * @throws UnsupportedSchemeException if the device does not support the 163 * specified scheme UUID 164 */ 165 public MediaDrm(UUID uuid) throws UnsupportedSchemeException { 166 Looper looper; 167 if ((looper = Looper.myLooper()) != null) { 168 mEventHandler = new EventHandler(this, looper); 169 } else if ((looper = Looper.getMainLooper()) != null) { 170 mEventHandler = new EventHandler(this, looper); 171 } else { 172 mEventHandler = null; 173 } 174 175 /* Native setup requires a weak reference to our object. 176 * It's easier to create it here than in C++. 177 */ 178 native_setup(new WeakReference<MediaDrm>(this), 179 getByteArrayFromUUID(uuid)); 180 } 181 182 /** 183 * Register a callback to be invoked when an event occurs 184 * 185 * @param listener the callback that will be run 186 */ 187 public void setOnEventListener(OnEventListener listener) 188 { 189 mOnEventListener = listener; 190 } 191 192 /** 193 * Interface definition for a callback to be invoked when a drm event 194 * occurs 195 */ 196 public interface OnEventListener 197 { 198 /** 199 * Called when an event occurs that requires the app to be notified 200 * 201 * @param md the MediaDrm object on which the event occurred 202 * @param sessionId the DRM session ID on which the event occurred 203 * @param event indicates the event type 204 * @param extra an secondary error code 205 * @param data optional byte array of data that may be associated with the event 206 */ 207 void onEvent(MediaDrm md, byte[] sessionId, int event, int extra, byte[] data); 208 } 209 210 /** 211 * This event type indicates that the app needs to request a certificate from 212 * the provisioning server. The request message data is obtained using 213 * {@link #getProvisionRequest} 214 */ 215 public static final int EVENT_PROVISION_REQUIRED = 1; 216 217 /** 218 * This event type indicates that the app needs to request keys from a license 219 * server. The request message data is obtained using {@link #getKeyRequest}. 220 */ 221 public static final int EVENT_KEY_REQUIRED = 2; 222 223 /** 224 * This event type indicates that the licensed usage duration for keys in a session 225 * has expired. The keys are no longer valid. 226 */ 227 public static final int EVENT_KEY_EXPIRED = 3; 228 229 /** 230 * This event may indicate some specific vendor-defined condition, see your 231 * DRM provider documentation for details 232 */ 233 public static final int EVENT_VENDOR_DEFINED = 4; 234 235 private static final int DRM_EVENT = 200; 236 237 private class EventHandler extends Handler 238 { 239 private MediaDrm mMediaDrm; 240 241 public EventHandler(MediaDrm md, Looper looper) { 242 super(looper); 243 mMediaDrm = md; 244 } 245 246 @Override 247 public void handleMessage(Message msg) { 248 if (mMediaDrm.mNativeContext == 0) { 249 Log.w(TAG, "MediaDrm went away with unhandled events"); 250 return; 251 } 252 switch(msg.what) { 253 254 case DRM_EVENT: 255 Log.i(TAG, "Drm event (" + msg.arg1 + "," + msg.arg2 + ")"); 256 257 if (mOnEventListener != null) { 258 if (msg.obj != null && msg.obj instanceof Parcel) { 259 Parcel parcel = (Parcel)msg.obj; 260 byte[] sessionId = parcel.createByteArray(); 261 if (sessionId.length == 0) { 262 sessionId = null; 263 } 264 byte[] data = parcel.createByteArray(); 265 if (data.length == 0) { 266 data = null; 267 } 268 mOnEventListener.onEvent(mMediaDrm, sessionId, msg.arg1, msg.arg2, data); 269 } 270 } 271 return; 272 273 default: 274 Log.e(TAG, "Unknown message type " + msg.what); 275 return; 276 } 277 } 278 } 279 280 /* 281 * This method is called from native code when an event occurs. This method 282 * just uses the EventHandler system to post the event back to the main app thread. 283 * We use a weak reference to the original MediaPlayer object so that the native 284 * code is safe from the object disappearing from underneath it. (This is 285 * the cookie passed to native_setup().) 286 */ 287 private static void postEventFromNative(Object mediadrm_ref, 288 int eventType, int extra, Object obj) 289 { 290 MediaDrm md = (MediaDrm)((WeakReference)mediadrm_ref).get(); 291 if (md == null) { 292 return; 293 } 294 if (md.mEventHandler != null) { 295 Message m = md.mEventHandler.obtainMessage(DRM_EVENT, eventType, extra, obj); 296 md.mEventHandler.sendMessage(m); 297 } 298 } 299 300 /** 301 * Open a new session with the MediaDrm object. A session ID is returned. 302 * 303 * @throws NotProvisionedException if provisioning is needed 304 * @throws ResourceBusyException if required resources are in use 305 */ 306 public native byte[] openSession() throws NotProvisionedException; 307 308 /** 309 * Close a session on the MediaDrm object that was previously opened 310 * with {@link #openSession}. 311 */ 312 public native void closeSession(byte[] sessionId); 313 314 /** 315 * This key request type species that the keys will be for online use, they will 316 * not be saved to the device for subsequent use when the device is not connected 317 * to a network. 318 */ 319 public static final int KEY_TYPE_STREAMING = 1; 320 321 /** 322 * This key request type specifies that the keys will be for offline use, they 323 * will be saved to the device for use when the device is not connected to a network. 324 */ 325 public static final int KEY_TYPE_OFFLINE = 2; 326 327 /** 328 * This key request type specifies that previously saved offline keys should be released. 329 */ 330 public static final int KEY_TYPE_RELEASE = 3; 331 332 /** 333 * Contains the opaque data an app uses to request keys from a license server 334 */ 335 public final static class KeyRequest { 336 private byte[] mData; 337 private String mDefaultUrl; 338 339 KeyRequest() {} 340 341 /** 342 * Get the opaque message data 343 */ 344 public byte[] getData() { return mData; } 345 346 /** 347 * Get the default URL to use when sending the key request message to a 348 * server, if known. The app may prefer to use a different license 349 * server URL from other sources. 350 */ 351 public String getDefaultUrl() { return mDefaultUrl; } 352 }; 353 354 /** 355 * A key request/response exchange occurs between the app and a license server 356 * to obtain or release keys used to decrypt encrypted content. 357 * <p> 358 * getKeyRequest() is used to obtain an opaque key request byte array that is 359 * delivered to the license server. The opaque key request byte array is returned 360 * in KeyRequest.data. The recommended URL to deliver the key request to is 361 * returned in KeyRequest.defaultUrl. 362 * <p> 363 * After the app has received the key request response from the server, 364 * it should deliver to the response to the DRM engine plugin using the method 365 * {@link #provideKeyResponse}. 366 * 367 * @param scope may be a sessionId or a keySetId, depending on the specified keyType. 368 * When the keyType is KEY_TYPE_STREAMING or KEY_TYPE_OFFLINE, 369 * scope should be set to the sessionId the keys will be provided to. When the keyType 370 * is KEY_TYPE_RELEASE, scope should be set to the keySetId of the keys 371 * being released. Releasing keys from a device invalidates them for all sessions. 372 * @param init container-specific data, its meaning is interpreted based on the 373 * mime type provided in the mimeType parameter. It could contain, for example, 374 * the content ID, key ID or other data obtained from the content metadata that is 375 * required in generating the key request. init may be null when keyType is 376 * KEY_TYPE_RELEASE. 377 * @param mimeType identifies the mime type of the content 378 * @param keyType specifes the type of the request. The request may be to acquire 379 * keys for streaming or offline content, or to release previously acquired 380 * keys, which are identified by a keySetId. 381 * @param optionalParameters are included in the key request message to 382 * allow a client application to provide additional message parameters to the server. 383 * 384 * @throws NotProvisionedException if reprovisioning is needed, due to a 385 * problem with the certifcate 386 */ 387 public native KeyRequest getKeyRequest(byte[] scope, byte[] init, 388 String mimeType, int keyType, 389 HashMap<String, String> optionalParameters) 390 throws NotProvisionedException; 391 392 393 /** 394 * A key response is received from the license server by the app, then it is 395 * provided to the DRM engine plugin using provideKeyResponse. When the 396 * response is for an offline key request, a keySetId is returned that can be 397 * used to later restore the keys to a new session with the method 398 * {@link #restoreKeys}. 399 * When the response is for a streaming or release request, null is returned. 400 * 401 * @param scope may be a sessionId or keySetId depending on the type of the 402 * response. Scope should be set to the sessionId when the response is for either 403 * streaming or offline key requests. Scope should be set to the keySetId when 404 * the response is for a release request. 405 * @param response the byte array response from the server 406 * 407 * @throws NotProvisionedException if the response indicates that 408 * reprovisioning is required 409 * @throws DeniedByServerException if the response indicates that the 410 * server rejected the request 411 * @throws ResourceBusyException if required resources are in use 412 */ 413 public native byte[] provideKeyResponse(byte[] scope, byte[] response) 414 throws NotProvisionedException, DeniedByServerException; 415 416 417 /** 418 * Restore persisted offline keys into a new session. keySetId identifies the 419 * keys to load, obtained from a prior call to {@link #provideKeyResponse}. 420 * 421 * @param sessionId the session ID for the DRM session 422 * @param keySetId identifies the saved key set to restore 423 */ 424 public native void restoreKeys(byte[] sessionId, byte[] keySetId); 425 426 /** 427 * Remove the current keys from a session. 428 * 429 * @param sessionId the session ID for the DRM session 430 */ 431 public native void removeKeys(byte[] sessionId); 432 433 /** 434 * Request an informative description of the key status for the session. The status is 435 * in the form of {name, value} pairs. Since DRM license policies vary by vendor, 436 * the specific status field names are determined by each DRM vendor. Refer to your 437 * DRM provider documentation for definitions of the field names for a particular 438 * DRM engine plugin. 439 * 440 * @param sessionId the session ID for the DRM session 441 */ 442 public native HashMap<String, String> queryKeyStatus(byte[] sessionId); 443 444 /** 445 * Contains the opaque data an app uses to request a certificate from a provisioning 446 * server 447 */ 448 public final static class ProvisionRequest { 449 ProvisionRequest() {} 450 451 /** 452 * Get the opaque message data 453 */ 454 public byte[] getData() { return mData; } 455 456 /** 457 * Get the default URL to use when sending the provision request 458 * message to a server, if known. The app may prefer to use a different 459 * provisioning server URL obtained from other sources. 460 */ 461 public String getDefaultUrl() { return mDefaultUrl; } 462 463 private byte[] mData; 464 private String mDefaultUrl; 465 } 466 467 /** 468 * A provision request/response exchange occurs between the app and a provisioning 469 * server to retrieve a device certificate. If provisionining is required, the 470 * EVENT_PROVISION_REQUIRED event will be sent to the event handler. 471 * getProvisionRequest is used to obtain the opaque provision request byte array that 472 * should be delivered to the provisioning server. The provision request byte array 473 * is returned in ProvisionRequest.data. The recommended URL to deliver the provision 474 * request to is returned in ProvisionRequest.defaultUrl. 475 */ 476 public ProvisionRequest getProvisionRequest() { 477 return getProvisionRequestNative(CERTIFICATE_TYPE_NONE, ""); 478 } 479 480 private native ProvisionRequest getProvisionRequestNative(int certType, 481 String certAuthority); 482 483 /** 484 * After a provision response is received by the app, it is provided to the DRM 485 * engine plugin using this method. 486 * 487 * @param response the opaque provisioning response byte array to provide to the 488 * DRM engine plugin. 489 * 490 * @throws DeniedByServerException if the response indicates that the 491 * server rejected the request 492 */ 493 public void provideProvisionResponse(byte[] response) 494 throws DeniedByServerException { 495 provideProvisionResponseNative(response); 496 } 497 498 private native Certificate provideProvisionResponseNative(byte[] response) 499 throws DeniedByServerException; 500 501 /** 502 * A means of enforcing limits on the number of concurrent streams per subscriber 503 * across devices is provided via SecureStop. This is achieved by securely 504 * monitoring the lifetime of sessions. 505 * <p> 506 * Information from the server related to the current playback session is written 507 * to persistent storage on the device when each MediaCrypto object is created. 508 * <p> 509 * In the normal case, playback will be completed, the session destroyed and the 510 * Secure Stops will be queried. The app queries secure stops and forwards the 511 * secure stop message to the server which verifies the signature and notifies the 512 * server side database that the session destruction has been confirmed. The persisted 513 * record on the client is only removed after positive confirmation that the server 514 * received the message using releaseSecureStops(). 515 */ 516 public native List<byte[]> getSecureStops(); 517 518 519 /** 520 * Process the SecureStop server response message ssRelease. After authenticating 521 * the message, remove the SecureStops identified in the response. 522 * 523 * @param ssRelease the server response indicating which secure stops to release 524 */ 525 public native void releaseSecureStops(byte[] ssRelease); 526 527 528 /** 529 * String property name: identifies the maker of the DRM engine plugin 530 */ 531 public static final String PROPERTY_VENDOR = "vendor"; 532 533 /** 534 * String property name: identifies the version of the DRM engine plugin 535 */ 536 public static final String PROPERTY_VERSION = "version"; 537 538 /** 539 * String property name: describes the DRM engine plugin 540 */ 541 public static final String PROPERTY_DESCRIPTION = "description"; 542 543 /** 544 * String property name: a comma-separated list of cipher and mac algorithms 545 * supported by CryptoSession. The list may be empty if the DRM engine 546 * plugin does not support CryptoSession operations. 547 */ 548 public static final String PROPERTY_ALGORITHMS = "algorithms"; 549 550 /** 551 * Read a DRM engine plugin String property value, given the property name string. 552 * <p> 553 * Standard fields names are: 554 * {@link #PROPERTY_VENDOR}, {@link #PROPERTY_VERSION}, 555 * {@link #PROPERTY_DESCRIPTION}, {@link #PROPERTY_ALGORITHMS} 556 */ 557 public native String getPropertyString(String propertyName); 558 559 560 /** 561 * Byte array property name: the device unique identifier is established during 562 * device provisioning and provides a means of uniquely identifying each device. 563 */ 564 public static final String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId"; 565 566 /** 567 * Read a DRM engine plugin byte array property value, given the property name string. 568 * <p> 569 * Standard fields names are {@link #PROPERTY_DEVICE_UNIQUE_ID} 570 */ 571 public native byte[] getPropertyByteArray(String propertyName); 572 573 574 /** 575 * Set a DRM engine plugin String property value. 576 */ 577 public native void setPropertyString(String propertyName, String value); 578 579 /** 580 * Set a DRM engine plugin byte array property value. 581 */ 582 public native void setPropertyByteArray(String propertyName, byte[] value); 583 584 585 private static final native void setCipherAlgorithmNative(MediaDrm drm, byte[] sessionId, 586 String algorithm); 587 588 private static final native void setMacAlgorithmNative(MediaDrm drm, byte[] sessionId, 589 String algorithm); 590 591 private static final native byte[] encryptNative(MediaDrm drm, byte[] sessionId, 592 byte[] keyId, byte[] input, byte[] iv); 593 594 private static final native byte[] decryptNative(MediaDrm drm, byte[] sessionId, 595 byte[] keyId, byte[] input, byte[] iv); 596 597 private static final native byte[] signNative(MediaDrm drm, byte[] sessionId, 598 byte[] keyId, byte[] message); 599 600 private static final native boolean verifyNative(MediaDrm drm, byte[] sessionId, 601 byte[] keyId, byte[] message, 602 byte[] signature); 603 604 /** 605 * In addition to supporting decryption of DASH Common Encrypted Media, the 606 * MediaDrm APIs provide the ability to securely deliver session keys from 607 * an operator's session key server to a client device, based on the factory-installed 608 * root of trust, and then perform encrypt, decrypt, sign and verify operations 609 * with the session key on arbitrary user data. 610 * <p> 611 * The CryptoSession class implements generic encrypt/decrypt/sign/verify methods 612 * based on the established session keys. These keys are exchanged using the 613 * getKeyRequest/provideKeyResponse methods. 614 * <p> 615 * Applications of this capability could include securing various types of 616 * purchased or private content, such as applications, books and other media, 617 * photos or media delivery protocols. 618 * <p> 619 * Operators can create session key servers that are functionally similar to a 620 * license key server, except that instead of receiving license key requests and 621 * providing encrypted content keys which are used specifically to decrypt A/V media 622 * content, the session key server receives session key requests and provides 623 * encrypted session keys which can be used for general purpose crypto operations. 624 * <p> 625 * A CryptoSession is obtained using {@link #getCryptoSession} 626 */ 627 public final class CryptoSession { 628 private MediaDrm mDrm; 629 private byte[] mSessionId; 630 631 CryptoSession(MediaDrm drm, byte[] sessionId, 632 String cipherAlgorithm, String macAlgorithm) 633 { 634 mSessionId = sessionId; 635 mDrm = drm; 636 setCipherAlgorithmNative(drm, sessionId, cipherAlgorithm); 637 setMacAlgorithmNative(drm, sessionId, macAlgorithm); 638 } 639 640 /** 641 * Encrypt data using the CryptoSession's cipher algorithm 642 * 643 * @param keyid specifies which key to use 644 * @param input the data to encrypt 645 * @param iv the initialization vector to use for the cipher 646 */ 647 public byte[] encrypt(byte[] keyid, byte[] input, byte[] iv) { 648 return encryptNative(mDrm, mSessionId, keyid, input, iv); 649 } 650 651 /** 652 * Decrypt data using the CryptoSessions's cipher algorithm 653 * 654 * @param keyid specifies which key to use 655 * @param input the data to encrypt 656 * @param iv the initialization vector to use for the cipher 657 */ 658 public byte[] decrypt(byte[] keyid, byte[] input, byte[] iv) { 659 return decryptNative(mDrm, mSessionId, keyid, input, iv); 660 } 661 662 /** 663 * Sign data using the CryptoSessions's mac algorithm. 664 * 665 * @param keyid specifies which key to use 666 * @param message the data for which a signature is to be computed 667 */ 668 public byte[] sign(byte[] keyid, byte[] message) { 669 return signNative(mDrm, mSessionId, keyid, message); 670 } 671 672 /** 673 * Verify a signature using the CryptoSessions's mac algorithm. Return true 674 * if the signatures match, false if they do no. 675 * 676 * @param keyid specifies which key to use 677 * @param message the data to verify 678 * @param signature the reference signature which will be compared with the 679 * computed signature 680 */ 681 public boolean verify(byte[] keyid, byte[] message, byte[] signature) { 682 return verifyNative(mDrm, mSessionId, keyid, message, signature); 683 } 684 }; 685 686 /** 687 * Obtain a CryptoSession object which can be used to encrypt, decrypt, 688 * sign and verify messages or data using the session keys established 689 * for the session using methods {@link #getKeyRequest} and 690 * {@link #provideKeyResponse} using a session key server. 691 * 692 * @param sessionId the session ID for the session containing keys 693 * to be used for encrypt, decrypt, sign and/or verify 694 * @param cipherAlgorithm the algorithm to use for encryption and 695 * decryption ciphers. The algorithm string conforms to JCA Standard 696 * Names for Cipher Transforms and is case insensitive. For example 697 * "AES/CBC/NoPadding". 698 * @param macAlgorithm the algorithm to use for sign and verify 699 * The algorithm string conforms to JCA Standard Names for Mac 700 * Algorithms and is case insensitive. For example "HmacSHA256". 701 * <p> 702 * The list of supported algorithms for a DRM engine plugin can be obtained 703 * using the method {@link #getPropertyString} with the property name 704 * "algorithms". 705 */ 706 public CryptoSession getCryptoSession(byte[] sessionId, 707 String cipherAlgorithm, 708 String macAlgorithm) 709 { 710 return new CryptoSession(this, sessionId, cipherAlgorithm, macAlgorithm); 711 } 712 713 /** 714 * Contains the opaque data an app uses to request a certificate from a provisioning 715 * server 716 * 717 * @hide - not part of the public API at this time 718 */ 719 public final static class CertificateRequest { 720 private byte[] mData; 721 private String mDefaultUrl; 722 723 CertificateRequest(byte[] data, String defaultUrl) { 724 mData = data; 725 mDefaultUrl = defaultUrl; 726 } 727 728 /** 729 * Get the opaque message data 730 */ 731 public byte[] getData() { return mData; } 732 733 /** 734 * Get the default URL to use when sending the certificate request 735 * message to a server, if known. The app may prefer to use a different 736 * certificate server URL obtained from other sources. 737 */ 738 public String getDefaultUrl() { return mDefaultUrl; } 739 } 740 741 /** 742 * Generate a certificate request, specifying the certificate type 743 * and authority. The response received should be passed to 744 * provideCertificateResponse. 745 * 746 * @param certType Specifies the certificate type. 747 * 748 * @param certAuthority is passed to the certificate server to specify 749 * the chain of authority. 750 * 751 * @hide - not part of the public API at this time 752 */ 753 public CertificateRequest getCertificateRequest(int certType, 754 String certAuthority) 755 { 756 ProvisionRequest provisionRequest = getProvisionRequestNative(certType, certAuthority); 757 return new CertificateRequest(provisionRequest.getData(), 758 provisionRequest.getDefaultUrl()); 759 } 760 761 /** 762 * Contains the wrapped private key and public certificate data associated 763 * with a certificate. 764 * 765 * @hide - not part of the public API at this time 766 */ 767 public final static class Certificate { 768 Certificate() {} 769 770 /** 771 * Get the wrapped private key data 772 */ 773 public byte[] getWrappedPrivateKey() { return mWrappedKey; } 774 775 /** 776 * Get the PEM-encoded certificate chain 777 */ 778 public byte[] getContent() { return mCertificateData; } 779 780 private byte[] mWrappedKey; 781 private byte[] mCertificateData; 782 } 783 784 785 /** 786 * Process a response from the certificate server. The response 787 * is obtained from an HTTP Post to the url provided by getCertificateRequest. 788 * <p> 789 * The public X509 certificate chain and wrapped private key are returned 790 * in the returned Certificate objec. The certificate chain is in PEM format. 791 * The wrapped private key should be stored in application private 792 * storage, and used when invoking the signRSA method. 793 * 794 * @param response the opaque certificate response byte array to provide to the 795 * DRM engine plugin. 796 * 797 * @throws DeniedByServerException if the response indicates that the 798 * server rejected the request 799 * 800 * @hide - not part of the public API at this time 801 */ 802 public Certificate provideCertificateResponse(byte[] response) 803 throws DeniedByServerException { 804 return provideProvisionResponseNative(response); 805 } 806 807 private static final native byte[] signRSANative(MediaDrm drm, byte[] sessionId, 808 String algorithm, byte[] wrappedKey, 809 byte[] message); 810 811 /** 812 * Sign data using an RSA key 813 * 814 * @param context the app context 815 * @param sessionId a sessionId obtained from openSession on the MediaDrm object 816 * @param algorithm the signing algorithm to use, e.g. "PKCS1-BlockType1" 817 * @param wrappedKey - the wrapped (encrypted) RSA private key obtained 818 * from provideCertificateResponse 819 * @param message the data for which a signature is to be computed 820 * 821 * @hide - not part of the public API at this time 822 */ 823 public byte[] signRSA(Context context, byte[] sessionId, String algorithm, byte[] wrappedKey, byte[] message) { 824 return signRSANative(this, sessionId, algorithm, wrappedKey, message); 825 } 826 827 @Override 828 protected void finalize() { 829 native_finalize(); 830 } 831 832 public native final void release(); 833 private static native final void native_init(); 834 835 private native final void native_setup(Object mediadrm_this, byte[] uuid); 836 837 private native final void native_finalize(); 838 839 static { 840 System.loadLibrary("media_jni"); 841 native_init(); 842 } 843} 844